From c48df93fe889ec63386c9bba42f511e064a41941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20K=C3=BChnel?= Date: Thu, 21 Mar 2024 10:39:20 +0100 Subject: [PATCH] Update MATSim (#88) Update MATSim CW12 --- .github/CODEOWNERS | 2 +- .../accessibility/AccessibilityUtils.java | 4 +- .../contrib/accessibility/VoronoiExample.java | 16 +- .../accessibility/utils/GeoserverUpdater.java | 22 +- .../AccidentsNetworkModification.java | 100 +- .../analysis/christoph/TravelTimesWriter.java | 6 +- contribs/application/pom.xml | 13 + .../matsim/application/ApplicationUtils.java | 217 +- .../matsim/application/MATSimApplication.java | 156 +- .../{commands => }/RunScenario.java | 5 +- .../application/{commands => }/ShowGUI.java | 18 +- .../analysis/population/TripAnalysis.java | 9 +- .../analysis/traffic/LinkStats.java | 2 +- .../traveltime/SampleValidationRoutes.java | 20 +- .../application/options/CsvOptions.java | 53 +- .../application/options/InputOptions.java | 4 + .../application/options/ShpOptions.java | 26 +- .../application/prepare/CreateLandUseShp.java | 4 +- .../DetermineAverageTruckLoad.java | 4 +- .../prepare/network/CleanNetwork.java | 6 +- .../network/CreateNetworkFromSumo.java | 12 +- .../prepare/network/SampleNetwork.java | 329 ++ .../network/params/ApplyNetworkParams.java | 177 + .../network/params/EvalFreespeedParams.java | 247 ++ .../network/params/FeatureRegressor.java | 31 + .../network/params/FreespeedOptServer.java | 158 + .../network/params/NetworkAttribute.java | 9 + .../prepare/network/params/NetworkModel.java | 22 + .../prepare/network/params/NetworkParams.java | 53 + .../network/params/NetworkParamsOpt.java | 182 + .../params/ref/DecisionTreeParams.java | 121 + .../params/ref/GermanyNetworkParams.java | 30 + ...ermanyNetworkParams_capacity_dead_end.java | 911 ++++ ...ermanyNetworkParams_capacity_priority.java | 3831 +++++++++++++++++ ...workParams_capacity_right_before_left.java | 51 + ...yNetworkParams_capacity_traffic_light.java | 1747 ++++++++ ...yNetworkParams_speedRelative_priority.java | 1615 +++++++ ...arams_speedRelative_right_before_left.java | 1551 +++++++ ...orkParams_speedRelative_traffic_light.java | 1647 +++++++ .../SplitActivityTypesDuration.java | 10 +- .../prepare/population/XYToLinks.java | 19 +- .../CarrierReaderFromCSV.java | 39 +- .../DemandReaderFromCSV.java | 231 +- .../FreightDemandGeneration.java | 81 +- .../FreightDemandGenerationUtils.java | 102 +- .../application/ConfigYamlUpdateTest.java | 239 + .../application/options/CsvOptionsTest.java | 29 +- .../application/options/ShpOptionsTest.java | 25 + .../params/ApplyNetworkParamsTest.java | 45 + .../CarrierReaderFromCSVTest.java | 39 +- .../DemandReaderFromCSVTest.java | 23 +- .../FreightDemandGenerationUtilsTest.java | 76 +- ...nerateSmallScaleCommercialTrafficTest.java | 120 - .../ConfigYamlUpdateTest/config.xml | 75 + .../ConfigYamlUpdateTest/multiLevel.yml | 11 + .../ConfigYamlUpdateTest/params.yml | 13 + .../ConfigYamlUpdateTest/standard.yml | 14 + .../prepare/network/params/osm.net.xml | 1759 ++++++++ .../config_demand.xml | 552 --- .../dataDistributionPerZone.csv | 4 - .../investigationAreaData.csv | 3 - .../contrib/bicycle/run/BicycleTest.java | 2 +- contribs/common/pom.xml | 10 + .../common/util/WeightedRandomSelection.java | 4 + .../org/matsim/contrib/common/zones/Zone.java | 19 + .../matsim/contrib/common/zones/ZoneImpl.java | 65 + .../contrib/common/zones/ZoneSystem.java | 14 + .../contrib/common/zones/ZoneSystemImpl.java | 43 + .../contrib/common/zones/ZoneSystemUtils.java | 64 + .../contrib/common/zones/h3/H3GridUtils.java | 112 + .../contrib/common/zones/h3/H3Utils.java | 27 + .../common/zones/h3/H3ZoneSystemUtils.java | 77 + .../constraints/TransitWalkConstraint.java | 3 +- .../utils/NullWaitingTimeEstimator.java | 10 + .../utils/PTWaitingTimeEstimator.java | 7 + .../utils/ScheduleWaitingTimeEstimator.java | 12 +- .../model/tour_based/TourBasedModel.java | 10 +- .../model/trip_based/TripBasedModel.java | 8 +- contribs/drt-extensions/pom.xml | 2 +- .../dashboards/DrtAnalysisPostProcessing.java | 8 +- .../edrt/run/EDrtModeOptimizerQSimModule.java | 12 +- .../estimator/MultiModalDrtLegEstimator.java | 2 +- .../contrib/drt/extension/fiss/FISS.java | 12 +- .../RunDrtWithCompanionExampleIT.java | 36 +- .../extension/edrt/run/RunEDrtScenarioIT.java | 8 +- .../h3/RunDrtWithH3ZonalSystemIT.java | 88 + .../h3/drtZone/H3DrtZonalSystemTest.java | 173 + .../insertion/DrtInsertionExtensionIT.java | 10 +- contribs/drt/pom.xml | 8 +- .../DrtAnalysisControlerListener.java | 11 +- .../drt/analysis/zonal/DrtGridUtils.java | 21 +- .../zonal/DrtModeZonalSystemModule.java | 120 +- .../drt/analysis/zonal/DrtZonalSystem.java | 111 - .../analysis/zonal/DrtZonalSystemParams.java | 17 +- .../zonal/DrtZonalWaitTimesAnalyzer.java | 68 +- .../contrib/drt/analysis/zonal/DrtZone.java | 77 - .../zonal/DrtZoneTargetLinkSelector.java | 3 +- .../MostCentralDrtZoneTargetLinkSelector.java | 10 +- .../RandomDrtZoneTargetLinkSelector.java | 3 +- .../zonal/ZonalIdleVehicleCollector.java | 32 +- .../zonal/ZonalIdleVehicleXYVisualiser.java | 39 +- .../optimizer/DrtModeOptimizerQSimModule.java | 8 +- .../insertion/InsertionGenerator.java | 23 +- .../extensive/ExtensiveInsertionProvider.java | 17 +- .../ExtensiveInsertionSearchQSimModule.java | 14 +- .../RepeatedSelectiveInsertionProvider.java | 35 +- ...tedSelectiveInsertionSearchQSimModule.java | 17 +- .../selective/SelectiveInsertionProvider.java | 19 +- .../SelectiveInsertionSearchQSimModule.java | 17 +- .../DrtModeFeedforwardRebalanceModule.java | 8 +- ...astHeuristicZonalRelocationCalculator.java | 14 +- .../FeedforwardRebalancingStrategy.java | 49 +- .../Feedforward/FeedforwardSignalHandler.java | 28 +- .../rebalancing/RebalancingModule.java | 1 - .../rebalancing/RebalancingUtils.java | 22 +- .../NetDepartureReplenishDemandEstimator.java | 30 +- .../PreviousIterationDrtDemandEstimator.java | 27 +- .../demandestimator/ZonalDemandEstimator.java | 6 +- ...AggregatedMinCostRelocationCalculator.java | 14 +- .../DrtModeMinCostFlowRebalancingModule.java | 18 +- .../MinCostFlowRebalancingStrategy.java | 18 +- .../mincostflow/TransportProblem.java | 12 +- .../ZonalRelocationCalculator.java | 10 +- .../DemandEstimatorAsTargetCalculator.java | 12 +- ...leVehicleDistributionTargetCalculator.java | 26 +- .../EqualVehicleDensityTargetCalculator.java | 33 +- ...clesToPopulationRatioTargetCalculator.java | 35 +- .../RebalancingTargetCalculator.java | 8 +- ...cceptor.java => DefaultOfferAcceptor.java} | 15 +- .../drt/passenger/DrtOfferAcceptor.java | 3 - .../prebooking/PrebookingStopActivity.java | 8 +- .../contrib/drt/run/DrtConfigGroup.java | 8 +- .../matsim/contrib/drt/run/DrtModeModule.java | 2 + .../DefaultRequestInsertionScheduler.java | 18 +- .../analysis/zonal/DrtZonalSystemTest.java | 29 +- .../RandomDrtZoneTargetLinkSelectorTest.java | 4 +- .../optimizer/MaxDetourConstraintTest.java | 13 - .../DefaultUnplannedRequestInserterTest.java | 3 +- .../insertion/InsertionGeneratorTest.java | 9 +- ...eviousIterationDrtDemandEstimatorTest.java | 14 +- ...ualVehicleDensityTargetCalculatorTest.java | 24 +- ...ToPopulationRatioTargetCalculatorTest.java | 87 +- .../drt/prebooking/PrebookingTest.java | 90 +- .../drt/run/examples/RunDrtExampleIT.java | 24 +- .../matsim/contrib/zone/io/ZoneShpReader.java | 4 +- .../matsim/contrib/zone/io/ZoneShpWriter.java | 2 +- .../events/VehicleLeavesTrafficEventTest.java | 6 +- ...unAverageEmissionToolOfflineExampleIT.java | 18 +- .../contrib/ev/example/RunEvExampleTest.java | 10 +- ...nEvExampleWithLTHConsumptionModelTest.java | 10 +- .../usecases/chessboard/RunChessboardIT.java | 6 +- contribs/hybridsim/pom.xml | 4 +- .../matsim/modechoice/CandidateGenerator.java | 7 +- .../modechoice/InformedModeChoiceModule.java | 34 +- .../matsim/modechoice/ModeAvailability.java | 21 +- .../org/matsim/modechoice/ModeEstimate.java | 6 +- .../org/matsim/modechoice/ModeOptions.java | 33 +- .../org/matsim/modechoice/PlanCandidate.java | 22 +- .../java/org/matsim/modechoice/PlanModel.java | 1 + .../matsim/modechoice/PlanModelService.java | 28 +- .../commands/GenerateChoiceSet.java | 5 +- .../estimators/DefaultLegScoreEstimator.java | 2 +- .../estimators/FixedCostsEstimator.java | 10 +- .../modechoice/estimators/LegEstimator.java | 5 +- .../estimators/PtTripEstimator.java | 2 +- .../modechoice/estimators/TripEstimator.java | 10 +- .../modechoice/pruning/CandidatePruner.java | 36 +- .../pruning/ChangeExpBetaPruner.java | 44 + .../SelectBestKPlanModesStrategyProvider.java | 10 +- .../SelectFromGeneratorStrategy.java | 34 - .../SelectSingleTripModeStrategy.java | 11 +- .../replanning/SelectSubtourModeStrategy.java | 16 +- .../SimplePlanSelectionStrategy.java | 69 + .../SimplePlanSelectionStrategyModule.java | 29 - .../search/AbstractCandidateGenerator.java | 4 +- .../search/BestChoiceGenerator.java | 6 +- .../modechoice/search/ModeChoiceSearch.java | 7 +- .../search/SingleTripChoicesGenerator.java | 2 +- .../search/TopKChoicesGenerator.java | 10 +- .../estimators/ComplexTripEstimator.java | 2 +- .../pruning/CandidatePrunerTest.java | 38 + .../modechoice/pruning/ExamplePruner.java | 32 + .../modechoice/search/TopKMinMaxTest.java | 10 +- .../minibus/schedule/CreatePStops.java | 68 +- ...JunctionApproachesAndBetweenJunctions.java | 130 +- .../parkingproxy/run/RunAreaAnalysis.java | 6 +- .../run/RunParkingSearchScenarioIT.java | 10 +- .../run/RunWithParkingProxyIT.java | 6 +- contribs/protobuf/pom.xml | 2 +- .../railsim/qsimengine/RailsimEngine.java | 9 +- .../railsim/qsimengine/UpdateEvent.java | 3 + .../deadlocks/SimpleDeadlockAvoidance.java | 4 +- .../disposition/SimpleDisposition.java | 2 +- .../qsimengine/resources/RailLink.java | 2 +- .../resources/RailResourceManager.java | 2 +- .../integration/RailsimIntegrationTest.java | 5 + .../qsimengine/RailsimDeadlockTest.java | 14 +- .../RailsimEngineMovingBlockTest.java | 45 +- .../railsim/qsimengine/RailsimEngineTest.java | 18 +- .../config.xml | 39 + .../trainNetwork.xml | 144 + .../transitSchedule.xml | 60 + .../transitVehicles.xml | 48 + .../run/RoadPricingByConfigfileTest.java | 4 +- .../analysis/skims/CalculateSkimMatrices.java | 4 +- .../matsim/analysis/skims/MatricesToXY.java | 4 +- .../utils/WriteStationShapefile.java | 4 +- .../builder/TravelTimeFourWaysTest.java | 5 +- .../signals/integration/SignalSystemsIT.java | 9 +- contribs/simwrapper/pom.xml | 12 + .../small-scale-traffic-generation/README.md | 43 +- ...ateDifferentPlansForFreightPopulation.java | 0 ...rateSmallScaleCommercialTrafficDemand.java | 99 +- .../LanduseBuildingAnalysis.java | 99 +- .../SmallScaleCommercialTrafficUtils.java | 91 +- .../TrafficVolumeGeneration.java | 24 +- .../TripDistributionMatrix.java | 82 +- .../ValueSelectorUnderGivenProbability.java | 12 +- .../LanduseBuildingAnalysisTest.java | 271 +- ...nerateSmallScaleCommercialTrafficTest.java | 198 + .../SCTUtils.java | 7 +- .../SmallScaleCommercialTrafficUtilsTest.java | 19 +- .../TrafficVolumeGenerationTest.java | 97 +- .../TripDistributionMatrixTest.java | 54 +- ...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 + .../config_demand.xml | 53 + .../dataDistributionPerZone.csv | 4 + .../output_carriers.xml.gz | Bin .../exampleServiceCarrier/vehicleTypes.xml.gz | Bin .../output_carriers.xml.gz | Bin .../vehicleTypes.xml.gz | Bin .../existingModels/existingModels.csv | 0 .../investigationAreaData.csv | 3 + .../shp/testBuildings.cpg | 0 .../shp/testBuildings.dbf | Bin .../shp/testBuildings.prj | 0 .../shp/testBuildings.qmd | 0 .../shp/testBuildings.shp | Bin .../shp/testBuildings.shx | Bin .../shp/testLanduse.cpg | 0 .../shp/testLanduse.dbf | Bin .../shp/testLanduse.prj | 0 .../shp/testLanduse.qmd | 0 .../shp/testLanduse.shp | Bin .../shp/testLanduse.shx | Bin .../shp/testRegions.cpg} | 0 .../shp/testRegions.dbf | Bin 0 -> 280 bytes .../shp/testRegions.prj} | 0 .../shp/testRegions.qmd | 26 + .../shp/testRegions.shp | Bin 0 -> 372 bytes .../shp/testRegions.shx | Bin 0 -> 116 bytes .../shp/testZones.cpg | 1 + .../shp/testZones.dbf | Bin .../shp/testZones.prj | 1 + .../shp/testZones.qmd | 0 .../shp/testZones.shp | Bin .../shp/testZones.shx | Bin .../test.output_events.xml.gz | Bin 0 -> 31240 bytes .../vehicleTypes.xml | 0 .../contrib/sumo/SumoNetworkConverter.java | 24 +- .../sumo/SumoNetworkFeatureExtractor.java | 194 + .../contrib/sumo/SumoNetworkHandler.java | 842 ++-- .../sumo/SumoNetworkConverterTest.java | 44 +- .../contrib/etaxi/run/RunETaxiScenarioIT.java | 6 +- .../taxi/optimizer/TaxiOptimizerTests.java | 6 +- contribs/vsp/pom.xml | 2 +- .../contrib/vsp/scenario/SnzActivities.java | 4 - ...tTimeAndDistanceAnalysisEventsHandler.java | 91 +- .../RunFreightAnalysisEventBased.java | 2 +- .../act2mode/ActivityToModeAnalysis.java | 30 +- .../networkAnalysis/NetworkAnalyzer.java | 330 +- .../utils/PtAccesShapeWriter.java | 38 +- .../utils/PtAccessMapShapeWriter.java | 40 +- .../ptPaxVolumes/PtPaxVolumesAnalyzer.java | 20 +- .../TransitSchedule2Shp.java | 34 +- .../TransitVehicleVolumeAnalyzer.java | 4 +- .../vsp/analysis/utils/heatMap/HeatMap.java | 30 +- .../andreas/utils/ana/RouteAllModesAsCar.java | 50 +- .../WorkHomeShapeCounter.java | 79 +- .../utils/pop/FilterPopulationByShape.java | 62 +- .../transitSchedule2shape/DaShapeWriter.java | 100 +- .../CORINELandCoverCoordsModifier.java | 10 +- .../corineLandcover/CorineLandCoverData.java | 4 +- .../CommuterGenerator.java | 36 +- .../DgLanduseReader.java | 24 +- .../DgPopulation2ShapeWriter.java | 20 +- .../demandde/pendlermatrix/GVPlanReader.java | 38 +- .../pendlermatrix/PendlerMatrixReader.java | 4 +- .../demandde/pendlermatrix/Verschmierer.java | 18 +- .../prognose2025/DemandMatrixReader.java | 4 +- .../src/main/java/playground/vsp/ev/README.md | 2 + .../java/playground/vsp/ev/UrbanEVModule.java | 34 +- .../vsp/ev/UrbanEVTripsPlanner.java | 63 +- .../java/playground/vsp/ev/UrbanEVUtils.java | 67 + .../cemdap/input/SynPopCreator.java | 130 +- .../cemdap/input/SynPopCreatorChildren.java | 34 +- .../cemdap/input/ZoneAndLOSGeneratorV2.java | 58 +- .../CemdapOutput2MatsimPlansConverter.java | 36 +- .../java/playground/vsp/ev/UrbanEVIT.java | 6 +- .../java/playground/vsp/ev/UrbanEVTests.java | 82 +- .../vsp/pt/fare/PtTripFareEstimatorTest.java | 2 +- .../TimeDistance_perVehicle.tsv | 2 +- .../TimeDistance_perVehicleType.tsv | 4 +- matsim/.gitignore | 2 +- matsim/pom.xml | 9 +- .../routing/pt/raptor/RaptorParameters.java | 10 + .../pt/raptor/SwissRailRaptorCore.java | 4 +- .../pt/stop2stop/PtStop2StopAnalysis2Shp.java | 4 +- .../core/config/ReflectiveConfigGroup.java | 43 +- .../config/groups/ControllerConfigGroup.java | 19 + .../core/controler/AbstractController.java | 2 +- .../org/matsim/core/events/EventsUtils.java | 81 +- .../org/matsim/core/network/LinkImpl.java | 8 +- .../org/matsim/core/network/NetworkUtils.java | 4 + ...tworkTeleatlasAddManeuverRestrictions.java | 14 +- .../network/io/NetworkReaderTeleatlas.java | 26 +- .../matsim/core/population/PersonUtils.java | 23 + .../core/population/PopulationUtils.java | 21 + .../annealing/ReplanningAnnealer.java | 62 +- .../ReplanningAnnealerConfigGroup.java | 54 +- .../NetworkRoutingInclAccessEgressModule.java | 19 +- .../matsim/core/utils/gis/GeoFileReader.java | 285 ++ .../matsim/core/utils/gis/GeoFileWriter.java | 101 + .../core/utils/gis/ShapeFileReader.java | 107 +- .../core/utils/gis/ShapeFileWriter.java | 35 +- .../java/org/matsim/run/gui/ExeRunner.java | 7 + .../ComparisonResult.java | 6 + .../EventFingerprint.java | 165 + .../EventsFileComparator.java | 38 +- .../EventsFileFingerprintComparator.java | 124 + .../FingerprintEventHandler.java | 212 + .../utils/eventsfilecomparison/Worker.java | 2 + .../matsim2esri/network/Links2ESRIShape.java | 4 +- .../matsim2esri/network/Nodes2ESRIShape.java | 8 +- .../plans/SelectedPlans2ESRIShape.java | 12 +- .../gis/shp2matsim/ShpGeometryUtils.java | 6 +- .../ObjectAttributesConverter.java | 1 + .../objectattributes/StringDoubleMap.java | 14 + .../attributeconverters/StringConverter.java | 13 +- .../StringDoubleMapConverter.java | 38 + .../org/matsim/vehicles/VehicleUtils.java | 47 +- .../pt/raptor/SwissRailRaptorTest.java | 45 +- .../config/ReflectiveConfigGroupTest.java | 9 +- .../AbstractNetworkWriterReaderTest.java | 19 + .../annealing/ReplanningAnnealerTest.java | 69 +- ...ReaderTest.java => GeoFileReaderTest.java} | 18 +- ...WriterTest.java => GeoFileWriterTest.java} | 83 +- .../java/org/matsim/examples/EquilTest.java | 5 +- .../examples/OnePercentBerlin10sIT.java | 5 +- .../org/matsim/testcases/MatsimTestUtils.java | 3 +- .../EventsFileComparatorTest.java | 2 +- .../EventsFileFingerprintComparatorTest.java | 143 + .../network/Network2ESRIShapeTest.java | 12 +- .../plans/SelectedPlans2ESRIShapeTest.java | 6 +- .../StringDoubleMapConverterTest.java | 16 + .../GeoFileReaderTest/testGpkg/test+test.gpkg | Bin 0 -> 106496 bytes .../testShp}/test+test.dbf | Bin .../testShp}/test+test.prj | 0 .../testShp}/test+test.qpj | 0 .../testShp}/test+test.shp | Bin .../testShp}/test+test.shx | Bin .../testGeopackageFileWriter/test.gpkg | Bin 0 -> 106496 bytes .../testShapeFileWriter/test.dbf | Bin .../testShapeFileWriter/test.prj | 0 .../testShapeFileWriter/test.qix | Bin .../testShapeFileWriter/test.qpj | 0 .../testShapeFileWriter/test.shp | Bin .../testShapeFileWriter/test.shx | Bin .../correct.fp.zst | Bin 0 -> 196 bytes .../events.attribute-order.xml | 14 + .../events.diff-hash.xml | 14 + .../events.diff-num-timestamps.xml | 12 + .../events.diff-type-count.fp.zst | Bin 0 -> 194 bytes .../events.diff-type-count.xml | 14 + .../events.event-order-wrong_logic.xml | 14 + .../events.event-order.xml | 14 + .../events.one-more-event.xml | 15 + .../events_correct.xml | 14 + pom.xml | 33 +- 386 files changed, 22342 insertions(+), 4208 deletions(-) rename contribs/application/src/main/java/org/matsim/application/{commands => }/RunScenario.java (67%) rename contribs/application/src/main/java/org/matsim/application/{commands => }/ShowGUI.java (65%) create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/SampleNetwork.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/FeatureRegressor.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkAttribute.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkModel.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParams.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/DecisionTreeParams.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_dead_end.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_priority.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_right_before_left.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_traffic_light.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_priority.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_right_before_left.java create mode 100644 contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_traffic_light.java create mode 100644 contribs/application/src/test/java/org/matsim/application/ConfigYamlUpdateTest.java create mode 100644 contribs/application/src/test/java/org/matsim/application/prepare/network/params/ApplyNetworkParamsTest.java delete mode 100644 contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java create mode 100644 contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/config.xml create mode 100644 contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/multiLevel.yml create mode 100644 contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/params.yml create mode 100644 contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/standard.yml create mode 100644 contribs/application/test/input/org/matsim/application/prepare/network/params/osm.net.xml delete mode 100644 contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/config_demand.xml delete mode 100644 contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/dataDistributionPerZone.csv delete mode 100644 contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/investigationAreaData.csv create mode 100644 contribs/common/src/main/java/org/matsim/contrib/common/zones/Zone.java create mode 100644 contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneImpl.java create mode 100644 contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystem.java create mode 100644 contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemImpl.java create mode 100644 contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemUtils.java create mode 100644 contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3GridUtils.java create mode 100644 contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3Utils.java create mode 100644 contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java create mode 100644 contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java create mode 100644 contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/drtZone/H3DrtZonalSystemTest.java delete mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystem.java delete mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZone.java rename contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/{MaxDetourOfferAcceptor.java => DefaultOfferAcceptor.java} (62%) create mode 100644 contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/pruning/ChangeExpBetaPruner.java delete mode 100644 contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectFromGeneratorStrategy.java create mode 100644 contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SimplePlanSelectionStrategy.java delete mode 100644 contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SimplePlanSelectionStrategyModule.java create mode 100644 contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/pruning/CandidatePrunerTest.java create mode 100644 contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/pruning/ExamplePruner.java create mode 100644 contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/config.xml create mode 100644 contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/trainNetwork.xml create mode 100644 contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitSchedule.xml create mode 100644 contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitVehicles.xml rename contribs/{application => small-scale-traffic-generation}/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/CreateDifferentPlansForFreightPopulation.java (100%) rename contribs/{application => small-scale-traffic-generation}/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java (97%) rename contribs/{application => small-scale-traffic-generation}/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java (80%) rename contribs/{application => small-scale-traffic-generation}/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java (86%) rename contribs/{application => small-scale-traffic-generation}/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java (99%) rename contribs/{application => small-scale-traffic-generation}/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java (90%) rename contribs/{application => small-scale-traffic-generation}/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java (86%) rename contribs/{application => small-scale-traffic-generation}/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java (52%) create mode 100644 contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java rename contribs/{application => small-scale-traffic-generation}/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SCTUtils.java (78%) rename contribs/{application => small-scale-traffic-generation}/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java (79%) rename contribs/{application => small-scale-traffic-generation}/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java (92%) rename contribs/{application => small-scale-traffic-generation}/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java (80%) 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/config_demand.xml create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/dataDistributionPerZone.csv rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/output_carriers.xml.gz (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/output_carriers.xml.gz (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/existingModels.csv (100%) create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/investigationAreaData.csv rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.cpg (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.dbf (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.prj (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.qmd (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.shp (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.shx (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.cpg (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.dbf (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.prj (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.qmd (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.shp (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.shx (100%) rename contribs/{application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.cpg => small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.cpg} (100%) create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.dbf rename contribs/{application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.prj => small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.prj} (100%) create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.qmd create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.shp create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.shx create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.cpg rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.dbf (100%) create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.prj rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.qmd (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.shp (100%) rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.shx (100%) create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz rename contribs/{application => small-scale-traffic-generation}/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml (100%) create mode 100644 contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java create mode 100644 contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVUtils.java create mode 100644 matsim/src/main/java/org/matsim/core/utils/gis/GeoFileReader.java create mode 100644 matsim/src/main/java/org/matsim/core/utils/gis/GeoFileWriter.java create mode 100644 matsim/src/main/java/org/matsim/utils/eventsfilecomparison/ComparisonResult.java create mode 100644 matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventFingerprint.java create mode 100644 matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparator.java create mode 100644 matsim/src/main/java/org/matsim/utils/eventsfilecomparison/FingerprintEventHandler.java create mode 100644 matsim/src/main/java/org/matsim/utils/objectattributes/StringDoubleMap.java create mode 100644 matsim/src/main/java/org/matsim/utils/objectattributes/attributeconverters/StringDoubleMapConverter.java rename matsim/src/test/java/org/matsim/core/utils/gis/{ShapeFileReaderTest.java => GeoFileReaderTest.java} (78%) rename matsim/src/test/java/org/matsim/core/utils/gis/{ShapeFileWriterTest.java => GeoFileWriterTest.java} (70%) create mode 100644 matsim/src/test/java/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest.java create mode 100644 matsim/src/test/java/org/matsim/utils/objectattributes/attributeconverters/StringDoubleMapConverterTest.java create mode 100644 matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testGpkg/test+test.gpkg rename matsim/src/test/resources/test/input/org/matsim/core/utils/gis/{ShapeFileReaderTest/testPlusInFilename => GeoFileReaderTest/testShp}/test+test.dbf (100%) rename matsim/src/test/resources/test/input/org/matsim/core/utils/gis/{ShapeFileReaderTest/testPlusInFilename => GeoFileReaderTest/testShp}/test+test.prj (100%) rename matsim/src/test/resources/test/input/org/matsim/core/utils/gis/{ShapeFileReaderTest/testPlusInFilename => GeoFileReaderTest/testShp}/test+test.qpj (100%) rename matsim/src/test/resources/test/input/org/matsim/core/utils/gis/{ShapeFileReaderTest/testPlusInFilename => GeoFileReaderTest/testShp}/test+test.shp (100%) rename matsim/src/test/resources/test/input/org/matsim/core/utils/gis/{ShapeFileReaderTest/testPlusInFilename => GeoFileReaderTest/testShp}/test+test.shx (100%) create mode 100644 matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testGeopackageFileWriter/test.gpkg rename matsim/src/test/resources/test/input/org/matsim/core/utils/gis/{ShapeFileWriterTest => GeoFileWriterTest}/testShapeFileWriter/test.dbf (100%) rename matsim/src/test/resources/test/input/org/matsim/core/utils/gis/{ShapeFileWriterTest => GeoFileWriterTest}/testShapeFileWriter/test.prj (100%) rename matsim/src/test/resources/test/input/org/matsim/core/utils/gis/{ShapeFileWriterTest => GeoFileWriterTest}/testShapeFileWriter/test.qix (100%) rename matsim/src/test/resources/test/input/org/matsim/core/utils/gis/{ShapeFileWriterTest => GeoFileWriterTest}/testShapeFileWriter/test.qpj (100%) rename matsim/src/test/resources/test/input/org/matsim/core/utils/gis/{ShapeFileWriterTest => GeoFileWriterTest}/testShapeFileWriter/test.shp (100%) rename matsim/src/test/resources/test/input/org/matsim/core/utils/gis/{ShapeFileWriterTest => GeoFileWriterTest}/testShapeFileWriter/test.shx (100%) create mode 100644 matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/correct.fp.zst create mode 100644 matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.attribute-order.xml create mode 100644 matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-hash.xml create mode 100644 matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-num-timestamps.xml create mode 100644 matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-type-count.fp.zst create mode 100644 matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-type-count.xml create mode 100644 matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order-wrong_logic.xml create mode 100644 matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order.xml create mode 100644 matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.one-more-event.xml create mode 100644 matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events_correct.xml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 04281ecd9a7..c4f3e2a0c02 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,4 +4,4 @@ # the repo. Unless a later match takes precedence, # mentioned account names will be requested for # review when someone opens a pull request. -* @moia-dev/mobility-analytics +* @mfrawley-moia @nkuehnel @fzwick @TomE168 diff --git a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityUtils.java b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityUtils.java index db9adc47ccd..43420197e8e 100644 --- a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityUtils.java +++ b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityUtils.java @@ -39,7 +39,7 @@ import org.matsim.core.network.NetworkUtils; import org.matsim.core.network.algorithms.TransportModeNetworkFilter; import org.matsim.core.utils.geometry.CoordUtils; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.facilities.*; import org.opengis.feature.simple.SimpleFeature; @@ -225,7 +225,7 @@ public static final ActivityFacilities createFacilityForEachLink(String facility public static final ActivityFacilities createFacilityFromBuildingShapefile(String shapeFileName, String identifierCaption, String numberOfHouseholdsCaption) { - ShapeFileReader shapeFileReader = new ShapeFileReader(); + GeoFileReader shapeFileReader = new GeoFileReader(); Collection features = shapeFileReader.readFileAndInitialize(shapeFileName); ActivityFacilities facilities = FacilitiesUtils.createActivityFacilities("DensitiyFacilities"); diff --git a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/VoronoiExample.java b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/VoronoiExample.java index 24544971132..382e13b68f7 100644 --- a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/VoronoiExample.java +++ b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/VoronoiExample.java @@ -28,17 +28,17 @@ import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.triangulate.VoronoiDiagramBuilder; import org.matsim.contrib.matrixbasedptrouter.utils.BoundingBox; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.opengis.feature.simple.SimpleFeature; /** * @author dziemke */ class VoronoiExample { - + public static void main(String[] args) { GeometryFactory geometryFactory = new GeometryFactory(); - + Collection sites = new ArrayList<>(); sites.add(new Coordinate(70, 70)); sites.add(new Coordinate(50, 150)); @@ -48,16 +48,16 @@ public static void main(String[] args) { sites.add(new Coordinate(250, 150)); sites.add(new Coordinate(350, 50)); sites.add(new Coordinate(370, 170)); - + VoronoiDiagramBuilder voronoiDiagramBuilder = new VoronoiDiagramBuilder(); - voronoiDiagramBuilder.setSites(sites); - + voronoiDiagramBuilder.setSites(sites); + List polygons = voronoiDiagramBuilder.getSubdivision().getVoronoiCellPolygons(geometryFactory); - + BoundingBox boundingBox = BoundingBox.createBoundingBox(0, 0, 400, 200); Polygon boundingPolygon = VoronoiGeometryUtils.createBoundingPolygon(boundingBox); Collection cutGeometries = VoronoiGeometryUtils.cutPolygonsByBoundary(polygons, boundingPolygon); Collection features = VoronoiGeometryUtils.createFeaturesFromPolygons(cutGeometries); - ShapeFileWriter.writeGeometries(features, "/Users/dominik/voronoi_test.shp"); + GeoFileWriter.writeGeometries(features, "/Users/dominik/voronoi_test.shp"); } } diff --git a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/utils/GeoserverUpdater.java b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/utils/GeoserverUpdater.java index 2f25f641a4c..a5799e30983 100644 --- a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/utils/GeoserverUpdater.java +++ b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/utils/GeoserverUpdater.java @@ -47,7 +47,7 @@ import org.matsim.core.utils.geometry.CoordinateTransformation; import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.geometry.transformations.TransformationFactory; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.matsim.facilities.ActivityFacility; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; @@ -74,7 +74,7 @@ public GeoserverUpdater (String crs, String name, Map, Geom this.pushing2Geoserver = pushing2Geoserver; this.createQGisOutput = createQGisOutput; } - + private Map, Map> accessibilitiesMap = new HashMap<>() ; @Override @@ -95,16 +95,16 @@ public void finish() { SimpleFeatureTypeBuilder featureTypeBuilder = createFeatureTypeBuilder(); SimpleFeatureType featureType = featureTypeBuilder.buildFeatureType(); DefaultFeatureCollection featureCollection = createFeatureCollection(geometryFactory, featureType); - + if (outputDirectory != null) { File file = new File(outputDirectory); file.mkdirs(); } - + if (createQGisOutput) { - ShapeFileWriter.writeGeometries(featureCollection, outputDirectory + "/result.shp"); + GeoFileWriter.writeGeometries(featureCollection, outputDirectory + "/result.shp"); } - + if (pushing2Geoserver) { updateOnGeoserver(featureType, featureCollection); } @@ -130,7 +130,7 @@ private DefaultFeatureCollection createFeatureCollection(GeometryFactory geometr LOG.info("Start creating features from accessibility data."); DefaultFeatureCollection featureCollection = new DefaultFeatureCollection("internal", featureType); SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType); - + CoordinateTransformation transformation = TransformationFactory.getCoordinateTransformation(this.crs, TransformationFactory.WGS84); for (Entry, Map> entry : accessibilitiesMap.entrySet()) { @@ -145,10 +145,10 @@ private DefaultFeatureCollection createFeatureCollection(GeometryFactory geometr i++; } featureBuilder.add(geometryFactory.createPolygon(transformedCoordinates)); - + featureBuilder.add(Integer.parseInt(entry.getKey().getFirst().getId().toString())); featureBuilder.add(entry.getKey().getSecond()); - + for (Modes4Accessibility modeEnum : Modes4Accessibility.values()) { String mode = modeEnum.toString(); Double accessibility = entry.getValue().get(mode); @@ -188,14 +188,14 @@ private void updateOnGeoserver(SimpleFeatureType featureType, DefaultFeatureColl // There have been errors with the data store if the dependency "gt-jdbc-postgis", version 13.0 was missing! DataStore dataStore = DataStoreFinder.getDataStore(params); LOG.info("dataStore = " + dataStore); - + // Remove schema in case it already exists try { dataStore.removeSchema(name); } catch (IllegalArgumentException e) { LOG.warn("Could not remove schema. Probably, it has not existed yet."); } - + dataStore.createSchema(featureType); SimpleFeatureStore featureStore = (SimpleFeatureStore) dataStore.getFeatureSource(name); featureStore.addFeatures(featureCollection); diff --git a/contribs/accidents/src/main/java/org/matsim/contrib/accidents/runExample/AccidentsNetworkModification.java b/contribs/accidents/src/main/java/org/matsim/contrib/accidents/runExample/AccidentsNetworkModification.java index 6794cd558d6..7388ce718d5 100644 --- a/contribs/accidents/src/main/java/org/matsim/contrib/accidents/runExample/AccidentsNetworkModification.java +++ b/contribs/accidents/src/main/java/org/matsim/contrib/accidents/runExample/AccidentsNetworkModification.java @@ -44,7 +44,7 @@ import org.matsim.core.utils.geometry.CoordinateTransformation; import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.geometry.transformations.TransformationFactory; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; /** @@ -59,26 +59,26 @@ public class AccidentsNetworkModification { public AccidentsNetworkModification(Scenario scenario) { this.scenario = scenario; } - + public Network setLinkAttributsBasedOnOSMFile(String landuseOsmFile, String osmCRS, String[] tunnelLinkIDs, String[] planfreeLinkIDs) throws MalformedURLException, IOException { - + AccidentsConfigGroup accidentsCfg = (AccidentsConfigGroup) scenario.getConfig().getModules().get(AccidentsConfigGroup.GROUP_NAME); - + Map landUseFeaturesBB = new HashMap<>(); Map landUseDataBB = new HashMap<>(); - + log.info("Initializing all link-specific information..."); - + if (landuseOsmFile == null) { log.warn("Landuse shape file is null. Using default values..."); } else { SimpleFeatureSource ftsLandUseBB; if (!landuseOsmFile.startsWith("http")) { - ftsLandUseBB = ShapeFileReader.readDataFile(landuseOsmFile); + ftsLandUseBB = GeoFileReader.readDataFile(landuseOsmFile); } else { ftsLandUseBB = FileDataStoreFinder.getDataStore(new URL(landuseOsmFile)).getFeatureSource(); - } + } try (SimpleFeatureIterator itLandUseBB = ftsLandUseBB.getFeatures().features()) { while (itLandUseBB.hasNext()) { SimpleFeature ftLandUseBB = itLandUseBB.next(); @@ -95,23 +95,23 @@ public Network setLinkAttributsBasedOnOSMFile(String landuseOsmFile, String osmC e.printStackTrace(); } } - + int linkCounter = 0; for (Link link : this.scenario.getNetwork().getLinks().values()) { - + if (linkCounter % 100 == 0) { log.info("Link #" + linkCounter + " (" + (int) ((double) linkCounter / this.scenario.getNetwork().getLinks().size() * 100) + "%)"); } - linkCounter++; - + linkCounter++; + link.getAttributes().putAttribute(accidentsCfg.getAccidentsComputationMethodAttributeName(), AccidentsConfigGroup.AccidentsComputationMethod.BVWP.toString()); - + ArrayList bvwpRoadType = new ArrayList<>(); - + // 'plangleich', 'planfrei' or tunnel? bvwpRoadType.add(0, 1); - + for(int j=0; j < planfreeLinkIDs.length; j++){ if(planfreeLinkIDs[j].equals(String.valueOf(link.getId()))){ bvwpRoadType.set(0, 0); // Change to Plan free @@ -119,7 +119,7 @@ public Network setLinkAttributsBasedOnOSMFile(String landuseOsmFile, String osmC break; } } - + for(int i=0; i < tunnelLinkIDs.length; i++){ if(tunnelLinkIDs[i].equals(String.valueOf(link.getId()))){ bvwpRoadType.set(0, 2); // Change to Tunnel @@ -127,25 +127,25 @@ public Network setLinkAttributsBasedOnOSMFile(String landuseOsmFile, String osmC break; } } - + // builtup or not builtup area? String osmLandUseFeatureBBId = getOSMLandUseFeatureBBId(link, landUseFeaturesBB, osmCRS); - - if (osmLandUseFeatureBBId == null) { + + if (osmLandUseFeatureBBId == null) { log.warn("No area type found for link " + link.getId() + ". Using default value: not built-up area."); if (link.getFreespeed() > 16.) { bvwpRoadType.add(1, 0); } else { bvwpRoadType.add(1, 2); } - + } else { String landUseTypeBB = landUseDataBB.get(osmLandUseFeatureBBId); if (landUseTypeBB.matches("commercial|industrial|recreation_ground|residential|retail")) { //built-up area if (link.getFreespeed() > 16.) { bvwpRoadType.add(1, 1); } else { - bvwpRoadType.add(1, 3); + bvwpRoadType.add(1, 3); } } else { if (link.getFreespeed() > 16.) { @@ -163,85 +163,85 @@ public Network setLinkAttributsBasedOnOSMFile(String landuseOsmFile, String osmC numberOfLanesBVWP = (int) link.getNumberOfLanes(); } bvwpRoadType.add(2, numberOfLanesBVWP); - + link.getAttributes().putAttribute( AccidentsConfigGroup.BVWP_ROAD_TYPE_ATTRIBUTE_NAME, bvwpRoadType.get(0) + "," + bvwpRoadType.get(1) + "," + bvwpRoadType.get(2)); } log.info("Initializing all link-specific information... Done."); return scenario.getNetwork(); } - + private String getOSMLandUseFeatureBBId(Link link, Map landUseFeaturesBB, String osmCRS) { - + if (landUseFeaturesBB == null || landUseFeaturesBB.isEmpty()) return null; - + CoordinateTransformation ctScenarioCRS2osmCRS = TransformationFactory.getCoordinateTransformation(this.scenario.getConfig().global().getCoordinateSystem(), osmCRS); - + Coord linkCoordinateTransformedToOSMCRS = ctScenarioCRS2osmCRS.transform(link.getCoord()); // this Method gives the middle point of the link back Point pMiddle = MGC.xy2Point(linkCoordinateTransformedToOSMCRS.getX(), linkCoordinateTransformedToOSMCRS.getY()); - + Coord linkStartCoordinateTransformedToOSMCRS = ctScenarioCRS2osmCRS.transform(link.getFromNode().getCoord()); Point pStart = MGC.xy2Point(linkStartCoordinateTransformedToOSMCRS.getX(), linkStartCoordinateTransformedToOSMCRS.getY()); - + Coord linkEndCoordinateTransformedToOSMCRS = ctScenarioCRS2osmCRS.transform(link.getToNode().getCoord()); Point pEnd = MGC.xy2Point(linkEndCoordinateTransformedToOSMCRS.getX(), linkEndCoordinateTransformedToOSMCRS.getY()); - + String osmLandUseFeatureBBId = null; - + for (SimpleFeature feature : landUseFeaturesBB.values()) { if (((Geometry) feature.getDefaultGeometry()).contains(pMiddle)) { return osmLandUseFeatureBBId = feature.getAttribute("osm_id").toString(); } } - + for (SimpleFeature feature : landUseFeaturesBB.values()) { if (((Geometry) feature.getDefaultGeometry()).contains(pStart)) { return osmLandUseFeatureBBId = feature.getAttribute("osm_id").toString(); } } - + for (SimpleFeature feature : landUseFeaturesBB.values()) { if (((Geometry) feature.getDefaultGeometry()).contains(pEnd)) { return osmLandUseFeatureBBId = feature.getAttribute("osm_id").toString(); } } - + // look around the link - + GeometryFactory geoFac = new GeometryFactory(); CoordinateTransformation cTosmCRSToGK4 = TransformationFactory.getCoordinateTransformation(osmCRS, "EPSG:31468"); - - double distance = 10.0; - + + double distance = 10.0; + while (osmLandUseFeatureBBId == null && distance <= 500) { Coord coordGK4 = cTosmCRSToGK4.transform(MGC.coordinate2Coord(pMiddle.getCoordinate())); Point pGK4 = geoFac.createPoint(MGC.coord2Coordinate(coordGK4)); - + Point pRightGK4 = geoFac.createPoint(new Coordinate(pGK4.getX() + distance, pGK4.getY())); Point pRight = transformPointFromGK4ToOSMCRS(pRightGK4, osmCRS); - + Point pDownGK4 = geoFac.createPoint(new Coordinate(pGK4.getX(), pGK4.getY() - distance)); Point pDown = transformPointFromGK4ToOSMCRS(pDownGK4, osmCRS); - + Point pLeftGK4 = geoFac.createPoint(new Coordinate(pGK4.getX() - distance, pGK4.getY())); Point pLeft = transformPointFromGK4ToOSMCRS(pLeftGK4, osmCRS); - + Point pUpGK4 = geoFac.createPoint(new Coordinate(pGK4.getX(), pGK4.getY() + distance)); Point pUp = transformPointFromGK4ToOSMCRS(pUpGK4, osmCRS); - + Point pUpRightGK4 = geoFac.createPoint(new Coordinate(pGK4.getX() + distance, pGK4.getY() + distance)); Point pUpRight = transformPointFromGK4ToOSMCRS(pUpRightGK4, osmCRS); - + Point pDownRightGK4 = geoFac.createPoint(new Coordinate(pGK4.getX() + distance, pGK4.getY() - distance)); Point pDownRight = transformPointFromGK4ToOSMCRS(pDownRightGK4, osmCRS); - + Point pDownLeftGK4 = geoFac.createPoint(new Coordinate(pGK4.getX() - distance, pGK4.getY() - distance)); Point pDownLeft = transformPointFromGK4ToOSMCRS(pDownLeftGK4, osmCRS); - + Point pUpLeftGK4 = geoFac.createPoint(new Coordinate(pGK4.getX() - distance, pGK4.getY() + distance)); Point pUpLeft = transformPointFromGK4ToOSMCRS(pUpLeftGK4, osmCRS); - + for (SimpleFeature feature : landUseFeaturesBB.values()) { - + if (((Geometry) feature.getDefaultGeometry()).contains(pRight)) { osmLandUseFeatureBBId = feature.getAttribute("osm_id").toString(); return osmLandUseFeatureBBId; @@ -268,17 +268,17 @@ private String getOSMLandUseFeatureBBId(Link link, Map la return osmLandUseFeatureBBId; } } - + distance += 10.0; } - + log.warn("No area type found. Returning null..."); return null; } private Point transformPointFromGK4ToOSMCRS(Point pointGK4, String osmCRS) { CoordinateTransformation ctGK4toOSMCRS = TransformationFactory.getCoordinateTransformation("EPSG:31468", osmCRS); - + Coord coordGK4 = MGC.coordinate2Coord(pointGK4.getCoordinate()); Point pointOSMCRS = new GeometryFactory().createPoint(MGC.coord2Coordinate(ctGK4toOSMCRS.transform(coordGK4))); return pointOSMCRS; diff --git a/contribs/analysis/src/main/java/org/matsim/contrib/analysis/christoph/TravelTimesWriter.java b/contribs/analysis/src/main/java/org/matsim/contrib/analysis/christoph/TravelTimesWriter.java index 21e616f6896..c1f1f9ea36e 100644 --- a/contribs/analysis/src/main/java/org/matsim/contrib/analysis/christoph/TravelTimesWriter.java +++ b/contribs/analysis/src/main/java/org/matsim/contrib/analysis/christoph/TravelTimesWriter.java @@ -41,7 +41,7 @@ import org.matsim.core.trafficmonitoring.TimeBinUtils; import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.gis.PolylineFeatureFactory; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.matsim.core.utils.io.IOUtils; import org.opengis.feature.simple.SimpleFeature; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -190,7 +190,7 @@ private void writeRows(BufferedWriter timesWriter, boolean absolute) throws IOEx public void writeAbsoluteSHPTravelTimes(String file, CoordinateReferenceSystem crs, boolean ignoreExitLinks) { try { Collection ft = generateSHPFileData(crs, this.network, true, ignoreExitLinks); - ShapeFileWriter.writeGeometries(ft, file); + GeoFileWriter.writeGeometries(ft, file); } catch (Exception e) { throw new RuntimeException(e); } @@ -199,7 +199,7 @@ public void writeAbsoluteSHPTravelTimes(String file, CoordinateReferenceSystem c public void writeRelativeSHPTravelTimes(String file, CoordinateReferenceSystem crs, boolean ignoreExitLinks) { try { Collection ft = generateSHPFileData(crs, this.network, false, ignoreExitLinks); - ShapeFileWriter.writeGeometries(ft, file); + GeoFileWriter.writeGeometries(ft, file); } catch (Exception e) { throw new RuntimeException(e); } 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/ApplicationUtils.java b/contribs/application/src/main/java/org/matsim/application/ApplicationUtils.java index bc9c97f08b3..083a315ecb5 100644 --- a/contribs/application/src/main/java/org/matsim/application/ApplicationUtils.java +++ b/contribs/application/src/main/java/org/matsim/application/ApplicationUtils.java @@ -1,5 +1,9 @@ package org.matsim.application; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Scenario; @@ -7,11 +11,14 @@ import org.matsim.application.options.InputOptions; import org.matsim.application.options.OutputOptions; import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigAliases; +import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ConfigUtils; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.io.IOUtils; import picocli.CommandLine; +import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; @@ -21,13 +28,20 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.PathMatcher; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; import java.util.stream.Stream; +import java.util.stream.StreamSupport; public class ApplicationUtils { private static final Logger log = LogManager.getLogger(ApplicationUtils.class); + /** + * This encoding indicates command line was used to start the jar. + */ + private static final String WIN_CLI_ENCODING = "cp850"; + private ApplicationUtils() { } @@ -46,7 +60,197 @@ public static String[] mergeArgs(String[] args, String... defaultArgs) { } /** - * Extends a context (usually config location) with an relative filename. + * Utility method to check if a jar might be run from the desktop (using double-click). + */ + public static boolean isRunFromDesktop() { + + // check if gui was explicitly enabled + String env = System.getenv().getOrDefault("RUN_GUI", "undefined"); + if (env.equalsIgnoreCase("true") || env.equals("1")) + return true; + else if (env.equalsIgnoreCase("false") || env.equals("0")) + return false; + + String property = System.getProperty("RUN_GUI", "undefined"); + if (property.equalsIgnoreCase("true") || property.equals("1")) + return true; + else if (property.equalsIgnoreCase("false") || property.equals("0")) + return false; + + String macIdentifier = System.getenv().getOrDefault("__CFBundleIdentifier", "none"); + + if (macIdentifier.equals("com.apple.java.JarLauncher") || macIdentifier.equals("com.apple.JavaLauncher")) + return true; + + String os = System.getProperty("os.name"); + + if (os.toLowerCase().startsWith("windows")) { + + // presence of the prompt variable indicates that the jar was run from the command line + boolean hasPrompt = System.getenv().containsKey("PROMPT"); + + // this prompt is not set in PowerShell, so we need another check + if (hasPrompt) + return false; + + // stdout.encoding from CLI are usually cp850 + String encoding = System.getProperty("stdout.encoding", "none"); + String sunEncoding = System.getProperty("sun.stdout.encoding", "none"); + + if (encoding.equals(WIN_CLI_ENCODING) || sunEncoding.equals(WIN_CLI_ENCODING)) + return false; + + // Run from intelij, will not start the gui by default + if (System.getenv().containsKey("IDEA_INITIAL_DIRECTORY")) + return false; + // also file.encoding=UTF-8, seems to be set by default in IntelliJ + + // if no other cli indicators are present, we have to assume that the jar was run from the desktop + return true; + } + + return false; + + } + + /** + * Apply run configuration in yaml format. + */ + public static void applyConfigUpdate(Config config, Path yaml) { + + if (!Files.exists(yaml)) { + throw new IllegalArgumentException("Given config yaml does not exist: " + yaml); + } + + ObjectMapper mapper = new ObjectMapper(new YAMLFactory() + .enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)); + + ConfigAliases aliases = new ConfigAliases(); + Deque emptyStack = new ArrayDeque<>(); + + try (BufferedReader reader = Files.newBufferedReader(yaml)) { + + JsonNode node = mapper.readTree(reader); + + Iterator> fields = node.fields(); + + while (fields.hasNext()) { + Map.Entry field = fields.next(); + String configGroupName = aliases.resolveAlias(field.getKey(), emptyStack); + ConfigGroup group = config.getModules().get(configGroupName); + if (group == null) { + group = new ConfigGroup(configGroupName); + config.addModule(group); + } + + applyNodeToConfigGroup(field.getValue(), group); + } + + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + } + + /** + * Sets the json config into + */ + private static void applyNodeToConfigGroup(JsonNode node, ConfigGroup group) { + + Iterator> fields = node.fields(); + + while (fields.hasNext()) { + Map.Entry field = fields.next(); + + if (isParameterSet(field.getValue())) { + + // store the current parameters sets, newly added sets are not merged with each other + List params = new ArrayList<>(group.getParameterSets(field.getKey())); + + for (JsonNode item : field.getValue()) { + + + // 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 { + + if (field.getValue().isTextual()) + group.addParam(field.getKey(), field.getValue().textValue()); + else if (field.getValue().isArray()) { + // arrays are joined using "," + Stream stream = StreamSupport.stream(field.getValue().spliterator(), false); + String string = stream.map(n -> n.isTextual() ? n.textValue() : n.toString()).collect(Collectors.joining(",")); + group.addParam(field.getKey(), string); + } else + group.addParam(field.getKey(), field.getValue().toString()); + } + } + } + + /** + * Any array of complex object can be considered a config group. + */ + private static boolean isParameterSet(JsonNode node) { + + if (!node.isArray()) + return false; + + // any object can be assigned as parameter set + for (JsonNode el : node) { + if (!el.isObject()) + return false; + } + + return true; + } + + /** + * Handle possible update and creation of parameter sets within a config group. + */ + private static void applyNodeAsParameterSet(String groupName, JsonNode item, ConfigGroup group, List params) { + + Iterator> it = item.fields(); + + // There was at least one matching group + boolean matched = false; + + while (!params.isEmpty() && it.hasNext()) { + + Map.Entry attr = it.next(); + List candidates = params.stream() + .filter(p -> p.getParams().containsKey(attr.getKey())) + .filter(p -> p.getParams().get(attr.getKey()) + .equals(attr.getValue().isTextual() ? attr.getValue().textValue() : attr.getValue().toString())) + .toList(); + + if (candidates.isEmpty()) + break; + + matched = true; + params = candidates; + } + + if (params.size() > 1) { + throw new IllegalArgumentException("Ambiguous parameter set: " + item); + } else if (params.size() == 1 && matched) { + applyNodeToConfigGroup(item, params.get(0)); + } else { + ConfigGroup newGroup = group.createParameterSet(groupName); + group.addParameterSet(newGroup); + applyNodeToConfigGroup(item, newGroup); + } + } + + /** + * Extends a context (usually config location) with a relative filename. * If the results is a local file, the path will be returned. Otherwise, it will be an url. * The results can be used as input for command line parameter or {@link IOUtils#resolveFileOrResource(String)}. * @@ -75,10 +279,11 @@ public static Path globFile(Path path, String pattern) { PathMatcher m = path.getFileSystem().getPathMatcher("glob:" + pattern); try { - return Files.list(path) - .filter(p -> m.matches(p.getFileName())) - .findFirst() - .orElseThrow(() -> new IllegalStateException("No " + pattern + " file found.")); + try (Stream list = Files.list(path)) { + return list.filter(p -> m.matches(p.getFileName())) + .findFirst() + .orElseThrow(() -> new IllegalStateException("No " + pattern + " file found.")); + } } catch (IOException e) { throw new RuntimeException(e); } 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 c1951c1b2a4..7d63518e323 100644 --- a/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java +++ b/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java @@ -1,17 +1,10 @@ package org.matsim.application; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; import com.google.common.collect.Lists; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Scenario; -import org.matsim.application.commands.RunScenario; -import org.matsim.application.commands.ShowGUI; import org.matsim.core.config.Config; -import org.matsim.core.config.ConfigAliases; import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ControllerConfigGroup; @@ -23,15 +16,12 @@ import picocli.CommandLine; import javax.annotation.Nullable; -import java.io.BufferedReader; import java.io.File; -import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; -import java.nio.file.Files; import java.nio.file.Path; import java.util.*; import java.util.concurrent.Callable; @@ -78,6 +68,8 @@ public abstract class MATSimApplication implements Callable, CommandLin private static final Logger log = LogManager.getLogger(MATSimApplication.class); + private static final String ARGS_DELIMITER = "§$"; + public static final String COLOR = "@|bold,fg(81) "; static final String DEFAULT_NAME = "MATSimApplication"; static final String HEADER = COLOR + @@ -170,7 +162,7 @@ public Integer call() throws Exception { Objects.requireNonNull(config); if (specs != null) - applySpecs(config, specs); + ApplicationUtils.applyConfigUpdate(config, specs); if (remainingArgs != null) { String[] args = remainingArgs.stream().map(s -> s.replace("-c:", "--config:")).toArray(String[]::new); @@ -210,99 +202,22 @@ public Integer call() throws Exception { } catch (Exception e) { log.error("Error running post-processing", e); } - } - } return 0; } - /** - * Apply given specs to config. - */ - private static void applySpecs(Config config, Path specs) { - - if (!Files.exists(specs)) { - throw new IllegalArgumentException("Desired run config does not exist:" + specs); - } - - ObjectMapper mapper = new ObjectMapper(new YAMLFactory() - .enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)); - - ConfigAliases aliases = new ConfigAliases(); - Deque emptyStack = new ArrayDeque<>(); - - try (BufferedReader reader = Files.newBufferedReader(specs)) { - - JsonNode node = mapper.readTree(reader); - - Iterator> fields = node.fields(); - - while (fields.hasNext()) { - Map.Entry field = fields.next(); - String configGroupName = aliases.resolveAlias(field.getKey(), emptyStack); - ConfigGroup group = config.getModules().get(configGroupName); - if (group == null) { - log.warn("Config group not found: {}", configGroupName); - continue; - } - - applyNodeToConfigGroup(field.getValue(), group); - } - - } catch (IOException e) { - e.printStackTrace(); - } - + File getConfigPath() { + return configPath; } - /** - * Sets the json config into - */ - private static void applyNodeToConfigGroup(JsonNode node, ConfigGroup group) { - - Iterator> fields = node.fields(); - - while (fields.hasNext()) { - Map.Entry field = fields.next(); - - if (field.getValue().isArray()) { - - Collection params = group.getParameterSets(field.getKey()); - - // single node and entry merged directly - if (field.getValue().size() == 1 && params.size() == 1) { - applyNodeToConfigGroup(field.getValue().get(0), params.iterator().next()); - } else { - - for (JsonNode item : field.getValue()) { - - Map.Entry first = item.fields().next(); - Optional m = params.stream().filter(p -> p.getParams().get(first.getKey()).equals(first.getValue().textValue())).findFirst(); - if (m.isEmpty()) - throw new IllegalArgumentException("Could not find matching param by key" + first); - - applyNodeToConfigGroup(item, m.get()); - } - } - - } else { - - if (!field.getValue().isValueNode()) - throw new IllegalArgumentException("Received complex value type instead of primitive: " + field.getValue()); - - - if (field.getValue().isTextual()) - group.addParam(field.getKey(), field.getValue().textValue()); - else - group.addParam(field.getKey(), field.getValue().toString()); - } - } + @Nullable + String getDefaultScenario() { + return defaultScenario; } - /** * Custom module configs that will be added to the {@link Config} object. * @@ -429,6 +344,13 @@ public static void run(Class clazz, String... args) l.addAll(Arrays.asList(args)); args = l.toArray(new String[0]); + + // Pass stored args to the instance as well + if (System.getenv().containsKey("MATSIM_GUI_ARGS")) { + String[] guiArgs = System.getenv("MATSIM_GUI_ARGS").split(ARGS_DELIMITER); + if (guiArgs.length > 0) + args = ApplicationUtils.mergeArgs(args, guiArgs); + } } prepareArgs(args); @@ -451,6 +373,50 @@ public static void run(Class clazz, String... args) System.exit(code); } + /** + * Convenience method to run a scenario from code or automatically with gui when desktop application is detected. + * This method may also be used to predefine some default arguments. + * @param clazz class of the scenario to run + * @param args pass arguments from the main method + * @param defaultArgs predefined default arguments that will always be present + */ + public static void runWithDefaults(Class clazz, String[] args, String... defaultArgs) { + + if (ApplicationUtils.isRunFromDesktop() && args.length == 0) { + + if (defaultArgs.length > 0) { + String value = String.join(ARGS_DELIMITER, defaultArgs); + System.setProperty("MATSIM_GUI_ARGS", value); + } + + // args are empty when run from desktop and is not used + run(clazz, "gui"); + + } else { + // run if no other command is present + if (args.length > 0) { + // valid command is present + if (args[0].equals("run") || args[0].equals("prepare") || args[0].equals("analysis") || args[0].equals("gui") ){ + // If this is a run command, the default args can be applied + if (args[0].equals("run")) + args = ApplicationUtils.mergeArgs(args, defaultArgs); + + } else { + // Automatically add run command + String[] runArgs = ApplicationUtils.mergeArgs(new String[]{"run"}, defaultArgs); + args = ApplicationUtils.mergeArgs(runArgs, args); + } + + } else + // Automatically add run command + args = ApplicationUtils.mergeArgs(new String[]{"run"}, defaultArgs); + + log.info("Running {} with: {}", clazz.getSimpleName(), String.join(" ", args)); + + run(clazz, args); + } + } + /** * Calls an application class and forwards any exceptions. * @@ -512,7 +478,7 @@ public static Controler prepare(MATSimApplication app, Config config, String... config = tmp != null ? tmp : config; if (app.specs != null) { - applySpecs(config, app.specs); + ApplicationUtils.applyConfigUpdate(config, app.specs); } if (app.remainingArgs != null) { @@ -744,7 +710,7 @@ public Integer call() throws Exception { } /** - * Option to switch post processing behavour + * Option to switch post-processing behaviour */ public enum PostProcessOption { diff --git a/contribs/application/src/main/java/org/matsim/application/commands/RunScenario.java b/contribs/application/src/main/java/org/matsim/application/RunScenario.java similarity index 67% rename from contribs/application/src/main/java/org/matsim/application/commands/RunScenario.java rename to contribs/application/src/main/java/org/matsim/application/RunScenario.java index 3221069de95..460d5585ee5 100644 --- a/contribs/application/src/main/java/org/matsim/application/commands/RunScenario.java +++ b/contribs/application/src/main/java/org/matsim/application/RunScenario.java @@ -1,12 +1,11 @@ -package org.matsim.application.commands; +package org.matsim.application; -import org.matsim.application.MATSimApplication; import picocli.CommandLine; import java.util.concurrent.Callable; @CommandLine.Command(name = "run", description = "Run the scenario") -public class RunScenario implements Callable { +class RunScenario implements Callable { @CommandLine.ParentCommand private MATSimApplication app; diff --git a/contribs/application/src/main/java/org/matsim/application/commands/ShowGUI.java b/contribs/application/src/main/java/org/matsim/application/ShowGUI.java similarity index 65% rename from contribs/application/src/main/java/org/matsim/application/commands/ShowGUI.java rename to contribs/application/src/main/java/org/matsim/application/ShowGUI.java index 443f6a5cccb..e394bfd7b79 100644 --- a/contribs/application/src/main/java/org/matsim/application/commands/ShowGUI.java +++ b/contribs/application/src/main/java/org/matsim/application/ShowGUI.java @@ -1,14 +1,14 @@ -package org.matsim.application.commands; +package org.matsim.application; -import org.matsim.application.MATSimApplication; import org.matsim.run.gui.Gui; import picocli.CommandLine; +import java.io.File; import java.util.concurrent.Callable; import java.util.concurrent.Future; @CommandLine.Command(name = "gui", description = "Run the scenario through the MATSim GUI") -public class ShowGUI implements Callable { +class ShowGUI implements Callable { @CommandLine.ParentCommand private MATSimApplication parent; @@ -26,7 +26,17 @@ public Integer call() throws Exception { name = name.substring(MATSimApplication.COLOR.length(), name.length() - 4); } - Future f = Gui.show(name, parent.getClass()); + File configFile = null; + + // Try to load default config file + if (parent.getDefaultScenario() != null && new File(parent.getDefaultScenario()).exists()) + configFile = new File(parent.getDefaultScenario()); + + // override the default if present + if (parent.getConfigPath() != null && parent.getConfigPath().exists()) + configFile = parent.getConfigPath(); + + Future f = Gui.show(name, parent.getClass(), configFile); Gui gui = f.get(); diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java index 35f11ab09d6..bc656e79a2f 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java @@ -16,6 +16,7 @@ import org.locationtech.jts.geom.Point; import org.matsim.application.CommandSpec; import org.matsim.application.MATSimAppCommand; +import org.matsim.application.options.CsvOptions; import org.matsim.application.options.InputOptions; import org.matsim.application.options.OutputOptions; import org.matsim.application.options.ShpOptions; @@ -26,11 +27,12 @@ import tech.tablesaw.joining.DataFrameJoiner; import tech.tablesaw.selection.Selection; -import java.io.IOException; +import java.io.*; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.file.Files; import java.util.*; +import java.util.zip.GZIPInputStream; import static tech.tablesaw.aggregate.AggregateFunctions.count; @@ -93,7 +95,7 @@ public Integer call() throws Exception { Table persons = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(input.getPath("persons.csv"))) .columnTypesPartial(Map.of("person", ColumnType.TEXT)) .sample(false) - .separator(';').build()); + .separator(new CsvOptions().detectDelimiter(input.getPath("persons.csv"))).build()); int total = persons.rowCount(); @@ -134,8 +136,7 @@ public Integer call() throws Exception { Table trips = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(input.getPath("trips.csv"))) .columnTypesPartial(columnTypes) .sample(false) - .separator(';').build()); - + .separator(CsvOptions.detectDelimiter(input.getPath("trips.csv"))).build()); // Trip filter with start and end if (shp.isDefined() && filter == LocationFilter.trip_start_and_end) { 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/analysis/traffic/traveltime/SampleValidationRoutes.java b/contribs/application/src/main/java/org/matsim/application/analysis/traffic/traveltime/SampleValidationRoutes.java index 168bf28499e..0e6c0f2af59 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/traffic/traveltime/SampleValidationRoutes.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/traffic/traveltime/SampleValidationRoutes.java @@ -23,6 +23,7 @@ import org.matsim.application.options.InputOptions; import org.matsim.application.options.OutputOptions; import org.matsim.application.options.ShpOptions; +import org.matsim.application.prepare.network.SampleNetwork; import org.matsim.core.network.NetworkUtils; import org.matsim.core.router.costcalculators.OnlyTimeDependentTravelDisutility; import org.matsim.core.router.speedy.SpeedyALTFactory; @@ -85,23 +86,6 @@ public class SampleValidationRoutes implements MATSimAppCommand { @CommandLine.Option(names = "--mode", description = "Mode to validate", defaultValue = TransportMode.car) private String mode; - /** - * Random coord in the same direction as a link. - */ - static Coord rndCoord(SplittableRandom rnd, double dist, Link link) { - - Coord v = link.getFromNode().getCoord(); - Coord u = link.getToNode().getCoord(); - - var angle = Math.atan2(u.getY() - v.getY(), u.getX() - v.getX()); - - var sample = angle + rnd.nextDouble(-0.2, 0.2) * Math.PI * 2; - - var x = Math.cos(sample) * dist; - var y = Math.sin(sample) * dist; - - return CoordUtils.round(new Coord(v.getX() + x, v.getY() + y)); - } public static void main(String[] args) { new SampleValidationRoutes().execute(args); @@ -268,7 +252,7 @@ public boolean test(Link link) { continue; } - Coord dest = rndCoord(rnd, rnd.nextDouble(distRange.get(0), distRange.get(1)), link); + Coord dest = SampleNetwork.rndCoord(rnd, rnd.nextDouble(distRange.get(0), distRange.get(1)), link); Link to = NetworkUtils.getNearestLink(network, dest); if (!to.getAllowedModes().contains(mode) || exclude.test(to)) { diff --git a/contribs/application/src/main/java/org/matsim/application/options/CsvOptions.java b/contribs/application/src/main/java/org/matsim/application/options/CsvOptions.java index 64740d7346b..a022a6f5771 100644 --- a/contribs/application/src/main/java/org/matsim/application/options/CsvOptions.java +++ b/contribs/application/src/main/java/org/matsim/application/options/CsvOptions.java @@ -3,9 +3,11 @@ import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.lang.StringUtils; import org.matsim.core.utils.io.IOUtils; import picocli.CommandLine; +import java.io.BufferedReader; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -40,24 +42,49 @@ public CsvOptions(CSVFormat.Predefined csvFormat) { this.csvFormat = csvFormat; } - /** - * Constructor with all available options. - */ - public CsvOptions(CSVFormat.Predefined csvFormat, Character csvDelimiter, Charset csvCharset) { - this.csvFormat = csvFormat; - this.csvDelimiter = csvDelimiter; - this.csvCharset = csvCharset; - } + /** + * Constructor with all available options. + */ + public CsvOptions(CSVFormat.Predefined csvFormat, Character csvDelimiter, Charset csvCharset) { + this.csvFormat = csvFormat; + this.csvDelimiter = csvDelimiter; + this.csvCharset = csvCharset; + } + + /** + * Detects possibly used delimiter from the header of a csv or tsv file. + */ + public static Character detectDelimiter(String path) throws IOException { + try (BufferedReader reader = IOUtils.getBufferedReader(path)) { + String firstLine = reader.readLine(); + + int comma = StringUtils.countMatches(firstLine, ","); + int semicolon = StringUtils.countMatches(firstLine, ";"); + int tab = StringUtils.countMatches(firstLine, "\t"); + + if (comma == 0 && semicolon == 0 && tab == 0) { + throw new IllegalArgumentException("No delimiter found in the first line of the file."); + } - /** + // Comma is preferred as the more likely format + if (comma >= semicolon && comma >= tab) { + return ','; + } else if (tab >= semicolon) + return '\t'; + else + return ';'; + } + } + + /** * Get the CSV format defined by the options. */ public CSVFormat getFormat() { - CSVFormat format = this.csvFormat.getFormat().withFirstRecordAsHeader(); + CSVFormat.Builder format = this.csvFormat.getFormat().builder().setSkipHeaderRecord(true); if (csvDelimiter != null) - format = format.withDelimiter(csvDelimiter); + format = format.setDelimiter(csvDelimiter); - return format; + return format.build(); } /** @@ -71,7 +98,7 @@ public CSVParser createParser(Path path) throws IOException { * Creates a new csv writer. */ public CSVPrinter createPrinter(Path path) throws IOException { - return new CSVPrinter(IOUtils.getBufferedWriter(path.toUri().toURL(), csvCharset, false), getFormat()); + return new CSVPrinter(IOUtils.getBufferedWriter(path.toUri().toURL(), csvCharset, false), getFormat()); } } diff --git a/contribs/application/src/main/java/org/matsim/application/options/InputOptions.java b/contribs/application/src/main/java/org/matsim/application/options/InputOptions.java index bd7f268a248..eae4b3a7c21 100644 --- a/contribs/application/src/main/java/org/matsim/application/options/InputOptions.java +++ b/contribs/application/src/main/java/org/matsim/application/options/InputOptions.java @@ -113,6 +113,10 @@ public Network getNetwork() { return NetworkUtils.readNetwork(networkPath); } + public String getNetworkPath() { + return networkPath; + } + public Population getPopulation() { if (!spec.requirePopulation()) throw new IllegalArgumentException("Population can not be accessed unless, requirePopulation=true."); diff --git a/contribs/application/src/main/java/org/matsim/application/options/ShpOptions.java b/contribs/application/src/main/java/org/matsim/application/options/ShpOptions.java index a541548a7d9..ab40fd1f3c8 100644 --- a/contribs/application/src/main/java/org/matsim/application/options/ShpOptions.java +++ b/contribs/application/src/main/java/org/matsim/application/options/ShpOptions.java @@ -18,7 +18,7 @@ import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.geometry.transformations.IdentityTransformation; import org.matsim.core.utils.geometry.transformations.TransformationFactory; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.core.utils.io.IOUtils; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; @@ -161,7 +161,7 @@ public List readFeatures() { if (shpCharset != null) ds.setCharset(shpCharset); - return ShapeFileReader.getSimpleFeatures(ds); + return GeoFileReader.getSimpleFeatures(ds); } catch (IOException e) { throw new UncheckedIOException(e); } @@ -341,13 +341,27 @@ public final class Index { } /** - * Query the index for first feature including a certain point. + * Query the index for first feature including matching the coordinate and return specified attribute. * * @return null when no features was found that contains the point */ @Nullable @SuppressWarnings("unchecked") - public String query(Coord coord) { + public T query(Coord coord) { + SimpleFeature ft = queryFeature(coord); + if (ft != null) + return (T) ft.getAttribute(attr); + + return null; + // throw new NoSuchElementException(String.format("No matching entry found for x:%f y:%f %s", x, y, p)); + } + + /** + * Query the index and return the whole feature. + */ + @Nullable + @SuppressWarnings("unchecked") + public SimpleFeature queryFeature(Coord coord) { // Because we can not easily transform the feature geometry with MATSim we have to do it the other way around... Coordinate p = MGC.coord2Coordinate(ct.transform(coord)); @@ -355,16 +369,16 @@ public String query(Coord coord) { for (SimpleFeature ft : result) { Geometry geom = (Geometry) ft.getDefaultGeometry(); if (geom.contains(MGC.coordinate2Point(p))) - return (String) ft.getAttribute(attr); + return ft; } return null; - // throw new NoSuchElementException(String.format("No matching entry found for x:%f y:%f %s", x, y, p)); } /** * Checks whether a coordinate is contained in any of the features. */ + @SuppressWarnings("unchecked") public boolean contains(Coord coord) { Coordinate p = MGC.coord2Coordinate(ct.transform(coord)); 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/application/src/main/java/org/matsim/application/prepare/freight/optimization/DetermineAverageTruckLoad.java b/contribs/application/src/main/java/org/matsim/application/prepare/freight/optimization/DetermineAverageTruckLoad.java index 8318bef7292..b89303a23bb 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/freight/optimization/DetermineAverageTruckLoad.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/freight/optimization/DetermineAverageTruckLoad.java @@ -26,7 +26,7 @@ import org.matsim.core.utils.geometry.CoordUtils; import org.matsim.core.utils.geometry.CoordinateTransformation; import org.matsim.core.utils.geometry.transformations.TransformationFactory; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; import picocli.CommandLine; @@ -110,7 +110,7 @@ public Integer call() throws Exception { } // Read shape file // TODO this is acutally not needed. Just testing the functionality of reading shape file from URL. Delete afterwards!!! - List nutsFeatures = ShapeFileReader.getAllFeatures(URI.create(nutsPath).toURL()). + List nutsFeatures = GeoFileReader.getAllFeatures(URI.create(nutsPath).toURL()). stream().filter(f -> relevantNutsIds.contains(f.getAttribute("NUTS_ID").toString())). collect(Collectors.toList()); System.out.println("There are " + nutsFeatures.size() + " relevant NUTS regions"); diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/CleanNetwork.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/CleanNetwork.java index 878cfad8156..8b3e621ac22 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/CleanNetwork.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/CleanNetwork.java @@ -11,8 +11,8 @@ import java.util.Set; @CommandLine.Command( - name = "clean-network", - description = "Ensures that all links in the network are strongly connected." + name = "clean-network", + description = "Ensures that all links in the network are strongly connected." ) public class CleanNetwork implements MATSimAppCommand { @@ -22,7 +22,7 @@ public class CleanNetwork implements MATSimAppCommand { @CommandLine.Option(names = "--output", description = "Output path", required = true) private Path output; - @CommandLine.Option(names = "--modes", description = "List of modes to clean", defaultValue = TransportMode.car) + @CommandLine.Option(names = "--modes", description = "List of modes to clean", split = ",", defaultValue = TransportMode.car) private Set modes; @Override diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateNetworkFromSumo.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateNetworkFromSumo.java index b4a3521e48d..1a7272bf277 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateNetworkFromSumo.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateNetworkFromSumo.java @@ -74,7 +74,15 @@ public static void main(String[] args) { @Override public Integer call() throws Exception { - SumoNetworkConverter converter = SumoNetworkConverter.newInstance(input, output, Path.of(shp.getShapeFile()), crs.getInputCRS(), crs.getTargetCRS(), freeSpeedFactor); +// since ShpOptions.getShapeFile() no longer is a path but a string, we have to check if it is defined before creating SumoNetworkConverter to +// preserve the possibility to run the converter without a shp file, otherwise, when calling Path.of(shp.getShapeFile) a NullPointerException is caused -sme0324 + Path path = null; + + if (shp.isDefined()) { + path = Path.of(shp.getShapeFile()); + } + + SumoNetworkConverter converter = SumoNetworkConverter.newInstance(input, output, path, crs.getInputCRS(), crs.getTargetCRS(), freeSpeedFactor); Network network = NetworkUtils.createNetwork(); Lanes lanes = LanesUtils.createLanesContainer(); @@ -112,6 +120,8 @@ public Integer call() throws Exception { converter.writeGeometry(handler, output.toAbsolutePath().toString().replace(".xml", "-linkGeometries.csv").replace(".gz", "")); + converter.writeFeatures(handler, output.toAbsolutePath().toString().replace(".xml", "-ft.csv")); + return 0; } diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/SampleNetwork.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/SampleNetwork.java new file mode 100644 index 00000000000..82a7a278e32 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/SampleNetwork.java @@ -0,0 +1,329 @@ +package org.matsim.application.prepare.network; + +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.locationtech.jts.geom.*; +import org.locationtech.jts.io.WKTWriter; +import org.locationtech.jts.simplify.TopologyPreservingSimplifier; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.Node; +import org.matsim.api.core.v01.population.Person; +import org.matsim.application.CommandSpec; +import org.matsim.application.MATSimAppCommand; +import org.matsim.application.options.CrsOptions; +import org.matsim.application.options.InputOptions; +import org.matsim.application.options.OutputOptions; +import org.matsim.application.options.ShpOptions; +import org.matsim.core.config.groups.NetworkConfigGroup; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.network.algorithms.MultimodalNetworkCleaner; +import org.matsim.core.network.filter.NetworkFilterManager; +import org.matsim.core.router.DijkstraFactory; +import org.matsim.core.router.costcalculators.OnlyTimeDependentTravelDisutility; +import org.matsim.core.router.util.LeastCostPathCalculator; +import org.matsim.core.router.util.TravelTime; +import org.matsim.core.scenario.ProjectionUtils; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.geometry.geotools.MGC; +import org.matsim.vehicles.Vehicle; +import picocli.CommandLine; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.util.*; +import java.util.stream.Collectors; + +@CommandLine.Command( + name = "sample-network", + description = "Sample intersections, links and routes from network" +) +@CommandSpec(requireNetwork = true, produces = {"intersections.txt", "edges.txt", "routes.txt"}) +public class SampleNetwork implements MATSimAppCommand { + private static final Logger log = LogManager.getLogger(SampleNetwork.class); + + @CommandLine.Mixin + private InputOptions input = InputOptions.ofCommand(SampleNetwork.class); + + @CommandLine.Mixin + private OutputOptions output = OutputOptions.ofCommand(SampleNetwork.class); + + @CommandLine.Mixin + private ShpOptions shp; + + @CommandLine.Mixin + private CrsOptions crs; + + @CommandLine.Option(names = "--sample-size", description = "Number of samples to collect for each category.", defaultValue = "5000") + private int sample; + + @CommandLine.Option(names = "--filter", description = "Remove certain road types") + private String typeFilter; + + @CommandLine.Option(names = "--routes-size", description = "Number of routes to collect.", defaultValue = "5000") + private int routesSize; + + @CommandLine.Option(names = "--routes-dist", description = "Avg. routes distance.", defaultValue = "6000") + private int routesDist; + + public static void main(String[] args) { + new SampleNetwork().execute(args); + } + + /** + * Random coord in the same direction as a link. + */ + public static Coord rndCoord(SplittableRandom rnd, double dist, Link link) { + + Coord v = link.getFromNode().getCoord(); + Coord u = link.getToNode().getCoord(); + + var angle = Math.atan2(u.getY() - v.getY(), u.getX() - v.getX()); + + var sample = angle + rnd.nextDouble(-0.2, 0.2) * Math.PI * 2; + + var x = Math.cos(sample) * dist; + var y = Math.sin(sample) * dist; + + return CoordUtils.round(new Coord(v.getX() + x, v.getY() + y)); + } + + /** + * Skip certain nodes to improve class imbalance regarding the allowed speed. + */ + private static double skip(Node node, String key) { + + // all traffic lights are considered + if (key.equals("traffic_light")) + return 1; + + Optional first = node.getInLinks().values().stream().findFirst(); + if (first.isEmpty()) + return 0; + + Link link = first.get(); + + // very long or short links are skipped + if (link.getLength() > 500 || link.getLength() < 15) + return 0; + + double skip = 1; + if (NetworkUtils.getAllowedSpeed(link) == 13.89) + skip = 0.6; + else if (NetworkUtils.getAllowedSpeed(link) == 8.33) + skip = 0.3; + + // Increase samples with more than 1 lane + if (link.getNumberOfLanes() == 1) + skip *= 0.7; + + return skip; + } + + @Override + public Integer call() throws Exception { + + Network network = input.getNetwork(); + + Map> byType = network.getNodes().values().stream().collect(Collectors.groupingBy( + n -> (String) n.getAttributes().getAttribute("type"), Collectors.toList() + )); + + SplittableRandom rnd = new SplittableRandom(0); + + try (BufferedWriter intersections = Files.newBufferedWriter(output.getPath("intersections.txt"))) { + + for (Map.Entry> e : byType.entrySet()) { + + List list = e.getValue(); + + log.info("Sampling {} out of {} intersections for type {}", sample, list.size(), e.getKey()); + + for (int i = 0; i < sample && !list.isEmpty(); i++) { + + Node n = list.remove(rnd.nextInt(0, list.size())); + + // leave out certain links + if (rnd.nextDouble() > skip(n, e.getKey())) { + i--; + continue; + } + + intersections.write(n.getId().toString() + "\n"); + } + } + } + + Map> bySpeed = network.getLinks().values().stream() + .filter(l -> !"traffic_light".equals(l.getToNode().getAttributes().getAttribute("type"))) + .filter(l -> l.getLength() < 500 && l.getLength() > 50) + .collect(Collectors.groupingBy( + n -> (Double) n.getAttributes().getAttribute("allowed_speed"), Collectors.toList() + )); + + try (BufferedWriter links = Files.newBufferedWriter(output.getPath("edges.txt"))) { + + for (Map.Entry> e : bySpeed.entrySet()) { + + List list = e.getValue(); + + if (list.size() < 50) + continue; + + log.info("Sampling {} out of {} links for speed {}", sample / 10, list.size(), e.getKey()); + + // Use longest link segments + list.sort(Comparator.comparingDouble(l -> -l.getLength())); + + for (int i = 0; i < sample / 10 && i < list.size(); i++) { + Link link = list.get(i); + links.write(link.getId().toString() + "\n"); + } + } + } + + Network cityNetwork = createCityNetwork(network); + + RandomizedTravelTime tt = new RandomizedTravelTime(rnd); + + LeastCostPathCalculator router = createRandomizedRouter(network, tt); + + sampleCityRoutes(cityNetwork, router, tt, rnd); + + return 0; + } + + /** + * Samples routes from the network. + */ + private void sampleCityRoutes(Network network, LeastCostPathCalculator router, RandomizedTravelTime tt, SplittableRandom rnd) throws IOException { + + List links = new ArrayList<>(network.getLinks().values()); + + GeometryFactory f = new GeometryFactory(); + WKTWriter w = new WKTWriter(); + w.setPrecisionModel(new PrecisionModel(1)); + + try (CSVPrinter csv = new CSVPrinter(Files.newBufferedWriter(output.getPath("routes.txt")), CSVFormat.DEFAULT)) { + + csv.printRecord("fromEdge", "toEdge", "min_capacity", "travel_time", "geometry"); + + for (int i = 0; i < routesSize; i++) { + + Link link = links.get(rnd.nextInt(0, links.size())); + + Coord dest = rndCoord(rnd, routesDist, link); + + Link to = NetworkUtils.getNearestLink(network, dest); + + LeastCostPathCalculator.Path path = router.calcLeastCostPath(link.getFromNode(), to.getToNode(), 0, null, null); + + if (path.nodes.size() < 2) { + i--; + continue; + } + + double minCapacity = path.links.stream().mapToDouble(Link::getCapacity).min().orElse(-1); + + LineString lineString = f.createLineString(path.nodes.stream().map(n -> MGC.coord2Point(n.getCoord()).getCoordinate()).toArray(Coordinate[]::new)); + + Polygon polygon = (Polygon) lineString.buffer(100); + + Polygon simplified = (Polygon) TopologyPreservingSimplifier.simplify(polygon, 30); + + csv.print(link.getId()); + csv.print(path.links.get(path.links.size() - 1).getId()); + csv.print(minCapacity); + csv.print(path.travelTime); + csv.print(w.write(simplified)); + + csv.println(); + + // Reset randomness + tt.reset(); + } + + } + } + + /** + * Create network without highways. + */ + private Network createCityNetwork(Network network) { + + // no filtering needed + if (typeFilter == null && !shp.isDefined()) + return network; + + NetworkFilterManager filter = new NetworkFilterManager(network, new NetworkConfigGroup()); + if (typeFilter != null) + filter.addLinkFilter(l -> !NetworkUtils.getHighwayType(l).startsWith(typeFilter)); + + if (shp.isDefined()) { + + String crs = ProjectionUtils.getCRS(network); + if (this.crs.getInputCRS() != null) + crs = this.crs.getInputCRS(); + if (crs == null) { + throw new IllegalArgumentException("Input CRS could not be detected. Please specify with --input-crs [EPSG:xxx]"); + } + + ShpOptions.Index index = shp.createIndex(crs, "_"); + filter.addLinkFilter(l -> index.contains(l.getCoord())); + } + + Network net = filter.applyFilters(); + + MultimodalNetworkCleaner cleaner = new MultimodalNetworkCleaner(net); + cleaner.run(Set.of(TransportMode.car)); + + return net; + } + + /** + * Router with randomization. + */ + private LeastCostPathCalculator createRandomizedRouter(Network network, TravelTime tt) { + + OnlyTimeDependentTravelDisutility util = new OnlyTimeDependentTravelDisutility(tt); + return new DijkstraFactory(false).createPathCalculator(network, util, tt); + } + + private static final class RandomizedTravelTime implements TravelTime { + + private final Object2DoubleMap factors = new Object2DoubleOpenHashMap<>(); + + private final SplittableRandom rnd; + + RandomizedTravelTime(SplittableRandom rnd) { + this.rnd = rnd; + } + + void reset() { + factors.clear(); + } + + @Override + public double getLinkTravelTime(Link link, double time, Person person, Vehicle vehicle) { + String type = NetworkUtils.getHighwayType(link); + + double f = factors.computeIfAbsent(link, l -> rnd.nextDouble(0.5, 1.5)); + // Main roads are penalized + if (type.startsWith("primary") || type.startsWith("secondary")) + f = 1.5; + else if (type.startsWith("motorway")) + f = 2; + + double speed = link.getLength() / Math.max(link.getFreespeed(time), 8.3); + return speed * f; + } + } + +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java new file mode 100644 index 00000000000..48f6310fad0 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java @@ -0,0 +1,177 @@ +package org.matsim.application.prepare.network.params; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.application.CommandSpec; +import org.matsim.application.MATSimAppCommand; +import org.matsim.application.options.InputOptions; +import org.matsim.application.options.OutputOptions; +import org.matsim.application.prepare.network.params.NetworkParamsOpt.Feature; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.utils.io.IOUtils; +import picocli.CommandLine; + +import java.io.BufferedReader; +import java.util.Map; +import java.util.Set; + +@CommandLine.Command( + name = "apply-network-params", description = "Apply network parameters for capacity and speed." +) +@CommandSpec( + requireNetwork = true, + requires = "features.csv", + produces = "network.xml.gz" +) +public class ApplyNetworkParams implements MATSimAppCommand { + + private static final Logger log = LogManager.getLogger(ApplyNetworkParams.class); + + @CommandLine.Mixin + private final InputOptions input = InputOptions.ofCommand(ApplyNetworkParams.class); + @CommandLine.Mixin + private final OutputOptions output = OutputOptions.ofCommand(ApplyNetworkParams.class); + + @CommandLine.Parameters(arity = "1..*", description = "Type of parameters to apply. Available: ${COMPLETION-CANDIDATES}") + private Set params; + + @CommandLine.Option(names = "--input-params", description = "Path to parameter json") + private String inputParams; + + @CommandLine.Option(names = "--model", description = "Reference to the network model class", required = true) + private Class modelClazz; + + @CommandLine.Option(names = "--factor-bounds", split = ",", description = "Speed factor limits (lower,upper bound)", defaultValue = NetworkParamsOpt.DEFAULT_FACTOR_BOUNDS) + private double[] speedFactorBounds; + + private NetworkModel model; + private NetworkParams paramsOpt; + + private int warn = 0; + + public static void main(String[] args) { + new ApplyNetworkParams().execute(args); + } + + /** + * Theoretical capacity. + */ + private static double capacityEstimate(double v) { + + // headway + double tT = 1.2; + + // car length + double lL = 7.0; + + double Qc = v / (v * tT + lL); + + return 3600 * Qc; + } + + + @Override + public Integer call() throws Exception { + + model = NetworkParamsOpt.load(modelClazz); + + Network network = input.getNetwork(); + ObjectMapper mapper = new ObjectMapper(); + mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); + + if (inputParams != null) { + try (BufferedReader in = IOUtils.getBufferedReader(inputParams)) { + paramsOpt = mapper.readValue(in, NetworkParams.class); + } + } + + Map, Feature> features = NetworkParamsOpt.readFeatures(input.getPath("features.csv"), network.getLinks().size()); + + for (Link link : network.getLinks().values()) { + Feature ft = features.get(link.getId()); + applyChanges(link, ft.junctionType(), ft.features()); + } + + log.warn("Observed {} warnings out of {} links", warn, network.getLinks().size()); + + NetworkUtils.writeNetwork(network, output.getPath("network.xml.gz").toString()); + + return 0; + } + + /** + * Apply speed and capacity models and apply changes. + */ + private void applyChanges(Link link, String junctionType, Object2DoubleMap features) { + + String type = NetworkUtils.getHighwayType(link); + + boolean modified = false; + + if (params.contains(NetworkAttribute.capacity)) { + + FeatureRegressor capacity = model.capacity(junctionType); + + double perLane = capacity.predict(features); + + double cap = capacityEstimate(features.getDouble("speed")); + + // Minimum thresholds + double threshold = switch (junctionType) { + // traffic light can reduce capacity at least to 50% (with equal green split) + case "traffic_light" -> 0.4; + case "right_before_left" -> 0.6; + // Motorways are kept at their max theoretical capacity + case "priority" -> type.startsWith("motorway") ? 1 : 0.8; + default -> throw new IllegalArgumentException("Unknown type: " + junctionType); + }; + + if (perLane < cap * threshold) { + log.warn("Increasing capacity per lane on {} ({}, {}) from {} to {}", link.getId(), type, junctionType, perLane, cap * threshold); + perLane = cap * threshold; + modified = true; + } + + link.setCapacity(link.getNumberOfLanes() * perLane); + } + + + if (params.contains(NetworkAttribute.freespeed)) { + + double speedFactor = 1.0; + FeatureRegressor speedModel = model.speedFactor(junctionType); + + speedFactor = paramsOpt != null ? + speedModel.predict(features, paramsOpt.getParams(junctionType)) : + speedModel.predict(features); + + if (speedFactor > speedFactorBounds[1]) { + log.warn("Reducing speed factor on {} from {} to {}", link.getId(), speedFactor, speedFactorBounds[1]); + speedFactor = speedFactorBounds[1]; + modified = true; + } + + // Threshold for very low speed factors + if (speedFactor < speedFactorBounds[0]) { + log.warn("Increasing speed factor on {} from {} to {}", link, speedFactor, speedFactorBounds[0]); + speedFactor = speedFactorBounds[0]; + modified = true; + } + + link.setFreespeed((double) link.getAttributes().getAttribute("allowed_speed") * speedFactor); + link.getAttributes().putAttribute("speed_factor", speedFactor); + } + + if (modified) + warn++; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java new file mode 100644 index 00000000000..014d2615549 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java @@ -0,0 +1,247 @@ +package org.matsim.application.prepare.network.params; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.io.FilenameUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.application.CommandSpec; +import org.matsim.application.MATSimAppCommand; +import org.matsim.application.analysis.traffic.traveltime.SampleValidationRoutes; +import org.matsim.application.options.InputOptions; +import org.matsim.application.options.OutputOptions; +import org.matsim.contrib.osm.networkReader.LinkProperties; +import org.matsim.core.network.NetworkUtils; +import picocli.CommandLine; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.matsim.application.prepare.network.params.NetworkParamsOpt.*; + +@CommandLine.Command( + name = "eval-network-params", description = "Evaluate network params" +) +@CommandSpec( + requireNetwork = true, + requires = "features.csv", + produces = {"eval_speed_factors.csv", "eval.csv"} +) +public class EvalFreespeedParams implements MATSimAppCommand { + + private static final Logger log = LogManager.getLogger(EvalFreespeedParams.class); + + @CommandLine.Mixin + private InputOptions input = InputOptions.ofCommand(EvalFreespeedParams.class); + + @CommandLine.Mixin + private OutputOptions output = OutputOptions.ofCommand(EvalFreespeedParams.class); + + @CommandLine.Parameters(arity = "1..*", description = "Input validation files loaded from APIs") + private List validationFiles; + + @CommandLine.Option(names = "--model", description = "Reference to the network model class", required = true) + private Class modelClazz; + + @CommandLine.Option(names = "--params", description = "Apply params to model") + private Path params; + + @CommandLine.Option(names = "--params-name", description = "Use specified name instead of filename") + private String paramsName; + + @CommandLine.Option(names = "--ref-hours", description = "Reference hours", defaultValue = "3,21", split = ",") + private List refHours; + + @CommandLine.Option(names = "--factor-bounds", split = ",", description = "Speed factor limits (lower,upper bound)", defaultValue = NetworkParamsOpt.DEFAULT_FACTOR_BOUNDS) + private double[] speedFactorBounds; + + @CommandLine.Option(names = "--eval-factors", description = "Eval freespeed factors", defaultValue = "false") + private boolean evalFactors; + + @CommandLine.Option(names = "--eval-detailed", description = "Write detailed csv for each request.") + private boolean evalDetailed; + + private Network network; + private NetworkModel model; + private Object2DoubleMap validationSet; + private Map, Feature> features; + + public static void main(String[] args) { + new EvalFreespeedParams().execute(args); + } + + static Result applyAndEvaluateParams( + Network network, NetworkModel model, Object2DoubleMap validationSet, Map, Feature> features, + double[] speedFactorBounds, NetworkParams request, String save) throws IOException { + + Map, double[]> attributes = new HashMap<>(); + + if (request != null) { + for (Link link : network.getLinks().values()) { + + double allowedSpeed = NetworkUtils.getAllowedSpeed(link); + + if (request.f <= 0) { + + Feature ft = features.get(link.getId()); + + if (ft == null || ft.junctionType().equals("dead_end")) { +// log.warn("Unknown link {}: {}", link.getId(), ft); + link.setFreespeed(allowedSpeed); + continue; + } + + FeatureRegressor speedModel = model.speedFactor(ft.junctionType()); + + if (speedModel == null) { + link.setFreespeed(allowedSpeed); + continue; + } + + double speedFactor; + + if (request.hasParams()) { + double[] p = request.getParams(ft.junctionType()); + speedFactor = speedModel.predict(ft.features(), p); + } else + speedFactor = speedModel.predict(ft.features()); + + // apply lower and upper bound + speedFactor = Math.max(speedFactorBounds[0], speedFactor); + speedFactor = Math.min(speedFactorBounds[1], speedFactor); + + attributes.put(link.getId(), speedModel.getData(ft.features())); + + link.setFreespeed(allowedSpeed * speedFactor); + link.getAttributes().putAttribute("speed_factor", speedFactor); + + } else + // Old MATSim freespeed logic + link.setFreespeed(LinkProperties.calculateSpeedIfSpeedTag(allowedSpeed, request.f)); + } + } + + Result result = evaluate(network, validationSet, features, attributes, save); + + log.info("{}, rmse: {}, mae: {}", request, result.rmse(), result.mae()); + + return result; + } + + @Override + public Integer call() throws Exception { + + model = load(modelClazz); + network = input.getNetwork(); + ObjectMapper mapper = new ObjectMapper(); + mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); + + validationSet = readValidation(validationFiles, refHours); + features = readFeatures(input.getPath("features.csv"), network.getLinks().size()); + + CSVPrinter csv; + Path out = output.getPath("eval.csv"); + if (Files.exists(out)) { + csv = new CSVPrinter(Files.newBufferedWriter(out, StandardOpenOption.APPEND), CSVFormat.DEFAULT); + } else { + csv = new CSVPrinter(Files.newBufferedWriter(out, StandardOpenOption.CREATE_NEW), CSVFormat.DEFAULT); + csv.printRecord("network", "package", "name", "params", "mae", "rmse"); + csv.flush(); + } + + + if (evalDetailed) + Files.createDirectories(Path.of("freespeed_detailed")); + + + log.info("Model score:"); + Result r = applyAndEvaluateParams(network, model, validationSet, features, speedFactorBounds, new NetworkParams(0), save(getParamsName(null))); + writeResult(csv, null, r); + + if (params != null) { + log.info("Model with parameter score:"); + r = applyAndEvaluateParams(network, model, validationSet, features, speedFactorBounds, + mapper.readValue(params.toFile(), NetworkParams.class), save(getParamsName(params))); + writeResult(csv, params, r); + } + + csv.close(); + + if (evalFactors) { + log.info("Evaluating free-speed factors"); + evalSpeedFactors(output.getPath(), save("best_urban_factor")); + } + + return 0; + } + + private String save(String postfix) { + if (!evalDetailed) + return null; + + Path base = Path.of("freespeed_detailed"); + return base.resolve(FilenameUtils.getBaseName(input.getNetworkPath()) + "_" + modelClazz.getSimpleName() + "_" + postfix).toString(); + } + + private void evalSpeedFactors(Path eval, String save) throws IOException { + + CSVPrinter csv; + if (Files.exists(eval)) { + csv = new CSVPrinter(Files.newBufferedWriter(eval, StandardOpenOption.APPEND), CSVFormat.DEFAULT); + } else { + csv = new CSVPrinter(Files.newBufferedWriter(eval, StandardOpenOption.CREATE_NEW), CSVFormat.DEFAULT); + csv.printRecord("network", "urban_speed_factor", "mae", "rmse"); + csv.flush(); + } + + String networkName = FilenameUtils.getName(input.getNetworkPath()); + + NetworkParams best = null; + double bestScore = Double.POSITIVE_INFINITY; + double[] bounds = {0, 1}; + + for (int i = 25; i <= 100; i++) { + NetworkParams req = new NetworkParams(i / 100d); + Result res = applyAndEvaluateParams(network, model, validationSet, features, bounds, req, null); + csv.printRecord(networkName, i / 100d, res.mae(), res.rmse()); + if (best == null || res.mae() < bestScore) { + best = req; + bestScore = res.mae(); + } + } + + log.info("Best factor {} with mae {}", best.f, bestScore); + + if (save != null) { + applyAndEvaluateParams(network, model, validationSet, features, bounds, best, save); + } + + csv.close(); + } + + private String getParamsName(Path params) { + String pName = paramsName != null ? paramsName : (params != null ? params.getFileName().toString() : "null"); + return params != null ? pName : ("non-optimized_" + pName); + } + + private void writeResult(CSVPrinter csv, Path params, Result r) throws IOException { + String network = FilenameUtils.getBaseName(input.getNetworkPath()); + + csv.printRecord(network, modelClazz.getPackageName(), modelClazz.getSimpleName(), getParamsName(params), r.mae(), r.rmse()); + } + +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FeatureRegressor.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FeatureRegressor.java new file mode 100644 index 00000000000..051135e89b6 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FeatureRegressor.java @@ -0,0 +1,31 @@ +package org.matsim.application.prepare.network.params; + +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; + +/** + * Predictor interface for regression. + */ +public interface FeatureRegressor { + + + /** + * Predict value from given features. + */ + double predict(Object2DoubleMap ft); + + /** + * Predict values with adjusted model params. + */ + default double predict(Object2DoubleMap ft, double[] params) { + throw new UnsupportedOperationException("Not implemented"); + } + + + /** + * Return data that is used for internal prediction function (normalization already applied). + */ + default double[] getData(Object2DoubleMap ft) { + throw new UnsupportedOperationException("Not implemented"); + } + +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java new file mode 100644 index 00000000000..387824839f4 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java @@ -0,0 +1,158 @@ +package org.matsim.application.prepare.network.params; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; +import org.apache.hc.core5.http.*; +import org.apache.hc.core5.http.impl.bootstrap.HttpServer; +import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap; +import org.apache.hc.core5.http.io.HttpRequestHandler; +import org.apache.hc.core5.http.io.entity.HttpEntities; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.util.TimeValue; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.application.CommandSpec; +import org.matsim.application.MATSimAppCommand; +import org.matsim.application.analysis.traffic.traveltime.SampleValidationRoutes; +import org.matsim.application.options.InputOptions; +import org.matsim.application.prepare.network.params.NetworkParamsOpt.Feature; +import org.matsim.application.prepare.network.params.NetworkParamsOpt.Result; +import picocli.CommandLine; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** + * This class runs a server that receives model parameters for free speed. + * The corresponding optimizer is part of `matsim-python-tools` package. + * See this code. + * More about the method can be found in the paper "Road network free flow speed estimation using microscopic simulation and point-to-point travel times"; ABMTRANS 2024. + */ +@CommandLine.Command( + name = "freespeed-opt-server", + description = "Start server for freespeed optimization." +) +@CommandSpec( + requireNetwork = true, + requires = "features.csv" +) +public class FreespeedOptServer implements MATSimAppCommand { + + private static final Logger log = LogManager.getLogger(FreespeedOptServer.class); + + @CommandLine.Mixin + private InputOptions input = InputOptions.ofCommand(FreespeedOptServer.class); + + @CommandLine.Option(names = "--model", description = "Reference to the network model class", required = true) + private Class modelClazz; + + @CommandLine.Parameters(arity = "1..*", description = "Input validation files loaded from APIs") + private List validationFiles; + + @CommandLine.Option(names = "--factor-bounds", split = ",", description = "Speed factor limits (lower,upper bound)", defaultValue = NetworkParamsOpt.DEFAULT_FACTOR_BOUNDS) + private double[] speedFactorBounds; + + @CommandLine.Option(names = "--ref-hours", description = "Reference hours", defaultValue = "3,21", split = ",") + private List refHours; + + @CommandLine.Option(names = "--port", description = "Port for the server", defaultValue = "9090") + private int port; + + private Network network; + private NetworkModel model; + private Object2DoubleMap validationSet; + private Map, Feature> features; + + private ObjectMapper mapper; + + /** + * Original speeds. + */ + private Object2DoubleMap> speeds = new Object2DoubleOpenHashMap<>(); + + public static void main(String[] args) { + new FreespeedOptServer().execute(args); + } + + @Override + public Integer call() throws Exception { + + try { + model = modelClazz.getDeclaredConstructor().newInstance(); + } catch (ReflectiveOperationException e) { + log.error("Could not instantiate the network model", e); + return 2; + } + + network = input.getNetwork(); + mapper = new ObjectMapper(); + mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); + + for (Link link : network.getLinks().values()) { + speeds.put(link.getId(), link.getFreespeed()); + } + + validationSet = NetworkParamsOpt.readValidation(validationFiles, refHours); + features = NetworkParamsOpt.readFeatures(input.getPath("features.csv"), network.getLinks().size()); + + log.info("Initial score:"); + applyAndEvaluateParams(null, "init"); + + Backend backend = new Backend(); + try (HttpServer server = ServerBootstrap.bootstrap() + .setListenerPort(port) + .setExceptionListener(backend) + .register("/", backend) + .create()) { + + server.start(); + + log.info("Server running on {}", port); + + server.awaitTermination(TimeValue.MAX_VALUE); + } + + return 0; + } + + private Result applyAndEvaluateParams(NetworkParams request, String save) throws IOException { + return EvalFreespeedParams.applyAndEvaluateParams(network, model, validationSet, features, speedFactorBounds, + request, save); + } + + private final class Backend implements HttpRequestHandler, ExceptionListener { + + @Override + public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws IOException { + + NetworkParams req = mapper.readValue(request.getEntity().getContent(), NetworkParams.class); + + Result stats = applyAndEvaluateParams(req, null); + + response.setCode(200); + + String result = mapper.writeValueAsString(stats); + response.setEntity(HttpEntities.create(result, ContentType.APPLICATION_JSON)); + } + + @Override + public void onError(Exception ex) { + log.error("Error during request", ex); + } + + @Override + public void onError(HttpConnection connection, Exception ex) { + log.error("Error during request {}", connection, ex); + } + } + +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkAttribute.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkAttribute.java new file mode 100644 index 00000000000..6ae14c9d1f7 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkAttribute.java @@ -0,0 +1,9 @@ +package org.matsim.application.prepare.network.params; + +/** + * Enum of network parameters. + */ +public enum NetworkAttribute { + freespeed, + capacity +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkModel.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkModel.java new file mode 100644 index 00000000000..f98bb9bd41e --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkModel.java @@ -0,0 +1,22 @@ +package org.matsim.application.prepare.network.params; + +/** + * A model for estimating network parameters. + */ +public interface NetworkModel { + + /** + * Flow Capacity (per lane) + */ + default FeatureRegressor capacity(String junctionType) { + return null; + } + + /** + * Speed factor (relative to free flow speed). + */ + default FeatureRegressor speedFactor(String junctionType) { + return null; + } + +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParams.java new file mode 100644 index 00000000000..e5b5c9d60d3 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParams.java @@ -0,0 +1,53 @@ +package org.matsim.application.prepare.network.params; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Object containing parameters for a model. Can be used to serialize and deserialize parameters. + */ +final class NetworkParams { + + double f; + + @JsonIgnore + Map params = new HashMap<>(); + + /** + * Used by jackson + */ + public NetworkParams() { + } + + public NetworkParams(double f) { + this.f = f; + } + + @JsonAnyGetter + public double[] getParams(String type) { + return params.get(type); + } + + @JsonAnySetter + public void setParams(String type, double[] params) { + this.params.put(type, params); + } + + public boolean hasParams() { + return !params.isEmpty(); + } + + @Override + public String toString() { + if (f == 0) + return "Request{" + params.entrySet().stream() + .map(e -> e.getKey() + "=" + e.getValue().length).collect(Collectors.joining(",")) + '}'; + + return "Request{f=" + f + "}"; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java new file mode 100644 index 00000000000..2c69e7c6498 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java @@ -0,0 +1,182 @@ +package org.matsim.application.prepare.network.params; + +import it.unimi.dsi.fastutil.doubles.DoubleList; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.csv.CSVRecord; +import org.apache.commons.math3.stat.descriptive.SummaryStatistics; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdMap; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.Node; +import org.matsim.application.analysis.traffic.traveltime.SampleValidationRoutes; +import org.matsim.core.router.DijkstraFactory; +import org.matsim.core.router.costcalculators.OnlyTimeDependentTravelDisutility; +import org.matsim.core.router.util.LeastCostPathCalculator; +import org.matsim.core.trafficmonitoring.FreeSpeedTravelTime; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.io.IOUtils; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +/** + * Private helper class with utility functions. + */ +class NetworkParamsOpt { + + /** + * Factor limits. Deviation of 3% above max is allowed. + */ + static final String DEFAULT_FACTOR_BOUNDS = "0.25,1.03"; + + private NetworkParamsOpt() { + } + + static NetworkModel load(Class modelClazz) { + try { + return modelClazz.getDeclaredConstructor().newInstance(); + } catch (ReflectiveOperationException e) { + throw new IllegalArgumentException("Could not instantiate the network model", e); + } + } + + /** + * Read network edge features from csv. + */ + static Map, Feature> readFeatures(String input, int expectedLinks) throws IOException { + + Map, Feature> features = new IdMap<>(Link.class, expectedLinks); + + try (CSVParser reader = new CSVParser(IOUtils.getBufferedReader(input), + CSVFormat.DEFAULT.builder().setHeader().setSkipHeaderRecord(true).build())) { + + List header = reader.getHeaderNames(); + + for (CSVRecord row : reader) { + + Id id = Id.createLinkId(row.get("linkId")); + + Object2DoubleOpenHashMap ft = new Object2DoubleOpenHashMap<>(); + ft.defaultReturnValue(Double.NaN); + + for (String column : header) { + String v = row.get(column); + try { + ft.put(column, Double.parseDouble(v)); + } catch (NumberFormatException e) { + // every not equal to True will be false + ft.put(column, Boolean.parseBoolean(v) ? 1 : 0); + } + } + + features.put(id, new Feature(row.get("junction_type"), ft)); + } + } + + return features; + } + + /** + * Read validation files and calc target speed. + */ + static Object2DoubleMap readValidation(List validationFiles, List refHours) throws IOException { + + // entry to hour and list of speeds + Map> entries = SampleValidationRoutes.readValidation(validationFiles); + + Object2DoubleMap result = new Object2DoubleOpenHashMap<>(); + + // Target values + for (Map.Entry> e : entries.entrySet()) { + + Int2ObjectMap perHour = e.getValue(); + + double avg = refHours.stream().map(h -> perHour.get((int) h).doubleStream()) + .flatMapToDouble(Function.identity()).average().orElseThrow(); + + + result.put(e.getKey(), avg); + } + + return result; + } + + static Result evaluate(Network network, Object2DoubleMap validationSet, Map, Feature> features, Map, double[]> attributes, String save) throws IOException { + FreeSpeedTravelTime tt = new FreeSpeedTravelTime(); + OnlyTimeDependentTravelDisutility util = new OnlyTimeDependentTravelDisutility(tt); + LeastCostPathCalculator router = new DijkstraFactory(false).createPathCalculator(network, util, tt); + + SummaryStatistics rmse = new SummaryStatistics(); + SummaryStatistics mse = new SummaryStatistics(); + + CSVPrinter csv = save != null ? new CSVPrinter(Files.newBufferedWriter(Path.of(save + "-eval.csv")), CSVFormat.DEFAULT) : null; + + if (csv != null) + csv.printRecord("from_node", "to_node", "beeline_dist", "sim_speed", "ref_speed"); + + Map> data = new HashMap<>(); + + for (Object2DoubleMap.Entry e : validationSet.object2DoubleEntrySet()) { + + SampleValidationRoutes.FromToNodes r = e.getKey(); + + Node fromNode = network.getNodes().get(r.fromNode()); + Node toNode = network.getNodes().get(r.toNode()); + LeastCostPathCalculator.Path path = router.calcLeastCostPath(fromNode, toNode, 0, null, null); + + // iterate over the path, calc better correction + double distance = path.links.stream().mapToDouble(Link::getLength).sum(); + double speed = distance / path.travelTime; + + double correction = speed / e.getDoubleValue(); + + for (Link link : path.links) { + + if (!attributes.containsKey(link.getId())) + continue; + + Feature ft = features.get(link.getId()); + double[] input = attributes.get(link.getId()); + double speedFactor = (double) link.getAttributes().getAttribute("speed_factor"); + + data.computeIfAbsent(ft.junctionType(), (k) -> new ArrayList<>()) + .add(new Data(input, speedFactor, speedFactor / correction)); + } + + + rmse.addValue(Math.pow(e.getDoubleValue() - speed, 2)); + mse.addValue(Math.abs((e.getDoubleValue() - speed) * 3.6)); + + if (csv != null) + csv.printRecord(r.fromNode(), r.toNode(), (int) CoordUtils.calcEuclideanDistance(fromNode.getCoord(), toNode.getCoord()), + speed, e.getDoubleValue()); + } + + if (csv != null) + csv.close(); + + return new Result(rmse.getMean(), mse.getMean(), data); + } + + record Feature(String junctionType, Object2DoubleMap features) { + } + + record Result(double rmse, double mae, Map> data) { + } + + record Data(double[] x, double yPred, double yTrue) { + } + +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/DecisionTreeParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/DecisionTreeParams.java new file mode 100644 index 00000000000..4bb84fa6577 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/DecisionTreeParams.java @@ -0,0 +1,121 @@ +package org.matsim.application.prepare.network.params.ref; + +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import org.matsim.application.prepare.network.params.FeatureRegressor; +import org.matsim.application.prepare.network.params.NetworkModel; + +/** + * Reference model with a manually defined decision tree using priority, road type and speed. + */ +public final class DecisionTreeParams implements NetworkModel { + + public static final double[] DEFAULT_PARAMS = { + 0.9, 0.8, 0.9, 0.8, 0.7, 0.7, 0.7, 0.7, + 0.9, 0.8, 0.9, 0.8, 0.7, 0.7, 0.7, 0.7, + 0.9, 0.8, 0.9, 0.8, 0.7, 0.7, 0.7, 0.7 + }; + + private static final FeatureRegressor INSTANCE = new Model(); + + @Override + public FeatureRegressor speedFactor(String junctionType) { + return INSTANCE; + } + + private static final class Model implements FeatureRegressor { + + @Override + public double predict(Object2DoubleMap ft) { + return predict(ft, DEFAULT_PARAMS); + } + + @Override + public double predict(Object2DoubleMap ft, double[] params) { + double[] inputs = getData(ft); + if (inputs[1] == 1) + if (inputs[6] == 1) + if (inputs[7] >= 27.5) + return params[0]; + else + return params[1]; + else if (inputs[5] == 1) + if (inputs[7] >= 22) + return params[2]; + else + return params[3]; + else if (inputs[4] == 1) + if (inputs[7] <= 10) + return params[4]; + else + return params[5]; + else { + if (inputs[7] <= 10) + return params[6]; + else + return params[7]; + } + + else if (inputs[2] == 1) + if (inputs[6] == 1) + if (inputs[7] >= 27.5) + return params[8]; + else + return params[9]; + else if (inputs[5] == 1) + if (inputs[7] >= 22) + return params[10]; + else + return params[11]; + else if (inputs[4] == 1) + if (inputs[7] <= 10) + return params[12]; + else + return params[13]; + else { + if (inputs[7] <= 10) + return params[14]; + else + return params[15]; + } + + else { + if (inputs[6] == 1) + if (inputs[7] >= 27.5) + return params[16]; + else + return params[17]; + else if (inputs[5] == 1) + if (inputs[7] >= 22) + return params[18]; + else + return params[19]; + else if (inputs[4] == 1) + if (inputs[7] <= 10) + return params[20]; + else + return params[21]; + else { + if (inputs[7] <= 10) + return params[22]; + else + return params[23]; + } + } + } + + @Override + public double[] getData(Object2DoubleMap ft) { + return new double[]{ + ft.getDouble("length"), + ft.getDouble("priority_lower"), + ft.getDouble("priority_equal"), + ft.getDouble("priority_higher"), + ft.getDouble("is_secondary_or_higher"), + ft.getDouble("is_primary_or_higher"), + ft.getDouble("is_motorway"), + ft.getDouble("speed") + }; + } + } + +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams.java new file mode 100644 index 00000000000..ffe7250b2f4 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams.java @@ -0,0 +1,30 @@ +package org.matsim.application.prepare.network.params.ref; + +import org.matsim.application.prepare.network.params.FeatureRegressor; +import org.matsim.application.prepare.network.params.NetworkModel; + +/** + * Model trained on three region types in germany (metropole, city, rural). + * It should work especially well on urban areas. For use on rural areas, additional fine-tuning should be considered. + */ +public final class GermanyNetworkParams implements NetworkModel { + @Override + public FeatureRegressor capacity(String junctionType) { + return switch (junctionType) { + case "traffic_light" -> GermanyNetworkParams_capacity_traffic_light.INSTANCE; + case "right_before_left" -> GermanyNetworkParams_capacity_right_before_left.INSTANCE; + case "priority" -> GermanyNetworkParams_capacity_priority.INSTANCE; + default -> throw new IllegalArgumentException("Unknown type: " + junctionType); + }; + } + + @Override + public FeatureRegressor speedFactor(String junctionType) { + return switch (junctionType) { + case "traffic_light" -> GermanyNetworkParams_speedRelative_traffic_light.INSTANCE; + case "right_before_left" -> GermanyNetworkParams_speedRelative_right_before_left.INSTANCE; + case "priority" -> GermanyNetworkParams_speedRelative_priority.INSTANCE; + default -> throw new IllegalArgumentException("Unknown type: " + junctionType); + }; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_dead_end.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_dead_end.java new file mode 100644 index 00000000000..f79c318063b --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_dead_end.java @@ -0,0 +1,911 @@ +package org.matsim.application.prepare.network.params.ref; +import org.matsim.application.prepare.network.params.FeatureRegressor; +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; + +/** +* Generated model, do not modify. +*/ +final class GermanyNetworkParams_capacity_dead_end implements FeatureRegressor { + + public static GermanyNetworkParams_capacity_dead_end INSTANCE = new GermanyNetworkParams_capacity_dead_end(); + public static final double[] DEFAULT_PARAMS = {859.6049, 1368.6547, 317.08328, 602.73334, 1051.5116, 1365.0673, 479.5267, 1510.9359, 1261.82, 586.93774, 1752.8143, 345.83023, 251.44379, 196.05144, -100.92311, 556.4511, 248.56212, 8.751958, -112.63192, 353.46375, -499.09198, 67.84669, 238.25359, 69.855865, -147.35197, -24.82771, -398.5832, -312.16702, 645.81635, -429.90787, -56.959373, 73.37216, -8.621415, -20.72194, -5.8856874, -45.02695, 673.52795, 73.94616, -51.44936, 27.939749, -1045.293, 100.6221, 41.877926, 176.6136, 102.3786, -0.9688834, -220.64973, 137.63858, 215.92377, 41.44684, -20.3626, 16.380981, -151.44092, 52.8146, 10.459056, -165.38365, 34.63168, 32.307022, 218.85617, -109.07436, 67.68019, 6.774578, 178.27382, -206.08951, -1.2301626, 391.88242, -192.48239, 76.81782, -80.081535, -117.16598, 35.795372, 11.609657, -67.645164, -4.0473456, 189.128, -27.950788, 1.5682833, -23.019985, 382.52103, -4.099745, 68.12114, -223.34529, 273.18823, -89.40101, -5.440557, -10.679427, 109.98401, -64.30533, 71.05594, 27.412102, 4.8957453, 4.3622723, -190.4019, 233.06438, -11.0441675, -344.44733, 147.786, -23.268576, -33.001354, -1.6072537, -189.9128, -6.27801, -1.5817443, 91.38268, -136.90344, 66.1445, 155.11888, -52.789665, 12.548233, -99.26018, -10.74564, 7.0323977, 30.524338, -34.451485, -76.895966, 25.581684, -2.531495, 16.72898, 29.978521, -14.7835455, -68.298965, -2.481075, 15.709786, 101.65081, -137.88113, 3.3836243, 2.924429, -12.824084, -1.1771411, 21.445478, 31.226662, -12.21468, 11.967453, 5.482041, 50.30282, -0.40552256, -25.395111, -51.44317, -0.99815965, 9.2745495, -6.7587147, -23.885403, 3.0521197, -16.76911, 78.22408, 34.127068, -3.9190707, -75.568504, 8.654165, -3.9965763, -0.9473669, -9.223031, -3.693175, 9.046608, -67.85387, 2.1328363, 8.552537, 63.788208, 13.773914, -23.446692, -0.35650137, -4.8897696, 12.350961, -36.01829, -3.3446863, 13.035452, 2.4459727, -1.5044533, 25.509474, -0.022190453, -9.799512, 12.084186, 0.5939214, -38.01811, -8.539415, 25.965952, -14.307394, 6.077125, 0.27664867, 3.100341, -21.760082, 3.2573829, 1.4723984, -4.4738817, 9.860579, -11.05045, -0.23873898, -17.215534, -1.7263151, 1.2006466, -1.0414621, 3.6885643, -2.7444, 0.22894292, -48.507504, 17.920248, 0.692537, 4.6048656, -4.2964005, -0.4720382, 21.348267, 9.8496065, -2.6010177, 10.099594, -12.914126, 47.707207, -13.917312, 0.0, -0.051987253, 12.860103, 2.255951, -5.9641266, 21.498459, 4.267856, -19.037823, 2.985492, -0.44421604, 2.0518365, 1.7539244, 0.74282753, 7.382213, -5.6273985, -2.0897858, -0.048497323, -4.767571}; + + @Override + public double predict(Object2DoubleMap ft) { + return predict(ft, DEFAULT_PARAMS); + } + + @Override + public double[] getData(Object2DoubleMap ft) { + double[] data = new double[14]; + data[0] = (ft.getDouble("length") - 121.64943999999997) / 102.75395159548076; + data[1] = (ft.getDouble("speed") - 15.9616) / 4.368329731144388; + data[2] = (ft.getDouble("num_lanes") - 1.856) / 0.8551397546600205; + data[3] = ft.getDouble("change_speed"); + data[4] = ft.getDouble("change_num_lanes"); + data[5] = ft.getDouble("num_to_links"); + data[6] = ft.getDouble("junction_inc_lanes"); + data[7] = ft.getDouble("priority_lower"); + data[8] = ft.getDouble("priority_equal"); + data[9] = ft.getDouble("priority_higher"); + data[10] = ft.getDouble("is_secondary_or_higher"); + data[11] = ft.getDouble("is_primary_or_higher"); + data[12] = ft.getDouble("is_motorway"); + data[13] = ft.getDouble("is_link"); + + return data; + } + + @Override + public double predict(Object2DoubleMap ft, double[] params) { + + double[] data = getData(ft); + for (int i = 0; i < data.length; i++) + if (Double.isNaN(data[i])) throw new IllegalArgumentException("Invalid data at index: " + i); + + return score(data, params); + } + public static double score(double[] input, double[] params) { + double var0; + if (input[0] >= -0.8462881) { + if (input[6] >= 1.5) { + if (input[0] >= -0.76468533) { + if (input[0] >= -0.68789995) { + var0 = params[0]; + } else { + var0 = params[1]; + } + } else { + if (input[0] >= -0.8073114) { + var0 = params[2]; + } else { + var0 = params[3]; + } + } + } else { + if (input[0] >= -0.82147145) { + if (input[0] >= 1.1191838) { + var0 = params[4]; + } else { + var0 = params[5]; + } + } else { + var0 = params[6]; + } + } + } else { + if (input[0] >= -1.0267677) { + if (input[0] >= -1.002243) { + if (input[0] >= -0.96248794) { + var0 = params[7]; + } else { + var0 = params[8]; + } + } else { + var0 = params[9]; + } + } else { + var0 = params[10]; + } + } + double var1; + if (input[0] >= 0.46680015) { + if (input[0] >= 1.0344182) { + if (input[1] >= 0.47922206) { + if (input[2] >= -0.41630626) { + var1 = params[11]; + } else { + var1 = params[12]; + } + } else { + if (input[0] >= 1.3222904) { + var1 = params[13]; + } else { + var1 = params[14]; + } + } + } else { + if (input[2] >= -0.41630626) { + var1 = params[15]; + } else { + var1 = params[16]; + } + } + } else { + if (input[0] >= -0.69982165) { + if (input[1] >= -0.792431) { + if (input[2] >= 0.75309324) { + var1 = params[17]; + } else { + var1 = params[18]; + } + } else { + var1 = params[19]; + } + } else { + if (input[2] >= 1.9224927) { + if (input[0] >= -0.76804286) { + var1 = params[20]; + } else { + var1 = params[21]; + } + } else { + if (input[0] >= -0.82147145) { + var1 = params[22]; + } else { + var1 = params[23]; + } + } + } + } + double var2; + if (input[0] >= 1.4293422) { + if (input[1] >= -0.15603217) { + if (input[0] >= 1.4803379) { + if (input[2] >= 0.1683935) { + var2 = params[24]; + } else { + var2 = params[25]; + } + } else { + var2 = params[26]; + } + } else { + var2 = params[27]; + } + } else { + if (input[0] >= 1.3335794) { + var2 = params[28]; + } else { + if (input[11] >= 0.5) { + if (input[0] >= 0.04920064) { + var2 = params[29]; + } else { + var2 = params[30]; + } + } else { + if (input[0] >= -0.45715457) { + var2 = params[31]; + } else { + var2 = params[32]; + } + } + } + } + double var3; + if (input[0] >= 1.3335794) { + if (input[0] >= 2.015451) { + if (input[0] >= 2.0768113) { + if (input[2] >= -0.41630626) { + var3 = params[33]; + } else { + var3 = params[34]; + } + } else { + var3 = params[35]; + } + } else { + if (input[0] >= 1.6961446) { + var3 = params[36]; + } else { + var3 = params[37]; + } + } + } else { + if (input[0] >= -0.87937677) { + if (input[0] >= -0.86414623) { + if (input[0] >= -0.28796402) { + var3 = params[38]; + } else { + var3 = params[39]; + } + } else { + var3 = params[40]; + } + } else { + if (input[0] >= -0.90594506) { + if (input[0] >= -0.8935368) { + var3 = params[41]; + } else { + var3 = params[42]; + } + } else { + if (input[0] >= -0.96248794) { + var3 = params[43]; + } else { + var3 = params[44]; + } + } + } + } + double var4; + if (input[1] >= -0.15603217) { + if (input[2] >= 0.75309324) { + if (input[0] >= -0.4062563) { + if (input[0] >= 1.246089) { + var4 = params[45]; + } else { + var4 = params[46]; + } + } else { + if (input[0] >= -0.5137947) { + var4 = params[47]; + } else { + var4 = params[48]; + } + } + } else { + if (input[4] >= -0.5) { + if (input[1] >= 1.7508751) { + var4 = params[49]; + } else { + var4 = params[50]; + } + } else { + if (input[0] >= 1.2568915) { + var4 = params[51]; + } else { + var4 = params[52]; + } + } + } + } else { + if (input[2] >= 0.75309324) { + if (input[0] >= -0.040090334) { + if (input[0] >= 0.20423117) { + var4 = params[53]; + } else { + var4 = params[54]; + } + } else { + if (input[0] >= -0.8073114) { + var4 = params[55]; + } else { + var4 = params[56]; + } + } + } else { + if (input[0] >= -0.45715457) { + if (input[0] >= 0.47254202) { + var4 = params[57]; + } else { + var4 = params[58]; + } + } else { + if (input[0] >= -0.74955213) { + var4 = params[59]; + } else { + var4 = params[60]; + } + } + } + } + double var5; + if (input[0] >= -0.82750535) { + if (input[0] >= -0.680601) { + if (input[0] >= -0.41589096) { + if (input[0] >= -0.28796402) { + var5 = params[61]; + } else { + var5 = params[62]; + } + } else { + if (input[0] >= -0.44343248) { + var5 = params[63]; + } else { + var5 = params[64]; + } + } + } else { + if (input[0] >= -0.68989503) { + var5 = params[65]; + } else { + if (input[0] >= -0.69982165) { + var5 = params[66]; + } else { + var5 = params[67]; + } + } + } + } else { + if (input[0] >= -0.87937677) { + if (input[0] >= -0.86414623) { + var5 = params[68]; + } else { + var5 = params[69]; + } + } else { + if (input[0] >= -0.96248794) { + if (input[0] >= -0.9273068) { + var5 = params[70]; + } else { + var5 = params[71]; + } + } else { + if (input[0] >= -1.0267677) { + var5 = params[72]; + } else { + var5 = params[73]; + } + } + } + } + double var6; + if (input[0] >= -0.7369492) { + if (input[0] >= -0.70867777) { + if (input[10] >= 0.5) { + if (input[0] >= -0.10972269) { + var6 = params[74]; + } else { + var6 = params[75]; + } + } else { + if (input[0] >= -0.5848869) { + var6 = params[76]; + } else { + var6 = params[77]; + } + } + } else { + if (input[0] >= -0.7131058) { + var6 = params[78]; + } else { + if (input[0] >= -0.7254168) { + var6 = params[79]; + } else { + var6 = params[80]; + } + } + } + } else { + if (input[0] >= -0.74955213) { + var6 = params[81]; + } else { + if (input[0] >= -0.77728826) { + var6 = params[82]; + } else { + if (input[2] >= 0.1683935) { + var6 = params[83]; + } else { + var6 = params[84]; + } + } + } + } + double var7; + if (input[1] >= -0.15603217) { + if (input[0] >= -0.3979841) { + if (input[0] >= -0.16801728) { + if (input[0] >= 0.1484669) { + var7 = params[85]; + } else { + var7 = params[86]; + } + } else { + var7 = params[87]; + } + } else { + if (input[0] >= -0.4428972) { + var7 = params[88]; + } else { + if (input[0] >= -0.68989503) { + var7 = params[89]; + } else { + var7 = params[90]; + } + } + } + } else { + if (input[0] >= -0.22996137) { + if (input[0] >= 0.04920064) { + if (input[0] >= 0.14014605) { + var7 = params[91]; + } else { + var7 = params[92]; + } + } else { + if (input[0] >= -0.10972269) { + var7 = params[93]; + } else { + var7 = params[94]; + } + } + } else { + if (input[0] >= -0.2746312) { + var7 = params[95]; + } else { + if (input[0] >= -0.34275508) { + var7 = params[96]; + } else { + var7 = params[97]; + } + } + } + } + double var8; + if (input[0] >= -0.4512667) { + if (input[2] >= -0.41630626) { + if (input[0] >= -0.43516028) { + if (input[0] >= 1.7182848) { + var8 = params[98]; + } else { + var8 = params[99]; + } + } else { + if (input[0] >= -0.44343248) { + var8 = params[100]; + } else { + var8 = params[101]; + } + } + } else { + if (input[0] >= -0.01722017) { + if (input[0] >= 0.47254202) { + var8 = params[102]; + } else { + var8 = params[103]; + } + } else { + var8 = params[104]; + } + } + } else { + if (input[2] >= -0.41630626) { + if (input[0] >= -0.48907548) { + if (input[0] >= -0.4726284) { + var8 = params[105]; + } else { + var8 = params[106]; + } + } else { + if (input[0] >= -0.52839273) { + var8 = params[107]; + } else { + var8 = params[108]; + } + } + } else { + if (input[0] >= -0.5803615) { + var8 = params[109]; + } else { + if (input[0] >= -0.82147145) { + var8 = params[110]; + } else { + var8 = params[111]; + } + } + } + } + double var9; + if (input[2] >= 0.75309324) { + if (input[0] >= 0.29619843) { + if (input[0] >= 1.3367424) { + var9 = params[112]; + } else { + if (input[0] >= 0.46680015) { + var9 = params[113]; + } else { + var9 = params[114]; + } + } + } else { + if (input[0] >= 0.20423117) { + var9 = params[115]; + } else { + if (input[4] >= -2.5) { + var9 = params[116]; + } else { + var9 = params[117]; + } + } + } + } else { + if (input[0] >= 1.3335794) { + if (input[0] >= 1.7471402) { + if (input[4] >= -0.5) { + var9 = params[118]; + } else { + var9 = params[119]; + } + } else { + if (input[0] >= 1.4293422) { + var9 = params[120]; + } else { + var9 = params[121]; + } + } + } else { + if (input[0] >= 1.1876483) { + if (input[0] >= 1.221759) { + var9 = params[122]; + } else { + var9 = params[123]; + } + } else { + if (input[0] >= 1.1512506) { + var9 = params[124]; + } else { + var9 = params[125]; + } + } + } + } + double var10; + if (input[1] >= -0.15603217) { + if (input[0] >= -0.68989503) { + if (input[2] >= 0.75309324) { + if (input[0] >= -0.61958146) { + var10 = params[126]; + } else { + var10 = params[127]; + } + } else { + if (input[0] >= 1.1512506) { + var10 = params[128]; + } else { + var10 = params[129]; + } + } + } else { + if (input[2] >= -0.41630626) { + var10 = params[130]; + } else { + if (input[0] >= -0.90594506) { + var10 = params[131]; + } else { + var10 = params[132]; + } + } + } + } else { + if (input[0] >= -0.45715457) { + if (input[1] >= -1.4288299) { + if (input[0] >= -0.42426047) { + var10 = params[133]; + } else { + var10 = params[134]; + } + } else { + if (input[0] >= 1.8040724) { + var10 = params[135]; + } else { + var10 = params[136]; + } + } + } else { + if (input[2] >= -0.41630626) { + if (input[0] >= -0.6213819) { + var10 = params[137]; + } else { + var10 = params[138]; + } + } else { + if (input[0] >= -0.92930186) { + var10 = params[139]; + } else { + var10 = params[140]; + } + } + } + } + double var11; + if (input[1] >= 3.3407278) { + var11 = params[141]; + } else { + if (input[0] >= 0.85053235) { + if (input[0] >= 1.1512506) { + if (input[0] >= 1.1876483) { + var11 = params[142]; + } else { + var11 = params[143]; + } + } else { + if (input[0] >= 1.1044399) { + var11 = params[144]; + } else { + var11 = params[145]; + } + } + } else { + if (input[0] >= -0.6213819) { + if (input[0] >= -0.5848869) { + var11 = params[146]; + } else { + var11 = params[147]; + } + } else { + if (input[0] >= -0.77728826) { + var11 = params[148]; + } else { + var11 = params[149]; + } + } + } + } + double var12; + if (input[0] >= -0.44343248) { + if (input[0] >= -0.43516028) { + if (input[4] >= -1.5) { + if (input[0] >= 0.64917755) { + var12 = params[150]; + } else { + var12 = params[151]; + } + } else { + if (input[0] >= 0.04920064) { + var12 = params[152]; + } else { + var12 = params[153]; + } + } + } else { + var12 = params[154]; + } + } else { + if (input[0] >= -0.4856693) { + if (input[1] >= -0.15603217) { + var12 = params[155]; + } else { + if (input[0] >= -0.4726284) { + var12 = params[156]; + } else { + var12 = params[157]; + } + } + } else { + if (input[10] >= 0.5) { + var12 = params[158]; + } else { + if (input[0] >= -0.52839273) { + var12 = params[159]; + } else { + var12 = params[160]; + } + } + } + } + double var13; + if (input[0] >= -1.0065739) { + if (input[0] >= 1.2568915) { + if (input[0] >= 1.4803379) { + if (input[0] >= 2.015451) { + var13 = params[161]; + } else { + var13 = params[162]; + } + } else { + if (input[0] >= 1.4293422) { + var13 = params[163]; + } else { + var13 = params[164]; + } + } + } else { + if (input[0] >= 1.1876483) { + var13 = params[165]; + } else { + if (input[0] >= -0.123736754) { + var13 = params[166]; + } else { + var13 = params[167]; + } + } + } + } else { + var13 = params[168]; + } + double var14; + if (input[0] >= -0.28796402) { + if (input[0] >= -0.22996137) { + if (input[0] >= 0.3694316) { + if (input[0] >= 0.64917755) { + var14 = params[169]; + } else { + var14 = params[170]; + } + } else { + if (input[0] >= 0.3540551) { + var14 = params[171]; + } else { + var14 = params[172]; + } + } + } else { + if (input[0] >= -0.27424192) { + var14 = params[173]; + } else { + var14 = params[174]; + } + } + } else { + if (input[0] >= -0.32484823) { + var14 = params[175]; + } else { + if (input[0] >= -0.41589096) { + var14 = params[176]; + } else { + if (input[0] >= -0.5848869) { + var14 = params[177]; + } else { + var14 = params[178]; + } + } + } + } + double var15; + if (input[10] >= 0.5) { + if (input[2] >= 1.9224927) { + var15 = params[179]; + } else { + if (input[2] >= 0.75309324) { + if (input[0] >= 0.04920064) { + var15 = params[180]; + } else { + var15 = params[181]; + } + } else { + var15 = params[182]; + } + } + } else { + if (input[1] >= 2.0690746) { + if (input[1] >= 3.3407278) { + var15 = params[183]; + } else { + var15 = params[184]; + } + } else { + if (input[2] >= 1.9224927) { + var15 = params[185]; + } else { + if (input[0] >= -0.9273068) { + var15 = params[186]; + } else { + var15 = params[187]; + } + } + } + } + double var16; + if (input[0] >= -1.0267677) { + if (input[1] >= -0.15603217) { + if (input[0] >= -0.52839273) { + if (input[2] >= -0.41630626) { + var16 = params[188]; + } else { + var16 = params[189]; + } + } else { + if (input[1] >= 0.47922206) { + var16 = params[190]; + } else { + var16 = params[191]; + } + } + } else { + if (input[0] >= -0.92930186) { + if (input[2] >= 0.75309324) { + var16 = params[192]; + } else { + var16 = params[193]; + } + } else { + var16 = params[194]; + } + } + } else { + var16 = params[195]; + } + double var17; + if (input[0] >= -0.123736754) { + if (input[0] >= 0.04920064) { + if (input[2] >= -0.41630626) { + if (input[0] >= 1.0344182) { + var17 = params[196]; + } else { + var17 = params[197]; + } + } else { + if (input[0] >= 1.7471402) { + var17 = params[198]; + } else { + var17 = params[199]; + } + } + } else { + if (input[0] >= -0.034445778) { + var17 = params[200]; + } else { + var17 = params[201]; + } + } + } else { + if (input[0] >= -0.74955213) { + if (input[0] >= -0.7369492) { + if (input[0] >= -0.7254168) { + var17 = params[202]; + } else { + var17 = params[203]; + } + } else { + var17 = params[204]; + } + } else { + if (input[0] >= -0.77728826) { + var17 = params[205]; + } else { + if (input[0] >= -0.80127764) { + var17 = params[206]; + } else { + var17 = params[207]; + } + } + } + } + double var18; + if (input[0] >= -0.69982165) { + if (input[0] >= -0.680601) { + if (input[0] >= -0.5848869) { + if (input[0] >= -0.52839273) { + var18 = params[208]; + } else { + var18 = params[209]; + } + } else { + if (input[11] >= 0.5) { + var18 = params[210]; + } else { + var18 = params[211]; + } + } + } else { + if (input[0] >= -0.68989503) { + var18 = params[212]; + } else { + var18 = params[213]; + } + } + } else { + if (input[0] >= -0.70867777) { + var18 = params[214]; + } else { + if (input[2] >= 1.9224927) { + var18 = params[215]; + } else { + if (input[0] >= -1.0267677) { + var18 = params[216]; + } else { + var18 = params[217]; + } + } + } + } + double var19; + if (input[0] >= 2.0768113) { + if (input[4] >= -1.5) { + if (input[0] >= 2.8893833) { + var19 = params[218]; + } else { + var19 = params[219]; + } + } else { + var19 = params[220]; + } + } else { + if (input[1] >= -1.4288299) { + if (input[0] >= 2.015451) { + var19 = params[221]; + } else { + if (input[11] >= 0.5) { + var19 = params[222]; + } else { + var19 = params[223]; + } + } + } else { + var19 = params[224]; + } + } + return 0.5 + (var0 + var1 + var2 + var3 + var4 + var5 + var6 + var7 + var8 + var9 + var10 + var11 + var12 + var13 + var14 + var15 + var16 + var17 + var18 + var19); + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_priority.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_priority.java new file mode 100644 index 00000000000..82454d7f087 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_priority.java @@ -0,0 +1,3831 @@ +package org.matsim.application.prepare.network.params.ref; +import org.matsim.application.prepare.network.params.FeatureRegressor; +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; + +/** +* Generated model, do not modify. +*/ +final class GermanyNetworkParams_capacity_priority implements FeatureRegressor { + + public static GermanyNetworkParams_capacity_priority INSTANCE = new GermanyNetworkParams_capacity_priority(); + public static final double[] DEFAULT_PARAMS = {1767.3695633827278, 1811.5273612880271, 1757.5880797775521, 1773.850780326021, 1749.8471454865478, 1781.4893514477765, 1805.964622790866, 1771.0005204318536, 1805.9376672865124, 1811.5545602813763, 1807.7955381067238, 1808.4814791987335, 1842.014288930537, 1849.5294602540107, 1833.5415279301687, 1832.8480380747665, 1843.3345259172886, 1835.6589021328305, 1845.4978793029343, 1823.2657367554266, 1851.5827789254217, 1890.964775838754, 1857.9783438684233, 1794.7187940973977, 1848.4993219498967, 1861.942325395404, 1886.4358778320757, 1880.6809076598129, 1853.1267683575707, 1820.2378931396981, 1851.999278904619, 1853.4774832845847, -54.69491511477343, -14.952893287109266, -63.498249305886795, -48.86181645229029, -70.46509292674844, -41.98710408590753, -19.95935883171663, -51.42705566359561, -19.98361839464748, -14.928414993956103, -18.311534349643743, -22.698695913194697, 11.235078192365727, 0.49191082455431334, 11.314355216489831, 17.938762932035235, 12.39527978841621, 18.297314935920248, 21.768043338156517, 61.073830871122006, 22.681061458706004, -30.08060617826899, 18.21045914742283, 26.58016329716441, 51.01825006219045, 49.157285245513854, 22.51461135142422, -15.176876762664723, 17.027715096506384, 23.390056814596775, 22.40115810421746, -27.35830258615927, -49.22542319214298, -13.457603659669525, -57.14842630783992, -43.97563486156685, -63.41858412192437, -37.78839383963801, -17.963422356837892, -46.28434726953077, -24.215866308435395, -12.511950075598438, -13.435573366338259, -16.480381484101756, -5.565031186173137, -29.042581515483814, 11.074314034684013, 17.510586423443456, 8.40209978351158, 14.05683590805522, -6.304364362492991, 19.04196386296601, 54.966445617215754, 20.41295537960444, -34.53045377534651, 16.47944917163163, 26.622800106122977, 50.05622729159367, 23.861373409605974, -13.659189384735033, 14.877210231150588, 21.050996679396178, 20.16104122189324, -24.62247321081888, -44.302880202664056, -12.11184406673444, -51.43358255783992, -39.57807211933358, -57.07672025662399, -34.009554573337816, -16.167080221139027, -41.65591335876235, -16.186731250446538, -14.756290202588753, -12.28360643739365, 17.3682990290438, 0.1935366738043478, -49.95896870782027, 0.8491962079365907, -15.590529513530687, 10.831638110473119, 2.8845979321507746, 12.886569267024868, -12.915315126673262, 14.642165746274351, 45.997374182196495, 21.41354001539226, -31.077408121049633, 14.940482443186369, 36.15391004645465, 19.746711215998328, -9.703932779449426, 17.43899574985967, 18.811544152875424, 18.214704761733948, -22.160225171573273, -39.87259185185701, -10.900659395182737, -46.290223182839924, -35.6202642679414, -51.36904819161803, -39.711629390843676, -15.472428864299824, -13.982227668730804, -37.49032124486892, -14.56805839260101, -10.944046626901219, -13.284514851109652, 7.973540418933019, 8.220226087270428, -29.114855896654912, 1.1214580858354324, 10.686627458342851, 14.200606993731979, 15.423787508904528, 11.288590797286412, 41.397636633368364, 19.27218610303874, -22.05569978507112, 13.312707057536727, 32.634840503051535, 34.33721036451335, 14.953017052575, -8.733539751190149, 15.714779712620468, 16.96156926255897, 16.393234119644102, -19.944203355026175, -35.88533259524218, -9.810593603762989, -54.24412757775778, -24.5792988296282, -36.64651249030197, -46.23214620207623, -28.605157235396792, -13.050558477940005, -33.74128933532484, -13.111252321936659, -14.091022492039261, -12.114068649791786, 14.462692273398147, -4.30844337341616, -14.108547244243576, 8.8955703959419, 1.7545502060039817, 10.446593128931612, -10.529378949303089, 12.050042660317212, 30.564472588027815, -25.764097302907274, 12.115163512147834, -13.251767336095723, 12.91316938684841, 16.03306648918068, 31.830941972190892, 12.024630143409848, -4.251487611363667, 15.446894706568628, 14.753910694351134, -17.949782144370374, -32.29680110110156, -8.829534328210714, -37.933161423554616, -17.189924523341627, -31.23024168493815, -41.60893163362288, -34.08975276606521, -12.566493524053577, -11.228502000270403, -30.367159769530765, -17.407675409660087, -6.874150994902543, 7.062255745276229, -11.568046482437722, -18.33365494222956, 5.8556083164779595, 11.463353607443254, 5.75888762355646, 10.868000790971323, 34.201426235720454, 14.288519969158125, -23.187687187347375, 10.90364640595285, -11.92659040511371, 11.62185239835006, 30.558190745568762, 9.488918261025729, 20.59338031247658, -3.826338405837951, 13.902204899133446, 13.278520069351135, -16.15480466282177, -47.89540139035027, -25.564490752236157, -9.454750128906843, -30.506466539832584, -37.4480397354823, -24.965939242056105, -24.258571207183806, -10.464416394077169, -21.543708806089032, -44.88691443477622, -8.181049177177306, -27.33044338805922, -15.666908433345567, -6.18673569804238, -13.338909158200934, 6.567799340080436, -10.452572592002753, -8.986411262223756, 3.9981095655790178, 8.99643421796618, 2.516661701911211, 11.096060972304448, 6.989158917500245, 12.342215732777758, 34.771019843146355, 12.673452610923473, -3.6667107049407583, -8.977536954074367, 9.07255506502411, 12.945669992550478, 11.919035696245196, -21.340787458705826, -26.25786867508077, -7.001105688723925, -41.26932699105734, -17.571364731121047, -26.82020604028312, -25.649788569491655, -34.28751414420071, -22.46934517896068, -21.83271454252621, -8.988306240556971, -8.751614044153035, -31.831314132673807, -9.558103673618536, -12.005018230920236, -27.541390877113248, 12.070692056037576, -8.04439473063256, -14.995578511655518, -10.788596512985158, 7.078384140056276, 5.411585164010169, 0.9473167342983567, 13.052060368281156, -0.14594378289048543, 7.7381790091320966, 11.360628756895302, 31.293917541043868, 11.406107327152089, 0.3768817976071709, 8.548475584366605, -7.194912206627286, 11.57977834102218, -39.699478782928395, -20.521696208685942, -7.518631884917354, -24.834826206371286, -30.332911359054904, -20.222410968224864, -23.632490123341817, -8.519144086593814, -25.378689584688253, -6.651893815527451, -11.077509174575745, -31.105314899320817, -13.144406724169258, -4.612251818152149, -10.80451654034944, -6.479877030957519, -18.329827725011594, 1.7826912219880269, 16.340421550888024, 1.098039477239943, 8.11896811608596, 1.6103167101985845, 9.190657211917678, 6.4466608480395955, 25.524147300565673, 10.545211758785202, -18.980226837713012, 2.372209462689832, 8.492556888904126, 10.278216725091507, 9.630293242365457, -12.416886022409836, -24.0317815746825, -5.626772396178357, -18.257115649616424, -27.50900231977861, -7.56087305343306, -19.56813943255927, -7.8178061451734635, -11.179244739081279, -5.7284049200999085, -38.38952377183326, -4.733118591423003, 3.7997704324762474, 3.1279140477400276, 5.299928874472152, -32.60215933922071, -3.1814414867763543, 4.95602008379262, 4.670068210955057, 8.390290894933932, -16.94943246513091, 7.219426299601938, 19.618109281915014, -3.6089840759426575, -10.894984687398214, 6.739785901202762, -13.211467473496999, 31.260846427470216, 26.332807387296555, -10.050183172569183, 11.081407022194687, 9.315811793386635, -3.8141589539403093, -33.26947091596599, -19.688452319332754, -5.0640950482275375, -16.43140439407767, -24.758102056368223, -9.359479426910324, -22.957720611535848, -4.8629528417900865, -30.843517738795228, -2.7984740547978397, -13.739425263313331, -4.954266877561722, -10.06132034450127, -5.1555642752968, -10.959366901368291, 12.695633252788637, -35.72803621318517, -17.601144784903468, 3.741916937773754, 6.326873156793451, 4.262664876559159, 8.670889274272794, -5.931613550105837, 6.784047249794916, 7.921156379212822, -15.254489527552437, 6.497483602349391, 17.6562987280464, -3.2480855943118456, 1.7133564761167763, 8.491299254088645, -29.644290596282886, -16.46100345743305, -5.208648928218929, -17.757164734461206, -22.28229192388648, -6.1377350391784855, -2.046207456931975, -22.937346375131572, -6.142145307949365, -9.05518824315271, -4.640007878915497, -0.3510693450115701, -32.15523308266853, -14.880896071439745, 3.3677250772128007, 5.649778810072448, 3.42097149115155, 9.647541929216594, -4.851574382469213, 4.046670766595191, 6.364666744503534, 8.157228910174743, -23.304263691166433, 5.058504011126922, 6.029054134698306, 25.04275433585475, 28.0301765378491, -8.286617132597632, 7.622389459960096, -17.655473416437356, 4.4962392939532805, 7.437407856661764, -26.679861645853926, -17.75946426325934, -4.036820701585159, -13.16940384218518, -20.054062942685064, -5.355821085143322, -11.610066990384567, -3.6369166366106533, -27.5903992541198, 13.371626490569057, -18.312734745158238, -33.65779577184153, 13.16484391301905, 4.872472100429489, -18.428550888038348, 3.8215297066660536, -14.807603628210977, 7.93320167402994, -18.110122160259845, -12.950973487071947, 3.211361082270354, 11.611351683676531, -3.4414626575247, 8.897840126744198, -17.473226644880466, 7.797429118470838, 15.854133386905119, -7.801347742920967, 4.27899407366003, 23.538976387905365, 7.310702219934561, 6.337708685571998, -24.01187529782097, -26.922324297000973, -5.806492126097983, -19.38107719279948, -12.32016525358173, -18.04865684705961, -15.306792305129969, -5.7711404373145285, -17.21459512538399, -3.0512453059186537, -14.456802915225285, -4.801529634013626, 17.951825191139427, -0.29076039775090895, 4.263143760818444, 17.17547684543871, 6.988431384667246, -11.07422363701394, 7.3438153923929095, -23.82136118923178, -7.024243341647228, 4.768382879519709, -0.9969281598448397, 9.709661658293326, 5.188822681158346, -6.732372539058938, -9.434638206278452, -1.4828838636744928, -14.722783300865954, 2.9826818436885096, 7.781950769390621, 3.574833825975974, -23.13787177829735, 1.235623269322312, -25.273748272524337, -9.330415566029215, -31.56515589902536, -13.76083030304833, -18.956136690028618, -0.5211609122525442, -22.244472445238486, -10.129328391741483, -2.9696446809867174, -11.57115325131609, -20.621664776760312, -10.4088772400385, 1.9587884859131681, 23.979706067102775, 2.0646115164590517, -29.991460773249948, -11.541534611276127, 0.8058377637346625, -2.153022004536465, 11.642037775625788, -19.37935517777656, -4.532456665875223, -4.075983344843618, 4.508985674407504, -6.216833255663194, -7.489204250099242, -13.477044514316521, 3.426571860561921, 3.1931903611550454, 5.190969995256267, -19.410207166946336, -21.594255555492822, -4.643012622877856, -11.901537016436519, -15.356818629733887, -4.0775528401120145, 11.453389192268757, -18.687384437039665, -3.693503046166126, -23.32057732418816, 13.199891299223843, -14.95095038236527, -28.71237339772307, -0.6913923147987575, 3.978482104068504, 7.522313332843703, -15.60350165561942, 6.235129356047593, -15.688233328008614, -5.726548939021409, 3.061752268005522, -2.6154340709331736, 7.019279635620108, -18.57523132343832, 3.7124478696785355, 4.164571006000287, 19.52828904723567, 5.625819452187308, -19.908441472238497, -2.0524043073557925, 3.007759131043981, 5.524315828669165, -21.688588602204675, -12.091984604749335, -4.485197878754913, -13.214988425422375, -3.1139990427464768, -7.761738327349767, -14.232853183371066, -6.021580096131204, -18.028598486001062, -1.9203242168950672, -24.072996843075696, -0.34107005208732405, 10.308050804481415, -16.818645766690544, -3.3518238165654965, -20.98851967648308, 13.189182433003328, -11.992849342903654, -25.84113614141287, -11.456467722176571, 1.5227049643733714, 3.6018878991277554, -6.581249422656947, -3.933888506067923, 1.9266202095828406, 4.040387157622585, 3.827778279377121, 17.037217823936555, 23.586761053913975, -6.526751314940748, 5.552555143919686, 4.279935252048252, -19.519729155072216, -18.22563167270155, -3.563113545904617, -9.834930856117126, -12.439023357840625, -16.348099546775725, -0.9733770514224753, -22.423262411769684, 0.16393322752356865, -5.054804341765359, -8.00384408539073, -1.204394328939539, -15.306904237341474, 3.163552334582141, 0.12713749834688703, 14.098442419462016, 4.633502353245653, -5.510842336027491, 8.27168683898836, 3.5077351352301975, -5.395963527125899, -23.172132633483812, -3.577495175804564, 0.9468815342485443, -10.914572041377246, -6.087796435553883, -11.308878369706617, 4.640517138717828, 9.367820346441247, -0.8846302584959699, 4.988184086888915, 4.918749629974307, -15.37209030021024, -10.114840669656473, -1.5699618700283273, 0.3606914291585863, 3.615701701736366, -12.013490570494653, 1.0369404412564025, -12.795721573087432, -11.195121118212604, -2.885584001356259, 9.601669216499236, -14.755696064745557, -2.583343832133586, -17.35897658566277, 12.20231525181731, -11.303183885985083, -22.518431468599456, -10.175816338259285, 1.07797327375669, 2.9782523924513367, -11.657221900249063, 5.219704956442371, -7.109070273307227, 6.806983189951025, -1.8858400813839546, 5.408078658993634, -14.669662747005844, 5.3275280464584265, 2.7450311720930505, -3.924743002856476, 5.8622463881840305, 3.667754930727992, -16.11636440134907, -8.676175398504595, -2.950580776160807, -9.681615168012957, -17.855024955954885, -13.011705229938281, 10.591211505023562, 5.4314407427672595, -10.511172529007174, 14.58649889980307, 1.6384331010215818, -3.4127661957008537, -2.9274220167114935, -11.840803977908756, 20.014944046950284, -41.95098560002637, -9.78935427892995, 3.2567635207596433, 10.006205420691929, 10.209032676571491, 3.1508950381418463, -4.638274340920346, -15.623829805198012, -0.7264477579510996, -10.267446249937954, -6.906511605127474, -5.2387542757289145, 4.055275965145635, 8.02946976105948, -0.7489271394586392, 4.106441033421752, 4.291352289054573, -15.222854105917534, -9.180354910657249, -3.1385525782115815, -7.780744017805162, -16.06952327227956, -11.603987638129212, 1.425482716876682, 1.4832588180757986, -3.5048495726278652, -2.6560952164022145, -3.6650185242091724, -17.158375195421403, 6.136202140236846, 6.18840651054922, 18.001263609282155, 3.7445850631005735, 0.23862405394459962, -16.894994157384176, 19.9662201884841, -5.8724094987048545, 11.107620455800536, 4.2751915344600695, 21.09978902232517, 3.203035109157947, -17.409440722111206, 4.606779023005443, -1.5141913101985187, 2.160644941488656, 4.25128567935384, -4.174446828141859, -3.842571359393363, 1.7839454733996405, -13.700568396139069, -7.302015662479324, 8.587900943516713, 2.353876116033255, -17.06958553337091, -11.028611257680241, -6.019883735947687, 0.23567671028418916, -23.093085836626056, -5.043163288312197, -20.431315858350395, -5.3634409006977535, -17.10464131965629, -0.5472640551794794, 5.891055417912786, -5.495798972166817, 3.612123969144603, -4.192460823305203, -22.722749799704495, 5.10789430786931, -6.95096798371446, 1.8855067056176686, -2.9435204386361082, 0.28829812760724643, 8.359691097056041, -11.844516343092861, -9.209923829850872, -0.2948042242990447, 6.416504326655782, -4.793124402743405, 0.5222902296139444, 2.5888651095736583, -11.047924232757495, -2.8812054870719894, -1.6249561759409965, -7.441071830812618, -8.364850896025455, -16.682293379706486, -0.016568295819839863, 7.419717423586282, -1.480931525680827, -0.34582426837815333, -3.484696045013553, -13.622143470809684, 3.7545594888080043, -3.469689239775082, -1.8832558951695244, 10.213107777369157, -3.691530629503239, 10.6297789977023, -7.78844366998214, 2.6938761352992113, -9.77050240691633, 1.5942162950170304, -0.3045814224053922, -12.546140624745632, -9.554843683586027, 1.8849194471281927, -1.4183525018647716, -9.024979479232023, 0.4868122665542208, 4.396613495669479, 2.06770433868977, 3.147333779240955, -11.45287126728686, -2.0321537315869995, -6.3474690072690345, -1.8874953366482288, -19.501931684621127, -8.045895757620638, 6.4589009765242595, -17.68787431295477, 16.90495794934351, -1.89796170191077, -5.6493750405218695, 5.428974325906296, -1.6176052585757397, 1.0660474967129805, -4.786807781694721, 3.7038703429541124, 3.0979645812731573, 1.41562374185309, -7.1973825764563175, 7.247182714814016, -1.5406981023311035, -25.178717341468243, -5.066437323495535, 11.249875512179763, -7.30633070574787, -9.071743503136037, 2.7720122714546673, 8.190234015833163, -5.421853189853557, 4.965363460650575, -1.1096731898456669, 2.60883867478117, -10.307583960183385, -12.664489487065978, -0.9601728209247442, -4.657926438514647, 2.268607779312079, -6.6472840185620585, -12.006208338383178, 0.8908495387952965, 5.9573644020457275, -1.9806963197539051, -32.72014581640914, 1.244137288609741, -5.786439898919818, -2.377516729949643, 1.9287645300934502, -7.082888127267527, -7.807297905242845, 6.857645771911975, 14.609950190965765, 2.880005312041705, 5.523959788981646, 8.404440500556694, 1.1113071679441782, 6.466286563387013, 2.1513056538339224, -13.050003047332673, 13.711774753786088, -4.684608202141697, -11.520741025892818, -1.0047039884474491, -3.9854187659079976, 1.3191712915463762, -9.132333493518752, -11.398040453768951, -0.7022429160079957, 5.37128594542855, -6.082368797980346, -6.731983269164087, 6.263283049132565, 6.012382780129481, 1.7584995426280576, -9.343408578585729, 2.0417469699859074, -5.982555533368066, -10.414711511278114, 11.682981859481737, 0.518342305514821, -1.6302242605307997, -2.121468004529438, -4.341399462486474, 2.767722746589623, -18.412228186532644, -7.123139618179144, 7.476786605246151, 2.4735574295882117, -17.751566505759016, 3.0972087786559315, -12.20830705921331, 0.2627005066370304, -7.269051739501889, -6.45801641624989, -12.216475500917367, 6.760444329754709, -17.810171782750587, 2.0973145028073654, -5.0258611666476325, -3.778488479610904, -0.05835244305614239, -5.208910624227999, -9.373240673685036, -1.119279886992781, 2.4064624312972094, -10.452215415382348, -21.286410265312103, 9.585143442497161, -9.287521337187233, 11.779600461500072, -22.93764644847556, -2.1126104137419937, 1.1825829857872399, -3.649811045554115, 0.8845491957834286, -8.981153644527003, -18.135242645231806, -1.642656417061886, 0.8486531937694395, 8.763458627851026, -3.5353938399258236, 22.71296492446256, 15.895486477770035, -5.619378631567127, 19.071137456794954, 9.065273378009255, 1.6179661755587185, -0.21367377081155806, 1.7501281159867774, -10.897085112103465, -9.755650725907499, -9.113978967007666, -1.6126244165084445, 3.5674244540099354, -4.838119622478276, -8.435916563018123, 10.626611561096118, 0.5784360444107689, -8.071536579683954, -9.103456218041083, -0.9060371285754644, 1.8259092332111617, 2.1148928773365276, -7.54211651239426, 2.1658161262129805, -9.40699375981486, -18.05123764262839, -5.914432566362707, 5.5944782546614675, -16.301567221031096, 5.724742116390283, 2.417056121571122, 0.3705732947302734, -15.1980761492614, -1.8092260466818315, 2.547546960299565, 7.200506365058448, -27.05268730953972, -0.045084452995398566, 0.9458530043332675, -0.8676832799054783, 1.62757134644459, -1.2049670455234818, -3.8963057618149968, -10.79012497641514, -4.230758595752639, 14.23254657583898, 2.8257259079787294, -1.1521617051755508, -43.56981262058068, 1.2086588443737594, -4.666815985236946, -1.7646224026638881, -3.918234071647295, 2.2079022783040303, -16.746832333738826, -6.159885739795087, 2.4563952104244957, 1.6630114450107076, -11.291371878866675, 4.107633381699683, -31.550823137333005, 2.8274580003737886, -3.9739832580347896, 8.276056085477512, -13.491860454018866, 10.3528090809748, -0.07524960728767772, -24.783608382415682, -11.796615644246799, 2.6215895365714363, 5.647703587564294, -0.13795591741222238, 1.3430259927969228}; + + @Override + public double predict(Object2DoubleMap ft) { + return predict(ft, DEFAULT_PARAMS); + } + + @Override + public double[] getData(Object2DoubleMap ft) { + double[] data = new double[14]; + data[0] = (ft.getDouble("length") - 140.91374966725232) / 113.09700132654554; + data[1] = (ft.getDouble("speed") - 17.315611457168714) / 6.460215616713478; + data[2] = (ft.getDouble("num_lanes") - 1.4162274397061172) / 0.7453179157424549; + data[3] = ft.getDouble("change_speed"); + data[4] = ft.getDouble("change_num_lanes"); + data[5] = ft.getDouble("num_to_links"); + data[6] = ft.getDouble("junction_inc_lanes"); + data[7] = ft.getDouble("priority_lower"); + data[8] = ft.getDouble("priority_equal"); + data[9] = ft.getDouble("priority_higher"); + data[10] = ft.getDouble("is_secondary_or_higher"); + data[11] = ft.getDouble("is_primary_or_higher"); + data[12] = ft.getDouble("is_motorway"); + data[13] = ft.getDouble("is_link"); + + return data; + } + + @Override + public double predict(Object2DoubleMap ft, double[] params) { + + double[] data = getData(ft); + for (int i = 0; i < data.length; i++) + if (Double.isNaN(data[i])) throw new IllegalArgumentException("Invalid data at index: " + i); + + return score(data, params); + } + public static double score(double[] input, double[] params) { + double var0; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 1.4046572252719522) { + if (input[2] > 2.7958170819201564) { + var0 = params[0]; + } else { + var0 = params[1]; + } + } else { + if (input[2] > 2.7958170819201564) { + var0 = params[2]; + } else { + var0 = params[3]; + } + } + } else { + var0 = params[4]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[3] > 7.22) { + var0 = params[5]; + } else { + var0 = params[6]; + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var0 = params[7]; + } else { + var0 = params[8]; + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var0 = params[9]; + } else { + if (input[3] <= -4.164999999999998) { + var0 = params[10]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9943123897915209) { + var0 = params[11]; + } else { + var0 = params[12]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var0 = params[13]; + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 2.5000000000000004) { + var0 = params[14]; + } else { + if (input[0] > 0.052576551659217236) { + if (input[5] > 1.5000000000000002) { + var0 = params[15]; + } else { + var0 = params[16]; + } + } else { + if (input[0] <= -0.9789715763336068) { + var0 = params[17]; + } else { + var0 = params[18]; + } + } + } + } else { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var0 = params[19]; + } else { + var0 = params[20]; + } + } + } + } + } + } + } else { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 1.4046572252719522) { + var0 = params[21]; + } else { + var0 = params[22]; + } + } else { + if (input[0] <= -0.9789715763336068) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var0 = params[23]; + } else { + var0 = params[24]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 0.544004836887963) { + if (input[3] <= -0.000000000000000000000000000000000010000000180025095) { + var0 = params[25]; + } else { + var0 = params[26]; + } + } else { + if (input[3] > 8.335000000000003) { + var0 = params[27]; + } else { + var0 = params[28]; + } + } + } else { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var0 = params[29]; + } else { + var0 = params[30]; + } + } else { + var0 = params[31]; + } + } + } + } + } + } + } + } + double var1; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 1.4046572252719522) { + if (input[2] > 2.7958170819201564) { + var1 = params[32]; + } else { + var1 = params[33]; + } + } else { + if (input[2] > 2.7958170819201564) { + var1 = params[34]; + } else { + var1 = params[35]; + } + } + } else { + var1 = params[36]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[3] > 7.22) { + var1 = params[37]; + } else { + var1 = params[38]; + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var1 = params[39]; + } else { + var1 = params[40]; + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var1 = params[41]; + } else { + if (input[3] <= -4.164999999999998) { + var1 = params[42]; + } else { + if (input[0] <= -1.060096627328628) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var1 = params[43]; + } else { + var1 = params[44]; + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + var1 = params[45]; + } else { + var1 = params[46]; + } + } else { + var1 = params[47]; + } + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 2.5000000000000004) { + var1 = params[48]; + } else { + var1 = params[49]; + } + } else { + var1 = params[50]; + } + } + } + } + } + } else { + if (input[1] > 2.0493725485847785) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var1 = params[51]; + } else { + var1 = params[52]; + } + } else { + if (input[0] <= -0.9789715763336068) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var1 = params[53]; + } else { + var1 = params[54]; + } + } else { + if (input[6] > 1.5000000000000002) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 0.544004836887963) { + if (input[3] <= -0.000000000000000000000000000000000010000000180025095) { + var1 = params[55]; + } else { + var1 = params[56]; + } + } else { + if (input[3] > 8.335000000000003) { + var1 = params[57]; + } else { + var1 = params[58]; + } + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[3] <= -2.774999999999998) { + var1 = params[59]; + } else { + var1 = params[60]; + } + } else { + var1 = params[61]; + } + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var1 = params[62]; + } else { + var1 = params[63]; + } + } + } + } + } + } + } + } + double var2; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 1.4046572252719522) { + if (input[2] > 2.7958170819201564) { + var2 = params[64]; + } else { + var2 = params[65]; + } + } else { + if (input[2] > 2.7958170819201564) { + var2 = params[66]; + } else { + var2 = params[67]; + } + } + } else { + var2 = params[68]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[3] > 7.22) { + var2 = params[69]; + } else { + var2 = params[70]; + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var2 = params[71]; + } else { + if (input[1] <= -0.3150996155456951) { + var2 = params[72]; + } else { + var2 = params[73]; + } + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var2 = params[74]; + } else { + if (input[3] <= -4.164999999999998) { + var2 = params[75]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9943123897915209) { + if (input[6] > 3.5000000000000004) { + var2 = params[76]; + } else { + var2 = params[77]; + } + } else { + var2 = params[78]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var2 = params[79]; + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 2.5000000000000004) { + var2 = params[80]; + } else { + var2 = params[81]; + } + } else { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var2 = params[82]; + } else { + var2 = params[83]; + } + } + } + } + } + } + } else { + if (input[1] > 2.0493725485847785) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var2 = params[84]; + } else { + var2 = params[85]; + } + } else { + if (input[0] <= -0.9842767567801477) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var2 = params[86]; + } else { + var2 = params[87]; + } + } else { + if (input[6] > 1.5000000000000002) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 1.4046572252719522) { + if (input[3] <= -0.000000000000000000000000000000000010000000180025095) { + var2 = params[88]; + } else { + var2 = params[89]; + } + } else { + var2 = params[90]; + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[3] <= -2.774999999999998) { + var2 = params[91]; + } else { + var2 = params[92]; + } + } else { + var2 = params[93]; + } + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var2 = params[94]; + } else { + var2 = params[95]; + } + } + } + } + } + } + } + } + double var3; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 1.4046572252719522) { + if (input[2] > 2.7958170819201564) { + var3 = params[96]; + } else { + var3 = params[97]; + } + } else { + if (input[2] > 2.7958170819201564) { + var3 = params[98]; + } else { + var3 = params[99]; + } + } + } else { + var3 = params[100]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[3] > 7.22) { + var3 = params[101]; + } else { + var3 = params[102]; + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var3 = params[103]; + } else { + var3 = params[104]; + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[3] <= -4.164999999999998) { + var3 = params[105]; + } else { + if (input[6] > 2.5000000000000004) { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var3 = params[106]; + } else { + var3 = params[107]; + } + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9789715763336068) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + var3 = params[108]; + } else { + var3 = params[109]; + } + } else { + var3 = params[110]; + } + } else { + if (input[5] > 1.5000000000000002) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var3 = params[111]; + } else { + if (input[0] <= -0.19292067350446304) { + var3 = params[112]; + } else { + var3 = params[113]; + } + } + } else { + var3 = params[114]; + } + } + } else { + var3 = params[115]; + } + } + } else { + var3 = params[116]; + } + } + } else { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 1.4046572252719522) { + var3 = params[117]; + } else { + var3 = params[118]; + } + } else { + if (input[0] <= -0.9842767567801477) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var3 = params[119]; + } else { + var3 = params[120]; + } + } else { + if (input[6] > 1.5000000000000002) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 0.544004836887963) { + var3 = params[121]; + } else { + var3 = params[122]; + } + } else { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var3 = params[123]; + } else { + var3 = params[124]; + } + } else { + var3 = params[125]; + } + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var3 = params[126]; + } else { + var3 = params[127]; + } + } + } + } + } + } + } + } + double var4; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 1.4046572252719522) { + if (input[2] > 2.7958170819201564) { + var4 = params[128]; + } else { + var4 = params[129]; + } + } else { + if (input[2] > 2.7958170819201564) { + var4 = params[130]; + } else { + var4 = params[131]; + } + } + } else { + var4 = params[132]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[0] <= -0.8365274813439836) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var4 = params[133]; + } else { + var4 = params[134]; + } + } else { + var4 = params[135]; + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var4 = params[136]; + } else { + var4 = params[137]; + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var4 = params[138]; + } else { + if (input[0] <= -0.9789715763336068) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var4 = params[139]; + } else { + var4 = params[140]; + } + } else { + if (input[0] > 0.2796824846082225) { + var4 = params[141]; + } else { + if (input[6] > 3.5000000000000004) { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + if (input[0] <= -0.8676954164674114) { + var4 = params[142]; + } else { + var4 = params[143]; + } + } else { + var4 = params[144]; + } + } else { + var4 = params[145]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var4 = params[146]; + } else { + var4 = params[147]; + } + } + } + } + } + } else { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 1.4046572252719522) { + var4 = params[148]; + } else { + var4 = params[149]; + } + } else { + if (input[0] <= -0.9789715763336068) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var4 = params[150]; + } else { + var4 = params[151]; + } + } else { + if (input[6] > 1.5000000000000002) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 0.544004836887963) { + var4 = params[152]; + } else { + if (input[0] <= -0.6870098124256391) { + var4 = params[153]; + } else { + var4 = params[154]; + } + } + } else { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var4 = params[155]; + } else { + var4 = params[156]; + } + } else { + var4 = params[157]; + } + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var4 = params[158]; + } else { + var4 = params[159]; + } + } + } + } + } + } + } + } + double var5; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 1.4046572252719522) { + if (input[2] > 2.7958170819201564) { + var5 = params[160]; + } else { + var5 = params[161]; + } + } else { + if (input[2] > 4.13752641008496) { + var5 = params[162]; + } else { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[163]; + } else { + var5 = params[164]; + } + } + } + } else { + var5 = params[165]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[3] > 7.22) { + var5 = params[166]; + } else { + var5 = params[167]; + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var5 = params[168]; + } else { + var5 = params[169]; + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[3] <= -4.164999999999998) { + var5 = params[170]; + } else { + if (input[6] > 2.5000000000000004) { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[171]; + } else { + var5 = params[172]; + } + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9789715763336068) { + var5 = params[173]; + } else { + if (input[5] > 1.5000000000000002) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[174]; + } else { + if (input[0] <= -0.19292067350446304) { + var5 = params[175]; + } else { + var5 = params[176]; + } + } + } else { + var5 = params[177]; + } + } + } else { + var5 = params[178]; + } + } + } else { + var5 = params[179]; + } + } + } else { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[180]; + } else { + if (input[0] <= -0.9842767567801477) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[181]; + } else { + var5 = params[182]; + } + } else { + if (input[6] > 1.5000000000000002) { + if (input[5] > 1.5000000000000002) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[183]; + } else { + var5 = params[184]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] <= -0.000000000000000000000000000000000010000000180025095) { + var5 = params[185]; + } else { + var5 = params[186]; + } + } else { + var5 = params[187]; + } + } else { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[188]; + } else { + var5 = params[189]; + } + } + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[190]; + } else { + var5 = params[191]; + } + } + } + } + } + } + } + } + double var6; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 1.4046572252719522) { + if (input[2] > 2.7958170819201564) { + var6 = params[192]; + } else { + var6 = params[193]; + } + } else { + if (input[2] > 2.7958170819201564) { + var6 = params[194]; + } else { + if (input[5] > 1.5000000000000002) { + var6 = params[195]; + } else { + var6 = params[196]; + } + } + } + } else { + var6 = params[197]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[0] <= -0.8365274813439836) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[198]; + } else { + var6 = params[199]; + } + } else { + var6 = params[200]; + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var6 = params[201]; + } else { + if (input[1] <= -0.3150996155456951) { + var6 = params[202]; + } else { + var6 = params[203]; + } + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[204]; + } else { + var6 = params[205]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -1.0491767975761646) { + var6 = params[206]; + } else { + var6 = params[207]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[208]; + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[209]; + } else { + var6 = params[210]; + } + } + } + } + } else { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 1.4046572252719522) { + var6 = params[211]; + } else { + var6 = params[212]; + } + } else { + if (input[0] <= -0.9842767567801477) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[213]; + } else { + var6 = params[214]; + } + } else { + if (input[6] > 1.5000000000000002) { + if (input[5] > 1.5000000000000002) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[215]; + } else { + var6 = params[216]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 1.4046572252719522) { + var6 = params[217]; + } else { + if (input[0] > 0.6208055873208026) { + var6 = params[218]; + } else { + var6 = params[219]; + } + } + } else { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[220]; + } else { + var6 = params[221]; + } + } + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[222]; + } else { + var6 = params[223]; + } + } + } + } + } + } + } + } + double var7; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 2.7958170819201564) { + if (input[2] > 4.13752641008496) { + var7 = params[224]; + } else { + var7 = params[225]; + } + } else { + var7 = params[226]; + } + } else { + var7 = params[227]; + } + } else { + var7 = params[228]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var7 = params[229]; + } else { + if (input[3] > 7.22) { + var7 = params[230]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] > 5.5550000000000015) { + var7 = params[231]; + } else { + if (input[6] > 3.5000000000000004) { + var7 = params[232]; + } else { + var7 = params[233]; + } + } + } else { + var7 = params[234]; + } + } + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var7 = params[235]; + } else { + if (input[1] <= -0.3150996155456951) { + var7 = params[236]; + } else { + var7 = params[237]; + } + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[3] <= -4.164999999999998) { + var7 = params[238]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var7 = params[239]; + } else { + var7 = params[240]; + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 4.500000000000001) { + var7 = params[241]; + } else { + var7 = params[242]; + } + } else { + var7 = params[243]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var7 = params[244]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var7 = params[245]; + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + var7 = params[246]; + } else { + var7 = params[247]; + } + } + } + } + } + } + } else { + if (input[1] > 2.0493725485847785) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var7 = params[248]; + } else { + var7 = params[249]; + } + } else { + if (input[6] > 4.500000000000001) { + var7 = params[250]; + } else { + if (input[3] <= -2.774999999999998) { + if (input[5] > 1.5000000000000002) { + var7 = params[251]; + } else { + var7 = params[252]; + } + } else { + if (input[6] > 1.5000000000000002) { + var7 = params[253]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var7 = params[254]; + } else { + var7 = params[255]; + } + } + } + } + } + } + } + } + } + double var8; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 1.4046572252719522) { + if (input[2] > 2.7958170819201564) { + var8 = params[256]; + } else { + var8 = params[257]; + } + } else { + if (input[2] > 4.13752641008496) { + var8 = params[258]; + } else { + if (input[5] > 1.5000000000000002) { + var8 = params[259]; + } else { + var8 = params[260]; + } + } + } + } else { + if (input[0] > 0.6889771560588532) { + var8 = params[261]; + } else { + var8 = params[262]; + } + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var8 = params[263]; + } else { + if (input[3] > 7.22) { + var8 = params[264]; + } else { + var8 = params[265]; + } + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + if (input[0] <= -0.7870566736799897) { + var8 = params[266]; + } else { + var8 = params[267]; + } + } else { + var8 = params[268]; + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[3] <= -4.164999999999998) { + var8 = params[269]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9224714045779462) { + var8 = params[270]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var8 = params[271]; + } else { + var8 = params[272]; + } + } + } else { + if (input[0] <= -1.060096627328628) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var8 = params[273]; + } else { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var8 = params[274]; + } else { + var8 = params[275]; + } + } + } else { + if (input[0] > 0.2796824846082225) { + var8 = params[276]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9789715763336068) { + var8 = params[277]; + } else { + var8 = params[278]; + } + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 2.5000000000000004) { + var8 = params[279]; + } else { + var8 = params[280]; + } + } else { + var8 = params[281]; + } + } + } + } + } + } + } else { + if (input[1] > 2.0493725485847785) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var8 = params[282]; + } else { + var8 = params[283]; + } + } else { + if (input[0] <= -1.0706185685476008) { + var8 = params[284]; + } else { + if (input[3] <= -2.774999999999998) { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + var8 = params[285]; + } else { + var8 = params[286]; + } + } else { + var8 = params[287]; + } + } + } + } + } + } + } + double var9; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 2.7958170819201564) { + if (input[2] > 4.13752641008496) { + var9 = params[288]; + } else { + var9 = params[289]; + } + } else { + var9 = params[290]; + } + } else { + var9 = params[291]; + } + } else { + var9 = params[292]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var9 = params[293]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] > 5.5550000000000015) { + if (input[3] > 7.22) { + var9 = params[294]; + } else { + var9 = params[295]; + } + } else { + var9 = params[296]; + } + } else { + var9 = params[297]; + } + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + if (input[1] > 2.0493725485847785) { + var9 = params[298]; + } else { + var9 = params[299]; + } + } else { + if (input[1] <= -0.3150996155456951) { + var9 = params[300]; + } else { + var9 = params[301]; + } + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[3] <= -4.164999999999998) { + var9 = params[302]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var9 = params[303]; + } else { + if (input[6] > 3.5000000000000004) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + var9 = params[304]; + } else { + var9 = params[305]; + } + } else { + if (input[3] > 5.55) { + var9 = params[306]; + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + var9 = params[307]; + } else { + var9 = params[308]; + } + } + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var9 = params[309]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var9 = params[310]; + } else { + var9 = params[311]; + } + } + } + } + } + } else { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 1.4046572252719522) { + var9 = params[312]; + } else { + var9 = params[313]; + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[5] > 1.5000000000000002) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var9 = params[314]; + } else { + var9 = params[315]; + } + } else { + var9 = params[316]; + } + } else { + if (input[6] > 1.5000000000000002) { + var9 = params[317]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var9 = params[318]; + } else { + var9 = params[319]; + } + } + } + } + } + } + } + } + double var10; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var10 = params[320]; + } else { + if (input[1] > 0.544004836887963) { + var10 = params[321]; + } else { + var10 = params[322]; + } + } + } else { + var10 = params[323]; + } + } else { + if (input[1] <= -1.1757520039296843) { + var10 = params[324]; + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var10 = params[325]; + } else { + var10 = params[326]; + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[3] <= -4.164999999999998) { + var10 = params[327]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var10 = params[328]; + } else { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -0.6288738766989617) { + if (input[5] > 1.5000000000000002) { + if (input[0] <= -0.7710085028292034) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var10 = params[329]; + } else { + var10 = params[330]; + } + } else { + var10 = params[331]; + } + } else { + var10 = params[332]; + } + } else { + var10 = params[333]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9613760611859128) { + if (input[6] > 2.5000000000000004) { + var10 = params[334]; + } else { + var10 = params[335]; + } + } else { + var10 = params[336]; + } + } else { + if (input[0] > 0.09011070331849418) { + var10 = params[337]; + } else { + var10 = params[338]; + } + } + } + } + } + } else { + if (input[0] <= -1.0706185685476008) { + if (input[6] > 2.5000000000000004) { + var10 = params[339]; + } else { + var10 = params[340]; + } + } else { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + var10 = params[341]; + } else { + if (input[6] > 4.500000000000001) { + var10 = params[342]; + } else { + if (input[3] <= -2.774999999999998) { + if (input[5] > 1.5000000000000002) { + var10 = params[343]; + } else { + var10 = params[344]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9613760611859128) { + var10 = params[345]; + } else { + if (input[1] > 0.544004836887963) { + var10 = params[346]; + } else { + if (input[0] <= -0.6870098124256391) { + var10 = params[347]; + } else { + if (input[0] <= -0.48284878490792343) { + var10 = params[348]; + } else { + var10 = params[349]; + } + } + } + } + } else { + if (input[6] > 1.5000000000000002) { + var10 = params[350]; + } else { + var10 = params[351]; + } + } + } + } + } + } + } + } + } + } + double var11; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + if (input[2] > 4.13752641008496) { + var11 = params[352]; + } else { + var11 = params[353]; + } + } else { + if (input[1] > 0.544004836887963) { + var11 = params[354]; + } else { + var11 = params[355]; + } + } + } else { + var11 = params[356]; + } + } else { + if (input[1] <= -0.7454258097376898) { + if (input[0] > 0.000000000000000000000000000000000010000000180025095) { + var11 = params[357]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] > 5.5550000000000015) { + if (input[3] > 7.22) { + var11 = params[358]; + } else { + var11 = params[359]; + } + } else { + var11 = params[360]; + } + } else { + var11 = params[361]; + } + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[1] <= -0.3150996155456951) { + var11 = params[362]; + } else { + var11 = params[363]; + } + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] <= -0.3150996155456951) { + if (input[3] <= -4.164999999999998) { + var11 = params[364]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var11 = params[365]; + } else { + if (input[0] <= -0.9789715763336068) { + if (input[6] > 2.5000000000000004) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.0706185685476008) { + var11 = params[366]; + } else { + var11 = params[367]; + } + } else { + var11 = params[368]; + } + } else { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var11 = params[369]; + } else { + var11 = params[370]; + } + } + } else { + var11 = params[371]; + } + } else { + if (input[0] > 0.01309716716954198) { + var11 = params[372]; + } else { + if (input[6] > 3.5000000000000004) { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + var11 = params[373]; + } else { + if (input[5] > 1.5000000000000002) { + var11 = params[374]; + } else { + var11 = params[375]; + } + } + } else { + var11 = params[376]; + } + } + } + } + } + } else { + if (input[0] <= -1.0706185685476008) { + if (input[6] > 2.5000000000000004) { + var11 = params[377]; + } else { + var11 = params[378]; + } + } else { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + var11 = params[379]; + } else { + if (input[6] > 4.500000000000001) { + var11 = params[380]; + } else { + if (input[3] <= -9.724999999999998) { + var11 = params[381]; + } else { + var11 = params[382]; + } + } + } + } + } + } else { + var11 = params[383]; + } + } + } + } + double var12; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 2.7958170819201564) { + var12 = params[384]; + } else { + var12 = params[385]; + } + } else { + var12 = params[386]; + } + } else { + var12 = params[387]; + } + } else { + if (input[1] <= -1.1757520039296843) { + var12 = params[388]; + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + if (input[0] <= -0.7870566736799897) { + var12 = params[389]; + } else { + var12 = params[390]; + } + } else { + var12 = params[391]; + } + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] <= -0.3150996155456951) { + if (input[3] <= -4.164999999999998) { + var12 = params[392]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var12 = params[393]; + } else { + if (input[0] <= -0.9789715763336068) { + if (input[6] > 2.5000000000000004) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + var12 = params[394]; + } else { + var12 = params[395]; + } + } else { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var12 = params[396]; + } else { + var12 = params[397]; + } + } + } else { + var12 = params[398]; + } + } else { + if (input[0] > 0.2796824846082225) { + var12 = params[399]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var12 = params[400]; + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + if (input[6] > 3.5000000000000004) { + var12 = params[401]; + } else { + var12 = params[402]; + } + } else { + var12 = params[403]; + } + } else { + var12 = params[404]; + } + } + } + } + } + } + } else { + if (input[0] <= -0.9842767567801477) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var12 = params[405]; + } else { + var12 = params[406]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 1.4046572252719522) { + if (input[3] <= -5.549999999999998) { + var12 = params[407]; + } else { + var12 = params[408]; + } + } else { + if (input[3] > 8.335000000000003) { + var12 = params[409]; + } else { + if (input[5] > 1.5000000000000002) { + var12 = params[410]; + } else { + var12 = params[411]; + } + } + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[3] <= -2.774999999999998) { + var12 = params[412]; + } else { + var12 = params[413]; + } + } else { + var12 = params[414]; + } + } + } + } + } else { + var12 = params[415]; + } + } + } + } + double var13; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var13 = params[416]; + } else { + if (input[1] > 0.544004836887963) { + var13 = params[417]; + } else { + var13 = params[418]; + } + } + } else { + var13 = params[419]; + } + } else { + if (input[1] <= -0.7454258097376898) { + var13 = params[420]; + } else { + if (input[2] > 1.4541077537553535) { + if (input[1] <= -0.3150996155456951) { + var13 = params[421]; + } else { + var13 = params[422]; + } + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9789715763336068) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 2.5000000000000004) { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.0902035263627476) { + var13 = params[423]; + } else { + if (input[0] <= -1.0189372690308816) { + var13 = params[424]; + } else { + var13 = params[425]; + } + } + } else { + var13 = params[426]; + } + } else { + var13 = params[427]; + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.0189372690308816) { + var13 = params[428]; + } else { + var13 = params[429]; + } + } else { + var13 = params[430]; + } + } + } else { + if (input[5] > 1.5000000000000002) { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var13 = params[431]; + } else { + var13 = params[432]; + } + } else { + if (input[6] > 4.500000000000001) { + var13 = params[433]; + } else { + if (input[6] > 2.5000000000000004) { + if (input[0] <= -0.23757260892951562) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var13 = params[434]; + } else { + var13 = params[435]; + } + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var13 = params[436]; + } else { + var13 = params[437]; + } + } + } else { + var13 = params[438]; + } + } + } + } else { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.3335963750119059) { + var13 = params[439]; + } else { + var13 = params[440]; + } + } else { + if (input[1] > 2.0493725485847785) { + var13 = params[441]; + } else { + if (input[3] <= -2.779999999999999) { + if (input[1] <= -0.3150996155456951) { + var13 = params[442]; + } else { + var13 = params[443]; + } + } else { + if (input[1] > 0.544004836887963) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var13 = params[444]; + } else { + var13 = params[445]; + } + } else { + var13 = params[446]; + } + } + } + } + } + } + } else { + var13 = params[447]; + } + } + } + } + double var14; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 4.13752641008496) { + var14 = params[448]; + } else { + var14 = params[449]; + } + } else { + if (input[2] > 2.7958170819201564) { + var14 = params[450]; + } else { + var14 = params[451]; + } + } + } else { + var14 = params[452]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var14 = params[453]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] > 5.5550000000000015) { + var14 = params[454]; + } else { + var14 = params[455]; + } + } else { + var14 = params[456]; + } + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var14 = params[457]; + } else { + var14 = params[458]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 2.0493725485847785) { + var14 = params[459]; + } else { + if (input[1] > 0.544004836887963) { + if (input[3] <= -11.384999999999996) { + var14 = params[460]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] <= -0.000000000000000000000000000000000010000000180025095) { + var14 = params[461]; + } else { + var14 = params[462]; + } + } else { + var14 = params[463]; + } + } + } else { + if (input[3] <= -5.555) { + var14 = params[464]; + } else { + if (input[3] > 0.000000000000000000000000000000000010000000180025095) { + var14 = params[465]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + if (input[6] > 4.500000000000001) { + var14 = params[466]; + } else { + var14 = params[467]; + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var14 = params[468]; + } else { + var14 = params[469]; + } + } + } else { + var14 = params[470]; + } + } else { + var14 = params[471]; + } + } + } + } + } + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var14 = params[472]; + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 4.500000000000001) { + var14 = params[473]; + } else { + if (input[3] <= -5.555) { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + var14 = params[474]; + } else { + var14 = params[475]; + } + } else { + if (input[6] > 2.5000000000000004) { + var14 = params[476]; + } else { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var14 = params[477]; + } else { + var14 = params[478]; + } + } + } + } + } else { + var14 = params[479]; + } + } + } + } + } + } + double var15; + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.3035336858148408) { + if (input[6] > 2.5000000000000004) { + if (input[1] > 2.0493725485847785) { + var15 = params[480]; + } else { + if (input[0] <= -0.9880345929297808) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -1.0189372690308816) { + if (input[0] <= -1.0706185685476008) { + var15 = params[481]; + } else { + var15 = params[482]; + } + } else { + var15 = params[483]; + } + } else { + var15 = params[484]; + } + } else { + if (input[2] > 2.7958170819201564) { + var15 = params[485]; + } else { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -0.9447089526163635) { + var15 = params[486]; + } else { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var15 = params[487]; + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var15 = params[488]; + } else { + var15 = params[489]; + } + } + } + } else { + if (input[0] <= -0.415915091607399) { + var15 = params[490]; + } else { + var15 = params[491]; + } + } + } + } + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var15 = params[492]; + } else { + var15 = params[493]; + } + } else { + if (input[0] <= -0.8207887793525789) { + var15 = params[494]; + } else { + var15 = params[495]; + } + } + } + } else { + if (input[2] > 2.7958170819201564) { + if (input[2] > 4.13752641008496) { + var15 = params[496]; + } else { + var15 = params[497]; + } + } else { + if (input[0] > 0.784160935237208) { + var15 = params[498]; + } else { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + var15 = params[499]; + } else { + var15 = params[500]; + } + } else { + if (input[3] <= -5.555) { + var15 = params[501]; + } else { + var15 = params[502]; + } + } + } + } + } + } else { + if (input[1] <= -0.7454258097376898) { + var15 = params[503]; + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 2.5000000000000004) { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var15 = params[504]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var15 = params[505]; + } else { + if (input[3] <= -2.779999999999999) { + var15 = params[506]; + } else { + if (input[0] <= -0.9842767567801477) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var15 = params[507]; + } else { + var15 = params[508]; + } + } else { + var15 = params[509]; + } + } + } + } + } else { + var15 = params[510]; + } + } else { + var15 = params[511]; + } + } + } + double var16; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 4.13752641008496) { + var16 = params[512]; + } else { + var16 = params[513]; + } + } else { + var16 = params[514]; + } + } else { + var16 = params[515]; + } + } else { + if (input[1] <= -1.1757520039296843) { + var16 = params[516]; + } else { + if (input[2] > 1.4541077537553535) { + if (input[0] <= -1.0189372690308816) { + var16 = params[517]; + } else { + if (input[2] > 2.7958170819201564) { + var16 = params[518]; + } else { + var16 = params[519]; + } + } + } else { + if (input[0] <= -0.9789715763336068) { + if (input[6] > 2.5000000000000004) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.0902035263627476) { + var16 = params[520]; + } else { + if (input[0] <= -1.0189372690308816) { + var16 = params[521]; + } else { + var16 = params[522]; + } + } + } else { + var16 = params[523]; + } + } else { + var16 = params[524]; + } + } else { + var16 = params[525]; + } + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] > 0.000000000000000000000000000000000010000000180025095) { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var16 = params[526]; + } else { + var16 = params[527]; + } + } else { + var16 = params[528]; + } + } else { + if (input[6] > 4.500000000000001) { + var16 = params[529]; + } else { + if (input[6] > 2.5000000000000004) { + if (input[0] <= -0.23757260892951562) { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var16 = params[530]; + } else { + var16 = params[531]; + } + } else { + var16 = params[532]; + } + } else { + var16 = params[533]; + } + } + } + } else { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.5112757101339717) { + var16 = params[534]; + } else { + var16 = params[535]; + } + } else { + if (input[1] > 1.4046572252719522) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] <= -5.549999999999998) { + var16 = params[536]; + } else { + var16 = params[537]; + } + } else { + var16 = params[538]; + } + } else { + if (input[3] <= -5.555) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var16 = params[539]; + } else { + var16 = params[540]; + } + } else { + if (input[0] > 0.33507741043752043) { + var16 = params[541]; + } else { + var16 = params[542]; + } + } + } + } + } + } else { + var16 = params[543]; + } + } + } + } + } + double var17; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var17 = params[544]; + } else { + if (input[0] <= -0.3335963750119059) { + if (input[6] > 3.5000000000000004) { + var17 = params[545]; + } else { + var17 = params[546]; + } + } else { + var17 = params[547]; + } + } + } else { + if (input[0] > 0.6889771560588532) { + var17 = params[548]; + } else { + var17 = params[549]; + } + } + } else { + if (input[1] <= -0.7454258097376898) { + if (input[0] > 0.01309716716954198) { + var17 = params[550]; + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] > 5.5550000000000015) { + if (input[3] > 7.22) { + var17 = params[551]; + } else { + var17 = params[552]; + } + } else { + var17 = params[553]; + } + } else { + var17 = params[554]; + } + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[0] <= -1.0189372690308816) { + var17 = params[555]; + } else { + if (input[2] > 2.7958170819201564) { + var17 = params[556]; + } else { + var17 = params[557]; + } + } + } else { + if (input[0] <= -0.9789715763336068) { + if (input[6] > 2.5000000000000004) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.0902035263627476) { + var17 = params[558]; + } else { + if (input[0] <= -1.0298570987833446) { + var17 = params[559]; + } else { + var17 = params[560]; + } + } + } else { + var17 = params[561]; + } + } else { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var17 = params[562]; + } else { + var17 = params[563]; + } + } + } else { + var17 = params[564]; + } + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] <= -0.3150996155456951) { + if (input[3] <= -4.164999999999998) { + var17 = params[565]; + } else { + if (input[0] > 0.01309716716954198) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var17 = params[566]; + } else { + var17 = params[567]; + } + } else { + var17 = params[568]; + } + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] > 1.4046572252719522) { + if (input[3] <= -5.549999999999998) { + var17 = params[569]; + } else { + var17 = params[570]; + } + } else { + if (input[3] > 8.335000000000003) { + var17 = params[571]; + } else { + if (input[5] > 1.5000000000000002) { + var17 = params[572]; + } else { + var17 = params[573]; + } + } + } + } else { + var17 = params[574]; + } + } + } else { + var17 = params[575]; + } + } + } + } + } + double var18; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 4.13752641008496) { + var18 = params[576]; + } else { + var18 = params[577]; + } + } else { + var18 = params[578]; + } + } else { + var18 = params[579]; + } + } else { + if (input[1] <= -0.7454258097376898) { + if (input[0] <= -0.16170852854398074) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] > 5.5550000000000015) { + if (input[3] > 7.22) { + var18 = params[580]; + } else { + var18 = params[581]; + } + } else { + var18 = params[582]; + } + } else { + var18 = params[583]; + } + } else { + var18 = params[584]; + } + } else { + if (input[2] > 1.4541077537553535) { + if (input[1] <= -0.3150996155456951) { + var18 = params[585]; + } else { + var18 = params[586]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -1.0706185685476008) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var18 = params[587]; + } else { + var18 = params[588]; + } + } else { + if (input[1] > 1.4046572252719522) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] <= -5.835) { + var18 = params[589]; + } else { + var18 = params[590]; + } + } else { + var18 = params[591]; + } + } else { + if (input[3] <= -5.555) { + var18 = params[592]; + } else { + if (input[3] > 12.774999999999997) { + var18 = params[593]; + } else { + var18 = params[594]; + } + } + } + } + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var18 = params[595]; + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -0.6928455109168341) { + if (input[6] > 4.500000000000001) { + var18 = params[596]; + } else { + var18 = params[597]; + } + } else { + var18 = params[598]; + } + } else { + if (input[0] <= -1.1469247473036808) { + var18 = params[599]; + } else { + if (input[1] <= -0.3150996155456951) { + if (input[3] <= -0.000000000000000000000000000000000010000000180025095) { + var18 = params[600]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var18 = params[601]; + } else { + if (input[0] <= -0.3035336858148408) { + var18 = params[602]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var18 = params[603]; + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + var18 = params[604]; + } else { + var18 = params[605]; + } + } + } + } + } + } else { + var18 = params[606]; + } + } + } + } else { + var18 = params[607]; + } + } + } + } + } + } + double var19; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var19 = params[608]; + } else { + if (input[1] > 0.544004836887963) { + var19 = params[609]; + } else { + if (input[5] > 1.5000000000000002) { + var19 = params[610]; + } else { + if (input[0] > 0.18878705962415496) { + var19 = params[611]; + } else { + if (input[6] > 3.5000000000000004) { + if (input[6] > 5.500000000000001) { + var19 = params[612]; + } else { + var19 = params[613]; + } + } else { + var19 = params[614]; + } + } + } + } + } + } else { + var19 = params[615]; + } + } else { + if (input[1] <= -0.7454258097376898) { + var19 = params[616]; + } else { + if (input[2] > 1.4541077537553535) { + if (input[0] <= -1.0189372690308816) { + var19 = params[617]; + } else { + if (input[2] > 2.7958170819201564) { + var19 = params[618]; + } else { + var19 = params[619]; + } + } + } else { + if (input[0] <= -0.9789715763336068) { + if (input[6] > 2.5000000000000004) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.0902035263627476) { + var19 = params[620]; + } else { + if (input[0] <= -1.0298570987833446) { + var19 = params[621]; + } else { + var19 = params[622]; + } + } + } else { + var19 = params[623]; + } + } else { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var19 = params[624]; + } else { + var19 = params[625]; + } + } + } else { + var19 = params[626]; + } + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var19 = params[627]; + } else { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + var19 = params[628]; + } else { + if (input[6] > 2.5000000000000004) { + if (input[0] <= -0.6870098124256391) { + if (input[6] > 3.5000000000000004) { + var19 = params[629]; + } else { + var19 = params[630]; + } + } else { + var19 = params[631]; + } + } else { + var19 = params[632]; + } + } + } + } else { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.3335963750119059) { + var19 = params[633]; + } else { + var19 = params[634]; + } + } else { + if (input[3] <= -2.779999999999999) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + var19 = params[635]; + } else { + var19 = params[636]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var19 = params[637]; + } else { + var19 = params[638]; + } + } + } + } + } else { + var19 = params[639]; + } + } + } + } + } + double var20; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[0] > 0.03758941689773911) { + if (input[6] > 3.5000000000000004) { + var20 = params[640]; + } else { + var20 = params[641]; + } + } else { + var20 = params[642]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[0] <= -0.8365274813439836) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var20 = params[643]; + } else { + if (input[0] <= -1.013587878747286) { + var20 = params[644]; + } else { + if (input[3] > 5.5550000000000015) { + var20 = params[645]; + } else { + if (input[5] > 1.5000000000000002) { + var20 = params[646]; + } else { + var20 = params[647]; + } + } + } + } + } else { + if (input[0] <= -0.51861454308502) { + if (input[0] <= -0.8148646611872749) { + var20 = params[648]; + } else { + var20 = params[649]; + } + } else { + var20 = params[650]; + } + } + } else { + if (input[2] > 1.4541077537553535) { + var20 = params[651]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -1.001120704697915) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -1.0244634986626948) { + if (input[0] <= -1.0706185685476008) { + var20 = params[652]; + } else { + var20 = params[653]; + } + } else { + var20 = params[654]; + } + } else { + if (input[3] <= -5.555) { + var20 = params[655]; + } else { + var20 = params[656]; + } + } + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var20 = params[657]; + } else { + if (input[1] > 2.0493725485847785) { + var20 = params[658]; + } else { + var20 = params[659]; + } + } + } + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var20 = params[660]; + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -0.9842767567801477) { + var20 = params[661]; + } else { + var20 = params[662]; + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var20 = params[663]; + } else { + if (input[0] <= -1.0806984113960285) { + var20 = params[664]; + } else { + if (input[3] <= -0.000000000000000000000000000000000010000000180025095) { + var20 = params[665]; + } else { + if (input[0] <= -0.3816082580531011) { + var20 = params[666]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var20 = params[667]; + } else { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + var20 = params[668]; + } else { + var20 = params[669]; + } + } + } + } + } + } + } else { + var20 = params[670]; + } + } + } else { + var20 = params[671]; + } + } + } + } + } + } + double var21; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.3035336858148408) { + var21 = params[672]; + } else { + if (input[2] > 1.4541077537553535) { + var21 = params[673]; + } else { + var21 = params[674]; + } + } + } else { + if (input[1] <= -0.7454258097376898) { + if (input[0] <= -0.8365274813439836) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var21 = params[675]; + } else { + if (input[0] <= -1.013587878747286) { + var21 = params[676]; + } else { + var21 = params[677]; + } + } + } else { + if (input[0] <= -0.3553918246797782) { + var21 = params[678]; + } else { + var21 = params[679]; + } + } + } else { + if (input[2] > 1.4541077537553535) { + var21 = params[680]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] <= -11.384999999999996) { + var21 = params[681]; + } else { + if (input[1] > 0.544004836887963) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.7289649477903667) { + var21 = params[682]; + } else { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + var21 = params[683]; + } else { + if (input[0] > 1.2557472670976397) { + var21 = params[684]; + } else { + var21 = params[685]; + } + } + } + } else { + var21 = params[686]; + } + } else { + if (input[0] <= -1.0706185685476008) { + if (input[0] <= -1.0806984113960285) { + var21 = params[687]; + } else { + var21 = params[688]; + } + } else { + if (input[0] <= -1.060096627328628) { + var21 = params[689]; + } else { + if (input[3] <= -5.555) { + var21 = params[690]; + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var21 = params[691]; + } else { + if (input[3] > 7.22) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] > 0.49078445654349595) { + var21 = params[692]; + } else { + var21 = params[693]; + } + } else { + var21 = params[694]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] > 2.8144092822913573) { + var21 = params[695]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var21 = params[696]; + } else { + var21 = params[697]; + } + } + } else { + var21 = params[698]; + } + } + } + } else { + var21 = params[699]; + } + } + } + } + } + } + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var21 = params[700]; + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -1.060096627328628) { + var21 = params[701]; + } else { + var21 = params[702]; + } + } else { + var21 = params[703]; + } + } + } + } + } + } + double var22; + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.3335963750119059) { + if (input[3] > 7.22) { + if (input[5] > 1.5000000000000002) { + var22 = params[704]; + } else { + var22 = params[705]; + } + } else { + if (input[1] > 2.0493725485847785) { + var22 = params[706]; + } else { + if (input[1] <= -1.1757520039296843) { + var22 = params[707]; + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 2.7958170819201564) { + var22 = params[708]; + } else { + var22 = params[709]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var22 = params[710]; + } else { + if (input[6] > 4.500000000000001) { + var22 = params[711]; + } else { + var22 = params[712]; + } + } + } + } + } + } + } else { + if (input[2] > 4.13752641008496) { + var22 = params[713]; + } else { + if (input[2] > 2.7958170819201564) { + var22 = params[714]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 5.500000000000001) { + var22 = params[715]; + } else { + var22 = params[716]; + } + } else { + var22 = params[717]; + } + } else { + var22 = params[718]; + } + } + } + } + } else { + if (input[1] <= -0.7454258097376898) { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var22 = params[719]; + } else { + if (input[0] <= -0.8480220389781555) { + if (input[3] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9505446511075585) { + var22 = params[720]; + } else { + var22 = params[721]; + } + } else { + if (input[5] > 1.5000000000000002) { + var22 = params[722]; + } else { + var22 = params[723]; + } + } + } else { + if (input[0] <= -0.51861454308502) { + var22 = params[724]; + } else { + var22 = params[725]; + } + } + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + var22 = params[726]; + } else { + var22 = params[727]; + } + } else { + if (input[0] <= -0.9842767567801477) { + var22 = params[728]; + } else { + if (input[3] <= -2.774999999999998) { + var22 = params[729]; + } else { + var22 = params[730]; + } + } + } + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var22 = params[731]; + } else { + var22 = params[732]; + } + } else { + if (input[3] <= -5.549999999999998) { + var22 = params[733]; + } else { + var22 = params[734]; + } + } + } else { + var22 = params[735]; + } + } + } + } + double var23; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[0] > 0.25969963825958503) { + var23 = params[736]; + } else { + if (input[1] > 2.0493725485847785) { + var23 = params[737]; + } else { + var23 = params[738]; + } + } + } else { + if (input[1] <= -0.7454258097376898) { + if (input[0] <= -1.013587878747286) { + var23 = params[739]; + } else { + if (input[0] <= -0.15330865950362435) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.7813093948629036) { + var23 = params[740]; + } else { + var23 = params[741]; + } + } else { + if (input[3] > 5.5550000000000015) { + if (input[0] <= -0.34774352286934845) { + var23 = params[742]; + } else { + var23 = params[743]; + } + } else { + var23 = params[744]; + } + } + } else { + var23 = params[745]; + } + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + var23 = params[746]; + } else { + if (input[3] > 5.55) { + var23 = params[747]; + } else { + var23 = params[748]; + } + } + } else { + if (input[3] > 2.7749999999999995) { + if (input[0] > 0.5330048509305506) { + var23 = params[749]; + } else { + var23 = params[750]; + } + } else { + if (input[0] <= -0.6036300597408378) { + if (input[1] <= -0.3150996155456951) { + var23 = params[751]; + } else { + if (input[6] > 4.500000000000001) { + var23 = params[752]; + } else { + if (input[0] <= -0.9880345929297808) { + var23 = params[753]; + } else { + var23 = params[754]; + } + } + } + } else { + if (input[0] > 2.8869134150607496) { + var23 = params[755]; + } else { + var23 = params[756]; + } + } + } + } + } else { + if (input[0] <= -1.0706185685476008) { + if (input[0] <= -1.0806984113960285) { + var23 = params[757]; + } else { + var23 = params[758]; + } + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] <= -5.549999999999998) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9447089526163635) { + var23 = params[759]; + } else { + var23 = params[760]; + } + } else { + if (input[0] > 0.348030892694491) { + var23 = params[761]; + } else { + var23 = params[762]; + } + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[0] > 0.12556699263620927) { + var23 = params[763]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var23 = params[764]; + } else { + var23 = params[765]; + } + } + } else { + var23 = params[766]; + } + } + } else { + var23 = params[767]; + } + } + } + } + } + double var24; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + var24 = params[768]; + } else { + var24 = params[769]; + } + } else { + if (input[1] <= -0.7454258097376898) { + var24 = params[770]; + } else { + if (input[6] > 4.500000000000001) { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + var24 = params[771]; + } else { + if (input[1] <= -0.3150996155456951) { + if (input[0] <= -0.2667511013854906) { + if (input[0] <= -0.5986785579907331) { + var24 = params[772]; + } else { + var24 = params[773]; + } + } else { + var24 = params[774]; + } + } else { + if (input[0] <= -0.8628323343914156) { + var24 = params[775]; + } else { + var24 = params[776]; + } + } + } + } else { + if (input[0] <= -0.7710085028292034) { + var24 = params[777]; + } else { + var24 = params[778]; + } + } + } else { + if (input[0] <= -1.0706185685476008) { + var24 = params[779]; + } else { + if (input[3] <= -5.555) { + if (input[1] > 0.544004836887963) { + var24 = params[780]; + } else { + var24 = params[781]; + } + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[1] <= -0.3150996155456951) { + if (input[3] > 5.55) { + var24 = params[782]; + } else { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + var24 = params[783]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var24 = params[784]; + } else { + if (input[0] <= -0.938386945917569) { + var24 = params[785]; + } else { + var24 = params[786]; + } + } + } else { + if (input[0] <= -0.6791404614299368) { + if (input[6] > 3.5000000000000004) { + if (input[5] > 1.5000000000000002) { + if (input[5] > 2.5000000000000004) { + var24 = params[787]; + } else { + var24 = params[788]; + } + } else { + if (input[0] <= -0.7870566736799897) { + if (input[0] <= -0.9673001793512168) { + var24 = params[789]; + } else { + var24 = params[790]; + } + } else { + var24 = params[791]; + } + } + } else { + if (input[0] <= -1.0491767975761646) { + var24 = params[792]; + } else { + var24 = params[793]; + } + } + } else { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var24 = params[794]; + } else { + if (input[0] <= -0.6036300597408378) { + var24 = params[795]; + } else { + if (input[0] <= -0.524803920272651) { + var24 = params[796]; + } else { + var24 = params[797]; + } + } + } + } + } + } + } + } else { + var24 = params[798]; + } + } else { + var24 = params[799]; + } + } + } + } + } + } + double var25; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[2] > 4.13752641008496) { + var25 = params[800]; + } else { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + var25 = params[801]; + } else { + var25 = params[802]; + } + } + } else { + if (input[0] > 2.022478471133964) { + var25 = params[803]; + } else { + var25 = params[804]; + } + } + } else { + if (input[1] <= -0.7454258097376898) { + if (input[3] > 5.5550000000000015) { + if (input[0] <= -0.34774352286934845) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] > 7.22) { + var25 = params[805]; + } else { + var25 = params[806]; + } + } else { + var25 = params[807]; + } + } else { + var25 = params[808]; + } + } else { + if (input[3] > 0.000000000000000000000000000000000010000000180025095) { + var25 = params[809]; + } else { + if (input[5] > 1.5000000000000002) { + var25 = params[810]; + } else { + var25 = params[811]; + } + } + } + } else { + if (input[2] > 1.4541077537553535) { + var25 = params[812]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] <= -11.384999999999996) { + if (input[0] > 0.8038343127264639) { + var25 = params[813]; + } else { + var25 = params[814]; + } + } else { + if (input[1] > 1.4046572252719522) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.634223266982557) { + var25 = params[815]; + } else { + if (input[12] > 0.000000000000000000000000000000000010000000180025095) { + var25 = params[816]; + } else { + var25 = params[817]; + } + } + } else { + var25 = params[818]; + } + } else { + if (input[3] > 12.774999999999997) { + var25 = params[819]; + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + var25 = params[820]; + } else { + var25 = params[821]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var25 = params[822]; + } else { + var25 = params[823]; + } + } + } + } + } + } else { + if (input[7] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9224714045779462) { + var25 = params[824]; + } else { + if (input[0] <= -0.6537640149606494) { + var25 = params[825]; + } else { + var25 = params[826]; + } + } + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9163704470644242) { + var25 = params[827]; + } else { + var25 = params[828]; + } + } else { + if (input[0] <= -1.0902035263627476) { + var25 = params[829]; + } else { + var25 = params[830]; + } + } + } else { + var25 = params[831]; + } + } + } + } + } + } + double var26; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[2] > 4.13752641008496) { + var26 = params[832]; + } else { + if (input[1] > 0.544004836887963) { + var26 = params[833]; + } else { + if (input[5] > 1.5000000000000002) { + if (input[0] <= -0.17094838448837282) { + var26 = params[834]; + } else { + var26 = params[835]; + } + } else { + if (input[6] > 4.500000000000001) { + if (input[0] <= -0.6928455109168341) { + var26 = params[836]; + } else { + var26 = params[837]; + } + } else { + if (input[0] > 0.25969963825958503) { + var26 = params[838]; + } else { + if (input[0] <= -0.8365274813439836) { + var26 = params[839]; + } else { + var26 = params[840]; + } + } + } + } + } + } + } else { + if (input[0] > 2.022478471133964) { + var26 = params[841]; + } else { + var26 = params[842]; + } + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var26 = params[843]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.524803920272651) { + var26 = params[844]; + } else { + var26 = params[845]; + } + } else { + var26 = params[846]; + } + } + } else { + if (input[2] > 1.4541077537553535) { + var26 = params[847]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + var26 = params[848]; + } else { + var26 = params[849]; + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var26 = params[850]; + } else { + if (input[0] <= -1.0341896628146865) { + var26 = params[851]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var26 = params[852]; + } else { + var26 = params[853]; + } + } + } + } else { + if (input[6] > 4.500000000000001) { + if (input[0] <= -0.8577039932930927) { + var26 = params[854]; + } else { + if (input[0] <= -0.3553918246797782) { + var26 = params[855]; + } else { + var26 = params[856]; + } + } + } else { + var26 = params[857]; + } + } + } else { + if (input[5] > 2.5000000000000004) { + var26 = params[858]; + } else { + if (input[0] <= -1.1469247473036808) { + var26 = params[859]; + } else { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var26 = params[860]; + } else { + var26 = params[861]; + } + } else { + var26 = params[862]; + } + } else { + var26 = params[863]; + } + } + } + } + } + } + } + } + double var27; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[2] > 2.7958170819201564) { + var27 = params[864]; + } else { + if (input[0] <= -0.3335963750119059) { + var27 = params[865]; + } else { + var27 = params[866]; + } + } + } else { + var27 = params[867]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var27 = params[868]; + } else { + var27 = params[869]; + } + } else { + if (input[2] > 2.7958170819201564) { + if (input[0] <= -0.7870566736799897) { + var27 = params[870]; + } else { + var27 = params[871]; + } + } else { + if (input[0] <= -0.9789715763336068) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -1.0298570987833446) { + if (input[0] <= -1.0706185685476008) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + var27 = params[872]; + } else { + if (input[0] <= -1.1261461238880623) { + var27 = params[873]; + } else { + var27 = params[874]; + } + } + } else { + var27 = params[875]; + } + } else { + if (input[0] <= -0.9943123897915209) { + var27 = params[876]; + } else { + var27 = params[877]; + } + } + } else { + if (input[0] <= -0.9943123897915209) { + var27 = params[878]; + } else { + var27 = params[879]; + } + } + } else { + if (input[5] > 0.000000000000000000000000000000000010000000180025095) { + if (input[3] <= -5.549999999999998) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + var27 = params[880]; + } else { + var27 = params[881]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var27 = params[882]; + } else { + var27 = params[883]; + } + } + } else { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + var27 = params[884]; + } else { + if (input[0] > 1.6078786192367922) { + if (input[1] > 1.4046572252719522) { + var27 = params[885]; + } else { + var27 = params[886]; + } + } else { + if (input[3] > 2.7749999999999995) { + var27 = params[887]; + } else { + if (input[0] <= -0.4675079714500093) { + if (input[0] <= -0.7639349289004822) { + var27 = params[888]; + } else { + var27 = params[889]; + } + } else { + if (input[0] <= -0.13774679686043764) { + var27 = params[890]; + } else { + var27 = params[891]; + } + } + } + } + } + } else { + var27 = params[892]; + } + } else { + if (input[0] > 0.2796824846082225) { + var27 = params[893]; + } else { + var27 = params[894]; + } + } + } + } else { + var27 = params[895]; + } + } + } + } + } + double var28; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[2] > 1.4541077537553535) { + if (input[2] > 4.13752641008496) { + var28 = params[896]; + } else { + if (input[3] <= -0.000000000000000000000000000000000010000000180025095) { + var28 = params[897]; + } else { + var28 = params[898]; + } + } + } else { + if (input[0] > 2.276552404686219) { + var28 = params[899]; + } else { + var28 = params[900]; + } + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var28 = params[901]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.524803920272651) { + var28 = params[902]; + } else { + var28 = params[903]; + } + } else { + if (input[3] > 7.22) { + var28 = params[904]; + } else { + if (input[5] > 1.5000000000000002) { + if (input[3] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9114631551513738) { + var28 = params[905]; + } else { + var28 = params[906]; + } + } else { + var28 = params[907]; + } + } else { + if (input[3] > 5.5550000000000015) { + var28 = params[908]; + } else { + var28 = params[909]; + } + } + } + } + } + } else { + if (input[2] > 2.7958170819201564) { + if (input[0] <= -0.7870566736799897) { + var28 = params[910]; + } else { + var28 = params[911]; + } + } else { + if (input[6] > 4.500000000000001) { + if (input[8] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + var28 = params[912]; + } else { + if (input[1] <= -0.3150996155456951) { + if (input[0] <= -0.2667511013854906) { + if (input[0] <= -0.5986785579907331) { + var28 = params[913]; + } else { + var28 = params[914]; + } + } else { + var28 = params[915]; + } + } else { + var28 = params[916]; + } + } + } else { + var28 = params[917]; + } + } else { + if (input[3] <= -5.549999999999998) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + var28 = params[918]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var28 = params[919]; + } else { + var28 = params[920]; + } + } + } else { + if (input[1] > 0.544004836887963) { + var28 = params[921]; + } else { + if (input[0] <= -1.0706185685476008) { + if (input[1] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -1.101034936441102) { + var28 = params[922]; + } else { + var28 = params[923]; + } + } else { + var28 = params[924]; + } + } else { + if (input[0] > 0.12556699263620927) { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var28 = params[925]; + } else { + var28 = params[926]; + } + } else { + var28 = params[927]; + } + } + } + } + } + } + } + } + double var29; + if (input[4] <= -0.000000000000000000000000000000000010000000180025095) { + if (input[0] > 0.25969963825958503) { + var29 = params[928]; + } else { + var29 = params[929]; + } + } else { + if (input[1] <= -1.1757520039296843) { + if (input[3] > 5.5550000000000015) { + if (input[0] <= -0.415915091607399) { + if (input[3] > 9.725000000000003) { + var29 = params[930]; + } else { + if (input[0] <= -0.9842767567801477) { + var29 = params[931]; + } else { + if (input[0] <= -0.794837605001583) { + var29 = params[932]; + } else { + var29 = params[933]; + } + } + } + } else { + var29 = params[934]; + } + } else { + if (input[3] > 0.000000000000000000000000000000000010000000180025095) { + var29 = params[935]; + } else { + if (input[5] > 1.5000000000000002) { + var29 = params[936]; + } else { + var29 = params[937]; + } + } + } + } else { + if (input[2] > 1.4541077537553535) { + var29 = params[938]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + var29 = params[939]; + } else { + var29 = params[940]; + } + } else { + if (input[1] <= -0.3150996155456951) { + if (input[9] > 0.000000000000000000000000000000000010000000180025095) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + var29 = params[941]; + } else { + if (input[0] <= -1.0244634986626948) { + var29 = params[942]; + } else { + var29 = params[943]; + } + } + } else { + if (input[3] > 5.55) { + if (input[13] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.8098689496001155) { + var29 = params[944]; + } else { + var29 = params[945]; + } + } else { + var29 = params[946]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + if (input[0] <= -0.775075807838218) { + var29 = params[947]; + } else { + var29 = params[948]; + } + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.8098689496001155) { + if (input[0] <= -0.9943123897915209) { + var29 = params[949]; + } else { + var29 = params[950]; + } + } else { + if (input[0] <= -0.6288738766989617) { + var29 = params[951]; + } else { + if (input[0] <= -0.5036274083235419) { + var29 = params[952]; + } else { + if (input[0] > 0.734513288224996) { + var29 = params[953]; + } else { + if (input[0] > 0.1583706917306538) { + var29 = params[954]; + } else { + if (input[0] <= -0.3335963750119059) { + var29 = params[955]; + } else { + var29 = params[956]; + } + } + } + } + } + } + } else { + var29 = params[957]; + } + } + } else { + var29 = params[958]; + } + } + } + } else { + var29 = params[959]; + } + } + } + } + } + return var0 + var1 + var2 + var3 + var4 + var5 + var6 + var7 + var8 + var9 + var10 + var11 + var12 + var13 + var14 + var15 + var16 + var17 + var18 + var19 + var20 + var21 + var22 + var23 + var24 + var25 + var26 + var27 + var28 + var29; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_right_before_left.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_right_before_left.java new file mode 100644 index 00000000000..11c1b41186d --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_right_before_left.java @@ -0,0 +1,51 @@ +package org.matsim.application.prepare.network.params.ref; +import org.matsim.application.prepare.network.params.FeatureRegressor; +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; + +/** +* Generated model, do not modify. +*/ +final class GermanyNetworkParams_capacity_right_before_left implements FeatureRegressor { + + public static GermanyNetworkParams_capacity_right_before_left INSTANCE = new GermanyNetworkParams_capacity_right_before_left(); + public static final double[] DEFAULT_PARAMS = {}; + + @Override + public double predict(Object2DoubleMap ft) { + return predict(ft, DEFAULT_PARAMS); + } + + @Override + public double[] getData(Object2DoubleMap ft) { + double[] data = new double[14]; + data[0] = (ft.getDouble("length") - 126.5781093424676) / 82.93604475431307; + data[1] = (ft.getDouble("speed") - 8.347924642353416) / 0.2530674029724574; + data[2] = (ft.getDouble("num_lanes") - 1.0161192826919203) / 0.1410293306032409; + data[3] = ft.getDouble("change_speed"); + data[4] = ft.getDouble("change_num_lanes"); + data[5] = ft.getDouble("num_to_links"); + data[6] = ft.getDouble("junction_inc_lanes"); + data[7] = ft.getDouble("priority_lower"); + data[8] = ft.getDouble("priority_equal"); + data[9] = ft.getDouble("priority_higher"); + data[10] = ft.getDouble("is_secondary_or_higher"); + data[11] = ft.getDouble("is_primary_or_higher"); + data[12] = ft.getDouble("is_motorway"); + data[13] = ft.getDouble("is_link"); + + return data; + } + + @Override + public double predict(Object2DoubleMap ft, double[] params) { + + double[] data = getData(ft); + for (int i = 0; i < data.length; i++) + if (Double.isNaN(data[i])) throw new IllegalArgumentException("Invalid data at index: " + i); + + return score(data, params); + } + public static double score(double[] input, double[] params) { + return 820.7862981813687 + input[0] * -2.2407160935169324 + input[1] * -1.0312478382897772 + input[2] * -65.10322048874464 + input[3] * -3.7672954706609025 + input[4] * 91.56185003046016 + input[5] * 8.354883935056996 + input[6] * -16.573320689701585 + input[7] * 1.3872614339054785 + input[8] * 798.9462847274731 + input[9] * 20.45275201994965 + input[10] * 12.054157458777055 + input[11] * -11.583879746981143 + input[12] * -1.4911083760151145 + input[13] * 15.111478746337356; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_traffic_light.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_traffic_light.java new file mode 100644 index 00000000000..6810cd54109 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_capacity_traffic_light.java @@ -0,0 +1,1747 @@ +package org.matsim.application.prepare.network.params.ref; +import org.matsim.application.prepare.network.params.FeatureRegressor; +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; + +/** +* Generated model, do not modify. +*/ +final class GermanyNetworkParams_capacity_traffic_light implements FeatureRegressor { + + public static GermanyNetworkParams_capacity_traffic_light INSTANCE = new GermanyNetworkParams_capacity_traffic_light(); + public static final double[] DEFAULT_PARAMS = {615.49475, 555.2296, 403.64377, 512.5417, 661.32526, 776.8592, 307.94974, 579.0987, 351.24344, 422.79248, 382.6958, 493.21002, 604.71576, 711.4676, 432.66574, 576.4394, 65.18873, -47.093124, 168.29794, 107.08128, 243.5391, 348.37152, 63.15197, 157.08269, 316.79657, 387.24396, 182.98808, 319.41205, 270.38162, 357.83185, 267.3479, 333.61728, 148.07251, 177.21588, 249.219, 155.23297, 118.858284, 173.88063, 126.52623, -24.637136, 16.66276, 56.981136, -81.52849, -7.1707215, 9.567015, -21.692072, -63.04734, -129.19891, 79.595566, 134.95496, 86.61436, 45.112183, -86.80803, 116.523636, 176.37932, 92.327934, 72.63386, 159.7371, 21.352165, -28.561874, -63.79159, 16.319218, -56.681995, -18.979984, 52.656525, 101.28996, -0.20502506, 69.61571, 33.462482, -65.63418, -68.76875, 48.720375, 23.87262, -17.97695, 62.186214, -9.389751, -5.4268684, -112.2844, 31.694218, 9.407171, -22.371742, 12.499399, 45.16506, 6.938427, -173.38019, 43.91622, 17.05614, -51.214798, -26.926168, -73.75736, -65.82583, 44.535336, 67.0273, 22.328768, 20.755566, -34.31819, 24.89524, -120.450294, -16.83533, 9.439478, -3.2446234, -139.10558, -4.885112, -73.83486, -105.620186, -33.20488, 28.100395, 7.387344, 34.008724, -37.129234, 1.1639067, -48.699387, -144.18034, -10.493104, 14.687679, -12.55395, -150.10774, 73.44105, -79.41268, 17.903439, -62.17122, 21.784134, 6.881216, -36.80274, 24.643566, -165.61743, 31.753023, 5.519214, 31.839605, -2.267683, -307.40558, -17.42233, -21.832182, 0.88072836, 29.75676, 1.7219872, 13.106872, -40.675232, -16.166363, 13.627753, 6.6565485, -103.0756, -28.808006, 110.27433, -35.767406, 2.9878566, -14.317886, -116.920265, 3.4358, -91.6584, 143.51192, 44.472115, -154.778, -81.63228, 57.86223, -52.41524, -62.078373, 17.617413, 127.360306, 21.375433, -8.385985, -22.935337, 48.906567, -34.74683, 3.9749646, -55.860897, 1.2457579, -30.196217, -1.5732583, -26.041641, -58.08545, 17.769197, -4.349664, -13.307687, 3.280725, -181.25356, -132.75182, 151.12465, -1.5777951, -16.651737, 90.23882, -15.37349, 13.606266, -91.40819, -41.258648, -180.38171, -19.271168, 1.0529263, -4.048095, 23.175564, -156.65048, -16.262281, 0.9099455, -44.414482, -99.75218, 99.07861, -6.1669326, 23.30339, -8.069562, 3.1905315, 105.503, 10.885436, 0.2122908, -3.832464, -28.705606, -104.79665, -15.315421, -138.83813, -0.05046561, 22.144823, -96.42455, -0.55342764, -51.706005, -133.55592, -45.583202, -2.5133393, 22.807049, -43.28402, 75.72772, 17.254173, -20.209124, 74.24624, 5.440937, 13.741028, -33.902576, 18.58394, -9.959772, 0.1041136, 11.82333, -55.533398, -5.4675765, -15.161497, -1.0267476, 32.695103, -24.99268, 11.922537, 168.70767, -130.78442, 142.66498, 73.242714, 22.27427, 63.905235, -1.3671306, 144.34485, -183.73148, -46.954998, 3.1506326, -66.14528, -76.67139, 101.13374, 4.0305805, 29.317297, 1.181701, -28.506397, -1.6518514, -31.184534, 111.60579, 24.28994, -79.61493, -116.00568, -32.023697, -5.7514906, 101.93708, 0.98392236, 31.337439, -75.310326, -4.5046306, -3.711782, -22.309193, -126.83017, -3.6419837, -0.33691192, 31.669813, -115.76439, -10.27076, 4.059611, -198.88503, -20.161263, -29.47476, 57.17951, -21.95527, 8.026982, 16.390108, -1.1080929, 7.407652, 64.743996, -120.04329, -17.445286, 75.8192, 20.360197, 53.785393, 10.200187, -30.04236, 6.437817, 0.3975224, -67.91621, 1.6522281, -7.837328, -29.006836, 201.19627, -7.32522, -105.99434, -2.4548867, 4.179684, 0.25429633, 15.097081, 7.4597287, -7.0939264, 28.318413, 2.313068, -3.7515059, -62.431297, 38.725285, -107.10958, 13.348956, -49.943775, -29.762196, 17.032738, -115.64885, -35.744957, -54.889526, 10.712898, -2.0292566, 6.2752585, 2.239138, -3.306334, -22.934214, 9.933622, 45.308083, 70.00484, 112.36703, -32.074837, -162.80998, -79.04883, 11.676644, 96.72633, -20.760891, 30.646982, -11.06929, -137.50465, -187.47688, 9.259439, -74.744194, 15.253941, 77.878845, 43.031143, -74.70491, 0.8596837, -3.5045547, 7.4930143, -62.12004, -201.92722, -14.383545, 188.42667, 52.05429, 25.04509, -25.63214, -74.18135, 46.912468, 99.37713, 17.79873, -2.1403294, 72.36021, 15.878182, -10.988122, -0.4876936, -98.321266, -15.296746, 78.528404, 1.3916807, -197.96143, 48.620667, -55.48649, 90.06772, -1.8789421, 148.41797, -79.165825, 44.078205, 5.211938, 104.9392, -3.1070962, -12.826189, -42.78979, 66.79847, -3.7024772, -4.8472857, 15.723977, 1.2936529, -8.688843, 21.240936, 1.3776098, -15.6449795, -154.3604, 23.49148, -7.519365, -1.6222787, 10.925819, -4.189361, -91.339485, 5.8957524, -4.6089797, -31.249628, 16.335638, -29.451998, 13.344731, -24.234076, 39.230362, -11.508264, -56.050926, -11.093029, 2.6919734, -78.32911, 71.32819, 22.187014, -229.40271, -165.41776, 3.8701072, 17.674295, -7.9431186, 3.8358455, -10.224057, 12.491475, 109.73238, -25.23852, 5.5010023, 0.013512374, -28.22281, -1.2147744, 14.7177105, 1.5710909, -47.821503, -14.950896, -126.36881, 37.637623, 146.43083, -128.48166, 11.404479, 29.001417, -16.301233}; + + @Override + public double predict(Object2DoubleMap ft) { + return predict(ft, DEFAULT_PARAMS); + } + + @Override + public double[] getData(Object2DoubleMap ft) { + double[] data = new double[14]; + data[0] = (ft.getDouble("length") - 107.8300974851653) / 88.3127424806261; + data[1] = (ft.getDouble("speed") - 14.238025572195534) / 3.7074142979554225; + data[2] = (ft.getDouble("num_lanes") - 1.8936140152585477) / 0.8774023537080416; + data[3] = ft.getDouble("change_speed"); + data[4] = ft.getDouble("change_num_lanes"); + data[5] = ft.getDouble("num_to_links"); + data[6] = ft.getDouble("junction_inc_lanes"); + data[7] = ft.getDouble("priority_lower"); + data[8] = ft.getDouble("priority_equal"); + data[9] = ft.getDouble("priority_higher"); + data[10] = ft.getDouble("is_secondary_or_higher"); + data[11] = ft.getDouble("is_primary_or_higher"); + data[12] = ft.getDouble("is_motorway"); + data[13] = ft.getDouble("is_link"); + + return data; + } + + @Override + public double predict(Object2DoubleMap ft, double[] params) { + + double[] data = getData(ft); + for (int i = 0; i < data.length; i++) + if (Double.isNaN(data[i])) throw new IllegalArgumentException("Invalid data at index: " + i); + + return score(data, params); + } + public static double score(double[] input, double[] params) { + double var0; + if (input[0] >= 0.09302058) { + if (input[6] >= 5.5) { + if (input[0] >= 0.70052063) { + if (input[1] >= -1.218646) { + var0 = params[0]; + } else { + var0 = params[1]; + } + } else { + if (input[6] >= 10.5) { + var0 = params[2]; + } else { + var0 = params[3]; + } + } + } else { + if (input[1] >= -1.218646) { + if (input[6] >= 3.5) { + var0 = params[4]; + } else { + var0 = params[5]; + } + } else { + if (input[3] >= 6.9449997) { + var0 = params[6]; + } else { + var0 = params[7]; + } + } + } + } else { + if (input[6] >= 4.5) { + if (input[5] >= 2.5) { + if (input[10] >= 0.5) { + var0 = params[8]; + } else { + var0 = params[9]; + } + } else { + if (input[1] >= 0.28105152) { + var0 = params[10]; + } else { + var0 = params[11]; + } + } + } else { + if (input[0] >= -0.68410397) { + if (input[6] >= 3.5) { + var0 = params[12]; + } else { + var0 = params[13]; + } + } else { + if (input[0] >= -0.88130087) { + var0 = params[14]; + } else { + var0 = params[15]; + } + } + } + } + double var1; + if (input[2] >= -0.44861287) { + if (input[5] >= 2.5) { + if (input[1] >= 1.0295516) { + if (input[3] >= -10.0) { + var1 = params[16]; + } else { + var1 = params[17]; + } + } else { + if (input[10] >= 0.5) { + var1 = params[18]; + } else { + var1 = params[19]; + } + } + } else { + if (input[0] >= -0.66694903) { + if (input[5] >= 1.5) { + var1 = params[20]; + } else { + var1 = params[21]; + } + } else { + if (input[3] >= 6.9449997) { + var1 = params[22]; + } else { + var1 = params[23]; + } + } + } + } else { + if (input[1] >= 0.28105152) { + if (input[0] >= -0.62159884) { + if (input[3] >= 1.385) { + var1 = params[24]; + } else { + var1 = params[25]; + } + } else { + if (input[6] >= 3.5) { + var1 = params[26]; + } else { + var1 = params[27]; + } + } + } else { + if (input[1] >= -0.46879724) { + if (input[13] >= 0.5) { + var1 = params[28]; + } else { + var1 = params[29]; + } + } else { + if (input[5] >= 2.5) { + var1 = params[30]; + } else { + var1 = params[31]; + } + } + } + } + double var2; + if (input[4] >= -0.5) { + if (input[10] >= 0.5) { + if (input[5] >= 2.5) { + if (input[9] >= 0.5) { + var2 = params[32]; + } else { + var2 = params[33]; + } + } else { + if (input[5] >= 1.5) { + var2 = params[34]; + } else { + var2 = params[35]; + } + } + } else { + if (input[4] >= 0.5) { + if (input[9] >= 0.5) { + var2 = params[36]; + } else { + var2 = params[37]; + } + } else { + if (input[3] >= -6.9449997) { + var2 = params[38]; + } else { + var2 = params[39]; + } + } + } + } else { + if (input[4] >= -1.5) { + if (input[10] >= 0.5) { + if (input[3] >= 4.165) { + var2 = params[40]; + } else { + var2 = params[41]; + } + } else { + if (input[1] >= 2.5279005) { + var2 = params[42]; + } else { + var2 = params[43]; + } + } + } else { + if (input[6] >= 8.5) { + if (input[8] >= 0.5) { + var2 = params[44]; + } else { + var2 = params[45]; + } + } else { + if (input[1] >= -0.46879724) { + var2 = params[46]; + } else { + var2 = params[47]; + } + } + } + } + double var3; + if (input[4] >= -0.5) { + if (input[0] >= -0.7546487) { + if (input[1] >= -0.46879724) { + if (input[5] >= 2.5) { + var3 = params[48]; + } else { + var3 = params[49]; + } + } else { + if (input[4] >= 0.5) { + var3 = params[50]; + } else { + var3 = params[51]; + } + } + } else { + if (input[0] >= -0.88130087) { + if (input[1] >= -1.218646) { + var3 = params[52]; + } else { + var3 = params[53]; + } + } else { + if (input[1] >= 0.28105152) { + var3 = params[54]; + } else { + var3 = params[55]; + } + } + } + } else { + if (input[2] >= 0.6911151) { + if (input[4] >= -1.5) { + if (input[6] >= 6.5) { + var3 = params[56]; + } else { + var3 = params[57]; + } + } else { + if (input[6] >= 11.5) { + var3 = params[58]; + } else { + var3 = params[59]; + } + } + } else { + if (input[1] >= 1.0295516) { + if (input[1] >= 2.9028249) { + var3 = params[60]; + } else { + var3 = params[61]; + } + } else { + if (input[0] >= 0.099814616) { + var3 = params[62]; + } else { + var3 = params[63]; + } + } + } + } + double var4; + if (input[4] >= -0.5) { + if (input[2] >= -0.44861287) { + if (input[0] >= -0.590233) { + if (input[5] >= 2.5) { + var4 = params[64]; + } else { + var4 = params[65]; + } + } else { + if (input[6] >= 5.5) { + var4 = params[66]; + } else { + var4 = params[67]; + } + } + } else { + if (input[0] >= -0.7723698) { + if (input[3] >= -1.385) { + var4 = params[68]; + } else { + var4 = params[69]; + } + } else { + if (input[0] >= -0.88130087) { + var4 = params[70]; + } else { + var4 = params[71]; + } + } + } + } else { + if (input[2] >= 0.6911151) { + if (input[5] >= 2.5) { + if (input[11] >= 0.5) { + var4 = params[72]; + } else { + var4 = params[73]; + } + } else { + if (input[4] >= -1.5) { + var4 = params[74]; + } else { + var4 = params[75]; + } + } + } else { + if (input[0] >= -0.88452804) { + if (input[0] >= -0.81109583) { + var4 = params[76]; + } else { + var4 = params[77]; + } + } else { + if (input[1] >= 0.28105152) { + var4 = params[78]; + } else { + var4 = params[79]; + } + } + } + } + double var5; + if (input[0] >= -0.6641182) { + if (input[0] >= 0.15620512) { + if (input[5] >= 2.5) { + if (input[6] >= 4.5) { + var5 = params[80]; + } else { + var5 = params[81]; + } + } else { + if (input[9] >= 0.5) { + var5 = params[82]; + } else { + var5 = params[83]; + } + } + } else { + if (input[4] >= -0.5) { + if (input[1] >= 2.5279005) { + var5 = params[84]; + } else { + var5 = params[85]; + } + } else { + if (input[6] >= 4.5) { + var5 = params[86]; + } else { + var5 = params[87]; + } + } + } + } else { + if (input[0] >= -0.88130087) { + if (input[6] >= 4.5) { + if (input[0] >= -0.80135775) { + var5 = params[88]; + } else { + var5 = params[89]; + } + } else { + if (input[1] >= 1.0295516) { + var5 = params[90]; + } else { + var5 = params[91]; + } + } + } else { + if (input[6] >= 4.5) { + if (input[4] >= -0.5) { + var5 = params[92]; + } else { + var5 = params[93]; + } + } else { + if (input[10] >= 0.5) { + var5 = params[94]; + } else { + var5 = params[95]; + } + } + } + } + double var6; + if (input[3] >= 4.165) { + if (input[3] >= 5.5550003) { + if (input[4] >= 0.5) { + if (input[0] >= -0.9836644) { + var6 = params[96]; + } else { + var6 = params[97]; + } + } else { + if (input[0] >= -0.68772745) { + var6 = params[98]; + } else { + var6 = params[99]; + } + } + } else { + if (input[4] >= -0.5) { + if (input[13] >= 0.5) { + var6 = params[100]; + } else { + var6 = params[101]; + } + } else { + if (input[0] >= -0.8086613) { + var6 = params[102]; + } else { + var6 = params[103]; + } + } + } + } else { + if (input[4] >= -0.5) { + if (input[2] >= 1.830843) { + if (input[8] >= 0.5) { + var6 = params[104]; + } else { + var6 = params[105]; + } + } else { + if (input[2] >= -0.44861287) { + var6 = params[106]; + } else { + var6 = params[107]; + } + } + } else { + if (input[2] >= 1.830843) { + if (input[4] >= -2.5) { + var6 = params[108]; + } else { + var6 = params[109]; + } + } else { + if (input[4] >= -1.5) { + var6 = params[110]; + } else { + var6 = params[111]; + } + } + } + } + double var7; + if (input[0] >= -0.456617) { + if (input[5] >= 1.5) { + if (input[0] >= 0.9316878) { + if (input[5] >= 3.5) { + var7 = params[112]; + } else { + var7 = params[113]; + } + } else { + if (input[1] >= -1.218646) { + var7 = params[114]; + } else { + var7 = params[115]; + } + } + } else { + if (input[4] >= -0.5) { + if (input[2] >= 1.830843) { + var7 = params[116]; + } else { + var7 = params[117]; + } + } else { + if (input[0] >= -0.026384613) { + var7 = params[118]; + } else { + var7 = params[119]; + } + } + } + } else { + if (input[0] >= -0.8788663) { + if (input[1] >= 1.0295516) { + if (input[11] >= 0.5) { + var7 = params[120]; + } else { + var7 = params[121]; + } + } else { + if (input[0] >= -0.78997767) { + var7 = params[122]; + } else { + var7 = params[123]; + } + } + } else { + if (input[1] >= 2.5279005) { + if (input[0] >= -0.9264246) { + var7 = params[124]; + } else { + var7 = params[125]; + } + } else { + if (input[1] >= 0.28105152) { + var7 = params[126]; + } else { + var7 = params[127]; + } + } + } + } + double var8; + if (input[10] >= 0.5) { + if (input[8] >= 0.5) { + if (input[0] >= -1.0257874) { + if (input[4] >= 0.5) { + var8 = params[128]; + } else { + var8 = params[129]; + } + } else { + if (input[4] >= 0.5) { + var8 = params[130]; + } else { + var8 = params[131]; + } + } + } else { + if (input[5] >= 2.5) { + if (input[0] >= 0.10587263) { + var8 = params[132]; + } else { + var8 = params[133]; + } + } else { + if (input[2] >= -0.44861287) { + var8 = params[134]; + } else { + var8 = params[135]; + } + } + } + } else { + if (input[2] >= -0.44861287) { + if (input[4] >= -0.5) { + if (input[0] >= 0.11057184) { + var8 = params[136]; + } else { + var8 = params[137]; + } + } else { + if (input[0] >= -0.6677983) { + var8 = params[138]; + } else { + var8 = params[139]; + } + } + } else { + if (input[0] >= -0.9973091) { + if (input[0] >= -0.95756394) { + var8 = params[140]; + } else { + var8 = params[141]; + } + } else { + if (input[7] >= 0.5) { + var8 = params[142]; + } else { + var8 = params[143]; + } + } + } + } + double var9; + if (input[3] >= -5.5550003) { + if (input[3] >= 1.385) { + if (input[6] >= 4.5) { + if (input[6] >= 10.5) { + var9 = params[144]; + } else { + var9 = params[145]; + } + } else { + if (input[0] >= -0.9889864) { + var9 = params[146]; + } else { + var9 = params[147]; + } + } + } else { + if (input[0] >= -1.1094673) { + if (input[0] >= -1.0898212) { + var9 = params[148]; + } else { + var9 = params[149]; + } + } else { + if (input[6] >= 4.5) { + var9 = params[150]; + } else { + var9 = params[151]; + } + } + } + } else { + if (input[0] >= -0.77072793) { + if (input[3] >= -6.9449997) { + if (input[6] >= 7.5) { + var9 = params[152]; + } else { + var9 = params[153]; + } + } else { + if (input[5] >= 2.5) { + var9 = params[154]; + } else { + var9 = params[155]; + } + } + } else { + if (input[6] >= 4.5) { + if (input[2] >= -0.44861287) { + var9 = params[156]; + } else { + var9 = params[157]; + } + } else { + var9 = params[158]; + } + } + } + double var10; + if (input[4] >= -0.5) { + if (input[9] >= 0.5) { + if (input[6] >= 3.5) { + if (input[2] >= -0.44861287) { + var10 = params[159]; + } else { + var10 = params[160]; + } + } else { + if (input[13] >= 0.5) { + var10 = params[161]; + } else { + var10 = params[162]; + } + } + } else { + if (input[6] >= 3.5) { + if (input[3] >= 6.9449997) { + var10 = params[163]; + } else { + var10 = params[164]; + } + } else { + if (input[7] >= 0.5) { + var10 = params[165]; + } else { + var10 = params[166]; + } + } + } + } else { + if (input[0] >= 0.10360795) { + if (input[6] >= 5.5) { + if (input[5] >= 2.5) { + var10 = params[167]; + } else { + var10 = params[168]; + } + } else { + if (input[8] >= 0.5) { + var10 = params[169]; + } else { + var10 = params[170]; + } + } + } else { + if (input[0] >= -0.287219) { + if (input[11] >= 0.5) { + var10 = params[171]; + } else { + var10 = params[172]; + } + } else { + if (input[6] >= 5.5) { + var10 = params[173]; + } else { + var10 = params[174]; + } + } + } + } + double var11; + if (input[4] >= 0.5) { + if (input[11] >= 0.5) { + if (input[4] >= 1.5) { + if (input[4] >= 2.5) { + var11 = params[175]; + } else { + var11 = params[176]; + } + } else { + if (input[1] >= 2.5279005) { + var11 = params[177]; + } else { + var11 = params[178]; + } + } + } else { + if (input[1] >= 0.28105152) { + if (input[1] >= 1.0295516) { + var11 = params[179]; + } else { + var11 = params[180]; + } + } else { + if (input[6] >= 9.5) { + var11 = params[181]; + } else { + var11 = params[182]; + } + } + } + } else { + if (input[3] >= 24.16) { + if (input[6] >= 7.5) { + var11 = params[183]; + } else { + var11 = params[184]; + } + } else { + if (input[1] >= 1.7780516) { + if (input[6] >= 9.5) { + var11 = params[185]; + } else { + var11 = params[186]; + } + } else { + if (input[11] >= 0.5) { + var11 = params[187]; + } else { + var11 = params[188]; + } + } + } + } + double var12; + if (input[6] >= 7.5) { + if (input[0] >= -0.73941875) { + if (input[4] >= 0.5) { + if (input[5] >= 1.5) { + var12 = params[189]; + } else { + var12 = params[190]; + } + } else { + if (input[4] >= -0.5) { + var12 = params[191]; + } else { + var12 = params[192]; + } + } + } else { + if (input[0] >= -0.97488874) { + if (input[5] >= 1.5) { + var12 = params[193]; + } else { + var12 = params[194]; + } + } else { + if (input[10] >= 0.5) { + var12 = params[195]; + } else { + var12 = params[196]; + } + } + } + } else { + if (input[2] >= 0.6911151) { + if (input[0] >= -0.9565449) { + if (input[4] >= -1.5) { + var12 = params[197]; + } else { + var12 = params[198]; + } + } else { + if (input[6] >= 6.5) { + var12 = params[199]; + } else { + var12 = params[200]; + } + } + } else { + if (input[4] >= -0.5) { + if (input[2] >= -0.44861287) { + var12 = params[201]; + } else { + var12 = params[202]; + } + } else { + if (input[5] >= 1.5) { + var12 = params[203]; + } else { + var12 = params[204]; + } + } + } + } + double var13; + if (input[3] >= -5.5550003) { + if (input[0] >= 4.074496) { + if (input[5] >= 1.5) { + if (input[0] >= 4.3374815) { + var13 = params[205]; + } else { + var13 = params[206]; + } + } else { + var13 = params[207]; + } + } else { + if (input[0] >= -1.033091) { + if (input[0] >= -0.92800987) { + var13 = params[208]; + } else { + var13 = params[209]; + } + } else { + if (input[0] >= -1.0600407) { + var13 = params[210]; + } else { + var13 = params[211]; + } + } + } + } else { + if (input[5] >= 1.5) { + if (input[11] >= 0.5) { + if (input[0] >= -0.60495347) { + var13 = params[212]; + } else { + var13 = params[213]; + } + } else { + if (input[10] >= 0.5) { + var13 = params[214]; + } else { + var13 = params[215]; + } + } + } else { + if (input[0] >= -0.9573375) { + if (input[0] >= -0.8931339) { + var13 = params[216]; + } else { + var13 = params[217]; + } + } else { + var13 = params[218]; + } + } + } + double var14; + if (input[0] >= 0.8187369) { + if (input[0] >= 1.7982671) { + if (input[0] >= 2.2454846) { + if (input[9] >= 0.5) { + var14 = params[219]; + } else { + var14 = params[220]; + } + } else { + if (input[8] >= 0.5) { + var14 = params[221]; + } else { + var14 = params[222]; + } + } + } else { + if (input[6] >= 4.5) { + if (input[1] >= 0.28105152) { + var14 = params[223]; + } else { + var14 = params[224]; + } + } else { + if (input[8] >= 0.5) { + var14 = params[225]; + } else { + var14 = params[226]; + } + } + } + } else { + if (input[0] >= -0.38686487) { + if (input[1] >= -1.218646) { + if (input[0] >= 0.10847701) { + var14 = params[227]; + } else { + var14 = params[228]; + } + } else { + if (input[2] >= 0.6911151) { + var14 = params[229]; + } else { + var14 = params[230]; + } + } + } else { + if (input[1] >= -1.218646) { + if (input[1] >= 1.0295516) { + var14 = params[231]; + } else { + var14 = params[232]; + } + } else { + if (input[3] >= 5.5550003) { + var14 = params[233]; + } else { + var14 = params[234]; + } + } + } + } + double var15; + if (input[4] >= 1.5) { + if (input[0] >= -0.92030996) { + if (input[0] >= -0.8825464) { + if (input[0] >= -0.84784025) { + var15 = params[235]; + } else { + var15 = params[236]; + } + } else { + var15 = params[237]; + } + } else { + if (input[0] >= -1.0717604) { + if (input[3] >= 1.39) { + var15 = params[238]; + } else { + var15 = params[239]; + } + } else { + var15 = params[240]; + } + } + } else { + if (input[0] >= -1.0984836) { + if (input[0] >= -1.0955961) { + if (input[0] >= 4.2805815) { + var15 = params[241]; + } else { + var15 = params[242]; + } + } else { + var15 = params[243]; + } + } else { + if (input[6] >= 5.5) { + if (input[0] >= -1.1162047) { + var15 = params[244]; + } else { + var15 = params[245]; + } + } else { + if (input[4] >= -0.5) { + var15 = params[246]; + } else { + var15 = params[247]; + } + } + } + } + double var16; + if (input[0] >= 4.316533) { + var16 = params[248]; + } else { + if (input[0] >= 4.282507) { + var16 = params[249]; + } else { + if (input[2] >= 1.830843) { + if (input[6] >= 9.5) { + var16 = params[250]; + } else { + var16 = params[251]; + } + } else { + if (input[4] >= -1.5) { + var16 = params[252]; + } else { + var16 = params[253]; + } + } + } + } + double var17; + if (input[0] >= 1.0731735) { + if (input[0] >= 1.4191599) { + if (input[0] >= 1.4496765) { + if (input[0] >= 1.5391879) { + var17 = params[254]; + } else { + var17 = params[255]; + } + } else { + if (input[0] >= 1.4420332) { + var17 = params[256]; + } else { + var17 = params[257]; + } + } + } else { + if (input[13] >= 0.5) { + if (input[0] >= 1.2611985) { + var17 = params[258]; + } else { + var17 = params[259]; + } + } else { + if (input[0] >= 1.248573) { + var17 = params[260]; + } else { + var17 = params[261]; + } + } + } + } else { + if (input[0] >= 1.0697765) { + var17 = params[262]; + } else { + if (input[3] >= -12.775) { + if (input[3] >= -8.335) { + var17 = params[263]; + } else { + var17 = params[264]; + } + } else { + if (input[4] >= -0.5) { + var17 = params[265]; + } else { + var17 = params[266]; + } + } + } + } + double var18; + if (input[6] >= 5.5) { + if (input[8] >= 0.5) { + if (input[1] >= -0.46879724) { + if (input[0] >= -0.59045947) { + var18 = params[267]; + } else { + var18 = params[268]; + } + } else { + if (input[11] >= 0.5) { + var18 = params[269]; + } else { + var18 = params[270]; + } + } + } else { + if (input[0] >= -1.0908968) { + if (input[0] >= -0.9190078) { + var18 = params[271]; + } else { + var18 = params[272]; + } + } else { + var18 = params[273]; + } + } + } else { + if (input[0] >= -0.69622004) { + if (input[0] >= -0.6800841) { + if (input[7] >= 0.5) { + var18 = params[274]; + } else { + var18 = params[275]; + } + } else { + if (input[1] >= 1.0295516) { + var18 = params[276]; + } else { + var18 = params[277]; + } + } + } else { + if (input[0] >= -0.7900909) { + if (input[7] >= 0.5) { + var18 = params[278]; + } else { + var18 = params[279]; + } + } else { + if (input[0] >= -0.83668673) { + var18 = params[280]; + } else { + var18 = params[281]; + } + } + } + } + double var19; + if (input[3] >= 5.5550003) { + if (input[5] >= 1.5) { + if (input[6] >= 3.5) { + if (input[1] >= 1.0295516) { + var19 = params[282]; + } else { + var19 = params[283]; + } + } else { + if (input[7] >= 0.5) { + var19 = params[284]; + } else { + var19 = params[285]; + } + } + } else { + if (input[9] >= 0.5) { + var19 = params[286]; + } else { + if (input[6] >= 5.5) { + var19 = params[287]; + } else { + var19 = params[288]; + } + } + } + } else { + if (input[3] >= 1.385) { + if (input[2] >= 0.6911151) { + if (input[10] >= 0.5) { + var19 = params[289]; + } else { + var19 = params[290]; + } + } else { + if (input[7] >= 0.5) { + var19 = params[291]; + } else { + var19 = params[292]; + } + } + } else { + if (input[6] >= 3.5) { + if (input[1] >= 0.28105152) { + var19 = params[293]; + } else { + var19 = params[294]; + } + } else { + if (input[7] >= 0.5) { + var19 = params[295]; + } else { + var19 = params[296]; + } + } + } + } + double var20; + if (input[3] >= 21.385) { + if (input[2] >= -0.44861287) { + if (input[2] >= 0.6911151) { + var20 = params[297]; + } else { + var20 = params[298]; + } + } else { + var20 = params[299]; + } + } else { + if (input[4] >= -0.5) { + if (input[3] >= 9.725) { + if (input[1] >= -1.218646) { + var20 = params[300]; + } else { + var20 = params[301]; + } + } else { + if (input[8] >= 0.5) { + var20 = params[302]; + } else { + var20 = params[303]; + } + } + } else { + if (input[1] >= 0.28105152) { + if (input[1] >= 1.0295516) { + var20 = params[304]; + } else { + var20 = params[305]; + } + } else { + if (input[6] >= 10.5) { + var20 = params[306]; + } else { + var20 = params[307]; + } + } + } + } + double var21; + if (input[6] >= 9.5) { + if (input[5] >= 2.5) { + if (input[6] >= 11.5) { + if (input[8] >= 0.5) { + var21 = params[308]; + } else { + var21 = params[309]; + } + } else { + if (input[0] >= -0.655569) { + var21 = params[310]; + } else { + var21 = params[311]; + } + } + } else { + if (input[4] >= -0.5) { + if (input[0] >= 0.16022491) { + var21 = params[312]; + } else { + var21 = params[313]; + } + } else { + if (input[0] >= -0.35748065) { + var21 = params[314]; + } else { + var21 = params[315]; + } + } + } + } else { + if (input[5] >= 3.5) { + if (input[2] >= -0.44861287) { + if (input[6] >= 7.5) { + var21 = params[316]; + } else { + var21 = params[317]; + } + } else { + if (input[0] >= 0.22833514) { + var21 = params[318]; + } else { + var21 = params[319]; + } + } + } else { + if (input[2] >= 0.6911151) { + if (input[0] >= 1.5724787) { + var21 = params[320]; + } else { + var21 = params[321]; + } + } else { + if (input[0] >= -0.7248682) { + var21 = params[322]; + } else { + var21 = params[323]; + } + } + } + } + double var22; + if (input[0] >= -0.9995737) { + if (input[0] >= -0.99679947) { + if (input[4] >= -1.5) { + if (input[0] >= -0.70408976) { + var22 = params[324]; + } else { + var22 = params[325]; + } + } else { + if (input[0] >= -0.4400282) { + var22 = params[326]; + } else { + var22 = params[327]; + } + } + } else { + if (input[3] >= 4.165) { + var22 = params[328]; + } else { + if (input[11] >= 0.5) { + var22 = params[329]; + } else { + var22 = params[330]; + } + } + } + } else { + if (input[6] >= 2.5) { + if (input[0] >= -1.0424328) { + if (input[0] >= -1.0356953) { + var22 = params[331]; + } else { + var22 = params[332]; + } + } else { + if (input[3] >= 4.165) { + var22 = params[333]; + } else { + var22 = params[334]; + } + } + } else { + var22 = params[335]; + } + } + double var23; + if (input[0] >= 3.4627495) { + if (input[0] >= 3.604858) { + if (input[6] >= 3.5) { + if (input[0] >= 4.105069) { + var23 = params[336]; + } else { + var23 = params[337]; + } + } else { + if (input[0] >= 3.9084382) { + var23 = params[338]; + } else { + var23 = params[339]; + } + } + } else { + if (input[8] >= 0.5) { + var23 = params[340]; + } else { + if (input[0] >= 3.5178943) { + var23 = params[341]; + } else { + var23 = params[342]; + } + } + } + } else { + if (input[0] >= 3.2692895) { + if (input[0] >= 3.395262) { + var23 = params[343]; + } else { + if (input[0] >= 3.3073926) { + var23 = params[344]; + } else { + var23 = params[345]; + } + } + } else { + if (input[0] >= 3.182835) { + var23 = params[346]; + } else { + if (input[0] >= -0.70969486) { + var23 = params[347]; + } else { + var23 = params[348]; + } + } + } + } + double var24; + if (input[4] >= 0.5) { + if (input[0] >= -0.8515203) { + if (input[3] >= -1.39) { + if (input[0] >= -0.80883116) { + var24 = params[349]; + } else { + var24 = params[350]; + } + } else { + if (input[3] >= -5.5550003) { + var24 = params[351]; + } else { + var24 = params[352]; + } + } + } else { + if (input[1] >= 0.28105152) { + if (input[6] >= 6.5) { + var24 = params[353]; + } else { + var24 = params[354]; + } + } else { + if (input[0] >= -0.97336006) { + var24 = params[355]; + } else { + var24 = params[356]; + } + } + } + } else { + if (input[0] >= 3.9279711) { + if (input[9] >= 0.5) { + if (input[0] >= 4.2983027) { + var24 = params[357]; + } else { + var24 = params[358]; + } + } else { + if (input[0] >= 4.2805815) { + var24 = params[359]; + } else { + var24 = params[360]; + } + } + } else { + if (input[5] >= 1.5) { + if (input[6] >= 2.5) { + var24 = params[361]; + } else { + var24 = params[362]; + } + } else { + if (input[6] >= 4.5) { + var24 = params[363]; + } else { + var24 = params[364]; + } + } + } + } + double var25; + if (input[0] >= -0.96871746) { + if (input[0] >= -0.95756394) { + if (input[0] >= -0.9499773) { + if (input[0] >= -0.9480523) { + var25 = params[365]; + } else { + var25 = params[366]; + } + } else { + if (input[9] >= 0.5) { + var25 = params[367]; + } else { + var25 = params[368]; + } + } + } else { + if (input[13] >= 0.5) { + if (input[3] >= 1.385) { + var25 = params[369]; + } else { + var25 = params[370]; + } + } else { + if (input[0] >= -0.9611874) { + var25 = params[371]; + } else { + var25 = params[372]; + } + } + } + } else { + if (input[0] >= -0.97296375) { + if (input[2] >= -0.44861287) { + if (input[0] >= -0.97086895) { + var25 = params[373]; + } else { + var25 = params[374]; + } + } else { + var25 = params[375]; + } + } else { + if (input[0] >= -0.9747189) { + var25 = params[376]; + } else { + if (input[6] >= 7.5) { + var25 = params[377]; + } else { + var25 = params[378]; + } + } + } + } + double var26; + if (input[0] >= 0.10360795) { + if (input[6] >= 4.5) { + if (input[6] >= 5.5) { + if (input[1] >= 1.7780516) { + var26 = params[379]; + } else { + var26 = params[380]; + } + } else { + if (input[0] >= 0.38210684) { + var26 = params[381]; + } else { + var26 = params[382]; + } + } + } else { + if (input[1] >= 1.0295516) { + if (input[4] >= -0.5) { + var26 = params[383]; + } else { + var26 = params[384]; + } + } else { + if (input[1] >= -0.46879724) { + var26 = params[385]; + } else { + var26 = params[386]; + } + } + } + } else { + if (input[6] >= 4.5) { + if (input[6] >= 5.5) { + if (input[0] >= -0.7606501) { + var26 = params[387]; + } else { + var26 = params[388]; + } + } else { + if (input[0] >= -0.6874443) { + var26 = params[389]; + } else { + var26 = params[390]; + } + } + } else { + if (input[0] >= -0.22697854) { + if (input[0] >= -0.2162213) { + var26 = params[391]; + } else { + var26 = params[392]; + } + } else { + if (input[9] >= 0.5) { + var26 = params[393]; + } else { + var26 = params[394]; + } + } + } + } + double var27; + if (input[3] >= -4.165) { + if (input[11] >= 0.5) { + if (input[5] >= 1.5) { + if (input[8] >= 0.5) { + var27 = params[395]; + } else { + var27 = params[396]; + } + } else { + if (input[3] >= -1.385) { + var27 = params[397]; + } else { + var27 = params[398]; + } + } + } else { + if (input[5] >= 1.5) { + if (input[8] >= 0.5) { + var27 = params[399]; + } else { + var27 = params[400]; + } + } else { + if (input[2] >= 0.6911151) { + var27 = params[401]; + } else { + var27 = params[402]; + } + } + } + } else { + if (input[8] >= 0.5) { + if (input[2] >= 1.830843) { + var27 = params[403]; + } else { + if (input[3] >= -11.115) { + var27 = params[404]; + } else { + var27 = params[405]; + } + } + } else { + if (input[5] >= 2.5) { + if (input[1] >= 0.6546272) { + var27 = params[406]; + } else { + var27 = params[407]; + } + } else { + if (input[4] >= -0.5) { + var27 = params[408]; + } else { + var27 = params[409]; + } + } + } + } + double var28; + if (input[4] >= -0.5) { + if (input[0] >= -1.0262969) { + if (input[0] >= -0.9953841) { + if (input[0] >= -0.98751426) { + var28 = params[410]; + } else { + var28 = params[411]; + } + } else { + if (input[0] >= -0.99696934) { + var28 = params[412]; + } else { + var28 = params[413]; + } + } + } else { + if (input[0] >= -1.0285616) { + var28 = params[414]; + } else { + if (input[1] >= 1.0295516) { + var28 = params[415]; + } else { + var28 = params[416]; + } + } + } + } else { + if (input[0] >= -0.5803817) { + if (input[6] >= 10.5) { + if (input[4] >= -1.5) { + var28 = params[417]; + } else { + var28 = params[418]; + } + } else { + if (input[1] >= 0.28105152) { + var28 = params[419]; + } else { + var28 = params[420]; + } + } + } else { + if (input[0] >= -0.734946) { + if (input[0] >= -0.73285115) { + var28 = params[421]; + } else { + var28 = params[422]; + } + } else { + if (input[0] >= -0.794507) { + var28 = params[423]; + } else { + var28 = params[424]; + } + } + } + } + double var29; + if (input[0] >= -0.875073) { + if (input[0] >= -0.8619379) { + if (input[1] >= 0.28105152) { + if (input[5] >= 1.5) { + var29 = params[425]; + } else { + var29 = params[426]; + } + } else { + if (input[0] >= -0.6480956) { + var29 = params[427]; + } else { + var29 = params[428]; + } + } + } else { + if (input[1] >= 0.28105152) { + if (input[1] >= 1.0295516) { + var29 = params[429]; + } else { + var29 = params[430]; + } + } else { + if (input[3] >= 5.5550003) { + var29 = params[431]; + } else { + var29 = params[432]; + } + } + } + } else { + if (input[0] >= -0.8769413) { + if (input[6] >= 3.5) { + var29 = params[433]; + } else { + var29 = params[434]; + } + } else { + if (input[6] >= 4.5) { + if (input[0] >= -0.8780737) { + var29 = params[435]; + } else { + var29 = params[436]; + } + } else { + if (input[0] >= -0.9050234) { + var29 = params[437]; + } else { + var29 = params[438]; + } + } + } + } + return 0.5 + (var0 + var1 + var2 + var3 + var4 + var5 + var6 + var7 + var8 + var9 + var10 + var11 + var12 + var13 + var14 + var15 + var16 + var17 + var18 + var19 + var20 + var21 + var22 + var23 + var24 + var25 + var26 + var27 + var28 + var29); + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_priority.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_priority.java new file mode 100644 index 00000000000..d1a6e4fd067 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_priority.java @@ -0,0 +1,1615 @@ +package org.matsim.application.prepare.network.params.ref; +import org.matsim.application.prepare.network.params.FeatureRegressor; +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; + +/** +* Generated model, do not modify. +*/ +final class GermanyNetworkParams_speedRelative_priority implements FeatureRegressor { + + public static GermanyNetworkParams_speedRelative_priority INSTANCE = new GermanyNetworkParams_speedRelative_priority(); + public static final double[] DEFAULT_PARAMS = {0.3637782335281372, 0.3614218235015869, 0.383897066116333, 0.3755773901939392, 0.28682008385658264, 0.2585180997848511, 0.34156814217567444, 0.3185553550720215, 0.3718447685241699, 0.35274016857147217, 0.26253145933151245, 0.2382100373506546, 0.058064043521881104, 0.0740966722369194, -0.05679725110530853, 0.021339688450098038, 0.02934892103075981, 0.07092590630054474, 0.0212340597063303, 0.017388977110385895, -0.07951025664806366, -0.024962320923805237, -0.010062946937978268, 0.04163287580013275, 0.0326605960726738, -0.036132149398326874, -0.025224462151527405, -0.03780181333422661, -0.009685792960226536, -0.017773333936929703, -0.014809105545282364, 0.019959913566708565, -0.061938200145959854, -0.04567628726363182, -0.016469258815050125, 0.04332061484456062, -0.042286477982997894, -0.022931916639208794, 0.0065815262496471405, -0.03677874803543091, 0.021557684987783432, -0.024354981258511543, -0.020873071625828743, -0.03207797557115555, 0.06513358652591705, -0.02379850298166275, 0.010097366757690907, 0.0891086608171463, 0.009472880512475967, -0.01522810384631157, -0.004405861254781485, 0.022464169189333916, -0.009634237736463547, -0.04903930798172951, 0.002658352255821228, 0.02149798907339573, -0.01455477811396122, -0.012056417763233185, 0.029186995700001717, -0.031515900045633316, -0.04741524159908295, 0.021956423297524452, 0.031237002462148666, 0.04802554100751877, -0.03444923833012581, -0.007921699434518814, -0.029558323323726654, -0.022936023771762848, 0.010797255672514439, 0.045908138155937195, -0.10000010579824448, -0.00937335193157196, 0.00033900211565196514, 0.01860804669559002, 0.013717050664126873, 0.03279625251889229, 0.0008873277110978961, 0.012767238542437553, 0.035769276320934296, -0.08010462671518326, 0.01633155718445778, -0.02708408422768116, 0.005279670935124159, -0.04875575378537178, 0.003950017504394054, -0.03749269247055054, -0.0515570230782032, -0.013348611071705818, 0.008300681598484516, -0.014397768303751945, -0.08500855416059494, -0.03224004805088043, -0.010642386972904205, -0.015546668320894241, -0.04178234562277794, 0.021476851776242256, 0.08180172741413116, 0.01769104041159153, -0.009755595587193966, -0.02927521988749504, 0.021947408095002174, -0.014959958381950855, -0.00870624091476202, 0.0007263520965352654, 0.007865003310143948, 0.05660587176680565, -0.033986255526542664, 0.03487946838140488, 0.012570952996611595, -0.0195362139493227, 0.011755423620343208, -0.031099572777748108, -0.003229639260098338, -0.024863874539732933, 0.0009477873099967837, 0.03023417480289936, -0.05318005755543709, 0.0019253295613452792, -0.02052280679345131, 0.00991956889629364, -0.013874579221010208, 0.005497346632182598, -0.023782776668667793, -0.04202472046017647, 0.04593120142817497, -0.037195708602666855, 0.012138103134930134, 0.016977915540337563, -0.042556487023830414, 0.0043861158192157745, -0.008102478459477425, 0.011768745258450508, -0.01065710186958313, -0.04357535392045975, -0.006400538142770529, -0.0115782106295228, -0.04371703416109085, 0.036339472979307175, -0.003198582911863923, 0.06704246252775192, 0.017427006736397743, -0.0005933382199145854, 0.008955877274274826, -0.02548826113343239, -0.008097999729216099, 0.002990646753460169, 0.012640644796192646, -0.0006432541413232684, 0.037932056933641434, -0.028267815709114075, -0.024455193430185318, 0.07280143350362778, 0.00035000144271180034, -0.01866171695291996, -0.005262991413474083, 0.021344808861613274, -0.010133828967809677, -0.010297955013811588, 0.01429181732237339, -0.020813506096601486, -0.037280309945344925, -0.018860090523958206, -0.06156115233898163, -0.00281521026045084, 0.000669417146127671, -0.01395697332918644, -0.007229289505630732, -0.0869751051068306, -0.02925538457930088, 0.0071889059618115425, 0.02876790054142475, 0.0125223807990551, 0.013144614174962044, -0.012680407613515854, -0.05923359841108322, -0.004741497803479433, -0.06450306624174118, 0.026873745024204254, -0.07459960132837296, -0.03914644196629524, -0.06504401564598083, -0.005390695296227932, -0.022049684077501297, -0.005413497798144817, 0.01049880962818861, 0.0023084788117557764, -0.01799708791077137, -0.002133547328412533, 0.01597646251320839, -0.016214435920119286, -0.016951773315668106, 0.0033068093471229076, -0.0013935897732153535, -0.010729228146374226, 0.020868686959147453, -0.006465913262218237, -0.004377259872853756, 0.0005968595505692065, -0.03573509305715561, 0.04443972930312157, -0.01937963254749775, 0.019298817962408066, -0.031265877187252045, 0.007212034892290831, 0.028614364564418793, -0.0011800326174125075, 0.033576153218746185, -0.0006205455865710974, -0.009261837229132652, 0.05111328884959221, -0.03780912235379219, -0.013162107206881046, 0.031568802893161774, 0.00040165489190258086, -0.019249461591243744, 0.007797026075422764, -0.012850829400122166, -0.008672687225043774, 0.006185037083923817, -0.0036216983571648598, -0.032741714268922806, 0.02690431848168373, -0.03770885244011879, -0.025922155007719994, 0.013039791956543922, -0.000474052329082042, 0.01974770985543728, -0.04893583059310913, 0.010358916595578194, -0.002607739297673106, 0.004165446385741234, -0.02026587538421154, -0.042514752596616745, 0.01972988247871399, 0.042134255170822144, -0.04910166934132576, 0.009181584231555462, -0.006061230320483446, -0.035198722034692764, -0.03807628154754639, -0.004992008674889803, -0.06918217986822128, -0.07436000555753708, 0.01909884437918663, -0.009508511051535606, 0.015200886875391006, -0.0020895658526569605, -0.07527001947164536, -0.01391940750181675, 0.008580495603382587, 0.00391254760324955, -0.04679833725094795, -0.027141371741890907, 0.006913655903190374, -0.11248551309108734, 0.050203897058963776, 0.015846315771341324, -0.017206573858857155, -0.025128813460469246, -0.07098793238401413, -0.07697086781263351, 0.031076420098543167, -0.005927834194153547, -0.06105758249759674, 0.023415520787239075, -0.009801242500543594, 0.031423136591911316, 0.05334761366248131, 0.03710203245282173, -0.07392022013664246, 0.04428170993924141, -0.03584817051887512, -0.03381654620170593, 0.03290421515703201, 0.08302813023328781, 0.013968883082270622, -0.0065446943044662476, -0.013700475916266441, -0.010839354246854782, -0.0010206960141658783, -0.02658669278025627, -0.025912929326295853, -0.0008662577020004392, -0.019497094675898552, -0.06554882973432541, -0.05629074200987816, -0.030291398987174034, -0.041469600051641464, 0.024082737043499947, 0.005145573522895575, 0.004569159355014563, 0.03584619611501694, 0.00917505007237196, 0.022853247821331024, 0.026813039556145668, -0.023505525663495064, -0.0052485391497612, -0.07031173259019852, -0.05817317217588425, 0.00025176024064421654, 0.029265716671943665, -0.07882880419492722, 0.005491776391863823, 0.0014526471495628357, 0.0052328347228467464, -0.006517454516142607, -0.003525523701682687, 0.007867665030062199, 0.003880856791511178, 0.05164279043674469, -0.03788694366812706, 0.03542916849255562, -0.04080580919981003, 0.014976377598941326, -0.07206366211175919, -0.0028124710079282522, -0.01770205609500408, -0.007484535686671734, 0.00918074231594801, 0.004485897719860077, 0.004660941194742918, -0.0027995810378342867, 0.003636928042396903, 0.0028716991655528545, 0.009062713012099266, -0.016396984457969666, -0.0011474796338006854, -0.019887544214725494, 0.056226253509521484, 0.009289677254855633, 0.0029299173038452864, 0.013792104087769985, 0.0001577992079546675, -0.0035906080156564713, -0.028217647224664688, -0.053379908204078674, 0.048540011048316956, 0.023068727925419807, 0.009644659236073494, -0.008045271970331669, -0.012953918427228928, -0.04577777907252312, 0.012964596971869469, -0.0032735613640397787, -0.013344255276024342, -0.008774071000516415, -0.00022526513203047216, -0.029385730624198914, 0.015316969715058804, -0.033611737191677094, 0.011155270040035248, -0.048190146684646606, -0.0100743118673563, 0.015322275459766388, -0.015126648359000683, 0.002708536572754383, 0.01651214249432087, 0.04236186668276787, -0.023447610437870026, -0.0005691073602065444, -0.0850084200501442, 0.03373489901423454, -0.00444692512974143, -0.03225868567824364, -0.06289532780647278, 0.012347227893769741, -0.0028485064394772053, 0.01437492948025465, 0.02857530489563942, -0.03885238617658615, -0.0021300658117979765, 0.030708378180861473, -0.017140071839094162, -0.03278900682926178, 0.01850981079041958, 0.020646488294005394, -0.04716883972287178, 0.020775284618139267, -0.0042621660977602005, -0.0027691777795553207, -0.0647282525897026, 0.015367957763373852, -0.033247802406549454, 0.001773053198121488, 0.01829376257956028, -0.0009999207686632872, 0.03853385150432587, 0.011664622463285923, 0.04012610390782356, 0.012450157664716244, -0.015043043531477451, -0.014847155660390854, -0.013817483559250832, -0.0005356948240660131, 0.015310121700167656, -0.0016980142099782825, -0.002164469799026847, -0.06938603520393372, -0.009514924138784409, -0.00599967734888196, 0.037029676139354706, -0.021834025159478188, -0.00501669105142355, -0.0017547043971717358, -0.017194082960486412, 0.020213624462485313}; + + @Override + public double predict(Object2DoubleMap ft) { + return predict(ft, DEFAULT_PARAMS); + } + + @Override + public double[] getData(Object2DoubleMap ft) { + double[] data = new double[14]; + data[0] = (ft.getDouble("length") - 136.6196185884635) / 100.86082059541495; + data[1] = (ft.getDouble("speed") - 13.986934871911906) / 4.71750654884318; + data[2] = (ft.getDouble("num_lanes") - 1.2681719632566897) / 0.6868784909822384; + data[3] = ft.getDouble("change_speed"); + data[4] = ft.getDouble("change_num_lanes"); + data[5] = ft.getDouble("num_to_links"); + data[6] = ft.getDouble("junction_inc_lanes"); + data[7] = ft.getDouble("priority_lower"); + data[8] = ft.getDouble("priority_equal"); + data[9] = ft.getDouble("priority_higher"); + data[10] = ft.getDouble("is_secondary_or_higher"); + data[11] = ft.getDouble("is_primary_or_higher"); + data[12] = ft.getDouble("is_motorway"); + data[13] = ft.getDouble("is_link"); + + return data; + } + + @Override + public double predict(Object2DoubleMap ft, double[] params) { + + double[] data = getData(ft); + for (int i = 0; i < data.length; i++) + if (Double.isNaN(data[i])) throw new IllegalArgumentException("Invalid data at index: " + i); + + return score(data, params); + } + public static double score(double[] input, double[] params) { + double var0; + if (input[0] >= -0.18931651) { + if (input[3] >= -5.5550003) { + if (input[5] >= 1.5) { + if (input[9] >= 0.5) { + var0 = params[0]; + } else { + var0 = params[1]; + } + } else { + if (input[11] >= 0.5) { + var0 = params[2]; + } else { + var0 = params[3]; + } + } + } else { + if (input[3] >= -12.775) { + var0 = params[4]; + } else { + var0 = params[5]; + } + } + } else { + if (input[3] >= -4.165) { + if (input[1] >= -0.31519508) { + if (input[11] >= 0.5) { + var0 = params[6]; + } else { + var0 = params[7]; + } + } else { + if (input[6] >= 2.5) { + var0 = params[8]; + } else { + var0 = params[9]; + } + } + } else { + if (input[0] >= -0.72341883) { + var0 = params[10]; + } else { + var0 = params[11]; + } + } + } + double var1; + if (input[0] >= -1.1267469) { + if (input[2] >= 0.3375095) { + if (input[0] >= 1.1064789) { + if (input[12] >= 0.5) { + var1 = params[12]; + } else { + var1 = params[13]; + } + } else { + if (input[4] >= -0.5) { + var1 = params[14]; + } else { + var1 = params[15]; + } + } + } else { + if (input[9] >= 0.5) { + if (input[0] >= -0.18297113) { + var1 = params[16]; + } else { + var1 = params[17]; + } + } else { + if (input[3] >= 1.385) { + var1 = params[18]; + } else { + var1 = params[19]; + } + } + } + } else { + if (input[2] >= 0.3375095) { + if (input[0] >= -1.1286306) { + var1 = params[20]; + } else { + if (input[5] >= 1.5) { + var1 = params[21]; + } else { + var1 = params[22]; + } + } + } else { + if (input[3] >= 12.5) { + var1 = params[23]; + } else { + if (input[9] >= 0.5) { + var1 = params[24]; + } else { + var1 = params[25]; + } + } + } + } + double var2; + if (input[5] >= 2.5) { + if (input[0] >= -0.6054345) { + if (input[1] >= -0.60984224) { + if (input[7] >= 0.5) { + var2 = params[26]; + } else { + var2 = params[27]; + } + } else { + if (input[0] >= -0.37278715) { + var2 = params[28]; + } else { + var2 = params[29]; + } + } + } else { + if (input[9] >= 0.5) { + if (input[0] >= -0.7754212) { + var2 = params[30]; + } else { + var2 = params[31]; + } + } else { + if (input[1] >= -0.60984224) { + var2 = params[32]; + } else { + var2 = params[33]; + } + } + } + } else { + if (input[1] >= 0.8623338) { + if (input[4] >= 0.5) { + if (input[4] >= 1.5) { + var2 = params[34]; + } else { + var2 = params[35]; + } + } else { + if (input[1] >= 3.5120387) { + var2 = params[36]; + } else { + var2 = params[37]; + } + } + } else { + if (input[7] >= 0.5) { + if (input[1] >= -0.9044894) { + var2 = params[38]; + } else { + var2 = params[39]; + } + } else { + if (input[0] >= -0.82038414) { + var2 = params[40]; + } else { + var2 = params[41]; + } + } + } + } + double var3; + if (input[12] >= 0.5) { + if (input[1] >= 3.5120387) { + if (input[0] >= -0.58545643) { + if (input[0] >= 0.43689296) { + var3 = params[42]; + } else { + var3 = params[43]; + } + } else { + if (input[0] >= -1.1621423) { + var3 = params[44]; + } else { + var3 = params[45]; + } + } + } else { + if (input[0] >= 1.1714696) { + var3 = params[46]; + } else { + if (input[2] >= 0.3375095) { + var3 = params[47]; + } else { + var3 = params[48]; + } + } + } + } else { + if (input[13] >= 0.5) { + if (input[6] >= 2.5) { + if (input[9] >= 0.5) { + var3 = params[49]; + } else { + var3 = params[50]; + } + } else { + if (input[0] >= -1.049363) { + var3 = params[51]; + } else { + var3 = params[52]; + } + } + } else { + if (input[11] >= 0.5) { + if (input[2] >= 1.7933712) { + var3 = params[53]; + } else { + var3 = params[54]; + } + } else { + if (input[0] >= 0.7997692) { + var3 = params[55]; + } else { + var3 = params[56]; + } + } + } + } + double var4; + if (input[3] >= 5.835) { + if (input[0] >= -0.21107918) { + if (input[0] >= 0.64663744) { + var4 = params[57]; + } else { + if (input[0] >= -0.20285001) { + var4 = params[58]; + } else { + var4 = params[59]; + } + } + } else { + if (input[5] >= 1.5) { + if (input[1] >= -0.60984224) { + var4 = params[60]; + } else { + var4 = params[61]; + } + } else { + if (input[0] >= -0.68727994) { + var4 = params[62]; + } else { + var4 = params[63]; + } + } + } + } else { + if (input[4] >= 0.5) { + if (input[0] >= -0.15991956) { + if (input[8] >= 0.5) { + var4 = params[64]; + } else { + var4 = params[65]; + } + } else { + if (input[7] >= 0.5) { + var4 = params[66]; + } else { + var4 = params[67]; + } + } + } else { + if (input[6] >= 1.5) { + if (input[0] >= -1.2913301) { + var4 = params[68]; + } else { + var4 = params[69]; + } + } else { + if (input[1] >= -0.31519508) { + var4 = params[70]; + } else { + var4 = params[71]; + } + } + } + } + double var5; + if (input[5] >= 1.5) { + if (input[0] >= 0.17985559) { + if (input[9] >= 0.5) { + if (input[2] >= 0.3375095) { + var5 = params[72]; + } else { + var5 = params[73]; + } + } else { + if (input[3] >= 2.775) { + var5 = params[74]; + } else { + var5 = params[75]; + } + } + } else { + if (input[9] >= 0.5) { + if (input[10] >= 0.5) { + var5 = params[76]; + } else { + var5 = params[77]; + } + } else { + if (input[1] >= 1.4505682) { + var5 = params[78]; + } else { + var5 = params[79]; + } + } + } + } else { + if (input[0] >= -0.1899114) { + if (input[6] >= 1.5) { + if (input[4] >= -0.5) { + var5 = params[80]; + } else { + var5 = params[81]; + } + } else { + if (input[1] >= 2.3345098) { + var5 = params[82]; + } else { + var5 = params[83]; + } + } + } else { + if (input[5] >= 0.5) { + if (input[6] >= 1.5) { + var5 = params[84]; + } else { + var5 = params[85]; + } + } else { + if (input[1] >= -0.60984224) { + var5 = params[86]; + } else { + var5 = params[87]; + } + } + } + } + double var6; + if (input[1] >= 0.8623338) { + if (input[0] >= -0.49880242) { + if (input[10] >= 0.5) { + if (input[11] >= 0.5) { + var6 = params[88]; + } else { + var6 = params[89]; + } + } else { + if (input[0] >= 1.5952713) { + var6 = params[90]; + } else { + var6 = params[91]; + } + } + } else { + if (input[5] >= 1.5) { + if (input[0] >= -0.6634352) { + var6 = params[92]; + } else { + var6 = params[93]; + } + } else { + if (input[0] >= -0.5407909) { + var6 = params[94]; + } else { + var6 = params[95]; + } + } + } + } else { + if (input[11] >= 0.5) { + if (input[7] >= 0.5) { + if (input[0] >= -1.1048355) { + var6 = params[96]; + } else { + var6 = params[97]; + } + } else { + if (input[0] >= -0.45141035) { + var6 = params[98]; + } else { + var6 = params[99]; + } + } + } else { + if (input[0] >= -1.249639) { + if (input[0] >= -0.18971309) { + var6 = params[100]; + } else { + var6 = params[101]; + } + } else { + if (input[0] >= -1.2646598) { + var6 = params[102]; + } else { + var6 = params[103]; + } + } + } + } + double var7; + if (input[0] >= 2.4748993) { + if (input[3] >= -5.5550003) { + if (input[7] >= 0.5) { + if (input[3] >= 1.39) { + var7 = params[104]; + } else { + var7 = params[105]; + } + } else { + if (input[1] >= 1.4505682) { + var7 = params[106]; + } else { + var7 = params[107]; + } + } + } else { + var7 = params[108]; + } + } else { + if (input[0] >= -1.1069176) { + if (input[0] >= -1.0723155) { + if (input[0] >= -0.58317614) { + var7 = params[109]; + } else { + var7 = params[110]; + } + } else { + if (input[7] >= 0.5) { + var7 = params[111]; + } else { + var7 = params[112]; + } + } + } else { + if (input[5] >= 0.5) { + if (input[10] >= 0.5) { + var7 = params[113]; + } else { + var7 = params[114]; + } + } else { + var7 = params[115]; + } + } + } + double var8; + if (input[6] >= 5.5) { + if (input[4] >= -0.5) { + if (input[8] >= 0.5) { + if (input[6] >= 6.5) { + var8 = params[116]; + } else { + var8 = params[117]; + } + } else { + if (input[10] >= 0.5) { + var8 = params[118]; + } else { + var8 = params[119]; + } + } + } else { + if (input[10] >= 0.5) { + if (input[1] >= 0.8623338) { + var8 = params[120]; + } else { + var8 = params[121]; + } + } else { + var8 = params[122]; + } + } + } else { + if (input[1] >= 3.5120387) { + if (input[2] >= 3.2492328) { + if (input[1] >= 4.747861) { + var8 = params[123]; + } else { + var8 = params[124]; + } + } else { + if (input[3] >= -1.39) { + var8 = params[125]; + } else { + var8 = params[126]; + } + } + } else { + if (input[4] >= 2.5) { + if (input[8] >= 0.5) { + var8 = params[127]; + } else { + var8 = params[128]; + } + } else { + if (input[3] >= -1.385) { + var8 = params[129]; + } else { + var8 = params[130]; + } + } + } + } + double var9; + if (input[5] >= 1.5) { + if (input[1] >= -0.9044894) { + if (input[3] >= 1.385) { + if (input[2] >= 0.3375095) { + var9 = params[131]; + } else { + var9 = params[132]; + } + } else { + if (input[4] >= 0.5) { + var9 = params[133]; + } else { + var9 = params[134]; + } + } + } else { + if (input[3] >= 5.5550003) { + if (input[0] >= -0.824697) { + var9 = params[135]; + } else { + var9 = params[136]; + } + } else { + if (input[9] >= 0.5) { + var9 = params[137]; + } else { + var9 = params[138]; + } + } + } + } else { + if (input[3] >= 1.385) { + if (input[0] >= -0.8564735) { + if (input[9] >= 0.5) { + var9 = params[139]; + } else { + var9 = params[140]; + } + } else { + if (input[3] >= 8.335) { + var9 = params[141]; + } else { + var9 = params[142]; + } + } + } else { + if (input[1] >= 1.4505682) { + if (input[0] >= 2.2239594) { + var9 = params[143]; + } else { + var9 = params[144]; + } + } else { + if (input[3] >= -1.385) { + var9 = params[145]; + } else { + var9 = params[146]; + } + } + } + } + double var10; + if (input[7] >= 0.5) { + if (input[0] >= -0.90738523) { + if (input[0] >= -0.103158176) { + if (input[6] >= 2.5) { + var10 = params[147]; + } else { + var10 = params[148]; + } + } else { + if (input[1] >= -0.9044894) { + var10 = params[149]; + } else { + var10 = params[150]; + } + } + } else { + if (input[1] >= -0.60984224) { + if (input[6] >= 2.5) { + var10 = params[151]; + } else { + var10 = params[152]; + } + } else { + if (input[3] >= 5.5550003) { + var10 = params[153]; + } else { + var10 = params[154]; + } + } + } + } else { + if (input[6] >= 2.5) { + if (input[0] >= -0.19030797) { + if (input[0] >= -0.02612133) { + var10 = params[155]; + } else { + var10 = params[156]; + } + } else { + if (input[0] >= -0.41636205) { + var10 = params[157]; + } else { + var10 = params[158]; + } + } + } else { + if (input[8] >= 0.5) { + if (input[0] >= -0.8501281) { + var10 = params[159]; + } else { + var10 = params[160]; + } + } else { + if (input[0] >= -1.0568982) { + var10 = params[161]; + } else { + var10 = params[162]; + } + } + } + } + double var11; + if (input[0] >= -0.8138405) { + if (input[0] >= -0.8104695) { + if (input[3] >= -5.5550003) { + if (input[0] >= -0.80809) { + var11 = params[163]; + } else { + var11 = params[164]; + } + } else { + if (input[0] >= 0.62140465) { + var11 = params[165]; + } else { + var11 = params[166]; + } + } + } else { + if (input[2] >= 0.3375095) { + var11 = params[167]; + } else { + if (input[0] >= -0.81126267) { + var11 = params[168]; + } else { + var11 = params[169]; + } + } + } + } else { + if (input[5] >= 2.5) { + if (input[9] >= 0.5) { + if (input[1] >= -0.60984224) { + var11 = params[170]; + } else { + var11 = params[171]; + } + } else { + if (input[0] >= -1.164026) { + var11 = params[172]; + } else { + var11 = params[173]; + } + } + } else { + if (input[13] >= 0.5) { + if (input[3] >= 2.775) { + var11 = params[174]; + } else { + var11 = params[175]; + } + } else { + if (input[2] >= 0.3375095) { + var11 = params[176]; + } else { + var11 = params[177]; + } + } + } + } + double var12; + if (input[1] >= 5.042508) { + if (input[5] >= 1.5) { + if (input[0] >= 0.9575609) { + var12 = params[178]; + } else { + var12 = params[179]; + } + } else { + if (input[0] >= 0.47868323) { + if (input[4] >= -0.5) { + var12 = params[180]; + } else { + var12 = params[181]; + } + } else { + var12 = params[182]; + } + } + } else { + if (input[6] >= 3.5) { + if (input[0] >= -1.1479642) { + if (input[5] >= 2.5) { + var12 = params[183]; + } else { + var12 = params[184]; + } + } else { + if (input[4] >= -0.5) { + var12 = params[185]; + } else { + var12 = params[186]; + } + } + } else { + if (input[0] >= -1.2884054) { + if (input[4] >= -0.5) { + var12 = params[187]; + } else { + var12 = params[188]; + } + } else { + if (input[5] >= 1.5) { + var12 = params[189]; + } else { + var12 = params[190]; + } + } + } + } + double var13; + if (input[3] >= -5.835) { + if (input[6] >= 4.5) { + if (input[0] >= -0.2966922) { + if (input[8] >= 0.5) { + var13 = params[191]; + } else { + var13 = params[192]; + } + } else { + if (input[10] >= 0.5) { + var13 = params[193]; + } else { + var13 = params[194]; + } + } + } else { + if (input[0] >= -0.5833248) { + if (input[1] >= -0.9044894) { + var13 = params[195]; + } else { + var13 = params[196]; + } + } else { + if (input[5] >= 0.5) { + var13 = params[197]; + } else { + var13 = params[198]; + } + } + } + } else { + if (input[7] >= 0.5) { + var13 = params[199]; + } else { + if (input[0] >= 0.71465194) { + if (input[0] >= 2.5458884) { + var13 = params[200]; + } else { + var13 = params[201]; + } + } else { + if (input[0] >= -0.6475718) { + var13 = params[202]; + } else { + var13 = params[203]; + } + } + } + } + double var14; + if (input[3] >= 2.775) { + if (input[9] >= 0.5) { + if (input[0] >= -0.8122046) { + if (input[3] >= 6.9449997) { + var14 = params[204]; + } else { + var14 = params[205]; + } + } else { + var14 = params[206]; + } + } else { + if (input[0] >= 1.137264) { + if (input[0] >= 2.1696272) { + var14 = params[207]; + } else { + var14 = params[208]; + } + } else { + if (input[10] >= 0.5) { + var14 = params[209]; + } else { + var14 = params[210]; + } + } + } + } else { + if (input[10] >= 0.5) { + if (input[5] >= 1.5) { + if (input[0] >= -0.79936504) { + var14 = params[211]; + } else { + var14 = params[212]; + } + } else { + if (input[0] >= -0.27433467) { + var14 = params[213]; + } else { + var14 = params[214]; + } + } + } else { + if (input[2] >= 0.3375095) { + if (input[2] >= 1.7933712) { + var14 = params[215]; + } else { + var14 = params[216]; + } + } else { + if (input[0] >= -0.8309928) { + var14 = params[217]; + } else { + var14 = params[218]; + } + } + } + } + double var15; + if (input[0] >= -1.2908344) { + if (input[0] >= -1.2877609) { + if (input[0] >= -1.2833984) { + if (input[0] >= -1.2753179) { + var15 = params[219]; + } else { + var15 = params[220]; + } + } else { + var15 = params[221]; + } + } else { + if (input[0] >= -1.2893472) { + var15 = params[222]; + } else { + var15 = params[223]; + } + } + } else { + var15 = params[224]; + } + double var16; + if (input[0] >= -0.943425) { + if (input[0] >= -0.89028245) { + if (input[4] >= -1.5) { + var16 = params[225]; + } else { + if (input[2] >= 3.2492328) { + var16 = params[226]; + } else { + var16 = params[227]; + } + } + } else { + if (input[3] >= 6.9449997) { + var16 = params[228]; + } else { + if (input[0] >= -0.92052215) { + var16 = params[229]; + } else { + var16 = params[230]; + } + } + } + } else { + if (input[0] >= -0.9524473) { + if (input[1] >= 0.27409926) { + var16 = params[231]; + } else { + if (input[2] >= 0.3375095) { + var16 = params[232]; + } else { + var16 = params[233]; + } + } + } else { + if (input[4] >= 0.5) { + if (input[1] >= 0.27409926) { + var16 = params[234]; + } else { + var16 = params[235]; + } + } else { + if (input[0] >= -0.9611722) { + var16 = params[236]; + } else { + var16 = params[237]; + } + } + } + } + double var17; + if (input[6] >= 7.5) { + if (input[2] >= 3.2492328) { + if (input[0] >= -0.7591116) { + var17 = params[238]; + } else { + if (input[0] >= -0.8616787) { + var17 = params[239]; + } else { + var17 = params[240]; + } + } + } else { + if (input[1] >= -0.60984224) { + if (input[0] >= -0.79941463) { + var17 = params[241]; + } else { + var17 = params[242]; + } + } else { + var17 = params[243]; + } + } + } else { + if (input[4] >= 1.5) { + if (input[13] >= 0.5) { + if (input[6] >= 3.5) { + var17 = params[244]; + } else { + var17 = params[245]; + } + } else { + if (input[11] >= 0.5) { + var17 = params[246]; + } else { + var17 = params[247]; + } + } + } else { + if (input[13] >= 0.5) { + if (input[6] >= 2.5) { + var17 = params[248]; + } else { + var17 = params[249]; + } + } else { + if (input[5] >= 0.5) { + var17 = params[250]; + } else { + var17 = params[251]; + } + } + } + } + double var18; + if (input[6] >= 1.5) { + if (input[1] >= 0.8623338) { + if (input[0] >= -0.96910393) { + if (input[0] >= -0.7581202) { + var18 = params[252]; + } else { + var18 = params[253]; + } + } else { + if (input[0] >= -0.97832453) { + var18 = params[254]; + } else { + var18 = params[255]; + } + } + } else { + if (input[0] >= -1.0342927) { + if (input[0] >= -1.030773) { + var18 = params[256]; + } else { + var18 = params[257]; + } + } else { + if (input[4] >= -1.5) { + var18 = params[258]; + } else { + var18 = params[259]; + } + } + } + } else { + if (input[0] >= -0.58600175) { + var18 = params[260]; + } else { + if (input[13] >= 0.5) { + if (input[4] >= 0.5) { + var18 = params[261]; + } else { + var18 = params[262]; + } + } else { + if (input[0] >= -1.2735829) { + var18 = params[263]; + } else { + var18 = params[264]; + } + } + } + } + double var19; + if (input[1] >= 1.4505682) { + if (input[2] >= 0.3375095) { + if (input[10] >= 0.5) { + if (input[6] >= 2.5) { + var19 = params[265]; + } else { + var19 = params[266]; + } + } else { + if (input[2] >= 1.7933712) { + var19 = params[267]; + } else { + var19 = params[268]; + } + } + } else { + if (input[5] >= 1.5) { + if (input[6] >= 2.5) { + var19 = params[269]; + } else { + var19 = params[270]; + } + } else { + if (input[6] >= 2.5) { + var19 = params[271]; + } else { + var19 = params[272]; + } + } + } + } else { + if (input[1] >= 0.8623338) { + if (input[0] >= -1.1637781) { + if (input[0] >= -1.1464274) { + var19 = params[273]; + } else { + var19 = params[274]; + } + } else { + if (input[2] >= 0.3375095) { + var19 = params[275]; + } else { + var19 = params[276]; + } + } + } else { + if (input[3] >= 15.275) { + var19 = params[277]; + } else { + if (input[2] >= 3.2492328) { + var19 = params[278]; + } else { + var19 = params[279]; + } + } + } + } + double var20; + if (input[2] >= 0.3375095) { + if (input[0] >= -0.38770872) { + if (input[4] >= -0.5) { + if (input[2] >= 1.7933712) { + var20 = params[280]; + } else { + var20 = params[281]; + } + } else { + if (input[2] >= 1.7933712) { + var20 = params[282]; + } else { + var20 = params[283]; + } + } + } else { + if (input[4] >= 0.5) { + if (input[0] >= -1.1215913) { + var20 = params[284]; + } else { + var20 = params[285]; + } + } else { + if (input[7] >= 0.5) { + var20 = params[286]; + } else { + var20 = params[287]; + } + } + } + } else { + if (input[11] >= 0.5) { + if (input[8] >= 0.5) { + if (input[0] >= -0.97723395) { + var20 = params[288]; + } else { + var20 = params[289]; + } + } else { + if (input[0] >= -0.17330435) { + var20 = params[290]; + } else { + var20 = params[291]; + } + } + } else { + if (input[0] >= 1.774677) { + if (input[6] >= 2.5) { + var20 = params[292]; + } else { + var20 = params[293]; + } + } else { + if (input[6] >= 2.5) { + var20 = params[294]; + } else { + var20 = params[295]; + } + } + } + } + double var21; + if (input[3] >= -11.385) { + if (input[1] >= 2.3345098) { + if (input[4] >= 2.5) { + if (input[6] >= 4.5) { + var21 = params[296]; + } else { + var21 = params[297]; + } + } else { + if (input[0] >= -1.0748932) { + var21 = params[298]; + } else { + var21 = params[299]; + } + } + } else { + if (input[1] >= 0.27409926) { + if (input[5] >= 0.5) { + var21 = params[300]; + } else { + var21 = params[301]; + } + } else { + if (input[13] >= 0.5) { + var21 = params[302]; + } else { + var21 = params[303]; + } + } + } + } else { + var21 = params[304]; + } + double var22; + if (input[0] >= -1.2305534) { + if (input[0] >= -1.2270832) { + if (input[0] >= -1.2170694) { + if (input[0] >= -1.2048744) { + var22 = params[305]; + } else { + var22 = params[306]; + } + } else { + if (input[4] >= 0.5) { + var22 = params[307]; + } else { + var22 = params[308]; + } + } + } else { + var22 = params[309]; + } + } else { + if (input[0] >= -1.2419057) { + if (input[0] >= -1.2383859) { + if (input[0] >= -1.2345688) { + var22 = params[310]; + } else { + var22 = params[311]; + } + } else { + var22 = params[312]; + } + } else { + if (input[0] >= -1.2443843) { + var22 = params[313]; + } else { + if (input[0] >= -1.2451775) { + var22 = params[314]; + } else { + var22 = params[315]; + } + } + } + } + double var23; + if (input[0] >= -0.23313928) { + if (input[3] >= 5.5550003) { + if (input[5] >= 1.5) { + if (input[5] >= 2.5) { + var23 = params[316]; + } else { + var23 = params[317]; + } + } else { + if (input[1] >= 0.8623338) { + var23 = params[318]; + } else { + var23 = params[319]; + } + } + } else { + if (input[3] >= 4.165) { + if (input[1] >= -0.60984224) { + var23 = params[320]; + } else { + var23 = params[321]; + } + } else { + if (input[13] >= 0.5) { + var23 = params[322]; + } else { + var23 = params[323]; + } + } + } + } else { + if (input[3] >= -4.165) { + if (input[0] >= -0.29907173) { + if (input[1] >= -0.9044894) { + var23 = params[324]; + } else { + var23 = params[325]; + } + } else { + if (input[5] >= 1.5) { + var23 = params[326]; + } else { + var23 = params[327]; + } + } + } else { + if (input[11] >= 0.5) { + if (input[3] >= -5.835) { + var23 = params[328]; + } else { + var23 = params[329]; + } + } else { + if (input[3] >= -5.5550003) { + var23 = params[330]; + } else { + var23 = params[331]; + } + } + } + } + double var24; + if (input[4] >= 1.5) { + if (input[6] >= 2.5) { + if (input[3] >= 8.335) { + var24 = params[332]; + } else { + if (input[3] >= -4.165) { + var24 = params[333]; + } else { + var24 = params[334]; + } + } + } else { + var24 = params[335]; + } + } else { + if (input[5] >= 1.5) { + if (input[13] >= 0.5) { + if (input[8] >= 0.5) { + var24 = params[336]; + } else { + var24 = params[337]; + } + } else { + if (input[3] >= 6.8) { + var24 = params[338]; + } else { + var24 = params[339]; + } + } + } else { + if (input[13] >= 0.5) { + if (input[5] >= 0.5) { + var24 = params[340]; + } else { + var24 = params[341]; + } + } else { + if (input[11] >= 0.5) { + var24 = params[342]; + } else { + var24 = params[343]; + } + } + } + } + double var25; + if (input[3] >= 5.5550003) { + if (input[4] >= 0.5) { + if (input[5] >= 1.5) { + var25 = params[344]; + } else { + if (input[3] >= 16.945) { + var25 = params[345]; + } else { + var25 = params[346]; + } + } + } else { + if (input[13] >= 0.5) { + if (input[1] >= -0.9044894) { + var25 = params[347]; + } else { + var25 = params[348]; + } + } else { + if (input[7] >= 0.5) { + var25 = params[349]; + } else { + var25 = params[350]; + } + } + } + } else { + if (input[8] >= 0.5) { + if (input[5] >= 2.5) { + if (input[3] >= -1.39) { + var25 = params[351]; + } else { + var25 = params[352]; + } + } else { + if (input[3] >= 1.385) { + var25 = params[353]; + } else { + var25 = params[354]; + } + } + } else { + if (input[5] >= 1.5) { + if (input[5] >= 2.5) { + var25 = params[355]; + } else { + var25 = params[356]; + } + } else { + if (input[7] >= 0.5) { + var25 = params[357]; + } else { + var25 = params[358]; + } + } + } + } + double var26; + if (input[0] >= -1.0577409) { + if (input[0] >= -1.0321611) { + if (input[0] >= -1.031368) { + var26 = params[359]; + } else { + if (input[10] >= 0.5) { + var26 = params[360]; + } else { + var26 = params[361]; + } + } + } else { + if (input[0] >= -1.0363252) { + if (input[10] >= 0.5) { + var26 = params[362]; + } else { + var26 = params[363]; + } + } else { + if (input[0] >= -1.0379117) { + var26 = params[364]; + } else { + var26 = params[365]; + } + } + } + } else { + if (input[0] >= -1.0630949) { + var26 = params[366]; + } else { + if (input[9] >= 0.5) { + if (input[0] >= -1.1243675) { + var26 = params[367]; + } else { + var26 = params[368]; + } + } else { + if (input[5] >= 0.5) { + var26 = params[369]; + } else { + var26 = params[370]; + } + } + } + } + double var27; + if (input[0] >= 3.4985871) { + var27 = params[371]; + } else { + if (input[0] >= -1.2877609) { + if (input[0] >= -1.2194489) { + if (input[0] >= -1.1886144) { + var27 = params[372]; + } else { + var27 = params[373]; + } + } else { + if (input[0] >= -1.2219276) { + var27 = params[374]; + } else { + var27 = params[375]; + } + } + } else { + if (input[10] >= 0.5) { + var27 = params[376]; + } else { + if (input[6] >= 1.5) { + var27 = params[377]; + } else { + var27 = params[378]; + } + } + } + } + double var28; + if (input[0] >= -0.98506653) { + if (input[0] >= -0.97316897) { + if (input[0] >= -0.9722271) { + if (input[0] >= -0.9719792) { + var28 = params[379]; + } else { + var28 = params[380]; + } + } else { + var28 = params[381]; + } + } else { + if (input[0] >= -0.9796135) { + if (input[4] >= 0.5) { + var28 = params[382]; + } else { + var28 = params[383]; + } + } else { + if (input[0] >= -0.9821913) { + var28 = params[384]; + } else { + var28 = params[385]; + } + } + } + } else { + if (input[0] >= -0.9951795) { + if (input[0] >= -0.9861572) { + var28 = params[386]; + } else { + if (input[0] >= -0.9890324) { + var28 = params[387]; + } else { + var28 = params[388]; + } + } + } else { + if (input[0] >= -1.0013762) { + if (input[3] >= 1.39) { + var28 = params[389]; + } else { + var28 = params[390]; + } + } else { + if (input[6] >= 5.5) { + var28 = params[391]; + } else { + var28 = params[392]; + } + } + } + } + double var29; + if (input[0] >= -1.1534669) { + if (input[0] >= -1.1388428) { + if (input[0] >= -1.0633923) { + var29 = params[393]; + } else { + if (input[0] >= -1.0981431) { + var29 = params[394]; + } else { + var29 = params[395]; + } + } + } else { + if (input[1] >= 0.27409926) { + var29 = params[396]; + } else { + if (input[1] >= -0.60984224) { + var29 = params[397]; + } else { + var29 = params[398]; + } + } + } + } else { + if (input[0] >= -1.1652157) { + if (input[1] >= 0.8623338) { + var29 = params[399]; + } else { + if (input[6] >= 2.5) { + var29 = params[400]; + } else { + var29 = params[401]; + } + } + } else { + if (input[6] >= 2.5) { + if (input[1] >= -0.60984224) { + var29 = params[402]; + } else { + var29 = params[403]; + } + } else { + if (input[1] >= -0.9044894) { + var29 = params[404]; + } else { + var29 = params[405]; + } + } + } + } + return 0.5 + (var0 + var1 + var2 + var3 + var4 + var5 + var6 + var7 + var8 + var9 + var10 + var11 + var12 + var13 + var14 + var15 + var16 + var17 + var18 + var19 + var20 + var21 + var22 + var23 + var24 + var25 + var26 + var27 + var28 + var29); + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_right_before_left.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_right_before_left.java new file mode 100644 index 00000000000..0d5c0a6bd8d --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_right_before_left.java @@ -0,0 +1,1551 @@ +package org.matsim.application.prepare.network.params.ref; +import org.matsim.application.prepare.network.params.FeatureRegressor; +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; + +/** +* Generated model, do not modify. +*/ +final class GermanyNetworkParams_speedRelative_right_before_left implements FeatureRegressor { + + public static GermanyNetworkParams_speedRelative_right_before_left INSTANCE = new GermanyNetworkParams_speedRelative_right_before_left(); + public static final double[] DEFAULT_PARAMS = {0.8969346880912781, 0.8932791352272034, 0.8656430840492249, 0.9045125842094421, 0.8472854495048523, 0.899616003036499, 0.9020329117774963, 0.8867653608322144, 0.8737413287162781, 0.8814451098442078, 0.9342221617698669, 0.905823290348053, 0.8733933568000793, -0.017216484993696213, 0.01411882508546114, -0.024693334475159645, 0.0034817014820873737, -0.014023089781403542, 0.009468963369727135, 0.00420250603929162, -0.03606761619448662, 0.000137182287289761, -0.008697520941495895, 0.04457535967230797, 0.015947440639138222, -0.01651959866285324, 0.023372743278741837, 0.003933880012482405, -0.01959068886935711, -0.005146856885403395, -0.021225718781352043, 0.034075163304805756, -0.09747143089771271, 0.04583640396595001, -0.0708184763789177, -0.03882693126797676, -0.007437888998538256, 0.04738380387425423, 0.008490425534546375, -0.025317160412669182, 0.00033890557824634016, -0.003862918121740222, -0.021145282313227654, -0.021151555702090263, 0.026381535455584526, 0.00825554970651865, -0.010276524350047112, -0.00837455503642559, -0.0076192086562514305, 0.017878109589219093, 0.04692127928137779, -0.02493266761302948, 0.0079382648691535, 0.011609111912548542, 0.016182217746973038, -0.003118315478786826, -0.0009778261883184314, -0.009727278724312782, -0.029686780646443367, 0.0025491476990282536, -0.010214459151029587, -0.03162773326039314, -0.005565272178500891, 0.02743721939623356, -0.015804193913936615, 0.02247174084186554, 0.0034927036613225937, -0.019536947831511497, 0.027158482000231743, -0.008909083902835846, -0.021149015054106712, 0.03434921056032181, -0.09737152606248856, 0.04595226049423218, -0.0709335058927536, -0.009865057654678822, 0.04743091017007828, 0.00843324139714241, 0.022146187722682953, 0.0033186497166752815, -0.019475700333714485, -0.0050894212909042835, -0.021111169829964638, 0.034513991326093674, -0.09724652022123337, 0.04596761614084244, -0.0710335299372673, -0.03878302872180939, -0.007461365777999163, 0.04749203845858574, 0.008395785465836525, -0.013853960670530796, 0.020882010459899902, -0.02637983299791813, 0.0038152551278471947, -0.01424961257725954, -0.0299422238022089, 0.0073717995546758175, 0.006415883544832468, -0.010157612152397633, -0.02570916898548603, -0.024049270898103714, -0.004721971228718758, 0.025308137759566307, -0.0013110479339957237, 0.008450356312096119, -0.026412954553961754, 0.05281567573547363, -0.01731293462216854, 0.023462241515517235, -0.009829001501202583, -0.04823678731918335, -0.02839708887040615, 0.01954198256134987, -0.001611438114196062, -0.0008953792275860906, 0.0050756847485899925, 0.008615916594862938, 0.011866389773786068, -0.02682277001440525, 0.003962477669119835, -0.014306685887277126, -0.03013903833925724, 0.007373748812824488, 0.006462195422500372, -0.025752076879143715, 0.024132251739501953, -0.07060722261667252, 0.07418836653232574, 0.0035389033146202564, -0.016978375613689423, -0.014731049537658691, 0.006670588161796331, -0.05935036018490791, 0.09828150272369385, -0.016232367604970932, 0.015815993770956993, -0.009821303188800812, -0.017407074570655823, -0.021032890304923058, -0.026629488915205002, -0.026723764836788177, 0.016459550708532333, -0.04799484461545944, 0.03917107358574867, 0.007095396053045988, 0.0029436347540467978, -0.023539600893855095, 0.007018357515335083, -0.025774525478482246, -0.021265365183353424, -0.026607178151607513, 0.015519917011260986, 0.12191402912139893, -0.014844520017504692, -0.0005782489897683263, 0.007428263779729605, -0.019149960950016975, 0.02712146006524563, -0.013160127215087414, 0.020213039591908455, -0.07122298330068588, 0.0027933744713664055, 0.006170899607241154, -0.06295029073953629, -0.059922877699136734, 0.04761561006307602, -0.02492097206413746, 0.026180438697338104, -0.016804074868559837, -0.006493807304650545, -0.008959464728832245, 0.022347930818796158, 0.004313645418733358, 0.016678636893630028, 0.0018308702856302261, -0.016901716589927673, -0.014502751640975475, -0.012276777997612953, -0.025795644149184227, -0.02160576917231083, 0.0018233073642477393, 0.009941601194441319, 0.048514872789382935, -0.06539357453584671, -0.016923826187849045, -0.01950983703136444, 0.023318078368902206, -0.06070621684193611, 0.024262741208076477, 0.00615229457616806, 0.005709284916520119, -0.0011453420156612992, -0.025743534788489342, 0.0018225166713818908, 0.01720350608229637, -0.016950957477092743, -0.019725296646356583, 0.023503601551055908, -0.06073663756251335, 0.02396107092499733, 0.005964959971606731, 0.005689680576324463, -0.0011207155184820294, 0.018986374139785767, 0.02193332277238369, 0.013194665312767029, -0.02508479543030262, -0.00043657340575009584, -0.007130774669349194, 0.004492490086704493, 0.023670580238103867, -0.060764018446207047, 0.023689571768045425, 0.010371639393270016, 0.001462819636799395, -0.025774789974093437, -0.059983160346746445, 0.014743374660611153, 0.026615995913743973, 0.09240083396434784, -0.00029774231370538473, -0.0071018454618752, 0.0042695882730185986, 0.023820850998163223, 6.864430906716734e-05, 0.010338236577808857, -0.003967626951634884, 0.015529663302004337, 0.12203358113765717, -0.01491069421172142, 0.013195684179663658, -0.022839980199933052, -0.016367319971323013, -0.01612250693142414, -0.006203614640980959, 0.007776564918458462, 0.017655564472079277, -0.01097297016531229, -0.003169120755046606, 0.072976253926754, -0.014190016314387321, -0.048480477184057236, -0.04644166678190231, -0.013813636265695095, 0.024412240833044052, -0.012622895650565624, 0.008132502436637878, -0.015751205384731293, 0.007804387249052525, 0.0176373478025198, -0.010915062390267849, 0.01407675351947546, 0.06408719718456268, -0.014134122058749199, -0.07820764929056168, 0.0284259095788002, -0.01390476431697607, 0.024487245827913284, -0.012625892646610737, 0.047943953424692154, -0.012636682949960232, -0.04461010918021202, -0.01536747720092535, 0.010182047262787819, -0.006486869882792234, -0.007890123873949051, -0.03694796934723854, 0.008161875419318676, 0.06943466514348984, -0.07080549001693726, 0.0627005472779274, 0.0011383740929886699, -0.0002732686698436737, 0.009764869697391987, -0.0376119464635849, -0.015571813099086285, 0.010045111179351807, 0.02624466083943844, -0.03264055401086807, -0.08527520298957825, -0.04906155541539192, -0.12232682853937149, -0.01743733510375023, 0.03188442066311836, -0.0009637424955144525, -0.0001507757551735267, 0.010490433312952518, 0.0028354472015053034, -0.037682339549064636, -0.015478742308914661, 0.009921867400407791, 0.026277689263224602, -0.032701075077056885, -0.09033584594726562, -0.1224091649055481, -0.017379816621541977, 0.03187757357954979, -0.0009695034823380411, 0.014686145819723606, -0.016170324757695198, 0.010904341004788876, 0.0034459964372217655, 0.010398865677416325, -0.081662118434906, -0.07766725867986679, -0.005778642371296883, 0.06101527065038681, -0.019757047295570374, 0.00609148433431983, -0.00129152019508183, 0.025983769446611404, 0.025266770273447037, 0.0021771041210740805, 0.04833025485277176, -0.13348862528800964, -0.01959702931344509, -0.05237772688269615, 0.10998885333538055, -0.011016570962965488, 0.0009022228186950088, 0.02465425804257393, 0.02398439310491085, -0.06955941766500473, 0.00030739509384147823, 0.06586393713951111, -0.04652060940861702, 0.08925998955965042, -0.06494390964508057, 0.029171675443649292, -0.050108082592487335, 0.011544130742549896, -0.0980726033449173, 0.009651513770222664, -0.034518055617809296, 0.019514210522174835, 0.06276965141296387, 0.0011355512542650104, 0.02537025511264801, 0.020401442423462868, -0.0648268461227417, 0.02912980131804943, -0.02259134128689766, 0.030576763674616814, -0.0979703962802887, 0.024685408920049667, -0.03697166591882706, 0.017974017187952995, -0.011090702377259731, -0.009887231513857841, -0.0006101102335378528, 0.014120001345872879, 0.0019063273211941123, 0.04046299681067467, -0.11613050103187561, 0.027663789689540863, -0.0016440957551822066, -0.08562656491994858, 0.016495544463396072, 0.02536923997104168, -0.09535735845565796, -0.004202811513096094, -0.018656302243471146, -0.0026488236617296934, 0.025478806346654892, 0.0012381263077259064, 0.036716144531965256, -0.11594530194997787, 0.027645956724882126, -0.007183317560702562, -0.08550762385129929, 0.06586962193250656, -0.060880694538354874, 0.02534572221338749, -0.02865692228078842, -0.018712729215621948, -0.002650597831234336, 0.014199822209775448, 0.001779478508979082, -0.01193657424300909, -0.017614424228668213, -0.05736732855439186, 0.07628544420003891, 0.01036988478153944, 0.052429914474487305, -0.05441503971815109, 0.03131815418601036, -0.07093314826488495, 0.06284057348966599, -0.0014957136008888483}; + + @Override + public double predict(Object2DoubleMap ft) { + return predict(ft, DEFAULT_PARAMS); + } + + @Override + public double[] getData(Object2DoubleMap ft) { + double[] data = new double[14]; + data[0] = (ft.getDouble("length") - 129.1767954600338) / 78.97322235207317; + data[1] = (ft.getDouble("speed") - 8.33391612331965) / 0.1443092283706778; + data[2] = (ft.getDouble("num_lanes") - 1.0065201642115431) / 0.08720432118127261; + data[3] = ft.getDouble("change_speed"); + data[4] = ft.getDouble("change_num_lanes"); + data[5] = ft.getDouble("num_to_links"); + data[6] = ft.getDouble("junction_inc_lanes"); + data[7] = ft.getDouble("priority_lower"); + data[8] = ft.getDouble("priority_equal"); + data[9] = ft.getDouble("priority_higher"); + data[10] = ft.getDouble("is_secondary_or_higher"); + data[11] = ft.getDouble("is_primary_or_higher"); + data[12] = ft.getDouble("is_motorway"); + data[13] = ft.getDouble("is_link"); + + return data; + } + + @Override + public double predict(Object2DoubleMap ft, double[] params) { + + double[] data = getData(ft); + for (int i = 0; i < data.length; i++) + if (Double.isNaN(data[i])) throw new IllegalArgumentException("Invalid data at index: " + i); + + return score(data, params); + } + public static double score(double[] input, double[] params) { + double var0; + if (input[0] <= -0.8087145687851901) { + if (input[5] > 2.5000000000000004) { + if (input[0] <= -1.203215376427391) { + var0 = params[0]; + } else { + var0 = params[1]; + } + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var0 = params[2]; + } else { + if (input[0] <= -1.265641599559346) { + if (input[0] <= -1.2806466856468441) { + var0 = params[3]; + } else { + var0 = params[4]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var0 = params[5]; + } else { + if (input[0] <= -1.1611124977430605) { + var0 = params[6]; + } else { + var0 = params[7]; + } + } + } + } + } + } else { + if (input[5] > 2.5000000000000004) { + var0 = params[8]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var0 = params[9]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var0 = params[10]; + } else { + if (input[0] > 0.9463740026559045) { + var0 = params[11]; + } else { + var0 = params[12]; + } + } + } + } + } + double var1; + if (input[0] <= -0.8087145687851901) { + if (input[5] > 2.5000000000000004) { + if (input[0] <= -1.2147382695409974) { + var1 = params[13]; + } else { + var1 = params[14]; + } + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var1 = params[15]; + } else { + if (input[0] <= -1.265641599559346) { + if (input[6] > 2.5000000000000004) { + var1 = params[16]; + } else { + var1 = params[17]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var1 = params[18]; + } else { + var1 = params[19]; + } + } + } + } + } else { + if (input[5] > 2.5000000000000004) { + if (input[0] > 0.2844407746187974) { + var1 = params[20]; + } else { + var1 = params[21]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var1 = params[22]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var1 = params[23]; + } else { + if (input[0] > 0.9463740026559045) { + var1 = params[24]; + } else { + var1 = params[25]; + } + } + } + } + } + double var2; + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var2 = params[26]; + } else { + var2 = params[27]; + } + } else { + var2 = params[28]; + } + } else { + if (input[5] > 2.5000000000000004) { + if (input[6] > 3.5000000000000004) { + var2 = params[29]; + } else { + var2 = params[30]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + var2 = params[31]; + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var2 = params[32]; + } else { + var2 = params[33]; + } + } + } else { + if (input[5] > 1.5000000000000002) { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var2 = params[34]; + } else { + if (input[6] > 3.5000000000000004) { + var2 = params[35]; + } else { + var2 = params[36]; + } + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var2 = params[37]; + } else { + var2 = params[38]; + } + } + } + } + } + double var3; + if (input[0] <= -0.8087145687851901) { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var3 = params[39]; + } else { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.2147382695409974) { + var3 = params[40]; + } else { + var3 = params[41]; + } + } else { + if (input[0] <= -1.265641599559346) { + if (input[6] > 2.5000000000000004) { + var3 = params[42]; + } else { + var3 = params[43]; + } + } else { + if (input[0] <= -1.1611124977430605) { + var3 = params[44]; + } else { + var3 = params[45]; + } + } + } + } + } else { + if (input[0] > 2.8196671974107512) { + var3 = params[46]; + } else { + if (input[6] > 3.5000000000000004) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var3 = params[47]; + } else { + if (input[0] > 0.2844407746187974) { + var3 = params[48]; + } else { + var3 = params[49]; + } + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var3 = params[50]; + } else { + var3 = params[51]; + } + } + } + } + double var4; + if (input[0] <= -0.7717400106624095) { + if (input[5] > 2.5000000000000004) { + if (input[0] <= -1.203215376427391) { + var4 = params[52]; + } else { + var4 = params[53]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + var4 = params[54]; + } else { + var4 = params[55]; + } + } else { + if (input[0] <= -1.265641599559346) { + if (input[6] > 2.5000000000000004) { + var4 = params[56]; + } else { + var4 = params[57]; + } + } else { + if (input[3] > 2.775000000000001) { + var4 = params[58]; + } else { + var4 = params[59]; + } + } + } + } + } else { + if (input[0] > 2.8196671974107512) { + var4 = params[60]; + } else { + if (input[5] > 2.5000000000000004) { + if (input[0] > 0.2844407746187974) { + var4 = params[61]; + } else { + var4 = params[62]; + } + } else { + if (input[0] <= -0.5611623046412313) { + var4 = params[63]; + } else { + var4 = params[64]; + } + } + } + } + double var5; + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[65]; + } else { + var5 = params[66]; + } + } else { + var5 = params[67]; + } + } else { + if (input[5] > 2.5000000000000004) { + if (input[6] > 3.5000000000000004) { + if (input[5] > 3.5000000000000004) { + var5 = params[68]; + } else { + var5 = params[69]; + } + } else { + var5 = params[70]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + var5 = params[71]; + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[72]; + } else { + var5 = params[73]; + } + } + } else { + if (input[5] > 1.5000000000000002) { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[74]; + } else { + var5 = params[75]; + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var5 = params[76]; + } else { + var5 = params[77]; + } + } + } + } + } + double var6; + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[78]; + } else { + var6 = params[79]; + } + } else { + var6 = params[80]; + } + } else { + if (input[5] > 2.5000000000000004) { + if (input[6] > 3.5000000000000004) { + var6 = params[81]; + } else { + var6 = params[82]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[5] > 1.5000000000000002) { + var6 = params[83]; + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[84]; + } else { + var6 = params[85]; + } + } + } else { + if (input[5] > 1.5000000000000002) { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[86]; + } else { + if (input[6] > 3.5000000000000004) { + var6 = params[87]; + } else { + var6 = params[88]; + } + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var6 = params[89]; + } else { + var6 = params[90]; + } + } + } + } + } + double var7; + if (input[0] <= -0.7717400106624095) { + if (input[5] > 2.5000000000000004) { + if (input[0] <= -1.2274007894460592) { + var7 = params[91]; + } else { + var7 = params[92]; + } + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var7 = params[93]; + } else { + if (input[0] <= -1.265641599559346) { + if (input[6] > 2.5000000000000004) { + var7 = params[94]; + } else { + var7 = params[95]; + } + } else { + if (input[3] > 2.775000000000001) { + var7 = params[96]; + } else { + if (input[0] <= -1.1611124977430605) { + var7 = params[97]; + } else { + var7 = params[98]; + } + } + } + } + } + } else { + if (input[0] > 2.8196671974107512) { + var7 = params[99]; + } else { + if (input[0] <= -0.42282427467843087) { + var7 = params[100]; + } else { + if (input[0] > 0.0546793509414504) { + if (input[0] > 0.23049843982323412) { + var7 = params[101]; + } else { + var7 = params[102]; + } + } else { + var7 = params[103]; + } + } + } + } + double var8; + if (input[0] <= -0.8087145687851901) { + if (input[5] > 2.5000000000000004) { + if (input[0] <= -1.2399366841520705) { + var8 = params[104]; + } else { + var8 = params[105]; + } + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var8 = params[106]; + } else { + if (input[0] <= -1.4358258670833768) { + if (input[6] > 2.5000000000000004) { + var8 = params[107]; + } else { + var8 = params[108]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var8 = params[109]; + } else { + var8 = params[110]; + } + } + } + } + } else { + if (input[0] > 3.0312579050243342) { + var8 = params[111]; + } else { + if (input[5] > 2.5000000000000004) { + if (input[0] > 0.2844407746187974) { + var8 = params[112]; + } else { + if (input[6] > 4.500000000000001) { + var8 = params[113]; + } else { + if (input[0] <= -0.42282427467843087) { + var8 = params[114]; + } else { + var8 = params[115]; + } + } + } + } else { + var8 = params[116]; + } + } + } + double var9; + if (input[0] <= -0.7717400106624095) { + if (input[5] > 2.5000000000000004) { + if (input[0] <= -1.203215376427391) { + var9 = params[117]; + } else { + var9 = params[118]; + } + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var9 = params[119]; + } else { + if (input[0] <= -1.265641599559346) { + if (input[6] > 2.5000000000000004) { + var9 = params[120]; + } else { + var9 = params[121]; + } + } else { + if (input[3] > 2.775000000000001) { + var9 = params[122]; + } else { + if (input[0] <= -1.1611124977430605) { + var9 = params[123]; + } else { + var9 = params[124]; + } + } + } + } + } + } else { + if (input[0] <= -0.42282427467843087) { + var9 = params[125]; + } else { + if (input[0] > 4.052173572369945) { + var9 = params[126]; + } else { + if (input[0] <= -0.3016439591869893) { + if (input[5] > 1.5000000000000002) { + var9 = params[127]; + } else { + var9 = params[128]; + } + } else { + var9 = params[129]; + } + } + } + } + double var10; + if (input[0] <= -0.8087145687851901) { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + var10 = params[130]; + } else { + var10 = params[131]; + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.3880881670412937) { + var10 = params[132]; + } else { + if (input[0] <= -0.8391679291568637) { + var10 = params[133]; + } else { + var10 = params[134]; + } + } + } else { + if (input[5] > 1.5000000000000002) { + if (input[0] <= -1.3880881670412937) { + var10 = params[135]; + } else { + var10 = params[136]; + } + } else { + var10 = params[137]; + } + } + } + } else { + if (input[0] <= -0.42282427467843087) { + var10 = params[138]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var10 = params[139]; + } else { + if (input[0] <= -0.3016439591869893) { + var10 = params[140]; + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var10 = params[141]; + } else { + var10 = params[142]; + } + } + } + } + } + double var11; + if (input[0] <= -0.7717400106624095) { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -1.192768797505715) { + var11 = params[143]; + } else { + var11 = params[144]; + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.3880881670412937) { + var11 = params[145]; + } else { + var11 = params[146]; + } + } else { + if (input[3] > 0.000000000000000000000000000000000010000000180025095) { + var11 = params[147]; + } else { + var11 = params[148]; + } + } + } + } else { + if (input[0] <= -0.42282427467843087) { + var11 = params[149]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var11 = params[150]; + } else { + if (input[0] <= -0.3016439591869893) { + var11 = params[151]; + } else { + if (input[0] > 2.430864523725828) { + if (input[0] > 2.5447005776723337) { + var11 = params[152]; + } else { + var11 = params[153]; + } + } else { + if (input[0] > 2.0490262359886886) { + var11 = params[154]; + } else { + var11 = params[155]; + } + } + } + } + } + } + double var12; + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[6] > 3.5000000000000004) { + var12 = params[156]; + } else { + var12 = params[157]; + } + } else { + if (input[5] > 2.5000000000000004) { + if (input[5] > 3.5000000000000004) { + var12 = params[158]; + } else { + var12 = params[159]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var12 = params[160]; + } else { + if (input[5] > 1.5000000000000002) { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var12 = params[161]; + } else { + if (input[6] > 2.5000000000000004) { + if (input[3] > 2.775000000000001) { + var12 = params[162]; + } else { + var12 = params[163]; + } + } else { + if (input[3] > 2.775000000000001) { + var12 = params[164]; + } else { + var12 = params[165]; + } + } + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var12 = params[166]; + } else { + if (input[6] > 2.5000000000000004) { + var12 = params[167]; + } else { + var12 = params[168]; + } + } + } + } + } + } + double var13; + if (input[0] <= -0.7717400106624095) { + if (input[5] > 1.5000000000000002) { + if (input[0] <= -1.3880881670412937) { + if (input[5] > 2.5000000000000004) { + var13 = params[169]; + } else { + var13 = params[170]; + } + } else { + if (input[5] > 2.5000000000000004) { + if (input[0] <= -1.2147382695409974) { + var13 = params[171]; + } else { + var13 = params[172]; + } + } else { + if (input[0] <= -1.1368637721248671) { + var13 = params[173]; + } else { + if (input[0] <= -1.0560135825310473) { + var13 = params[174]; + } else { + var13 = params[175]; + } + } + } + } + } else { + if (input[6] > 3.5000000000000004) { + var13 = params[176]; + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var13 = params[177]; + } else { + var13 = params[178]; + } + } + } + } else { + if (input[0] <= -0.42282427467843087) { + var13 = params[179]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var13 = params[180]; + } else { + var13 = params[181]; + } + } + } + double var14; + if (input[0] <= -1.265641599559346) { + if (input[6] > 2.5000000000000004) { + if (input[0] <= -1.2806466856468441) { + if (input[0] <= -1.3880881670412937) { + var14 = params[182]; + } else { + var14 = params[183]; + } + } else { + var14 = params[184]; + } + } else { + var14 = params[185]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9405947135964089) { + var14 = params[186]; + } else { + if (input[0] <= -0.6992470842059305) { + var14 = params[187]; + } else { + if (input[0] > 0.000000000000000000000000000000000010000000180025095) { + var14 = params[188]; + } else { + var14 = params[189]; + } + } + } + } else { + if (input[0] <= -0.7717400106624095) { + if (input[3] > 2.775000000000001) { + var14 = params[190]; + } else { + if (input[0] <= -1.182702094181191) { + var14 = params[191]; + } else { + var14 = params[192]; + } + } + } else { + if (input[0] <= -0.42282427467843087) { + var14 = params[193]; + } else { + var14 = params[194]; + } + } + } + } + double var15; + if (input[0] <= -1.265641599559346) { + if (input[6] > 2.5000000000000004) { + var15 = params[195]; + } else { + var15 = params[196]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9405947135964089) { + var15 = params[197]; + } else { + if (input[0] <= -0.6992470842059305) { + var15 = params[198]; + } else { + if (input[0] > 0.000000000000000000000000000000000010000000180025095) { + var15 = params[199]; + } else { + var15 = params[200]; + } + } + } + } else { + if (input[0] <= -0.7717400106624095) { + if (input[3] > 2.775000000000001) { + var15 = params[201]; + } else { + if (input[0] <= -1.182702094181191) { + var15 = params[202]; + } else { + var15 = params[203]; + } + } + } else { + if (input[0] <= -0.5446377161651256) { + if (input[5] > 2.5000000000000004) { + var15 = params[204]; + } else { + var15 = params[205]; + } + } else { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var15 = params[206]; + } else { + var15 = params[207]; + } + } + } + } + } + double var16; + if (input[0] <= -1.2399366841520705) { + if (input[5] > 2.5000000000000004) { + var16 = params[208]; + } else { + var16 = params[209]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9405947135964089) { + var16 = params[210]; + } else { + if (input[0] <= -0.6992470842059305) { + var16 = params[211]; + } else { + if (input[0] > 0.000000000000000000000000000000000010000000180025095) { + var16 = params[212]; + } else { + var16 = params[213]; + } + } + } + } else { + if (input[0] <= -0.7717400106624095) { + if (input[0] <= -1.182702094181191) { + var16 = params[214]; + } else { + var16 = params[215]; + } + } else { + if (input[0] <= -0.42282427467843087) { + var16 = params[216]; + } else { + if (input[0] <= -0.038010294763601994) { + var16 = params[217]; + } else { + if (input[0] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] > 0.007701402093671097) { + var16 = params[218]; + } else { + var16 = params[219]; + } + } else { + var16 = params[220]; + } + } + } + } + } + } + double var17; + if (input[0] <= -1.2399366841520705) { + if (input[5] > 2.5000000000000004) { + var17 = params[221]; + } else { + var17 = params[222]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + if (input[0] <= -0.9405947135964089) { + var17 = params[223]; + } else { + if (input[0] <= -0.6992470842059305) { + var17 = params[224]; + } else { + var17 = params[225]; + } + } + } else { + if (input[0] <= -0.8087145687851901) { + if (input[0] <= -1.182702094181191) { + var17 = params[226]; + } else { + var17 = params[227]; + } + } else { + if (input[0] > 2.430864523725828) { + if (input[0] > 2.5447005776723337) { + var17 = params[228]; + } else { + var17 = params[229]; + } + } else { + if (input[0] > 2.0490262359886886) { + var17 = params[230]; + } else { + if (input[0] > 0.972901981857009) { + if (input[0] > 1.1375780532223383) { + var17 = params[231]; + } else { + var17 = params[232]; + } + } else { + var17 = params[233]; + } + } + } + } + } + } + double var18; + if (input[0] <= -0.899251586106382) { + if (input[5] > 1.5000000000000002) { + if (input[0] <= -1.3880881670412937) { + if (input[5] > 2.5000000000000004) { + var18 = params[234]; + } else { + var18 = params[235]; + } + } else { + if (input[0] <= -0.9633239368259949) { + if (input[0] <= -1.0560135825310473) { + if (input[0] <= -1.1368637721248671) { + if (input[0] <= -1.2399366841520705) { + var18 = params[236]; + } else { + var18 = params[237]; + } + } else { + var18 = params[238]; + } + } else { + if (input[0] <= -1.026446598552728) { + var18 = params[239]; + } else { + var18 = params[240]; + } + } + } else { + var18 = params[241]; + } + } + } else { + if (input[0] <= -1.1368637721248671) { + if (input[0] <= -1.182702094181191) { + var18 = params[242]; + } else { + var18 = params[243]; + } + } else { + var18 = params[244]; + } + } + } else { + if (input[0] > 4.052173572369945) { + var18 = params[245]; + } else { + var18 = params[246]; + } + } + double var19; + if (input[0] <= -0.899251586106382) { + if (input[5] > 1.5000000000000002) { + if (input[0] <= -1.3880881670412937) { + if (input[6] > 3.5000000000000004) { + var19 = params[247]; + } else { + var19 = params[248]; + } + } else { + if (input[0] <= -0.9633239368259949) { + if (input[0] <= -1.0560135825310473) { + if (input[0] <= -1.1368637721248671) { + if (input[0] <= -1.2399366841520705) { + var19 = params[249]; + } else { + var19 = params[250]; + } + } else { + var19 = params[251]; + } + } else { + if (input[0] <= -1.0146704550410206) { + var19 = params[252]; + } else { + var19 = params[253]; + } + } + } else { + var19 = params[254]; + } + } + } else { + if (input[0] <= -1.1368637721248671) { + if (input[0] <= -1.203215376427391) { + var19 = params[255]; + } else { + var19 = params[256]; + } + } else { + var19 = params[257]; + } + } + } else { + if (input[0] > 4.052173572369945) { + var19 = params[258]; + } else { + var19 = params[259]; + } + } + double var20; + if (input[0] <= -1.2399366841520705) { + if (input[6] > 2.5000000000000004) { + if (input[0] <= -1.4358258670833768) { + var20 = params[260]; + } else { + var20 = params[261]; + } + } else { + if (input[0] <= -1.2966647733267473) { + var20 = params[262]; + } else { + var20 = params[263]; + } + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var20 = params[264]; + } else { + if (input[0] > 0.0546793509414504) { + if (input[0] > 0.20821240479032524) { + if (input[6] > 2.5000000000000004) { + if (input[6] > 4.500000000000001) { + var20 = params[265]; + } else { + if (input[0] > 2.8196671974107512) { + var20 = params[266]; + } else { + var20 = params[267]; + } + } + } else { + var20 = params[268]; + } + } else { + if (input[5] > 2.5000000000000004) { + var20 = params[269]; + } else { + var20 = params[270]; + } + } + } else { + if (input[0] > 0.03638200967863615) { + var20 = params[271]; + } else { + var20 = params[272]; + } + } + } + } + double var21; + if (input[0] <= -1.2399366841520705) { + if (input[5] > 2.5000000000000004) { + var21 = params[273]; + } else { + if (input[6] > 2.5000000000000004) { + var21 = params[274]; + } else { + if (input[0] <= -1.2966647733267473) { + var21 = params[275]; + } else { + var21 = params[276]; + } + } + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var21 = params[277]; + } else { + if (input[5] > 2.5000000000000004) { + if (input[0] <= -0.5849045294632221) { + var21 = params[278]; + } else { + if (input[0] <= -0.5014585232888648) { + var21 = params[279]; + } else { + if (input[0] <= -0.1195569229522002) { + if (input[0] <= -0.20129348893937427) { + if (input[0] <= -0.2256688397566183) { + if (input[0] <= -0.2468152479980715) { + var21 = params[280]; + } else { + var21 = params[281]; + } + } else { + var21 = params[282]; + } + } else { + var21 = params[283]; + } + } else { + var21 = params[284]; + } + } + } + } else { + var21 = params[285]; + } + } + } + double var22; + if (input[0] <= -1.2399366841520705) { + if (input[5] > 2.5000000000000004) { + var22 = params[286]; + } else { + if (input[6] > 2.5000000000000004) { + if (input[0] <= -1.3880881670412937) { + var22 = params[287]; + } else { + var22 = params[288]; + } + } else { + if (input[0] <= -1.2966647733267473) { + var22 = params[289]; + } else { + var22 = params[290]; + } + } + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var22 = params[291]; + } else { + if (input[5] > 2.5000000000000004) { + if (input[0] <= -0.5849045294632221) { + var22 = params[292]; + } else { + if (input[0] <= -0.5014585232888648) { + var22 = params[293]; + } else { + if (input[0] <= -0.1195569229522002) { + if (input[0] <= -0.20129348893937427) { + if (input[0] <= -0.2256688397566183) { + var22 = params[294]; + } else { + var22 = params[295]; + } + } else { + var22 = params[296]; + } + } else { + var22 = params[297]; + } + } + } + } else { + var22 = params[298]; + } + } + } + double var23; + if (input[5] > 1.5000000000000002) { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var23 = params[299]; + } else { + if (input[6] > 3.5000000000000004) { + var23 = params[300]; + } else { + if (input[6] > 2.5000000000000004) { + if (input[5] > 2.5000000000000004) { + var23 = params[301]; + } else { + if (input[3] > 2.775000000000001) { + var23 = params[302]; + } else { + var23 = params[303]; + } + } + } else { + if (input[3] > 2.775000000000001) { + var23 = params[304]; + } else { + var23 = params[305]; + } + } + } + } + } else { + if (input[6] > 3.5000000000000004) { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var23 = params[306]; + } else { + var23 = params[307]; + } + } else { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + if (input[10] > 0.000000000000000000000000000000000010000000180025095) { + var23 = params[308]; + } else { + var23 = params[309]; + } + } else { + if (input[6] > 2.5000000000000004) { + var23 = params[310]; + } else { + var23 = params[311]; + } + } + } + } + double var24; + if (input[0] <= -1.0560135825310473) { + if (input[0] <= -1.4358258670833768) { + var24 = params[312]; + } else { + if (input[11] > 0.000000000000000000000000000000000010000000180025095) { + var24 = params[313]; + } else { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.2147382695409974) { + if (input[0] <= -1.251332952066626) { + var24 = params[314]; + } else { + var24 = params[315]; + } + } else { + var24 = params[316]; + } + } else { + if (input[0] <= -1.1039412203717063) { + var24 = params[317]; + } else { + var24 = params[318]; + } + } + } + } + } else { + if (input[0] <= -1.026446598552728) { + var24 = params[319]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var24 = params[320]; + } else { + if (input[0] > 2.8196671974107512) { + if (input[0] > 3.6239271491807528) { + if (input[0] > 4.052173572369945) { + var24 = params[321]; + } else { + var24 = params[322]; + } + } else { + var24 = params[323]; + } + } else { + var24 = params[324]; + } + } + } + } + double var25; + if (input[0] <= -1.2399366841520705) { + if (input[0] <= -1.251332952066626) { + if (input[6] > 2.5000000000000004) { + if (input[0] <= -1.265641599559346) { + if (input[0] <= -1.2806466856468441) { + if (input[0] <= -1.3333860810514266) { + if (input[6] > 3.5000000000000004) { + var25 = params[325]; + } else { + var25 = params[326]; + } + } else { + var25 = params[327]; + } + } else { + var25 = params[328]; + } + } else { + var25 = params[329]; + } + } else { + if (input[5] > 1.5000000000000002) { + var25 = params[330]; + } else { + var25 = params[331]; + } + } + } else { + var25 = params[332]; + } + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var25 = params[333]; + } else { + if (input[0] > 0.0546793509414504) { + if (input[0] > 0.20821240479032524) { + var25 = params[334]; + } else { + var25 = params[335]; + } + } else { + if (input[0] > 0.03638200967863615) { + var25 = params[336]; + } else { + var25 = params[337]; + } + } + } + } + double var26; + if (input[0] <= -1.0560135825310473) { + if (input[0] <= -1.4358258670833768) { + var26 = params[338]; + } else { + if (input[0] <= -1.1611124977430605) { + if (input[0] <= -1.2399366841520705) { + if (input[0] <= -1.251332952066626) { + if (input[6] > 2.5000000000000004) { + if (input[0] <= -1.265641599559346) { + if (input[0] <= -1.2806466856468441) { + var26 = params[339]; + } else { + var26 = params[340]; + } + } else { + var26 = params[341]; + } + } else { + if (input[5] > 1.5000000000000002) { + var26 = params[342]; + } else { + var26 = params[343]; + } + } + } else { + var26 = params[344]; + } + } else { + var26 = params[345]; + } + } else { + if (input[5] > 1.5000000000000002) { + var26 = params[346]; + } else { + var26 = params[347]; + } + } + } + } else { + if (input[0] <= -1.026446598552728) { + var26 = params[348]; + } else { + if (input[0] > 2.8196671974107512) { + var26 = params[349]; + } else { + var26 = params[350]; + } + } + } + double var27; + if (input[0] <= -1.3880881670412937) { + var27 = params[351]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var27 = params[352]; + } else { + if (input[0] <= -1.0560135825310473) { + if (input[0] <= -1.1611124977430605) { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.2147382695409974) { + if (input[0] <= -1.251332952066626) { + var27 = params[353]; + } else { + var27 = params[354]; + } + } else { + var27 = params[355]; + } + } else { + if (input[0] <= -1.2399366841520705) { + if (input[0] <= -1.2806466856468441) { + var27 = params[356]; + } else { + if (input[0] <= -1.265641599559346) { + var27 = params[357]; + } else { + var27 = params[358]; + } + } + } else { + var27 = params[359]; + } + } + } else { + if (input[0] <= -1.1498428550275557) { + var27 = params[360]; + } else { + var27 = params[361]; + } + } + } else { + if (input[0] <= -1.026446598552728) { + var27 = params[362]; + } else { + var27 = params[363]; + } + } + } + } + double var28; + if (input[0] <= -1.4358258670833768) { + var28 = params[364]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var28 = params[365]; + } else { + if (input[0] <= -1.0560135825310473) { + if (input[0] <= -1.1611124977430605) { + if (input[6] > 3.5000000000000004) { + if (input[0] <= -1.2147382695409974) { + if (input[0] <= -1.251332952066626) { + var28 = params[366]; + } else { + var28 = params[367]; + } + } else { + var28 = params[368]; + } + } else { + if (input[0] <= -1.2399366841520705) { + if (input[0] <= -1.2806466856468441) { + var28 = params[369]; + } else { + if (input[0] <= -1.265641599559346) { + var28 = params[370]; + } else { + if (input[0] <= -1.251332952066626) { + var28 = params[371]; + } else { + var28 = params[372]; + } + } + } + } else { + var28 = params[373]; + } + } + } else { + var28 = params[374]; + } + } else { + if (input[0] <= -1.026446598552728) { + var28 = params[375]; + } else { + var28 = params[376]; + } + } + } + } + double var29; + if (input[0] <= -1.3880881670412937) { + var29 = params[377]; + } else { + if (input[2] > 0.000000000000000000000000000000000010000000180025095) { + var29 = params[378]; + } else { + if (input[0] > 0.0546793509414504) { + if (input[0] > 0.20821240479032524) { + if (input[4] > 0.000000000000000000000000000000000010000000180025095) { + var29 = params[379]; + } else { + if (input[0] > 0.2844407746187974) { + var29 = params[380]; + } else { + var29 = params[381]; + } + } + } else { + if (input[5] > 2.5000000000000004) { + if (input[0] > 0.18219092638542328) { + var29 = params[382]; + } else { + if (input[0] > 0.14439330446881357) { + var29 = params[383]; + } else { + if (input[0] > 0.1064690573531535) { + var29 = params[384]; + } else { + if (input[0] > 0.09608579103100272) { + var29 = params[385]; + } else { + var29 = params[386]; + } + } + } + } + } else { + var29 = params[387]; + } + } + } else { + if (input[0] > 0.03638200967863615) { + var29 = params[388]; + } else { + var29 = params[389]; + } + } + } + } + return var0 + var1 + var2 + var3 + var4 + var5 + var6 + var7 + var8 + var9 + var10 + var11 + var12 + var13 + var14 + var15 + var16 + var17 + var18 + var19 + var20 + var21 + var22 + var23 + var24 + var25 + var26 + var27 + var28 + var29; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_traffic_light.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_traffic_light.java new file mode 100644 index 00000000000..18cfc0554ff --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ref/GermanyNetworkParams_speedRelative_traffic_light.java @@ -0,0 +1,1647 @@ +package org.matsim.application.prepare.network.params.ref; +import org.matsim.application.prepare.network.params.FeatureRegressor; +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; + +/** +* Generated model, do not modify. +*/ +final class GermanyNetworkParams_speedRelative_traffic_light implements FeatureRegressor { + + public static GermanyNetworkParams_speedRelative_traffic_light INSTANCE = new GermanyNetworkParams_speedRelative_traffic_light(); + public static final double[] DEFAULT_PARAMS = {0.05494196340441704, 0.04779257997870445, -0.015234474092721939, 0.07736470550298691, 0.09873587638139725, 0.008024599403142929, 0.08351196348667145, 0.10926468670368195, -0.058559417724609375, -0.04763520509004593, -0.05684131011366844, -0.041668955236673355, -0.00997074693441391, 0.02661237120628357, -0.03437960147857666, -0.02870810218155384, -0.041999075561761856, 0.04567043110728264, 0.02771405316889286, -0.00476707611232996, -0.05357557162642479, -0.017584914341568947, -0.07030895352363586, -0.02354312129318714, -0.01750415377318859, 0.0739993155002594, 0.0208088718354702, 0.04332546889781952, -0.044793836772441864, -0.0002192184911109507, -0.0022371041122823954, -0.005610611289739609, -0.07203513383865356, 0.03666815534234047, 0.014177811332046986, -0.009345941245555878, 0.01586073264479637, -0.19408322870731354, 0.0013310295762494206, 0.05246831104159355, -0.034978583455085754, -0.03658885881304741, -0.07402987033128738, 0.014084706082940102, -0.03680648282170296, -0.0015945483464747667, 0.004086916800588369, -0.006683459505438805, 0.06032155081629753, 0.035939157009124756, 0.05442888289690018, -0.016226349398493767, -0.0876597911119461, 0.04168204963207245, 0.04722951352596283, -0.0016762592131271958, 0.025803618133068085, -0.011612710542976856, -0.006582271307706833, -0.002813681960105896, -0.02796594612300396, -0.018422534689307213, 0.023005982860922813, -0.02858370915055275, -0.04530055820941925, -0.045756347477436066, 0.08237827569246292, -0.09391671419143677, 0.007437951862812042, -0.06974528729915619, 0.003825301071628928, 0.013319403864443302, 0.03287561982870102, 0.05626516789197922, 0.0004987511201761663, -0.0813227966427803, -0.09187865257263184, 0.020839611068367958, -0.016477003693580627, 0.02420324645936489, -0.04686195030808449, -0.010501761920750141, 0.03780946880578995, -0.015062357299029827, 0.009624850004911423, -0.036835942417383194, 0.025251172482967377, -0.08547673374414444, -0.03463619947433472, -0.024063413962721825, 0.00894383154809475, 0.02036842703819275, -0.03764268010854721, 0.03504512086510658, 0.10648515820503235, -0.0631951317191124, 0.03052983433008194, 0.014989575371146202, -0.015113979578018188, 0.0065378411673009396, -0.005680262576788664, -0.014421471394598484, -0.000271660799626261, -0.027654381468892097, -0.0028037731535732746, -0.015686094760894775, -0.016765626147389412, 0.0019256231607869267, -0.00013922658399678767, 0.009077224880456924, 0.015840677544474602, -0.03412685543298721, -0.06759577989578247, 0.03010719083249569, 0.01474516186863184, -0.011174854822456837, -0.006634588818997145, 0.00040022918255999684, -0.030267195776104927, -0.009796671569347382, 0.004295100923627615, 0.006765577010810375, -0.0460900142788887, 0.009414967149496078, -0.04050338640809059, -0.06400635093450546, 0.03312788903713226, -0.009421229362487793, 0.09023075550794601, 0.052395857870578766, -0.039187997579574585, 0.09028498083353043, -0.037093620747327805, -0.015643062070012093, -0.00912883598357439, 0.01544719934463501, -0.03807868808507919, 0.03767954930663109, -0.028379471972584724, 0.017962932586669922, 0.015587315894663334, 0.01441947091370821, 0.0013551840092986822, 0.021745771169662476, -0.02562386728823185, -0.03568590432405472, 0.04939783364534378, -0.07852426916360855, -0.015924062579870224, 0.054845988750457764, 0.03895912319421768, 0.008636949583888054, -0.017450258135795593, 0.002697995398193598, -0.010129989124834538, 0.00457617174834013, -0.04645630717277527, -0.002303493907675147, 0.08984003961086273, -0.020053774118423462, -0.010222584940493107, 0.02176843024790287, 0.001108949538320303, 0.11584299057722092, 0.1256875842809677, -0.01127974409610033, 0.0, 0.05386563390493393, -0.06787845492362976, 0.0052926079370081425, 0.06740543246269226, -0.04552216827869415, -0.03708253055810928, 0.11921743303537369, -0.02075464464724064, -0.09385070949792862, 0.009245629422366619, 0.07638315856456757, 0.015277346596121788, 0.0029226276092231274, 0.03144538402557373, -0.00012550220708362758, -0.059757329523563385, -0.010375665500760078, 0.11395904421806335, -0.025083886459469795, 0.026127347722649574, 0.043335095047950745, -0.02150913141667843, -0.04844348877668381, -0.05051602050662041, 0.050325438380241394, 0.005146080628037453, -0.0111991036683321, -0.02230091206729412, 0.003937116824090481, 0.010075689293444157, 0.0037522052880376577, -0.03682716190814972, 0.06259677559137344, -0.01390145905315876, 0.004004108253866434, -0.05506502464413643, 0.014146552421152592, -0.08298080414533615, 0.06036271154880524, 0.017649220302700996, -0.07424549758434296, -0.01064007543027401, 0.04562237113714218, 0.03737334907054901, 0.004702978301793337, 0.04701211303472519, 0.049740299582481384, -0.008932603523135185, -0.00018998028826899827, 0.0014867562567815185, 0.09833535552024841, 0.015825586393475533, -0.023263530805706978, -0.06609666347503662, -0.021393995732069016, -0.007685319986194372, -0.03144681826233864, 0.026180842891335487, -0.04223193973302841, -0.09698043018579483, 0.042356573045253754, 0.02706247754395008, 0.07363837957382202, 0.03707076981663704, -0.11252197623252869, -0.060959555208683014, 0.012293665669858456, 0.06237619370222092, 0.008896224200725555, 0.07136287540197372, 0.008649415336549282, -0.013386181555688381, 0.009057166054844856, -0.04459235817193985, 0.04399498552083969, -0.019223731011152267, -0.0023875164333730936, 0.06532847136259079, -0.0008553717634640634, 0.1703612357378006, 0.10483639687299728, 0.0933697447180748, -0.018426110967993736, 0.11792874336242676, -0.14899668097496033, -0.0023274251725524664, 0.03347187861800194, -0.04179104417562485, -0.015197165310382843, 0.08197180181741714, -0.008846216835081577, 0.1493602693080902, 0.03148182854056358, -0.015561082400381565, -0.030860597267746925, 0.08213122189044952, -0.01307750679552555, -0.06027509272098541, 0.04081973806023598, -0.01905861496925354, -0.09909496456384659, 0.012512750923633575, 0.06225074455142021, -0.02270331420004368, 0.002883350243791938, -0.06150973588228226, -0.0060563525184988976, 0.00525425560772419, -0.03229088708758354, 0.04610208049416542, 0.003909624181687832, 0.01495292130857706, -0.030835779383778572, 0.019642261788249016, 0.05034139007329941, -0.09797187894582748, 0.007241955958306789, -0.01400011032819748, -0.020630551502108574, -0.07291948795318604, -0.05083348974585533, -0.00022685836302116513, 0.008354829624295235, 0.005579552613198757, 0.028652600944042206, -0.04632113501429558, 0.016029175370931625, 0.004957331344485283, 0.0032050206791609526, 0.0604572631418705, -0.040276866406202316, 0.05822932347655296, 0.05622018128633499, 0.012461614795029163, -0.027291085571050644, 0.012979046441614628, -0.028196725994348526, -0.000802377937361598, -0.0038899476639926434, -0.023680981248617172, -0.11050555855035782, 0.04594624042510986, 0.04995771497488022, 0.015930619090795517, -0.03386387974023819, -0.013838841579854488, 0.022164830937981606, 0.01039939746260643, -0.0021733141038566828, -0.022006060928106308, 0.0025807959027588367, -0.03482571244239807, 0.03015352226793766, 0.010282360948622227, -0.015488870441913605, -0.014940714463591576, -0.02374706044793129, 0.046672478318214417, 0.032416969537734985, 0.015097244642674923, 0.019595876336097717, -0.07559806108474731, -0.04216289892792702, 0.004835860803723335, -0.031014347448945045, 0.015382446348667145, 0.061512336134910583, -0.03035709075629711, -0.06553195416927338, -0.07939787954092026, 0.001244266051799059, 0.0009079983574338257, -0.00408412329852581, 0.029755849391222, 0.008650460280478, -0.008736466988921165, -0.03871670365333557, 0.04014125093817711, -0.009947581216692924, 0.009818813763558865, -0.012899719178676605, -0.00572023494169116, 0.047454532235860825, 0.02957983687520027, 0.03530416265130043, 0.0002597011625766754, 0.04035596549510956, 0.01198265515267849, 0.02699294500052929, -0.0028655033092945814, -0.0034787601325660944, -0.00785762444138527, 0.021542461588978767, 0.03866448253393173, 0.07855118811130524, 0.0020651081576943398, 0.0003099012828897685, -0.0043701715767383575, 0.006230761297047138, -0.0033235878217965364, 0.03375754877924919, 0.004826302174478769, -0.08562468737363815, -0.06096173822879791, 0.02043997496366501, -0.07900462299585342, 0.0005181746673770249, 0.07581894099712372, -0.0973147600889206, 0.025550279766321182, 0.0019101080251857638, -0.037592947483062744, -0.024027273058891296, -0.014737183228135109, 0.05098038166761398, -0.027552425861358643, -0.013514778576791286, -0.021064288914203644, 0.049483522772789, -0.009120531380176544, 0.0010890060802921653, 0.06981270760297775, 0.0054853083565831184, -1.3831166143063456e-05, 0.000642701459582895, 0.08029990643262863, -0.04223058000206947, -0.028529712930321693, -0.009597638621926308, -0.03014504536986351, 0.09113029390573502, -0.050656795501708984, -0.0890624076128006, -0.004748611245304346, -0.0763397142291069, 0.08935647457838058, -0.04953158274292946, -0.0017624205211177468, -0.013737273402512074, 0.03526974096894264, -0.0035586205776780844, -0.005924544297158718, -0.017519811168313026, 0.013018002733588219, 0.07598046213388443, 0.01555555034428835, 0.050532303750514984}; + + @Override + public double predict(Object2DoubleMap ft) { + return predict(ft, DEFAULT_PARAMS); + } + + @Override + public double[] getData(Object2DoubleMap ft) { + double[] data = new double[14]; + data[0] = (ft.getDouble("length") - 118.1870083102493) / 85.53737656584288; + data[1] = (ft.getDouble("speed") - 13.07573990377606) / 2.714858934612079; + data[2] = (ft.getDouble("num_lanes") - 1.898819069835253) / 0.9764526365080834; + data[3] = ft.getDouble("change_speed"); + data[4] = ft.getDouble("change_num_lanes"); + data[5] = ft.getDouble("num_to_links"); + data[6] = ft.getDouble("junction_inc_lanes"); + data[7] = ft.getDouble("priority_lower"); + data[8] = ft.getDouble("priority_equal"); + data[9] = ft.getDouble("priority_higher"); + data[10] = ft.getDouble("is_secondary_or_higher"); + data[11] = ft.getDouble("is_primary_or_higher"); + data[12] = ft.getDouble("is_motorway"); + data[13] = ft.getDouble("is_link"); + + return data; + } + + @Override + public double predict(Object2DoubleMap ft, double[] params) { + + double[] data = getData(ft); + for (int i = 0; i < data.length; i++) + if (Double.isNaN(data[i])) throw new IllegalArgumentException("Invalid data at index: " + i); + + return score(data, params); + } + public static double score(double[] input, double[] params) { + double var0; + if (input[0] >= -0.1273947) { + if (input[6] >= 6.5) { + if (input[0] >= 0.6765813) { + if (input[0] >= 1.1753106) { + var0 = params[0]; + } else { + var0 = params[1]; + } + } else { + if (input[1] >= -1.2360642) { + var0 = params[2]; + } else { + var0 = params[3]; + } + } + } else { + if (input[1] >= -1.2360642) { + if (input[0] >= 1.2711751) { + var0 = params[4]; + } else { + var0 = params[5]; + } + } else { + if (input[0] >= 0.64478236) { + var0 = params[6]; + } else { + var0 = params[7]; + } + } + } + } else { + if (input[6] >= 6.5) { + if (input[5] >= 2.5) { + if (input[1] >= -0.72406703) { + var0 = params[8]; + } else { + var0 = params[9]; + } + } else { + if (input[0] >= -0.7543136) { + var0 = params[10]; + } else { + var0 = params[11]; + } + } + } else { + if (input[0] >= -0.6443032) { + if (input[1] >= -1.2360642) { + var0 = params[12]; + } else { + var0 = params[13]; + } + } else { + if (input[1] >= -0.72406703) { + var0 = params[14]; + } else { + var0 = params[15]; + } + } + } + } + double var1; + if (input[6] >= 4.5) { + if (input[0] >= -0.24336739) { + if (input[0] >= 0.5039667) { + if (input[6] >= 8.5) { + var1 = params[16]; + } else { + var1 = params[17]; + } + } else { + if (input[6] >= 8.5) { + var1 = params[18]; + } else { + var1 = params[19]; + } + } + } else { + if (input[6] >= 8.5) { + if (input[0] >= -0.49056926) { + var1 = params[20]; + } else { + var1 = params[21]; + } + } else { + if (input[2] >= 0.6156785) { + var1 = params[22]; + } else { + var1 = params[23]; + } + } + } + } else { + if (input[0] >= -0.4307124) { + if (input[0] >= 0.2598629) { + if (input[13] >= 0.5) { + var1 = params[24]; + } else { + var1 = params[25]; + } + } else { + if (input[13] >= 0.5) { + var1 = params[26]; + } else { + var1 = params[27]; + } + } + } else { + if (input[0] >= -0.8881732) { + if (input[0] >= -0.83574) { + var1 = params[28]; + } else { + var1 = params[29]; + } + } else { + if (input[2] >= 0.6156785) { + var1 = params[30]; + } else { + var1 = params[31]; + } + } + } + } + double var2; + if (input[0] >= -0.34355754) { + if (input[6] >= 8.5) { + if (input[1] >= 0.81192434) { + if (input[0] >= -0.27352965) { + var2 = params[32]; + } else { + var2 = params[33]; + } + } else { + if (input[0] >= 0.2842967) { + var2 = params[34]; + } else { + var2 = params[35]; + } + } + } else { + if (input[1] >= 0.81192434) { + if (input[3] >= -5.5550003) { + var2 = params[36]; + } else { + var2 = params[37]; + } + } else { + if (input[0] >= 0.7530391) { + var2 = params[38]; + } else { + var2 = params[39]; + } + } + } + } else { + if (input[6] >= 5.5) { + if (input[1] >= -0.72406703) { + if (input[0] >= -0.648395) { + var2 = params[40]; + } else { + var2 = params[41]; + } + } else { + if (input[3] >= 2.78) { + var2 = params[42]; + } else { + var2 = params[43]; + } + } + } else { + if (input[1] >= 0.81192434) { + if (input[6] >= 2.5) { + var2 = params[44]; + } else { + var2 = params[45]; + } + } else { + if (input[0] >= -0.723333) { + var2 = params[46]; + } else { + var2 = params[47]; + } + } + } + } + double var3; + if (input[0] >= 0.011608863) { + if (input[0] >= 1.6133647) { + if (input[3] >= 6.95) { + if (input[0] >= 3.2881882) { + var3 = params[48]; + } else { + var3 = params[49]; + } + } else { + if (input[0] >= 2.6381216) { + var3 = params[50]; + } else { + var3 = params[51]; + } + } + } else { + if (input[3] >= 5.5550003) { + if (input[3] >= 6.9449997) { + var3 = params[52]; + } else { + var3 = params[53]; + } + } else { + if (input[3] >= 1.385) { + var3 = params[54]; + } else { + var3 = params[55]; + } + } + } + } else { + if (input[5] >= 2.5) { + if (input[3] >= 5.5550003) { + if (input[0] >= -0.5320132) { + var3 = params[56]; + } else { + var3 = params[57]; + } + } else { + if (input[0] >= -0.7692194) { + var3 = params[58]; + } else { + var3 = params[59]; + } + } + } else { + if (input[0] >= -0.89366794) { + if (input[7] >= 0.5) { + var3 = params[60]; + } else { + var3 = params[61]; + } + } else { + if (input[4] >= 0.5) { + var3 = params[62]; + } else { + var3 = params[63]; + } + } + } + } + double var4; + if (input[1] >= -1.2360642) { + if (input[1] >= 1.8340769) { + if (input[5] >= 2.5) { + if (input[11] >= 0.5) { + var4 = params[64]; + } else { + var4 = params[65]; + } + } else { + if (input[8] >= 0.5) { + var4 = params[66]; + } else { + var4 = params[67]; + } + } + } else { + if (input[5] >= 2.5) { + if (input[6] >= 4.5) { + var4 = params[68]; + } else { + var4 = params[69]; + } + } else { + if (input[4] >= -0.5) { + var4 = params[70]; + } else { + var4 = params[71]; + } + } + } + } else { + if (input[6] >= 10.5) { + if (input[7] >= 0.5) { + var4 = params[72]; + } else { + var4 = params[73]; + } + } else { + if (input[3] >= 5.5550003) { + if (input[5] >= 1.5) { + var4 = params[74]; + } else { + var4 = params[75]; + } + } else { + if (input[5] >= 3.5) { + var4 = params[76]; + } else { + var4 = params[77]; + } + } + } + } + double var5; + if (input[0] >= -0.4926736) { + if (input[1] >= 1.8340769) { + if (input[0] >= 0.008861526) { + if (input[5] >= 2.5) { + var5 = params[78]; + } else { + var5 = params[79]; + } + } else { + if (input[1] >= 2.8562293) { + var5 = params[80]; + } else { + var5 = params[81]; + } + } + } else { + if (input[1] >= -1.2360642) { + if (input[3] >= 4.165) { + var5 = params[82]; + } else { + var5 = params[83]; + } + } else { + if (input[5] >= 1.5) { + var5 = params[84]; + } else { + var5 = params[85]; + } + } + } + } else { + if (input[1] >= 0.81192434) { + if (input[4] >= 0.5) { + if (input[0] >= -0.90757996) { + var5 = params[86]; + } else { + var5 = params[87]; + } + } else { + if (input[3] >= 1.385) { + var5 = params[88]; + } else { + var5 = params[89]; + } + } + } else { + if (input[5] >= 2.5) { + if (input[0] >= -0.8758979) { + var5 = params[90]; + } else { + var5 = params[91]; + } + } else { + if (input[1] >= -1.2360642) { + var5 = params[92]; + } else { + var5 = params[93]; + } + } + } + } + double var6; + if (input[0] >= 0.20041522) { + if (input[0] >= 2.0295572) { + if (input[2] >= -0.40843666) { + if (input[4] >= -0.5) { + var6 = params[94]; + } else { + var6 = params[95]; + } + } else { + if (input[0] >= 2.772975) { + var6 = params[96]; + } else { + var6 = params[97]; + } + } + } else { + if (input[6] >= 3.5) { + if (input[11] >= 0.5) { + var6 = params[98]; + } else { + var6 = params[99]; + } + } else { + if (input[0] >= 0.2598629) { + var6 = params[100]; + } else { + var6 = params[101]; + } + } + } + } else { + if (input[6] >= 10.5) { + if (input[0] >= -1.1355505) { + if (input[0] >= -0.25447363) { + var6 = params[102]; + } else { + var6 = params[103]; + } + } else { + var6 = params[104]; + } + } else { + if (input[2] >= 0.6156785) { + if (input[3] >= 9.725) { + var6 = params[105]; + } else { + var6 = params[106]; + } + } else { + if (input[6] >= 4.5) { + var6 = params[107]; + } else { + var6 = params[108]; + } + } + } + } + double var7; + if (input[0] >= -0.53101945) { + if (input[6] >= 10.5) { + if (input[3] >= -5.5550003) { + if (input[11] >= 0.5) { + var7 = params[109]; + } else { + var7 = params[110]; + } + } else { + var7 = params[111]; + } + } else { + if (input[3] >= 8.335) { + if (input[3] >= 16.945) { + var7 = params[112]; + } else { + var7 = params[113]; + } + } else { + if (input[11] >= 0.5) { + var7 = params[114]; + } else { + var7 = params[115]; + } + } + } + } else { + if (input[6] >= 7.5) { + if (input[0] >= -1.1889775) { + if (input[3] >= 9.725) { + var7 = params[116]; + } else { + var7 = params[117]; + } + } else { + var7 = params[118]; + } + } else { + if (input[0] >= -1.0966785) { + if (input[10] >= 0.5) { + var7 = params[119]; + } else { + var7 = params[120]; + } + } else { + if (input[4] >= -0.5) { + var7 = params[121]; + } else { + var7 = params[122]; + } + } + } + } + double var8; + if (input[1] >= 0.81192434) { + if (input[3] >= 1.385) { + if (input[3] >= 2.775) { + if (input[0] >= 0.6119897) { + var8 = params[123]; + } else { + var8 = params[124]; + } + } else { + if (input[0] >= -1.1440263) { + var8 = params[125]; + } else { + var8 = params[126]; + } + } + } else { + if (input[1] >= 1.8340769) { + if (input[0] >= -1.167934) { + var8 = params[127]; + } else { + var8 = params[128]; + } + } else { + if (input[0] >= -0.52914894) { + var8 = params[129]; + } else { + var8 = params[130]; + } + } + } + } else { + if (input[1] >= -1.2360642) { + if (input[3] >= 4.165) { + if (input[0] >= 0.32328546) { + var8 = params[131]; + } else { + var8 = params[132]; + } + } else { + if (input[10] >= 0.5) { + var8 = params[133]; + } else { + var8 = params[134]; + } + } + } else { + if (input[3] >= 5.5550003) { + if (input[0] >= -1.2164508) { + var8 = params[135]; + } else { + var8 = params[136]; + } + } else { + if (input[0] >= 0.29347396) { + var8 = params[137]; + } else { + var8 = params[138]; + } + } + } + } + double var9; + if (input[6] >= 6.5) { + if (input[0] >= -1.1738379) { + if (input[2] >= 0.6156785) { + if (input[0] >= 0.45930788) { + var9 = params[139]; + } else { + var9 = params[140]; + } + } else { + if (input[0] >= 2.6381216) { + var9 = params[141]; + } else { + var9 = params[142]; + } + } + } else { + if (input[2] >= 0.6156785) { + if (input[0] >= -1.1889775) { + var9 = params[143]; + } else { + var9 = params[144]; + } + } else { + if (input[9] >= 0.5) { + var9 = params[145]; + } else { + var9 = params[146]; + } + } + } + } else { + if (input[5] >= 3.5) { + if (input[0] >= -1.1991484) { + if (input[0] >= 0.5094614) { + var9 = params[147]; + } else { + var9 = params[148]; + } + } else { + var9 = params[149]; + } + } else { + if (input[2] >= -0.40843666) { + if (input[13] >= 0.5) { + var9 = params[150]; + } else { + var9 = params[151]; + } + } else { + if (input[1] >= -0.2120699) { + var9 = params[152]; + } else { + var9 = params[153]; + } + } + } + } + double var10; + if (input[6] >= 4.5) { + if (input[0] >= -0.88887465) { + if (input[2] >= -0.40843666) { + if (input[6] >= 7.5) { + var10 = params[154]; + } else { + var10 = params[155]; + } + } else { + if (input[4] >= 0.5) { + var10 = params[156]; + } else { + var10 = params[157]; + } + } + } else { + if (input[4] >= 0.5) { + if (input[3] >= 4.165) { + var10 = params[158]; + } else { + var10 = params[159]; + } + } else { + if (input[0] >= -1.1740131) { + var10 = params[160]; + } else { + var10 = params[161]; + } + } + } + } else { + if (input[0] >= -1.0966785) { + if (input[6] >= 2.5) { + if (input[0] >= -1.0678023) { + var10 = params[162]; + } else { + var10 = params[163]; + } + } else { + if (input[4] >= 0.5) { + var10 = params[164]; + } else { + var10 = params[165]; + } + } + } else { + if (input[2] >= 0.6156785) { + if (input[0] >= -1.1775205) { + var10 = params[166]; + } else { + var10 = params[167]; + } + } else { + if (input[0] >= -1.1268408) { + var10 = params[168]; + } else { + var10 = params[169]; + } + } + } + } + double var11; + if (input[0] >= 1.1105437) { + if (input[0] >= 2.9452972) { + var11 = params[170]; + } else { + if (input[6] >= 3.5) { + if (input[2] >= -0.40843666) { + var11 = params[171]; + } else { + var11 = params[172]; + } + } else { + if (input[3] >= 6.9449997) { + var11 = params[173]; + } else { + var11 = params[174]; + } + } + } + } else { + if (input[1] >= 0.81192434) { + if (input[5] >= 2.5) { + if (input[0] >= -0.13610435) { + var11 = params[175]; + } else { + var11 = params[176]; + } + } else { + if (input[0] >= -0.102727115) { + var11 = params[177]; + } else { + var11 = params[178]; + } + } + } else { + if (input[2] >= 0.6156785) { + if (input[6] >= 9.5) { + var11 = params[179]; + } else { + var11 = params[180]; + } + } else { + if (input[6] >= 3.5) { + var11 = params[181]; + } else { + var11 = params[182]; + } + } + } + } + double var12; + if (input[6] >= 11.5) { + if (input[0] >= -1.0830588) { + if (input[0] >= -0.7648938) { + if (input[0] >= -0.7618542) { + var12 = params[183]; + } else { + var12 = params[184]; + } + } else { + var12 = params[185]; + } + } else { + var12 = params[186]; + } + } else { + if (input[2] >= 1.6397938) { + if (input[0] >= -1.0583327) { + if (input[0] >= -0.88460755) { + var12 = params[187]; + } else { + var12 = params[188]; + } + } else { + if (input[0] >= -1.1504562) { + var12 = params[189]; + } else { + var12 = params[190]; + } + } + } else { + if (input[0] >= 0.30399567) { + if (input[2] >= 0.6156785) { + var12 = params[191]; + } else { + var12 = params[192]; + } + } else { + if (input[4] >= -1.5) { + var12 = params[193]; + } else { + var12 = params[194]; + } + } + } + } + double var13; + if (input[0] >= -0.6066004) { + if (input[0] >= -0.6060159) { + if (input[1] >= 1.8340769) { + if (input[2] >= -0.40843666) { + var13 = params[195]; + } else { + var13 = params[196]; + } + } else { + if (input[5] >= 1.5) { + var13 = params[197]; + } else { + var13 = params[198]; + } + } + } else { + var13 = params[199]; + } + } else { + if (input[0] >= -1.241469) { + if (input[1] >= -0.72406703) { + if (input[4] >= 0.5) { + var13 = params[200]; + } else { + var13 = params[201]; + } + } else { + if (input[13] >= 0.5) { + var13 = params[202]; + } else { + var13 = params[203]; + } + } + } else { + if (input[4] >= 0.5) { + if (input[0] >= -1.2780613) { + var13 = params[204]; + } else { + var13 = params[205]; + } + } else { + var13 = params[206]; + } + } + } + double var14; + if (input[4] >= 1.5) { + if (input[1] >= -0.72406703) { + if (input[6] >= 3.5) { + if (input[11] >= 0.5) { + var14 = params[207]; + } else { + var14 = params[208]; + } + } else { + if (input[7] >= 0.5) { + var14 = params[209]; + } else { + var14 = params[210]; + } + } + } else { + if (input[4] >= 2.5) { + var14 = params[211]; + } else { + var14 = params[212]; + } + } + } else { + if (input[6] >= 2.5) { + if (input[9] >= 0.5) { + if (input[4] >= 0.5) { + var14 = params[213]; + } else { + var14 = params[214]; + } + } else { + if (input[1] >= -0.72406703) { + var14 = params[215]; + } else { + var14 = params[216]; + } + } + } else { + if (input[4] >= 0.5) { + if (input[8] >= 0.5) { + var14 = params[217]; + } else { + var14 = params[218]; + } + } else { + if (input[3] >= -1.39) { + var14 = params[219]; + } else { + var14 = params[220]; + } + } + } + } + double var15; + if (input[6] >= 4.5) { + if (input[2] >= -0.40843666) { + if (input[3] >= 1.385) { + if (input[13] >= 0.5) { + var15 = params[221]; + } else { + var15 = params[222]; + } + } else { + if (input[5] >= 2.5) { + var15 = params[223]; + } else { + var15 = params[224]; + } + } + } else { + if (input[4] >= 0.5) { + if (input[5] >= 1.5) { + var15 = params[225]; + } else { + var15 = params[226]; + } + } else { + if (input[3] >= 8.335) { + var15 = params[227]; + } else { + var15 = params[228]; + } + } + } + } else { + if (input[4] >= 1.5) { + if (input[0] >= -1.2207179) { + if (input[13] >= 0.5) { + var15 = params[229]; + } else { + var15 = params[230]; + } + } else { + var15 = params[231]; + } + } else { + if (input[2] >= -0.40843666) { + if (input[5] >= 3.5) { + var15 = params[232]; + } else { + var15 = params[233]; + } + } else { + if (input[3] >= 16.94) { + var15 = params[234]; + } else { + var15 = params[235]; + } + } + } + } + double var16; + if (input[1] >= -1.2360642) { + if (input[3] >= 1.385) { + if (input[0] >= -0.28451902) { + if (input[3] >= 2.775) { + var16 = params[236]; + } else { + var16 = params[237]; + } + } else { + if (input[8] >= 0.5) { + var16 = params[238]; + } else { + var16 = params[239]; + } + } + } else { + if (input[0] >= 2.6961663) { + if (input[8] >= 0.5) { + var16 = params[240]; + } else { + var16 = params[241]; + } + } else { + if (input[2] >= -0.40843666) { + var16 = params[242]; + } else { + var16 = params[243]; + } + } + } + } else { + if (input[0] >= -1.0745245) { + if (input[0] >= -1.0508506) { + if (input[3] >= 9.725) { + var16 = params[244]; + } else { + var16 = params[245]; + } + } else { + if (input[9] >= 0.5) { + var16 = params[246]; + } else { + var16 = params[247]; + } + } + } else { + if (input[8] >= 0.5) { + if (input[4] >= 0.5) { + var16 = params[248]; + } else { + var16 = params[249]; + } + } else { + if (input[4] >= 1.5) { + var16 = params[250]; + } else { + var16 = params[251]; + } + } + } + } + double var17; + if (input[1] >= 1.8340769) { + if (input[0] >= 3.0555997) { + var17 = params[252]; + } else { + if (input[2] >= -0.40843666) { + if (input[4] >= -1.5) { + var17 = params[253]; + } else { + var17 = params[254]; + } + } else { + if (input[6] >= 3.5) { + var17 = params[255]; + } else { + var17 = params[256]; + } + } + } + } else { + if (input[0] >= -1.2234068) { + if (input[0] >= -1.1792741) { + if (input[0] >= -1.1776373) { + var17 = params[257]; + } else { + var17 = params[258]; + } + } else { + if (input[6] >= 6.5) { + var17 = params[259]; + } else { + var17 = params[260]; + } + } + } else { + if (input[5] >= 2.5) { + if (input[0] >= -1.2355652) { + var17 = params[261]; + } else { + var17 = params[262]; + } + } else { + if (input[0] >= -1.2304213) { + var17 = params[263]; + } else { + var17 = params[264]; + } + } + } + } + double var18; + if (input[2] >= 1.6397938) { + if (input[8] >= 0.5) { + if (input[5] >= 2.5) { + if (input[0] >= 0.25588804) { + var18 = params[265]; + } else { + var18 = params[266]; + } + } else { + if (input[0] >= -0.043630145) { + var18 = params[267]; + } else { + var18 = params[268]; + } + } + } else { + if (input[6] >= 10.5) { + if (input[0] >= 0.039666772) { + var18 = params[269]; + } else { + var18 = params[270]; + } + } else { + if (input[0] >= -1.0241957) { + var18 = params[271]; + } else { + var18 = params[272]; + } + } + } + } else { + if (input[6] >= 9.5) { + if (input[5] >= 2.5) { + if (input[0] >= -1.0833511) { + var18 = params[273]; + } else { + var18 = params[274]; + } + } else { + if (input[1] >= -0.72406703) { + var18 = params[275]; + } else { + var18 = params[276]; + } + } + } else { + if (input[2] >= 0.6156785) { + if (input[5] >= 2.5) { + var18 = params[277]; + } else { + var18 = params[278]; + } + } else { + if (input[6] >= 5.5) { + var18 = params[279]; + } else { + var18 = params[280]; + } + } + } + } + double var19; + if (input[0] >= 1.562393) { + if (input[0] >= 3.5200167) { + var19 = params[281]; + } else { + if (input[2] >= 1.6397938) { + var19 = params[282]; + } else { + if (input[6] >= 9.5) { + var19 = params[283]; + } else { + var19 = params[284]; + } + } + } + } else { + if (input[0] >= 1.4279487) { + if (input[7] >= 0.5) { + if (input[4] >= 0.5) { + var19 = params[285]; + } else { + var19 = params[286]; + } + } else { + var19 = params[287]; + } + } else { + if (input[0] >= -1.2381372) { + if (input[0] >= -1.1435586) { + var19 = params[288]; + } else { + var19 = params[289]; + } + } else { + if (input[2] >= 0.6156785) { + var19 = params[290]; + } else { + var19 = params[291]; + } + } + } + } + double var20; + if (input[3] >= -2.775) { + if (input[6] >= 2.5) { + if (input[11] >= 0.5) { + if (input[3] >= 4.165) { + var20 = params[292]; + } else { + var20 = params[293]; + } + } else { + if (input[1] >= -0.2120699) { + var20 = params[294]; + } else { + var20 = params[295]; + } + } + } else { + if (input[4] >= -0.5) { + if (input[4] >= 0.5) { + var20 = params[296]; + } else { + var20 = params[297]; + } + } else { + if (input[1] >= 0.81192434) { + var20 = params[298]; + } else { + var20 = params[299]; + } + } + } + } else { + if (input[7] >= 0.5) { + var20 = params[300]; + } else { + if (input[6] >= 11.5) { + var20 = params[301]; + } else { + if (input[6] >= 7.5) { + var20 = params[302]; + } else { + var20 = params[303]; + } + } + } + } + double var21; + if (input[0] >= -0.18257526) { + if (input[4] >= -1.5) { + if (input[0] >= -0.07835181) { + if (input[2] >= 1.6397938) { + var21 = params[304]; + } else { + var21 = params[305]; + } + } else { + if (input[5] >= 1.5) { + var21 = params[306]; + } else { + var21 = params[307]; + } + } + } else { + if (input[6] >= 5.5) { + if (input[11] >= 0.5) { + var21 = params[308]; + } else { + var21 = params[309]; + } + } else { + var21 = params[310]; + } + } + } else { + if (input[0] >= -0.19888392) { + var21 = params[311]; + } else { + if (input[0] >= -0.53101945) { + if (input[13] >= 0.5) { + var21 = params[312]; + } else { + var21 = params[313]; + } + } else { + if (input[4] >= 0.5) { + var21 = params[314]; + } else { + var21 = params[315]; + } + } + } + } + double var22; + if (input[5] >= 3.5) { + if (input[0] >= -0.8305961) { + if (input[6] >= 4.5) { + var22 = params[316]; + } else { + if (input[8] >= 0.5) { + var22 = params[317]; + } else { + var22 = params[318]; + } + } + } else { + if (input[6] >= 10.5) { + var22 = params[319]; + } else { + var22 = params[320]; + } + } + } else { + if (input[5] >= 1.5) { + if (input[2] >= -0.40843666) { + if (input[3] >= -5.5550003) { + var22 = params[321]; + } else { + var22 = params[322]; + } + } else { + if (input[5] >= 2.5) { + var22 = params[323]; + } else { + var22 = params[324]; + } + } + } else { + if (input[3] >= -5.5550003) { + if (input[2] >= 2.663909) { + var22 = params[325]; + } else { + var22 = params[326]; + } + } else { + if (input[8] >= 0.5) { + var22 = params[327]; + } else { + var22 = params[328]; + } + } + } + } + double var23; + if (input[6] >= 3.5) { + if (input[3] >= 16.665) { + var23 = params[329]; + } else { + if (input[0] >= -0.8443327) { + if (input[3] >= -5.5550003) { + var23 = params[330]; + } else { + var23 = params[331]; + } + } else { + if (input[3] >= -4.17) { + var23 = params[332]; + } else { + var23 = params[333]; + } + } + } + } else { + if (input[7] >= 0.5) { + if (input[0] >= -1.0372308) { + var23 = params[334]; + } else { + if (input[1] >= 0.81192434) { + var23 = params[335]; + } else { + var23 = params[336]; + } + } + } else { + if (input[0] >= 0.5085846) { + if (input[1] >= -0.2120699) { + var23 = params[337]; + } else { + var23 = params[338]; + } + } else { + var23 = params[339]; + } + } + } + double var24; + if (input[6] >= 7.5) { + if (input[2] >= 1.6397938) { + if (input[0] >= -1.1504562) { + if (input[0] >= -0.96270204) { + var24 = params[340]; + } else { + var24 = params[341]; + } + } else { + var24 = params[342]; + } + } else { + if (input[4] >= 1.5) { + if (input[0] >= -0.22103798) { + var24 = params[343]; + } else { + var24 = params[344]; + } + } else { + if (input[3] >= -5.5550003) { + var24 = params[345]; + } else { + var24 = params[346]; + } + } + } + } else { + if (input[2] >= -0.40843666) { + if (input[5] >= 1.5) { + if (input[3] >= 9.725) { + var24 = params[347]; + } else { + var24 = params[348]; + } + } else { + if (input[7] >= 0.5) { + var24 = params[349]; + } else { + var24 = params[350]; + } + } + } else { + if (input[0] >= -1.0936389) { + if (input[3] >= 9.725) { + var24 = params[351]; + } else { + var24 = params[352]; + } + } else { + if (input[0] >= -1.095568) { + var24 = params[353]; + } else { + var24 = params[354]; + } + } + } + } + double var25; + if (input[4] >= 2.5) { + var25 = params[355]; + } else { + if (input[5] >= 1.5) { + if (input[2] >= 0.6156785) { + if (input[5] >= 2.5) { + var25 = params[356]; + } else { + var25 = params[357]; + } + } else { + if (input[4] >= -0.5) { + var25 = params[358]; + } else { + var25 = params[359]; + } + } + } else { + if (input[2] >= 1.6397938) { + if (input[4] >= -0.5) { + var25 = params[360]; + } else { + var25 = params[361]; + } + } else { + if (input[3] >= 2.775) { + var25 = params[362]; + } else { + var25 = params[363]; + } + } + } + } + double var26; + if (input[0] >= -0.12295219) { + if (input[0] >= -0.09384212) { + if (input[0] >= -0.09273149) { + if (input[6] >= 4.5) { + var26 = params[364]; + } else { + var26 = params[365]; + } + } else { + var26 = params[366]; + } + } else { + if (input[3] >= 2.775) { + if (input[6] >= 3.5) { + var26 = params[367]; + } else { + var26 = params[368]; + } + } else { + if (input[0] >= -0.10927397) { + var26 = params[369]; + } else { + var26 = params[370]; + } + } + } + } else { + if (input[0] >= -0.15434198) { + if (input[0] >= -0.14627534) { + if (input[0] >= -0.14352798) { + var26 = params[371]; + } else { + var26 = params[372]; + } + } else { + var26 = params[373]; + } + } else { + if (input[0] >= -0.15632942) { + if (input[5] >= 2.5) { + var26 = params[374]; + } else { + var26 = params[375]; + } + } else { + if (input[0] >= -0.53101945) { + var26 = params[376]; + } else { + var26 = params[377]; + } + } + } + } + double var27; + if (input[1] >= 0.81192434) { + if (input[7] >= 0.5) { + if (input[4] >= -1.5) { + if (input[2] >= 0.6156785) { + var27 = params[378]; + } else { + var27 = params[379]; + } + } else { + var27 = params[380]; + } + } else { + var27 = params[381]; + } + } else { + if (input[11] >= 0.5) { + if (input[4] >= 1.5) { + var27 = params[382]; + } else { + if (input[2] >= -0.40843666) { + var27 = params[383]; + } else { + var27 = params[384]; + } + } + } else { + if (input[1] >= -0.2120699) { + if (input[3] >= 4.165) { + var27 = params[385]; + } else { + var27 = params[386]; + } + } else { + var27 = params[387]; + } + } + } + double var28; + if (input[0] >= -1.200376) { + if (input[6] >= 6.5) { + if (input[4] >= 0.5) { + if (input[2] >= 0.6156785) { + var28 = params[388]; + } else { + var28 = params[389]; + } + } else { + if (input[1] >= 2.8562293) { + var28 = params[390]; + } else { + var28 = params[391]; + } + } + } else { + if (input[0] >= -1.1789818) { + if (input[1] >= 0.81192434) { + var28 = params[392]; + } else { + var28 = params[393]; + } + } else { + if (input[4] >= 0.5) { + var28 = params[394]; + } else { + var28 = params[395]; + } + } + } + } else { + if (input[2] >= 0.6156785) { + var28 = params[396]; + } else { + if (input[6] >= 3.5) { + if (input[10] >= 0.5) { + var28 = params[397]; + } else { + var28 = params[398]; + } + } else { + var28 = params[399]; + } + } + } + double var29; + if (input[2] >= -0.40843666) { + if (input[0] >= -1.0989583) { + if (input[0] >= -1.0953926) { + if (input[0] >= -1.0896641) { + var29 = params[400]; + } else { + var29 = params[401]; + } + } else { + var29 = params[402]; + } + } else { + if (input[0] >= -1.1170206) { + if (input[6] >= 9.0) { + var29 = params[403]; + } else { + var29 = params[404]; + } + } else { + if (input[7] >= 0.5) { + var29 = params[405]; + } else { + var29 = params[406]; + } + } + } + } else { + if (input[0] >= -1.0439532) { + if (input[0] >= -1.0098159) { + if (input[0] >= 0.7677696) { + var29 = params[407]; + } else { + var29 = params[408]; + } + } else { + if (input[6] >= 3.5) { + var29 = params[409]; + } else { + var29 = params[410]; + } + } + } else { + if (input[0] >= -1.0448884) { + var29 = params[411]; + } else { + if (input[6] >= 6.5) { + var29 = params[412]; + } else { + var29 = params[413]; + } + } + } + } + return 0.5 + (var0 + var1 + var2 + var3 + var4 + var5 + var6 + var7 + var8 + var9 + var10 + var11 + var12 + var13 + var14 + var15 + var16 + var17 + var18 + var19 + var20 + var21 + var22 + var23 + var24 + var25 + var26 + var27 + var28 + var29); + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/population/SplitActivityTypesDuration.java b/contribs/application/src/main/java/org/matsim/application/prepare/population/SplitActivityTypesDuration.java index b49a1d5b2c4..9bf459cdc19 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/population/SplitActivityTypesDuration.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/population/SplitActivityTypesDuration.java @@ -13,6 +13,7 @@ import picocli.CommandLine; import java.nio.file.Path; +import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; @@ -47,7 +48,7 @@ public class SplitActivityTypesDuration implements MATSimAppCommand, PersonAlgor private String subpopulation; @CommandLine.Option(names = "--exclude", description = "Activity types that won't be split", split = ",", defaultValue = "") - private Set exclude; + private Set exclude = new HashSet<>(); /** @@ -65,6 +66,13 @@ public SplitActivityTypesDuration(int activityBinSize, int maxTypicalDuration, i this.endTimeToDuration = endTimeToDuration; } + /** + * Set activity types to be excluded from splitting. + */ + public void setExclude(Set exclude) { + this.exclude = exclude; + } + public static void main(String[] args) { new SplitActivityTypesDuration().execute(args); } diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/population/XYToLinks.java b/contribs/application/src/main/java/org/matsim/application/prepare/population/XYToLinks.java index ec9ada3bad5..83aefa033e0 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/population/XYToLinks.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/population/XYToLinks.java @@ -1,15 +1,20 @@ package org.matsim.application.prepare.population; +import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.population.Population; import org.matsim.application.MATSimAppCommand; +import org.matsim.core.config.ConfigUtils; import org.matsim.core.network.NetworkUtils; import org.matsim.core.network.algorithms.TransportModeNetworkFilter; import org.matsim.core.population.PopulationUtils; import org.matsim.core.population.algorithms.ParallelPersonAlgorithmUtils; import org.matsim.core.population.algorithms.XY2Links; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.facilities.ActivityFacilities; import org.matsim.facilities.FacilitiesUtils; +import org.matsim.facilities.MatsimFacilitiesReader; import picocli.CommandLine; import java.nio.file.Path; @@ -29,6 +34,9 @@ public class XYToLinks implements MATSimAppCommand { @CommandLine.Option(names = "--car-only", description = "Convert to car-only network", defaultValue = "false") private boolean carOnly; + @CommandLine.Option(names = "--facilities", description = "Input facilities. Necessary if activities already were assigned facility ids.") + private Path inputFacilities; + @Override public Integer call() throws Exception { @@ -42,7 +50,16 @@ public Integer call() throws Exception { network = carOnlyNetwork; } - XY2Links algo = new XY2Links(network, FacilitiesUtils.createActivityFacilities()); + ActivityFacilities facilities = FacilitiesUtils.createActivityFacilities(); + + if (inputFacilities != null) { + Scenario scenario = ScenarioUtils.loadScenario(ConfigUtils.createConfig()); + MatsimFacilitiesReader reader = new MatsimFacilitiesReader(scenario); + reader.parse(inputFacilities.toUri().toURL()); + facilities = scenario.getActivityFacilities(); + } + + XY2Links algo = new XY2Links(network, facilities); Population population = PopulationUtils.readPopulation(input.toString()); diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSV.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSV.java index b8dc592921e..7939a9dab9a 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSV.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSV.java @@ -27,6 +27,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Link; +import org.matsim.application.options.ShpOptions; import org.matsim.freight.carriers.*; import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; import org.matsim.core.utils.geometry.CoordinateTransformation; @@ -41,7 +42,7 @@ /** * This CarrierReaderFromCSV reads all carrier information given in the read CSV - * file and creates the carriers. While the process of creating the carriers the + * file and creates the carriers. While the process of creating the carriers, the * consistency of the information will be checked. * * @author Ricardo Ewert @@ -55,11 +56,11 @@ public final class CarrierReaderFromCSV { * file. For one carrier several CarrierInformationElement can be read in. This * is necessary for creating different configurations of the vehicles. Not every * parameter should be set for creating the carrier. While the process of - * creating the carriers the consistency of the information will be checked. + * creating the carriers, the consistency of the information will be checked. */ static class CarrierInformationElement { /** - * Name of carrier of this information element. + * Name of the carrier of this information element. */ private final String carrierName; /** @@ -97,8 +98,8 @@ static class CarrierInformationElement { private final int jspritIterations; /** * Sets a fixed number of vehicles per vehicleType and location. If this - * number is e.g. 3.: for each vehicleType 3 vehicles at each location will be - * created and the fleetsize is finite. + * number is e.g., 3.: for each vehicleType 3 vehicles at each location will be + * created, and the fleetsize is finite. */ private int fixedNumberOfVehiclePerTypeAndLocation; @@ -236,20 +237,20 @@ public void setFixedNumberOfVehiclePerTypeAndLocation(int fixedNumberOfVehiclePe * @param scenario * @param freightCarriersConfigGroup * @param csvLocationCarrier - * @param polygonsInShape + * @param indexShape * @param defaultJspritIterations * @param crsTransformationNetworkAndShape * @param shapeCategory * @throws IOException */ public static void readAndCreateCarrierFromCSV(Scenario scenario, FreightCarriersConfigGroup freightCarriersConfigGroup, - Path csvLocationCarrier, Collection polygonsInShape, int defaultJspritIterations, + Path csvLocationCarrier, ShpOptions.Index indexShape, int defaultJspritIterations, CoordinateTransformation crsTransformationNetworkAndShape, String shapeCategory) throws IOException { Set allNewCarrierInformation = readCarrierInformation(csvLocationCarrier); - checkNewCarrier(allNewCarrierInformation, freightCarriersConfigGroup, scenario, polygonsInShape, shapeCategory); + checkNewCarrier(allNewCarrierInformation, freightCarriersConfigGroup, scenario, indexShape, shapeCategory); log.info("The read carrier information from the csv are checked without errors."); - createNewCarrierAndAddVehicleTypes(scenario, allNewCarrierInformation, freightCarriersConfigGroup, polygonsInShape, + createNewCarrierAndAddVehicleTypes(scenario, allNewCarrierInformation, freightCarriersConfigGroup, indexShape, defaultJspritIterations, crsTransformationNetworkAndShape); } @@ -302,16 +303,16 @@ else if (!record.get("fleetSize").isBlank()) } /** - * Checks if the read carrier information are consistent. + * Checks if the read carrier information is consistent. * * @param allNewCarrierInformation * @param freightCarriersConfigGroup * @param scenario - * @param polygonsInShape + * @param indexShape * @param shapeCategory */ static void checkNewCarrier(Set allNewCarrierInformation, - FreightCarriersConfigGroup freightCarriersConfigGroup, Scenario scenario, Collection polygonsInShape, String shapeCategory) { + FreightCarriersConfigGroup freightCarriersConfigGroup, Scenario scenario, ShpOptions.Index indexShape, String shapeCategory) { CarriersUtils.addOrGetCarriers(scenario); for (CarrierInformationElement carrierElement : allNewCarrierInformation) { @@ -355,12 +356,12 @@ static void checkNewCarrier(Set allNewCarrierInformat log.warn( "No possible area for additional depot given. Random choice in the hole network of a possible position"); if (carrierElement.getAreaOfAdditionalDepots() != null) { - if (polygonsInShape == null) + if (indexShape == null) throw new RuntimeException("For carrier " + carrierElement.getName() + " a certain area for depots is selected, but no shape is read in. Please check."); for (String depotArea : carrierElement.getAreaOfAdditionalDepots()) { boolean isInShape = false; - for (SimpleFeature singlePolygon : polygonsInShape) { + for (SimpleFeature singlePolygon : indexShape.getShp().readFeatures()) { if (singlePolygon.getAttribute(shapeCategory).equals(depotArea)) { isInShape = true; break; @@ -409,14 +410,14 @@ static void checkNewCarrier(Set allNewCarrierInformat * @param scenario * @param allNewCarrierInformation * @param freightCarriersConfigGroup - * @param polygonsInShape + * @param indexShape * @param defaultJspritIterations * @param crsTransformationNetworkAndShape */ static void createNewCarrierAndAddVehicleTypes(Scenario scenario, - Set allNewCarrierInformation, FreightCarriersConfigGroup freightCarriersConfigGroup, - Collection polygonsInShape, int defaultJspritIterations, - CoordinateTransformation crsTransformationNetworkAndShape) { + Set allNewCarrierInformation, FreightCarriersConfigGroup freightCarriersConfigGroup, + ShpOptions.Index indexShape, int defaultJspritIterations, + CoordinateTransformation crsTransformationNetworkAndShape) { Carriers carriers = CarriersUtils.addOrGetCarriers(scenario); CarrierVehicleTypes carrierVehicleTypes = new CarrierVehicleTypes(); @@ -457,7 +458,7 @@ static void createNewCarrierAndAddVehicleTypes(Scenario scenario, && !link.getId().toString().contains("pt") && (!link.getAttributes().getAsMap().containsKey("type") || !link.getAttributes().getAsMap().get("type").toString().contains("motorway")) - && FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, + && FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, singleNewCarrier.getAreaOfAdditionalDepots(), crsTransformationNetworkAndShape)) { singleNewCarrier.getVehicleDepots().add(link.getId().toString()); } diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java index 8c1f113a6d0..d991eaa9a6f 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java @@ -24,17 +24,18 @@ import org.apache.commons.csv.CSVRecord; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.locationtech.jts.geom.Point; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.Population; -import org.matsim.freight.carriers.*; +import org.matsim.application.options.ShpOptions; import org.matsim.core.network.NetworkUtils; +import org.matsim.core.population.PopulationUtils; +import org.matsim.core.router.TripStructureUtils; import org.matsim.core.utils.geometry.CoordinateTransformation; -import org.matsim.core.utils.geometry.geotools.MGC; +import org.matsim.freight.carriers.*; import org.opengis.feature.simple.SimpleFeature; import java.io.IOException; @@ -45,7 +46,7 @@ /** * This DemandReaderFromCSV reads all demand information given in the read CSV * file and creates the demand for the carriers. While the process of creating - * the demand the consistency of the information will be checked. + * the demand, the consistency of the information will be checked. * * @author Ricardo Ewert */ @@ -58,9 +59,9 @@ public final class DemandReaderFromCSV { * file. Several DemandInformationElement can be read in for one carrier. This * is necessary for creating configurations of the demand. Not every parameter * should be set for creating the demand. While the process of creating the - * demand the consistency of the information will be checked. If this demand - * creates a service the information for the firstJobElement should be set. If - * this demands creates a shipment the firstJobElement is the pickup and the + * demand, the consistency of the information will be checked. If this demand + * creates a service, the information for the firstJobElement should be set. If + * this demand creates a shipment, the firstJobElement is the pickup and the * secondJobElement is the delivery. */ static class DemandInformationElement { @@ -317,7 +318,7 @@ public String getTypeOfDemand() { * * @param scenario * @param csvLocationDemand - * @param polygonsInShape + * @param indexShape * @param combineSimilarJobs * @param crsTransformationNetworkAndShape * @param population @@ -325,18 +326,18 @@ public String getTypeOfDemand() { * @throws IOException */ static void readAndCreateDemand(Scenario scenario, Path csvLocationDemand, - Collection polygonsInShape, boolean combineSimilarJobs, + ShpOptions.Index indexShape, boolean combineSimilarJobs, CoordinateTransformation crsTransformationNetworkAndShape, Population population, String shapeCategory) throws IOException { Set demandInformation = readDemandInformation(csvLocationDemand); - checkNewDemand(scenario, demandInformation, polygonsInShape, shapeCategory); - createDemandForCarriers(scenario, polygonsInShape, demandInformation, population, combineSimilarJobs, + checkNewDemand(scenario, demandInformation, indexShape, shapeCategory); + createDemandForCarriers(scenario, indexShape, demandInformation, population, combineSimilarJobs, crsTransformationNetworkAndShape); } /** * Reads the demand information from the csv file and checks if the information - * are consistent + * is consistent * * @param csvLocationDemand * @return @@ -404,11 +405,11 @@ static Set readDemandInformation(Path csvLocationDeman * * @param scenario * @param demandInformation - * @param polygonsInShape + * @param indexShape * @param shapeCategory */ static void checkNewDemand(Scenario scenario, Set demandInformation, - Collection polygonsInShape, String shapeCategory) { + ShpOptions.Index indexShape, String shapeCategory) { for (DemandInformationElement newDemand : demandInformation) { Carriers carriers = (Carriers) scenario.getScenarioElement("carriers"); @@ -439,13 +440,13 @@ static void checkNewDemand(Scenario scenario, Set dema throw new RuntimeException("For the carrier " + newDemand.getCarrierName() + ": Select either share of population or number of locations"); if (newDemand.getAreasFirstJobElement() != null) { - if (polygonsInShape == null) + if (indexShape == null) throw new RuntimeException("You selected a certain area for the carrier" + newDemand.getCarrierName() + " although no shape file is loaded."); for (String demandArea : newDemand.getAreasFirstJobElement()) { boolean isInShape = false; - for (SimpleFeature singlePolygon : polygonsInShape) + for (SimpleFeature singlePolygon : indexShape.getAllFeatures()) if ((singlePolygon.getAttribute(shapeCategory) != null && singlePolygon.getAttribute(shapeCategory).equals(demandArea))) { isInShape = true; @@ -501,12 +502,12 @@ static void checkNewDemand(Scenario scenario, Set dema throw new RuntimeException("For the carrier " + newDemand.getCarrierName() + ": The percentage of the population should be more than 0 and maximum 100pct. Please check!"); if (newDemand.getAreasSecondJobElement() != null) { - if (polygonsInShape == null) + if (indexShape == null) throw new RuntimeException("You selected a certain area for the carrier" + newDemand.getCarrierName() + " although no shape file is loaded."); for (String demand : newDemand.getAreasSecondJobElement()) { boolean isInShape = false; - for (SimpleFeature singlePolygon : polygonsInShape) + for (SimpleFeature singlePolygon : indexShape.getAllFeatures()) if (singlePolygon.getAttribute(shapeCategory).equals(demand)) { isInShape = true; break; @@ -537,22 +538,22 @@ static void checkNewDemand(Scenario scenario, Set dema * Creates for every demand information the services/shipments for the carriers * * @param scenario - * @param polygonsInShape + * @param indexShape * @param demandInformation * @param population * @param combineSimilarJobs * @param crsTransformationNetworkAndShape */ - static void createDemandForCarriers(Scenario scenario, Collection polygonsInShape, + static void createDemandForCarriers(Scenario scenario, ShpOptions.Index indexShape, Set demandInformation, Population population, boolean combineSimilarJobs, CoordinateTransformation crsTransformationNetworkAndShape) { for (DemandInformationElement newDemandInformationElement : demandInformation) { if (newDemandInformationElement.getTypeOfDemand().equals("service")) - createServices(scenario, newDemandInformationElement, polygonsInShape, population, combineSimilarJobs, + createServices(scenario, newDemandInformationElement, indexShape, population, combineSimilarJobs, crsTransformationNetworkAndShape); else if (newDemandInformationElement.getTypeOfDemand().equals("shipment")) - createShipments(scenario, newDemandInformationElement, polygonsInShape, population, combineSimilarJobs, + createShipments(scenario, newDemandInformationElement, indexShape, population, combineSimilarJobs, crsTransformationNetworkAndShape); } @@ -563,14 +564,14 @@ else if (newDemandInformationElement.getTypeOfDemand().equals("shipment")) * * @param scenario * @param newDemandInformationElement - * @param polygonsInShape + * @param indexShape * @param population * @param combineSimilarJobs * @param crsTransformationNetworkAndShape */ private static void createServices(Scenario scenario, DemandInformationElement newDemandInformationElement, - Collection polygonsInShape, Population population, boolean combineSimilarJobs, - CoordinateTransformation crsTransformationNetworkAndShape) { + ShpOptions.Index indexShape, Population population, boolean combineSimilarJobs, + CoordinateTransformation crsTransformationNetworkAndShape) { int countOfLinks = 1; int distributedDemand = 0; @@ -598,7 +599,7 @@ else if (population == null) String samplingOption = String.valueOf(population.getAttributes().getAttribute("samplingOption")); if (areasForServiceLocations != null) - possiblePersonsForService = findPossiblePersons(population, areasForServiceLocations, polygonsInShape, + possiblePersonsForService = findPossiblePersons(population, areasForServiceLocations, indexShape, crsTransformationNetworkAndShape); else possiblePersonsForService.putAll(population.getPersons()); @@ -619,7 +620,7 @@ else if (samplingOption.equals("changeDemandOnLocation")) { numberOfServiceLocations = numberPossibleServices; } // find possible links for the services - HashMap, Link> possibleLinksForService = findAllPossibleLinks(scenario, polygonsInShape, + HashMap, Link> possibleLinksForService = findAllPossibleLinks(scenario, indexShape, crsTransformationNetworkAndShape, numberOfServiceLocations, areasForServiceLocations, locationsOfServices, possiblePersonsForService, nearestLinkPerPerson); @@ -634,7 +635,7 @@ else if (samplingOption.equals("changeDemandOnLocation")) { if (possibleLinksForService.size() > demandToDistribute) { for (int i = 0; i < demandToDistribute; i++) { - Link link = findNextUsedLink(scenario, polygonsInShape, possibleLinksForService, numberOfJobs, + Link link = findNextUsedLink(scenario, indexShape, possibleLinksForService, numberOfJobs, areasForServiceLocations, locationsOfServices, usedServiceLocations, possiblePersonsForService, nearestLinkPerPerson, crsTransformationNetworkAndShape, i); double serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit(); @@ -706,7 +707,7 @@ else if (samplingOption.equals("changeDemandOnLocation")) { if (locationsOfServices != null && locationsOfServices.length > i) { link = scenario.getNetwork().getLinks().get(Id.createLinkId(locationsOfServices[i])); } else - link = findNextUsedLink(scenario, polygonsInShape, possibleLinksForService, + link = findNextUsedLink(scenario, indexShape, possibleLinksForService, numberOfServiceLocations, areasForServiceLocations, locationsOfServices, usedServiceLocations, possiblePersonsForService, nearestLinkPerPerson, crsTransformationNetworkAndShape, i); @@ -755,14 +756,14 @@ else if (samplingOption.equals("changeDemandOnLocation")) { * * @param scenario * @param newDemandInformationElement - * @param polygonsInShape + * @param indexShape * @param population * @param combineSimilarJobs * @param crsTransformationNetworkAndShape */ private static void createShipments(Scenario scenario, DemandInformationElement newDemandInformationElement, - Collection polygonsInShape, Population population, boolean combineSimilarJobs, - CoordinateTransformation crsTransformationNetworkAndShape) { + ShpOptions.Index indexShape, Population population, boolean combineSimilarJobs, + CoordinateTransformation crsTransformationNetworkAndShape) { int countOfLinks = 1; int distributedDemand = 0; @@ -797,12 +798,12 @@ else if (population == null) String samplingOption = String.valueOf(population.getAttributes().getAttribute("samplingOption")); if (areasForPickupLocations != null) - possiblePersonsPickup = findPossiblePersons(population, areasForPickupLocations, polygonsInShape, + possiblePersonsPickup = findPossiblePersons(population, areasForPickupLocations, indexShape, crsTransformationNetworkAndShape); else possiblePersonsPickup.putAll(population.getPersons()); if (areasForDeliveryLocations != null) - possiblePersonsDelivery = findPossiblePersons(population, areasForDeliveryLocations, polygonsInShape, + possiblePersonsDelivery = findPossiblePersons(population, areasForDeliveryLocations, indexShape, crsTransformationNetworkAndShape); else possiblePersonsDelivery.putAll(population.getPersons()); @@ -861,10 +862,10 @@ else if (population == null) numberOfDeliveryLocations = numberPossibleJobsDelivery; } // find possible Links for delivery and pickup - HashMap, Link> possibleLinksPickup = findAllPossibleLinks(scenario, polygonsInShape, + HashMap, Link> possibleLinksPickup = findAllPossibleLinks(scenario, indexShape, crsTransformationNetworkAndShape, numberOfPickupLocations, areasForPickupLocations, setLocationsOfPickup, possiblePersonsPickup, nearestLinkPerPersonPickup); - HashMap, Link> possibleLinksDelivery = findAllPossibleLinks(scenario, polygonsInShape, + HashMap, Link> possibleLinksDelivery = findAllPossibleLinks(scenario, indexShape, crsTransformationNetworkAndShape, numberOfDeliveryLocations, areasForDeliveryLocations, setLocationsOfDelivery, possiblePersonsDelivery, nearestLinkPerPersonPickup); @@ -882,22 +883,25 @@ else if (population == null) + " for pickup is not part of the possible links for pickup. Please check!"); if (setLocationsOfDelivery != null) - for (String selectedLinkIdDelivery : setLocationsOfDelivery) - if (!possibleLinksDelivery.containsKey(Id.createLinkId(selectedLinkIdDelivery))) - throw new RuntimeException("The selected link " + selectedLinkIdDelivery + if (numberOfDeliveryLocations < setLocationsOfDelivery.length) + log.warn("You selected more certain locations than the set number of locations. Randomly selected locations will be used."); + else + for (String selectedLinkIdDelivery : setLocationsOfDelivery) + if (!possibleLinksDelivery.containsKey(Id.createLinkId(selectedLinkIdDelivery))) + throw new RuntimeException("The selected link " + selectedLinkIdDelivery + " for delivery is not part of the possible links for delivery. Please check!"); - // distribute the demand over the network because no number of jobs are selected + // distribute the demand over the network because no number of jobs is selected if (numberOfJobs == null) { // creates shipments with a demand of 1 if (possibleLinksPickup.size() > demandToDistribute || possibleLinksDelivery.size() > demandToDistribute) { for (int i = 0; i < demandToDistribute; i++) { Link linkPickup; Link linkDelivery; - linkPickup = findNextUsedLink(scenario, polygonsInShape, possibleLinksPickup, + linkPickup = findNextUsedLink(scenario, indexShape, possibleLinksPickup, numberOfPickupLocations, areasForPickupLocations, setLocationsOfPickup, usedPickupLocations, possiblePersonsPickup, nearestLinkPerPersonPickup, crsTransformationNetworkAndShape, i); - linkDelivery = findNextUsedLink(scenario, polygonsInShape, possibleLinksDelivery, + linkDelivery = findNextUsedLink(scenario, indexShape, possibleLinksDelivery, numberOfDeliveryLocations, areasForDeliveryLocations, setLocationsOfDelivery, usedDeliveryLocations, possiblePersonsDelivery, nearestLinkPerPersonDelivery, crsTransformationNetworkAndShape, i); @@ -970,12 +974,12 @@ else if (numberOfPickupLocations != null) { } if (pickupIsDemandBase) { linkPickup = demandBasedLink; - linkDelivery = findNextUsedLink(scenario, polygonsInShape, possibleLinksDelivery, + linkDelivery = findNextUsedLink(scenario, indexShape, possibleLinksDelivery, numberOfDeliveryLocations, areasForDeliveryLocations, setLocationsOfDelivery, usedDeliveryLocations, possiblePersonsDelivery, nearestLinkPerPersonDelivery, crsTransformationNetworkAndShape, countOfLinks - 1); while (usedDeliveryLocations.contains(linkDelivery.getId().toString())) { - linkDelivery = findNextUsedLink(scenario, polygonsInShape, possibleLinksDelivery, + linkDelivery = findNextUsedLink(scenario, indexShape, possibleLinksDelivery, numberOfDeliveryLocations, areasForDeliveryLocations, setLocationsOfDelivery, usedDeliveryLocations, possiblePersonsDelivery, nearestLinkPerPersonDelivery, crsTransformationNetworkAndShape, countOfLinks - 1); @@ -986,12 +990,12 @@ else if (numberOfPickupLocations != null) { } } else { linkDelivery = demandBasedLink; - linkPickup = findNextUsedLink(scenario, polygonsInShape, possibleLinksPickup, + linkPickup = findNextUsedLink(scenario, indexShape, possibleLinksPickup, numberOfPickupLocations, areasForPickupLocations, setLocationsOfPickup, usedPickupLocations, possiblePersonsPickup, nearestLinkPerPersonPickup, crsTransformationNetworkAndShape, countOfLinks - 1); while (usedPickupLocations.contains(linkPickup.getId().toString())) { - linkPickup = findNextUsedLink(scenario, polygonsInShape, possibleLinksPickup, + linkPickup = findNextUsedLink(scenario, indexShape, possibleLinksPickup, numberOfPickupLocations, areasForPickupLocations, setLocationsOfPickup, usedPickupLocations, possiblePersonsPickup, nearestLinkPerPersonPickup, crsTransformationNetworkAndShape, countOfLinks - 1); @@ -1036,10 +1040,10 @@ else if (numberOfPickupLocations != null) { if (demandToDistribute != 0 && demandToDistribute < numberOfJobs) throw new RuntimeException( "The resulting number of jobs is not feasible, because the demand is smaller then the number of jobs. Please check!"); - Link linkPickup = findNextUsedLink(scenario, polygonsInShape, possibleLinksPickup, + Link linkPickup = findNextUsedLink(scenario, indexShape, possibleLinksPickup, numberOfPickupLocations, areasForPickupLocations, setLocationsOfPickup, usedPickupLocations, possiblePersonsPickup, nearestLinkPerPersonPickup, crsTransformationNetworkAndShape, i); - Link linkDelivery = findNextUsedLink(scenario, polygonsInShape, possibleLinksDelivery, + Link linkDelivery = findNextUsedLink(scenario, indexShape, possibleLinksDelivery, numberOfDeliveryLocations, areasForDeliveryLocations, setLocationsOfDelivery, usedDeliveryLocations, possiblePersonsDelivery, nearestLinkPerPersonDelivery, crsTransformationNetworkAndShape, i); @@ -1088,8 +1092,8 @@ else if (numberOfPickupLocations != null) { } /** - * Creates a job Id for a new job. If a certain Id is already used a number will - * be added at the end until no existing job was the same Id. + * Creates a job Id for a new job. + * If a certain Id is already used, a number will be added at the end until no existing job was the same Id. * * @param scenario * @param newDemandInformationElement @@ -1127,8 +1131,8 @@ private static String createJobId(Scenario scenario, DemandInformationElement ne } /** - * If jobs of a carrier have the same characteristics (time window, location) - * they will be combined to one job, + * If jobs of a carrier have the same characteristics (time window, location), + * they will be combined to one job. * * @param scenario * @param newDemandInformationElement @@ -1240,7 +1244,7 @@ private static void reduceNumberOfJobsIfSameCharacteristics(Scenario scenario, * Finds and returns all possible links for this job. * * @param scenario - * @param polygonsInShape + * @param indexShape * @param crsTransformationNetworkAndShape * @param numberOfLocations * @param areasForLocations @@ -1250,22 +1254,24 @@ private static void reduceNumberOfJobsIfSameCharacteristics(Scenario scenario, * @return */ private static HashMap, Link> findAllPossibleLinks(Scenario scenario, - Collection polygonsInShape, CoordinateTransformation crsTransformationNetworkAndShape, - Integer numberOfLocations, String[] areasForLocations, String[] setLocations, - HashMap, Person> possiblePersons, - HashMap, HashMap> nearestLinkPerPerson) { + ShpOptions.Index indexShape, CoordinateTransformation crsTransformationNetworkAndShape, + Integer numberOfLocations, String[] areasForLocations, String[] setLocations, + HashMap, Person> possiblePersons, + HashMap, HashMap> nearestLinkPerPerson) { HashMap, Link> possibleLinks = new HashMap, Link>(); if (numberOfLocations == null) { for (Link link : scenario.getNetwork().getLinks().values()) - if (!link.getId().toString().contains("pt") && (!link.getAttributes().getAsMap().containsKey("type") || !link.getAttributes().getAsMap().get("type").toString().contains("motorway")) && FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, - areasForLocations, crsTransformationNetworkAndShape)) { + if (!link.getId().toString().contains("pt") && (!link.getAttributes().getAsMap().containsKey( + "type") || !link.getAttributes().getAsMap().get("type").toString().contains( + "motorway")) && FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, + areasForLocations, crsTransformationNetworkAndShape)) { possibleLinks.put(link.getId(), link); } } else { - Link newPossibleLink = null; + Link newPossibleLink; while (possibleLinks.size() < numberOfLocations) { newPossibleLink = findPossibleLinkForDemand(possibleLinks, possiblePersons, nearestLinkPerPerson, - polygonsInShape, areasForLocations, numberOfLocations, scenario, setLocations, + indexShape, areasForLocations, numberOfLocations, scenario, setLocations, crsTransformationNetworkAndShape); if (!possibleLinks.containsKey(newPossibleLink.getId())) possibleLinks.put(newPossibleLink.getId(), newPossibleLink); @@ -1279,7 +1285,7 @@ private static HashMap, Link> findAllPossibleLinks(Scenario scenario, * Finds the next link which can be used as a location. * * @param scenario - * @param polygonsInShape + * @param indexShape * @param possibleLinks * @param selectedNumberOfLocations * @param areasForLocations @@ -1291,7 +1297,7 @@ private static HashMap, Link> findAllPossibleLinks(Scenario scenario, * @param i * @return */ - private static Link findNextUsedLink(Scenario scenario, Collection polygonsInShape, + private static Link findNextUsedLink(Scenario scenario, ShpOptions.Index indexShape, HashMap, Link> possibleLinks, Integer selectedNumberOfLocations, String[] areasForLocations, String[] selectedLocations, ArrayList usedLocations, HashMap, Person> possiblePersons, HashMap, HashMap> nearestLinkPerPerson, @@ -1305,7 +1311,7 @@ private static Link findNextUsedLink(Scenario scenario, Collection usedLocations.size() && usedLocations.contains(link.getId().toString()))) link = findPossibleLinkForDemand(possibleLinks, possiblePersons, nearestLinkPerPerson, - polygonsInShape, areasForLocations, selectedNumberOfLocations, scenario, selectedLocations, + indexShape, areasForLocations, selectedNumberOfLocations, scenario, selectedLocations, crsTransformationNetworkAndShape); } else { link = scenario.getNetwork().getLinks() @@ -1315,30 +1321,26 @@ private static Link findNextUsedLink(Scenario scenario, Collection, Person> findPossiblePersons(Population population, - String[] areasForServiceLocations, Collection polygonsInShape, + String[] areasForServiceLocations, ShpOptions.Index indexShape, CoordinateTransformation crsTransformationNetworkAndShape) { HashMap, Person> possiblePersons = new HashMap, Person>(); for (Person person : population.getPersons().values()) { - Point p = MGC.xy2Point((double) person.getAttributes().getAttribute("homeX"), - (double) person.getAttributes().getAttribute("homeY")); - Coord coord; + Coord coord = getHomeCoord(person); if (crsTransformationNetworkAndShape != null) - coord = crsTransformationNetworkAndShape.transform(MGC.point2Coord(p)); - else - coord = MGC.point2Coord(p); + coord = crsTransformationNetworkAndShape.transform(coord); - if (FreightDemandGenerationUtils.checkPositionInShape(null, MGC.coord2Point(coord), polygonsInShape, + if (FreightDemandGenerationUtils.checkPositionInShape(null, coord, indexShape, areasForServiceLocations, crsTransformationNetworkAndShape)) possiblePersons.put(person.getId(), person); } @@ -1352,15 +1354,13 @@ private static HashMap, Person> findPossiblePersons(Population popula * @param nearestLinkPerPerson * @param person */ - static void findLinksForPersons(Scenario scenario, - HashMap, HashMap> nearestLinkPerPerson, Person person) { - + static void findLinksForPerson(Scenario scenario, + HashMap, HashMap> nearestLinkPerPerson, Person person) { + Coord homePoint = getHomeCoord(person); for (Link link : scenario.getNetwork().getLinks().values()) if (!link.getId().toString().contains("pt") && (!link.getAttributes().getAsMap().containsKey("type") || !link.getAttributes().getAsMap().get("type").toString().contains("motorway"))) { - Coord homePoint = MGC.point2Coord(MGC.xy2Point((double) person.getAttributes().getAttribute("homeX"), - (double) person.getAttributes().getAttribute("homeY"))); Coord middlePointLink = FreightDemandGenerationUtils.getCoordOfMiddlePointOfLink(link); double distance = NetworkUtils.getEuclideanDistance(homePoint, middlePointLink); if (!nearestLinkPerPerson.containsKey(person.getId()) @@ -1371,13 +1371,37 @@ static void findLinksForPersons(Scenario scenario, } } + /** + * Method to get the home coordinate of a person. + * The default is to get the home coordinate from one home activity of the selected plan. + * If the selected plan does not contain a home activity, the home coordinate is read from the attributes of the person. + * + * @param person The person for which the home coordinate should be returned. + * @return + */ + private static Coord getHomeCoord(Person person) { + Coord homeCoord = null; + if (person.getSelectedPlan() != null) + homeCoord = PopulationUtils.getActivities(person.getSelectedPlan(), + TripStructureUtils.StageActivityHandling.ExcludeStageActivities).stream().filter( + activity -> activity.getType().contains("home")).findFirst().get().getCoord(); + if (homeCoord == null) { + double home_x = (double) person.getAttributes().getAsMap().entrySet().stream().filter( + entry -> entry.getKey().contains("home") && entry.getKey().contains("X")).findFirst().get().getValue(); + double home_y = (double) person.getAttributes().getAsMap().entrySet().stream().filter( + entry -> entry.getKey().contains("home") && entry.getKey().contains("Y")).findFirst().get().getValue(); + homeCoord = new Coord(home_x, home_y); + } + return homeCoord; + } + /** * Searches a possible link for the demand. * * @param possibleLinks * @param possiblePersons * @param nearestLinkPerPerson - * @param polygonsInShape + * @param indexShape * @param areasForTheDemand * @param selectedNumberOfLocations * @param scenario @@ -1386,10 +1410,10 @@ static void findLinksForPersons(Scenario scenario, * @return */ private static Link findPossibleLinkForDemand(HashMap, Link> possibleLinks, - HashMap, Person> possiblePersons, - HashMap, HashMap> nearestLinkPerPerson, - Collection polygonsInShape, String[] areasForTheDemand, Integer selectedNumberOfLocations, - Scenario scenario, String[] selectedLocations, CoordinateTransformation crsTransformationNetworkAndShape) { + HashMap, Person> possiblePersons, + HashMap, HashMap> nearestLinkPerPerson, + ShpOptions.Index indexShape, String[] areasForTheDemand, Integer selectedNumberOfLocations, + Scenario scenario, String[] selectedLocations, CoordinateTransformation crsTransformationNetworkAndShape) { Link selectedlink = null; Link newLink = null; if (selectedNumberOfLocations == null) @@ -1406,16 +1430,7 @@ private static Link findPossibleLinkForDemand(HashMap, Link> possibleLi newLink = scenario.getNetwork().getLinks().values().stream() .skip(rand.nextInt(scenario.getNetwork().getLinks().size())).findFirst().get(); else { - Person person = possiblePersons.values().stream().skip(rand.nextInt(possiblePersons.size())) - .findFirst().get(); - if (nearestLinkPerPerson.containsKey(person.getId())) - newLink = scenario.getNetwork().getLinks().get(Id - .createLinkId(nearestLinkPerPerson.get(person.getId()).values().iterator().next())); - else { - findLinksForPersons(scenario, nearestLinkPerPerson, person); - newLink = scenario.getNetwork().getLinks().get(Id - .createLinkId(nearestLinkPerPerson.get(person.getId()).values().iterator().next())); - } + newLink = getNewLinkForPerson(possiblePersons, nearestLinkPerPerson, scenario); } } } else { @@ -1423,25 +1438,29 @@ private static Link findPossibleLinkForDemand(HashMap, Link> possibleLi newLink = possibleLinks.values().stream().skip(rand.nextInt(possibleLinks.size())).findFirst() .get(); } else { - Person person = possiblePersons.values().stream().skip(rand.nextInt(possiblePersons.size())) - .findFirst().get(); - if (nearestLinkPerPerson.containsKey(person.getId())) - newLink = scenario.getNetwork().getLinks().get( - Id.createLinkId(nearestLinkPerPerson.get(person.getId()).values().iterator().next())); - else { - findLinksForPersons(scenario, nearestLinkPerPerson, person); - newLink = scenario.getNetwork().getLinks().get( - Id.createLinkId(nearestLinkPerPerson.get(person.getId()).values().iterator().next())); - } + newLink = getNewLinkForPerson(possiblePersons, nearestLinkPerPerson, scenario); } } if (!newLink.getId().toString().contains("pt") && (!newLink.getAttributes().getAsMap().containsKey("type") || !newLink.getAttributes().getAsMap().get("type").toString().contains("motorway")) - && (polygonsInShape == null || FreightDemandGenerationUtils.checkPositionInShape(newLink, null, - polygonsInShape, areasForTheDemand, crsTransformationNetworkAndShape))) + && (indexShape == null || FreightDemandGenerationUtils.checkPositionInShape(newLink, null, + indexShape, areasForTheDemand, crsTransformationNetworkAndShape))) selectedlink = newLink; } return selectedlink; } + + private static Link getNewLinkForPerson(HashMap, Person> possiblePersons, + HashMap, HashMap> nearestLinkPerPerson, Scenario scenario) { + Link newLink; + Person person = possiblePersons.values().stream().skip(rand.nextInt(possiblePersons.size())) + .findFirst().get(); + if (!nearestLinkPerPerson.containsKey(person.getId())) { + findLinksForPerson(scenario, nearestLinkPerPerson, person); + } + newLink = scenario.getNetwork().getLinks().get( + Id.createLinkId(nearestLinkPerPerson.get(person.getId()).values().iterator().next())); + return newLink; + } } diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java index caec3bbf367..d43ee64522e 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java @@ -26,14 +26,6 @@ import org.matsim.api.core.v01.population.Population; import org.matsim.application.MATSimAppCommand; import org.matsim.application.options.ShpOptions; -import org.matsim.freight.carriers.FreightCarriersConfigGroup; -import org.matsim.freight.carriers.Carrier; -import org.matsim.freight.carriers.CarrierPlanWriter; -import org.matsim.freight.carriers.CarriersUtils; -import org.matsim.freight.carriers.Carriers; -import org.matsim.freight.carriers.controler.CarrierModule; -import org.matsim.freight.carriers.controler.CarrierScoringFunctionFactory; -import org.matsim.freight.carriers.usecases.chessboard.CarrierScoringFunctionFactoryImpl; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ControllerConfigGroup; @@ -44,14 +36,15 @@ import org.matsim.core.population.PopulationUtils; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.CoordinateTransformation; -import org.opengis.feature.simple.SimpleFeature; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.controler.CarrierModule; +import org.matsim.freight.carriers.controler.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.usecases.chessboard.CarrierScoringFunctionFactoryImpl; import picocli.CommandLine; import javax.management.InvalidAttributeValueException; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collection; import java.util.Objects; import java.util.concurrent.ExecutionException; @@ -129,7 +122,7 @@ private enum OptionsOfVRPSolutions { private ShpOptions shp = new ShpOptions(shapeFilePath, shapeCRS, null); @CommandLine.Option(names = "--populationFileLocation", description = "Path to the population file.", defaultValue = "") - private Path populationFilePath; + private String populationFilePath; @CommandLine.Option(names = "--populationCRS", description = "CRS of the input network (e.g.\"EPSG:31468\")") private String populationCRS; @@ -169,8 +162,6 @@ public static void main(String[] args) { public Integer call() throws IOException, InvalidAttributeValueException, ExecutionException, InterruptedException { String vehicleTypesFileLocation = carrierVehicleFilePath.toString(); - String carriersFileLocation = carrierFilePath.toString(); - String populationFile = populationFilePath.toString(); CoordinateTransformation crsTransformationFromNetworkToShape = null; // create and prepare MATSim config @@ -194,20 +185,20 @@ public Integer call() throws IOException, InvalidAttributeValueException, Execut // load or create carrier Scenario scenario = ScenarioUtils.loadScenario(config); - Collection polygonsInShape = null; + ShpOptions.Index indexShape = null; shp = new ShpOptions(shapeFilePath, shapeCRS, null); if (shp.isDefined()) { log.warn("Use of shpFile. Locations for the carriers and the demand only in shp: " + shp.getShapeFile()); - polygonsInShape = shp.readFeatures(); + indexShape = shp.createIndex(shapeCategory); crsTransformationFromNetworkToShape = shp.createTransformation(networkCRS); } log.info("Start creating carriers. Selected option: " + selectedCarrierInputOption); - createCarrier(scenario, selectedCarrierInputOption, carriersFileLocation, csvCarrierPath, polygonsInShape, + createCarrier(scenario, selectedCarrierInputOption, csvCarrierPath, indexShape, defaultJspritIterations, crsTransformationFromNetworkToShape); // create the demand log.info("Start creating the demand. Selected option: " + selectedCarrierInputOption); - createDemand(selectedDemandGenerationOption, scenario, csvDemandPath, polygonsInShape, populationFile, + createDemand(selectedDemandGenerationOption, scenario, csvDemandPath, indexShape, populationFilePath, selectedPopulationSamplingOption, selectedPopulationOption, Boolean.getBoolean(combineSimilarJobs), crsTransformationFromNetworkToShape); @@ -243,6 +234,8 @@ private Config prepareConfig(int lastMATSimIteration, String coordinateSystem) { FreightCarriersConfigGroup freightCarriersConfigGroup = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); freightCarriersConfigGroup.setTravelTimeSliceWidth(1800); freightCarriersConfigGroup.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.enforceBeginnings); + if (carrierFilePath != null) + freightCarriersConfigGroup.setCarriersFile(carrierFilePath.toString()); return config; } @@ -258,12 +251,12 @@ private Config prepareConfig(int lastMATSimIteration, String coordinateSystem) { private static void setNetworkAndNetworkChangeEvents(Config config, String networkPathOfOtherNetwork, String networkChangeEventsFileLocation) throws RuntimeException { - if (networkPathOfOtherNetwork.equals("")) + if (networkPathOfOtherNetwork.isEmpty()) throw new RuntimeException("no correct network path network"); else { config.network().setInputFile(networkPathOfOtherNetwork); log.info("The following input network is selected: imported network from " + networkPathOfOtherNetwork); - if (networkChangeEventsFileLocation.equals("")) + if (networkChangeEventsFileLocation.isEmpty()) log.info("No networkChangeEvents selected"); else { log.info("Setting networkChangeEventsInput file: " + networkChangeEventsFileLocation); @@ -295,15 +288,14 @@ private static void prepareVehicles(Config config, String vehicleTypesFileLocati * * @param scenario * @param selectedCarrierInputOption - * @param carriersFileLocation * @param csvLocationCarrier - * @param polygonsInShape + * @param indexShape * @param defaultJspritIterations * @param crsTransformationNetworkAndShape * @throws IOException */ private void createCarrier(Scenario scenario, CarrierInputOptions selectedCarrierInputOption, - String carriersFileLocation, Path csvLocationCarrier, Collection polygonsInShape, + Path csvLocationCarrier, ShpOptions.Index indexShape, int defaultJspritIterations, CoordinateTransformation crsTransformationNetworkAndShape) throws IOException { FreightCarriersConfigGroup freightCarriersConfigGroup = ConfigUtils.addOrGetModule(scenario.getConfig(), @@ -312,42 +304,40 @@ private void createCarrier(Scenario scenario, CarrierInputOptions selectedCarrie case addCSVDataToExistingCarrierFileData -> { // reads an existing carrier file and adds the information based on the read csv // carrier file - if (Objects.equals(carriersFileLocation, "")) + if (freightCarriersConfigGroup.getCarriersFile() == null) throw new RuntimeException("No path to the carrier file selected"); else { - freightCarriersConfigGroup.setCarriersFile(carriersFileLocation); CarriersUtils.loadCarriersAccordingToFreightConfig(scenario); - log.info("Load carriers from: " + carriersFileLocation); + log.info("Load carriers from: " + freightCarriersConfigGroup.getCarriersFile()); CarrierReaderFromCSV.readAndCreateCarrierFromCSV(scenario, freightCarriersConfigGroup, csvLocationCarrier, - polygonsInShape, defaultJspritIterations, crsTransformationNetworkAndShape, shapeCategory); + indexShape, defaultJspritIterations, crsTransformationNetworkAndShape, shapeCategory); } } case readCarrierFile -> { // reads only a carrier file as the carrier import. - if (Objects.equals(carriersFileLocation, "")) + if (freightCarriersConfigGroup.getCarriersFile() == null) throw new RuntimeException("No path to the carrier file selected"); else { - freightCarriersConfigGroup.setCarriersFile(carriersFileLocation); CarriersUtils.loadCarriersAccordingToFreightConfig(scenario); - log.info("Load carriers from: " + carriersFileLocation); + log.info("Load carriers from: " + freightCarriersConfigGroup.getCarriersFile()); } } case createCarriersFromCSV -> // creates all carriers based on the given information in the read carrier csv CarrierReaderFromCSV.readAndCreateCarrierFromCSV(scenario, freightCarriersConfigGroup, csvLocationCarrier, - polygonsInShape, defaultJspritIterations, crsTransformationNetworkAndShape, shapeCategory); + indexShape, defaultJspritIterations, crsTransformationNetworkAndShape, shapeCategory); default -> throw new RuntimeException("no method to create or read carrier selected."); } } /** - * Differs between the different options of creating the demand.. + * Differs between the different options of creating the demand. * * @param selectedDemandGenerationOption * @param scenario * @param csvLocationDemand - * @param polygonsInShape - * @param populationFile + * @param indexShape + * @param populationFilePath * @param selectedSamplingOption * @param selectedPopulationOption * @param combineSimilarJobs @@ -355,31 +345,31 @@ private void createCarrier(Scenario scenario, CarrierInputOptions selectedCarrie * @throws IOException */ private void createDemand(DemandGenerationOptions selectedDemandGenerationOption, Scenario scenario, - Path csvLocationDemand, Collection polygonsInShape, String populationFile, - PopulationSamplingOption selectedSamplingOption, PopulationOptions selectedPopulationOption, - boolean combineSimilarJobs, CoordinateTransformation crsTransformationNetworkAndShape) throws IOException { + Path csvLocationDemand, ShpOptions.Index indexShape, String populationFilePath, + PopulationSamplingOption selectedSamplingOption, PopulationOptions selectedPopulationOption, + boolean combineSimilarJobs, CoordinateTransformation crsTransformationNetworkAndShape) throws IOException { switch (selectedDemandGenerationOption) { case createDemandFromCSV -> // creates the demand by using the information given in the read csv file - DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, polygonsInShape, combineSimilarJobs, + DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, indexShape, combineSimilarJobs, crsTransformationNetworkAndShape, null, shapeCategory); case createDemandFromCSVAndUsePopulation -> { /* * Option creates the demand by using the information given in the read csv file * and uses a population for finding demand locations */ - Population population = PopulationUtils.readPopulation(populationFile); + Population population = PopulationUtils.readPopulation(populationFilePath); switch (selectedSamplingOption) { /* - * this option is important if the sample of the population and the sample of + * This option is important if the sample of the population and the sample of * the resulting demand is different. For example, you can create with a 10pct * sample a 100pct demand modal for the waste collection. */ case createMoreLocations -> /* * If the demand sample is higher than the population sample, more demand - * location are created related to the given share of persons of the population + * locations are created related to the given share of persons in the population * with this demand. */ FreightDemandGenerationUtils.preparePopulation(population, sampleSizeInputPopulation, @@ -398,14 +388,14 @@ private void createDemand(DemandGenerationOptions selectedDemandGenerationOption break; case useHolePopulation: // uses the hole population as possible demand locations - DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, polygonsInShape, + DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, indexShape, combineSimilarJobs, crsTransformationNetworkAndShape, population, shapeCategory); break; case usePopulationInShape: // uses only the population with home location in the given shape file FreightDemandGenerationUtils.reducePopulationToShapeArea(population, shp.createIndex(populationCRS, "_")); - DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, polygonsInShape, + DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, indexShape, combineSimilarJobs, crsTransformationNetworkAndShape, population, shapeCategory); break; default: @@ -460,7 +450,7 @@ private static void solveSelectedSolution(OptionsOfVRPSolutions selectedSolution Controler controler) throws ExecutionException, InterruptedException { switch (selectedSolution) { case runJspritAndMATSim -> { - // solves the VRP with jsprit and runs MATSim afterwards + // solves the VRP with jsprit and runs MATSim afterward new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) .write(config.controller().getOutputDirectory() + "/output_carriersNoPlans.xml"); runJsprit(controler, false); @@ -469,8 +459,7 @@ private static void solveSelectedSolution(OptionsOfVRPSolutions selectedSolution .write(config.controller().getOutputDirectory() + "/output_carriersWithPlans.xml"); } case runJspritAndMATSimWithDistanceConstraint -> { - // solves the VRP with jsprit by using the distance constraint and runs MATSim - // afterwards + // solves the VRP with jsprit by using the distance constraint and runs MATSim afterward new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) .write(config.controller().getOutputDirectory() + "/output_carriersNoPlans.xml"); runJsprit(controler, true); diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java index b2d70951be8..234d657c0b6 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java @@ -21,29 +21,30 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.Point; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; -import org.matsim.api.core.v01.population.*; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Plan; +import org.matsim.api.core.v01.population.Population; import org.matsim.application.options.ShpOptions; +import org.matsim.core.controler.Controler; +import org.matsim.core.population.PopulationUtils; +import org.matsim.core.router.TripStructureUtils; +import org.matsim.core.utils.geometry.CoordinateTransformation; +import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarrierService; import org.matsim.freight.carriers.CarrierShipment; import org.matsim.freight.carriers.CarriersUtils; -import org.matsim.core.controler.Controler; -import org.matsim.core.utils.geometry.CoordinateTransformation; -import org.matsim.core.utils.geometry.geotools.MGC; -import org.opengis.feature.simple.SimpleFeature; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; -import java.util.Collection; import java.util.List; +import java.util.Objects; /** * Collection of different methods for the FreightDemandGeneration. @@ -75,16 +76,39 @@ static void preparePopulation(Population population, double sampleSizeInputPopul personsToRemove.add(person.getId()); continue; } - for (Plan plan : person.getPlans()) - for (PlanElement element : plan.getPlanElements()) - if (element instanceof Activity) - if (((Activity) element).getType().contains("home")) { - double x = ((Activity) element).getCoord().getX(); - double y = ((Activity) element).getCoord().getY(); - person.getAttributes().putAttribute("homeX", x); - person.getAttributes().putAttribute("homeY", y); - break; - } + Coord homeCoord = null; + if (person.getSelectedPlan() != null) { + if (PopulationUtils.getActivities(person.getSelectedPlan(), + TripStructureUtils.StageActivityHandling.ExcludeStageActivities).stream().anyMatch( + activity -> activity.getType().contains("home"))) { + homeCoord = PopulationUtils.getActivities(person.getSelectedPlan(), + TripStructureUtils.StageActivityHandling.ExcludeStageActivities).stream().filter( + activity -> activity.getType().contains("home")).findFirst().get().getCoord(); + } + } else if (!person.getPlans().isEmpty()) + for (Plan plan : person.getPlans()) + if (PopulationUtils.getActivities(plan, + TripStructureUtils.StageActivityHandling.ExcludeStageActivities).stream().anyMatch( + activity -> activity.getType().contains("home"))) { + homeCoord = PopulationUtils.getActivities(plan, + TripStructureUtils.StageActivityHandling.ExcludeStageActivities).stream().filter( + activity -> activity.getType().contains("home")).findFirst().get().getCoord(); + } + if (homeCoord == null){ + double home_x = (double) person.getAttributes().getAsMap().entrySet().stream().filter( + entry -> entry.getKey().contains("home") && entry.getKey().contains("X") || entry.getKey().contains("x")).findFirst().get().getValue(); + double home_y = (double) person.getAttributes().getAsMap().entrySet().stream().filter( + entry -> entry.getKey().contains("home") && (entry.getKey().contains("Y") || entry.getKey().contains("y"))).findFirst().get().getValue(); + homeCoord = new Coord(home_x, home_y); + } + + + if (homeCoord != null) { + person.getAttributes().putAttribute("homeX", homeCoord.getX()); + person.getAttributes().putAttribute("homeY", homeCoord.getY()); + } else { + log.warn("No home found for person " + person.getId()); + } person.removePlan(person.getSelectedPlan()); } for (Id id : personsToRemove) @@ -164,42 +188,34 @@ static void reducePopulationToShapeArea(Population population, ShpOptions.Index * Checks if a link is one of the possible areas. * * @param link - * @param point - * @param polygonsInShape + * @param givenCoord + * @param indexShape * @param possibleAreas * @param crsTransformationNetworkAndShape * @return */ - static boolean checkPositionInShape(Link link, Point point, Collection polygonsInShape, - String[] possibleAreas, CoordinateTransformation crsTransformationNetworkAndShape) { - - if (polygonsInShape == null) + static boolean checkPositionInShape(Link link, Coord givenCoord, ShpOptions.Index indexShape, + String[] possibleAreas, CoordinateTransformation crsTransformationNetworkAndShape) { + if (indexShape == null) return true; - boolean isInShape = false; - Point p = null; - if (link != null && point == null) { + Coord coordToCheck = null; + if (link != null && givenCoord == null) { if (crsTransformationNetworkAndShape != null) - p = MGC.coord2Point(crsTransformationNetworkAndShape.transform(getCoordOfMiddlePointOfLink(link))); + coordToCheck = crsTransformationNetworkAndShape.transform(getCoordOfMiddlePointOfLink(link)); else - p = MGC.coord2Point(getCoordOfMiddlePointOfLink(link)); - } else if (link == null && point != null) - p = point; - for (SimpleFeature singlePolygon : polygonsInShape) { - if (possibleAreas != null) { - for (String area : possibleAreas) { - if (area.equals(singlePolygon.getAttribute("Ortsteil")) - || area.equals(singlePolygon.getAttribute("BEZNAME"))) - if (((Geometry) singlePolygon.getDefaultGeometry()).contains(p)) { - return true; - } - } - } else { - if (((Geometry) singlePolygon.getDefaultGeometry()).contains(p)) { + coordToCheck = getCoordOfMiddlePointOfLink(link); + } else if (link == null && givenCoord != null) + coordToCheck = givenCoord; + if (possibleAreas != null) { + for (String area : possibleAreas) { + if (Objects.equals(indexShape.query(coordToCheck), area)) { return true; } } + } else { + return indexShape.contains(coordToCheck); } - return isInShape; + return false; } /** diff --git a/contribs/application/src/test/java/org/matsim/application/ConfigYamlUpdateTest.java b/contribs/application/src/test/java/org/matsim/application/ConfigYamlUpdateTest.java new file mode 100644 index 00000000000..8c6c4768b22 --- /dev/null +++ b/contribs/application/src/test/java/org/matsim/application/ConfigYamlUpdateTest.java @@ -0,0 +1,239 @@ +package org.matsim.application; + + +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; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +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() { + + Config config = ConfigUtils.createConfig(); + Path input = Path.of(utils.getClassInputDirectory()); + + ApplicationUtils.applyConfigUpdate( + config, input.resolve("standard.yml") + ); + + assertThat(config.controller().getRunId()).isEqualTo("567"); + assertThat(config.global().getNumberOfThreads()).isEqualTo(8); + + assertThat(config.scoring().getOrCreateModeParams("car").getConstant()).isEqualTo(-1); + assertThat(config.scoring().getOrCreateModeParams("bike").getConstant()).isEqualTo(-2); + } + + @Test + void createParamSet() { + + Config config = ConfigUtils.createConfig(); + Path input = Path.of(utils.getClassInputDirectory()); + + TestConfigGroup testGroup = ConfigUtils.addOrGetModule(config, TestConfigGroup.class); + + ApplicationUtils.applyConfigUpdate( + config, input.resolve("multiLevel.yml") + ); + + testGroup.addParam("values", "1, 2, 3"); + + assertThat(testGroup.values) + .containsExactly(1, 2, 3); + + Collection params = testGroup.getParameterSets("params"); + + assertThat(params).hasSize(2); + + Iterator it = params.iterator(); + TestParamSet next = (TestParamSet) it.next(); + + assertThat(next.getParams().get("mode")).isEqualTo("car"); + assertThat(next.getParams().get("values")).isEqualTo("-1.0, -2.0"); + assertThat(next.values).containsExactly(-1d, -2d); + + next = (TestParamSet) it.next(); + + assertThat(next.getParams().get("mode")).isEqualTo("bike"); + assertThat(next.getParams().get("values")).isEqualTo("3.0, 4.0"); + 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() { + + Config config = ConfigUtils.createConfig(); + Path input = Path.of(utils.getClassInputDirectory()); + + TestConfigGroup testGroup = ConfigUtils.addOrGetModule(config, TestConfigGroup.class); + + testGroup.addParameterSet(new TestParamSet("car", "person", "work")); + testGroup.addParameterSet(new TestParamSet("bike", "person", "work")); + + ApplicationUtils.applyConfigUpdate( + config, input.resolve("multiLevel.yml") + ); + + Collection params = testGroup.getParameterSets("params"); + assertThat(params).hasSize(2); + + Iterator it = params.iterator(); + ConfigGroup next = it.next(); + + // These parameters are recognized as lists correctly + assertThat(next.getParams().get("values")).isEqualTo("-1.0, -2.0"); + + next = it.next(); + assertThat(next.getParams().get("values")).isEqualTo("3.0, 4.0"); + assertThat(next.getParams().get("extra")).isEqualTo("extra"); + + } + + @Test + void updateOne() { + + Config config = ConfigUtils.createConfig(); + Path input = Path.of(utils.getClassInputDirectory()); + + TestConfigGroup testGroup = ConfigUtils.addOrGetModule(config, TestConfigGroup.class); + + testGroup.addParameterSet(new TestParamSet("car", "person", "work")); + + ApplicationUtils.applyConfigUpdate( + config, input.resolve("multiLevel.yml") + ); + + Collection params = testGroup.getParameterSets("params"); + assertThat(params).hasSize(2); + + Iterator it = params.iterator(); + ConfigGroup next = it.next(); + + assertThat(next.getParams().get("mode")).isEqualTo("car"); + assertThat(next.getParams().get("values")).isEqualTo("-1.0, -2.0"); + + next = it.next(); + assertThat(next.getParams().get("mode")).isEqualTo("bike"); + assertThat(next.getParams().get("values")).isEqualTo("3.0, 4.0"); + assertThat(next.getParams().get("extra")).isEqualTo("extra"); + } + + @Test + void ambiguous() { + + Config config = ConfigUtils.createConfig(); + Path input = Path.of(utils.getClassInputDirectory()); + + TestConfigGroup testGroup = ConfigUtils.addOrGetModule(config, TestConfigGroup.class); + + testGroup.addParameterSet(new TestParamSet("car", "person", "work")); + testGroup.addParameterSet(new TestParamSet("car", "person", "home")); + + // This should fail because the parameter set is ambiguous + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> { + ApplicationUtils.applyConfigUpdate( + config, input.resolve("multiLevel.yml") + ); + }); + } + + + public static final class TestConfigGroup extends ReflectiveConfigGroup { + + @Parameter + private List values; + + public TestConfigGroup() { + super("test"); + } + + @Override + public ConfigGroup createParameterSet(String type) { + if (type.equals("params")) { + return new TestParamSet(); + } + + return super.createParameterSet(type); + } + } + + + public static final class TestParamSet extends ReflectiveConfigGroup { + + @Parameter + private List values; + + public TestParamSet() { + super("params", true); + } + + public TestParamSet(String mode, String subpopulation, String activity) { + super("params", true); + + this.addParam("mode", mode); + this.addParam("subpopulation", subpopulation); + this.addParam("activity", activity); + } + } + +} diff --git a/contribs/application/src/test/java/org/matsim/application/options/CsvOptionsTest.java b/contribs/application/src/test/java/org/matsim/application/options/CsvOptionsTest.java index 65299cb0e81..a406deca398 100644 --- a/contribs/application/src/test/java/org/matsim/application/options/CsvOptionsTest.java +++ b/contribs/application/src/test/java/org/matsim/application/options/CsvOptionsTest.java @@ -3,11 +3,13 @@ import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.io.TempDir; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -20,18 +22,27 @@ public class CsvOptionsTest { @Test void output() throws IOException { - CsvOptions csv = new CsvOptions(CSVFormat.Predefined.TDF); + List delimiters = new ArrayList<>(); - Path tmp = f.resolve("test.csv"); + delimiters.add(new CsvOptions(CSVFormat.Predefined.TDF)); + delimiters.add(new CsvOptions(CSVFormat.Predefined.Default)); + delimiters.add(new CsvOptions(CSVFormat.Predefined.Default, ';', StandardCharsets.UTF_8)); - CSVPrinter printer = csv.createPrinter(tmp); + for (CsvOptions csv : delimiters) { + Path tmp = f.resolve("test.csv"); - printer.printRecord("header", "column"); - printer.printRecord("1", "2"); - printer.close(); + CSVPrinter printer = csv.createPrinter(tmp); - assertThat(tmp) - .hasContent("header\tcolumn\n1\t2"); + String delimiter = csv.getFormat().getDelimiterString(); + printer.printRecord("header", "column"); + printer.printRecord("1", "2"); + printer.close(); + + assertThat(tmp) + .hasContent("header" + delimiter + "column\n1" + delimiter + "2"); + + assertThat(delimiter).isEqualTo(CsvOptions.detectDelimiter(tmp.toString()).toString()); + } } } diff --git a/contribs/application/src/test/java/org/matsim/application/options/ShpOptionsTest.java b/contribs/application/src/test/java/org/matsim/application/options/ShpOptionsTest.java index 7742e1bdc2e..9b4b662733f 100644 --- a/contribs/application/src/test/java/org/matsim/application/options/ShpOptionsTest.java +++ b/contribs/application/src/test/java/org/matsim/application/options/ShpOptionsTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.locationtech.jts.geom.Geometry; +import org.matsim.api.core.v01.Coord; import org.matsim.testcases.MatsimTestUtils; import org.opengis.feature.simple.SimpleFeature; @@ -41,6 +42,30 @@ void readZip() { } + @Test + void get() { + + Path input = Path.of(utils.getClassInputDirectory() + .replace("ShpOptionsTest", "CreateLandUseShpTest") + .replace("options", "prepare")) + .resolve("andorra-latest-free.shp.zip"); + + Assumptions.assumeTrue(Files.exists(input)); + + ShpOptions shp = new ShpOptions(input, null, null); + + ShpOptions.Index index = shp.createIndex(shp.getShapeCrs(), "name"); + + SimpleFeature result = index.queryFeature(new Coord(1.5333461, 42.555388)); + + assertThat(result) + .isNotNull(); + + String name = index.query(new Coord(1.5333461, 42.555388)); + assertThat(name) + .isEqualTo("Museu de la Miniatura"); + } + @Test void all() { diff --git a/contribs/application/src/test/java/org/matsim/application/prepare/network/params/ApplyNetworkParamsTest.java b/contribs/application/src/test/java/org/matsim/application/prepare/network/params/ApplyNetworkParamsTest.java new file mode 100644 index 00000000000..b25737d6c40 --- /dev/null +++ b/contribs/application/src/test/java/org/matsim/application/prepare/network/params/ApplyNetworkParamsTest.java @@ -0,0 +1,45 @@ +package org.matsim.application.prepare.network.params; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.contrib.sumo.SumoNetworkConverter; +import org.matsim.testcases.MatsimTestUtils; + +import java.nio.file.Path; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class ApplyNetworkParamsTest { + + @RegisterExtension + MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + void apply() throws Exception { + + Path networkPath = Path.of(utils.getPackageInputDirectory()).resolve("osm.net.xml"); + + Path output = Path.of(utils.getOutputDirectory()); + + SumoNetworkConverter converter = SumoNetworkConverter.newInstance(List.of(networkPath), + output.resolve("network.xml"), + "EPSG:4326", "EPSG:4326"); + + converter.call(); + + assertThat(output.resolve("network.xml")).exists(); + assertThat(output.resolve("network-ft.csv")).exists(); + + new ApplyNetworkParams().execute( + "capacity", "freespeed", + "--network", output.resolve("network.xml").toString(), + "--input-features", output.resolve("network-ft.csv").toString(), + "--output", output.resolve("network-opt.xml").toString(), + "--model", "org.matsim.application.prepare.network.params.ref.GermanyNetworkParams" + ); + + assertThat(output.resolve("network-opt.xml")).exists(); + + } +} diff --git a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSVTest.java b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSVTest.java index 1bcb22e6b80..96e405eefd3 100644 --- a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSVTest.java +++ b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSVTest.java @@ -1,14 +1,7 @@ package org.matsim.freightDemandGeneration; -import java.io.IOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -17,21 +10,21 @@ import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; import org.matsim.application.options.ShpOptions; -import org.matsim.freight.carriers.FreightCarriersConfigGroup; -import org.matsim.freight.carriers.Carrier; -import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; -import org.matsim.freight.carriers.CarriersUtils; -import org.matsim.freight.carriers.CarrierVehicle; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.network.NetworkUtils; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.CarrierVehicle; +import org.matsim.freight.carriers.CarriersUtils; +import org.matsim.freight.carriers.FreightCarriersConfigGroup; import org.matsim.freightDemandGeneration.CarrierReaderFromCSV.CarrierInformationElement; import org.matsim.testcases.MatsimTestUtils; -import org.opengis.feature.simple.SimpleFeature; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import java.io.IOException; +import java.nio.file.Path; +import java.util.*; /** * @author Ricardo Ewert @@ -54,13 +47,13 @@ void carrierCreation() throws IOException { Path carrierCSVLocation = Path.of(utils.getPackageInputDirectory() + "testCarrierCSV.csv"); Path shapeFilePath = Path.of(utils.getPackageInputDirectory() + "testShape/testShape.shp"); ShpOptions shp = new ShpOptions(shapeFilePath, "WGS84", null); - Collection polygonsInShape = shp.readFeatures(); Set allNewCarrierInformation = CarrierReaderFromCSV .readCarrierInformation(carrierCSVLocation); String shapeCategory = "Ortsteil"; - CarrierReaderFromCSV.checkNewCarrier(allNewCarrierInformation, freightCarriersConfigGroup, scenario, polygonsInShape, shapeCategory); + ShpOptions.Index indexShape = shp.createIndex(shapeCategory); + CarrierReaderFromCSV.checkNewCarrier(allNewCarrierInformation, freightCarriersConfigGroup, scenario, indexShape, shapeCategory); CarrierReaderFromCSV.createNewCarrierAndAddVehicleTypes(scenario, allNewCarrierInformation, freightCarriersConfigGroup, - polygonsInShape, 1, null); + indexShape, 1, null); Assertions.assertEquals(3, CarriersUtils.getCarriers(scenario).getCarriers().size()); Assertions.assertTrue( CarriersUtils.getCarriers(scenario).getCarriers().containsKey(Id.create("testCarrier1", Carrier.class))); @@ -146,9 +139,9 @@ void carrierCreation() throws IOException { if (!depot.equals("j(2,6)R")) { Link link = network.getLinks().get(Id.createLinkId(depot)); Assertions.assertTrue( - FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, null, null)); - Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, new String[]{"area1"}, null)); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, new String[]{"area2"}, null)); + FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, new String[]{"area1"}, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, new String[]{"area2"}, null)); } } diff --git a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java index da396bb7a9e..c9133b6b56b 100644 --- a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java +++ b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java @@ -51,7 +51,7 @@ void testLinkForPerson() throws IOException { FreightDemandGenerationUtils.preparePopulation(population, 1.0, 1.0, "changeNumberOfLocationsWithDemand"); HashMap, HashMap> nearestLinkPerPerson = new HashMap<>(); for (Person person : population.getPersons().values()) { - DemandReaderFromCSV.findLinksForPersons(scenario, nearestLinkPerPerson, person); + DemandReaderFromCSV.findLinksForPerson(scenario, nearestLinkPerPerson, person); } Assertions.assertEquals("j(1,8)",nearestLinkPerPerson.get(Id.createPersonId("person1")).values().iterator().next()); Assertions.assertEquals("j(3,3)",nearestLinkPerPerson.get(Id.createPersonId("person2")).values().iterator().next()); @@ -78,9 +78,10 @@ void demandCreation() throws IOException { freightCarriersConfigGroup.setCarriersVehicleTypesFile(utils.getPackageInputDirectory() + "testVehicleTypes.xml"); Path carrierCSVLocation = Path.of(utils.getPackageInputDirectory() + "testCarrierCSV.csv"); Path demandCSVLocation = Path.of(utils.getPackageInputDirectory() + "testDemandCSV.csv"); - String shapeCategory = "Ortsteil"; Path shapeFilePath = Path.of(utils.getPackageInputDirectory() + "testShape/testShape.shp"); ShpOptions shp = new ShpOptions(shapeFilePath, "WGS84", null); + String shapeCategory = "Ortsteil"; + ShpOptions.Index indexShape = shp.createIndex("Ortsteil"); Collection polygonsInShape = shp.readFeatures(); String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml"; Population population = PopulationUtils.readPopulation(populationLocation); @@ -90,10 +91,10 @@ void demandCreation() throws IOException { Set allNewCarrierInformation = CarrierReaderFromCSV .readCarrierInformation(carrierCSVLocation); CarrierReaderFromCSV.createNewCarrierAndAddVehicleTypes(scenario, allNewCarrierInformation, freightCarriersConfigGroup, - polygonsInShape, 1, null); + indexShape, 1, null); Set demandInformation = DemandReaderFromCSV.readDemandInformation(demandCSVLocation); - DemandReaderFromCSV.checkNewDemand(scenario, demandInformation, polygonsInShape, shapeCategory); - DemandReaderFromCSV.createDemandForCarriers(scenario, polygonsInShape, demandInformation, population, false, + DemandReaderFromCSV.checkNewDemand(scenario, demandInformation, indexShape, shapeCategory); + DemandReaderFromCSV.createDemandForCarriers(scenario, indexShape, demandInformation, population, false, null); Assertions.assertEquals(3, CarriersUtils.getCarriers(scenario).getCarriers().size()); Assertions.assertTrue( @@ -142,10 +143,10 @@ void demandCreation() throws IOException { for (String locationsOfServiceElement : locationsPerServiceElement.get("serviceElement1")) { Link link = network.getLinks().get(Id.createLinkId(locationsOfServiceElement)); Assertions.assertTrue( - FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, null, null)); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, + FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, new String[] { "area1" }, null)); - Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, new String[] { "area2" }, null)); } Assertions.assertEquals(4, locationsPerServiceElement.get("serviceElement2").size()); @@ -230,10 +231,10 @@ void demandCreation() throws IOException { for (String locationsOfShipmentElement : locationsPerShipmentElement.get("ShipmenElement1_delivery")) { Link link = network.getLinks().get(Id.createLinkId(locationsOfShipmentElement)); Assertions.assertTrue( - FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, null, null)); - Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, + FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, new String[] { "area1" }, null)); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, new String[] { "area2" }, null)); } } diff --git a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtilsTest.java b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtilsTest.java index e1528caf871..4015178449d 100644 --- a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtilsTest.java +++ b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtilsTest.java @@ -1,12 +1,8 @@ package org.matsim.freightDemandGeneration; -import java.nio.file.Path; -import java.util.Collection; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import org.locationtech.jts.geom.Point; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; @@ -16,10 +12,10 @@ import org.matsim.application.options.ShpOptions; import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PopulationUtils; -import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.testcases.MatsimTestUtils; -import org.opengis.feature.simple.SimpleFeature; - + +import java.nio.file.Path; + /** * @author Ricardo Ewert * @@ -27,9 +23,9 @@ public class FreightDemandGenerationUtilsTest { @RegisterExtension - private MatsimTestUtils utils = new MatsimTestUtils(); - - @Test + private MatsimTestUtils utils = new MatsimTestUtils(); + + @Test void testPreparePopulation() { String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml"; Population population = PopulationUtils.readPopulation(populationLocation); @@ -78,9 +74,9 @@ void testPreparePopulation() { Assertions.assertEquals(5200.0,person.getAttributes().getAttribute("homeY")); Assertions.assertEquals(0, person.getPlans().size()); Assertions.assertNull(person.getSelectedPlan()); - } - - @Test + } + + @Test void testCoordOfMiddlePointOfLink() { Network network = NetworkUtils.readNetwork("https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"); Link link = network.getLinks().get(Id.createLinkId("i(8,8)")); @@ -91,9 +87,9 @@ void testCoordOfMiddlePointOfLink() { Coord middlePoint2 = FreightDemandGenerationUtils.getCoordOfMiddlePointOfLink(link2); Assertions.assertEquals(5000, middlePoint2.getX(), MatsimTestUtils.EPSILON); Assertions.assertEquals(7500, middlePoint2.getY(), MatsimTestUtils.EPSILON); - } - - @Test + } + + @Test void testReducePopulationToShapeArea() { String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml"; Population population = PopulationUtils.readPopulation(populationLocation); @@ -105,38 +101,38 @@ void testReducePopulationToShapeArea() { Assertions.assertEquals(6, population.getPersons().size()); Assertions.assertFalse(population.getPersons().containsKey(Id.createPersonId("person2"))); Assertions.assertFalse(population.getPersons().containsKey(Id.createPersonId("person4"))); - } - - @Test + } + + @Test void testCheckPositionInShape_link() { Network network = NetworkUtils.readNetwork("https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"); Link link = network.getLinks().get(Id.createLinkId("i(8,8)")); Path shapeFilePath = Path.of(utils.getPackageInputDirectory() + "testShape/testShape.shp"); ShpOptions shp = new ShpOptions(shapeFilePath,"WGS84", null); - Collection polygonsInShape = shp.readFeatures(); - Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, null, null)); - Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, new String[]{"area1"}, null)); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, new String[]{"area2"}, null)); + ShpOptions.Index indexShape = shp.createIndex("Ortsteil"); + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, new String[]{"area1"}, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, new String[]{"area2"}, null)); link = network.getLinks().get(Id.createLinkId("i(6,3)R")); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, null, null)); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, new String[]{"area1"}, null)); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, polygonsInShape, new String[]{"area2"}, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, new String[]{"area1"}, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, new String[]{"area2"}, null)); + + } - } - - @Test + @Test void testCheckPositionInShape_point() { Path shapeFilePath = Path.of(utils.getPackageInputDirectory() + "testShape/testShape.shp"); ShpOptions shp = new ShpOptions(shapeFilePath,"WGS84", null); - Collection polygonsInShape = shp.readFeatures(); - Point point = MGC.xy2Point(6000, 6000); - Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(null, point, polygonsInShape, null, null)); - Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(null, point, polygonsInShape, new String[]{"area1"}, null)); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(null, point, polygonsInShape, new String[]{"area2"}, null)); - point = MGC.xy2Point(2000, 2000); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(null, point, polygonsInShape, null, null)); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(null, point, polygonsInShape, new String[]{"area1"}, null)); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(null, point, polygonsInShape, new String[]{"area2"}, null)); + ShpOptions.Index indexShape = shp.createIndex("Ortsteil"); + Coord coord = new Coord(6000, 6000); + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(null, coord, indexShape, null, null)); + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(null, coord, indexShape, new String[]{"area1"}, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(null, coord, indexShape, new String[]{"area2"}, null)); + coord = new Coord(2000, 2000); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(null, coord, indexShape, null, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(null, coord, indexShape, new String[]{"area1"}, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(null, coord, indexShape, new String[]{"area2"}, null)); } } diff --git a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java b/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java deleted file mode 100644 index 62127e7e2f5..00000000000 --- a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* *********************************************************************** * - * project: org.matsim.* - * Controler.java - * * - * *********************************************************************** * - * * - * copyright : (C) 2007 by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** */ -package org.matsim.smallScaleCommercialTrafficGeneration; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.matsim.api.core.v01.Scenario; -import org.matsim.api.core.v01.population.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.population.PopulationUtils; -import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.testcases.MatsimTestUtils; - -import java.io.File; -import java.util.Objects; - -/** - * @author Ricardo Ewert - * - */ -public class RunGenerateSmallScaleCommercialTrafficTest { - - @RegisterExtension - private MatsimTestUtils utils = new MatsimTestUtils(); - - @Test - void testMainRunAndResults() { - String inputDataDirectory = utils.getPackageInputDirectory() + "config_demand.xml"; - String output = utils.getOutputDirectory(); - String sample = "0.1"; - String jspritIterations = "2"; - String creationOption = "createNewCarrierFile"; - String landuseConfiguration = "useExistingDataDistribution"; - String smallScaleCommercialTrafficType = "commercialPersonTraffic"; - String zoneShapeFileName = utils.getPackageInputDirectory() + "/shp/testZones.shp"; - String buildingsShapeFileName = utils.getPackageInputDirectory() + "/shp/testBuildings.shp"; - String landuseShapeFileName = utils.getPackageInputDirectory() + "/shp/testLanduse.shp"; - String shapeCRS = "EPSG:4326"; - - new GenerateSmallScaleCommercialTrafficDemand().execute( - inputDataDirectory, - "--sample", sample, - "--jspritIterations", jspritIterations, - "--creationOption", creationOption, - "--landuseConfiguration", landuseConfiguration, - "--smallScaleCommercialTrafficType", smallScaleCommercialTrafficType, - "--includeExistingModels", - "--zoneShapeFileName", zoneShapeFileName, - "--buildingsShapeFileName", buildingsShapeFileName, - "--landuseShapeFileName", landuseShapeFileName, - "--shapeCRS", shapeCRS); - - // 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; - 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.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")); - Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("vehicles")); - Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("subpopulation")); - Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("purpose")); - } - - Assertions.assertEquals(CarriersUtils.addOrGetCarriers(scenarioWSolution).getCarriers().size(), - CarriersUtils.addOrGetCarriers(scenarioWOSolution).getCarriers().size(), 0); - int countedTours = 0; - for (Carrier carrier_withSolution : CarriersUtils.addOrGetCarriers(scenarioWSolution).getCarriers().values()) { - countedTours += carrier_withSolution.getSelectedPlan().getScheduledTours().size(); - } - Assertions.assertEquals(population.getPersons().size(), countedTours, 0); - } -} 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/multiLevel.yml b/contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/multiLevel.yml new file mode 100644 index 00000000000..f1d3c105534 --- /dev/null +++ b/contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/multiLevel.yml @@ -0,0 +1,11 @@ + +test: + values: [1,2,3] + params: + - mode: car + subpopulation: person + values: ["-1", "-2"] + - mode: bike + subpopulation: person + values: [3, 4] + extra: "extra" \ No newline at end of file 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 diff --git a/contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/standard.yml b/contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/standard.yml new file mode 100644 index 00000000000..dc25f14bdf3 --- /dev/null +++ b/contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/standard.yml @@ -0,0 +1,14 @@ +controler: + runId: 567 + +global: + numberOfThreads: 8 + +planCalcScore: + + scoringParameters: + - modeParams: + - mode: car + constant: -1 + - mode: bike + constant: -2 \ No newline at end of file diff --git a/contribs/application/test/input/org/matsim/application/prepare/network/params/osm.net.xml b/contribs/application/test/input/org/matsim/application/prepare/network/params/osm.net.xml new file mode 100644 index 00000000000..021ff2e24cb --- /dev/null +++ b/contribs/application/test/input/org/matsim/application/prepare/network/params/osm.net.xml @@ -0,0 +1,1759 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/config_demand.xml b/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/config_demand.xml deleted file mode 100644 index bc64ce1501a..00000000000 --- a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/config_demand.xml +++ /dev/null @@ -1,552 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/dataDistributionPerZone.csv b/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/dataDistributionPerZone.csv deleted file mode 100644 index 70857ece6c1..00000000000 --- a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/dataDistributionPerZone.csv +++ /dev/null @@ -1,4 +0,0 @@ -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/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/investigationAreaData.csv b/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/investigationAreaData.csv deleted file mode 100644 index e8dd1cb57ff..00000000000 --- a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/investigationAreaData.csv +++ /dev/null @@ -1,3 +0,0 @@ -Area Inhabitants Employee Employee Primary Sector Employee Construction Employee Secondary Sector Rest Employee Retail Employee Traffic/Parcels Employee Tertiary Sector Rest -testArea1 8000 10000 500 2000 1000 1500 2000 3000 -testArea2 800 1000 50 200 100 150 200 300 \ No newline at end of file diff --git a/contribs/bicycle/src/test/java/org/matsim/contrib/bicycle/run/BicycleTest.java b/contribs/bicycle/src/test/java/org/matsim/contrib/bicycle/run/BicycleTest.java index 961e43f0182..222834c746b 100644 --- a/contribs/bicycle/src/test/java/org/matsim/contrib/bicycle/run/BicycleTest.java +++ b/contribs/bicycle/src/test/java/org/matsim/contrib/bicycle/run/BicycleTest.java @@ -65,7 +65,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.matsim.utils.eventsfilecomparison.EventsFileComparator.Result.FILES_ARE_EQUAL; +import static org.matsim.utils.eventsfilecomparison.ComparisonResult.FILES_ARE_EQUAL; /** * @author dziemke diff --git a/contribs/common/pom.xml b/contribs/common/pom.xml index 05952b173e1..106a9e01e46 100644 --- a/contribs/common/pom.xml +++ b/contribs/common/pom.xml @@ -18,5 +18,15 @@ org.assertj assertj-core + + one.util + streamex + 0.8.2 + + + com.uber + h3 + 4.1.1 + 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; diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/Zone.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/Zone.java new file mode 100644 index 00000000000..dbf0c77caf8 --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/Zone.java @@ -0,0 +1,19 @@ +package org.matsim.contrib.common.zones; + +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.matsim.api.core.v01.BasicLocation; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Identifiable; +import org.matsim.api.core.v01.network.Link; + +import javax.annotation.Nullable; +import java.util.List; + +public interface Zone extends BasicLocation, Identifiable { + @Nullable + PreparedGeometry getPreparedGeometry(); + + Coord getCentroid(); + + List getLinks(); +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneImpl.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneImpl.java new file mode 100644 index 00000000000..64b4a009733 --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneImpl.java @@ -0,0 +1,65 @@ +package org.matsim.contrib.common.zones; + +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.geometry.geotools.MGC; + +import javax.annotation.Nullable; +import java.util.List; + +public class ZoneImpl implements Zone { + + private final Id id; + @Nullable + private final PreparedGeometry preparedGeometry; //null for virtual/dummy zones + private final List links; + private final Coord centroid; + + public ZoneImpl(Id id, PreparedGeometry preparedGeometry, List links) { + this(id, preparedGeometry, links, MGC.point2Coord(preparedGeometry.getGeometry().getCentroid())); + } + + private ZoneImpl(Id id, @Nullable PreparedGeometry preparedGeometry, List links, Coord centroid) { + this.id = id; + this.preparedGeometry = preparedGeometry; + this.links = links; + this.centroid = centroid; + } + + @Override + public Id getId() { + return id; + } + + @Override + public Coord getCoord() { + return centroid; + } + + @Override + @Nullable + public PreparedGeometry getPreparedGeometry() { + return preparedGeometry; + } + + @Override + public Coord getCentroid() { + return centroid; + } + + @Override + public List getLinks() { + return links; + } + + boolean isDummy() { + return preparedGeometry == null; + } + + public static ZoneImpl createDummyZone(Id id, List links, Coord centroid) { + return new ZoneImpl(id, null, links, centroid); + } + +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystem.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystem.java new file mode 100644 index 00000000000..11299b67ad6 --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystem.java @@ -0,0 +1,14 @@ +package org.matsim.contrib.common.zones; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; + +import javax.annotation.Nullable; +import java.util.Map; + +public interface ZoneSystem { + @Nullable + Zone getZoneForLinkId(Id linkId); + + Map, Zone> getZones(); +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemImpl.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemImpl.java new file mode 100644 index 00000000000..958575ecf40 --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemImpl.java @@ -0,0 +1,43 @@ +package org.matsim.contrib.common.zones; + +import org.apache.commons.lang3.tuple.Pair; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdMap; +import org.matsim.api.core.v01.network.Link; + +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +public class ZoneSystemImpl implements ZoneSystem { + + private final Map, Zone> zones = new IdMap<>(Zone.class); + private final IdMap link2zone = new IdMap<>(Link.class); + + public ZoneSystemImpl(Collection zones) { + zones.forEach(zone -> this.zones.put(zone.getId(), zone)); + zones.stream() + .flatMap(zone -> zone.getLinks().stream().map(link -> Pair.of(link.getId(), zone))) + .forEach(idZonePair -> link2zone.put(idZonePair.getKey(), idZonePair.getValue())); + } + + /** + * @param linkId + * @return the the {@code DrtZone} that contains the {@code linkId}. If the given link's {@code Coord} borders two or more cells, the allocation to a cell is random. + * Result may be null in case the given link is outside of the service area. + */ + @Override + @Nullable + public Zone getZoneForLinkId(Id linkId) { + return link2zone.get(linkId); + } + + /** + * @return the zones + */ + @Override + public Map, Zone> getZones() { + return Collections.unmodifiableMap(zones); + } +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemUtils.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemUtils.java new file mode 100644 index 00000000000..d1e3e6f2094 --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemUtils.java @@ -0,0 +1,64 @@ +package org.matsim.contrib.common.zones; + +import one.util.streamex.EntryStream; +import one.util.streamex.StreamEx; +import org.locationtech.jts.geom.Point; +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.utils.geometry.geotools.MGC; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static java.util.stream.Collectors.toList; + +public final class ZoneSystemUtils { + + + private ZoneSystemUtils() {} + + public static ZoneSystem createFromPreparedGeometries(Network network, Map geometries) { + + //geometries without links are skipped + Map> linksByGeometryId = StreamEx.of(network.getLinks().values()) + .mapToEntry(l -> getGeometryIdForLink(l, geometries), l -> l) + .filterKeys(Objects::nonNull) + .grouping(toList()); + + //the zonal system contains only zones that have at least one link + List zones = EntryStream.of(linksByGeometryId) + .mapKeyValue((id, links) -> new ZoneImpl(Id.create(id, Zone.class), geometries.get(id), links)) + .collect(toList()); + + return new ZoneSystemImpl(zones); + } + + /** + * @param link + * @return the the {@code PreparedGeometry} that contains the {@code linkId}. + * If a given link's {@code Coord} borders two or more cells, the allocation to a cell is random. + * Result may be null in case the given link is outside of the service area. + */ + @Nullable + private static String getGeometryIdForLink(Link link, Map geometries) { + Point linkCoord = MGC.coord2Point(link.getToNode().getCoord()); + return geometries.entrySet() + .stream() + .filter(e -> e.getValue().intersects(linkCoord)) + .findAny() + .map(Map.Entry::getKey) + .orElse(null); + } + + public static Id createZoneId(String id) { + return Id.create(id, Zone.class); + } + + public static Id createZoneId(long id) { + return Id.create(id, Zone.class); + } +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3GridUtils.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3GridUtils.java new file mode 100644 index 00000000000..9139e56442b --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3GridUtils.java @@ -0,0 +1,112 @@ +package org.matsim.contrib.common.zones.h3; + +import com.uber.h3core.AreaUnit; +import com.uber.h3core.H3Core; +import com.uber.h3core.LengthUnit; +import com.uber.h3core.util.LatLng; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Polygon; +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.locationtech.jts.geom.prep.PreparedGeometryFactory; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.geometry.CoordinateTransformation; +import org.matsim.core.utils.geometry.transformations.TransformationFactory; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author nkuehnel / MOIA + */ +public class H3GridUtils { + + static final Logger log = LogManager.getLogger(H3GridUtils.class); + + public static Map createH3GridFromNetwork(Network network, int resolution, String crs) { + + H3Core h3 = H3Utils.getInstance(); + + log.info("start creating H3 grid from network at resolution " + resolution); + double hexagonEdgeLengthAvg = h3.getHexagonEdgeLengthAvg(resolution, LengthUnit.m); + log.info("Average edge length: " + hexagonEdgeLengthAvg + " meters."); + log.info("Average centroid distance: " + hexagonEdgeLengthAvg * Math.sqrt(3) + " meters."); + log.info("Average hexagon area: " + h3.getHexagonAreaAvg(resolution, AreaUnit.m2) + " m^2"); + + double[] boundingbox = NetworkUtils.getBoundingBox(network.getNodes().values()); + double minX = boundingbox[0]; + double maxX = boundingbox[2]; + double minY = boundingbox[1]; + double maxY = boundingbox[3]; + + GeometryFactory gf = new GeometryFactory(); + PreparedGeometryFactory preparedGeometryFactory = new PreparedGeometryFactory(); + Map grid = new HashMap<>(); + CoordinateTransformation toLatLong = TransformationFactory.getCoordinateTransformation(crs, TransformationFactory.WGS84); + CoordinateTransformation fromLatLong = TransformationFactory.getCoordinateTransformation(TransformationFactory.WGS84, crs); + + List boundingBoxPoints = new ArrayList<>(); + + Coord bottomLeft = toLatLong.transform(new Coord(minX, minY)); + Coord topLeft = toLatLong.transform(new Coord(minX, maxY)); + Coord topRight = toLatLong.transform(new Coord(maxX, maxY)); + Coord bottomRight = toLatLong.transform(new Coord(maxX, minY)); + + boundingBoxPoints.add(coordToLatLng(bottomLeft)); + boundingBoxPoints.add(coordToLatLng(topLeft)); + boundingBoxPoints.add(coordToLatLng(topRight)); + boundingBoxPoints.add(coordToLatLng(bottomRight)); + boundingBoxPoints.add(coordToLatLng(bottomLeft)); + + long millis = System.currentTimeMillis(); + + //get cells in a finer resolution to catch links at the border + List h3Grid = h3.polygonToCellAddresses(boundingBoxPoints, Collections.emptyList(), Math.min(H3Utils.MAX_RES, resolution)); + h3Grid = h3Grid + .parallelStream() + //also include neighbors with distance 1 + .flatMap(h3Id -> h3.gridDisk(h3Id, 1).stream()) + .distinct() + .toList(); + + if(h3Grid.isEmpty()) { + // bounding box too small to cover even a single H3 cell for a significant part. Use bounding box coords directly. + h3Grid = boundingBoxPoints.stream().map(corner -> h3.latLngToCellAddress(corner.lat, corner.lng, resolution)).distinct().toList(); + } + + log.info("Obtained " + h3Grid.size() + " H3 cells in " + (System.currentTimeMillis() - millis) + " ms."); + + + for (String h3Id : h3Grid) { + List coordinateList = h3.cellToBoundary(h3Id) + .stream() + .map(latLng -> CoordUtils.createGeotoolsCoordinate(fromLatLong.transform(latLngToCoord(latLng)))) + .collect(Collectors.toList()); + + if (!coordinateList.isEmpty()) { + coordinateList.add(coordinateList.get(0)); + } + + Polygon polygon = new Polygon(gf.createLinearRing(coordinateList.toArray(new Coordinate[0])), null, gf); + grid.put(h3Id, preparedGeometryFactory.create(polygon)); + } + + log.info("finished creating H3 grid from network."); + return grid; + } + + public static LatLng coordToLatLng(Coord coord) { + //invert coordinate order + return new LatLng(coord.getY(), coord.getX()); + } + + public static Coord latLngToCoord(LatLng latLng) { + //invert coordinate order + return new Coord(latLng.lng, latLng.lat); + } +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3Utils.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3Utils.java new file mode 100644 index 00000000000..3bc44478ebf --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3Utils.java @@ -0,0 +1,27 @@ +package org.matsim.contrib.common.zones.h3; + +import com.uber.h3core.H3Core; + +import java.io.IOException; + +/** + * @author nkuehnel / MOIA + */ +public final class H3Utils { + + private static H3Core h3; + + public final static int MAX_RES = 16; + + + public static H3Core getInstance() { + if(h3 == null) { + try { + h3 = H3Core.newInstance(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return h3; + } +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java new file mode 100644 index 00000000000..f496d62cc5d --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java @@ -0,0 +1,77 @@ +package org.matsim.contrib.common.zones.h3; + +import com.uber.h3core.H3Core; +import com.uber.h3core.util.LatLng; +import one.util.streamex.EntryStream; +import one.util.streamex.StreamEx; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneImpl; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.ZoneSystemImpl; +import org.matsim.core.utils.geometry.CoordinateTransformation; +import org.matsim.core.utils.geometry.transformations.TransformationFactory; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static java.util.stream.Collectors.toList; + +/** + * @author nkuehnel / MOIA + */ +public class H3ZoneSystemUtils { + + static final Logger log = LogManager.getLogger(H3ZoneSystemUtils.class); + + + public static ZoneSystem createFromPreparedGeometries(Network network, Map geometries, + String crs, int resolution) { + + //geometries without links are skipped + CoordinateTransformation ct = TransformationFactory.getCoordinateTransformation(crs, TransformationFactory.WGS84); + Map> linksByGeometryId = StreamEx.of(network.getLinks().values()) + .mapToEntry(l -> getGeometryIdForLink(l, geometries, resolution, ct), l -> l) + .filterKeys(Objects::nonNull) + .grouping(toList()); + + log.info("Network filtered zone system contains " + linksByGeometryId.size() + " zones for " + + network.getLinks().size() + " links and " + network.getNodes().size() + " nodes."); + + //the zonal system contains only zones that have at least one link + List zones = EntryStream.of(linksByGeometryId) + .mapKeyValue((id, links) -> new ZoneImpl(Id.create(id, Zone.class), geometries.get(id), links) { + }) + .collect(toList()); + + return new ZoneSystemImpl(zones); + } + + /** + * @param ct + * @param link + * @return the the {@code PreparedGeometry} that contains the {@code linkId}. + * If a given link's {@code Coord} borders two or more cells, the allocation to a cell is random. + * Result may be null in case the given link is outside of the service area. + *

+ * Careful: does not work if grid contains different levels of h3 resolutions. + */ + @Nullable + private static String getGeometryIdForLink(Link link, Map geometries, int resolution, CoordinateTransformation ct) { + H3Core h3 = H3Utils.getInstance(); + LatLng latLng = H3GridUtils.coordToLatLng(ct.transform(link.getToNode().getCoord())); + String s = h3.latLngToCellAddress(latLng.lat, latLng.lng, resolution); + if (geometries.containsKey(s)) { + return s; + } else { + return null; + } + } +} diff --git a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/constraints/TransitWalkConstraint.java b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/constraints/TransitWalkConstraint.java index 7bfd6d0b61b..5c63102b7a9 100644 --- a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/constraints/TransitWalkConstraint.java +++ b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/constraints/TransitWalkConstraint.java @@ -13,6 +13,7 @@ import org.matsim.contribs.discrete_mode_choice.model.trip_based.TripConstraintFactory; import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.RoutedTripCandidate; import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; +import org.matsim.pt.routes.TransitPassengerRoute; /** * This contraint forbids "pt" trips that only consist of walk legs, i.e. there @@ -29,7 +30,7 @@ public boolean validateAfterEstimation(DiscreteModeChoiceTrip trip, TripCandidat // Go through all plan elments for (PlanElement element : ((RoutedTripCandidate) candidate).getRoutedPlanElements()) { if (element instanceof Leg) { - if (((Leg) element).getMode().equals(TransportMode.pt)) { + if (((Leg) element).getRoute() instanceof TransitPassengerRoute) { // If we find at least one pt leg, we're good return true; } diff --git a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/NullWaitingTimeEstimator.java b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/NullWaitingTimeEstimator.java index 445451713ca..e003a9f09e9 100644 --- a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/NullWaitingTimeEstimator.java +++ b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/NullWaitingTimeEstimator.java @@ -1,5 +1,8 @@ package org.matsim.contribs.discrete_mode_choice.components.utils; +import java.util.List; + +import org.matsim.api.core.v01.population.PlanElement; import org.matsim.pt.routes.TransitPassengerRoute; /** @@ -9,8 +12,15 @@ * @author sebhoerl */ public class NullWaitingTimeEstimator implements PTWaitingTimeEstimator { + @Override public double estimateWaitingTime(double agentDepartureTime, TransitPassengerRoute route) { return 0.0; } + + @Override + public double estimateWaitingTime(List elements) { + return 0.0; + } + } diff --git a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/PTWaitingTimeEstimator.java b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/PTWaitingTimeEstimator.java index 2b4da256f0b..25804cddb95 100644 --- a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/PTWaitingTimeEstimator.java +++ b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/PTWaitingTimeEstimator.java @@ -1,5 +1,8 @@ package org.matsim.contribs.discrete_mode_choice.components.utils; +import java.util.List; + +import org.matsim.api.core.v01.population.PlanElement; import org.matsim.pt.routes.TransitPassengerRoute; /** @@ -11,5 +14,9 @@ * @author sebhoerl */ public interface PTWaitingTimeEstimator { + double estimateWaitingTime(double departureTime, TransitPassengerRoute route); + + double estimateWaitingTime(List elements); + } diff --git a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/ScheduleWaitingTimeEstimator.java b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/ScheduleWaitingTimeEstimator.java index 2ab5bfe10ca..6fc60d7ad73 100644 --- a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/ScheduleWaitingTimeEstimator.java +++ b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/ScheduleWaitingTimeEstimator.java @@ -8,6 +8,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.PlanElement; import org.matsim.core.utils.collections.Tuple; @@ -54,17 +55,14 @@ private Tuple, Id> createId(TransitLine transitLin return new Tuple<>(transitLine.getId(), transitRoute.getId()); } + @Override public double estimateWaitingTime(List elements) { double totalWaitingTime = 0.0; for (PlanElement element : elements) { - if (element instanceof Leg) { - Leg leg = (Leg) element; - - if (leg.getMode().equals("pt")) { - TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); - totalWaitingTime += estimateWaitingTime(leg.getDepartureTime().seconds(), route); - } + if (element instanceof Leg leg && leg.getMode().equals(TransportMode.pt)) { + TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); + totalWaitingTime += this.estimateWaitingTime(leg.getDepartureTime().seconds(), route); } } diff --git a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/model/tour_based/TourBasedModel.java b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/model/tour_based/TourBasedModel.java index 962ce8a6ee3..295e71e94c4 100644 --- a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/model/tour_based/TourBasedModel.java +++ b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/model/tour_based/TourBasedModel.java @@ -93,7 +93,7 @@ public List chooseModes(Person person, List chooseModes(Person person, List16.0-SNAPSHOT test - + org.mockito mockito-core diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java index 90eddf50abf..34ce02553dc 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java @@ -30,8 +30,8 @@ import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.CoordinateTransformation; import org.matsim.core.utils.geometry.transformations.TransformationFactory; -import org.matsim.core.utils.gis.ShapeFileReader; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileReader; +import org.matsim.core.utils.gis.GeoFileWriter; import org.matsim.pt.transitSchedule.api.TransitScheduleReader; import org.matsim.pt.transitSchedule.api.TransitStopFacility; import org.opengis.feature.simple.SimpleFeature; @@ -207,9 +207,9 @@ public Integer call() throws Exception { if (areaFile != null) { // create copy of shp file so that it is accessible for sim wrapper - Collection allFeatures = ShapeFileReader.getAllFeatures(areaFile); + Collection allFeatures = GeoFileReader.getAllFeatures(areaFile); //do not convert coordinates! all MATSim output should be in the same CRS. if input was not in correct CRS, simulation would have crashed... - ShapeFileWriter.writeGeometries(allFeatures, output.getPath("serviceArea.shp").toString()); + GeoFileWriter.writeGeometries(allFeatures, output.getPath("serviceArea.shp").toString()); //needs to be a DoubleColumn because transposing later forces us to have the same column type for all (new) value columns tableSupplyKPI.addColumns(DoubleColumn.create("Number of areas", new Integer[]{allFeatures.size()})); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java index 71ee5abe1c1..b617a93a0d3 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java @@ -44,6 +44,7 @@ import org.matsim.contrib.drt.optimizer.insertion.UnplannedRequestInserter; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; +import org.matsim.contrib.drt.passenger.DefaultOfferAcceptor; import org.matsim.contrib.drt.prebooking.PrebookingActionCreator; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.schedule.DrtTaskFactory; @@ -178,7 +179,8 @@ public EmptyVehicleRelocator get() { getter.getModal(StopTimeCalculator.class), scheduleWaitBeforeDrive))) .asEagerSingleton(); - bindModal(DrtOfferAcceptor.class).toInstance(DrtOfferAcceptor.DEFAULT_ACCEPTOR); + bindModal(DefaultOfferAcceptor.class).toProvider(modalProvider(getter -> new DefaultOfferAcceptor(drtCfg.maxAllowedPickupDelay))); + bindModal(DrtOfferAcceptor.class).to(modalKey(DefaultOfferAcceptor.class)); bindModal(ScheduleTimingUpdater.class).toProvider(modalProvider( getter -> new ScheduleTimingUpdater(getter.get(MobsimTimer.class), @@ -187,11 +189,11 @@ public EmptyVehicleRelocator get() { bindModal(VrpLegFactory.class).toProvider(modalProvider(getter -> { DvrpConfigGroup dvrpCfg = getter.get(DvrpConfigGroup.class); MobsimTimer timer = getter.get(MobsimTimer.class); - + // Makes basic DrtActionCreator create legs with consumption tracker return v -> EDrtActionCreator.createLeg(dvrpCfg.mobsimMode, v, timer); })).in(Singleton.class); - + bindModal(EDrtActionCreator.class).toProvider(modalProvider(getter -> { VrpAgentLogic.DynActionCreator delegate = drtCfg.getPrebookingParams().isPresent() ? getter.getModal(PrebookingActionCreator.class) @@ -201,9 +203,9 @@ public EmptyVehicleRelocator get() { // + adds ChargingActivity return new EDrtActionCreator(delegate, getter.get(MobsimTimer.class)); })).asEagerSingleton(); - + bindModal(VrpAgentLogic.DynActionCreator.class).to(modalKey(EDrtActionCreator.class)); - + bindModal(VrpOptimizer.class).to(modalKey(DrtOptimizer.class)); } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimator.java index db6168ac2e1..3481b7ec7a2 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimator.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimator.java @@ -20,7 +20,7 @@ /** * Aggregate class for informed-mode-choice that makes sure to invoke the correct estimator for each drt mode. */ -public class MultiModalDrtLegEstimator implements LegEstimator { +public class MultiModalDrtLegEstimator implements LegEstimator { private static final Logger log = LogManager.getLogger(MultiModalDrtLegEstimator.class); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/fiss/FISS.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/fiss/FISS.java index 58705f89cb3..6ce932ecebc 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/fiss/FISS.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/fiss/FISS.java @@ -15,6 +15,7 @@ import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; import org.matsim.contrib.dynagent.DynAgent; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.controler.MatsimServices; @@ -94,13 +95,16 @@ public boolean handleDeparture(double now, MobsimAgent agent, Id linkId) { Leg currentLeg = (Leg) planAgent.getCurrentPlanElement(); Gbl.assertIf(this.fissConfigGroup.sampledModes.contains(currentLeg.getMode())); NetworkRoute networkRoute = (NetworkRoute) currentLeg.getRoute(); + Person person = planAgent.getCurrentPlan().getPerson(); + Vehicle vehicle = this.matsimServices.getScenario().getVehicles().getVehicles() + .get(networkRoute.getVehicleId()); // update travel time with travel times of last iteration double newTravelTime = 0.0; - // start and end link are not consideres in NetworkRoutingModule for travel time + // start and end link are not considered in NetworkRoutingModule for travel time for (Id routeLinkId : networkRoute.getLinkIds()) { newTravelTime += this.travelTime.getLinkTravelTime(network.getLinks().get(routeLinkId), - now + newTravelTime, null, null); + now + newTravelTime, person, vehicle); } LOG.debug("New travelTime: {}, was {}", newTravelTime, networkRoute.getTravelTime().orElseGet(() -> Double.NaN)); @@ -108,8 +112,8 @@ public boolean handleDeparture(double now, MobsimAgent agent, Id linkId) { } // remove vehicle of teleported agent from parking spot QVehicle removedVehicle = null; - if (agent instanceof MobsimDriverAgent) { - Id vehicleId = ((MobsimDriverAgent) agent).getPlannedVehicleId(); + if (agent instanceof MobsimDriverAgent driverAgent) { + Id vehicleId = driverAgent.getPlannedVehicleId(); QVehicle vehicle = qNetsimEngine.getVehicles().get(vehicleId); QLinkI qLinkI = (QLinkI) this.qNetsimEngine.getNetsimNetwork().getNetsimLink(linkId); removedVehicle = qLinkI.removeParkedVehicle(vehicleId); diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/companions/RunDrtWithCompanionExampleIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/companions/RunDrtWithCompanionExampleIT.java index 4a7cb879f50..8a6b6e4098c 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/companions/RunDrtWithCompanionExampleIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/companions/RunDrtWithCompanionExampleIT.java @@ -20,13 +20,6 @@ package org.matsim.contrib.drt.extension.companions; -import java.io.IOException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.List; -import java.util.stream.Collectors; - import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -44,6 +37,13 @@ import org.matsim.testcases.MatsimTestUtils; import org.matsim.vis.otfvis.OTFVisConfigGroup; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Collectors; + /** * @author Steffen Axer */ @@ -74,8 +74,9 @@ void testRunDrtWithCompanions() { Controler controler = DrtCompanionControlerCreator.createControler(config); controler.run(); - int actualRides = getTotalNumberOfDrtRides(); - Assertions.assertThat(actualRides).isEqualTo(706); + int[] actualRides = getTotalNumberOfDrtRides(); + Assertions.assertThat(actualRides[0]).isEqualTo(378); + Assertions.assertThat(actualRides[1]).isEqualTo(706); } @Test @@ -101,11 +102,12 @@ void testRunDrtWithCompanionsMultiThreaded() { Controler controler = DrtCompanionControlerCreator.createControler(config); controler.run(); - int actualRides = getTotalNumberOfDrtRides(); - Assertions.assertThat(actualRides).isEqualTo(699); + int[] actualRides = getTotalNumberOfDrtRides(); + Assertions.assertThat(actualRides[0]).isEqualTo(375); + Assertions.assertThat(actualRides[1]).isEqualTo(699); } - private int getTotalNumberOfDrtRides() { + private int[] getTotalNumberOfDrtRides() { String filename = utils.getOutputDirectory() + "/drt_customer_stats_drt.csv"; final List collect; @@ -119,8 +121,12 @@ private int getTotalNumberOfDrtRides() { List keys = List.of(collect.get(0).split(";")); List lastIterationValues = List.of(collect.get(size - 1).split(";")); - int index = keys.indexOf("rides"); - String value = lastIterationValues.get(index); - return Integer.parseInt(value); + int ridesRequestIndex = keys.indexOf("rides"); + int ridesRequest = Integer.parseInt(lastIterationValues.get(ridesRequestIndex)); + + int ridesPaxIndex = keys.indexOf("rides_pax"); + int ridesPax = Integer.parseInt(lastIterationValues.get(ridesPaxIndex)); + + return new int[]{ridesRequest, ridesPax}; } } diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java index 48a6c4aeeea..2ced56d6edf 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java @@ -109,10 +109,10 @@ void testWithPrebooking() { controller.run(); - assertEquals(74, tracker.immediateScheduled); - assertEquals(198, tracker.prebookedScheduled); - assertEquals(116, tracker.immediateRejected); - assertEquals(7, tracker.prebookedRejected); + assertEquals(112, tracker.immediateScheduled); + assertEquals(182, tracker.prebookedScheduled); + assertEquals(94, tracker.immediateRejected); + assertEquals(23, tracker.prebookedRejected); } static private class PassengerPickUpTracker implements PassengerPickedUpEventHandler { 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 new file mode 100644 index 00000000000..86595942ed2 --- /dev/null +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java @@ -0,0 +1,88 @@ +package org.matsim.contrib.drt.extension.h3; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.application.MATSimApplication; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; +import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystemParams; +import org.matsim.contrib.drt.analysis.zonal.DrtZonalWaitTimesAnalyzer; +import org.matsim.contrib.drt.extension.DrtTestScenario; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.testcases.MatsimTestUtils; + +import java.io.File; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author nkuehnel / MOIA + */ +public class RunDrtWithH3ZonalSystemIT { + + @RegisterExtension + private MatsimTestUtils utils = new MatsimTestUtils(); + + private Controler controler; + + @BeforeEach + public void setUp() throws Exception { + + Config config = DrtTestScenario.loadConfig(utils); + config.controller().setLastIteration(0); + + controler = MATSimApplication.prepare(new DrtTestScenario(controller -> prepare(controller, config), RunDrtWithH3ZonalSystemIT::prepare), config); + } + + private static void prepare(Controler controler, Config config) { + + MultiModeDrtConfigGroup drtConfigs = ConfigUtils.addOrGetModule(config, MultiModeDrtConfigGroup.class); + for (DrtConfigGroup drtConfig : drtConfigs.getModalElements()) { + drtConfig.getZonalSystemParams().get().h3Resolution = 9; + drtConfig.getZonalSystemParams().get().zonesGeneration = DrtZonalSystemParams.ZoneGeneration.H3; + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new AbstractDvrpModeModule(drtConfig.mode) { + @Override + public void install() { + bindModal(DrtZonalWaitTimesAnalyzer.class).toProvider(modalProvider( + getter -> new DrtZonalWaitTimesAnalyzer(drtConfig, getter.getModal(DrtEventSequenceCollector.class), + getter.getModal(ZoneSystem.class)))).asEagerSingleton(); + addControlerListenerBinding().to(modalKey(DrtZonalWaitTimesAnalyzer.class)); + } + }); + } + }); + + } + } + + private static void prepare(Config config) { + MultiModeDrtConfigGroup drtConfigs = ConfigUtils.addOrGetModule(config, MultiModeDrtConfigGroup.class); + for (DrtConfigGroup drtConfig : drtConfigs.getModalElements()) { + DrtZonalSystemParams params = drtConfig.getZonalSystemParams().orElseThrow(); + params.cellSize = 1.; + params.zonesGeneration = DrtZonalSystemParams.ZoneGeneration.GridFromNetwork; + } + } + + @Test + void run() { + String out = utils.getOutputDirectory(); + controler.run(); + + assertThat(new File(out, "kelheim-mini-drt.drt_waitStats_drt_zonal.gpkg")) + .exists() + .isNotEmpty(); + + } +} + diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/drtZone/H3DrtZonalSystemTest.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/drtZone/H3DrtZonalSystemTest.java new file mode 100644 index 00000000000..293fa254280 --- /dev/null +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/drtZone/H3DrtZonalSystemTest.java @@ -0,0 +1,173 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) 2020 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** * + */ + +package org.matsim.contrib.drt.extension.h3.drtZone; + +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.h3.H3GridUtils; +import org.matsim.contrib.common.zones.h3.H3ZoneSystemUtils; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.utils.geometry.transformations.TransformationFactory; +import org.matsim.examples.ExamplesUtils; + +import java.net.URL; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.matsim.contrib.common.zones.ZoneSystemUtils.createZoneId; + +/** + * @author nkuehnel / MOIA + */ +public class H3DrtZonalSystemTest { + + @Test + void test_Holzkirchen_Resolution3() { + Network network = getNetwork(); + String crs = TransformationFactory.DHDN_GK4; + int resolution = 3; + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("831f8dfffffffff"))).isTrue(); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("831f8dfffffffff")); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo(createZoneId("831f8dfffffffff")); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("831f89fffffffff")); + + //check all links are mapped + for (Link link : network.getLinks().values()) { + assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId())); + } + } + + @Test + void test_Holzkirchen_Resolution5() { + Network network = getNetwork(); + String crs = TransformationFactory.DHDN_GK4; + int resolution = 5; + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("851f88b7fffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("851f8d6bfffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("851f88a7fffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("851f89d3fffffff"))).isTrue(); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("851f8d6bfffffff")); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo(createZoneId("851f88b7fffffff")); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("851f89d3fffffff")); + + //check all links are mapped + for (Link link : network.getLinks().values()) { + assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId())); + } + } + + @Test + void test_Holzkirchen_Resolution6() { + Network network = getNetwork(); + String crs = TransformationFactory.DHDN_GK4; + int resolution = 6; + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f8d697ffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f8d687ffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f8d69fffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f88a6fffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f88a6fffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f89d37ffffff"))).isTrue(); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("861f8d697ffffff")); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo(createZoneId("861f88b47ffffff")); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("861f89d07ffffff")); + + //check all links are mapped + for (Link link : network.getLinks().values()) { + assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId())); + } + } + + @Test + void test_Holzkirchen_Resolution10() { + Network network = getNetwork(); + String crs = TransformationFactory.DHDN_GK4; + int resolution = 10; + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("8a1f8d6930b7fff")); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo(createZoneId("8a1f88b4025ffff")); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("8a1f89d06d5ffff")); + + //check all links are mapped + for (Link link : network.getLinks().values()) { + assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId())); + } + } + + @Test + void test_Holzkirchen_Resolution12() { + Network network = getNetwork(); + String crs = TransformationFactory.DHDN_GK4; + int resolution = 12; + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("8c1f8d6930b63ff")); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo(createZoneId("8c1f88b4025d1ff")); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("8c1f89d06d581ff")); + + //check all links are mapped + for (Link link : network.getLinks().values()) { + assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId())); + } + } + + + static Network getNetwork() { + Network network = NetworkUtils.createNetwork(); + URL holzkirchen = ConfigGroup.getInputFileURL(ExamplesUtils.getTestScenarioURL("holzkirchen"), "holzkirchenNetwork.xml.gz"); + new MatsimNetworkReader(network).parse(holzkirchen); + return network; + } +} diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/insertion/DrtInsertionExtensionIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/insertion/DrtInsertionExtensionIT.java index 69febd3aab0..be42758f698 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/insertion/DrtInsertionExtensionIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/insertion/DrtInsertionExtensionIT.java @@ -283,7 +283,7 @@ void testRangeConstraintWithCustomInstances() { } assertEquals(1470, distanceCalculator.calculatedDistances); - assertEquals(5288, distanceApproximator.calculatedDistances); + assertEquals(5280, distanceApproximator.calculatedDistances); } @Test @@ -319,7 +319,7 @@ protected void configureQSim() { } assertEquals(1470, distanceCalculator.calculatedDistances); - assertEquals(5288, distanceApproximator.calculatedDistances); + assertEquals(5280, distanceApproximator.calculatedDistances); } static class CustomDistanceCalculator extends CustomCalculator { @@ -464,9 +464,9 @@ void testVehicleDistanceObjective() { controller.run(); assertEquals(22, handler.rejectedRequests); - assertEquals(2066658.0, handler.fleetDistance, 1e-3); - assertEquals(694149.0, handler.activeTime(), 1e-3); - assertEquals(280.61475, handler.meanWaitTime(), 1e-3); + assertEquals(2070663.0, handler.fleetDistance, 1e-3); + assertEquals(699076.0, handler.activeTime(), 1e-3); + assertEquals(279.37704, handler.meanWaitTime(), 1e-3); } @Test diff --git a/contribs/drt/pom.xml b/contribs/drt/pom.xml index a80d854f1b5..f04956d8ea0 100644 --- a/contribs/drt/pom.xml +++ b/contribs/drt/pom.xml @@ -50,19 +50,13 @@ gt-main ${geotools.version} - + org.geotools gt-opengis ${geotools.version} - - one.util - streamex - 0.8.2 - - org.locationtech.jts jts-core 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 399804f9aee..edc20fb87b7 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 @@ -20,6 +20,8 @@ package org.matsim.contrib.drt.analysis; import com.google.common.base.Preconditions; +import com.google.common.collect.HashMultiset; +import com.google.common.collect.Multiset; import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; import org.apache.logging.log4j.LogManager; @@ -332,7 +334,7 @@ private void writeIterationPassengerStats(String summarizeLegs, int it) { try (var bw = getAppendingBufferedWriter("drt_customer_stats", ".csv")) { if (!headerWritten) { headerWritten = true; - bw.write(line("runId", "iteration", "rides", "wait_average", "wait_max", "wait_p95", "wait_p75", "wait_median", + bw.write(line("runId", "iteration", "rides", "rides_pax", "groupSize_mean", "wait_average", "wait_max", "wait_p95", "wait_p75", "wait_median", "percentage_WT_below_10", "percentage_WT_below_15", "inVehicleTravelTime_mean", "distance_m_mean", "directDistance_m_mean", "totalTravelTime_mean", "fareAllReferences_mean", "rejections", "rejectionRate")); } @@ -569,10 +571,13 @@ private static String summarizeLegs(List legs, Map, Double> format.setMaximumFractionDigits(2); format.setGroupingUsed(false); + Multiset> servedRides = HashMultiset.create(); + for (DrtLeg leg : legs) { if (leg.toLinkId == null) { continue; } + servedRides.add(leg.request); waitStats.addValue(leg.waitTime); rideStats.addValue(leg.arrivalTime - leg.departureTime - leg.waitTime); distanceStats.addValue(travelDistances.get(leg.request)); @@ -580,7 +585,9 @@ private static String summarizeLegs(List legs, Map, Double> traveltimes.addValue(leg.arrivalTime - leg.departureTime); } - return String.join(delimiter, format.format(waitStats.getValues().length) + "",// + return String.join(delimiter, format.format(servedRides.entrySet().size()) + "",// + format.format(servedRides.size()) + "",// + format.format(((double) servedRides.size()) / servedRides.entrySet().size()) + "",// format.format(waitStats.getMean()) + "",// format.format(waitStats.getMax()) + "",// format.format(waitStats.getPercentile(95)) + "",// diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtGridUtils.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtGridUtils.java index b33136cec26..75101e4bc6c 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtGridUtils.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtGridUtils.java @@ -22,10 +22,7 @@ */ package org.matsim.contrib.drt.analysis.zonal; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import one.util.streamex.EntryStream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.locationtech.jts.geom.Coordinate; @@ -37,7 +34,9 @@ import org.matsim.core.network.NetworkUtils; import org.matsim.core.utils.misc.Counter; -import one.util.streamex.EntryStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * @author jbischoff @@ -74,21 +73,17 @@ public static Map createGridFromNetwork(Network networ } /** - * First creates a grid based on the network bounding box. Then removes all zones that do not intersect the service area. + * Takes an existing grid and removes all zones that do not intersect the service area. * Result may contain zones that are barely included in the service area. But as passengers may walk into the service area, * it seems appropriate that the DrtZonalSystem, which is used for demand estimation, is larger than the service area. * The {@code cellsize} indirectly determines, how much larger the DrtZonalSystem may get. * - * @param network - * @param cellsize + * @param grid a pre-computed grid of zones * @param serviceAreaGeoms geometries that define the service area * @return */ - public static Map createGridFromNetworkWithinServiceArea(Network network, double cellsize, - List serviceAreaGeoms) { - Map grid = createGridFromNetwork(network, cellsize); - log.info("total number of created grid zones = " + grid.size()); - + public static Map filterGridWithinServiceArea(Map grid, List serviceAreaGeoms) { + log.info("total number of initial grid zones = " + grid.size()); log.info("searching for grid zones within the drt service area..."); Counter counter = new Counter("dealt with zone "); Map zonesWithinServiceArea = EntryStream.of(grid) 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 8d81ba21749..bd3e6b7ddc6 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 @@ -20,24 +20,26 @@ package org.matsim.contrib.drt.analysis.zonal; -import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtils.createGridFromNetwork; -import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtils.createGridFromNetworkWithinServiceArea; -import static org.matsim.contrib.drt.run.DrtConfigGroup.OperationalScheme; -import static org.matsim.utils.gis.shp2matsim.ShpGeometryUtils.loadPreparedGeometries; - -import java.util.List; - +import com.google.common.base.Preconditions; +import one.util.streamex.EntryStream; import org.locationtech.jts.geom.prep.PreparedGeometry; import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.ZoneSystemUtils; +import org.matsim.contrib.common.zones.h3.H3GridUtils; +import org.matsim.contrib.common.zones.h3.H3ZoneSystemUtils; import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; import org.matsim.core.config.ConfigGroup; import org.matsim.core.controler.MatsimServices; -import com.google.common.base.Preconditions; +import java.util.List; +import java.util.Map; -import one.util.streamex.EntryStream; +import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtils.createGridFromNetwork; +import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtils.filterGridWithinServiceArea; +import static org.matsim.utils.gis.shp2matsim.ShpGeometryUtils.loadPreparedGeometries; /** * @author Michal Maciejewski (michalm) @@ -53,53 +55,73 @@ public DrtModeZonalSystemModule(DrtConfigGroup drtCfg) { @Override public void install() { - DrtZonalSystemParams params = drtCfg.getZonalSystemParams().orElseThrow(); - - bindModal(DrtZonalSystem.class).toProvider(modalProvider(getter -> { - Network network = getter.getModal(Network.class); - switch (params.zonesGeneration) { - case ShapeFile: - final List preparedGeometries = loadPreparedGeometries( + if (drtCfg.getZonalSystemParams().isPresent()) { + DrtZonalSystemParams params = drtCfg.getZonalSystemParams().get(); + + bindModal(ZoneSystem.class).toProvider(modalProvider(getter -> { + Network network = getter.getModal(Network.class); + switch (params.zonesGeneration) { + case ShapeFile: { + final List preparedGeometries = loadPreparedGeometries( ConfigGroup.getInputFileURL(getConfig().getContext(), params.zonesShapeFile)); - return DrtZonalSystem.createFromPreparedGeometries(network, + return ZoneSystemUtils.createFromPreparedGeometries(network, EntryStream.of(preparedGeometries).mapKeys(i -> (i + 1) + "").toMap()); - - case GridFromNetwork: - Preconditions.checkNotNull(params.cellSize); - var gridZones = drtCfg.operationalScheme == OperationalScheme.serviceAreaBased ? - createGridFromNetworkWithinServiceArea(network, params.cellSize, + } + + case GridFromNetwork: { + Preconditions.checkNotNull(params.cellSize); + Map gridFromNetwork = createGridFromNetwork(network, params.cellSize); + var gridZones = + switch (drtCfg.operationalScheme) { + case stopbased, door2door -> gridFromNetwork; + case serviceAreaBased -> filterGridWithinServiceArea(gridFromNetwork, loadPreparedGeometries(ConfigGroup.getInputFileURL(getConfig().getContext(), - drtCfg.drtServiceAreaShapeFile))) : - createGridFromNetwork(network, params.cellSize); - return DrtZonalSystem.createFromPreparedGeometries(network, gridZones); - - default: - throw new RuntimeException("Unsupported zone generation"); - } - })).asEagerSingleton(); - - bindModal(DrtZoneTargetLinkSelector.class).toProvider(modalProvider(getter -> { - switch (params.targetLinkSelection) { - case mostCentral: - return new MostCentralDrtZoneTargetLinkSelector(getter.getModal(DrtZonalSystem.class)); - case random: - return new RandomDrtZoneTargetLinkSelector(); - default: - throw new RuntimeException( + drtCfg.drtServiceAreaShapeFile))); + }; + return ZoneSystemUtils.createFromPreparedGeometries(network, gridZones); + } + + case H3: + Preconditions.checkNotNull(params.h3Resolution); + String crs = getConfig().global().getCoordinateSystem(); + Map gridFromNetwork = H3GridUtils.createH3GridFromNetwork(network, params.h3Resolution, crs); + var gridZones = + switch (drtCfg.operationalScheme) { + case stopbased, door2door -> gridFromNetwork; + case serviceAreaBased -> filterGridWithinServiceArea(gridFromNetwork, + loadPreparedGeometries(ConfigGroup.getInputFileURL(getConfig().getContext(), + drtCfg.drtServiceAreaShapeFile))); + }; + return H3ZoneSystemUtils.createFromPreparedGeometries(network, gridZones, crs, params.h3Resolution); + + default: + throw new RuntimeException("Unsupported zone generation"); + } + })).asEagerSingleton(); + + bindModal(DrtZoneTargetLinkSelector.class).toProvider(modalProvider(getter -> { + switch (params.targetLinkSelection) { + case mostCentral: + return new MostCentralDrtZoneTargetLinkSelector(getter.getModal(ZoneSystem.class)); + case random: + return new RandomDrtZoneTargetLinkSelector(); + default: + throw new RuntimeException( "Unsupported target link selection = " + params.targetLinkSelection); - } - })).asEagerSingleton(); + } + })).asEagerSingleton(); - //zonal analysis - bindModal(ZonalIdleVehicleXYVisualiser.class).toProvider(modalProvider( + //zonal analysis + bindModal(ZonalIdleVehicleXYVisualiser.class).toProvider(modalProvider( getter -> new ZonalIdleVehicleXYVisualiser(getter.get(MatsimServices.class), drtCfg.getMode(), - getter.getModal(DrtZonalSystem.class)))).asEagerSingleton(); - addControlerListenerBinding().to(modalKey(ZonalIdleVehicleXYVisualiser.class)); - addEventHandlerBinding().to(modalKey(ZonalIdleVehicleXYVisualiser.class)); + getter.getModal(ZoneSystem.class)))).asEagerSingleton(); + addControlerListenerBinding().to(modalKey(ZonalIdleVehicleXYVisualiser.class)); + addEventHandlerBinding().to(modalKey(ZonalIdleVehicleXYVisualiser.class)); - bindModal(DrtZonalWaitTimesAnalyzer.class).toProvider(modalProvider( + bindModal(DrtZonalWaitTimesAnalyzer.class).toProvider(modalProvider( getter -> new DrtZonalWaitTimesAnalyzer(drtCfg, getter.getModal(DrtEventSequenceCollector.class), - getter.getModal(DrtZonalSystem.class)))).asEagerSingleton(); - addControlerListenerBinding().to(modalKey(DrtZonalWaitTimesAnalyzer.class)); + getter.getModal(ZoneSystem.class)))).asEagerSingleton(); + addControlerListenerBinding().to(modalKey(DrtZonalWaitTimesAnalyzer.class)); + } } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystem.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystem.java deleted file mode 100644 index 33647f30d80..00000000000 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystem.java +++ /dev/null @@ -1,111 +0,0 @@ -/* *********************************************************************** * - * project: org.matsim.* - * * - * *********************************************************************** * - * * - * copyright : (C) 2017 by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** */ - -package org.matsim.contrib.drt.analysis.zonal; - -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toMap; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; - -import javax.annotation.Nullable; - -import org.apache.commons.lang3.tuple.Pair; -import org.locationtech.jts.geom.Point; -import org.locationtech.jts.geom.prep.PreparedGeometry; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.network.Link; -import org.matsim.api.core.v01.network.Network; -import org.matsim.core.utils.geometry.geotools.MGC; - -import one.util.streamex.EntryStream; -import one.util.streamex.StreamEx; - -/** - * @author jbischoff - * @author Michal Maciejewski (michalm) - * @author Tilmann Schlenther (tschlenther) - */ -public class DrtZonalSystem { - - public static DrtZonalSystem createFromPreparedGeometries(Network network, - Map geometries) { - - //geometries without links are skipped - Map> linksByGeometryId = StreamEx.of(network.getLinks().values()) - .mapToEntry(l -> getGeometryIdForLink(l, geometries), l -> l) - .filterKeys(Objects::nonNull) - .grouping(toList()); - - //the zonal system contains only zones that have at least one link - List zones = EntryStream.of(linksByGeometryId) - .mapKeyValue((id, links) -> new DrtZone(id, geometries.get(id), links)) - .collect(toList()); - - return new DrtZonalSystem(zones); - } - - /** - * @param link - * @return the the {@code PreparedGeometry} that contains the {@code linkId}. - * If a given link's {@code Coord} borders two or more cells, the allocation to a cell is random. - * Result may be null in case the given link is outside of the service area. - */ - @Nullable - private static String getGeometryIdForLink(Link link, Map geometries) { - Point linkCoord = MGC.coord2Point(link.getToNode().getCoord()); - return geometries.entrySet() - .stream() - .filter(e -> e.getValue().intersects(linkCoord)) - .findAny() - .map(Entry::getKey) - .orElse(null); - } - - private final Map zones; - private final Map, DrtZone> link2zone; - - public DrtZonalSystem(Collection zones) { - this.zones = zones.stream().collect(toMap(DrtZone::getId, z -> z)); - this.link2zone = zones.stream() - .flatMap(zone -> zone.getLinks().stream().map(link -> Pair.of(link.getId(), zone))) - .collect(toMap(Pair::getKey, Pair::getValue)); - } - - /** - * @param linkId - * @return the the {@code DrtZone} that contains the {@code linkId}. If the given link's {@code Coord} borders two or more cells, the allocation to a cell is random. - * Result may be null in case the given link is outside of the service area. - */ - @Nullable - public DrtZone getZoneForLinkId(Id linkId) { - return link2zone.get(linkId); - } - - /** - * @return the zones - */ - public Map getZones() { - return zones; - } -} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemParams.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemParams.java index 01230c1e115..4dd0860b578 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemParams.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemParams.java @@ -22,6 +22,7 @@ import javax.annotation.Nullable; +import org.matsim.contrib.common.zones.h3.H3Utils; import org.matsim.core.config.Config; import org.matsim.core.config.ReflectiveConfigGroup; @@ -40,10 +41,10 @@ public DrtZonalSystemParams() { super(SET_NAME); } - public enum ZoneGeneration {GridFromNetwork, ShapeFile} + public enum ZoneGeneration {GridFromNetwork, ShapeFile, H3} @Parameter - @Comment("Logic for generation of zones for the DRT zonal system. Value can be: [GridFromNetwork, ShapeFile].") + @Comment("Logic for generation of zones for the DRT zonal system. Value can be: [GridFromNetwork, ShapeFile, H3].") @NotNull public ZoneGeneration zonesGeneration = null; @@ -59,6 +60,14 @@ public enum ZoneGeneration {GridFromNetwork, ShapeFile} @Nullable public String zonesShapeFile = null; + @Parameter + @Comment("allows to configure H3 hexagonal zones. Used with zonesGeneration=H3. " + + "Range from 0 (122 cells worldwide) to 15 (569 E^12 cells). " + + "Usually meaningful between resolution 6 (3.7 km avg edge length) " + + "and 10 (70 m avg edge length). ") + @Nullable + public Integer h3Resolution = null; + public enum TargetLinkSelection {random, mostCentral} @Parameter("zoneTargetLinkSelection") @@ -75,5 +84,9 @@ protected void checkConsistency(Config config) { "cellSize must not be null when zonesGeneration is " + ZoneGeneration.GridFromNetwork); Preconditions.checkArgument(zonesGeneration != ZoneGeneration.ShapeFile || zonesShapeFile != null, "zonesShapeFile must not be null when zonesGeneration is " + ZoneGeneration.ShapeFile); + Preconditions.checkArgument(zonesGeneration != ZoneGeneration.H3 || h3Resolution != null, + "H3 resolution must not be null when zonesGeneration is " + ZoneGeneration.H3); + Preconditions.checkArgument(h3Resolution == null || h3Resolution >= 0 && h3Resolution <= H3Utils.MAX_RES, + "H3 resolution must not be null when zonesGeneration is " + ZoneGeneration.H3); } } 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 40c885b5531..4972db0a280 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 @@ -20,18 +20,6 @@ package org.matsim.contrib.drt.analysis.zonal; -import java.io.BufferedWriter; -import java.io.IOException; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.SortedSet; -import java.util.TreeSet; - import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -40,7 +28,10 @@ import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Polygon; import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdMap; import org.matsim.api.core.v01.population.Person; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector.EventSequence; import org.matsim.contrib.drt.run.DrtConfigGroup; @@ -49,21 +40,27 @@ import org.matsim.core.controler.listener.IterationEndsListener; import org.matsim.core.controler.listener.ShutdownListener; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.matsim.core.utils.io.IOUtils; import org.opengis.feature.simple.SimpleFeature; +import java.io.BufferedWriter; +import java.io.IOException; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.*; + public final class DrtZonalWaitTimesAnalyzer implements IterationEndsListener, ShutdownListener { private final DrtConfigGroup drtCfg; private final DrtEventSequenceCollector requestAnalyzer; - private final DrtZonalSystem zones; - private static final String zoneIdForOutsideOfZonalSystem = "outsideOfDrtZonalSystem"; + private final ZoneSystem zones; + private static final Id zoneIdForOutsideOfZonalSystem = Id.create("outsideOfDrtZonalSystem", Zone.class); private static final String notAvailableString = "NaN"; private static final Logger log = LogManager.getLogger(DrtZonalWaitTimesAnalyzer.class); public DrtZonalWaitTimesAnalyzer(DrtConfigGroup configGroup, DrtEventSequenceCollector requestAnalyzer, - DrtZonalSystem zones) { + ZoneSystem zones) { this.drtCfg = configGroup; this.requestAnalyzer = requestAnalyzer; this.zones = zones; @@ -79,7 +76,7 @@ public void notifyIterationEnds(IterationEndsEvent event) { public void write(String fileName) { String delimiter = ";"; - Map zoneStats = createZonalStats(); + Map, DescriptiveStatistics> zoneStats = createZonalStats(); BufferedWriter bw = IOUtils.getBufferedWriter(fileName); try { DecimalFormat format = new DecimalFormat(); @@ -89,16 +86,16 @@ public void write(String fileName) { format.setGroupingUsed(false); bw.append("zone;centerX;centerY;nRequests;sumWaitTime;meanWaitTime;min;max;p95;p90;p80;p75;p50"); // sorted output - SortedSet zoneIdsAndOutside = new TreeSet<>(zones.getZones().keySet()); + SortedSet> zoneIdsAndOutside = new TreeSet<>(zones.getZones().keySet()); zoneIdsAndOutside.add(zoneIdForOutsideOfZonalSystem); - for (String zoneId : zoneIdsAndOutside) { - DrtZone drtZone = zones.getZones().get(zoneId); + for (Id zoneId : zoneIdsAndOutside) { + Zone drtZone = zones.getZones().get(zoneId); String centerX = drtZone != null ? String.valueOf(drtZone.getCentroid().getX()) : notAvailableString; String centerY = drtZone != null ? String.valueOf(drtZone.getCentroid().getY()) : notAvailableString; DescriptiveStatistics stats = zoneStats.get(zoneId); bw.newLine(); - bw.append(zoneId) + bw.append(zoneId.toString()) .append(delimiter) .append(centerX) .append(delimiter) @@ -131,10 +128,10 @@ public void write(String fileName) { } } - private Map createZonalStats() { - Map zoneStats = new HashMap<>(); + private Map, DescriptiveStatistics> createZonalStats() { + Map, DescriptiveStatistics> zoneStats = new IdMap<>(Zone.class); // prepare stats for all zones - for (String zoneId : zones.getZones().keySet()) { + for (Id zoneId : zones.getZones().keySet()) { zoneStats.put(zoneId, new DescriptiveStatistics()); } zoneStats.put(zoneIdForOutsideOfZonalSystem, new DescriptiveStatistics()); @@ -142,8 +139,8 @@ private Map createZonalStats() { for (EventSequence seq : requestAnalyzer.getPerformedRequestSequences().values()) { for (Map.Entry, EventSequence.PersonEvents> entry : seq.getPersonEvents().entrySet()) { if(entry.getValue().getPickedUp().isPresent()) { - DrtZone zone = zones.getZoneForLinkId(seq.getSubmitted().getFromLinkId()); - final String zoneStr = zone != null ? zone.getId() : zoneIdForOutsideOfZonalSystem; + Zone zone = zones.getZoneForLinkId(seq.getSubmitted().getFromLinkId()); + final Id zoneStr = zone != null ? zone.getId() : zoneIdForOutsideOfZonalSystem; double waitTime = entry.getValue().getPickedUp().get() .getTime() - seq.getSubmitted().getTime(); zoneStats.get(zoneStr).addValue(waitTime); } @@ -159,10 +156,12 @@ private Map createZonalStats() { public void notifyShutdown(ShutdownEvent event) { String crs = event.getServices().getConfig().global().getCoordinateSystem(); Collection features = convertGeometriesToSimpleFeatures(crs); - String fileName = event.getServices() + if(!features.isEmpty()) { + String fileName = event.getServices() .getControlerIO() - .getOutputFilename("drt_waitStats" + "_" + drtCfg.getMode() + "_zonal.shp"); - ShapeFileWriter.writeGeometries(features, fileName); + .getOutputFilename("drt_waitStats" + "_" + drtCfg.getMode() + "_zonal.gpkg"); + GeoFileWriter.writeGeometries(features, fileName); + } } private Collection convertGeometriesToSimpleFeatures(String targetCoordinateSystem) { @@ -172,9 +171,10 @@ private Collection convertGeometriesToSimpleFeatures(String targe } catch (IllegalArgumentException e) { log.warn("Coordinate reference system \"" + targetCoordinateSystem - + "\" is unknown. Please set a crs in config global. Will try to create drt_waitStats_" + + "\" is unknown. Please set a crs in config global. Will not create drt_waitStats_" + drtCfg.getMode() - + "_zonal.shp anyway."); + + "_zonal.gpkg."); + return Collections.emptyList(); } simpleFeatureBuilder.setName("drtZoneFeature"); @@ -197,9 +197,9 @@ private Collection convertGeometriesToSimpleFeatures(String targe Collection features = new ArrayList<>(); - Map zoneStats = createZonalStats(); + Map, DescriptiveStatistics> zoneStats = createZonalStats(); - for (DrtZone zone : zones.getZones().values()) { + for (Zone zone : zones.getZones().values()) { Object[] routeFeatureAttributes = new Object[14]; Geometry geometry = zone.getPreparedGeometry() != null ? zone.getPreparedGeometry().getGeometry() : null; DescriptiveStatistics stats = zoneStats.get(zone.getId()); @@ -219,7 +219,7 @@ private Collection convertGeometriesToSimpleFeatures(String targe routeFeatureAttributes[13] = stats.getPercentile(50); try { - features.add(builder.buildFeature(zone.getId(), routeFeatureAttributes)); + features.add(builder.buildFeature(zone.getId().toString(), routeFeatureAttributes)); } catch (IllegalArgumentException e) { e.printStackTrace(); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZone.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZone.java deleted file mode 100644 index cca2045837a..00000000000 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZone.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * *********************************************************************** * - * project: org.matsim.* - * *********************************************************************** * - * * - * copyright : (C) 2020 by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** * - */ - -package org.matsim.contrib.drt.analysis.zonal; - -import java.util.List; - -import javax.annotation.Nullable; - -import org.locationtech.jts.geom.prep.PreparedGeometry; -import org.matsim.api.core.v01.Coord; -import org.matsim.api.core.v01.network.Link; -import org.matsim.core.utils.geometry.geotools.MGC; - -/** - * @author Michal Maciejewski (michalm) - */ -public class DrtZone { - public static DrtZone createDummyZone(String id, List links, Coord centroid) { - return new DrtZone(id, null, links, centroid); - } - - private final String id; - @Nullable - private final PreparedGeometry preparedGeometry; //null for virtual/dummy zones - private final List links; - private final Coord centroid; - - public DrtZone(String id, PreparedGeometry preparedGeometry, List links) { - this(id, preparedGeometry, links, MGC.point2Coord(preparedGeometry.getGeometry().getCentroid())); - } - - private DrtZone(String id, @Nullable PreparedGeometry preparedGeometry, List links, Coord centroid) { - this.id = id; - this.preparedGeometry = preparedGeometry; - this.links = links; - this.centroid = centroid; - } - - public String getId() { - return id; - } - - @Nullable - public PreparedGeometry getPreparedGeometry() { - return preparedGeometry; - } - - public Coord getCentroid() { - return centroid; - } - - public List getLinks() { - return links; - } - - boolean isDummy() { - return preparedGeometry == null; - } -} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZoneTargetLinkSelector.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZoneTargetLinkSelector.java index ac7442ca369..c7c8bbeb240 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZoneTargetLinkSelector.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZoneTargetLinkSelector.java @@ -20,9 +20,10 @@ package org.matsim.contrib.drt.analysis.zonal; import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.common.zones.Zone; public interface DrtZoneTargetLinkSelector { - Link selectTargetLink(DrtZone zone); + Link selectTargetLink(Zone zone); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/MostCentralDrtZoneTargetLinkSelector.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/MostCentralDrtZoneTargetLinkSelector.java index ce30fc7b5df..22022631dcc 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/MostCentralDrtZoneTargetLinkSelector.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/MostCentralDrtZoneTargetLinkSelector.java @@ -28,14 +28,16 @@ import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Node; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; /** * @author tschlenther */ public class MostCentralDrtZoneTargetLinkSelector implements DrtZoneTargetLinkSelector { - private final Map targetLinks; + private final Map targetLinks; - public MostCentralDrtZoneTargetLinkSelector(DrtZonalSystem drtZonalSystem) { + public MostCentralDrtZoneTargetLinkSelector(ZoneSystem drtZonalSystem) { targetLinks = drtZonalSystem.getZones() .values() .stream() @@ -48,11 +50,11 @@ public MostCentralDrtZoneTargetLinkSelector(DrtZonalSystem drtZonalSystem) { } @Override - public Link selectTargetLink(DrtZone zone) { + public Link selectTargetLink(Zone zone) { return this.targetLinks.get(zone); } - private double squaredDistance(DrtZone zone, Node node) { + private double squaredDistance(Zone zone, Node node) { return calculateSquaredDistance(zone.getCentroid(), node.getCoord()); } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelector.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelector.java index 2027834e17b..7c7f4413e0a 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelector.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelector.java @@ -23,6 +23,7 @@ import java.util.function.IntUnaryOperator; import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.common.zones.Zone; import org.matsim.core.gbl.MatsimRandom; /** @@ -40,7 +41,7 @@ public RandomDrtZoneTargetLinkSelector(IntUnaryOperator random) { } @Override - public Link selectTargetLink(DrtZone zone) { + public Link selectTargetLink(Zone zone) { return zone.getLinks().get(random.applyAsInt(zone.getLinks().size())); } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/ZonalIdleVehicleCollector.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/ZonalIdleVehicleCollector.java index ddba7676cdf..2626e21fc3f 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/ZonalIdleVehicleCollector.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/ZonalIdleVehicleCollector.java @@ -19,34 +19,31 @@ package org.matsim.contrib.drt.analysis.zonal; +import org.matsim.api.core.v01.Id; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.drt.schedule.DrtStayTask; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; +import org.matsim.contrib.dvrp.vrpagent.*; + import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.function.Consumer; -import org.matsim.api.core.v01.Id; -import org.matsim.contrib.drt.schedule.DrtStayTask; -import org.matsim.contrib.dvrp.fleet.DvrpVehicle; -import org.matsim.contrib.dvrp.vrpagent.AbstractTaskEvent; -import org.matsim.contrib.dvrp.vrpagent.TaskEndedEvent; -import org.matsim.contrib.dvrp.vrpagent.TaskEndedEventHandler; -import org.matsim.contrib.dvrp.vrpagent.TaskStartedEvent; -import org.matsim.contrib.dvrp.vrpagent.TaskStartedEventHandler; - /** * @author jbischoff * @author Michal Maciejewski */ public class ZonalIdleVehicleCollector implements TaskStartedEventHandler, TaskEndedEventHandler { - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final String dvrpMode; - private final Map>> vehiclesPerZone = new HashMap<>(); - private final Map, DrtZone> zonePerVehicle = new HashMap<>(); + private final Map>> vehiclesPerZone = new HashMap<>(); - public ZonalIdleVehicleCollector(String dvrpMode, DrtZonalSystem zonalSystem) { + public ZonalIdleVehicleCollector(String dvrpMode, ZoneSystem zonalSystem) { this.dvrpMode = dvrpMode; this.zonalSystem = zonalSystem; } @@ -55,34 +52,31 @@ public ZonalIdleVehicleCollector(String dvrpMode, DrtZonalSystem zonalSystem) { public void handleEvent(TaskStartedEvent event) { handleEvent(event, zone -> { vehiclesPerZone.computeIfAbsent(zone, z -> new HashSet<>()).add(event.getDvrpVehicleId()); - zonePerVehicle.put(event.getDvrpVehicleId(), zone); }); } @Override public void handleEvent(TaskEndedEvent event) { handleEvent(event, zone -> { - zonePerVehicle.remove(event.getDvrpVehicleId()); vehiclesPerZone.get(zone).remove(event.getDvrpVehicleId()); }); } - private void handleEvent(AbstractTaskEvent event, Consumer handler) { + private void handleEvent(AbstractTaskEvent event, Consumer handler) { if (event.getDvrpMode().equals(dvrpMode) && event.getTaskType().equals(DrtStayTask.TYPE)) { - DrtZone zone = zonalSystem.getZoneForLinkId(event.getLinkId()); + Zone zone = zonalSystem.getZoneForLinkId(event.getLinkId()); if (zone != null) { handler.accept(zone); } } } - public Set> getIdleVehiclesPerZone(DrtZone zone) { + public Set> getIdleVehiclesPerZone(Zone zone) { return this.vehiclesPerZone.get(zone); } @Override public void reset(int iteration) { - zonePerVehicle.clear(); vehiclesPerZone.clear(); } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/ZonalIdleVehicleXYVisualiser.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/ZonalIdleVehicleXYVisualiser.java index ffaa6a8312f..8813f7673ab 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/ZonalIdleVehicleXYVisualiser.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/ZonalIdleVehicleXYVisualiser.java @@ -20,38 +20,35 @@ package org.matsim.contrib.drt.analysis.zonal; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.Map; -import java.util.function.Consumer; - +import com.opencsv.CSVWriter; import org.matsim.api.core.v01.Coord; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.schedule.DrtStayTask; -import org.matsim.contrib.dvrp.vrpagent.AbstractTaskEvent; -import org.matsim.contrib.dvrp.vrpagent.TaskEndedEvent; -import org.matsim.contrib.dvrp.vrpagent.TaskEndedEventHandler; -import org.matsim.contrib.dvrp.vrpagent.TaskStartedEvent; -import org.matsim.contrib.dvrp.vrpagent.TaskStartedEventHandler; +import org.matsim.contrib.dvrp.vrpagent.*; import org.matsim.core.controler.MatsimServices; import org.matsim.core.controler.events.IterationEndsEvent; import org.matsim.core.controler.listener.IterationEndsListener; import org.matsim.core.utils.collections.Tuple; -import com.opencsv.CSVWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.function.Consumer; public class ZonalIdleVehicleXYVisualiser implements TaskStartedEventHandler, TaskEndedEventHandler, IterationEndsListener { private final String mode; - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final MatsimServices services; - private final Map>> zoneEntries = new LinkedHashMap<>(); + private final Map>> zoneEntries = new LinkedHashMap<>(); - public ZonalIdleVehicleXYVisualiser(MatsimServices services, String mode, DrtZonalSystem zonalSystem) { + public ZonalIdleVehicleXYVisualiser(MatsimServices services, String mode, ZoneSystem zonalSystem) { this.services = services; this.mode = mode; this.zonalSystem = zonalSystem; @@ -59,7 +56,7 @@ public ZonalIdleVehicleXYVisualiser(MatsimServices services, String mode, DrtZon } private void initEntryMap() { - for (DrtZone z : zonalSystem.getZones().values()) { + for (Zone z : zonalSystem.getZones().values()) { LinkedList> list = new LinkedList<>(); list.add(new Tuple<>(0d, 0)); zoneEntries.put(z, list); @@ -84,9 +81,9 @@ public void handleEvent(TaskEndedEvent event) { }); } - private void handleEvent(AbstractTaskEvent event, Consumer handler) { + private void handleEvent(AbstractTaskEvent event, Consumer handler) { if (event.getDvrpMode().equals(mode) && event.getTaskType().equals(DrtStayTask.TYPE)) { - DrtZone zone = zonalSystem.getZoneForLinkId(event.getLinkId()); + Zone zone = zonalSystem.getZoneForLinkId(event.getLinkId()); if (zone != null) { handler.accept(zone); } @@ -104,7 +101,7 @@ public void notifyIterationEnds(IterationEndsEvent event) { this.zoneEntries.forEach((zone, entriesList) -> { Coord c = zone.getCentroid(); entriesList.forEach(entry -> writer.writeNext( - new String[] { zone.getId(), "" + c.getX(), "" + c.getY(), "" + entry.getFirst(), + new String[] { zone.getId().toString(), "" + c.getX(), "" + c.getY(), "" + entry.getFirst(), "" + entry.getSecond() }, false)); }); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/DrtModeOptimizerQSimModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/DrtModeOptimizerQSimModule.java index 8534468ce81..92336f544c4 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/DrtModeOptimizerQSimModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/DrtModeOptimizerQSimModule.java @@ -37,6 +37,7 @@ import org.matsim.contrib.drt.optimizer.insertion.selective.SelectiveInsertionSearchQSimModule; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; +import org.matsim.contrib.drt.passenger.DefaultOfferAcceptor; import org.matsim.contrib.drt.prebooking.PrebookingActionCreator; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.schedule.DrtStayTaskEndTimeCalculator; @@ -138,7 +139,7 @@ public EmptyVehicleRelocator get() { }).asEagerSingleton(); bindModal(DrtScheduleInquiry.class).to(DrtScheduleInquiry.class).asEagerSingleton(); - + boolean scheduleWaitBeforeDrive = drtCfg.getPrebookingParams().map(p -> p.scheduleWaitBeforeDrive).orElse(false); bindModal(RequestInsertionScheduler.class).toProvider(modalProvider( getter -> new DefaultRequestInsertionScheduler(getter.getModal(Fleet.class), @@ -147,7 +148,8 @@ public EmptyVehicleRelocator get() { getter.getModal(StopTimeCalculator.class), scheduleWaitBeforeDrive))) .asEagerSingleton(); - bindModal(DrtOfferAcceptor.class).toInstance(DrtOfferAcceptor.DEFAULT_ACCEPTOR); + bindModal(DefaultOfferAcceptor.class).toProvider(modalProvider(getter -> new DefaultOfferAcceptor(drtCfg.maxAllowedPickupDelay))); + bindModal(DrtOfferAcceptor.class).to(modalKey(DefaultOfferAcceptor.class)); bindModal(ScheduleTimingUpdater.class).toProvider(modalProvider( getter -> new ScheduleTimingUpdater(getter.get(MobsimTimer.class), @@ -160,7 +162,7 @@ public EmptyVehicleRelocator get() { return v -> VrpLegFactory.createWithOnlineTracker(dvrpCfg.mobsimMode, v, OnlineTrackerListener.NO_LISTENER, timer); })).in(Singleton.class); - + if (drtCfg.getPrebookingParams().isEmpty()) { bindModal(VrpAgentLogic.DynActionCreator.class).to(modalKey(DrtActionCreator.class)); } else { diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/InsertionGenerator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/InsertionGenerator.java index 60e27e4bc5a..2d1bd2aa13e 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/InsertionGenerator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/InsertionGenerator.java @@ -186,7 +186,8 @@ public List generateInsertions(DrtRequest drtRequest, V // task here on the same link (maybe a pickup followed by its dropoff) but much // earlier. In that case it is actually a valid insertion. - if (drtRequest.getEarliestStartTime() < nextStop.getArrivalTime()) { + boolean viableSameLink = vEntry.getPrecedingStayTime(i) > 0.0; + if (viableSameLink && drtRequest.getEarliestStartTime() < nextStop.getArrivalTime()) { // the new request wants to depart before the start of the next stop, which may // be a viable insertion. Note that if the requested wanted to depart after the // start of the next stop, but before its end, this is a special case that is @@ -235,6 +236,16 @@ private void generateDropoffInsertions(DrtRequest request, VehicleEntry vEntry, addInsertion(insertions, createInsertionWithDetourData(request, vEntry, pickupInsertion, fromPickupTT, pickupDetourInfo, j)); + } else { + // special case: inserting dropoff before prebooked task on the same link + // see the reasoning in generateInsertions + + boolean viableSameLink = vEntry.getPrecedingStayTime(j) > 0.0; + if (viableSameLink && earliestPickupStartTime + fromPickupTT < nextStop(vEntry, j).getArrivalTime()) { + addInsertion(insertions, + createInsertionWithDetourData(request, vEntry, pickupInsertion, fromPickupTT, pickupDetourInfo, + j)); + } } } @@ -274,6 +285,16 @@ private void generateDropoffInsertions(DrtRequest request, VehicleEntry vEntry, addInsertion(insertions, createInsertionWithDetourData(request, vEntry, pickupInsertion, fromPickupTT, pickupDetourInfo, j)); + } else { + // special case: inserting dropoff before prebooked task on the same link + // see the reasoning in generateInsertions + + boolean viableSameLink = vEntry.getPrecedingStayTime(j) > 0.0; + if (viableSameLink && earliestPickupStartTime + fromPickupTT < nextStop(vEntry, j).getArrivalTime()) { + addInsertion(insertions, + createInsertionWithDetourData(request, vEntry, pickupInsertion, fromPickupTT, pickupDetourInfo, + j)); + } } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/extensive/ExtensiveInsertionProvider.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/extensive/ExtensiveInsertionProvider.java index c58eaeb9bdc..7bcec87ac9b 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/extensive/ExtensiveInsertionProvider.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/extensive/ExtensiveInsertionProvider.java @@ -28,14 +28,14 @@ import java.util.stream.Collectors; import org.matsim.contrib.drt.optimizer.VehicleEntry; -import org.matsim.contrib.drt.optimizer.insertion.*; +import org.matsim.contrib.drt.optimizer.insertion.DetourTimeEstimator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionCostCalculator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionGenerator; import org.matsim.contrib.drt.optimizer.insertion.InsertionGenerator.Insertion; +import org.matsim.contrib.drt.optimizer.insertion.InsertionWithDetourData; import org.matsim.contrib.drt.passenger.DrtRequest; import org.matsim.contrib.drt.run.DrtConfigGroup; -import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; import org.matsim.contrib.drt.stops.StopTimeCalculator; -import org.matsim.contrib.zone.skims.TravelTimeMatrix; -import org.matsim.core.router.util.TravelTime; import com.google.common.annotations.VisibleForTesting; @@ -44,12 +44,9 @@ */ class ExtensiveInsertionProvider { static ExtensiveInsertionProvider create(DrtConfigGroup drtCfg, InsertionCostCalculator insertionCostCalculator, - TravelTimeMatrix travelTimeMatrix, TravelTime travelTime, ForkJoinPool forkJoinPool, - StopTimeCalculator stopTimeCalculator) { - var insertionParams = (ExtensiveInsertionSearchParams)drtCfg.getDrtInsertionSearchParams(); - var admissibleTimeEstimator = DetourTimeEstimator.createMatrixBasedEstimator( - insertionParams.admissibleBeelineSpeedFactor, travelTimeMatrix, travelTime); - return new ExtensiveInsertionProvider((ExtensiveInsertionSearchParams)drtCfg.getDrtInsertionSearchParams(), + ForkJoinPool forkJoinPool, StopTimeCalculator stopTimeCalculator, + DetourTimeEstimator admissibleTimeEstimator) { + return new ExtensiveInsertionProvider((ExtensiveInsertionSearchParams) drtCfg.getDrtInsertionSearchParams(), insertionCostCalculator, new InsertionGenerator(stopTimeCalculator, admissibleTimeEstimator), forkJoinPool); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/extensive/ExtensiveInsertionSearchQSimModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/extensive/ExtensiveInsertionSearchQSimModule.java index cfeaa94ec38..53153700371 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/extensive/ExtensiveInsertionSearchQSimModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/extensive/ExtensiveInsertionSearchQSimModule.java @@ -22,10 +22,10 @@ import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.optimizer.QSimScopeForkJoinPoolHolder; +import org.matsim.contrib.drt.optimizer.insertion.DetourTimeEstimator; import org.matsim.contrib.drt.optimizer.insertion.DrtInsertionSearch; import org.matsim.contrib.drt.optimizer.insertion.InsertionCostCalculator; import org.matsim.contrib.drt.run.DrtConfigGroup; -import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; import org.matsim.contrib.drt.stops.StopTimeCalculator; import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; import org.matsim.contrib.dvrp.run.DvrpModes; @@ -48,11 +48,19 @@ public ExtensiveInsertionSearchQSimModule(DrtConfigGroup drtCfg) { @Override protected void configureQSim() { + bindModal(DetourTimeEstimator.class).toProvider(modalProvider(getter -> { + var insertionParams = (ExtensiveInsertionSearchParams) drtCfg.getDrtInsertionSearchParams(); + var admissibleTimeEstimator = DetourTimeEstimator.createMatrixBasedEstimator( + insertionParams.admissibleBeelineSpeedFactor, getter.getModal(TravelTimeMatrix.class), + getter.getModal(TravelTime.class)); + return admissibleTimeEstimator; + })); + bindModal(DrtInsertionSearch.class).toProvider(modalProvider(getter -> { var insertionCostCalculator = getter.getModal(InsertionCostCalculator.class); var provider = ExtensiveInsertionProvider.create(drtCfg, insertionCostCalculator, - getter.getModal(TravelTimeMatrix.class), getter.getModal(TravelTime.class), - getter.getModal(QSimScopeForkJoinPoolHolder.class).getPool(), getter.getModal(StopTimeCalculator.class)); + getter.getModal(QSimScopeForkJoinPoolHolder.class).getPool(), + getter.getModal(StopTimeCalculator.class), getter.getModal(DetourTimeEstimator.class)); return new ExtensiveInsertionSearch(provider, getter.getModal(MultiInsertionDetourPathCalculator.class), insertionCostCalculator, getter.getModal(StopTimeCalculator.class)); })).asEagerSingleton(); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/repeatedselective/RepeatedSelectiveInsertionProvider.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/repeatedselective/RepeatedSelectiveInsertionProvider.java index aa3e2d8db06..9e2be45d6bf 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/repeatedselective/RepeatedSelectiveInsertionProvider.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/repeatedselective/RepeatedSelectiveInsertionProvider.java @@ -19,17 +19,7 @@ package org.matsim.contrib.drt.optimizer.insertion.repeatedselective; -import com.google.common.annotations.VisibleForTesting; -import org.matsim.contrib.drt.optimizer.VehicleEntry; -import org.matsim.contrib.drt.optimizer.insertion.*; -import org.matsim.contrib.drt.optimizer.insertion.BestInsertionFinder.InsertionWithCost; import static org.matsim.contrib.drt.optimizer.insertion.BestInsertionFinder.INSERTION_WITH_COST_COMPARATOR; -import org.matsim.contrib.drt.passenger.DrtRequest; -import org.matsim.contrib.drt.run.DrtConfigGroup; -import org.matsim.contrib.drt.stops.StopTimeCalculator; -import org.matsim.contrib.zone.skims.AdaptiveTravelTimeMatrix; -import org.matsim.core.router.util.TravelTime; - import static org.matsim.contrib.drt.optimizer.insertion.InsertionCostCalculator.INFEASIBLE_SOLUTION_COST; import java.util.Collection; @@ -37,11 +27,21 @@ import java.util.concurrent.ForkJoinPool; import java.util.stream.Collectors; +import org.matsim.contrib.drt.optimizer.VehicleEntry; +import org.matsim.contrib.drt.optimizer.insertion.BestInsertionFinder.InsertionWithCost; +import org.matsim.contrib.drt.optimizer.insertion.DetourTimeEstimator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionCostCalculator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionGenerator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionWithDetourData; +import org.matsim.contrib.drt.passenger.DrtRequest; +import org.matsim.contrib.drt.stops.StopTimeCalculator; + +import com.google.common.annotations.VisibleForTesting; + /** * @author steffenaxer */ class RepeatedSelectiveInsertionProvider { - private static final double SPEED_FACTOR = 1.; private final InsertionCostCalculator insertionCostCalculator; private final InsertionGenerator insertionGenerator; private final ForkJoinPool forkJoinPool; @@ -54,14 +54,11 @@ class RepeatedSelectiveInsertionProvider { this.forkJoinPool = forkJoinPool; } - public static RepeatedSelectiveInsertionProvider create( InsertionCostCalculator insertionCostCalculator, AdaptiveTravelTimeMatrix updatableTravelTimeMatrix, - TravelTime travelTime, - ForkJoinPool forkJoinPool, StopTimeCalculator stopTimeCalculator) { - var detourTimeEstimatorWithUpdatedTravelTimes = DetourTimeEstimatorWithAdaptiveTravelTimes.create( - SPEED_FACTOR, updatableTravelTimeMatrix, travelTime); - return new RepeatedSelectiveInsertionProvider(insertionCostCalculator, - new InsertionGenerator(stopTimeCalculator, detourTimeEstimatorWithUpdatedTravelTimes), forkJoinPool); - } + public static RepeatedSelectiveInsertionProvider create(InsertionCostCalculator insertionCostCalculator, + ForkJoinPool forkJoinPool, StopTimeCalculator stopTimeCalculator, DetourTimeEstimator detourTimeEstimator) { + return new RepeatedSelectiveInsertionProvider(insertionCostCalculator, + new InsertionGenerator(stopTimeCalculator, detourTimeEstimator), forkJoinPool); + } public List getInsertions(DrtRequest drtRequest, Collection vehicleEntries) { // Parallel outer stream over vehicle entries. The inner stream (flatmap) is diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/repeatedselective/RepeatedSelectiveInsertionSearchQSimModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/repeatedselective/RepeatedSelectiveInsertionSearchQSimModule.java index 2f15a6638d8..234bbed7481 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/repeatedselective/RepeatedSelectiveInsertionSearchQSimModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/repeatedselective/RepeatedSelectiveInsertionSearchQSimModule.java @@ -22,6 +22,7 @@ import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.optimizer.QSimScopeForkJoinPoolHolder; +import org.matsim.contrib.drt.optimizer.insertion.DetourTimeEstimator; import org.matsim.contrib.drt.optimizer.insertion.DrtInsertionSearch; import org.matsim.contrib.drt.optimizer.insertion.InsertionCostCalculator; import org.matsim.contrib.drt.optimizer.insertion.selective.SingleInsertionDetourPathCalculator; @@ -41,6 +42,8 @@ * @author steffenaxer */ public class RepeatedSelectiveInsertionSearchQSimModule extends AbstractDvrpModeQSimModule { + private static final double SPEED_FACTOR = 1.; + private final DrtConfigGroup drtCfg; public RepeatedSelectiveInsertionSearchQSimModule(DrtConfigGroup drtCfg) { @@ -50,11 +53,17 @@ public RepeatedSelectiveInsertionSearchQSimModule(DrtConfigGroup drtCfg) { @Override protected void configureQSim() { + bindModal(DetourTimeEstimator.class).toProvider(modalProvider(getter -> { + var detourTimeEstimatorWithUpdatedTravelTimes = DetourTimeEstimatorWithAdaptiveTravelTimes.create( + SPEED_FACTOR, getter.getModal(AdaptiveTravelTimeMatrix.class), getter.getModal(TravelTime.class)); + return detourTimeEstimatorWithUpdatedTravelTimes; + })); + addModalComponent(RepeatedSelectiveInsertionSearch.class, modalProvider(getter -> { - RepeatedSelectiveInsertionProvider provider = RepeatedSelectiveInsertionProvider.create( - getter.getModal(InsertionCostCalculator.class), getter.getModal(AdaptiveTravelTimeMatrix.class), - getter.getModal(TravelTime.class), getter.getModal(QSimScopeForkJoinPoolHolder.class).getPool(), - getter.getModal(StopTimeCalculator.class)); + RepeatedSelectiveInsertionProvider provider = RepeatedSelectiveInsertionProvider.create( + getter.getModal(InsertionCostCalculator.class), + getter.getModal(QSimScopeForkJoinPoolHolder.class).getPool(), + getter.getModal(StopTimeCalculator.class), getter.getModal(DetourTimeEstimator.class)); var insertionCostCalculator = getter.getModal(InsertionCostCalculator.class); return new RepeatedSelectiveInsertionSearch(provider, getter.getModal(SingleInsertionDetourPathCalculator.class), diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/selective/SelectiveInsertionProvider.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/selective/SelectiveInsertionProvider.java index b6efbb923f8..0988d929260 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/selective/SelectiveInsertionProvider.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/selective/SelectiveInsertionProvider.java @@ -25,13 +25,13 @@ import java.util.concurrent.ForkJoinPool; import org.matsim.contrib.drt.optimizer.VehicleEntry; -import org.matsim.contrib.drt.optimizer.insertion.*; +import org.matsim.contrib.drt.optimizer.insertion.BestInsertionFinder; +import org.matsim.contrib.drt.optimizer.insertion.DetourTimeEstimator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionCostCalculator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionGenerator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionWithDetourData; import org.matsim.contrib.drt.passenger.DrtRequest; -import org.matsim.contrib.drt.run.DrtConfigGroup; -import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; import org.matsim.contrib.drt.stops.StopTimeCalculator; -import org.matsim.contrib.zone.skims.TravelTimeMatrix; -import org.matsim.core.router.util.TravelTime; import com.google.common.annotations.VisibleForTesting; @@ -39,12 +39,9 @@ * @author michalm */ class SelectiveInsertionProvider { - public static SelectiveInsertionProvider create(DrtConfigGroup drtCfg, - InsertionCostCalculator insertionCostCalculator, TravelTimeMatrix travelTimeMatrix, TravelTime travelTime, - ForkJoinPool forkJoinPool, StopTimeCalculator stopTimeCalculator) { - var insertionParams = (SelectiveInsertionSearchParams)drtCfg.getDrtInsertionSearchParams(); - var restrictiveDetourTimeEstimator = DetourTimeEstimator.createMatrixBasedEstimator( - insertionParams.restrictiveBeelineSpeedFactor, travelTimeMatrix, travelTime); + public static SelectiveInsertionProvider create(InsertionCostCalculator insertionCostCalculator, + ForkJoinPool forkJoinPool, StopTimeCalculator stopTimeCalculator, + DetourTimeEstimator restrictiveDetourTimeEstimator) { return new SelectiveInsertionProvider(new BestInsertionFinder(insertionCostCalculator), new InsertionGenerator(stopTimeCalculator, restrictiveDetourTimeEstimator), forkJoinPool); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/selective/SelectiveInsertionSearchQSimModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/selective/SelectiveInsertionSearchQSimModule.java index f92cc82413c..7d8b045f173 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/selective/SelectiveInsertionSearchQSimModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/selective/SelectiveInsertionSearchQSimModule.java @@ -22,10 +22,10 @@ import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.optimizer.QSimScopeForkJoinPoolHolder; +import org.matsim.contrib.drt.optimizer.insertion.DetourTimeEstimator; import org.matsim.contrib.drt.optimizer.insertion.DrtInsertionSearch; import org.matsim.contrib.drt.optimizer.insertion.InsertionCostCalculator; import org.matsim.contrib.drt.run.DrtConfigGroup; -import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; import org.matsim.contrib.drt.stops.StopTimeCalculator; import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; import org.matsim.contrib.dvrp.run.DvrpModes; @@ -49,10 +49,19 @@ public SelectiveInsertionSearchQSimModule(DrtConfigGroup drtCfg) { @Override protected void configureQSim() { + bindModal(DetourTimeEstimator.class).toProvider(modalProvider(getter -> { + var insertionParams = (SelectiveInsertionSearchParams) drtCfg.getDrtInsertionSearchParams(); + var restrictiveDetourTimeEstimator = DetourTimeEstimator.createMatrixBasedEstimator( + insertionParams.restrictiveBeelineSpeedFactor, getter.getModal(TravelTimeMatrix.class), + getter.getModal(TravelTime.class)); + return restrictiveDetourTimeEstimator; + })); + addModalComponent(SelectiveInsertionSearch.class, modalProvider(getter -> { - SelectiveInsertionProvider provider = SelectiveInsertionProvider.create(drtCfg, - getter.getModal(InsertionCostCalculator.class), getter.getModal(TravelTimeMatrix.class), - getter.getModal(TravelTime.class), getter.getModal(QSimScopeForkJoinPoolHolder.class).getPool(), getter.getModal(StopTimeCalculator.class)); + SelectiveInsertionProvider provider = SelectiveInsertionProvider.create( + getter.getModal(InsertionCostCalculator.class), + getter.getModal(QSimScopeForkJoinPoolHolder.class).getPool(), + getter.getModal(StopTimeCalculator.class), getter.getModal(DetourTimeEstimator.class)); // Use 0 as the cost for the selected insertion: // - In the selective strategy, there is at most 1 insertion pre-selected. So no need to compute as there is // no other insertion to compare with. diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/DrtModeFeedforwardRebalanceModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/DrtModeFeedforwardRebalanceModule.java index 5980ec233ad..db9f1f45bce 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/DrtModeFeedforwardRebalanceModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/DrtModeFeedforwardRebalanceModule.java @@ -22,7 +22,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.analysis.zonal.DrtZoneTargetLinkSelector; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; @@ -56,7 +56,7 @@ public void install() { @Override protected void configureQSim() { bindModal(RebalancingStrategy.class).toProvider(modalProvider( - getter -> new FeedforwardRebalancingStrategy(getter.getModal(DrtZonalSystem.class), + getter -> new FeedforwardRebalancingStrategy(getter.getModal(ZoneSystem.class), getter.getModal(Fleet.class), generalParams, strategySpecificParams, getter.getModal(FeedforwardSignalHandler.class), getter.getModal(DrtZoneTargetLinkSelector.class), @@ -67,11 +67,11 @@ protected void configureQSim() { // Create PreviousIterationDepartureRecoder (this will be created only once) bindModal(FeedforwardSignalHandler.class).toProvider(modalProvider( - getter -> new FeedforwardSignalHandler(getter.getModal(DrtZonalSystem.class), strategySpecificParams, + getter -> new FeedforwardSignalHandler(getter.getModal(ZoneSystem.class), strategySpecificParams, getter.getModal(NetDepartureReplenishDemandEstimator.class)))).asEagerSingleton(); bindModal(NetDepartureReplenishDemandEstimator.class).toProvider(modalProvider( - getter -> new NetDepartureReplenishDemandEstimator(getter.getModal(DrtZonalSystem.class), drtCfg, + getter -> new NetDepartureReplenishDemandEstimator(getter.getModal(ZoneSystem.class), drtCfg, strategySpecificParams))).asEagerSingleton(); bindModal(FastHeuristicZonalRelocationCalculator.class).toProvider(modalProvider( diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FastHeuristicZonalRelocationCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FastHeuristicZonalRelocationCalculator.java index bb7a1e5b0e6..b3af6a40713 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FastHeuristicZonalRelocationCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FastHeuristicZonalRelocationCalculator.java @@ -1,11 +1,7 @@ package org.matsim.contrib.drt.optimizer.rebalancing.Feedforward; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; import org.matsim.contrib.drt.analysis.zonal.DrtZoneTargetLinkSelector; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy.Relocation; import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus; @@ -14,6 +10,10 @@ import org.matsim.contrib.drt.optimizer.rebalancing.plusOne.LinkBasedRelocationCalculator; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + public class FastHeuristicZonalRelocationCalculator implements ZonalRelocationCalculator { private final DrtZoneTargetLinkSelector drtZoneTargetLinkSelector; @@ -25,13 +25,13 @@ public FastHeuristicZonalRelocationCalculator(DrtZoneTargetLinkSelector drtZoneT @Override public List calcRelocations(List vehicleSurplus, - Map> rebalancableVehiclesPerZone) { + Map> rebalancableVehiclesPerZone) { List targetLinks = new ArrayList<>(); List selectedRebalancableVehicles = new ArrayList<>(); for (DrtZoneVehicleSurplus drtZoneVehicleSurplus : vehicleSurplus) { int surplus = drtZoneVehicleSurplus.surplus; - DrtZone zone = drtZoneVehicleSurplus.zone; + Zone zone = drtZoneVehicleSurplus.zone; if (surplus > 0) { List rebalancableVehiclesInZone = rebalancableVehiclesPerZone.get(zone); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardRebalancingStrategy.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardRebalancingStrategy.java index fa2e4d84547..3d61a38ee3a 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardRebalancingStrategy.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardRebalancingStrategy.java @@ -1,30 +1,25 @@ package org.matsim.contrib.drt.optimizer.rebalancing.Feedforward; -import static java.util.stream.Collectors.toSet; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.analysis.zonal.DrtZoneTargetLinkSelector; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingUtils; -import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus; +import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.AggregatedMinCostRelocationCalculator; import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.TransportProblem.Flow; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.Fleet; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toSet; + /** * This strategy is created based on the Feedforward Fluidic rebalancing * algorithm in AMoDeus. The algorithm send rebalancing vehicles based on the @@ -41,7 +36,7 @@ public class FeedforwardRebalancingStrategy implements RebalancingStrategy { private static final Logger log = LogManager.getLogger(FeedforwardRebalancingStrategy.class); - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final Fleet fleet; private final RebalancingParams generalParams; @@ -56,9 +51,9 @@ public class FeedforwardRebalancingStrategy implements RebalancingStrategy { private final DrtZoneTargetLinkSelector drtZoneTargetLinkSelector; private final FastHeuristicZonalRelocationCalculator fastHeuristicRelocationCalculator; - private final Map>> feedforwardSignal; + private final Map>> feedforwardSignal; - public FeedforwardRebalancingStrategy(DrtZonalSystem zonalSystem, Fleet fleet, RebalancingParams generalParams, + public FeedforwardRebalancingStrategy(ZoneSystem zonalSystem, Fleet fleet, RebalancingParams generalParams, FeedforwardRebalancingStrategyParams strategySpecificParams, FeedforwardSignalHandler feedforwardSignalHandler, DrtZoneTargetLinkSelector drtZoneTargetLinkSelector, FastHeuristicZonalRelocationCalculator fastHeuristicRelocationCalculator) { @@ -90,22 +85,22 @@ public FeedforwardRebalancingStrategy(DrtZonalSystem zonalSystem, Fleet fleet, R public List calcRelocations(Stream rebalancableVehicles, double time) { List relocationList = new ArrayList<>(); int timeBin = (int)Math.floor((time + feedforwardSignalLead) / timeBinSize); - Map> rebalancableVehiclesPerZone = RebalancingUtils + Map> rebalancableVehiclesPerZone = RebalancingUtils .groupRebalancableVehicles(zonalSystem, generalParams, rebalancableVehicles, time); - Map> actualRebalancableVehiclesPerZone = new HashMap<>(); + Map> actualRebalancableVehiclesPerZone = new HashMap<>(); // Feedback part if (feedbackSwitch) { - List vehicleSurplusList = new ArrayList<>(); - Map> soonRebalancableVehiclesPerZone = RebalancingUtils + List vehicleSurplusList = new ArrayList<>(); + Map> soonRebalancableVehiclesPerZone = RebalancingUtils .groupSoonIdleVehicles(zonalSystem, generalParams, fleet, time); - for (DrtZone zone : zonalSystem.getZones().values()) { + for (Zone zone : zonalSystem.getZones().values()) { int rebalancable = rebalancableVehiclesPerZone.getOrDefault(zone, List.of()).size(); int soonIdle = soonRebalancableVehiclesPerZone.getOrDefault(zone, List.of()).size(); int surplus = rebalancable + soonIdle - minNumVehiclesPerZone; - vehicleSurplusList.add(new DrtZoneVehicleSurplus(zone, Math.min(surplus, rebalancable))); + vehicleSurplusList.add(new AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus(zone, Math.min(surplus, rebalancable))); } relocationList.addAll( @@ -113,7 +108,7 @@ public List calcRelocations(Stream rebalancab // Connection between feedback and feedforward part Set relocatedVehicles = relocationList.stream().map(relocation -> relocation.vehicle) .collect(toSet()); - for (DrtZone zone : rebalancableVehiclesPerZone.keySet()) { + for (Zone zone : rebalancableVehiclesPerZone.keySet()) { actualRebalancableVehiclesPerZone.put(zone, rebalancableVehiclesPerZone.get(zone).stream() .filter(v -> !relocatedVehicles.contains(v)).collect(Collectors.toList())); } @@ -125,9 +120,9 @@ public List calcRelocations(Stream rebalancab // assign rebalance vehicles based on the rebalance plan if (feedforwardSignal.containsKey(timeBin)) { // Generate relocations based on the "rebalancePlanCore" - for (Flow rebalanceInfo : feedforwardSignal.get(timeBin)) { - DrtZone departureZone = rebalanceInfo.origin(); - DrtZone arrivalZone = rebalanceInfo.destination(); + for (Flow rebalanceInfo : feedforwardSignal.get(timeBin)) { + Zone departureZone = rebalanceInfo.origin(); + Zone arrivalZone = rebalanceInfo.destination(); int vehicleToSend = (int) Math.floor(scaling * rebalanceInfo.amount() + rnd.nextDouble()); // Note: we use probability to solve the problem of non-integer value of // vehileToSend after scaling. diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardSignalHandler.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardSignalHandler.java index d670f9be2ec..a8557441636 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardSignalHandler.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardSignalHandler.java @@ -1,16 +1,9 @@ package org.matsim.contrib.drt.optimizer.rebalancing.Feedforward; -import static java.util.stream.Collectors.toList; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.ToDoubleFunction; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.NetDepartureReplenishDemandEstimator; import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus; import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.TransportProblem; @@ -18,10 +11,17 @@ import org.matsim.core.controler.events.IterationStartsEvent; import org.matsim.core.controler.listener.IterationStartsListener; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.ToDoubleFunction; + +import static java.util.stream.Collectors.toList; + public class FeedforwardSignalHandler implements IterationStartsListener { private static final Logger log = LogManager.getLogger(FeedforwardSignalHandler.class); - private final DrtZonalSystem zonalSystem; - private final Map>> feedforwardSignal = new HashMap<>(); + private final ZoneSystem zonalSystem; + private final Map>> feedforwardSignal = new HashMap<>(); private final int timeBinSize; private final NetDepartureReplenishDemandEstimator netDepartureReplenishDemandEstimator; @@ -30,7 +30,7 @@ public class FeedforwardSignalHandler implements IterationStartsListener { /** * Constructor */ - public FeedforwardSignalHandler(DrtZonalSystem zonalSystem, + public FeedforwardSignalHandler(ZoneSystem zonalSystem, FeedforwardRebalancingStrategyParams strategySpecificParams, NetDepartureReplenishDemandEstimator netDepartureReplenishDemandEstimator) { this.zonalSystem = zonalSystem; @@ -45,7 +45,7 @@ private void calculateFeedforwardSignal() { int numOfTimeBin = simulationEndTime * 3600 / timeBinSize; log.info("Start calculating rebalnace plan now"); for (int t = 0; t < numOfTimeBin; t++) { - ToDoubleFunction netDepartureInputFunction = netDepartureReplenishDemandEstimator.getExpectedDemandForTimeBin(t); + ToDoubleFunction netDepartureInputFunction = netDepartureReplenishDemandEstimator.getExpectedDemandForTimeBin(t); List vehicleSurpluses = zonalSystem.getZones() .values() .stream() @@ -59,7 +59,7 @@ private void calculateFeedforwardSignal() { log.info("Rebalance plan calculation is now complete! "); } - public Map>> getFeedforwardSignal() { + public Map>> getFeedforwardSignal() { return feedforwardSignal; } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingModule.java index b9c008bc3a1..ef148776efd 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingModule.java @@ -46,7 +46,6 @@ public RebalancingModule(DrtConfigGroup drtCfg) { public void install() { if (drtCfg.getRebalancingParams().isPresent()) { RebalancingParams rebalancingParams = drtCfg.getRebalancingParams().get(); - install(new DrtModeZonalSystemModule(drtCfg)); if (rebalancingParams.getRebalancingStrategyParams() instanceof MinCostFlowRebalancingStrategyParams) { install(new DrtModeMinCostFlowRebalancingModule(drtCfg)); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingUtils.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingUtils.java index da0a741d5e0..8584026e706 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingUtils.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingUtils.java @@ -26,9 +26,11 @@ import java.util.Map; import java.util.stream.Stream; +import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneImpl; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.Fleet; import org.matsim.contrib.dvrp.schedule.Schedule; @@ -40,14 +42,14 @@ * @author Michal Maciejewski (michalm) */ public class RebalancingUtils { - public static Map> groupRebalancableVehicles(DrtZonalSystem zonalSystem, - RebalancingParams params, Stream rebalancableVehicles, double time) { - Map> rebalancableVehiclesPerZone = new HashMap<>(); + public static Map> groupRebalancableVehicles(ZoneSystem zonalSystem, + RebalancingParams params, Stream rebalancableVehicles, double time) { + Map> rebalancableVehiclesPerZone = new HashMap<>(); rebalancableVehicles.filter(v -> v.getServiceEndTime() > time + params.minServiceTime).forEach(v -> { Link link = ((StayTask)v.getSchedule().getCurrentTask()).getLink(); - DrtZone zone = zonalSystem.getZoneForLinkId(link.getId()); + Zone zone = zonalSystem.getZoneForLinkId(link.getId()); if (zone == null) { - zone = DrtZone.createDummyZone("single-vehicle-zone-" + v.getId(), List.of(link), + zone = ZoneImpl.createDummyZone(Id.create("single-vehicle-zone-" + v.getId(), Zone.class), List.of(link), link.getToNode().getCoord()); } rebalancableVehiclesPerZone.computeIfAbsent(zone, z -> new ArrayList<>()).add(v); @@ -56,16 +58,16 @@ public static Map> groupRebalancableVehicles(DrtZonal } // also include vehicles being right now relocated or recharged - public static Map> groupSoonIdleVehicles(DrtZonalSystem zonalSystem, + public static Map> groupSoonIdleVehicles(ZoneSystem zonalSystem, RebalancingParams params, Fleet fleet, double time) { - Map> soonIdleVehiclesPerZone = new HashMap<>(); + Map> soonIdleVehiclesPerZone = new HashMap<>(); for (DvrpVehicle v : fleet.getVehicles().values()) { Schedule s = v.getSchedule(); StayTask stayTask = (StayTask)Schedules.getLastTask(s); if (stayTask.getStatus() == Task.TaskStatus.PLANNED && stayTask.getBeginTime() < time + params.maxTimeBeforeIdle && v.getServiceEndTime() > time + params.minServiceTime) { - DrtZone zone = zonalSystem.getZoneForLinkId(stayTask.getLink().getId()); + Zone zone = zonalSystem.getZoneForLinkId(stayTask.getLink().getId()); if (zone != null) { soonIdleVehiclesPerZone.computeIfAbsent(zone, z -> new ArrayList<>()).add(v); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/NetDepartureReplenishDemandEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/NetDepartureReplenishDemandEstimator.java index 2529a02b8d3..cc1c0b41dd5 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/NetDepartureReplenishDemandEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/NetDepartureReplenishDemandEstimator.java @@ -1,13 +1,8 @@ package org.matsim.contrib.drt.optimizer.rebalancing.demandestimator; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.function.ToDoubleFunction; - import org.matsim.api.core.v01.Id; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.optimizer.rebalancing.Feedforward.FeedforwardRebalancingStrategyParams; import org.matsim.contrib.drt.passenger.events.DrtRequestSubmittedEvent; import org.matsim.contrib.drt.passenger.events.DrtRequestSubmittedEventHandler; @@ -18,20 +13,25 @@ import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEvent; import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEventHandler; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.ToDoubleFunction; + public class NetDepartureReplenishDemandEstimator implements PassengerRequestScheduledEventHandler, DrtRequestSubmittedEventHandler, PassengerRequestRejectedEventHandler { - private record Trip(int timeBin, DrtZone fromZone, DrtZone toZone) { + private record Trip(int timeBin, Zone fromZone, Zone toZone) { } - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final String mode; private final int timeBinSize; - private final Map> currentZoneNetDepartureMap = new HashMap<>(); - private final Map> previousZoneNetDepartureMap = new HashMap<>(); + private final Map> currentZoneNetDepartureMap = new HashMap<>(); + private final Map> previousZoneNetDepartureMap = new HashMap<>(); private final Map, Trip> potentialDrtTripsMap = new HashMap<>(); - public NetDepartureReplenishDemandEstimator(DrtZonalSystem zonalSystem, DrtConfigGroup drtCfg, + public NetDepartureReplenishDemandEstimator(ZoneSystem zonalSystem, DrtConfigGroup drtCfg, FeedforwardRebalancingStrategyParams strategySpecificParams) { this.zonalSystem = zonalSystem; mode = drtCfg.getMode(); @@ -52,8 +52,8 @@ public void handleEvent(DrtRequestSubmittedEvent event) { if (event.getMode().equals(mode)) { // At the submission time, this is only a potential trip. int timeBin = (int)Math.floor(event.getTime() / timeBinSize); - DrtZone departureZoneId = zonalSystem.getZoneForLinkId(event.getFromLinkId()); - DrtZone arrivalZoneId = zonalSystem.getZoneForLinkId(event.getToLinkId()); + Zone departureZoneId = zonalSystem.getZoneForLinkId(event.getFromLinkId()); + Zone arrivalZoneId = zonalSystem.getZoneForLinkId(event.getToLinkId()); potentialDrtTripsMap.put(event.getRequestId(), new Trip(timeBin, departureZoneId, arrivalZoneId)); } } @@ -78,7 +78,7 @@ public void updateForNextIteration() { potentialDrtTripsMap.clear(); } - public ToDoubleFunction getExpectedDemandForTimeBin(int timeBin) { + public ToDoubleFunction getExpectedDemandForTimeBin(int timeBin) { var expectedDemandForTimeBin = previousZoneNetDepartureMap.getOrDefault(timeBin, Collections.emptyMap()); return zone -> expectedDemandForTimeBin.getOrDefault(zone, 0); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimator.java index 003c1649507..f6d2f17745d 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimator.java @@ -23,20 +23,19 @@ */ package org.matsim.contrib.drt.optimizer.rebalancing.demandestimator; -import java.util.HashMap; -import java.util.Map; -import java.util.function.ToDoubleFunction; - +import com.google.common.base.Preconditions; import org.apache.commons.lang3.mutable.MutableInt; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.events.PersonDepartureEvent; import org.matsim.api.core.v01.events.handler.PersonDepartureEventHandler; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.run.DrtConfigGroup; -import com.google.common.base.Preconditions; +import java.util.HashMap; +import java.util.Map; +import java.util.function.ToDoubleFunction; /** * Aggregates PersonDepartureEvents per iteration for the given mode and returns the numbers from the previous iteration @@ -48,13 +47,13 @@ public final class PreviousIterationDrtDemandEstimator implements ZonalDemandEstimator, PersonDepartureEventHandler { private static final Logger logger = LogManager.getLogger(PreviousIterationDrtDemandEstimator.class); - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final String mode; private final int timeBinSize; - private Map> currentIterationDepartures = new HashMap<>(); - private Map> previousIterationDepartures = new HashMap<>(); + private Map> currentIterationDepartures = new HashMap<>(); + private Map> previousIterationDepartures = new HashMap<>(); - public PreviousIterationDrtDemandEstimator(DrtZonalSystem zonalSystem, DrtConfigGroup drtCfg, + public PreviousIterationDrtDemandEstimator(ZoneSystem zonalSystem, DrtConfigGroup drtCfg, int demandEstimationPeriod) { this.zonalSystem = zonalSystem; mode = drtCfg.getMode(); @@ -70,7 +69,7 @@ public void reset(int iteration) { @Override public void handleEvent(PersonDepartureEvent event) { if (event.getLegMode().equals(mode)) { - DrtZone zone = zonalSystem.getZoneForLinkId(event.getLinkId()); + Zone zone = zonalSystem.getZoneForLinkId(event.getLinkId()); if (zone == null) { //might be that somebody walks into the service area or that service area is larger/different than DrtZonalSystem... logger.warn("No zone found for linkId " + event.getLinkId().toString()); @@ -87,10 +86,10 @@ public void handleEvent(PersonDepartureEvent event) { private static final MutableInt ZERO = new MutableInt(0); @Override - public ToDoubleFunction getExpectedDemand(double fromTime, double estimationPeriod) { + public ToDoubleFunction getExpectedDemand(double fromTime, double estimationPeriod) { Preconditions.checkArgument(estimationPeriod == timeBinSize);//TODO add more flexibility later int timeBin = getBinForTime(fromTime); - Map expectedDemandForTimeBin = previousIterationDepartures.getOrDefault(timeBin, Map.of()); + Map expectedDemandForTimeBin = previousIterationDepartures.getOrDefault(timeBin, Map.of()); return zone -> expectedDemandForTimeBin.getOrDefault(zone, ZERO).intValue(); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/ZonalDemandEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/ZonalDemandEstimator.java index 42d75e30f6e..9faee8637bd 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/ZonalDemandEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/ZonalDemandEstimator.java @@ -23,14 +23,14 @@ */ package org.matsim.contrib.drt.optimizer.rebalancing.demandestimator; -import java.util.function.ToDoubleFunction; +import org.matsim.contrib.common.zones.Zone; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import java.util.function.ToDoubleFunction; /** * @author jbischoff * @author Michal Maciejewski (michalm) */ public interface ZonalDemandEstimator { - ToDoubleFunction getExpectedDemand(double fromTime, double estimationPeriod); + ToDoubleFunction getExpectedDemand(double fromTime, double estimationPeriod); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/AggregatedMinCostRelocationCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/AggregatedMinCostRelocationCalculator.java index 4a16cb05b5d..14130e4d152 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/AggregatedMinCostRelocationCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/AggregatedMinCostRelocationCalculator.java @@ -25,7 +25,7 @@ import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; import org.matsim.contrib.drt.analysis.zonal.DrtZoneTargetLinkSelector; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy.Relocation; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; @@ -39,10 +39,10 @@ */ public class AggregatedMinCostRelocationCalculator implements ZonalRelocationCalculator { public static class DrtZoneVehicleSurplus { - public final DrtZone zone; + public final Zone zone; public final int surplus; - public DrtZoneVehicleSurplus(DrtZone zone, int surplus) { + public DrtZoneVehicleSurplus(Zone zone, int surplus) { this.zone = zone; this.surplus = surplus; } @@ -56,14 +56,14 @@ public AggregatedMinCostRelocationCalculator(DrtZoneTargetLinkSelector targetLin @Override public List calcRelocations(List vehicleSurplus, - Map> rebalancableVehiclesPerZone) { + Map> rebalancableVehiclesPerZone) { return calcRelocations(rebalancableVehiclesPerZone, TransportProblem.solveForVehicleSurplus(vehicleSurplus)); } - private List calcRelocations(Map> rebalancableVehiclesPerZone, - List> flows) { + private List calcRelocations(Map> rebalancableVehiclesPerZone, + List> flows) { List relocations = new ArrayList<>(); - for (TransportProblem.Flow flow : flows) { + for (TransportProblem.Flow flow : flows) { List rebalancableVehicles = rebalancableVehiclesPerZone.get(flow.origin()); Link targetLink = targetLinkSelector.selectTargetLink(flow.destination()); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/DrtModeMinCostFlowRebalancingModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/DrtModeMinCostFlowRebalancingModule.java index d624e6a000a..eeef009b3da 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/DrtModeMinCostFlowRebalancingModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/DrtModeMinCostFlowRebalancingModule.java @@ -21,17 +21,13 @@ package org.matsim.contrib.drt.optimizer.rebalancing.mincostflow; import org.matsim.api.core.v01.population.Population; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.analysis.zonal.DrtZoneTargetLinkSelector; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.PreviousIterationDrtDemandEstimator; import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.ZonalDemandEstimator; -import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.DemandEstimatorAsTargetCalculator; -import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.EqualRebalancableVehicleDistributionTargetCalculator; -import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.EqualVehicleDensityTargetCalculator; -import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.EqualVehiclesToPopulationRatioTargetCalculator; -import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.RebalancingTargetCalculator; +import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.*; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.dvrp.fleet.Fleet; import org.matsim.contrib.dvrp.fleet.FleetSpecification; @@ -59,7 +55,7 @@ public void install() { protected void configureQSim() { bindModal(RebalancingStrategy.class).toProvider(modalProvider( getter -> new MinCostFlowRebalancingStrategy(getter.getModal(RebalancingTargetCalculator.class), - getter.getModal(DrtZonalSystem.class), getter.getModal(Fleet.class), + getter.getModal(ZoneSystem.class), getter.getModal(Fleet.class), getter.getModal(ZonalRelocationCalculator.class), params))).asEagerSingleton(); switch (strategyParams.rebalancingTargetCalculatorType) { @@ -71,19 +67,19 @@ protected void configureQSim() { case EqualRebalancableVehicleDistribution: bindModal(RebalancingTargetCalculator.class).toProvider(modalProvider(getter -> new EqualRebalancableVehicleDistributionTargetCalculator( getter.getModal(ZonalDemandEstimator.class), - getter.getModal(DrtZonalSystem.class), strategyParams.demandEstimationPeriod))).asEagerSingleton(); + getter.getModal(ZoneSystem.class), strategyParams.demandEstimationPeriod))).asEagerSingleton(); break; case EqualVehicleDensity: bindModal(RebalancingTargetCalculator.class).toProvider(modalProvider( - getter -> new EqualVehicleDensityTargetCalculator(getter.getModal(DrtZonalSystem.class), + getter -> new EqualVehicleDensityTargetCalculator(getter.getModal(ZoneSystem.class), getter.getModal(FleetSpecification.class)))).asEagerSingleton(); break; case EqualVehiclesToPopulationRatio: bindModal(RebalancingTargetCalculator.class).toProvider(modalProvider( getter -> new EqualVehiclesToPopulationRatioTargetCalculator( - getter.getModal(DrtZonalSystem.class), getter.get(Population.class), + getter.getModal(ZoneSystem.class), getter.get(Population.class), getter.getModal(FleetSpecification.class)))).asEagerSingleton(); break; @@ -101,7 +97,7 @@ protected void configureQSim() { switch (strategyParams.zonalDemandEstimatorType) { case PreviousIterationDemand: bindModal(PreviousIterationDrtDemandEstimator.class).toProvider(modalProvider( - getter -> new PreviousIterationDrtDemandEstimator(getter.getModal(DrtZonalSystem.class), drtCfg, + getter -> new PreviousIterationDrtDemandEstimator(getter.getModal(ZoneSystem.class), drtCfg, strategyParams.demandEstimationPeriod))).asEagerSingleton(); bindModal(ZonalDemandEstimator.class).to(modalKey(PreviousIterationDrtDemandEstimator.class)); addEventHandlerBinding().to(modalKey(PreviousIterationDrtDemandEstimator.class)); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategy.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategy.java index b08dcb56e01..4e06666ed05 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategy.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategy.java @@ -25,8 +25,8 @@ import java.util.function.ToDoubleFunction; import java.util.stream.Stream; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingUtils; @@ -41,13 +41,13 @@ public class MinCostFlowRebalancingStrategy implements RebalancingStrategy { private final RebalancingTargetCalculator rebalancingTargetCalculator; - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final Fleet fleet; private final ZonalRelocationCalculator relocationCalculator; private final RebalancingParams params; public MinCostFlowRebalancingStrategy(RebalancingTargetCalculator rebalancingTargetCalculator, - DrtZonalSystem zonalSystem, Fleet fleet, ZonalRelocationCalculator relocationCalculator, + ZoneSystem zonalSystem, Fleet fleet, ZonalRelocationCalculator relocationCalculator, RebalancingParams params) { this.rebalancingTargetCalculator = rebalancingTargetCalculator; this.zonalSystem = zonalSystem; @@ -58,20 +58,20 @@ public MinCostFlowRebalancingStrategy(RebalancingTargetCalculator rebalancingTar @Override public List calcRelocations(Stream rebalancableVehicles, double time) { - Map> rebalancableVehiclesPerZone = RebalancingUtils.groupRebalancableVehicles( + Map> rebalancableVehiclesPerZone = RebalancingUtils.groupRebalancableVehicles( zonalSystem, params, rebalancableVehicles, time); if (rebalancableVehiclesPerZone.isEmpty()) { return List.of(); } - Map> soonIdleVehiclesPerZone = RebalancingUtils.groupSoonIdleVehicles(zonalSystem, + Map> soonIdleVehiclesPerZone = RebalancingUtils.groupSoonIdleVehicles(zonalSystem, params, fleet, time); return calculateMinCostRelocations(time, rebalancableVehiclesPerZone, soonIdleVehiclesPerZone); } private List calculateMinCostRelocations(double time, - Map> rebalancableVehiclesPerZone, - Map> soonIdleVehiclesPerZone) { - ToDoubleFunction targetFunction = rebalancingTargetCalculator.calculate(time, + Map> rebalancableVehiclesPerZone, + Map> soonIdleVehiclesPerZone) { + ToDoubleFunction targetFunction = rebalancingTargetCalculator.calculate(time, rebalancableVehiclesPerZone); var minCostFlowRebalancingStrategyParams = (MinCostFlowRebalancingStrategyParams)params.getRebalancingStrategyParams(); double alpha = minCostFlowRebalancingStrategyParams.targetAlpha; diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/TransportProblem.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/TransportProblem.java index b48f0f2e635..ca019b03ea2 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/TransportProblem.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/TransportProblem.java @@ -26,19 +26,19 @@ import org.apache.commons.lang3.tuple.Pair; import org.matsim.contrib.common.util.DistanceUtils; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; import graphs.flows.MinCostFlow; import graphs.flows.MinCostFlow.Edge; +import org.matsim.contrib.common.zones.Zone; /** * @author michalm */ public class TransportProblem { - public static List> solveForVehicleSurplus( + public static List> solveForVehicleSurplus( List vehicleSurplus) { - List> supply = new ArrayList<>(); - List> demand = new ArrayList<>(); + List> supply = new ArrayList<>(); + List> demand = new ArrayList<>(); for (AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus s : vehicleSurplus) { if (s.surplus > 0) { supply.add(Pair.of(s.zone, s.surplus)); @@ -46,10 +46,10 @@ public static List> solveForVehicleSurplus( demand.add(Pair.of(s.zone, -s.surplus)); } } - return new TransportProblem(TransportProblem::calcStraightLineDistance).solve(supply, demand); + return new TransportProblem(TransportProblem::calcStraightLineDistance).solve(supply, demand); } - private static int calcStraightLineDistance(DrtZone zone1, DrtZone zone2) { + private static int calcStraightLineDistance(Zone zone1, Zone zone2) { return (int)DistanceUtils.calculateDistance(zone1.getCentroid(), zone2.getCentroid()); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/ZonalRelocationCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/ZonalRelocationCalculator.java index 8ccfd234b23..a01e6afbfae 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/ZonalRelocationCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/ZonalRelocationCalculator.java @@ -18,14 +18,14 @@ package org.matsim.contrib.drt.optimizer.rebalancing.mincostflow; -import java.util.List; -import java.util.Map; - -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy.Relocation; import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; +import java.util.List; +import java.util.Map; + /** * @author michalm */ @@ -36,5 +36,5 @@ public interface ZonalRelocationCalculator { * @return vehicle relocations */ List calcRelocations(List vehicleSurplus, - Map> rebalancableVehiclesPerZone); + Map> rebalancableVehiclesPerZone); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/DemandEstimatorAsTargetCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/DemandEstimatorAsTargetCalculator.java index 611299b55bf..1ce22dd43e7 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/DemandEstimatorAsTargetCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/DemandEstimatorAsTargetCalculator.java @@ -20,14 +20,14 @@ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.ZonalDemandEstimator; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; + import java.util.List; import java.util.Map; import java.util.function.ToDoubleFunction; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; -import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.ZonalDemandEstimator; -import org.matsim.contrib.dvrp.fleet.DvrpVehicle; - /** * @author michalm */ @@ -41,8 +41,8 @@ public DemandEstimatorAsTargetCalculator(ZonalDemandEstimator demandEstimator, d } @Override - public ToDoubleFunction calculate(double time, - Map> rebalancableVehiclesPerZone) { + public ToDoubleFunction calculate(double time, + Map> rebalancableVehiclesPerZone) { return demandEstimator.getExpectedDemand(time, demandEstimationPeriod); } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualRebalancableVehicleDistributionTargetCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualRebalancableVehicleDistributionTargetCalculator.java index c3975986dce..e03314a8d07 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualRebalancableVehicleDistributionTargetCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualRebalancableVehicleDistributionTargetCalculator.java @@ -20,19 +20,19 @@ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; -import static java.util.stream.Collectors.toSet; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.ZonalDemandEstimator; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.ToDoubleFunction; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; -import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.ZonalDemandEstimator; -import org.matsim.contrib.dvrp.fleet.DvrpVehicle; +import static java.util.stream.Collectors.toSet; /** * TODO add some description @@ -43,24 +43,24 @@ public class EqualRebalancableVehicleDistributionTargetCalculator implements Reb private static final Logger log = LogManager.getLogger(EqualRebalancableVehicleDistributionTargetCalculator.class); private final ZonalDemandEstimator demandEstimator; - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final double demandEstimationPeriod; public EqualRebalancableVehicleDistributionTargetCalculator(ZonalDemandEstimator demandEstimator, - DrtZonalSystem zonalSystem, double demandEstimationPeriod) { + ZoneSystem zonalSystem, double demandEstimationPeriod) { this.demandEstimator = demandEstimator; this.zonalSystem = zonalSystem; this.demandEstimationPeriod = demandEstimationPeriod; } @Override - public ToDoubleFunction calculate(double time, - Map> rebalancableVehiclesPerZone) { + public ToDoubleFunction calculate(double time, + Map> rebalancableVehiclesPerZone) { int numAvailableVehicles = rebalancableVehiclesPerZone.values().stream().mapToInt(List::size).sum(); - ToDoubleFunction currentDemandEstimator = demandEstimator.getExpectedDemand(time, + ToDoubleFunction currentDemandEstimator = demandEstimator.getExpectedDemand(time, demandEstimationPeriod); - Set activeZones = zonalSystem.getZones() + Set activeZones = zonalSystem.getZones() .values() .stream() .filter(zone -> currentDemandEstimator.applyAsDouble(zone) > 0) diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculator.java index 03b6b8879f4..64a0e6bd0bc 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculator.java @@ -23,19 +23,18 @@ */ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.ToDoubleFunction; - +import com.google.common.base.Preconditions; import jakarta.validation.constraints.NotNull; - -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdMap; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.FleetSpecification; -import com.google.common.base.Preconditions; +import java.util.List; +import java.util.Map; +import java.util.function.ToDoubleFunction; /** * This class does not really calculate the expected demand but aims to @@ -46,32 +45,32 @@ */ public final class EqualVehicleDensityTargetCalculator implements RebalancingTargetCalculator { - private final Map zoneAreaShares = new HashMap<>(); + private final Map, Double> zoneAreaShares = new IdMap<>(Zone.class); private final FleetSpecification fleetSpecification; - public EqualVehicleDensityTargetCalculator(@NotNull DrtZonalSystem zonalSystem, + public EqualVehicleDensityTargetCalculator(@NotNull ZoneSystem zonalSystem, @NotNull FleetSpecification fleetSpecification) { initAreaShareMap(zonalSystem); this.fleetSpecification = fleetSpecification; } @Override - public ToDoubleFunction calculate(double time, - Map> rebalancableVehiclesPerZone) { - return zone -> zoneAreaShares.getOrDefault(zone, 0.) * fleetSpecification.getVehicleSpecifications().size(); + public ToDoubleFunction calculate(double time, + Map> rebalancableVehiclesPerZone) { + return zone -> zoneAreaShares.getOrDefault(zone.getId(), 0.) * fleetSpecification.getVehicleSpecifications().size(); } - private void initAreaShareMap(DrtZonalSystem zonalSystem) { + private void initAreaShareMap(ZoneSystem zonalSystem) { double areaSum = zonalSystem.getZones() .values() .stream() .mapToDouble(z -> z.getPreparedGeometry().getGeometry().getArea()) .sum(); - for (DrtZone zone : zonalSystem.getZones().values()) { + for (Zone zone : zonalSystem.getZones().values()) { double areaShare = zone.getPreparedGeometry().getGeometry().getArea() / areaSum; Preconditions.checkState(areaShare >= 0. && areaShare <= 1.); - zoneAreaShares.put(zone, areaShare); + zoneAreaShares.put(zone.getId(), areaShare); } } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculator.java index 51c23a64db5..7968af6e705 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculator.java @@ -23,26 +23,25 @@ */ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; -import static java.util.stream.Collectors.collectingAndThen; -import static java.util.stream.Collectors.counting; - -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.ToDoubleFunction; -import java.util.stream.Collectors; - import jakarta.validation.constraints.NotNull; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Population; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.FleetSpecification; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.ToDoubleFunction; +import java.util.stream.Collectors; + +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.counting; + /** * Calculates population size per zone by counting first activites per zone in the selected plans. * Returns the share of population of the total population inside the drt service area for the given zone multiplied with the overall fleet size. @@ -55,11 +54,11 @@ public final class EqualVehiclesToPopulationRatioTargetCalculator implements Reb private static final Logger log = LogManager.getLogger(EqualVehiclesToPopulationRatioTargetCalculator.class); private final int fleetSize; - private final Map activitiesPerZone; + private final Map activitiesPerZone; private final int totalNrActivities; - public EqualVehiclesToPopulationRatioTargetCalculator(DrtZonalSystem zonalSystem, Population population, - @NotNull FleetSpecification fleetSpecification) { + public EqualVehiclesToPopulationRatioTargetCalculator(ZoneSystem zonalSystem, Population population, + @NotNull FleetSpecification fleetSpecification) { log.debug("nr of zones: " + zonalSystem.getZones().size() + "\t nr of persons = " + population.getPersons() .size()); fleetSize = fleetSpecification.getVehicleSpecifications().size(); @@ -68,7 +67,7 @@ public EqualVehiclesToPopulationRatioTargetCalculator(DrtZonalSystem zonalSystem log.debug("nr of persons that have their first activity inside the service area = " + this.totalNrActivities); } - private Map countFirstActsPerZone(DrtZonalSystem zonalSystem, Population population) { + private Map countFirstActsPerZone(ZoneSystem zonalSystem, Population population) { return population.getPersons() .values() .stream() @@ -79,8 +78,8 @@ private Map countFirstActsPerZone(DrtZonalSystem zonalSystem, } @Override - public ToDoubleFunction calculate(double time, - Map> rebalancableVehiclesPerZone) { + public ToDoubleFunction calculate(double time, + Map> rebalancableVehiclesPerZone) { if (totalNrActivities == 0) { return zoneId -> 0; } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/RebalancingTargetCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/RebalancingTargetCalculator.java index e7b2e36d1c4..c89ac8677e6 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/RebalancingTargetCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/RebalancingTargetCalculator.java @@ -20,16 +20,16 @@ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; + import java.util.List; import java.util.Map; import java.util.function.ToDoubleFunction; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; -import org.matsim.contrib.dvrp.fleet.DvrpVehicle; - /** * @author Michal Maciejewski (michalm) */ public interface RebalancingTargetCalculator { - ToDoubleFunction calculate(double time, Map> rebalancableVehiclesPerZone); + ToDoubleFunction calculate(double time, Map> rebalancableVehiclesPerZone); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/MaxDetourOfferAcceptor.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DefaultOfferAcceptor.java similarity index 62% rename from contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/MaxDetourOfferAcceptor.java rename to contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DefaultOfferAcceptor.java index fe2dfb25834..9eeed624139 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/MaxDetourOfferAcceptor.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DefaultOfferAcceptor.java @@ -2,13 +2,24 @@ import java.util.Optional; -public class MaxDetourOfferAcceptor implements DrtOfferAcceptor{ +public class DefaultOfferAcceptor implements DrtOfferAcceptor{ private final double maxAllowedPickupDelay; - public MaxDetourOfferAcceptor(double maxAllowedPickupDelay) { + /** + * Generate Default offer acceptor with max allowed pickup delay. + * @param maxAllowedPickupDelay: maximum allowed delay since the initially assigned pickup time. + */ + public DefaultOfferAcceptor(double maxAllowedPickupDelay) { this.maxAllowedPickupDelay = maxAllowedPickupDelay; } + /** + * Generate Default offer acceptor. + */ + public DefaultOfferAcceptor() { + this.maxAllowedPickupDelay = Double.POSITIVE_INFINITY; + } + @Override public Optional acceptDrtOffer(DrtRequest request, double departureTime, double arrivalTime) { double updatedLatestStartTime = Math.min(departureTime diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DrtOfferAcceptor.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DrtOfferAcceptor.java index 4118169fe70..68ab4751459 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DrtOfferAcceptor.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DrtOfferAcceptor.java @@ -26,9 +26,6 @@ * @author Michal Maciejewski (michalm) */ public interface DrtOfferAcceptor { - DrtOfferAcceptor DEFAULT_ACCEPTOR = (request, departureTime, arrivalTime) -> Optional.of( - AcceptedDrtRequest.createFromOriginalRequest(request)); - /** * @param request drt request * @param departureTime offered departure time for the new request 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 b2abd66b16f..747e1ae77f2 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 @@ -68,7 +68,9 @@ public PrebookingStopActivity(PassengerHandler passengerHandler, DynAgent driver @Override protected boolean isLastStep(double now) { - return updatePickupRequests(now) && processDropoffRequests(now) && now >= endTime.get(); + boolean pickupsReady = updatePickupRequests(now); + boolean dropoffsReady = updateDropoffRequests(now); + return pickupsReady && dropoffsReady && now >= endTime.get(); } @Override @@ -83,10 +85,10 @@ private void initDropoffRequests(double now) { leaveTimes.put(request.getId(), leaveTime); } - processDropoffRequests(now); + updateDropoffRequests(now); } - private boolean processDropoffRequests(double now) { + private boolean updateDropoffRequests(double now) { var iterator = leaveTimes.entrySet().iterator(); while (iterator.hasNext()) { diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtConfigGroup.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtConfigGroup.java index 7fb685bd92e..93597ab6271 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtConfigGroup.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtConfigGroup.java @@ -133,7 +133,7 @@ public static DrtConfigGroup getSingleModeDrtConfig(Config config) { @Comment( "Defines the maximum delay allowed from the initial scheduled pick up time. Once the initial pickup time is offered, the latest promised" + "pickup time is calculated based on initial scheduled pickup time + maxAllowedPickupDelay. " - + "By default, this limit is disabled. If enabled, a value between 120 and 240 is a good choice.") + + "By default, this limit is disabled. If enabled, a value between 0 and 240 is a good choice.") @PositiveOrZero public double maxAllowedPickupDelay = Double.POSITIVE_INFINITY;// [s] @@ -323,6 +323,12 @@ protected void checkConsistency(Config config) { if (useModeFilteredSubnetwork) { DvrpModeRoutingNetworkModule.checkUseModeFilteredSubnetworkAllowed(config, mode); } + + if ((maxDetourAlpha != Double.POSITIVE_INFINITY && maxDetourBeta != Double.POSITIVE_INFINITY) || maxAbsoluteDetour != Double.POSITIVE_INFINITY) { + Verify.verify(maxAllowedPickupDelay != Double.POSITIVE_INFINITY, "Detour constraints are activated, " + + "maxAllowedPickupDelay must be specified! A value between 0 and 240 seconds can be a good choice for maxAllowedPickupDelay."); + } + } @Override diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtModeModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtModeModule.java index a0cb1fc007c..f667841b104 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtModeModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtModeModule.java @@ -25,6 +25,7 @@ import com.google.inject.name.Names; import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; +import org.matsim.contrib.drt.analysis.zonal.DrtModeZonalSystemModule; import org.matsim.contrib.drt.fare.DrtFareHandler; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingModule; import org.matsim.contrib.drt.prebooking.analysis.PrebookingModeAnalysisModule; @@ -65,6 +66,7 @@ public void install() { null : ConfigGroup.getInputFileURL(getConfig().getContext(), drtCfg.vehiclesFile), drtCfg.changeStartLinkToLastLinkInSchedule)); + install(new DrtModeZonalSystemModule(drtCfg)); install(new RebalancingModule(drtCfg)); install(new DrtModeRoutingModule(drtCfg)); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java index a8551b6ab9b..8b3755ba082 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java @@ -313,8 +313,13 @@ private DrtStopTask insertPickup(AcceptedDrtRequest request, InsertionWithDetour // prebooking case when we are already at the stop location, but next stop task happens in the future Task afterPickupTask = insertWait(vehicleEntry.vehicle, pickupStopTask, nextBeginTime); - scheduleTimingUpdater.updateTimingsStartingFromTaskIdx(vehicleEntry.vehicle, afterPickupTask.getTaskIdx() + 1, - afterPickupTask.getEndTime()); + // update timings + if (pickupIdx != dropoffIdx) { + // update schedule when inserting the dropoff, otherwise we will illegally shift + // the begin time of a following prebooked stop if there is one + scheduleTimingUpdater.updateTimingsStartingFromTaskIdx(vehicleEntry.vehicle, afterPickupTask.getTaskIdx() + 1, + afterPickupTask.getEndTime()); + } } else { VrpPathWithTravelData vrpPath = VrpPaths.createPath(request.getFromLink(), toLink, pickupStopTask.getEndTime(), detourData.detourFromPickup, travelTime); @@ -323,9 +328,12 @@ private DrtStopTask insertPickup(AcceptedDrtRequest request, InsertionWithDetour Task afterPickupTask = insertDriveWithWait(vehicleEntry.vehicle, pickupStopTask, vrpPath, nextBeginTime); // update timings - // TODO should be enough to update the timeline only till dropoffIdx... - scheduleTimingUpdater.updateTimingsStartingFromTaskIdx(vehicleEntry.vehicle, afterPickupTask.getTaskIdx() + 1, - afterPickupTask.getEndTime()); + if (pickupIdx != dropoffIdx) { + // update schedule when inserting the dropoff, otherwise we will illegally shift + // the begin time of a following prebooked stop if there is one + scheduleTimingUpdater.updateTimingsStartingFromTaskIdx(vehicleEntry.vehicle, afterPickupTask.getTaskIdx() + 1, + afterPickupTask.getEndTime()); + } } return pickupStopTask; diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemTest.java index a49cc10a3d0..e17d38c7901 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemTest.java @@ -20,11 +20,7 @@ package org.matsim.contrib.drt.analysis.zonal; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtilsTest.createNetwork; -import static org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem.createFromPreparedGeometries; - +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; @@ -33,11 +29,16 @@ import org.locationtech.jts.geom.prep.PreparedGeometryFactory; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.common.zones.ZoneSystem; import java.util.ArrayList; import java.util.List; import java.util.Map; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.matsim.contrib.common.zones.ZoneSystemUtils.createFromPreparedGeometries; +import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtilsTest.createNetwork; + /** * @author Michal Maciejewski (michalm) */ @@ -45,16 +46,16 @@ public class DrtZonalSystemTest { @Test void test_cellSize100() { - DrtZonalSystem drtZonalSystem = createFromPreparedGeometries(createNetwork(), + ZoneSystem drtZonalSystem = createFromPreparedGeometries(createNetwork(), DrtGridUtils.createGridFromNetwork(createNetwork(), 100)); - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId("ab")).getId()).isEqualTo("10"); + Assertions.assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId("ab")).getId().toString()).isEqualTo("10"); } @Test void test_cellSize700() { - DrtZonalSystem drtZonalSystem = createFromPreparedGeometries(createNetwork(), + ZoneSystem drtZonalSystem = createFromPreparedGeometries(createNetwork(), DrtGridUtils.createGridFromNetwork(createNetwork(), 700)); - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId("ab")).getId()).isEqualTo("2"); + Assertions.assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId("ab")).getId().toString()).isEqualTo("2"); } @Test @@ -62,15 +63,15 @@ void test_gridWithinServiceArea(){ Coordinate min = new Coordinate(-500, 500); Coordinate max = new Coordinate(1500, 1500); List serviceArea = createServiceArea(min,max); - Map grid = DrtGridUtils.createGridFromNetworkWithinServiceArea(createNetwork(), 100, serviceArea); - DrtZonalSystem zonalSystem = createFromPreparedGeometries(createNetwork(), + Map grid = DrtGridUtils.filterGridWithinServiceArea(DrtGridUtils.createGridFromNetwork(createNetwork(), 100), serviceArea); + ZoneSystem zonalSystem = createFromPreparedGeometries(createNetwork(), grid); assertEquals(2, zonalSystem.getZones().size()); //link 'da' is outside of the service area Id id = Id.createLinkId("da"); - assertThat(zonalSystem.getZoneForLinkId(id) == null); + Assertions.assertThat(zonalSystem.getZoneForLinkId(id)).isNull(); } @Test @@ -78,8 +79,8 @@ void test_noZonesWithoutLinks(){ Coordinate min = new Coordinate(1500, 1500); Coordinate max = new Coordinate(2500, 2500); List serviceArea = createServiceArea(min,max); - Map grid = DrtGridUtils.createGridFromNetworkWithinServiceArea(createNetwork(), 100, serviceArea); - DrtZonalSystem zonalSystem = createFromPreparedGeometries(createNetwork(), + Map grid = DrtGridUtils.filterGridWithinServiceArea(DrtGridUtils.createGridFromNetwork(createNetwork(), 100), serviceArea); + ZoneSystem zonalSystem = createFromPreparedGeometries(createNetwork(), grid); //service area is off the network - so we should have 0 zones.. diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelectorTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelectorTest.java index fa38b72749b..f77e5fa57a3 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelectorTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelectorTest.java @@ -30,6 +30,8 @@ import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneImpl; import org.matsim.testcases.fakes.FakeLink; import org.mockito.ArgumentCaptor; @@ -45,7 +47,7 @@ public class RandomDrtZoneTargetLinkSelectorTest { @Test void testSelectTargetLink_fourLinks() { - DrtZone zone = DrtZone.createDummyZone("zone", List.of(link0, link1, link2, link3), null); + Zone zone = ZoneImpl.createDummyZone(Id.create("zone", Zone.class), List.of(link0, link1, link2, link3), null); //fake random sequence IntUnaryOperator random = mock(IntUnaryOperator.class); diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/MaxDetourConstraintTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/MaxDetourConstraintTest.java index 895f3a096f2..83ffce4ddb5 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/MaxDetourConstraintTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/MaxDetourConstraintTest.java @@ -2,12 +2,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; -import org.matsim.contrib.drt.passenger.MaxDetourOfferAcceptor; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.run.DrtControlerCreator; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; -import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; @@ -29,7 +26,6 @@ public void testMaxDetourConstraint() { URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_drt_config.xml"); Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(), new OTFVisConfigGroup()); - MultiModeDrtConfigGroup multiModeDrtConfigGroup = MultiModeDrtConfigGroup.get(config); DrtConfigGroup drtConfigGroup = DrtConfigGroup.getSingleModeDrtConfig(config); // Max wait time @@ -50,15 +46,6 @@ public void testMaxDetourConstraint() { Controler controler = DrtControlerCreator.createControler(config, false); - for (DrtConfigGroup drtCfg : multiModeDrtConfigGroup.getModalElements()) { - controler.addOverridingQSimModule(new AbstractDvrpModeQSimModule(drtCfg.mode) { - @Override - protected void configureQSim() { - bindModal(DrtOfferAcceptor.class).toProvider(modalProvider(getter -> new MaxDetourOfferAcceptor(drtCfg.maxAllowedPickupDelay))); - } - }); - } - controler.run(); } } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserterTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserterTest.java index 58637acaddc..2396c4da810 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserterTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserterTest.java @@ -42,6 +42,7 @@ import org.matsim.contrib.drt.optimizer.DrtRequestInsertionRetryQueue; import org.matsim.contrib.drt.optimizer.VehicleEntry; import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; +import org.matsim.contrib.drt.passenger.DefaultOfferAcceptor; import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; import org.matsim.contrib.drt.passenger.DrtRequest; import org.matsim.contrib.drt.schedule.DefaultDrtStopTask; @@ -285,7 +286,7 @@ private DefaultUnplannedRequestInserter newInserter(Fleet fleet, double now, VehicleEntry.EntryFactory vehicleEntryFactory, DrtRequestInsertionRetryQueue insertionRetryQueue, DrtInsertionSearch insertionSearch, RequestInsertionScheduler insertionScheduler) { return new DefaultUnplannedRequestInserter(mode, fleet, () -> now, eventsManager, insertionScheduler, - vehicleEntryFactory, insertionRetryQueue, insertionSearch, DrtOfferAcceptor.DEFAULT_ACCEPTOR, + vehicleEntryFactory, insertionRetryQueue, insertionSearch, new DefaultOfferAcceptor(), forkJoinPoolExtension.forkJoinPool, StaticPassengerStopDurationProvider.of(10.0, 0.0)); } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/InsertionGeneratorTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/InsertionGeneratorTest.java index 5a44c12c118..6ffde35326c 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/InsertionGeneratorTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/InsertionGeneratorTest.java @@ -378,7 +378,8 @@ void startEmpty_onlineRequest_beforeAlreadyPrebookedOtherRequest() { Waypoint.Start start = new Waypoint.Start(null, link("start"), 0, 0); Waypoint.Stop stop0 = stop(200, fromLink, 1); Waypoint.Stop stop1 = stop(400, link("stop"), 0); - VehicleEntry entry = entry(start, stop0, stop1); + List precedingStayTimes = Arrays.asList(100.0, 0.0); + VehicleEntry entry = entry(start, precedingStayTimes, stop0, stop1); assertInsertionsOnly(drtRequest, entry, new Insertion(drtRequest, entry, 0, 0), new Insertion(drtRequest, entry, 0, 1), @@ -524,9 +525,13 @@ private Waypoint.Stop stop(double beginTime, Link link, int outgoingOccupancy) { } private VehicleEntry entry(Waypoint.Start start, Waypoint.Stop... stops) { + List precedingStayTimes = Collections.nCopies(stops.length, 0.0); + return entry(start, precedingStayTimes, stops); + } + + private VehicleEntry entry(Waypoint.Start start, List precedingStayTimes, Waypoint.Stop... stops) { var slackTimes = new double[stops.length + 2]; Arrays.fill(slackTimes, Double.POSITIVE_INFINITY); - List precedingStayTimes = Collections.nCopies(stops.length, 0.0); return new VehicleEntry(vehicle, start, ImmutableList.copyOf(stops), slackTimes, precedingStayTimes, 0); } } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimatorTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimatorTest.java index 954959480ba..0b93d725f48 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimatorTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimatorTest.java @@ -30,8 +30,10 @@ import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.events.PersonDepartureEvent; import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneImpl; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.ZoneSystemImpl; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.testcases.fakes.FakeLink; @@ -46,9 +48,9 @@ public class PreviousIterationDrtDemandEstimatorTest { private final Link link1 = new FakeLink(Id.createLinkId("link_1")); private final Link link2 = new FakeLink(Id.createLinkId("link_2")); - private final DrtZone zone1 = DrtZone.createDummyZone("zone_1", List.of(link1), new Coord()); - private final DrtZone zone2 = DrtZone.createDummyZone("zone_2", List.of(link2), new Coord()); - private final DrtZonalSystem zonalSystem = new DrtZonalSystem(List.of(zone1, zone2)); + private final Zone zone1 = ZoneImpl.createDummyZone(Id.create("zone_1", Zone.class), List.of(link1), new Coord()); + private final Zone zone2 = ZoneImpl.createDummyZone(Id.create("zone_2", Zone.class), List.of(link2), new Coord()); + private final ZoneSystem zonalSystem = new ZoneSystemImpl(List.of(zone1, zone2)); @Test void noDepartures() { @@ -170,7 +172,7 @@ private PersonDepartureEvent departureEvent(double time, Link link, String mode) return new PersonDepartureEvent(time, null, link.getId(), mode, mode); } - private void assertDemand(PreviousIterationDrtDemandEstimator estimator, double fromTime, DrtZone zone, + private void assertDemand(PreviousIterationDrtDemandEstimator estimator, double fromTime, Zone zone, double expectedDemand) { assertThat(estimator.getExpectedDemand(fromTime, ESTIMATION_PERIOD).applyAsDouble(zone)).isEqualTo( expectedDemand); diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculatorTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculatorTest.java index 4f51cb334a5..e1ef42a98d1 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculatorTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculatorTest.java @@ -20,17 +20,14 @@ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Map; -import java.util.function.ToDoubleFunction; - +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.ZoneSystemUtils; import org.matsim.contrib.drt.analysis.zonal.DrtGridUtils; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.FleetSpecification; @@ -42,6 +39,11 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; +import java.util.Map; +import java.util.function.ToDoubleFunction; + +import static org.assertj.core.api.Assertions.assertThat; + /** * @author Michal Maciejewski (michalm) */ @@ -53,7 +55,7 @@ public class EqualVehicleDensityTargetCalculatorTest { private final Network network = NetworkUtils.readNetwork( config.network().getInputFileURL(config.getContext()).toString()); - private final DrtZonalSystem zonalSystem = DrtZonalSystem.createFromPreparedGeometries(network, + private final ZoneSystem zonalSystem = ZoneSystemUtils.createFromPreparedGeometries(network, DrtGridUtils.createGridFromNetwork(network, 500.)); @Test @@ -91,8 +93,8 @@ private FleetSpecification createFleetSpecification(int count) { return fleetSpecification; } - private void assertTarget(ToDoubleFunction targetFunction, DrtZonalSystem zonalSystem, String zoneId, - double expectedValue) { - assertThat(targetFunction.applyAsDouble(zonalSystem.getZones().get(zoneId))).isEqualTo(expectedValue); + private void assertTarget(ToDoubleFunction targetFunction, ZoneSystem zonalSystem, Id zoneId, + double expectedValue) { + Assertions.assertThat(targetFunction.applyAsDouble(zonalSystem.getZones().get(zoneId))).isEqualTo(expectedValue); } } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculatorTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculatorTest.java index 7d1044fcd6e..7c24bd07c26 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculatorTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculatorTest.java @@ -33,9 +33,10 @@ import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.Population; import org.matsim.api.core.v01.population.PopulationFactory; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.ZoneSystemUtils; import org.matsim.contrib.drt.analysis.zonal.DrtGridUtils; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.FleetSpecification; @@ -59,7 +60,7 @@ public class EqualVehiclesToPopulationRatioTargetCalculatorTest { private final Network network = NetworkUtils.readNetwork( config.network().getInputFileURL(config.getContext()).toString()); - private final DrtZonalSystem zonalSystem = DrtZonalSystem.createFromPreparedGeometries(network, + private final ZoneSystem zonalSystem = ZoneSystemUtils.createFromPreparedGeometries(network, DrtGridUtils.createGridFromNetwork(network, 500.)); private final Population population = PopulationUtils.createPopulation(config); @@ -67,34 +68,36 @@ public class EqualVehiclesToPopulationRatioTargetCalculatorTest { @Test void testCalculate_oneVehiclePerZone() { - initPopulation(Map.of("2", 1, "4", 1, "8", 1)); + initPopulation(Map.of(ZoneSystemUtils.createZoneId("2"), 1, ZoneSystemUtils.createZoneId("4"), 1, ZoneSystemUtils.createZoneId("8"), 1)); + var targetFunction = new EqualVehiclesToPopulationRatioTargetCalculator(zonalSystem, population, createFleetSpecification(8)).calculate(0, Map.of()); - assertTarget(targetFunction, zonalSystem, "1", 0); - assertTarget(targetFunction, zonalSystem, "2", 8. * (1. / 3)); - assertTarget(targetFunction, zonalSystem, "3", 0); - assertTarget(targetFunction, zonalSystem, "4", 8. * (1. / 3)); - assertTarget(targetFunction, zonalSystem, "5", 0); - assertTarget(targetFunction, zonalSystem, "6", 0); - assertTarget(targetFunction, zonalSystem, "7", 0); - assertTarget(targetFunction, zonalSystem, "8", 8. * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("1", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("2", Zone.class), 8. * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("3", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("4", Zone.class), 8. * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("5", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("6", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("7", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("8", Zone.class), 8. * (1. / 3)); } @Test void testCalculate_twoVehiclesPerZone() { - initPopulation(Map.of("2", 1, "4", 1, "8", 1)); + initPopulation(Map.of(ZoneSystemUtils.createZoneId("2"), 1, ZoneSystemUtils.createZoneId("4"), 1, ZoneSystemUtils.createZoneId("8"), 1)); + var targetFunction = new EqualVehiclesToPopulationRatioTargetCalculator(zonalSystem, population, createFleetSpecification(16)).calculate(0, Map.of()); - assertTarget(targetFunction, zonalSystem, "1", 0); - assertTarget(targetFunction, zonalSystem, "2", 16 * (1. / 3)); - assertTarget(targetFunction, zonalSystem, "3", 0); - assertTarget(targetFunction, zonalSystem, "4", 16 * (1. / 3)); - assertTarget(targetFunction, zonalSystem, "5", 0); - assertTarget(targetFunction, zonalSystem, "6", 0); - assertTarget(targetFunction, zonalSystem, "7", 0); - assertTarget(targetFunction, zonalSystem, "8", 16. * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("1", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("2", Zone.class), 16 * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("3", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("4", Zone.class), 16 * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("5", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("6", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("7", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("8", Zone.class), 16. * (1. / 3)); } @Test @@ -103,30 +106,30 @@ void testCalculate_noPopulation() { var targetFunction = new EqualVehiclesToPopulationRatioTargetCalculator(zonalSystem, population, createFleetSpecification(16)).calculate(0, Map.of()); - assertTarget(targetFunction, zonalSystem, "1", 0); - assertTarget(targetFunction, zonalSystem, "2", 0); - assertTarget(targetFunction, zonalSystem, "3", 0); - assertTarget(targetFunction, zonalSystem, "4", 0); - assertTarget(targetFunction, zonalSystem, "5", 0); - assertTarget(targetFunction, zonalSystem, "6", 0); - assertTarget(targetFunction, zonalSystem, "7", 0); - assertTarget(targetFunction, zonalSystem, "8", 0); + assertTarget(targetFunction, zonalSystem, Id.create("1", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("2", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("3", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("4", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("5", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("6", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("7", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("8", Zone.class), 0); } @Test void testCalculate_unevenDistributionOfActivitiesInPopulatedZones() { - initPopulation(Map.of("2", 2, "4", 4, "8", 8)); + initPopulation(Map.of(ZoneSystemUtils.createZoneId("2"), 2, ZoneSystemUtils.createZoneId("4"), 4, ZoneSystemUtils.createZoneId("8"), 8)); var targetFunction = new EqualVehiclesToPopulationRatioTargetCalculator(zonalSystem, population, createFleetSpecification(16)).calculate(0, Map.of()); - assertTarget(targetFunction, zonalSystem, "1", 0); - assertTarget(targetFunction, zonalSystem, "2", 16 * (2. / 14)); - assertTarget(targetFunction, zonalSystem, "3", 0); - assertTarget(targetFunction, zonalSystem, "4", 16 * (4. / 14)); - assertTarget(targetFunction, zonalSystem, "5", 0); - assertTarget(targetFunction, zonalSystem, "6", 0); - assertTarget(targetFunction, zonalSystem, "7", 0); - assertTarget(targetFunction, zonalSystem, "8", 16 * (8. / 14)); + assertTarget(targetFunction, zonalSystem, Id.create("1", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("2", Zone.class), 16 * (2. / 14)); + assertTarget(targetFunction, zonalSystem, Id.create("3", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("4", Zone.class), 16 * (4. / 14)); + assertTarget(targetFunction, zonalSystem, Id.create("5", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("6", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("7", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("8", Zone.class), 16 * (8. / 14)); } private FleetSpecification createFleetSpecification(int count) { @@ -149,7 +152,7 @@ private FleetSpecification createFleetSpecification(int count) { * 2 4 6 8 * 1 3 5 7 */ - private void initPopulation(Map populationPerZone) { + private void initPopulation(Map, Integer> populationPerZone) { populationPerZone.forEach((zoneId, population) -> { for (int i = 0; i < population; i++) { createAndAddPerson(zoneId + "_" + i, zoneId); @@ -157,7 +160,7 @@ private void initPopulation(Map populationPerZone) { }); } - private void createAndAddPerson(String id, String zoneId) { + private void createAndAddPerson(String id, Id zoneId) { Id linkId = zonalSystem.getZones().get(zoneId).getLinks().get(0).getId(); Person person = factory.createPerson(Id.createPersonId(id)); Plan plan = factory.createPlan(); @@ -166,8 +169,8 @@ private void createAndAddPerson(String id, String zoneId) { population.addPerson(person); } - private void assertTarget(ToDoubleFunction targetFunction, DrtZonalSystem zonalSystem, String zoneId, - double expectedValue) { + private void assertTarget(ToDoubleFunction targetFunction, ZoneSystem zonalSystem, Id zoneId, + double expectedValue) { assertThat(targetFunction.applyAsDouble(zonalSystem.getZones().get(zoneId))).isEqualTo(expectedValue); } } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTest.java index 0bf2f375f6e..152ac850766 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTest.java @@ -207,8 +207,8 @@ void twoSequentialRequests_inverseSubmission() { { RequestInfo requestInfo = environment.getRequestInfo().get("lateRequest"); assertEquals(0.0, requestInfo.submissionTime, 1e-3); - assertEquals(4000.0 + 60.0, requestInfo.pickupTime, 1e-3); - assertEquals(4103.0, requestInfo.dropoffTime, 1e-3); + assertEquals(4000.0 + 60.0 + 1.0, requestInfo.pickupTime, 1e-3); + assertEquals(4104.0, requestInfo.dropoffTime, 1e-3); } } @@ -528,4 +528,90 @@ public void install() { assertEquals(2060.0, taskInfo.get(3).endTime, 1e-3); // Ending stop (260s duration) assertEquals(2060.0, taskInfo.get(4).startTime, 1e-3); // Starting drive (ending stop) } + + @Test + void destinationEqualsPrebookedOrigin_twoRequests() { + /*- + * In this test, we have two prebooked requests: + * P[A] ---------> D[A] P[B] --------> D[B] + * + * The dropoff of A happens at the same place as the pickup of B. Then we dispatch a new request C + * traveling the same trip as A. Without an implemented fix, inserting the dropfof between D[A] and P[B] + * was not an option as P[B] was the same link as the destination of C. The only viable dropoff insertion + * was after P[B], which, however, was too late. + */ + + PrebookingTestEnvironment environment = new PrebookingTestEnvironment(utils) // + .addVehicle("vehicleA", 1, 1) // + .addRequest("requestA", 1, 1, 4, 4, 1000.0, 0.0) // + .addRequest("requestB", 4, 4, 8, 8, 8000.0, 1.0) // + .addRequest("requestC", 1, 1, 4, 4, 1000.0, 2.0) // + .configure(300.0, 2.0, 1800.0, 60.0) // + .endTime(12.0 * 3600.0); + + Controler controller = environment.build(); + installPrebooking(controller); + controller.run(); + + { + RequestInfo requestInfo = environment.getRequestInfo().get("requestA"); + assertEquals(0.0, requestInfo.submissionTime, 1e-3); + assertEquals(1000.0 + 60.0 + 1.0, requestInfo.pickupTime, 1e-3); + assertEquals(1188.0, requestInfo.dropoffTime, 1e-3); + } + + { + RequestInfo requestInfo = environment.getRequestInfo().get("requestB"); + assertEquals(1.0, requestInfo.submissionTime, 1e-3); + assertEquals(8000.0 + 60.0 + 1.0, requestInfo.pickupTime, 1e-3); + assertEquals(8230.0, requestInfo.dropoffTime, 1e-3); + } + + { + RequestInfo requestInfo = environment.getRequestInfo().get("requestC"); + assertEquals(2.0, requestInfo.submissionTime, 1e-3); + assertEquals(1000.0 + 60.0 + 1.0, requestInfo.pickupTime, 1e-3); + assertEquals(1188.0, requestInfo.dropoffTime, 1e-3); + } + + assertEquals(4, environment.getTaskInfo().get("vehicleA").stream().filter(t -> t.type.equals("STOP")).count()); + } + + @Test + void destinationEqualsPrebookedOrigin_oneRequest() { + /*- + * In this test, we aprebooked requests: + * P[A] ---------> D[A] + * + * Then we dispatch a new request C before A. The destination of C is the origin of A. Without an implemented fix, + * inserting the dropoff before P[A] was not allowed as it is the same link, but inserting after D[A] was too late. + */ + + PrebookingTestEnvironment environment = new PrebookingTestEnvironment(utils) // + .addVehicle("vehicleA", 1, 1) // + .addRequest("requestA", 4, 4, 8, 8, 4000.0, 1.0) // + .addRequest("requestB", 1, 1, 4, 4, 1000.0, 2.0) // + .configure(300.0, 2.0, 1800.0, 60.0) // + .endTime(12.0 * 3600.0); + + Controler controller = environment.build(); + installPrebooking(controller); + controller.run(); + + { + RequestInfo requestInfo = environment.getRequestInfo().get("requestA"); + assertEquals(1.0, requestInfo.submissionTime, 1e-3); + assertEquals(4000.0 + 60.0 + 1.0, requestInfo.pickupTime, 1e-3); + assertEquals(4230.0, requestInfo.dropoffTime, 1e-3); + } + + { + RequestInfo requestInfo = environment.getRequestInfo().get("requestB"); + assertEquals(2.0, requestInfo.submissionTime, 1e-3); + assertEquals(1000.0 + 60.0 + 1.0, requestInfo.pickupTime, 1e-3); + assertEquals(1188.0, requestInfo.dropoffTime, 1e-3); + } + + assertEquals(4, environment.getTaskInfo().get("vehicleA").stream().filter(t -> t.type.equals("STOP")).count()); + } } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java index e3ac88d4985..652d66ecf19 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java @@ -304,16 +304,12 @@ public void install() { controller.run(); - // sh, 11/08/2023: updated after introducing prebookg, basically we generate a - // new feasible insertion (see InsertionGenerator) that previously did not - // exist, but has the same cost (pickup loss + drop-off loss) as the original - // one var expectedStats = Stats.newBuilder() .rejectionRate(0.04) .rejections(16) - .waitAverage(278.76) - .inVehicleTravelTimeMean(384.93) - .totalTravelTimeMean(663.68) + .waitAverage(278.92) + .inVehicleTravelTimeMean(384.6) + .totalTravelTimeMean(663.52) .build(); verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); @@ -342,17 +338,17 @@ void testRunDrtWithPrebooking() { controller.run(); - assertEquals(157, tracker.immediateScheduled); + assertEquals(169, tracker.immediateScheduled); assertEquals(205, tracker.prebookedScheduled); - assertEquals(26, tracker.immediateRejected); + assertEquals(14, tracker.immediateRejected); assertEquals(0, tracker.prebookedRejected); var expectedStats = Stats.newBuilder() - .rejectionRate(0.07) - .rejections(26) - .waitAverage(232.76) - .inVehicleTravelTimeMean(389.09) - .totalTravelTimeMean(621.85) + .rejectionRate(0.04) + .rejections(14) + .waitAverage(232.47) + .inVehicleTravelTimeMean(389.16) + .totalTravelTimeMean(621.63) .build(); verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/io/ZoneShpReader.java b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/io/ZoneShpReader.java index 9913f890326..d47dac4c588 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/io/ZoneShpReader.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/io/ZoneShpReader.java @@ -26,7 +26,7 @@ import org.locationtech.jts.geom.MultiPolygon; import org.matsim.api.core.v01.Id; import org.matsim.contrib.zone.Zone; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; public class ZoneShpReader { @@ -41,7 +41,7 @@ public void readZones(URL url) { } public void readZones(URL url, String idHeader) { - Collection features = ShapeFileReader.getAllFeatures(url); + Collection features = GeoFileReader.getAllFeatures(url); if (features.size() != zones.size()) { throw new RuntimeException("Features#: " + features.size() + "; zones#: " + zones.size()); } diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/io/ZoneShpWriter.java b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/io/ZoneShpWriter.java index 1e3fde7b279..ba5bb104c9d 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/io/ZoneShpWriter.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/io/ZoneShpWriter.java @@ -51,6 +51,6 @@ public void write(String shpFile) { features.add(factory.createPolygon(z.getMultiPolygon(), new Object[] { id }, id)); } - ShapeFileWriter.writeGeometries(features, shpFile); + GeoFileWriter.writeGeometries(features, shpFile); } } diff --git a/contribs/emissions/src/test/java/org/matsim/contrib/emissions/events/VehicleLeavesTrafficEventTest.java b/contribs/emissions/src/test/java/org/matsim/contrib/emissions/events/VehicleLeavesTrafficEventTest.java index 2858e572d58..1eacd47330d 100644 --- a/contribs/emissions/src/test/java/org/matsim/contrib/emissions/events/VehicleLeavesTrafficEventTest.java +++ b/contribs/emissions/src/test/java/org/matsim/contrib/emissions/events/VehicleLeavesTrafficEventTest.java @@ -19,7 +19,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; import java.net.URL; @@ -81,8 +81,8 @@ public void install(){ throw new RuntimeException(e) ; } final String expected = utils.getClassInputDirectory() + emissionEventsFileName; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles(expected, resultingEvents); - Assertions.assertEquals( EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles(expected, resultingEvents); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result); } } diff --git a/contribs/emissions/src/test/java/org/matsim/contrib/emissions/example/RunAverageEmissionToolOfflineExampleIT.java b/contribs/emissions/src/test/java/org/matsim/contrib/emissions/example/RunAverageEmissionToolOfflineExampleIT.java index 951ed2fb237..259b8472549 100644 --- a/contribs/emissions/src/test/java/org/matsim/contrib/emissions/example/RunAverageEmissionToolOfflineExampleIT.java +++ b/contribs/emissions/src/test/java/org/matsim/contrib/emissions/example/RunAverageEmissionToolOfflineExampleIT.java @@ -30,7 +30,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator.Result; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; import java.net.URL; @@ -58,8 +58,8 @@ final void testAverage_vehTypeV1() { String expected = utils.getInputDirectory() + RunAverageEmissionToolOfflineExample.emissionEventsFilename; String actual = utils.getOutputDirectory() + RunAverageEmissionToolOfflineExample.emissionEventsFilename; - Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals( Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result); } @Test @@ -80,8 +80,8 @@ final void testAverage_vehTypeV2() { String expected = utils.getInputDirectory() + RunAverageEmissionToolOfflineExample.emissionEventsFilename; String actual = utils.getOutputDirectory() + RunAverageEmissionToolOfflineExample.emissionEventsFilename; - Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals( Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result); } /** @@ -106,8 +106,8 @@ final void testAverage_vehTypeV2b() { String expected = utils.getInputDirectory() + RunAverageEmissionToolOfflineExample.emissionEventsFilename; String actual = utils.getOutputDirectory() + RunAverageEmissionToolOfflineExample.emissionEventsFilename; - Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals( Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result); } @@ -130,7 +130,7 @@ final void testAverage_vehTypeV2_HBEFA4() { String expected = utils.getInputDirectory() + RunAverageEmissionToolOfflineExample.emissionEventsFilename; String actual = utils.getOutputDirectory() + RunAverageEmissionToolOfflineExample.emissionEventsFilename; - Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals( Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result); } } diff --git a/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleTest.java b/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleTest.java index e8bb29fea1c..87644405c7d 100644 --- a/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleTest.java +++ b/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleTest.java @@ -10,7 +10,7 @@ import org.matsim.core.events.EventsUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class RunEvExampleTest{ @@ -39,8 +39,8 @@ public class RunEvExampleTest{ { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } catch ( Exception ee ) { @@ -72,8 +72,8 @@ public class RunEvExampleTest{ { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } catch ( Exception ee ) { diff --git a/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModelTest.java b/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModelTest.java index ffc5f81e296..447b79966ad 100644 --- a/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModelTest.java +++ b/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModelTest.java @@ -10,11 +10,7 @@ import org.matsim.core.events.EventsUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; - -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class RunEvExampleWithLTHConsumptionModelTest{ @@ -43,8 +39,8 @@ void runTest(){ { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals( EventsFileComparator.Result.FILES_ARE_EQUAL, result ); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result ); } } catch ( Exception ee ) { diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT.java index ced181d3172..b195b3b89d7 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT.java @@ -32,7 +32,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class RunChessboardIT { @@ -60,8 +60,8 @@ void runChessboard() { { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals( EventsFileComparator.Result.FILES_ARE_EQUAL, result ); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result ); } } catch (Exception ee ) { ee.printStackTrace(); diff --git a/contribs/hybridsim/pom.xml b/contribs/hybridsim/pom.xml index 3ffc35cae01..b276eda7285 100644 --- a/contribs/hybridsim/pom.xml +++ b/contribs/hybridsim/pom.xml @@ -10,8 +10,8 @@ hybridsim - 3.25.2 - 1.61.1 + 4.26.0 + 1.62.2 diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/CandidateGenerator.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/CandidateGenerator.java index d31e30c2ffd..be52b42752c 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/CandidateGenerator.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/CandidateGenerator.java @@ -3,7 +3,7 @@ import org.matsim.api.core.v01.population.Plan; import javax.annotation.Nullable; -import java.util.Collection; +import java.util.List; import java.util.Set; /** @@ -15,7 +15,7 @@ public interface CandidateGenerator { /** * Generate plan candidates, ordered by their natural comparator. */ - default Collection generate(PlanModel planModel) { + default List generate(PlanModel planModel) { return generate(planModel, null, null); } @@ -23,6 +23,7 @@ default Collection generate(PlanModel planModel) { * Generate plan candidates, ordered by their natural comparator. * @param consideredModes if not null, will restrict usable modes to these present in the set * @param mask if not null, only include these trips with a true entry at their respective index. + * @return list of candidates, this list must be mutable */ - Collection generate(PlanModel planModel, @Nullable Set consideredModes, @Nullable boolean[] mask); + List generate(PlanModel planModel, @Nullable Set consideredModes, @Nullable boolean[] mask); } diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/InformedModeChoiceModule.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/InformedModeChoiceModule.java index a6229390386..e681025ef92 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/InformedModeChoiceModule.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/InformedModeChoiceModule.java @@ -7,6 +7,7 @@ import com.google.inject.multibindings.MapBinder; import com.google.inject.multibindings.Multibinder; import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.listener.ControlerListener; import org.matsim.core.router.PlanRouter; import org.matsim.core.router.TripRouter; import org.matsim.core.utils.timing.TimeInterpretation; @@ -48,6 +49,10 @@ private InformedModeChoiceModule(Builder builder) { this.builder = builder; } + public static Builder newBuilder() { + return new Builder(); + } + @Override public void install() { @@ -80,7 +85,12 @@ public void install() { MapBinder pBinder = MapBinder.newMapBinder(binder(), String.class, CandidatePruner.class); for (Map.Entry e : builder.pruner.entrySet()) { - pBinder.addBinding(e.getKey()).toInstance(e.getValue()); + CandidatePruner instance = e.getValue(); + + pBinder.addBinding(e.getKey()).toInstance(instance); + + if (instance instanceof ControlerListener cl) + addControlerListenerBinding().toInstance(cl); } addPlanStrategyBinding(SELECT_BEST_K_PLAN_MODES_STRATEGY).toProvider(SelectBestKPlanModesStrategyProvider.class); @@ -131,20 +141,16 @@ private void bindAllModes(Map> map, TypeLiteral>> fixedCosts = new HashMap<>(); - private final Map>> legEstimators = new HashMap<>(); - private final Map>> tripEstimators = new HashMap<>(); + private final Map> fixedCosts = new HashMap<>(); + private final Map> legEstimators = new HashMap<>(); + private final Map> tripEstimators = new HashMap<>(); - private final Map>> options = new HashMap<>(); + private final Map> options = new HashMap<>(); private final Set>> constraints = new LinkedHashSet<>(); @@ -155,7 +161,7 @@ public static final class Builder { /** * Adds a fixed cost to one or more modes. */ - public > Builder withFixedCosts(Class> estimator, String... modes) { + public Builder withFixedCosts(Class estimator, String... modes) { for (String mode : modes) { fixedCosts.put(mode, estimator); @@ -167,8 +173,8 @@ public > Builder withFixedCosts(Class> Builder withLegEstimator(Class> estimator, Class> option, - String... modes) { + public Builder withLegEstimator(Class estimator, Class option, + String... modes) { for (String mode : modes) { @@ -187,8 +193,8 @@ public > Builder withLegEstimator(Class> Builder withTripEstimator(Class> estimator, Class> option, - String... modes) { + public Builder withTripEstimator(Class estimator, Class option, + String... modes) { for (String mode : modes) { diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeAvailability.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeAvailability.java index ccbc7b8cf2f..0470fbceb6e 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeAvailability.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeAvailability.java @@ -1,11 +1,28 @@ package org.matsim.modechoice; /** - * Default mode availability enumeration with two different options. + * Mode availability enumeration with different options. + * Different options are required in case there a different pricing schemes, depending on the usage of the mode. */ public enum ModeAvailability { YES, - NO; + NO, + + MONTHLY_SUBSCRIPTION, + YEARLY_SUBSCRIPTION, + DAILY_TICKET, + + /** + * May be used if the other options are not applicable. + */ + OTHER; + + /** + * True for all options except {@link #NO}. + */ + public boolean isModeAvailable() { + return this != NO; + } } diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeEstimate.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeEstimate.java index a73a2b9cbac..6b08caba569 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeEstimate.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeEstimate.java @@ -13,7 +13,7 @@ public final class ModeEstimate { private final String mode; - private final Enum option; + private final ModeAvailability option; private final double[] est; private final double[] tripEst; @@ -35,7 +35,7 @@ public final class ModeEstimate { * @param isMin whether these are minimum estimates * @param storeTripEst whether trip est needs to be stored */ - ModeEstimate(String mode, Enum option, int n, boolean isUsable, boolean storeTripEst, boolean isMin) { + ModeEstimate(String mode, ModeAvailability option, int n, boolean isUsable, boolean storeTripEst, boolean isMin) { this.mode = mode; this.option = option; this.min = isMin; @@ -48,7 +48,7 @@ public String getMode() { return mode; } - public Enum getOption() { + public ModeAvailability getOption() { return option; } diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeOptions.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeOptions.java index 62932b758c6..f0eb03bfd73 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeOptions.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/ModeOptions.java @@ -6,28 +6,30 @@ import java.util.List; /** - * Interface to determine which mode options are available to an agent and considered when computing best options. + * Interface to determine which {@link ModeAvailability} are available to an agent and considered when computing best options. *

* This interface also contains the default implementations. * - * @param enum listing the possible options */ -public interface ModeOptions> { +public interface ModeOptions { /** * Determine options for one agent. */ - List get(Person person); + List get(Person person); /** - * Return whether an option allows to use the mode. Normally only one of the option should forbid using the mode at all. + * Return whether an option allows to use the mode. */ - boolean allowUsage(T option); + default boolean allowUsage(ModeAvailability option) { + return option.isModeAvailable(); + } /** * The mode is always available and considered. + * This also means that there should be no daily costs associated with the mode. */ - final class AlwaysAvailable implements ModeOptions { + final class AlwaysAvailable implements ModeOptions { private static final List YES = List.of(ModeAvailability.YES); private static final List NO = List.of(ModeAvailability.NO); @@ -37,16 +39,12 @@ public List get(Person person) { return YES; } - @Override - public boolean allowUsage(ModeAvailability option) { - return option == ModeAvailability.YES; - } } /** * Plans are considered with and without this mode. */ - final class ConsiderYesAndNo implements ModeOptions { + final class ConsiderYesAndNo implements ModeOptions { private static final List BOTH = List.of(ModeAvailability.YES, ModeAvailability.NO); @@ -55,17 +53,13 @@ public List get(Person person) { return BOTH; } - @Override - public boolean allowUsage(ModeAvailability option) { - return option == ModeAvailability.YES; - } } /** * Consider both options if car is available, otherwise none. */ - final class ConsiderIfCarAvailable implements ModeOptions { + final class ConsiderIfCarAvailable implements ModeOptions { @Override public List get(Person person) { @@ -75,10 +69,5 @@ public List get(Person person) { return AlwaysAvailable.NO; } - - @Override - public boolean allowUsage(ModeAvailability option) { - return option == ModeAvailability.YES; - } } } diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanCandidate.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanCandidate.java index 9a3cc6ccebd..418dc8e744c 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanCandidate.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanCandidate.java @@ -38,7 +38,8 @@ public double getUtility() { } /** - * Get mode for trip i. + * Get mode for trip i. Indexing starts at 0. + * @see #size() */ public String getMode(int i) { return modes[i]; @@ -51,6 +52,25 @@ public String[] getModes() { return Arrays.copyOf(modes, modes.length); } + /** + * Check whether a certain mode is present at least once. + */ + public boolean containsMode(String mode) { + for (String m : modes) { + if (mode.equals(m)) { + return true; + } + } + return false; + } + + /** + * Number of trips. + */ + public int size() { + return modes.length; + } + /** * Return features vector with number of occurrences per mode. */ diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModel.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModel.java index f0de060d997..cfb4c3f7966 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModel.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModel.java @@ -81,6 +81,7 @@ public Person getPerson() { } public Plan getPlan() { + // TODO: This should better be removed, memory usage by keeping these plans is increased return plan; } diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModelService.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModelService.java index 93c2ca21a0f..85f80664279 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModelService.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModelService.java @@ -28,10 +28,10 @@ public final class PlanModelService implements StartupListener { @Inject - private Map> legEstimators; + private Map legEstimators; @Inject - private Map> tripEstimator; + private Map tripEstimator; @Inject private Set> constraints; @@ -49,10 +49,10 @@ public final class PlanModelService implements StartupListener { private ControlerListenerManager controlerListenerManager; private final InformedModeChoiceConfigGroup config; - private final Map> options; + private final Map options; @Inject - private PlanModelService(InformedModeChoiceConfigGroup config, Map> options) { + private PlanModelService(InformedModeChoiceConfigGroup config, Map options) { this.config = config; this.options = options; @@ -92,14 +92,14 @@ public void initEstimates(EstimatorContext context, PlanModel planModel) { for (String mode : config.getModes()) { - ModeOptions> t = (ModeOptions>) this.options.get(mode); + ModeOptions t = this.options.get(mode); - List> modeOptions = t.get(planModel.getPerson()); + List modeOptions = t.get(planModel.getPerson()); List c = new ArrayList<>(); - for (Enum modeOption : modeOptions) { - TripEstimator> te = (TripEstimator>) tripEstimator.get(mode); + for (ModeAvailability modeOption : modeOptions) { + TripEstimator te = tripEstimator.get(mode); boolean usable = t.allowUsage(modeOption); @@ -123,7 +123,7 @@ public void initEstimates(EstimatorContext context, PlanModel planModel) { /** * Return the modes an estimator was registered for. */ - public List modesForEstimator(LegEstimator est) { + public List modesForEstimator(LegEstimator est) { return legEstimators.entrySet().stream().filter(e -> e.getValue().equals(est)) .map(Map.Entry::getKey) .distinct() @@ -139,10 +139,10 @@ public List allowedModes(PlanModel planModel) { for (String mode : config.getModes()) { - ModeOptions> t = (ModeOptions>) this.options.get(mode); - List> modeOptions = t.get(planModel.getPerson()); + ModeOptions t = this.options.get(mode); + List modeOptions = t.get(planModel.getPerson()); - for (Enum modeOption : modeOptions) { + for (ModeAvailability modeOption : modeOptions) { boolean usable = t.allowUsage(modeOption); if (usable) { @@ -181,7 +181,7 @@ public void calculateEstimates(EstimatorContext context, PlanModel planModel) { continue; } - TripEstimator> tripEst = (TripEstimator>) tripEstimator.get(c.getMode()); + TripEstimator tripEst = tripEstimator.get(c.getMode()); // some options may produce equivalent results, but are re-estimated // however, the more expensive computation is routing and only done once @@ -265,7 +265,7 @@ public boolean isValidOption(PlanModel model, String[] modes) { /** * Return the trip estimator for one specific mode. */ - public TripEstimator getTripEstimator(String mode) { + public TripEstimator getTripEstimator(String mode) { return tripEstimator.get(mode); } diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/commands/GenerateChoiceSet.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/commands/GenerateChoiceSet.java index 46e295edce7..3c05d8e43b5 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/commands/GenerateChoiceSet.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/commands/GenerateChoiceSet.java @@ -27,6 +27,7 @@ import java.nio.file.Path; import java.util.Collection; import java.util.HashSet; +import java.util.Objects; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -42,7 +43,7 @@ public class GenerateChoiceSet implements MATSimAppCommand, PersonAlgorithm { @CommandLine.Mixin private ScenarioOptions scenario; - @CommandLine.Option(names = "--subpopulation", description = "Subpopulation filter", defaultValue = "person") + @CommandLine.Option(names = "--subpopulation", description = "Subpopulation filter") private String subpopulation; @CommandLine.Option(names = "--top-k", description = "Use top k estimates") @@ -103,7 +104,7 @@ public Integer call() throws Exception { // copy the original plan, so no modifications are made for (Person person : controler.getScenario().getPopulation().getPersons().values()) { String subpop = PopulationUtils.getSubpopulation(person); - if (subpopulation != null && !subpop.equals(subpopulation)) + if (subpopulation != null && !Objects.equals(subpop, subpopulation)) continue; Plan selected = person.getSelectedPlan(); diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/DefaultLegScoreEstimator.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/DefaultLegScoreEstimator.java index e84b670f33d..b66f27782d5 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/DefaultLegScoreEstimator.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/DefaultLegScoreEstimator.java @@ -8,7 +8,7 @@ /** * Default estimator using MATSim scoring config. */ -public class DefaultLegScoreEstimator implements LegEstimator { +public class DefaultLegScoreEstimator implements LegEstimator { @Override diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/FixedCostsEstimator.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/FixedCostsEstimator.java index 6104b0f3e38..8bcf5deefe6 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/FixedCostsEstimator.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/FixedCostsEstimator.java @@ -4,17 +4,17 @@ import org.matsim.modechoice.EstimatorContext; import org.matsim.modechoice.ModeAvailability; -public interface FixedCostsEstimator> { +public interface FixedCostsEstimator { /** * The usage utility is added to the total score estimate, if this mode was used at least one tine. */ - double usageUtility(EstimatorContext context, String mode, T option); + double usageUtility(EstimatorContext context, String mode, ModeAvailability option); /** * The fixed utility is always added to the score estimate, regardless of usage. */ - default double fixedUtility(EstimatorContext context, String mode, T option) { + default double fixedUtility(EstimatorContext context, String mode, ModeAvailability option) { return 0; } @@ -22,12 +22,12 @@ default double fixedUtility(EstimatorContext context, String mode, T option) { /** * Default implementation that uses the daily constant as fixed costs. */ - final class DailyConstant implements FixedCostsEstimator { + final class DailyConstant implements FixedCostsEstimator { @Override public double usageUtility(EstimatorContext context, String mode, ModeAvailability option) { - if (option == ModeAvailability.YES) { + if (option.isModeAvailable()) { ModeUtilityParameters params = context.scoring.modeParams.get(mode); if (params == null) throw new IllegalStateException("Scoring parameter for mode " + mode + " not configured."); diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/LegEstimator.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/LegEstimator.java index 927f52c314f..b868bd45e04 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/LegEstimator.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/LegEstimator.java @@ -2,13 +2,14 @@ import org.matsim.api.core.v01.population.Leg; import org.matsim.modechoice.EstimatorContext; +import org.matsim.modechoice.ModeAvailability; /** * Estimator for a single leg. * * @param enumeration of possible ownerships */ -public interface LegEstimator> { +public interface LegEstimator { /** * Calculate an estimate of utility íf this mode would be used. @@ -20,7 +21,7 @@ public interface LegEstimator> { * @param option used mode availability * @return Estimated utility */ - double estimate(EstimatorContext context, String mode, Leg leg, T option); + double estimate(EstimatorContext context, String mode, Leg leg, ModeAvailability option); diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/PtTripEstimator.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/PtTripEstimator.java index 073326c431d..bf8eba848b4 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/PtTripEstimator.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/PtTripEstimator.java @@ -26,7 +26,7 @@ *

* Based on the estimator in the discrete_mode_choice module. */ -public class PtTripEstimator implements TripEstimator { +public class PtTripEstimator implements TripEstimator { private static final Logger log = LogManager.getLogger(PtTripEstimator.class); diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/TripEstimator.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/TripEstimator.java index d66628651ed..853a5da61a4 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/TripEstimator.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/estimators/TripEstimator.java @@ -2,6 +2,7 @@ import org.matsim.api.core.v01.population.Leg; import org.matsim.modechoice.EstimatorContext; +import org.matsim.modechoice.ModeAvailability; import org.matsim.modechoice.PlanModel; import java.util.List; @@ -11,9 +12,8 @@ * the final estimate can not be given until the whole plan is known. * This is usually the case with zone based fare systems or pt pricing based on the distance of the entire day. * - * @param enumeration of possible ownerships */ -public interface TripEstimator> { +public interface TripEstimator { /** * Calculate an estimate of utility íf this mode would be used. This method will be called with all legs of a trip. @@ -26,7 +26,7 @@ public interface TripEstimator> { * @param option used mode availability * @return Estimated utility */ - MinMaxEstimate estimate(EstimatorContext context, String mode, PlanModel plan, List trip, T option); + MinMaxEstimate estimate(EstimatorContext context, String mode, PlanModel plan, List trip, ModeAvailability option); /** * Provide an estimate for the whole plan. This function must only estimate the cost by using its mode. @@ -37,14 +37,14 @@ public interface TripEstimator> { * @param option mode availability * @return Estimated utility */ - default double estimate(EstimatorContext context, String mode, String[] modes, PlanModel plan, T option) { + default double estimate(EstimatorContext context, String mode, String[] modes, PlanModel plan, ModeAvailability option) { throw new UnsupportedOperationException("providesMinEstimate returned true, but estimate function for the whole plan is not implemented yet."); } /** * Indicate whether an estimate will be uncertain, so that it requires an additional minimum estimation. */ - default boolean providesMinEstimate(EstimatorContext context, String mode, T option) { + default boolean providesMinEstimate(EstimatorContext context, String mode, ModeAvailability option) { return false; } diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/pruning/CandidatePruner.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/pruning/CandidatePruner.java index 439caeab260..ef2cc7af044 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/pruning/CandidatePruner.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/pruning/CandidatePruner.java @@ -1,23 +1,53 @@ package org.matsim.modechoice.pruning; +import org.matsim.core.controler.listener.ControlerListener; +import org.matsim.modechoice.PlanCandidate; import org.matsim.modechoice.PlanModel; +import java.util.List; +import java.util.Random; + /** * Class used for pruning unpromising candidates, i.e. their score is below the calculated threshold. + * All methods of implementations must be thread safe! They will be invoked in parallel during planning! + *

+ * Implementations can also implement {@link ControlerListener} to get notified simulation progress. */ public interface CandidatePruner { + /** + * Remove candidates from a given collection. This method is expected to modify the collection directly. + * This method of pruning can be used for more complex strategies, but requires that the necesarry amount of candidates is generated first. + * The threshold based pruning {@link #planThreshold(PlanModel)} is usually more efficient. + */ + default void pruneCandidates(PlanModel model, List candidates, Random rnd) { + } + + /** + * Called when a candidate was selected. + * + * @param model the model used for planning + * @param candidate the selected candidate + */ + default void onSelectCandidate(PlanModel model, PlanCandidate candidate) { + } + /** * Calculate threshold to be applied on the best known plan estimate. Candidates with a larger difference to the best, than this threshold are discarded. + * * @return positive threshold, if negative it will not be applied */ - double planThreshold(PlanModel planModel); + default double planThreshold(PlanModel planModel) { + return -1; + } /** * Calculate threshold to be applied on a single trip. Modes worse than this threshold on this trip will be discarded. + * * @return positive threshold, if negative it will not be applied */ - double tripThreshold(PlanModel planModel, int idx); - + default double tripThreshold(PlanModel planModel, int idx) { + return -1; + } } diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/pruning/ChangeExpBetaPruner.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/pruning/ChangeExpBetaPruner.java new file mode 100644 index 00000000000..12f7763c104 --- /dev/null +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/pruning/ChangeExpBetaPruner.java @@ -0,0 +1,44 @@ +package org.matsim.modechoice.pruning; + +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.modechoice.PlanModel; + +/** + * Prunes candidates based on the probability calculated using change exp beta formula. + *

+ * E.g. using percentile of 0.9 will remove plans for which the probability of being changed to is less than 10% + * + * The smaller p, the more plans are removed. + * + * + * @see org.matsim.core.replanning.selectors.ExpBetaPlanChanger + */ +public class ChangeExpBetaPruner implements CandidatePruner { + + private final double threshold; + + /** + * Create pruner with the desired percentile of plans to keep. + * @param p percentile larger than 0.01 and 1. + */ + public ChangeExpBetaPruner(ScoringConfigGroup config, double p) { + + // because of hard-coded 0.01 in ExpBetaPlanChanger + if (p <= 0.01 || p >= 1) { + throw new IllegalArgumentException("p must be larger than 0.01 and smaller than 1"); + } + + // Calculate utility threshold based on desired percentage + threshold = 2 * Math.log(100 * p) / config.getBrainExpBeta(); + } + + @Override + public double planThreshold(PlanModel planModel) { + return threshold; + } + + @Override + public double tripThreshold(PlanModel planModel, int idx) { + return threshold; + } +} diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectBestKPlanModesStrategyProvider.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectBestKPlanModesStrategyProvider.java index 2852b788656..1278ee3c22a 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectBestKPlanModesStrategyProvider.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectBestKPlanModesStrategyProvider.java @@ -1,7 +1,6 @@ package org.matsim.modechoice.replanning; import org.matsim.core.config.groups.GlobalConfigGroup; -import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.replanning.PlanStrategy; import org.matsim.core.replanning.PlanStrategyImpl; import org.matsim.core.replanning.modules.ReRoute; @@ -9,15 +8,12 @@ import org.matsim.core.router.TripRouter; import org.matsim.core.utils.timing.TimeInterpretation; import org.matsim.facilities.ActivityFacilities; -import org.matsim.modechoice.ModeChoiceWeightScheduler; -import org.matsim.modechoice.PlanCandidate; -import org.matsim.modechoice.search.TopKChoicesGenerator; import jakarta.inject.Inject; import jakarta.inject.Provider; /** - * Provider for {@link SelectFromGeneratorStrategy}. + * Provider for {@link SimplePlanSelectionStrategy}. */ public class SelectBestKPlanModesStrategyProvider implements Provider { @@ -31,7 +27,7 @@ public class SelectBestKPlanModesStrategyProvider implements Provider generator; + private Provider generator; @Inject private Provider selector; @@ -41,7 +37,7 @@ public PlanStrategy get() { PlanStrategyImpl.Builder builder = new PlanStrategyImpl.Builder(new RandomPlanSelector<>()); - builder.addStrategyModule(new SimplePlanSelectionStrategyModule(globalConfigGroup, generator, selector)); + builder.addStrategyModule(new SimplePlanSelectionStrategy(globalConfigGroup, generator, selector)); builder.addStrategyModule(new ReRoute(facilities, tripRouterProvider, globalConfigGroup, timeInterpretation)); return builder.build(); diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectFromGeneratorStrategy.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectFromGeneratorStrategy.java deleted file mode 100644 index 833c787b343..00000000000 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectFromGeneratorStrategy.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.matsim.modechoice.replanning; - -import org.matsim.api.core.v01.population.Plan; -import org.matsim.core.population.algorithms.PlanAlgorithm; -import org.matsim.modechoice.CandidateGenerator; -import org.matsim.modechoice.PlanCandidate; -import org.matsim.modechoice.PlanModel; - -import java.util.Collection; - -/** - * Choose route using a generator and selector. - */ -public class SelectFromGeneratorStrategy implements PlanAlgorithm { - - private final CandidateGenerator generator; - private final PlanSelector selector; - - public SelectFromGeneratorStrategy(CandidateGenerator generator, PlanSelector selector) { - this.generator = generator; - this.selector = selector; - } - - @Override - public void run(Plan plan) { - - Collection candidates = generator.generate(PlanModel.newInstance(plan)); - PlanCandidate candidate = selector.select(candidates); - - if (candidate != null) { - candidate.applyTo(plan); - } - } -} diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectSingleTripModeStrategy.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectSingleTripModeStrategy.java index 0ee937c25ea..89b50019936 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectSingleTripModeStrategy.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectSingleTripModeStrategy.java @@ -83,8 +83,13 @@ public void run(Plan plan) { PlanCandidate c = chooseCandidate(model, null); - if (c != null) + if (c != null) { + if (pruner != null) { + pruner.onSelectCandidate(model, c); + } + c.applyTo(plan); + } } @@ -141,7 +146,7 @@ public PlanCandidate chooseCandidate(PlanModel model, @Nullable Collection candidates = generator.generate(model, modes, mask); + List candidates = generator.generate(model, modes, mask); // Remove based on threshold if (pruner != null) { @@ -153,6 +158,8 @@ public PlanCandidate chooseCandidate(PlanModel model, @Nullable Collection c.getUtility() < threshold); } + + pruner.pruneCandidates(model, candidates, rnd); } // Remove options that are the same as the current mode diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectSubtourModeStrategy.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectSubtourModeStrategy.java index 2d1e6f37945..21863fe785e 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectSubtourModeStrategy.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SelectSubtourModeStrategy.java @@ -156,16 +156,19 @@ public void run(Plan plan) { continue; } - Set candidates = new HashSet<>(); + Set candidateSet = new LinkedHashSet<>(); // Single modes are also added - candidates.addAll(singleModeCandidates); + candidateSet.addAll(singleModeCandidates); // one could either allow all modes here or only non chain based // config switch might be useful to investigate which option is better // execute best k modes - candidates.addAll(ctx.generator.generate(model, nonChainBasedModes, mask)); + candidateSet.addAll(ctx.generator.generate(model, nonChainBasedModes, mask)); + + // candidates are unique after this + List candidates = new ArrayList<>(candidateSet); if (config.isRequireDifferentModes()) candidates.removeIf(c -> Arrays.equals(c.getModes(), model.getCurrentModesMutable())); @@ -177,12 +180,19 @@ public void run(Plan plan) { if (!Double.isNaN(threshold) && threshold > 0) { candidates.removeIf(c -> c.getUtility() < singleModeCandidates.get(0).getUtility() - threshold); } + + // Only applied at the end + ctx.pruner.pruneCandidates(model, candidates, rnd); } if (!candidates.isEmpty()) { PlanCandidate select = ctx.selector.select(candidates); if (select != null) { + if (ctx.pruner != null) { + ctx.pruner.onSelectCandidate(model, select); + } + select.applyTo(plan); break; } diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SimplePlanSelectionStrategy.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SimplePlanSelectionStrategy.java new file mode 100644 index 00000000000..37f48e67cad --- /dev/null +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SimplePlanSelectionStrategy.java @@ -0,0 +1,69 @@ +package org.matsim.modechoice.replanning; + +import org.matsim.api.core.v01.population.Plan; +import org.matsim.core.config.groups.GlobalConfigGroup; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.population.algorithms.PlanAlgorithm; +import org.matsim.core.replanning.modules.AbstractMultithreadedModule; + +import jakarta.inject.Provider; +import org.matsim.modechoice.PlanCandidate; +import org.matsim.modechoice.PlanModel; + +import java.util.List; +import java.util.Random; + +/** + * Strategy that simply select from configured generator.. + */ +public class SimplePlanSelectionStrategy extends AbstractMultithreadedModule { + + private final Provider generator; + private final Provider selector; + + public SimplePlanSelectionStrategy(GlobalConfigGroup globalConfigGroup, + Provider generator, + Provider selector) { + super(globalConfigGroup); + this.generator = generator; + this.selector = selector; + } + + @Override + public PlanAlgorithm getPlanAlgoInstance() { + return new Algorithm(generator.get()); + } + + private static final class Algorithm implements PlanAlgorithm { + + private final GeneratorContext ctx; + private final Random rnd; + + public Algorithm(GeneratorContext ctx) { + this.ctx = ctx; + this.rnd = MatsimRandom.getLocalInstance(); + } + + @Override + public void run(Plan plan) { + + PlanModel planModel = PlanModel.newInstance(plan); + List candidates = ctx.generator.generate(planModel); + + if (ctx.pruner != null) { + ctx.pruner.pruneCandidates(planModel, candidates, rnd); + } + + PlanCandidate candidate = ctx.selector.select(candidates); + + if (candidate != null) { + if (ctx.pruner != null) { + ctx.pruner.onSelectCandidate(planModel, candidate); + } + + candidate.applyTo(plan); + } + } + } + +} diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SimplePlanSelectionStrategyModule.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SimplePlanSelectionStrategyModule.java deleted file mode 100644 index 2621291d4e2..00000000000 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/replanning/SimplePlanSelectionStrategyModule.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.matsim.modechoice.replanning; - -import org.matsim.core.config.groups.GlobalConfigGroup; -import org.matsim.core.population.algorithms.PlanAlgorithm; -import org.matsim.core.replanning.modules.AbstractMultithreadedModule; -import org.matsim.modechoice.CandidateGenerator; - -import jakarta.inject.Provider; - -/** - * Module for {@link SelectFromGeneratorStrategy}. - */ -public class SimplePlanSelectionStrategyModule extends AbstractMultithreadedModule { - - private final Provider generator; - private final Provider selector; - - public SimplePlanSelectionStrategyModule(GlobalConfigGroup globalConfigGroup, Provider generator, Provider selector) { - super(globalConfigGroup); - this.generator = generator; - this.selector = selector; - } - - @Override - public PlanAlgorithm getPlanAlgoInstance() { - return new SelectFromGeneratorStrategy(generator.get(), selector.get()); - } - -} diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/AbstractCandidateGenerator.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/AbstractCandidateGenerator.java index 54fd77228fc..fe1c92afee2 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/AbstractCandidateGenerator.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/AbstractCandidateGenerator.java @@ -19,10 +19,10 @@ abstract class AbstractCandidateGenerator implements CandidateGenerator { @Inject - protected Map> tripEstimator; + protected Map tripEstimator; @Inject - protected Map> fixedCosts; + protected Map fixedCosts; @Inject protected ScoringParametersForPerson params; diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/BestChoiceGenerator.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/BestChoiceGenerator.java index 3085da656e1..c7f2ded08ea 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/BestChoiceGenerator.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/BestChoiceGenerator.java @@ -26,14 +26,14 @@ public class BestChoiceGenerator extends TopKChoicesGenerator { @Override - public Collection generate(PlanModel planModel, @Nullable Set consideredModes, @Nullable boolean[] mask) { + public List generate(PlanModel planModel, @Nullable Set consideredModes, @Nullable boolean[] mask) { List candidates = new ArrayList<>(generate(planModel, consideredModes, mask, 10, 0, Double.NaN)); if (candidates.isEmpty()) - return Set.of(); + return candidates; - return List.of(candidates.stream().max(Comparator.comparingDouble(PlanCandidate::getUtility)).orElseThrow()); + return candidates.subList(0, 1); } } diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/ModeChoiceSearch.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/ModeChoiceSearch.java index 9764e80cad7..755fb3d006c 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/ModeChoiceSearch.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/ModeChoiceSearch.java @@ -194,10 +194,8 @@ public double nextDouble() { for (int i = 0; i < result.length; i++) { - byte[] path = Arrays.copyOf(entry.modes, entry.modes.length); - byte mode = -1; - byte originalMode = path[i]; + byte originalMode = entry.modes[i]; // This mode had no options if (originalMode == -1) @@ -215,8 +213,9 @@ public double nextDouble() { } } - path[i] = mode; if (mode != -1) { + byte[] path = Arrays.copyOf(entry.modes, entry.modes.length); + path[i] = mode; // recompute the deviation from the maximum // there might be a way to store and update this, without recomputing diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/SingleTripChoicesGenerator.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/SingleTripChoicesGenerator.java index 70d6ea4edcc..5ba80a11740 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/SingleTripChoicesGenerator.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/SingleTripChoicesGenerator.java @@ -19,7 +19,7 @@ public SingleTripChoicesGenerator(InformedModeChoiceConfigGroup config) { } @Override - public Collection generate(PlanModel planModel, @Nullable Set consideredModes, @Nullable boolean[] mask) { + public List generate(PlanModel planModel, @Nullable Set consideredModes, @Nullable boolean[] mask) { if (mask == null) throw new IllegalArgumentException("Mask must be provided"); diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/TopKChoicesGenerator.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/TopKChoicesGenerator.java index 4cb0dce962a..27ed135b3b2 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/TopKChoicesGenerator.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/search/TopKChoicesGenerator.java @@ -35,7 +35,7 @@ public class TopKChoicesGenerator extends AbstractCandidateGenerator { super(config); } - public Collection generate(PlanModel planModel, Set consideredModes, boolean[] mask) { + public List generate(PlanModel planModel, Set consideredModes, boolean[] mask) { CandidatePruner p = pruner.get(); double threshold = -1; @@ -54,7 +54,7 @@ public Collection generate(PlanModel planModel, Set consi * @param diffThreshold allowed difference to the best solution (if positive) * @param absThreshold minimal required estimate score (use NaN or negative infinity if not needed) */ - public Collection generate(PlanModel planModel, @Nullable Set consideredModes, @Nullable boolean[] mask, + public List generate(PlanModel planModel, @Nullable Set consideredModes, @Nullable boolean[] mask, int topK, double diffThreshold, double absThreshold) { EstimatorContext context = new EstimatorContext(planModel.getPerson(), params.getScoringParameters(planModel.getPerson())); @@ -88,7 +88,7 @@ protected final void prepareModel(PlanModel planModel, EstimatorContext context) } - private Collection generateCandidate(EstimatorContext context, PlanModel planModel, boolean[] mask, int topK, double diffThreshold, double absThreshold, + private List generateCandidate(EstimatorContext context, PlanModel planModel, boolean[] mask, int topK, double diffThreshold, double absThreshold, Set consideredModes, Set consolidateModes, List> constraints) { ModeChoiceSearch search = new ModeChoiceSearch(planModel.trips(), planModel.modes()); @@ -255,7 +255,7 @@ private double computePlanEstimate(EstimatorContext context, PlanModel planModel // Add the fixed costs estimate if a mode has been used for (ModeEstimate mode : options) { - FixedCostsEstimator> f = (FixedCostsEstimator>) fixedCosts.get(mode.getMode()); + FixedCostsEstimator f = fixedCosts.get(mode.getMode()); // Fixed costs are not required for each mode if (f == null) @@ -273,7 +273,7 @@ private double computePlanEstimate(EstimatorContext context, PlanModel planModel for (ModeEstimate mode : options) { if (mode.getMode() == consolidateMode && usedModes.contains(consolidateMode)) { - TripEstimator> f = (TripEstimator>) tripEstimator.get(mode.getMode()); + TripEstimator f = tripEstimator.get(mode.getMode()); // subtract all the trip estimates that have been made before for (int i = 0; i < result.length; i++) { diff --git a/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/estimators/ComplexTripEstimator.java b/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/estimators/ComplexTripEstimator.java index c50b8dfe7dd..05edcbc745f 100644 --- a/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/estimators/ComplexTripEstimator.java +++ b/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/estimators/ComplexTripEstimator.java @@ -14,7 +14,7 @@ /** * Complex estimator, using MATSim infrastructure */ -public final class ComplexTripEstimator implements TripEstimator, LinkEnterEventHandler, IterationEndsListener { +public final class ComplexTripEstimator implements TripEstimator, LinkEnterEventHandler, IterationEndsListener { private int iters = 0; private int events = 0; diff --git a/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/pruning/CandidatePrunerTest.java b/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/pruning/CandidatePrunerTest.java new file mode 100644 index 00000000000..f264be63ce8 --- /dev/null +++ b/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/pruning/CandidatePrunerTest.java @@ -0,0 +1,38 @@ +package org.matsim.modechoice.pruning; + +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.modechoice.PlanCandidate; +import org.matsim.modechoice.PlanModel; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import static org.assertj.core.api.Assertions.assertThat; + +class CandidatePrunerTest { + + private final CandidatePruner pruner = new ExamplePruner(TransportMode.drt); + + @Test + void example() { + + PlanModel model = Mockito.mock(PlanModel.class); + + List candidates = new ArrayList<>(List.of( + new PlanCandidate(new String[]{"car", "car", "car", "car"}, Double.NaN), + new PlanCandidate(new String[]{"car", "bike", "pt", "car"}, Double.NaN), + new PlanCandidate(new String[]{"car", "drt", "car", "car"}, Double.NaN), + new PlanCandidate(new String[]{"drt"}, Double.NaN) + )); + + pruner.pruneCandidates(model, candidates, new Random()); + + assertThat(candidates) + .hasSize(2); + + } + +} diff --git a/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/pruning/ExamplePruner.java b/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/pruning/ExamplePruner.java new file mode 100644 index 00000000000..ea92034fec6 --- /dev/null +++ b/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/pruning/ExamplePruner.java @@ -0,0 +1,32 @@ +package org.matsim.modechoice.pruning; + +import org.matsim.modechoice.PlanCandidate; +import org.matsim.modechoice.PlanModel; + +import java.util.List; +import java.util.Random; + +public class ExamplePruner implements CandidatePruner { + + private final String mode; + + public ExamplePruner(String mode) { + this.mode = mode; + } + + @Override + public void pruneCandidates(PlanModel model, List candidates, Random rnd) { + + candidates.removeIf(candidate -> candidate.containsMode(mode)); + } + + @Override + public double planThreshold(PlanModel planModel) { + return Double.POSITIVE_INFINITY; + } + + @Override + public double tripThreshold(PlanModel planModel, int idx) { + return Double.POSITIVE_INFINITY; + } +} diff --git a/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/search/TopKMinMaxTest.java b/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/search/TopKMinMaxTest.java index 01efd0381a4..04cfe9860e2 100644 --- a/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/search/TopKMinMaxTest.java +++ b/contribs/informed-mode-choice/src/test/java/org/matsim/modechoice/search/TopKMinMaxTest.java @@ -209,7 +209,7 @@ else if (invocationOnMock.getArgument(0).equals(TransportMode.walk)) { FacilitiesUtils.createActivityFacilities(), TimeInterpretation.create(PlansConfigGroup.ActivityDurationInterpretation.minOfDurationAndEndTime, PlansConfigGroup.TripDurationHandling.shiftActivityEndTimes))); - MapBinder> optionBinder = MapBinder.newMapBinder(binder(), new TypeLiteral<>() {}, new TypeLiteral<>(){}); + MapBinder optionBinder = MapBinder.newMapBinder(binder(), new TypeLiteral<>() {}, new TypeLiteral<>(){}); optionBinder.addBinding(TransportMode.car).toInstance(new ModeOptions.AlwaysAvailable()); optionBinder.addBinding(TransportMode.walk).toInstance(new ModeOptions.AlwaysAvailable()); @@ -217,20 +217,20 @@ else if (invocationOnMock.getArgument(0).equals(TransportMode.walk)) { Multibinder> tcBinder = Multibinder.newSetBinder(binder(), new TypeLiteral<>() { }); - MapBinder> fcBinder = MapBinder.newMapBinder(binder(), new TypeLiteral<>() { + MapBinder fcBinder = MapBinder.newMapBinder(binder(), new TypeLiteral<>() { }, new TypeLiteral<>() { }); fcBinder.addBinding(TransportMode.car).toInstance((context, mode, option) -> -1); - MapBinder> legBinder = MapBinder.newMapBinder(binder(), new TypeLiteral<>() { + MapBinder legBinder = MapBinder.newMapBinder(binder(), new TypeLiteral<>() { }, new TypeLiteral<>() { }); legBinder.addBinding(TransportMode.walk).toInstance((context, mode, leg, option) -> -0.5); - MapBinder> tripBinder = MapBinder.newMapBinder(binder(), new TypeLiteral<>() { + MapBinder tripBinder = MapBinder.newMapBinder(binder(), new TypeLiteral<>() { }, new TypeLiteral<>() { }); @@ -251,7 +251,7 @@ protected CandidatePruner pruner() { } // Provides fixed estimates for testing - private class CarTripEstimator implements TripEstimator { + private class CarTripEstimator implements TripEstimator { @Override public MinMaxEstimate estimate(EstimatorContext context, String mode, PlanModel plan, List trip, ModeAvailability option) { diff --git a/contribs/minibus/src/main/java/org/matsim/contrib/minibus/schedule/CreatePStops.java b/contribs/minibus/src/main/java/org/matsim/contrib/minibus/schedule/CreatePStops.java index a9838bc4e12..52c5a6fe36d 100644 --- a/contribs/minibus/src/main/java/org/matsim/contrib/minibus/schedule/CreatePStops.java +++ b/contribs/minibus/src/main/java/org/matsim/contrib/minibus/schedule/CreatePStops.java @@ -44,7 +44,7 @@ import org.matsim.contrib.minibus.PConfigGroup; import org.matsim.core.network.algorithms.NetworkCalcTopoType; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.core.utils.io.IOUtils; import org.matsim.pt.transitSchedule.TransitScheduleFactoryImpl; import org.matsim.pt.transitSchedule.api.TransitSchedule; @@ -53,14 +53,14 @@ /** * Create one TransitStopFacility for each car mode link of the network - * + * * @author aneumann, droeder * */ public final class CreatePStops{ - + private final static Logger log = LogManager.getLogger(CreatePStops.class); - + private final Network net; private final PConfigGroup pConfigGroup; private TransitSchedule transitSchedule; @@ -74,7 +74,7 @@ public final class CreatePStops{ private List topoTypesForStops = null; private NetworkCalcTopoType networkCalcTopoType; - + public static TransitSchedule createPStops(Network network, PConfigGroup pConfigGroup){ return createPStops(network, pConfigGroup, null); } @@ -84,14 +84,14 @@ public static TransitSchedule createPStops(Network network, PConfigGroup pConfig cS.run(); return cS.getTransitSchedule(); } - + /** * Creates PStops in two ways. First, if a serviceAreaFile is defined in the config and this file exists, the file is used. * Second, the (default) min/max-x/y-values are used. - * + * * Following FileTypes are supported: *

    - *
  • Shapefiles with polygons. If one ore more attributes are defined, the last one is parsed + *
  • Shapefiles with polygons. If one ore more attributes are defined, the last one is parsed * to Boolean and used to get include- and exclude-areas.
  • *
  • Textfile, containing a List of x/y-pairs per row, divided by semicolon. The first and the last coordinate should be equal * to get a closed and well defined Geometry.
  • @@ -104,13 +104,13 @@ private CreatePStops(Network net, PConfigGroup pConfigGroup, TransitSchedule rea this.net = net; this.pConfigGroup = pConfigGroup; this.factory = new GeometryFactory(); - + this.linkId2StopFacilityMap = new LinkedHashMap<>(); - + Set> stopsWithoutLinkIds = new TreeSet<>(); int warnCounter = 10; - + if (realTransitSchedule != null) { for (TransitStopFacility stopFacility : realTransitSchedule.getFacilities().values()) { if (stopFacility.getLinkId() != null) { @@ -131,7 +131,7 @@ private CreatePStops(Network net, PConfigGroup pConfigGroup, TransitSchedule rea } } } - + this.exclude = this.factory.buildGeometry(new ArrayList()); if(!new File(pConfigGroup.getServiceAreaFile()).exists()){ log.warn("file " + this.pConfigGroup.getServiceAreaFile() + " not found. Falling back to min/max serviceArea parameters."); @@ -140,7 +140,7 @@ private CreatePStops(Network net, PConfigGroup pConfigGroup, TransitSchedule rea log.warn("using " + this.pConfigGroup.getServiceAreaFile() + " for servicearea. x/y-values defined in the config are not used."); createServiceArea(pConfigGroup.getServiceAreaFile()); } - + if (stopsWithoutLinkIds.size() > 0) { log.warn("There are " + stopsWithoutLinkIds.size() + " stop facilities without a link id, namely: " + stopsWithoutLinkIds.toString()); } @@ -184,7 +184,7 @@ private void createServiceArea(String serviceAreaFile) { * @param serviceAreaFile */ private void createServiceAreaTxt(String serviceAreaFile) { - + List lines = new ArrayList<>(); String line; try { @@ -202,15 +202,15 @@ private void createServiceAreaTxt(String serviceAreaFile) { } catch (IOException e) { e.printStackTrace(); } - + if(lines.size() < 3){ log.warn("an area needs at least 3 points, to be defined. Falling back to simple (default) x/y-values..."); this.createServiceArea(pConfigGroup.getMinX(), pConfigGroup.getMaxX(), pConfigGroup.getMinY(), pConfigGroup.getMaxY()); - return; + return; } - + Coordinate[] c = new Coordinate[lines.size() + 1]; - + double x,y; for(int i = 0; i < lines.size(); i++){ x = Double.parseDouble(lines.get(i).split(";")[0]); @@ -226,10 +226,10 @@ private void createServiceAreaTxt(String serviceAreaFile) { * @param serviceAreaFile */ private void createServiceAreaShp(String serviceAreaFile) { - Collection features = new ShapeFileReader().readFileAndInitialize(serviceAreaFile); + Collection features = new GeoFileReader().readFileAndInitialize(serviceAreaFile); Collection include = new ArrayList<>(); Collection exclude = new ArrayList<>(); - + for(SimpleFeature f: features){ boolean incl = true; Geometry g = null; @@ -240,7 +240,7 @@ private void createServiceAreaShp(String serviceAreaFile) { g = (Geometry) o; } // TODO use a better way to get the attributes, maybe directly per index. - // Now the last attribute is used per default... + // Now the last attribute is used per default... else if (o instanceof String){ incl = Boolean.parseBoolean((String) o); } @@ -253,46 +253,46 @@ else if (o instanceof String){ } } } - this.include = this.factory.createGeometryCollection( + this.include = this.factory.createGeometryCollection( include.toArray(new Geometry[include.size()])).buffer(0); - this.exclude = this.factory.createGeometryCollection( + this.exclude = this.factory.createGeometryCollection( exclude.toArray(new Geometry[exclude.size()])).buffer(0); } private void run(){ this.transitSchedule = new TransitScheduleFactoryImpl().createTransitSchedule(); int stopsAdded = 0; - + for (Link link : this.net.getLinks().values()) { if(link.getAllowedModes().contains(TransportMode.car)){ stopsAdded += addStopOnLink(link); } } - + log.info("Added " + stopsAdded + " additional stops for paratransit services"); } - + private int addStopOnLink(Link link) { if(link == null){ return 0; } - + if(!linkToNodeInServiceArea(link)){ return 0; } - + if (linkHasAlreadyAFormalPTStopFromTheGivenSchedule(link)) { return 0; } - + if(!topoTypeAllowed(link)){ return 0; } - + if (link.getFreespeed() >= this.pConfigGroup.getSpeedLimitForStops()) { return 0; } - + if (link.getCapacity() < this.pConfigGroup.getMinCapacityForStops()) { return 0; } @@ -301,12 +301,12 @@ private int addStopOnLink(Link link) { log.warn("Link " + link.getId() + " has already a stop. This should not happen. Check code."); return 0; } - + Id stopId = Id.create(this.pConfigGroup.getPIdentifier() + link.getId(), TransitStopFacility.class); TransitStopFacility stop = this.transitSchedule.getFactory().createTransitStopFacility(stopId, link.getToNode().getCoord(), false); stop.setLinkId(link.getId()); this.transitSchedule.addStopFacility(stop); - return 1; + return 1; } private boolean topoTypeAllowed(Link link) { @@ -316,7 +316,7 @@ private boolean topoTypeAllowed(Link link) { } Integer topoType = this.networkCalcTopoType.getTopoType(link.getToNode()); return this.topoTypesForStops.contains(topoType); - } + } private boolean linkToNodeInServiceArea(Link link) { Point p = factory.createPoint(MGC.coord2Coordinate(link.getToNode().getCoord())); diff --git a/contribs/minibus/src/main/java/org/matsim/contrib/minibus/schedule/CreatePStopsOnJunctionApproachesAndBetweenJunctions.java b/contribs/minibus/src/main/java/org/matsim/contrib/minibus/schedule/CreatePStopsOnJunctionApproachesAndBetweenJunctions.java index c8f6676e835..f2303896615 100644 --- a/contribs/minibus/src/main/java/org/matsim/contrib/minibus/schedule/CreatePStopsOnJunctionApproachesAndBetweenJunctions.java +++ b/contribs/minibus/src/main/java/org/matsim/contrib/minibus/schedule/CreatePStopsOnJunctionApproachesAndBetweenJunctions.java @@ -55,7 +55,7 @@ import org.matsim.core.network.filter.NetworkFilterManager; import org.matsim.core.network.filter.NetworkLinkFilter; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.core.utils.io.IOUtils; import org.matsim.pt.transitSchedule.TransitScheduleFactoryImpl; import org.matsim.pt.transitSchedule.api.TransitSchedule; @@ -64,14 +64,14 @@ /** * Create one TransitStopFacility for each car mode link of the network - * + * * @author aneumann, droeder, gleich * */ public final class CreatePStopsOnJunctionApproachesAndBetweenJunctions{ - + private final static Logger log = LogManager.getLogger(CreatePStopsOnJunctionApproachesAndBetweenJunctions.class); - + private final Network net; private final Network intersectionSimplifiedRoadNetwork; private final PConfigGroup pConfigGroup; @@ -89,7 +89,7 @@ public final class CreatePStopsOnJunctionApproachesAndBetweenJunctions{ private final double stopDistance; private NetworkCalcTopoType networkCalcTopoType; - + public static TransitSchedule createPStops(Network network, PConfigGroup pConfigGroup, NetworkConfigGroup networkConfigGroup) { return createPStops(network, pConfigGroup, null, networkConfigGroup); } @@ -99,14 +99,14 @@ public static TransitSchedule createPStops(Network network, PConfigGroup pConfig cS.run(); return cS.getTransitSchedule(); } - + /** * Creates PStops in two ways. First, if a serviceAreaFile is defined in the config and this file exists, the file is used. * Second, the (default) min/max-x/y-values are used. - * + * * Following FileTypes are supported: *
      - *
    • Shapefiles with polygons. If one ore more attributes are defined, the last one is parsed + *
    • Shapefiles with polygons. If one ore more attributes are defined, the last one is parsed * to Boolean and used to get include- and exclude-areas.
    • *
    • Textfile, containing a List of x/y-pairs per row, divided by semicolon. The first and the last coordinate should be equal * to get a closed and well defined Geometry.
    • @@ -120,13 +120,13 @@ private CreatePStopsOnJunctionApproachesAndBetweenJunctions(Network net, PConfig this.pConfigGroup = pConfigGroup; this.networkConfigGroup = networkConfigGroup; this.factory = new GeometryFactory(); - + this.linkId2StopFacilityMap = new LinkedHashMap<>(); - + Set> stopsWithoutLinkIds = new TreeSet<>(); int warnCounter = 10; - + if (realTransitSchedule != null) { for (TransitStopFacility stopFacility : realTransitSchedule.getFacilities().values()) { if (stopFacility.getLinkId() != null) { @@ -147,7 +147,7 @@ private CreatePStopsOnJunctionApproachesAndBetweenJunctions(Network net, PConfig } } } - + this.exclude = this.factory.buildGeometry(new ArrayList()); if(!new File(pConfigGroup.getServiceAreaFile()).exists()){ log.warn("file " + this.pConfigGroup.getServiceAreaFile() + " not found. Falling back to min/max serviceArea parameters."); @@ -156,14 +156,14 @@ private CreatePStopsOnJunctionApproachesAndBetweenJunctions(Network net, PConfig log.warn("using " + this.pConfigGroup.getServiceAreaFile() + " for servicearea. x/y-values defined in the config are not used."); createServiceArea(pConfigGroup.getServiceAreaFile()); } - + if (stopsWithoutLinkIds.size() > 0) { log.warn("There are " + stopsWithoutLinkIds.size() + " stop facilities without a link id, namely: " + stopsWithoutLinkIds.toString()); } this.topoTypesForStops = this.pConfigGroup.getTopoTypesForStops(); this.networkCalcTopoType = new NetworkCalcTopoType(); this.networkCalcTopoType.run(net); - + // parse StopLocationSelectorParameter from config String[] stopLocationSelectorParameter = pConfigGroup.getStopLocationSelectorParameter().split(","); if (stopLocationSelectorParameter.length != 3) { @@ -178,7 +178,7 @@ private CreatePStopsOnJunctionApproachesAndBetweenJunctions(Network net, PConfig } else { stopDistance = Double.parseDouble(stopLocationSelectorParameter[2]); } - + intersectionSimplifiedRoadNetwork = generateIntersectionSimplifiedNetwork(pmin, epsilon); } @@ -216,7 +216,7 @@ private void createServiceArea(String serviceAreaFile) { * @param serviceAreaFile */ private void createServiceAreaTxt(String serviceAreaFile) { - + List lines = new ArrayList<>(); String line; try { @@ -234,15 +234,15 @@ private void createServiceAreaTxt(String serviceAreaFile) { } catch (IOException e) { e.printStackTrace(); } - + if(lines.size() < 3){ log.warn("an area needs at least 3 points, to be defined. Falling back to simple (default) x/y-values..."); this.createServiceArea(pConfigGroup.getMinX(), pConfigGroup.getMaxX(), pConfigGroup.getMinY(), pConfigGroup.getMaxY()); - return; + return; } - + Coordinate[] c = new Coordinate[lines.size() + 1]; - + double x,y; for(int i = 0; i < lines.size(); i++){ x = Double.parseDouble(lines.get(i).split(";")[0]); @@ -258,10 +258,10 @@ private void createServiceAreaTxt(String serviceAreaFile) { * @param serviceAreaFile */ private void createServiceAreaShp(String serviceAreaFile) { - Collection features = new ShapeFileReader().readFileAndInitialize(serviceAreaFile); + Collection features = new GeoFileReader().readFileAndInitialize(serviceAreaFile); Collection include = new ArrayList<>(); Collection exclude = new ArrayList<>(); - + for(SimpleFeature f: features){ boolean incl = true; Geometry g = null; @@ -272,7 +272,7 @@ private void createServiceAreaShp(String serviceAreaFile) { g = (Geometry) o; } // TODO use a better way to get the attributes, maybe directly per index. - // Now the last attribute is used per default... + // Now the last attribute is used per default... else if (o instanceof String){ incl = Boolean.parseBoolean((String) o); } @@ -285,18 +285,18 @@ else if (o instanceof String){ } } } - this.include = this.factory.createGeometryCollection( + this.include = this.factory.createGeometryCollection( include.toArray(new Geometry[include.size()])).buffer(0); - this.exclude = this.factory.createGeometryCollection( + this.exclude = this.factory.createGeometryCollection( exclude.toArray(new Geometry[exclude.size()])).buffer(0); } - + /* Generate a simplified network to determine stop locations (the simplified network will not be used in simulation) */ private Network generateIntersectionSimplifiedNetwork(double pmin, int epsilon) { // Extract road network NetworkFilterManager nfmCar = new NetworkFilterManager(net, networkConfigGroup); nfmCar.addLinkFilter(new NetworkLinkFilter() { - + @Override public boolean judgeLink(Link l) { if (l.getAllowedModes().contains("car")) return true; @@ -304,11 +304,11 @@ public boolean judgeLink(Link l) { } }); Network roadNetwork = nfmCar.applyFilters(); - + // Remove low capacity links NetworkFilterManager nfm = new NetworkFilterManager(roadNetwork, networkConfigGroup); nfm.addLinkFilter(new NetworkLinkFilter() { - + @Override public boolean judgeLink(Link l) { if (l.getCapacity() >= pConfigGroup.getMinCapacityForStops()) return true; @@ -317,58 +317,58 @@ public boolean judgeLink(Link l) { }); Network newRoadNetwork = nfm.applyFilters(); new NetworkCleaner().run(newRoadNetwork); - + // Run Johan's intersection clustering algorithm IntersectionSimplifier ns = new IntersectionSimplifier(pmin, epsilon); Network newClusteredIntersectionsRoadNetwork = ns.simplify(newRoadNetwork); new NetworkCleaner().run(newClusteredIntersectionsRoadNetwork); - + // intersection clustering leaves some duplicate links (same start and end node), merge them NetworkMergeDoubleLinks mergeDoubleLinks = new NetworkMergeDoubleLinks(MergeType.MAXIMUM, LogInfoLevel.NOINFO); mergeDoubleLinks.run(newClusteredIntersectionsRoadNetwork); - + // Merge all links between two junctions NetworkSimplifier simplifier = new NetworkSimplifier(); // Merge links with different attributes, because we will not use the output network for simulation simplifier.setMergeLinkStats(true); simplifier.run(newClusteredIntersectionsRoadNetwork); new NetworkCleaner().run(newClusteredIntersectionsRoadNetwork); - + return(newClusteredIntersectionsRoadNetwork); } private void run(){ this.transitSchedule = new TransitScheduleFactoryImpl().createTransitSchedule(); int stopsAdded = 0; - + /* handle all (merged) links between junction */ for (Link link : this.intersectionSimplifiedRoadNetwork.getLinks().values()) { if(link.getAllowedModes().contains(TransportMode.car)){ stopsAdded += addStopForSimplifiedNetworkLink(link); } } - + log.info("Added " + stopsAdded + " additional stops for paratransit services"); } - + private int addStopForSimplifiedNetworkLink(Link simplifiedNetworkLink) { int numberOfStopsCreated = 0; String[] originalIdsMergedLink = simplifiedNetworkLink.getId().toString().split("-"); /* Bus stops should be placed on approaches to road junctions, and not inside junction - * areas. - * The Intersection simplifier creates a network where most junction nodes are merged into + * areas. + * The Intersection simplifier creates a network where most junction nodes are merged into * one node per junction. By merging two neighbouring nodes, all links in between are removed. * So, initially no links are modified, but most links located inside a junction area are - * removed. Than the NetworkSimplifier merges short links between intersections, thereby + * removed. Than the NetworkSimplifier merges short links between intersections, thereby * creating a network where between two junctions there is at most one link per direction. * Given that simplified network the corresponding stop locations are looked up on the * original network using the link ids remaining in the simplified network. - * + * * First add stops at links approaching junction areas: - * Start from last part of the merged link and move forward until the first intersection + * Start from last part of the merged link and move forward until the first intersection * (>=2 outlinks) is reached. This should be in most cases the begin of the junction area. * - * It could be that the original network already had "-" in link ids, + * It could be that the original network already had "-" in link ids, * so the link would not be found here. Add previous id parts of the merged link. * Go from the last link id backwards, because we want to find the last link. */ @@ -384,33 +384,33 @@ private int addStopForSimplifiedNetworkLink(Link simplifiedNetworkLink) { reappendedlinkIds = originalIdsMergedLink[indexOfNextLinkIdToBeAppended] + "-" + reappendedlinkIds; lastPartOfMergedLink = net.getLinks().get(Id.createLinkId(reappendedlinkIds)); } - + /* Get node ids of all nodes merged into the clustered node where the merged link ends */ Set> originalNodeIdsBeforeClustering = new HashSet<>(); String[] clusteredNodeIdSplit = simplifiedNetworkLink.getToNode().getId().toString().split("-"); for (String originalNodeId : clusteredNodeIdSplit) { originalNodeIdsBeforeClustering.add(Id.createNodeId(originalNodeId)); } - - while (lastPartOfMergedLink.getToNode().getOutLinks().size() <= 1 && + + while (lastPartOfMergedLink.getToNode().getOutLinks().size() <= 1 && ! originalNodeIdsBeforeClustering.contains(lastPartOfMergedLink.getToNode().getId())) { lastPartOfMergedLink = lastPartOfMergedLink.getToNode().getOutLinks().values().iterator().next(); } - + numberOfStopsCreated += addStopOnLink(lastPartOfMergedLink); - + /* Go backward from junction approach and add infill stops to create a proper bus stop spacing between junctions. */ double distanceFromLastStop = lastPartOfMergedLink.getLength(); if (numberOfStopsCreated == 0) { - /* No stop was created on link approaching the junction (due to link characteristics excluded + /* No stop was created on link approaching the junction (due to link characteristics excluded in pConfigGroup, see {@link addStopOnLink(Link link)}), so make the algorithm add one on the next suitable link */ distanceFromLastStop = stopDistance; } - + Link currentLink = lastPartOfMergedLink; reappendedlinkIds = ""; - + /* Stop if the previous junction area is reached */ while (indexOfNextLinkIdToBeAppended > 0) { indexOfNextLinkIdToBeAppended--; @@ -418,9 +418,9 @@ private int addStopForSimplifiedNetworkLink(Link simplifiedNetworkLink) { reappendedlinkIds = originalIdsMergedLink[indexOfNextLinkIdToBeAppended]; } else { reappendedlinkIds = originalIdsMergedLink[indexOfNextLinkIdToBeAppended] + "-" + reappendedlinkIds; - } + } Link tryLinkId = net.getLinks().get(Id.createLinkId(reappendedlinkIds)); - + if (tryLinkId == null) { /* Next backward link could not be found, because it's id already contains "-", e.g. because */ continue; @@ -428,11 +428,11 @@ private int addStopForSimplifiedNetworkLink(Link simplifiedNetworkLink) { distanceFromLastStop += currentLink.getLength(); currentLink = tryLinkId; reappendedlinkIds = ""; - + if (distanceFromLastStop >= stopDistance) { /* Try to add a new stop on current link */ int stopCreated = addStopOnLink(currentLink); - + // TODO: Add check of distance to next junction further backward if (stopCreated > 0) { /* If stop was added, reset distanceFromLastStop */ @@ -442,31 +442,31 @@ private int addStopForSimplifiedNetworkLink(Link simplifiedNetworkLink) { } } } - + return numberOfStopsCreated; } - + private int addStopOnLink(Link link) { if(link == null){ return 0; } - + if(!linkToNodeInServiceArea(link)){ return 0; } - + if (linkHasAlreadyAFormalPTStopFromTheGivenSchedule(link)) { return 0; } - + if(!topoTypeAllowed(link)){ return 0; } - + if (link.getFreespeed() >= this.pConfigGroup.getSpeedLimitForStops()) { return 0; } - + if (link.getCapacity() < this.pConfigGroup.getMinCapacityForStops()) { return 0; } @@ -475,17 +475,17 @@ private int addStopOnLink(Link link) { log.warn("Link " + link.getId() + " has already a stop in the given (non-paratransit) TransitSchedule. This should not happen. Check code."); return 0; } - + if (this.transitSchedule.getFacilities().get(Id.create(pConfigGroup.getPIdentifier() + link.getId().toString(), TransitStopFacility.class)) != null) { log.warn("Link " + link.getId() + " has already a stop. This should not happen. Check code."); return 0; } - + Id stopId = Id.create(this.pConfigGroup.getPIdentifier() + link.getId(), TransitStopFacility.class); TransitStopFacility stop = this.transitSchedule.getFactory().createTransitStopFacility(stopId, link.getToNode().getCoord(), false); stop.setLinkId(link.getId()); this.transitSchedule.addStopFacility(stop); - return 1; + return 1; } private boolean topoTypeAllowed(Link link) { @@ -495,7 +495,7 @@ private boolean topoTypeAllowed(Link link) { } Integer topoType = this.networkCalcTopoType.getTopoType(link.getToNode()); return this.topoTypesForStops.contains(topoType); - } + } private boolean linkToNodeInServiceArea(Link link) { Point p = factory.createPoint(MGC.coord2Coordinate(link.getToNode().getCoord())); diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/run/RunAreaAnalysis.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/run/RunAreaAnalysis.java index 270cb77fa09..7643b4ea3b4 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/run/RunAreaAnalysis.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/run/RunAreaAnalysis.java @@ -28,7 +28,7 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.population.io.StreamingPopulationReader; import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; public class RunAreaAnalysis { @@ -38,8 +38,8 @@ public static void main(String[] args) { Path experiencedPlansPath = Paths.get(args[1]); Path networkFile = Paths.get(args[2]); - Collection features = ShapeFileReader.getAllFeatures(shapefile.toString()); - + Collection features = GeoFileReader.getAllFeatures(shapefile.toString()); + Config conf = ConfigUtils.createConfig(); conf.network().setInputFile(networkFile.toString()); RegionModeshareAnalyzer modeshares = new RegionModeshareAnalyzer(features); diff --git a/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingchoice/run/RunParkingSearchScenarioIT.java b/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingchoice/run/RunParkingSearchScenarioIT.java index fa0dc4f5ffd..e3959961195 100644 --- a/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingchoice/run/RunParkingSearchScenarioIT.java +++ b/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingchoice/run/RunParkingSearchScenarioIT.java @@ -33,7 +33,7 @@ import org.matsim.core.events.EventsUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; /** * @author jbischoff @@ -108,8 +108,8 @@ void testRunParkingDistanceMemoryStrategy() { { String expected = utils.getInputDirectory() + "/output_events.xml.gz"; String actual = utils.getOutputDirectory() + "/output_events.xml.gz"; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles(expected, actual); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles(expected, actual); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } catch (Exception e) { e.printStackTrace(); @@ -146,8 +146,8 @@ void testRunParkingNearestParkingSpotStrategy() { { String expected = utils.getInputDirectory() + "/output_events.xml.gz"; String actual = utils.getOutputDirectory() + "/output_events.xml.gz"; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles(expected, actual); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles(expected, actual); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } catch (Exception e) { e.printStackTrace(); diff --git a/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingproxy/run/RunWithParkingProxyIT.java b/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingproxy/run/RunWithParkingProxyIT.java index 6d17839c44c..e87a4afbaba 100644 --- a/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingproxy/run/RunWithParkingProxyIT.java +++ b/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingproxy/run/RunWithParkingProxyIT.java @@ -30,7 +30,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator.Result; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class RunWithParkingProxyIT { private static final Logger log = LogManager.getLogger(RunWithParkingProxyIT.class); @@ -50,8 +50,8 @@ void testMain(){ { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - Result result = EventsUtils.compareEventsFiles( expected, actual ); - if(!result.equals(Result.FILES_ARE_EQUAL)) { + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + if(!result.equals(ComparisonResult.FILES_ARE_EQUAL)) { throw new RuntimeException("Events comparison ended with result " + result.name()); } } diff --git a/contribs/protobuf/pom.xml b/contribs/protobuf/pom.xml index c53160b6208..202864deec5 100644 --- a/contribs/protobuf/pom.xml +++ b/contribs/protobuf/pom.xml @@ -11,7 +11,7 @@ protobuf - 3.25.2 + 4.26.0 diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngine.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngine.java index ff98123051a..3b20be8ca7c 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngine.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngine.java @@ -55,7 +55,7 @@ final class RailsimEngine implements Steppable { * Additional safety distance in meter that is added to the reservation distance. * Ensure that trains always have enough distance to progress. */ - private static double SAFETY_DIST = 10; + private static final double SAFETY_DIST = 10; private static final Logger log = LogManager.getLogger(RailsimEngine.class); private final EventsManager eventsManager; private final RailsimConfigGroup config; @@ -193,7 +193,7 @@ private void blockTrack(double time, UpdateEvent event) { updatePosition(time, event); if (!blockLinkTracks(time, state)) { - + // train needs to stop decideTargetSpeed(event, state); event.checkReservation = time + config.pollInterval; @@ -388,7 +388,7 @@ private void enterLink(double time, UpdateEvent event) { return; } - // Train stopped and reserves next links + // Train stopped exactly at the end of the link and tries to enter the next link if (FuzzyUtils.equals(state.speed, 0) && !blockLinkTracks(time, state)) { RailLink currentLink = state.route.get(state.routeIdx); @@ -766,6 +766,7 @@ private double retrieveAllowedMaxSpeed(TrainState state) { double maxSpeed = resources.getLink(state.headLink).getAllowedFreespeed(state.driver); + // get minium allowed speed on all links occupied by the train for (int i = state.routeIdx - 1; i >= 0; i--) { RailLink link = state.route.get(i); maxSpeed = Math.min(maxSpeed, link.getAllowedFreespeed(state.driver)); @@ -780,7 +781,7 @@ private double retrieveAllowedMaxSpeed(TrainState state) { /** * Remove all trains from simulation and generate events at the end of the day. * - * @param now end of day time + * @param now end of daytime */ void clearTrains(double now) { diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/UpdateEvent.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/UpdateEvent.java index a8a2c246ddd..1fc5a29b1ef 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/UpdateEvent.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/UpdateEvent.java @@ -55,6 +55,9 @@ final class UpdateEvent implements Comparable { this.unblockLink = null; } + /** + * Update event to unblock a link after minimum headway time. + */ UpdateEvent(TrainState state, RailLink unblockLink, double time) { this.state = state; this.unblockLink = unblockLink; diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/deadlocks/SimpleDeadlockAvoidance.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/deadlocks/SimpleDeadlockAvoidance.java index 6ad95f76623..c92e0788325 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/deadlocks/SimpleDeadlockAvoidance.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/deadlocks/SimpleDeadlockAvoidance.java @@ -43,14 +43,15 @@ public void onReserve(double time, RailResource resource, TrainPosition position RailLink link = position.getRoute(i); RailResource r = link.getResource(); // // Iterate through route until requested resource is present - if (r == resource) { resourceFound = true; } + // all resources before requested resource can be ignored if (!resourceFound) continue; + // check for all conflict points at and beyond the resource if (isConflictPoint(r)) { Reservation reservation = conflictPoints.computeIfAbsent(r, k -> new Reservation()); @@ -63,6 +64,7 @@ public void onReserve(double time, RailResource resource, TrainPosition position reservation.trains.add(position.getDriver()); } else + // as soon as we find an avoidance point we can stop reserving break; } diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/disposition/SimpleDisposition.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/disposition/SimpleDisposition.java index 7bb0642bfad..3e1094fc776 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/disposition/SimpleDisposition.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/disposition/SimpleDisposition.java @@ -111,7 +111,7 @@ public DispositionResponse requestNextSegment(double time, TrainPosition positio } } - return new DispositionResponse(reserveDist, stop ? 0 : Double.POSITIVE_INFINITY, detour); + return new DispositionResponse(reserveDist, stop ? 0 : Double.POSITIVE_INFINITY, null); } private Detour checkDetour(double time, List segment, TrainPosition position) { diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailLink.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailLink.java index 06be3f5556e..8702b955afa 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailLink.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailLink.java @@ -28,7 +28,7 @@ import java.util.Objects; /** - * Rail links which can has multiple tracks and corresponds to exactly one link. + * Rail links can have multiple tracks and corresponds to exactly one link. */ public final class RailLink implements HasLinkId { private final Id id; diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailResourceManager.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailResourceManager.java index 9a04894bf00..14b90ad151d 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailResourceManager.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailResourceManager.java @@ -47,7 +47,7 @@ public final class RailResourceManager { public static final int ANY_TRACK = -1; /** - * Constant to indicate than any track is allowed as long as the opposing direction is not blocked. + * Constant to indicate that any track is allowed as long as the opposing direction is not blocked. */ public static final int ANY_TRACK_NON_BLOCKING = -2; diff --git a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java index 6a61f5d0f16..b139bfd423b 100644 --- a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java +++ b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java @@ -243,6 +243,11 @@ void testMicroTrainFollowingVaryingSpeed() { EventsCollector collector = runSimulation(new File(utils.getPackageInputDirectory(), "microTrainFollowingVaryingSpeed")); } + @Test + void testMicroTrainFollowingFixedVsMovingBlock() { + EventsCollector collector = runSimulation(new File(utils.getPackageInputDirectory(), "microTrainFollowingFixedVsMovingBlock")); + } + @Test void testMicroStationSameLink() { EventsCollector collector = runSimulation(new File(utils.getPackageInputDirectory(), "microStationSameLink")); diff --git a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimDeadlockTest.java b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimDeadlockTest.java index ddd998ee3f1..bc7d7cfca00 100644 --- a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimDeadlockTest.java +++ b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimDeadlockTest.java @@ -67,7 +67,7 @@ public void deadlock() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "HG", "DC"); test.doSimStepUntil(250); -// test.debugFiles(collector, "deadLock"); + test.debugFiles(collector, utils.getOutputDirectory() + "/deadLock"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 240, "y1y", 0) @@ -93,7 +93,7 @@ public void deadLockAvoidancePoint() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "HG", "CD"); test.doSimStepUntil(250); -// test.debugFiles(collector, "deadLockAvoidancePoint"); + test.debugFiles(collector, utils.getOutputDirectory() + "/deadLockAvoidancePoint"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 240, "y1y", 0) @@ -118,7 +118,7 @@ public void avoidancePoint() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "HG", "CD"); test.doSimStepUntil(800); - test.debugFiles(collector, "avoidancePoint"); + test.debugFiles(collector, utils.getOutputDirectory() + "/avoidancePoint"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 420, "EF", 0) @@ -147,7 +147,7 @@ public void tooSmall() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2b", 0, "HG", "CD"); test.doSimStepUntil(1500); -// test.debugFiles(collector, "tooSmall"); + test.debugFiles(collector, utils.getOutputDirectory() + "/tooSmall"); RailsimTestUtils.assertThat(collector) @@ -166,7 +166,7 @@ public void oneWay() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "HG", "CD"); test.doSimStepUntil(800); -// test.debugFiles(collector, "oneWay"); + test.debugFiles(collector, utils.getOutputDirectory() + "/oneWay"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 350, "EF", 0) @@ -185,7 +185,7 @@ public void twoWay() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2b", 0, "HG", "CD"); test.doSimStepUntil(800); -// test.debugFiles(collector, "twoWay"); + test.debugFiles(collector, utils.getOutputDirectory() + "/twoWay"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1a", 350, "EF", 0) @@ -217,7 +217,7 @@ public void movingBlock() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2b", 0, "HG", "CD"); test.doSimStepUntil(1500); -// test.debugFiles(collector, "movingBlock"); + test.debugFiles(collector, utils.getOutputDirectory() + "/movingBlock"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1a", 670, "EF", 0) diff --git a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineMovingBlockTest.java b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineMovingBlockTest.java index ae31cac7539..134959bb6a2 100644 --- a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineMovingBlockTest.java +++ b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineMovingBlockTest.java @@ -71,11 +71,9 @@ public void multipleTrains() { test.doSimStepUntil(5_000); -// test.debugFiles(collector, "movingBlock"); + test.debugFiles(collector, utils.getOutputDirectory() + "/movingBlock"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 2370, 200, 0) - .hasTrainState("cargo", 3268, 200, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 2370, 200, 0).hasTrainState("cargo", 3268, 200, 0) .hasTrainState("sprinter", 3345, 200, 0); test = getTestEngine("networkMovingBlocks.xml"); @@ -84,10 +82,9 @@ public void multipleTrains() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 120, "l1-2", "l6-7"); test.doStateUpdatesUntil(5_000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/movingBlock_detailed"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 2370, 200, 0) - .hasTrainState("cargo", 3268, 200, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 2370, 200, 0).hasTrainState("cargo", 3268, 200, 0) .hasTrainState("sprinter", 3345, 200, 0); } @@ -100,22 +97,18 @@ public void opposite() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter2", 400, "l6-5", "l2-1"); test.doSimStepUntil(2_000); -// test.debugFiles(collector, "opposite"); + test.debugFiles(collector, utils.getOutputDirectory() + "/opposite"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("sprinter2", 1368, 200, 0) - .hasTrainState("sprinter", 1559, 200, 0); + RailsimTestUtils.assertThat(collector).hasTrainState("sprinter2", 1368, 200, 0).hasTrainState("sprinter", 1559, 200, 0); test = getTestEngine("networkMovingBlocks.xml"); RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 0, "l1-2", "l6-7"); RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter2", 400, "l6-5", "l2-1"); test.doStateUpdatesUntil(2_000, 5); -// test.debugFiles(collector, "opposite_detailed"); + test.debugFiles(collector, utils.getOutputDirectory() + "/opposite_detailed"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("sprinter2", 1368, 200, 0) - .hasTrainState("sprinter", 1559, 200, 0); + RailsimTestUtils.assertThat(collector).hasTrainState("sprinter2", 1368, 200, 0).hasTrainState("sprinter", 1559, 200, 0); } @@ -130,11 +123,9 @@ public void multiTrack() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 120, "l1-2", "l6-7"); test.doSimStepUntil(5_000); -// test.debugFiles(collector, "multiTrack"); + test.debugFiles(collector, utils.getOutputDirectory() + "/multiTrack"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 2370, 200, 0) - .hasTrainState("cargo", 3268, 200, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 2370, 200, 0).hasTrainState("cargo", 3268, 200, 0) .hasTrainState("sprinter", 1984, 200, 0); test = getTestEngine("networkMovingBlocks.xml", l -> RailsimUtils.setTrainCapacity(l, 3)); @@ -144,10 +135,9 @@ public void multiTrack() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 120, "l1-2", "l6-7"); test.doStateUpdatesUntil(5_000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/multiTrack_detailed"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 2370, 200, 0) - .hasTrainState("cargo", 3268, 200, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 2370, 200, 0).hasTrainState("cargo", 3268, 200, 0) .hasTrainState("sprinter", 1984, 200, 0); } @@ -162,11 +152,9 @@ public void mixed() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 0, "1-2", "20-21"); test.doSimStepUntil(2_000); - test.debugFiles(collector, "mixed"); + test.debugFiles(collector, utils.getOutputDirectory() + "/mixed"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 1418, 1000, 0) - .hasTrainState("cargo", 1241, 1000, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 1418, 1000, 0).hasTrainState("cargo", 1241, 1000, 0) .hasTrainState("sprinter", 1324, 1000, 0); test = getTestEngine("networkMixedTypes.xml"); @@ -175,10 +163,9 @@ public void mixed() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 0, "1-2", "20-21"); test.doStateUpdatesUntil(2_000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/mixed_detailed"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 1418, 1000, 0) - .hasTrainState("cargo", 1241, 1000, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 1418, 1000, 0).hasTrainState("cargo", 1241, 1000, 0) .hasTrainState("sprinter", 1324, 1000, 0); } diff --git a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineTest.java b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineTest.java index 6d0d67ad81b..cd25d4536ac 100644 --- a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineTest.java +++ b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineTest.java @@ -42,7 +42,7 @@ public class RailsimEngineTest { @RegisterExtension - private MatsimTestUtils utils = new MatsimTestUtils(); + private final MatsimTestUtils utils = new MatsimTestUtils(); private EventsManager eventsManager; private RailsimTestUtils.EventCollector collector; @@ -84,6 +84,7 @@ void testSimple() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "train", 0, "l1-2", "l5-6"); test.doSimStepUntil(400); + test.debugFiles(collector, utils.getOutputDirectory() + "/simple"); RailsimTestUtils.assertThat(collector) .hasSizeGreaterThan(5) @@ -94,6 +95,7 @@ void testSimple() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "train", 0, "l1-2", "l5-6"); test.doStateUpdatesUntil(400, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/simple_detailed"); RailsimTestUtils.assertThat(collector) .hasSizeGreaterThan(5) @@ -111,6 +113,7 @@ void testCongested() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio", 60, "l1-2", "l5-6"); test.doSimStepUntil(600); + test.debugFiles(collector, utils.getOutputDirectory() + "/congested"); RailsimTestUtils.assertThat(collector) .hasTrainState("cargo", 359, 2000, 0) @@ -127,6 +130,7 @@ void testCongestedWithHeadway() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio", 60, "l1-2", "l5-6"); test.doSimStepUntil(600); + test.debugFiles(collector, utils.getOutputDirectory() + "/congestedWithHeadway"); RailsimTestUtils.assertThat(collector) .hasTrainState("cargo", 359, 2000, 0) @@ -144,6 +148,7 @@ void testOpposite() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "l8-7", "l2-1"); test.doSimStepUntil(600); + test.debugFiles(collector, utils.getOutputDirectory() + "/opposite"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1", 293, 600, 0) @@ -156,6 +161,7 @@ void testOpposite() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "l8-7", "l2-1"); test.doStateUpdatesUntil(600, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/opposite_detailed"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1", 293, 600, 0) @@ -171,6 +177,7 @@ void testVaryingSpeedOne() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio", 0, "t1_IN-t1_OUT", "t3_IN-t3_OUT"); test.doSimStepUntil(10000); + test.debugFiles(collector, utils.getOutputDirectory() + "/varyingSpeedOne"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 7599, 0, 2.7777777) @@ -181,6 +188,7 @@ void testVaryingSpeedOne() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio", 0, "t1_IN-t1_OUT", "t3_IN-t3_OUT"); test.doStateUpdatesUntil(10000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/varyingSpeedOne_detailed"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 7599, 0, 2.7777777) @@ -198,6 +206,7 @@ void testVaryingSpeedMany() { } test.doSimStepUntil(30000); + test.debugFiles(collector, utils.getOutputDirectory() + "/varyingSpeedMany"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio0", 7599, 0, 2.7777777) @@ -212,6 +221,7 @@ void testVaryingSpeedMany() { } test.doStateUpdatesUntil(30000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/varyingSpeedMany_detailed"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio0", 7599, 0, 2.7777777) @@ -229,6 +239,7 @@ void testTrainFollowing() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "1-2", "20-21"); test.doSimStepUntil(5000); + test.debugFiles(collector, utils.getOutputDirectory() + "/trainFollowing"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1", 1138, 1000, 0) @@ -239,6 +250,7 @@ void testTrainFollowing() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "1-2", "20-21"); test.doStateUpdatesUntil(5000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/trainFollowing_detailed"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1", 1138, 1000, 0) @@ -254,7 +266,7 @@ void testMicroTrainFollowingVaryingSpeed() { RailsimTestUtils.createDeparture(test, TestVehicle.Cargo, "cargo2", 15, "1-2", "20-21"); test.doSimStepUntil(3000); -// test.debugFiles(collector, "microVarying"); + test.debugFiles(collector, utils.getOutputDirectory() + "/microVarying"); RailsimTestUtils.assertThat(collector) .hasTrainState("cargo1", 1278, 1000, 0) @@ -265,7 +277,7 @@ void testMicroTrainFollowingVaryingSpeed() { RailsimTestUtils.createDeparture(test, TestVehicle.Cargo, "cargo1", 0, "1-2", "20-21"); RailsimTestUtils.createDeparture(test, TestVehicle.Cargo, "cargo2", 15, "1-2", "20-21"); test.doStateUpdatesUntil(3000, 1); -// test.debugFiles(collector, "microVarying_detailed"); + test.debugFiles(collector, utils.getOutputDirectory() + "/microVarying_detailed"); RailsimTestUtils.assertThat(collector) .hasTrainState("cargo1", 1278, 1000, 0) diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/config.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/config.xml new file mode 100644 index 00000000000..da3761b5c4e --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/config.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/trainNetwork.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/trainNetwork.xml new file mode 100644 index 00000000000..9787942945a --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/trainNetwork.xml @@ -0,0 +1,144 @@ + + + + + + Atlantis + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixedBlock + 5 + + + + + fixedBlock + 1 + + + + + fixedBlock + 1 + + + + + fixedBlock + 1 + + + + + fixedBlock + 1 + + + + + fixedBlock + 1 + + + + + fixedBlock + 5 + + + + + + + movingBlock + 5 + + + + + movingBlock + 1 + + + + + movingBlock + 1 + + + + + movingBlock + 1 + + + + + movingBlock + 1 + + + + + movingBlock + 1 + + + + + movingBlock + 5 + + + + + + + + diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitSchedule.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitSchedule.xml new file mode 100644 index 00000000000..104bc96ace6 --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitSchedule.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + rail + + + + + + + + + + + + + + + + + + + + + + rail + + + + + + + + + + + + + + + + + + + + diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitVehicles.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitVehicles.xml new file mode 100644 index 00000000000..5e4675ae4ae --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitVehicles.xml @@ -0,0 +1,48 @@ + + + + + + + 0.1 + 0.1 + + + + + + + + + + + + + + + + + + 0.4 + 0.1 + + + + + + + + + + + + + + + + + + + + + diff --git a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/run/RoadPricingByConfigfileTest.java b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/run/RoadPricingByConfigfileTest.java index 70b4bc9344d..e59e74dd90b 100644 --- a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/run/RoadPricingByConfigfileTest.java +++ b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/run/RoadPricingByConfigfileTest.java @@ -32,7 +32,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; /** * @author vsp-gleich @@ -55,7 +55,7 @@ final void testMain() { { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, EventsUtils.compareEventsFiles( expected, actual )); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, EventsUtils.compareEventsFiles( expected, actual )); } { final Population expected = PopulationUtils.createPopulation( ConfigUtils.createConfig() ); diff --git a/contribs/sbb-extensions/src/main/java/ch/sbb/matsim/analysis/skims/CalculateSkimMatrices.java b/contribs/sbb-extensions/src/main/java/ch/sbb/matsim/analysis/skims/CalculateSkimMatrices.java index c3ba439a7c7..2684832db0a 100644 --- a/contribs/sbb-extensions/src/main/java/ch/sbb/matsim/analysis/skims/CalculateSkimMatrices.java +++ b/contribs/sbb-extensions/src/main/java/ch/sbb/matsim/analysis/skims/CalculateSkimMatrices.java @@ -70,7 +70,7 @@ import org.matsim.core.trafficmonitoring.FreeSpeedTravelTime; import org.matsim.core.trafficmonitoring.TravelTimeCalculator; import org.matsim.core.utils.collections.CollectionUtils; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.core.utils.io.IOUtils; import org.matsim.core.utils.misc.Counter; import org.matsim.core.utils.misc.StringUtils; @@ -233,7 +233,7 @@ public final void calculateSamplingPointsPerZoneFromNetwork(String networkFilena public final void selectSamplingPoints(List locations, int numberOfPointsPerZone, String zonesShapeFilename, String zonesIdAttributeName, Random r) throws IOException { log.info("loading zones from " + zonesShapeFilename); - Collection zones = new ShapeFileReader().readFileAndInitialize(zonesShapeFilename); + Collection zones = new GeoFileReader().readFileAndInitialize(zonesShapeFilename); SpatialIndex zonesQt = new Quadtree(); for (SimpleFeature zone : zones) { Envelope envelope = ((Geometry) (zone.getDefaultGeometry())).getEnvelopeInternal(); diff --git a/contribs/sbb-extensions/src/main/java/ch/sbb/matsim/analysis/skims/MatricesToXY.java b/contribs/sbb-extensions/src/main/java/ch/sbb/matsim/analysis/skims/MatricesToXY.java index 1facd37be1e..405cdb0be00 100644 --- a/contribs/sbb-extensions/src/main/java/ch/sbb/matsim/analysis/skims/MatricesToXY.java +++ b/contribs/sbb-extensions/src/main/java/ch/sbb/matsim/analysis/skims/MatricesToXY.java @@ -29,7 +29,7 @@ import org.apache.logging.log4j.Logger; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Point; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.core.utils.io.IOUtils; import org.opengis.feature.simple.SimpleFeature; @@ -52,7 +52,7 @@ public static void main(String[] args) throws IOException { String xyCsvOutputFilename = args[3]; // path to the csv-file to be written, e.g. /path/to/skim-data.csv log.info("loading zones from " + zonesShapeFilename); - Collection zones = new ShapeFileReader().readFileAndInitialize(zonesShapeFilename); + Collection zones = new GeoFileReader().readFileAndInitialize(zonesShapeFilename); Map zonesById = new HashMap<>(); for (SimpleFeature zone : zones) { String zoneId = zone.getAttribute(zonesIdAttributeName).toString(); diff --git a/contribs/shared_mobility/src/main/java/org/matsim/contrib/shared_mobility/utils/WriteStationShapefile.java b/contribs/shared_mobility/src/main/java/org/matsim/contrib/shared_mobility/utils/WriteStationShapefile.java index 9a870c93a3b..5edcf65eb29 100644 --- a/contribs/shared_mobility/src/main/java/org/matsim/contrib/shared_mobility/utils/WriteStationShapefile.java +++ b/contribs/shared_mobility/src/main/java/org/matsim/contrib/shared_mobility/utils/WriteStationShapefile.java @@ -16,7 +16,7 @@ import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.gis.PointFeatureFactory; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.opengis.feature.simple.SimpleFeature; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -57,6 +57,6 @@ static public void main(String[] args) throws ConfigurationException { null)); } - ShapeFileWriter.writeGeometries(features, cmd.getOptionStrict("output-path")); + GeoFileWriter.writeGeometries(features, cmd.getOptionStrict("output-path")); } } diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java index 9e341d444a6..ba97489f89e 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java @@ -38,8 +38,7 @@ import org.matsim.core.scenario.ScenarioUtils; import org.matsim.testcases.MatsimTestUtils; import org.matsim.utils.eventsfilecomparison.EventsFileComparator; - -import static org.matsim.utils.eventsfilecomparison.EventsFileComparator.*; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; /** * @author aneumann @@ -125,7 +124,7 @@ private void runQSimWithSignals(final Scenario scenario) { eventsXmlWriter.closeFile(); // Assert.assertEquals("different events files", EventsFileComparator.compareAndReturnInt(this.testUtils.getInputDirectory() + EVENTSFILE, eventsOut), 0); - Assertions.assertEquals( Result.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( this.testUtils.getInputDirectory() + EVENTSFILE, eventsOut ) ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( this.testUtils.getInputDirectory() + EVENTSFILE, eventsOut ) ); } } diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/integration/SignalSystemsIT.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/integration/SignalSystemsIT.java index 49e8af1f140..b44a5cf35ea 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/integration/SignalSystemsIT.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/integration/SignalSystemsIT.java @@ -36,6 +36,7 @@ import org.matsim.core.scenario.ScenarioUtils; import org.matsim.testcases.MatsimTestUtils; import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; import java.io.File; @@ -88,7 +89,7 @@ void testSignalSystems() { //iteration 0 String iterationOutput = controlerOutputDir + "ITERS/it.0/"; - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( inputDirectory + "0.events.xml.gz", iterationOutput + "0.events.xml.gz"), "different events files after iteration 0 " @@ -113,7 +114,7 @@ void testSignalSystems() { //iteration 10 String iterationOutput = controlerOutputDir + "ITERS/it.10/"; - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( inputDirectory + "10.events.xml.gz", iterationOutput + "10.events.xml.gz" ), "different event files after iteration 10" ); @@ -181,7 +182,7 @@ void testSignalSystemsWTryEndTimeThenDuration() { //iteration 0 String iterationOutput = controlerOutputDir + "ITERS/it.0/"; - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( inputDirectory + "0.events.xml.gz", iterationOutput + "0.events.xml.gz"), "different events files after iteration 0 " @@ -206,7 +207,7 @@ void testSignalSystemsWTryEndTimeThenDuration() { //iteration 10 String iterationOutput = controlerOutputDir + "ITERS/it.10/"; - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( inputDirectory + "10.events.xml.gz", iterationOutput + "10.events.xml.gz"), "different event files after iteration 10" ); 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 diff --git a/contribs/small-scale-traffic-generation/README.md b/contribs/small-scale-traffic-generation/README.md index 19a22421db1..23eda473092 100644 --- a/contribs/small-scale-traffic-generation/README.md +++ b/contribs/small-scale-traffic-generation/README.md @@ -1,3 +1,44 @@ # small scale traffic generation -construction site; will contain small scale traffic generation code +This provides a tool to generate small-scale commercial traffic. + +The tool is based on : +- IVV. Kleinräumige Wirtschaftsverkehrsmodelle. Endbericht zum Forschungsprojekt FE-Nr. 70.0689/2002/ im Auftrag des Bundesministeriums für Verkehr, Bau und Wohnungswesen. 2005. Download: +[https://daten.clearingstelle-verkehr.de/194/](https://daten.clearingstelle-verkehr.de/194/). + +The description of the implementation in MATSim is given in the following paper : +- R. Ewert and K. Nagel, “Agentenbasierte Modellierung des kleinräumigen Wirtschaftsverkehrs,” 2024. Accepted for publication at HEUREKA Conference 2024. + +## Model types +The tool provides two different model types of small-scale commercial traffic. Therefore, you can select between the following options: +- **commercialPersonTraffic**: This model contains the personal commercial traffic. This traffic has the objective to transport persons from one location to another. +- **goodsTraffic**: This model contains the goods traffic. This traffic has the objective to transport goods from one location to another. + - !! The long distance freight traffic is not included in this model. !! Therefore, see application contrib: [link](https://github.com/matsim-org/matsim-libs/tree/master/contribs/application/src/main/java/org/matsim/application/prepare/freight) +- **completeSmallScaleCommercialTraffic**: This model contains both, the personal commercial traffic and the goods traffic. + + +## Input data +- The generation model uses only open data. + - zone shape file: + - contains the zones for each region + - should contain columns: `areaID`, `region` + - structure data: + - *dataDistributionPerZone.csv* + - contains numbers of inhabitants and employees per sector for each `region` + - this file should be located next to the config file + - OSM data: + - Landuse + - should contain the following columns: `fclass` + - Buildings + - should contain the following columns: `type`, `levels`, `area` +- Remarks: + - The zone shape file and the structure data should have the same regions. + +## Usage +For generating the traffic, the following steps are necessary: +- get necessary input data +- run the tool by calling the main class `GenerateSmallScaleCommercialTrafficDemand` + +## Example +An example is given as a test. See test `RunGenerateSmallScaleCommercialTrafficTest` and the mentioned example input data. + diff --git a/contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/CreateDifferentPlansForFreightPopulation.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/CreateDifferentPlansForFreightPopulation.java similarity index 100% rename from contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/CreateDifferentPlansForFreightPopulation.java rename to contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/CreateDifferentPlansForFreightPopulation.java diff --git a/contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java similarity index 97% rename from contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java rename to contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java index 46ec4a745b6..e5b6a27b774 100644 --- a/contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java @@ -36,24 +36,17 @@ import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Leg; import org.matsim.application.MATSimAppCommand; -import org.matsim.application.options.ShpOptions; import org.matsim.application.options.ShpOptions.Index; -import org.matsim.core.config.consistency.UnmaterializedConfigGroupChecker; -import org.matsim.core.scenario.ProjectionUtils; -import org.matsim.core.utils.geometry.CoordUtils; -import org.matsim.core.utils.geometry.CoordinateTransformation; -import org.matsim.freight.carriers.*; -import org.matsim.freight.carriers.controler.*; -import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; -import org.matsim.freight.carriers.usecases.chessboard.CarrierTravelDisutilities; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.consistency.UnmaterializedConfigGroupChecker; import org.matsim.core.config.groups.ControllerConfigGroup; import org.matsim.core.config.groups.VspExperimentalConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.gbl.Gbl; +import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.routes.NetworkRoute; import org.matsim.core.replanning.GenericPlanStrategyImpl; @@ -63,10 +56,17 @@ import org.matsim.core.router.util.LeastCostPathCalculatorFactory; import org.matsim.core.router.util.TravelDisutility; import org.matsim.core.router.util.TravelTime; +import org.matsim.core.scenario.ProjectionUtils; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.scoring.ScoringFunction; import org.matsim.core.scoring.SumScoringFunction; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.geometry.CoordinateTransformation; import org.matsim.core.utils.geometry.geotools.MGC; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.controler.*; +import org.matsim.freight.carriers.usecases.chessboard.CarrierTravelDisutilities; import org.matsim.vehicles.CostInformation; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; @@ -76,7 +76,6 @@ import java.io.File; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -100,6 +99,7 @@ public class GenerateSmallScaleCommercialTrafficDemand implements MATSimAppComma // Option 3: Leerkamp (nur in RVR Modell). + // Option: Add prepare class with OSM Analyse and create facility file with results private static final Logger log = LogManager.getLogger(GenerateSmallScaleCommercialTrafficDemand.class); private enum CreationOption { @@ -117,6 +117,12 @@ private enum SmallScaleCommercialTrafficType { @CommandLine.Parameters(arity = "1", paramLabel = "INPUT", description = "Path to the config for small scale commercial generation") private Path configPath; + @CommandLine.Option(names = "--pathToInvestigationAreaData", description = "Path to the investigation area data") + private Path pathToInvestigationAreaData; + + @CommandLine.Option(names = "--pathToExistingDataDistributionToZones", description = "Path to the existing data distribution to zones. This is only needed if the option useExistingDataDistribution is selected.") + private Path pathToExistingDataDistributionToZones; + @CommandLine.Option(names = "--sample", description = "Scaling factor of the small scale commercial traffic (0, 1)", required = true) private double sample; @@ -135,15 +141,30 @@ private enum SmallScaleCommercialTrafficType { @CommandLine.Option(names = "--includeExistingModels", description = "If models for some segments exist they can be included.") private boolean includeExistingModels; + @CommandLine.Option(names = "--regionsShapeFileName", description = "Path of the region shape file.") + private Path shapeFileRegionsPath; + + @CommandLine.Option(names = "--regionsShapeRegionColumn", description = "Name of the region column in the region shape file.") + private String regionsShapeRegionColumn; + @CommandLine.Option(names = "--zoneShapeFileName", description = "Path of the zone shape file.") private Path shapeFileZonePath; + @CommandLine.Option(names = "--zoneShapeFileNameColumn", description = "Name of the unique column of the name/Id of each zone in the zones shape file.") + private String shapeFileZoneNameColumn; + @CommandLine.Option(names = "--buildingsShapeFileName", description = "Path of the buildings shape file") private Path shapeFileBuildingsPath; + @CommandLine.Option(names = "--shapeFileBuildingTypeColumn", description = "Name of the unique column of the building type in the buildings shape file.") + private String shapeFileBuildingTypeColumn; + @CommandLine.Option(names = "--landuseShapeFileName", description = "Path of the landuse shape file") private Path shapeFileLandusePath; + @CommandLine.Option(names = "--shapeFileLanduseTypeColumn", description = "Name of the unique column of the landuse type in the landuse shape file.") + private String shapeFileLanduseTypeColumn; + @CommandLine.Option(names = "--shapeCRS", description = "CRS of the three input shape files (zones, landuse, buildings") private String shapeCRS; @@ -169,6 +190,7 @@ private enum SmallScaleCommercialTrafficType { private Index indexZones; private Index indexBuildings; private Index indexLanduse; + private Index indexInvestigationAreaRegions; public static void main(String[] args) { System.exit(new CommandLine(new GenerateSmallScaleCommercialTrafficDemand()).execute(args)); @@ -225,31 +247,32 @@ public Integer call() throws Exception { if (!Files.exists(shapeFileZonePath)) { throw new Exception("Required districts shape file {} not found" + shapeFileZonePath.toString()); } - Path inputDataDirectory = Path.of(config.getContext().toURI()).getParent(); - - ShpOptions shpZones = new ShpOptions(shapeFileZonePath, shapeCRS, StandardCharsets.UTF_8); + if (!Files.exists(shapeFileRegionsPath)) { + throw new Exception("Required regions shape file {} not found" + shapeFileRegionsPath.toString()); + } - indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS); - indexBuildings = SmallScaleCommercialTrafficUtils.getIndexBuildings(shapeFileBuildingsPath, shapeCRS); - indexLanduse = SmallScaleCommercialTrafficUtils.getIndexLanduse(shapeFileLandusePath, shapeCRS); + indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS, shapeFileZoneNameColumn); + indexBuildings = SmallScaleCommercialTrafficUtils.getIndexBuildings(shapeFileBuildingsPath, shapeCRS, shapeFileBuildingTypeColumn); + indexLanduse = SmallScaleCommercialTrafficUtils.getIndexLanduse(shapeFileLandusePath, shapeCRS, shapeFileLanduseTypeColumn); + indexInvestigationAreaRegions = SmallScaleCommercialTrafficUtils.getIndexRegions(shapeFileRegionsPath, shapeCRS, regionsShapeRegionColumn); Map> resultingDataPerZone = LanduseBuildingAnalysis - .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, + .createInputDataDistribution(output, landuseCategoriesAndDataConnection, usedLanduseConfiguration.toString(), indexLanduse, indexZones, - indexBuildings, buildingsPerZone); - - Map, Link>> regionLinksMap = filterLinksForZones(scenario, indexZones, buildingsPerZone); + indexBuildings, indexInvestigationAreaRegions, shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, + pathToExistingDataDistributionToZones); + Map, Link>> linksPerZone = filterLinksForZones(scenario, indexZones, buildingsPerZone); switch (usedSmallScaleCommercialTrafficType) { case commercialPersonTraffic, goodsTraffic -> - createCarriersAndDemand(output, scenario, shpZones, resultingDataPerZone, regionLinksMap, + createCarriersAndDemand(output, scenario, resultingDataPerZone, linksPerZone, usedSmallScaleCommercialTrafficType.toString(), includeExistingModels); case completeSmallScaleCommercialTraffic -> { - createCarriersAndDemand(output, scenario, shpZones, resultingDataPerZone, regionLinksMap, "commercialPersonTraffic", + createCarriersAndDemand(output, scenario, resultingDataPerZone, linksPerZone, "commercialPersonTraffic", includeExistingModels); includeExistingModels = false; // because already included in the step before - createCarriersAndDemand(output, scenario, shpZones, resultingDataPerZone, regionLinksMap, "goodsTraffic", + createCarriersAndDemand(output, scenario, resultingDataPerZone, linksPerZone, "goodsTraffic", includeExistingModels); } default -> throw new RuntimeException("No traffic type selected."); @@ -261,7 +284,7 @@ public Integer call() throws Exception { new CarrierPlanWriter(CarriersUtils.addOrGetCarriers(scenario)) .write(scenario.getConfig().controller().getOutputDirectory() + "/" + scenario.getConfig().controller().getRunId() + ".output_CarrierDemand.xml"); - solveSeparatedVRPs(scenario, regionLinksMap); + solveSeparatedVRPs(scenario, linksPerZone); } } if (config.controller().getRunId() == null) @@ -423,9 +446,9 @@ private void solveSeparatedVRPs(Scenario originalScenario, Map> resultingDataPerZone, - Map, Link>> regionLinksMap, String smallScaleCommercialTrafficType, + Map, Link>> linksPerZone, String smallScaleCommercialTrafficType, boolean includeExistingModels) throws Exception { ArrayList modesORvehTypes; @@ -445,13 +468,13 @@ else if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) .createTrafficVolume_stop(resultingDataPerZone, output, sample, modesORvehTypes, smallScaleCommercialTrafficType); if (includeExistingModels) { - SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); - TrafficVolumeGeneration.reduceDemandBasedOnExistingCarriers(scenario, regionLinksMap, smallScaleCommercialTrafficType, + SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, linksPerZone); + TrafficVolumeGeneration.reduceDemandBasedOnExistingCarriers(scenario, linksPerZone, smallScaleCommercialTrafficType, trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop); } final TripDistributionMatrix odMatrix = createTripDistribution(trafficVolumePerTypeAndZone_start, - trafficVolumePerTypeAndZone_stop, shpZones, smallScaleCommercialTrafficType, scenario, output, regionLinksMap); - createCarriers(scenario, odMatrix, resultingDataPerZone, smallScaleCommercialTrafficType, regionLinksMap); + trafficVolumePerTypeAndZone_stop, smallScaleCommercialTrafficType, scenario, output, linksPerZone); + createCarriers(scenario, odMatrix, resultingDataPerZone, smallScaleCommercialTrafficType, linksPerZone); } /** @@ -491,8 +514,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) @@ -946,17 +969,17 @@ 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 { - 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,10 +991,10 @@ 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); + network, regionLinksMap, resistanceFactor, shapeFileZoneNameColumn); } } } diff --git a/contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java similarity index 80% rename from contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java rename to contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java index faffac894c1..7e26668438e 100644 --- a/contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java @@ -54,13 +54,17 @@ public class LanduseBuildingAnalysis { * used OSM data. */ static Map> createInputDataDistribution(Path output, - Map> landuseCategoriesAndDataConnection, Path inputDataDirectory, + Map> landuseCategoriesAndDataConnection, String usedLanduseConfiguration, Index indexLanduse, Index indexZones, - Index indexBuildings, Map>> buildingsPerZone) - throws IOException { + Index indexBuildings, Index indexInvestigationAreaRegions, + String shapeFileZoneNameColumn, + Map>> buildingsPerZone, + Path pathToInvestigationAreaData, + Path pathToExistingDataDistributionToZones) + throws IOException { Map> resultingDataPerZone = new HashMap<>(); - Map zoneIdNameConnection = new HashMap<>(); + Map zoneIdRegionConnection = new HashMap<>(); Path outputFileInOutputFolder = output.resolve("calculatedData").resolve("dataDistributionPerZone.csv"); landuseCategoriesAndDataConnection.put("Inhabitants", @@ -80,18 +84,17 @@ static Map> createInputDataDistribution(Path ou Arrays.asList("commercial", "embassy", "foundation", "government", "office", "townhall"))); if (usedLanduseConfiguration.equals("useExistingDataDistribution")) { - Path existingDataDistribution = inputDataDirectory.resolve("dataDistributionPerZone.csv"); - if (!Files.exists(existingDataDistribution)) { - log.error("Required data per zone file {} not found", existingDataDistribution); + if (!Files.exists(pathToExistingDataDistributionToZones)) { + log.error("Required data per zone file {} not found", pathToExistingDataDistributionToZones); } - try (BufferedReader reader = IOUtils.getBufferedReader(existingDataDistribution.toString())) { + try (BufferedReader reader = IOUtils.getBufferedReader(pathToExistingDataDistributionToZones.toString())) { CSVParser parse = CSVFormat.Builder.create(CSVFormat.DEFAULT).setDelimiter('\t').setHeader() .setSkipHeaderRecord(true).build().parse(reader); for (CSVRecord record : parse) { - String zoneID = record.get("areaID"); + String zoneID = record.get("zoneID"); resultingDataPerZone.put(zoneID, new Object2DoubleOpenHashMap<>()); for (int n = 2; n < parse.getHeaderMap().size(); n++) { resultingDataPerZone.get(zoneID).mergeDouble(parse.getHeaderNames().get(n), @@ -100,8 +103,8 @@ static Map> createInputDataDistribution(Path ou } } log.info("Data distribution for " + resultingDataPerZone.size() + " zones was imported from " + - existingDataDistribution); - Files.copy(existingDataDistribution, outputFileInOutputFolder, StandardCopyOption.COPY_ATTRIBUTES); + pathToExistingDataDistributionToZones); + Files.copy(pathToExistingDataDistributionToZones, outputFileInOutputFolder, StandardCopyOption.COPY_ATTRIBUTES); } else { @@ -109,18 +112,18 @@ static Map> createInputDataDistribution(Path ou log.info("New analyze for data distribution is started. The used method is: " + usedLanduseConfiguration); Map> landuseCategoriesPerZone = new HashMap<>(); - createLanduseDistribution(landuseCategoriesPerZone, indexLanduse, indexZones, + createLanduseDistribution(landuseCategoriesPerZone, indexLanduse, indexZones, indexInvestigationAreaRegions, usedLanduseConfiguration, indexBuildings, landuseCategoriesAndDataConnection, - buildingsPerZone, zoneIdNameConnection); + buildingsPerZone, shapeFileZoneNameColumn, zoneIdRegionConnection); Map> investigationAreaData = new HashMap<>(); - readAreaData(investigationAreaData, inputDataDirectory); + readAreaData(investigationAreaData, pathToInvestigationAreaData); createResultingDataForLanduseInZones(landuseCategoriesPerZone, investigationAreaData, resultingDataPerZone, - landuseCategoriesAndDataConnection); + landuseCategoriesAndDataConnection, zoneIdRegionConnection); SmallScaleCommercialTrafficUtils.writeResultOfDataDistribution(resultingDataPerZone, outputFileInOutputFolder, - zoneIdNameConnection); + zoneIdRegionConnection); } return resultingDataPerZone; @@ -131,10 +134,10 @@ static Map> createInputDataDistribution(Path ou * and the original data. */ private static void createResultingDataForLanduseInZones( - Map> landuseCategoriesPerZone, - Map> investigationAreaData, - Map> resultingDataPerZone, - Map> landuseCategoriesAndDataConnection) { + Map> landuseCategoriesPerZone, + Map> investigationAreaData, + Map> resultingDataPerZone, + Map> landuseCategoriesAndDataConnection, Map zoneIdRegionConnection) { Map> totalSquareMetersPerCategory = new HashMap>(); Map> totalEmployeesInCategoriesPerZone = new HashMap>(); @@ -149,7 +152,7 @@ private static void createResultingDataForLanduseInZones( // connects the collected landuse data with the needed categories for (String zoneId : landuseCategoriesPerZone.keySet()) { - String investigationArea = zoneId.split("_")[0]; + String regionOfZone = zoneIdRegionConnection.get(zoneId); resultingDataPerZone.put(zoneId, new Object2DoubleOpenHashMap<>()); for (String categoryLanduse : landuseCategoriesPerZone.get(zoneId).keySet()) for (String categoryData : landuseCategoriesAndDataConnection.keySet()) { @@ -161,7 +164,7 @@ private static void createResultingDataForLanduseInZones( if (categoryLanduse.equals("commercial")) additionalArea = additionalArea * 0.5; resultingDataPerZone.get(zoneId).mergeDouble(categoryData, additionalArea, Double::sum); - totalSquareMetersPerCategory.get(investigationArea).mergeDouble(categoryData, additionalArea, + totalSquareMetersPerCategory.get(regionOfZone).mergeDouble(categoryData, additionalArea, Double::sum); } } @@ -176,12 +179,12 @@ private static void createResultingDataForLanduseInZones( .forEach(c -> checkPercentages.computeIfAbsent(c, k -> new Object2DoubleOpenHashMap<>())); for (String zoneId : resultingDataPerZone.keySet()) for (String categoryData : resultingDataPerZone.get(zoneId).keySet()) { - String investigationArea = zoneId.split("_")[0]; + String regionOfZone = zoneIdRegionConnection.get(zoneId); double newValue = resultingDataPerZone.get(zoneId).getDouble(categoryData) - / totalSquareMetersPerCategory.get(investigationArea).getDouble(categoryData); + / totalSquareMetersPerCategory.get(regionOfZone).getDouble(categoryData); resultingDataPerZone.get(zoneId).replace(categoryData, resultingDataPerZone.get(zoneId).getDouble(categoryData), newValue); - checkPercentages.get(investigationArea).mergeDouble(categoryData, + checkPercentages.get(regionOfZone).mergeDouble(categoryData, resultingDataPerZone.get(zoneId).getDouble(categoryData), Double::sum); } // tests the result @@ -193,21 +196,21 @@ private static void createResultingDataForLanduseInZones( } // calculates the data per zone and category data for (String zoneId : resultingDataPerZone.keySet()) { - String investigationArea = zoneId.split("_")[0]; + String regionOfZone = zoneIdRegionConnection.get(zoneId); for (String categoryData : resultingDataPerZone.get(zoneId).keySet()) { double percentageValue = resultingDataPerZone.get(zoneId).getDouble(categoryData); - int inputDataForCategory = investigationAreaData.get(investigationArea).get(categoryData); + int inputDataForCategory = investigationAreaData.get(regionOfZone).get(categoryData); double resultingNumberPerCategory = percentageValue * inputDataForCategory; resultingDataPerZone.get(zoneId).replace(categoryData, percentageValue, resultingNumberPerCategory); - totalEmployeesPerCategories.get(investigationArea).mergeDouble(categoryData, resultingNumberPerCategory, + totalEmployeesPerCategories.get(regionOfZone).mergeDouble(categoryData, resultingNumberPerCategory, Double::sum); if (!categoryData.equals("Inhabitants")) - totalEmployeesInCategoriesPerZone.get(investigationArea).mergeDouble(zoneId, + totalEmployeesInCategoriesPerZone.get(regionOfZone).mergeDouble(zoneId, resultingNumberPerCategory, Double::sum); } - if (totalEmployeesInCategoriesPerZone.get(investigationArea).getDouble(zoneId) != 0) + if (totalEmployeesInCategoriesPerZone.get(regionOfZone).getDouble(zoneId) != 0) resultingDataPerZone.get(zoneId).mergeDouble("Employee", - totalEmployeesInCategoriesPerZone.get(investigationArea).getDouble(zoneId), Double::sum); + totalEmployeesInCategoriesPerZone.get(regionOfZone).getDouble(zoneId), Double::sum); } } @@ -216,23 +219,30 @@ private static void createResultingDataForLanduseInZones( * the sum of this category in all zones of the zone shape file */ private static void createLanduseDistribution(Map> landuseCategoriesPerZone, - Index indexLanduse, Index indexZones, String usedLanduseConfiguration, + Index indexLanduse, Index indexZones, Index indexInvestigationAreaRegions, String usedLanduseConfiguration, Index indexBuildings, Map> landuseCategoriesAndDataConnection, Map>> buildingsPerZone, - Map zoneIdNameConnection) { + String shapeFileZoneNameColumn, Map zoneIdRegionConnection) { List neededLanduseCategories = List.of("residential", "industrial", "commercial", "retail", "farmyard", "farmland", "construction"); List landuseFeatures = indexLanduse.getAllFeatures(); List zonesFeatures = indexZones.getAllFeatures(); - - for (SimpleFeature singleZone : zonesFeatures) { - Object2DoubleMap landusePerCategory = new Object2DoubleOpenHashMap<>(); - landuseCategoriesPerZone.put((String) singleZone.getAttribute("areaID"), landusePerCategory); - zoneIdNameConnection.put((String) singleZone.getAttribute("areaID"), - (String) singleZone.getAttribute("name")); + // get the region of the zone + Coord middleCoordOfZone = MGC.point2Coord(((Geometry) singleZone.getDefaultGeometry()).getCentroid()); + String regionName = indexInvestigationAreaRegions.query(middleCoordOfZone); + if (regionName != null) { + Object2DoubleMap landusePerCategory = new Object2DoubleOpenHashMap<>(); + String zoneID = (String) singleZone.getAttribute(shapeFileZoneNameColumn); + var previousValue = landuseCategoriesPerZone.putIfAbsent(zoneID, landusePerCategory); + if (previousValue != null) { + throw new IllegalStateException( + "Key " + zoneID + " already exists in the zone map. This should not happen. Please check if the data in the column " + shapeFileZoneNameColumn + " is unique."); + } + zoneIdRegionConnection.put(zoneID, regionName); + } } if (usedLanduseConfiguration.equals("useOSMBuildingsAndLanduse")) { @@ -279,14 +289,13 @@ private static void createLanduseDistribution(Map> areaData, Path inputDataDirectory) + private static void readAreaData(Map> areaData, Path pathToInvestigationAreaData) throws IOException { - Path areaDataPath = inputDataDirectory.resolve("investigationAreaData.csv"); - if (!Files.exists(areaDataPath)) { - log.error("Required input data file {} not found", areaDataPath); + if (!Files.exists(pathToInvestigationAreaData)) { + log.error("Required input data file {} not found", pathToInvestigationAreaData); } - try (CSVParser parser = new CSVParser(Files.newBufferedReader(areaDataPath), + try (CSVParser parser = new CSVParser(Files.newBufferedReader(pathToInvestigationAreaData), CSVFormat.Builder.create(CSVFormat.TDF).setHeader().setSkipHeaderRecord(true).build())) { for (CSVRecord record : parser) { @@ -295,7 +304,7 @@ private static void readAreaData(Map> areaData, Pat if (parser.getHeaderMap().get(csvRecord) > 0) lookUpTable.put(csvRecord, Integer.valueOf(record.get(csvRecord))); } - areaData.put(record.get("Area"), lookUpTable); + areaData.put(record.get("Region"), lookUpTable); } } } diff --git a/contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java similarity index 86% rename from contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java rename to contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java index 1ea26e82ee3..f00dcd020e5 100644 --- a/contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java @@ -77,52 +77,90 @@ public class SmallScaleCommercialTrafficUtils { /** * Creates and return the Index of the zone shape. * + * @param shapeFileZonePath Path to the shape file of the zones + * @param shapeCRS CRS of the shape file + * @param shapeFileZoneNameColumn Column name of the zone in the shape file * @return indexZones */ - static Index getIndexZones(Path shapeFileZonePath, String shapeCRS) { + static Index getIndexZones(Path shapeFileZonePath, String shapeCRS, String shapeFileZoneNameColumn) { ShpOptions shpZones = new ShpOptions(shapeFileZonePath, shapeCRS, StandardCharsets.UTF_8); - return shpZones.createIndex(shapeCRS, "areaID"); + if (shpZones.readFeatures().iterator().next().getAttribute(shapeFileZoneNameColumn) == null) + throw new NullPointerException("The column '" + shapeFileZoneNameColumn + "' does not exist in the zones shape file. Please check the input."); + return shpZones.createIndex(shapeCRS, shapeFileZoneNameColumn); } /** * Creates and return the Index of the landuse shape. * - * @return indexLanduse + * @param shapeFileLandusePath Path to the shape file of the landuse + * @param shapeCRS CRS of the shape file + * @param shapeFileLanduseTypeColumn Column name of the landuse in the shape file + * @return indexLanduse */ - static Index getIndexLanduse(Path shapeFileLandusePath, String shapeCRS) { - + static Index getIndexLanduse(Path shapeFileLandusePath, String shapeCRS, String shapeFileLanduseTypeColumn) { ShpOptions shpLanduse = new ShpOptions(shapeFileLandusePath, shapeCRS, StandardCharsets.UTF_8); - return shpLanduse.createIndex(shapeCRS, "fclass"); + if (shpLanduse.readFeatures().iterator().next().getAttribute(shapeFileLanduseTypeColumn) == null) + throw new NullPointerException("The column '" + shapeFileLanduseTypeColumn + "' does not exist in the landuse shape file. Please check the input."); + return shpLanduse.createIndex(shapeCRS, shapeFileLanduseTypeColumn); } /** * Creates and return the Index of the building shape. * - * @return indexBuildings + * @param shapeFileBuildingsPath Path to the shape file of the buildings + * @param shapeCRS CRS of the shape file + * @param shapeFileBuildingTypeColumn Column name of the building in the shape file + * @return indexBuildings */ - static Index getIndexBuildings(Path shapeFileBuildingsPath, String shapeCRS) { + static Index getIndexBuildings(Path shapeFileBuildingsPath, String shapeCRS, String shapeFileBuildingTypeColumn) { + ShpOptions shpBuildings = new ShpOptions(shapeFileBuildingsPath, shapeCRS, StandardCharsets.UTF_8); + if (shpBuildings.readFeatures().iterator().next().getAttribute(shapeFileBuildingTypeColumn) == null) + throw new NullPointerException("The column '" + shapeFileBuildingTypeColumn + "' does not exist in the building shape file. Please check the input."); + + return shpBuildings.createIndex(shapeCRS, shapeFileBuildingTypeColumn); + } - ShpOptions shpLanduse = new ShpOptions(shapeFileBuildingsPath, shapeCRS, StandardCharsets.UTF_8); - return shpLanduse.createIndex(shapeCRS, "type"); + /** + * Creates and return the Index of the regions shape. + * + * @param shapeFileRegionsPath Path to the shape file of the regions + * @param shapeCRS CRS of the shape file + * @param regionsShapeRegionColumn Column name of the region in the shape file + * @return indexRegions + */ + public static Index getIndexRegions(Path shapeFileRegionsPath, String shapeCRS, String regionsShapeRegionColumn) { + ShpOptions shpRegions = new ShpOptions(shapeFileRegionsPath, shapeCRS, StandardCharsets.UTF_8); + if (shpRegions.readFeatures().iterator().next().getAttribute(regionsShapeRegionColumn) == null) + throw new NullPointerException("The column '" + regionsShapeRegionColumn + "' does not exist in the region shape file. Please check the input."); + return shpRegions.createIndex(shapeCRS, regionsShapeRegionColumn); } /** * Writes a csv file with the result of the distribution per zone of the input data. */ static void writeResultOfDataDistribution(Map> resultingDataPerZone, - Path outputFileInOutputFolder, Map zoneIdNameConnection) + Path outputFileInOutputFolder, Map zoneIdRegionConnection) throws IOException { - writeCSVWithCategoryHeader(resultingDataPerZone, outputFileInOutputFolder, zoneIdNameConnection); + writeCSVWithCategoryHeader(resultingDataPerZone, outputFileInOutputFolder, zoneIdRegionConnection); log.info("The data distribution is finished and written to: " + outputFileInOutputFolder); } - static Id findNearestPossibleLink(String zone, List noPossibleLinks, Map, Link>> regionLinksMap, + /** Finds the nearest possible link for the building polygon. + * @param zone + * @param noPossibleLinks + * @param linksPerZone + * @param newLink + * @param centroidPointOfBuildingPolygon + * @param numberOfPossibleLinks + * @return + */ + static Id findNearestPossibleLink(String zone, List noPossibleLinks, Map, Link>> linksPerZone, Id newLink, Coord centroidPointOfBuildingPolygon, int numberOfPossibleLinks) { double minDistance = Double.MAX_VALUE; searchLink: - for (Link possibleLink : regionLinksMap.get(zone).values()) { + for (Link possibleLink : linksPerZone.get(zone).values()) { if (possibleLink.getToNode().getOutLinks() == null) continue; if (noPossibleLinks != null && numberOfPossibleLinks > noPossibleLinks.size()) @@ -140,7 +178,7 @@ static Id findNearestPossibleLink(String zone, List noPossibleLink } } if (newLink == null && numberOfPossibleLinks > 0) { - for (Link possibleLink : regionLinksMap.get(zone).values()) { + for (Link possibleLink : linksPerZone.get(zone).values()) { double distance = NetworkUtils.getEuclideanDistance(centroidPointOfBuildingPolygon, (Coord) possibleLink.getAttributes().getAttribute("newCoord")); if (distance < minDistance) { @@ -158,11 +196,11 @@ static Id findNearestPossibleLink(String zone, List noPossibleLink */ private static void writeCSVWithCategoryHeader(Map> resultingDataPerZone, Path outputFileInInputFolder, - Map zoneIdNameConnection) throws MalformedURLException { + Map zoneIdRegionConnection) throws MalformedURLException { BufferedWriter writer = IOUtils.getBufferedWriter(outputFileInInputFolder.toUri().toURL(), StandardCharsets.UTF_8, true); try { - String[] header = new String[]{"areaID", "areaName", "Inhabitants", "Employee", "Employee Primary Sector", + String[] header = new String[]{"zoneID", "region", "Inhabitants", "Employee", "Employee Primary Sector", "Employee Construction", "Employee Secondary Sector Rest", "Employee Retail", "Employee Traffic/Parcels", "Employee Tertiary Sector Rest"}; JOIN.appendTo(writer, header); @@ -170,9 +208,9 @@ private static void writeCSVWithCategoryHeader(Map row = new ArrayList<>(); row.add(zone); - row.add(zoneIdNameConnection.get(zone)); + row.add(zoneIdRegionConnection.get(zone)); for (String category : header) { - if (!category.equals("areaID") && !category.equals("areaName")) + if (!category.equals("zoneID") && !category.equals("region")) row.add(String.valueOf((int) Math.round(resultingDataPerZone.get(zone).getDouble(category)))); } JOIN.appendTo(writer, row); @@ -189,7 +227,6 @@ private static void writeCSVWithCategoryHeader(Map vehicleId = Id.createVehicleId(person.getId().toString()); - VehicleUtils.insertVehicleIdsIntoAttributes(newPerson, Map.of(mode, vehicleId)); - VehicleUtils.insertVehicleTypesIntoAttributes(newPerson, Map.of(mode, allVehicles.getVehicles().get(vehicleId).getType().getId())); + VehicleUtils.insertVehicleIdsIntoPersonAttributes(newPerson, Map.of(mode, vehicleId)); + VehicleUtils.insertVehicleTypesIntoPersonAttributes(newPerson, Map.of(mode, allVehicles.getVehicles().get(vehicleId).getType().getId())); population.addPerson(newPerson); } @@ -297,7 +334,7 @@ static String getSampleNameOfOutputFolder(double sample) { * dispersedTraffic will be added additionally. */ static void readExistingModels(Scenario scenario, double sampleScenario, - Map, Link>> regionLinksMap) throws Exception { + Map, Link>> linksPerZone) throws Exception { Path existingModelsFolder = Path.of(scenario.getConfig().getContext().toURI()).getParent().resolve("existingModels"); String locationOfExistingModels = existingModelsFolder.resolve("existingModels.csv").toString(); @@ -498,7 +535,7 @@ else if (!carrier.getShipments().isEmpty()) List startAreas = new ArrayList<>(); for (ScheduledTour tour : newCarrier.getSelectedPlan().getScheduledTours()) { - String tourStartZone = findZoneOfLink(tour.getTour().getStartLinkId(), regionLinksMap); + String tourStartZone = findZoneOfLink(tour.getTour().getStartLinkId(), linksPerZone); if (!startAreas.contains(tourStartZone)) startAreas.add(tourStartZone); } @@ -526,9 +563,9 @@ else if (!carrier.getShipments().isEmpty()) /** * Find the zone where the link is located */ - static String findZoneOfLink(Id linkId, Map, Link>> regionLinksMap) { - for (String area : regionLinksMap.keySet()) { - if (regionLinksMap.get(area).containsKey(linkId)) + static String findZoneOfLink(Id linkId, Map, Link>> linksPerZone) { + for (String area : linksPerZone.keySet()) { + if (linksPerZone.get(area).containsKey(linkId)) return area; } return null; diff --git a/contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java similarity index 99% rename from contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java rename to contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java index 7e9e591eabc..b376d16d176 100644 --- a/contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java @@ -221,7 +221,7 @@ private static void writeCSVTrafficVolume(Map, Link>> regionLinksMap, String smallScaleCommercialTrafficType, + Map, Link>> linksPerZone, String smallScaleCommercialTrafficType, Map> trafficVolumePerTypeAndZone_start, Map> trafficVolumePerTypeAndZone_stop) { @@ -290,11 +290,11 @@ static void reduceDemandBasedOnExistingCarriers(Scenario scenario, if (carrier.getSelectedPlan() != null) { for (ScheduledTour tour : carrier.getSelectedPlan().getScheduledTours()) { String startZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(tour.getTour().getStartLinkId(), - regionLinksMap); + linksPerZone); for (TourElement tourElement : tour.getTour().getTourElements()) { if (tourElement instanceof ServiceActivity service) { String stopZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(service.getLocation(), - regionLinksMap); + linksPerZone); try { reduceVolumeForThisExistingJobElement(trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, modeORvehType, purpose, startZone, stopZone); @@ -306,9 +306,9 @@ static void reduceDemandBasedOnExistingCarriers(Scenario scenario, } if (tourElement instanceof Pickup pickup) { startZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(pickup.getShipment().getFrom(), - regionLinksMap); + linksPerZone); String stopZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(pickup.getShipment().getTo(), - regionLinksMap); + linksPerZone); try { reduceVolumeForThisExistingJobElement(trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, modeORvehType, purpose, startZone, stopZone); @@ -325,13 +325,13 @@ static void reduceDemandBasedOnExistingCarriers(Scenario scenario, List possibleStartAreas = new ArrayList<>(); for (CarrierVehicle vehicle : carrier.getCarrierCapabilities().getCarrierVehicles().values()) { possibleStartAreas - .add(SmallScaleCommercialTrafficUtils.findZoneOfLink(vehicle.getLinkId(), regionLinksMap)); + .add(SmallScaleCommercialTrafficUtils.findZoneOfLink(vehicle.getLinkId(), linksPerZone)); } for (CarrierService service : carrier.getServices().values()) { String startZone = (String) possibleStartAreas.toArray()[MatsimRandom.getRandom() .nextInt(possibleStartAreas.size())]; String stopZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(service.getLocationLinkId(), - regionLinksMap); + linksPerZone); try { reduceVolumeForThisExistingJobElement(trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, modeORvehType, purpose, startZone, stopZone); @@ -344,9 +344,9 @@ static void reduceDemandBasedOnExistingCarriers(Scenario scenario, } else if (!carrier.getShipments().isEmpty()) { for (CarrierShipment shipment : carrier.getShipments().values()) { String startZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(shipment.getFrom(), - regionLinksMap); + linksPerZone); String stopZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(shipment.getTo(), - regionLinksMap); + linksPerZone); try { reduceVolumeForThisExistingJobElement(trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, modeORvehType, purpose, startZone, stopZone); @@ -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/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java similarity index 90% rename from contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java rename to contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java index 7d631a6b96d..f577c73deaa 100644 --- a/contribs/application/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<>(); @@ -280,23 +284,24 @@ private TripDistributionMatrix(Builder builder) { * Calculates the traffic volume between two zones for a specific modeORvehType * and purpose. * - * @param startZone start zone - * @param stopZone stop zone - * @param modeORvehType selected mode or vehicle type - * @param purpose selected purpose + * @param startZone start zone + * @param stopZone stop zone + * @param modeORvehType selected mode or vehicle type + * @param purpose selected purpose * @param smallScaleCommercialTrafficType goodsTraffic or commercialPersonTraffic - * @param regionLinksMap links in each zone + * @param linksPerZone links in each zone + * @param shapeFileZoneNameColumn Name of the unique column of the name/Id of each zone in the zones shape file */ void setTripDistributionValue(String startZone, String stopZone, String modeORvehType, Integer purpose, String smallScaleCommercialTrafficType, Network network, - Map, Link>> regionLinksMap, double resistanceFactor) { + Map, Link>> linksPerZone, double resistanceFactor, String shapeFileZoneNameColumn) { double volumeStart = trafficVolume_start.get(TrafficVolumeGeneration.makeTrafficVolumeKey(startZone, modeORvehType)).getDouble(purpose); double volumeStop = trafficVolume_stop.get(TrafficVolumeGeneration.makeTrafficVolumeKey(stopZone, modeORvehType)).getDouble(purpose); int roundedVolume; if (volumeStart != 0 && volumeStop != 0) { - double resistanceValue = getResistanceFunktionValue(startZone, stopZone, network, regionLinksMap, resistanceFactor); - double gravityConstantA = getGravityConstant(stopZone, trafficVolume_start, modeORvehType, purpose, network, regionLinksMap, - resistanceFactor); + double resistanceValue = getResistanceFunktionValue(startZone, stopZone, network, linksPerZone, resistanceFactor, shapeFileZoneNameColumn); + double gravityConstantA = getGravityConstant(stopZone, trafficVolume_start, modeORvehType, purpose, network, linksPerZone, + resistanceFactor, shapeFileZoneNameColumn); roundingError.computeIfAbsent(stopZone, (k) -> new Object2DoubleOpenHashMap<>()); //Bisher: Gravity model mit fixem Zielverkehr @@ -309,10 +314,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); @@ -336,11 +337,13 @@ Integer getTripDistributionValue(String startZone, String stopZone, String modeO /** * Calculates the values of the resistance function between two zones. * - * @param startZone start zone - * @param stopZone stop zone - * @param regionLinksMap links for each zone + * @param startZone start zone + * @param stopZone stop zone + * @param linksPerZone links for each zone + * @param shapeFileZoneNameColumn Name of the unique column of the name/Id of each zone in the zones shape file */ - private Double getResistanceFunktionValue(String startZone, String stopZone, Network network, Map, Link>> regionLinksMap, double resistanceFactor) { + private Double getResistanceFunktionValue(String startZone, String stopZone, Network network, Map, Link>> linksPerZone, + double resistanceFactor, String shapeFileZoneNameColumn) { //if false the calculation is faster; e.g. for debugging boolean useNetworkRoutesForResistanceFunction = true; @@ -353,11 +356,11 @@ private Double getResistanceFunktionValue(String startZone, String stopZone, Net } if (!resistanceFunktionCache.containsKey(makeResistanceFunktionKey(startZone, stopZone))) for (SimpleFeature startZoneFeature : zonesFeatures) { - String zone1 = String.valueOf(startZoneFeature.getAttribute("areaID")); + String zone1 = String.valueOf(startZoneFeature.getAttribute(shapeFileZoneNameColumn)); if (!startZone.equals(zone1)) continue; for (SimpleFeature stopZoneFeature : zonesFeatures) { - String zone2 = String.valueOf(stopZoneFeature.getAttribute("areaID")); + String zone2 = String.valueOf(stopZoneFeature.getAttribute(shapeFileZoneNameColumn)); if (!stopZone.equals(zone2)) continue; double distance = Double.MAX_VALUE; @@ -368,8 +371,8 @@ private Double getResistanceFunktionValue(String startZone, String stopZone, Net } else { if (useNetworkRoutesForResistanceFunction) { - Location startLocation = Location.newInstance(regionLinksMap.get(startZone).keySet().iterator().next().toString()); - Location stopLocation = Location.newInstance(regionLinksMap.get(stopZone).keySet().iterator().next().toString()); + Location startLocation = Location.newInstance(linksPerZone.get(startZone).keySet().iterator().next().toString()); + Location stopLocation = Location.newInstance(linksPerZone.get(stopZone).keySet().iterator().next().toString()); Vehicle exampleVehicle = getExampleVehicle(startLocation); // distance = netBasedCosts.getDistance(startLocation, stopLocation, 21600., exampleVehicle); travelCosts = netBasedCosts.getTransportCost(startLocation, stopLocation, 21600., null, exampleVehicle); @@ -412,7 +415,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); @@ -443,16 +446,17 @@ private VehicleImpl getExampleVehicle(Location fromId) { /** * Calculates the gravity constant. * - * @param baseZone base zone - * @param trafficVolume volume of the traffic - * @param modeORvehType selected mode or vehicle type - * @param purpose selected purpose - * @param regionLinksMap links for each zone + * @param baseZone base zone + * @param trafficVolume volume of the traffic + * @param modeORvehType selected mode or vehicle type + * @param purpose selected purpose + * @param linksPerZone links for each zone + * @param shapeFileZoneNameColumn Name of the unique column of the name/Id of each zone in the zones shape file * @return gravity constant */ private double getGravityConstant(String baseZone, Map> trafficVolume, String modeORvehType, - Integer purpose, Network network, Map, Link>> regionLinksMap, double resistanceFactor) { + Integer purpose, Network network, Map, Link>> linksPerZone, double resistanceFactor, String shapeFileZoneNameColumn) { GravityConstantKey gravityKey = makeGravityKey(baseZone, modeORvehType, purpose); if (!gravityConstantACache.containsKey(gravityKey)) { @@ -464,7 +468,7 @@ private double getGravityConstant(String baseZone, continue; else { double resistanceValue = getResistanceFunktionValue(baseZone, trafficVolumeKey.getZone(), network, - regionLinksMap, resistanceFactor); + linksPerZone, resistanceFactor, shapeFileZoneNameColumn); sum = sum + (volume * resistanceValue); } } @@ -519,16 +523,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; } @@ -611,7 +605,7 @@ void writeODMatrices(Path output, String smallScaleCommercialTrafficType) throws try { List headerRow = new ArrayList<>(); - headerRow.add(""); + headerRow.add("O/D"); headerRow.addAll(usedZones); JOIN.appendTo(writer, headerRow); writer.write("\n"); diff --git a/contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java similarity index 86% rename from contribs/application/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java rename to contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java index f0aff20d0e1..8a2d7ef9407 100644 --- a/contribs/application/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 @@ -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) { diff --git a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java similarity index 52% rename from contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java rename to contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java index 6d562e6fbf1..fa640744c92 100644 --- a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java @@ -33,8 +33,6 @@ import java.util.List; import java.util.Map; -import static org.matsim.smallScaleCommercialTrafficGeneration.SCTUtils.*; - /** * @author Ricardo Ewert * @@ -53,18 +51,22 @@ void testReadOfDataDistributionPerZoneAndBuildingAnalysis() throws IOException { assert(new File(output.resolve("calculatedData").toString()).mkdir()); Path inputDataDirectory = Path.of(utils.getPackageInputDirectory()); String usedLanduseConfiguration = "useExistingDataDistribution"; - + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); // Test if the reading of the existing data distribution works correctly + Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); Assertions.assertEquals(3, resultingDataPerZone.size(), MatsimTestUtils.EPSILON); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea1_area1")); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea1_area2")); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea2_area3")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area1")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area2")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area3")); for (String zone : resultingDataPerZone.keySet()) { Object2DoubleMap categories = resultingDataPerZone.get(zone); @@ -88,75 +90,79 @@ void testReadOfDataDistributionPerZoneAndBuildingAnalysis() throws IOException { Assertions.assertEquals(categories.getDouble("Employee"), employeeSum, MatsimTestUtils.EPSILON); - if (zone.equals("testArea1_area1")) { - Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(3500, resultingDataPerZone.get(zone).getDouble("Employee"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(0, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Retail"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), - MatsimTestUtils.EPSILON); - } - if (zone.equals("testArea1_area2")) { - Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(6500, resultingDataPerZone.get(zone).getDouble("Employee"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Retail"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(2000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), - MatsimTestUtils.EPSILON); - } - if (zone.equals("testArea2_area3")) { - Assertions.assertEquals(800, resultingDataPerZone.get(zone).getDouble("Inhabitants"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(50, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Construction"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(100, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(150, resultingDataPerZone.get(zone).getDouble("Employee Retail"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(300, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), - MatsimTestUtils.EPSILON); - } + switch (zone) { + case "area1" -> { + Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(3500, resultingDataPerZone.get(zone).getDouble("Employee"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(0, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Retail"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), + MatsimTestUtils.EPSILON); + } + case "area2" -> { + Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(6500, resultingDataPerZone.get(zone).getDouble("Employee"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Retail"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(2000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), + MatsimTestUtils.EPSILON); + } + case "area3" -> { + Assertions.assertEquals(800, resultingDataPerZone.get(zone).getDouble("Inhabitants"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(50, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Construction"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(100, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(150, resultingDataPerZone.get(zone).getDouble("Employee Retail"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(300, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), + MatsimTestUtils.EPSILON); + } + default -> Assertions.fail("Zone not found"); + } + } // tests if the reading of the buildings works correctly - List buildingsFeatures = getIndexBuildings(inputDataDirectory).getAllFeatures(); + List buildingsFeatures = SCTUtils.getIndexBuildings(inputDataDirectory).getAllFeatures(); Assertions.assertEquals(31, buildingsFeatures.size(), MatsimTestUtils.EPSILON); LanduseBuildingAnalysis.analyzeBuildingType(buildingsFeatures, buildingsPerZone, - landuseCategoriesAndDataConnection, getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory)); + landuseCategoriesAndDataConnection, SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory)); Assertions.assertEquals(3, buildingsPerZone.size(), MatsimTestUtils.EPSILON); - Assertions.assertTrue(buildingsPerZone.containsKey("testArea1_area1")); - Assertions.assertTrue(buildingsPerZone.containsKey("testArea1_area2")); - Assertions.assertTrue(buildingsPerZone.containsKey("testArea2_area3")); + Assertions.assertTrue(buildingsPerZone.containsKey("area1")); + Assertions.assertTrue(buildingsPerZone.containsKey("area2")); + Assertions.assertTrue(buildingsPerZone.containsKey("area3")); // test for area1 - Map> builingsPerArea1 = buildingsPerZone.get("testArea1_area1"); + Map> builingsPerArea1 = buildingsPerZone.get("area1"); Assertions.assertEquals(7, builingsPerArea1.size(), MatsimTestUtils.EPSILON); List inhabitantsBuildings = builingsPerArea1.get("Inhabitants"); Assertions.assertEquals(4, inhabitantsBuildings.size(), MatsimTestUtils.EPSILON); @@ -186,7 +192,7 @@ void testReadOfDataDistributionPerZoneAndBuildingAnalysis() throws IOException { Assertions.assertEquals(6, builingsPerArea1.get("Employee").size(), MatsimTestUtils.EPSILON); // test for area2 - Map> builingsPerArea2 = buildingsPerZone.get("testArea1_area2"); + Map> builingsPerArea2 = buildingsPerZone.get("area2"); Assertions.assertEquals(8, builingsPerArea2.size(), MatsimTestUtils.EPSILON); List employeeRetail = builingsPerArea2.get("Employee Retail"); Assertions.assertEquals(2, employeeRetail.size(), MatsimTestUtils.EPSILON); @@ -210,7 +216,7 @@ void testReadOfDataDistributionPerZoneAndBuildingAnalysis() throws IOException { Assertions.assertEquals(8, builingsPerArea2.get("Employee").size(), MatsimTestUtils.EPSILON); // test for area3 - Map> builingsPerArea3 = buildingsPerZone.get("testArea2_area3"); + Map> builingsPerArea3 = buildingsPerZone.get("area3"); Assertions.assertEquals(8, builingsPerArea3.size(), MatsimTestUtils.EPSILON); List tertiaryRetail = builingsPerArea3.get("Employee Tertiary Sector Rest"); Assertions.assertEquals(1, tertiaryRetail.size(), MatsimTestUtils.EPSILON); @@ -240,18 +246,20 @@ void testLanduseDistribution() throws IOException { assert(new File(output.resolve("calculatedData").toString()).mkdir()); Path inputDataDirectory = Path.of(utils.getPackageInputDirectory()); String usedLanduseConfiguration = "useOSMBuildingsAndLanduse"; - + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); // Analyze resultingData per zone Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, null); Assertions.assertEquals(3, resultingDataPerZone.size(), MatsimTestUtils.EPSILON); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea1_area1")); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea1_area2")); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea2_area3")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area1")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area2")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area3")); for (String zone : resultingDataPerZone.keySet()) { Object2DoubleMap categories = resultingDataPerZone.get(zone); @@ -275,60 +283,63 @@ void testLanduseDistribution() throws IOException { Assertions.assertEquals(categories.getDouble("Employee"), employeeSum, MatsimTestUtils.EPSILON); - if (zone.equals("testArea1_area1")) { - Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(3500, resultingDataPerZone.get(zone).getDouble("Employee"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(0, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Retail"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), - MatsimTestUtils.EPSILON); - } - if (zone.equals("testArea1_area2")) { - Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(6500, resultingDataPerZone.get(zone).getDouble("Employee"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Retail"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(2000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), - MatsimTestUtils.EPSILON); - } - if (zone.equals("testArea2_area3")) { - Assertions.assertEquals(800, resultingDataPerZone.get(zone).getDouble("Inhabitants"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(50, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Construction"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(100, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(150, resultingDataPerZone.get(zone).getDouble("Employee Retail"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(300, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), - MatsimTestUtils.EPSILON); - } + switch (zone) { + case "area1" -> { + Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(3500, resultingDataPerZone.get(zone).getDouble("Employee"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(0, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Retail"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), + MatsimTestUtils.EPSILON); + } + case "area2" -> { + Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(6500, resultingDataPerZone.get(zone).getDouble("Employee"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Retail"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(2000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), + MatsimTestUtils.EPSILON); + } + case "area3" -> { + Assertions.assertEquals(800, resultingDataPerZone.get(zone).getDouble("Inhabitants"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(50, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Construction"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(100, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(150, resultingDataPerZone.get(zone).getDouble("Employee Retail"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(300, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), + MatsimTestUtils.EPSILON); + } + default -> Assertions.fail("Zone not found"); + } } } } 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 new file mode 100644 index 00000000000..c664ba46440 --- /dev/null +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java @@ -0,0 +1,198 @@ +/* *********************************************************************** * + * project: org.matsim.* + * Controler.java + * * + * *********************************************************************** * + * * + * copyright : (C) 2007 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ +package org.matsim.smallScaleCommercialTrafficGeneration; + +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Population; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.events.EventsUtils; +import org.matsim.core.population.PopulationUtils; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +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.ComparisonResult; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * @author Ricardo Ewert + * + */ +public class RunGenerateSmallScaleCommercialTrafficTest { + + @RegisterExtension + private MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + void testMainRunAndResults() { + String pathToConfig = utils.getPackageInputDirectory() + "config_demand.xml"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); + String output = utils.getOutputDirectory(); + String sample = "0.1"; + String jspritIterations = "2"; + String creationOption = "createNewCarrierFile"; + String landuseConfiguration = "useExistingDataDistribution"; + String smallScaleCommercialTrafficType = "commercialPersonTraffic"; + String regionsShapeFileName = utils.getPackageInputDirectory() + "/shp/testRegions.shp"; + String regionsShapeRegionColumn = "region"; + String zoneShapeFileName = utils.getPackageInputDirectory() + "/shp/testZones.shp"; + String zoneShapeFileNameColumn = "name"; + String buildingsShapeFileName = utils.getPackageInputDirectory() + "/shp/testBuildings.shp"; + String shapeFileBuildingTypeColumn = "type"; + String landuseShapeFileName = utils.getPackageInputDirectory() + "/shp/testLanduse.shp"; + String shapeFileLanduseTypeColumn = "fclass"; + String shapeCRS = "EPSG:4326"; + String resultPopulation = "testPopulation.xml.gz"; + + new GenerateSmallScaleCommercialTrafficDemand().execute( + pathToConfig, + "--pathToInvestigationAreaData", pathToInvestigationAreaData.toString(), + "--pathToExistingDataDistributionToZones", pathToExistingDataDistributionToZones.toString(), + "--sample", sample, + "--jspritIterations", jspritIterations, + "--creationOption", creationOption, + "--landuseConfiguration", landuseConfiguration, + "--smallScaleCommercialTrafficType", smallScaleCommercialTrafficType, + "--includeExistingModels", + "--regionsShapeFileName", regionsShapeFileName, + "--regionsShapeRegionColumn", regionsShapeRegionColumn, + "--zoneShapeFileName", zoneShapeFileName, + "--zoneShapeFileNameColumn", zoneShapeFileNameColumn, + "--buildingsShapeFileName", buildingsShapeFileName, + "--shapeFileBuildingTypeColumn", shapeFileBuildingTypeColumn, + "--landuseShapeFileName", landuseShapeFileName, + "--shapeFileLanduseTypeColumn", shapeFileLanduseTypeColumn, + "--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); + 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); + freightCarriersConfigGroup.setCarriersVehicleTypesFile(utils.getOutputDirectory() + "test.output_carriersVehicleTypes.xml.gz"); + + freightCarriersConfigGroup.setCarriersFile(carriersWOSolutionFileLocation); + CarriersUtils.loadCarriersAccordingToFreightConfig(scenarioWOSolution); + freightCarriersConfigGroup.setCarriersFile(carriersWSolutionFileLocation); + CarriersUtils.loadCarriersAccordingToFreightConfig(scenarioWSolution); + + for (Person person : population.getPersons().values()) { + Assertions.assertNotNull(person.getSelectedPlan()); + Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("tourStartArea")); + Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("vehicles")); + Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("subpopulation")); + Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("purpose")); + } + + Assertions.assertEquals(CarriersUtils.addOrGetCarriers(scenarioWSolution).getCarriers().size(), + CarriersUtils.addOrGetCarriers(scenarioWOSolution).getCarriers().size(), 0); + int countedTours = 0; + for (Carrier carrier_withSolution : CarriersUtils.addOrGetCarriers(scenarioWSolution).getCarriers().values()) { + countedTours += carrier_withSolution.getSelectedPlan().getScheduledTours().size(); + } + Assertions.assertEquals(population.getPersons().size(), countedTours, 0); + + for (File calculatedFile : Objects.requireNonNull( + Objects.requireNonNull(new File(utils.getOutputDirectory() + "calculatedData").listFiles()))) { + Map> existingDataDistribution = readCSVInputAndCreateMap(calculatedFile.getAbsolutePath()); + Map> simulatedDataDistribution = readCSVInputAndCreateMap( + utils.getPackageInputDirectory() + "calculatedData/" + calculatedFile.getName()); + compareDataDistribution(calculatedFile.getName(), existingDataDistribution, simulatedDataDistribution); + } + + // compare events + String expected = utils.getPackageInputDirectory() + "test.output_events.xml.gz"; + String actual = utils.getOutputDirectory() + "test.output_events.xml.gz" ; + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result ); + } + + /** + * Reads a CSV file and creates a map with the first column as key and the rest as a map with the header as key and the value as value + * + * @param calculatedFile the file to read + * @return + */ + private static Map> readCSVInputAndCreateMap(String calculatedFile) { + Map> dataDistribution = new HashMap<>(); + try (BufferedReader reader = IOUtils.getBufferedReader(calculatedFile)) { + CSVParser parse = CSVFormat.Builder.create(CSVFormat.DEFAULT).setDelimiter('\t').setHeader() + .setSkipHeaderRecord(true).build().parse(reader); + for (CSVRecord record : parse) { + System.out.println(record); + dataDistribution.computeIfAbsent(record.get(0), k -> new Object2DoubleOpenHashMap<>()); + for (int i = 1; i < record.size(); i++) { + if (i == 1 && (calculatedFile.contains("dataDistributionPerZone") || calculatedFile.contains("TrafficVolume_"))) + continue; + dataDistribution.get(record.get(0)).put(parse.getHeaderNames().get(i), Double.parseDouble(record.get(i))); + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return dataDistribution; + } + + /** + * Compares the data distribution of two files + * + * @param calculatedFile the file to compare + * @param existingDataDistribution the existing data distribution + * @param simulatedDataDistribution the simulated data distribution + */ + private void compareDataDistribution(String calculatedFile, Map> existingDataDistribution, + Map> simulatedDataDistribution) { + Assertions.assertEquals(existingDataDistribution.size(), simulatedDataDistribution.size()); + for (String key : existingDataDistribution.keySet()) { + Object2DoubleMap existingMap = existingDataDistribution.get(key); + Object2DoubleMap simulatedMap = simulatedDataDistribution.get(key); + for (String subKey : existingMap.keySet()) { + Assertions.assertEquals(existingMap.getDouble(subKey), simulatedMap.getDouble(subKey), + "File: " + calculatedFile + "; Expected: " + existingMap.getDouble(subKey) + " but was: " + simulatedMap.getDouble( + subKey) + " for key: " + key + " and subKey: " + subKey); + } + } + } +} diff --git a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SCTUtils.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SCTUtils.java similarity index 78% rename from contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SCTUtils.java rename to contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SCTUtils.java index 7b16b902d08..843a690196d 100644 --- a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SCTUtils.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SCTUtils.java @@ -11,7 +11,7 @@ public class SCTUtils { static ShpOptions.Index getZoneIndex(Path inputDataDirectory) { Path shapeFileZonePath = inputDataDirectory.resolve("shp/testZones.shp"); - return new ShpOptions(shapeFileZonePath, null, null).createIndex("areaID"); + return new ShpOptions(shapeFileZonePath, null, null).createIndex("name"); } static ShpOptions.Index getIndexLanduse(Path inputDataDirectory) { @@ -24,4 +24,9 @@ static ShpOptions.Index getIndexBuildings(Path inputDataDirectory) { return new ShpOptions(shapeFileBuildingsPath, null, null).createIndex("type"); } + static ShpOptions.Index getIndexRegions(Path inputDataDirectory) { + Path shapeFileRegionsPath = inputDataDirectory.resolve("shp/testRegions.shp"); + return new ShpOptions(shapeFileRegionsPath, null, null).createIndex("region"); + } + } diff --git a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java similarity index 79% rename from contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java rename to contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java index 3aedc210cde..5aa06d111fc 100644 --- a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java @@ -25,7 +25,6 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Link; -import org.matsim.application.options.ShpOptions; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.scenario.ScenarioUtils; @@ -34,9 +33,7 @@ import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -62,19 +59,21 @@ void findZoneOfLinksTest() throws IOException, URISyntaxException { config.network().setInputCRS("EPSG:4326"); Scenario scenario = ScenarioUtils.loadScenario(config); Map>> buildingsPerZone = new HashMap<>(); + String shapeFileZoneNameColumn = "name"; Map, Link>> regionLinksMap = GenerateSmallScaleCommercialTrafficDemand - .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem()), + .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem(), + shapeFileZoneNameColumn), buildingsPerZone); Assertions.assertEquals(3, regionLinksMap.size(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(60, regionLinksMap.get("testArea1_area1").size(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(41, regionLinksMap.get("testArea1_area2").size(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(28, regionLinksMap.get("testArea2_area3").size(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(60, regionLinksMap.get("area1").size(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(41, regionLinksMap.get("area2").size(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(28, regionLinksMap.get("area3").size(), MatsimTestUtils.EPSILON); Assertions.assertNull(SmallScaleCommercialTrafficUtils.findZoneOfLink(Id.createLinkId("j(5,4)"), regionLinksMap)); - Assertions.assertEquals("testArea1_area1", SmallScaleCommercialTrafficUtils.findZoneOfLink(Id.createLinkId("j(6,5)R"), regionLinksMap)); - Assertions.assertEquals("testArea1_area2", SmallScaleCommercialTrafficUtils.findZoneOfLink(Id.createLinkId("j(2,7)R"), regionLinksMap)); - Assertions.assertEquals("testArea2_area3", SmallScaleCommercialTrafficUtils.findZoneOfLink(Id.createLinkId("j(2,2)R"), regionLinksMap)); + Assertions.assertEquals("area1", SmallScaleCommercialTrafficUtils.findZoneOfLink(Id.createLinkId("j(6,5)R"), regionLinksMap)); + Assertions.assertEquals("area2", SmallScaleCommercialTrafficUtils.findZoneOfLink(Id.createLinkId("j(2,7)R"), regionLinksMap)); + Assertions.assertEquals("area3", SmallScaleCommercialTrafficUtils.findZoneOfLink(Id.createLinkId("j(2,2)R"), regionLinksMap)); } } diff --git a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java similarity index 92% rename from contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java rename to contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java index ef979568774..b680e568ffb 100644 --- a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java @@ -41,8 +41,6 @@ import java.nio.file.Path; import java.util.*; -import static org.matsim.smallScaleCommercialTrafficGeneration.SCTUtils.*; - /** * @author Ricardo Ewert * @@ -62,11 +60,15 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { assert(new File(output.resolve("calculatedData").toString()).mkdir()); Path inputDataDirectory = Path.of(utils.getPackageInputDirectory()); String usedLanduseConfiguration = "useExistingDataDistribution"; + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "commercialPersonTraffic"; @@ -88,7 +90,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertTrue(trafficVolumePerTypeAndZone_start.containsKey(trafficVolumeKey)); Assertions.assertTrue(trafficVolumePerTypeAndZone_stop.containsKey(trafficVolumeKey)); } - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area1", modesORvehTypes.get(0)); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area1", modesORvehTypes.get(0)); Assertions.assertEquals(30, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(124, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(277, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -101,7 +103,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertEquals(121, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(65, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area2", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area2", modesORvehTypes.get(0)); Assertions.assertEquals(30, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(211, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(514, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -114,7 +116,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertEquals(246, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(102, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea2_area3", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area3", modesORvehTypes.get(0)); Assertions.assertEquals(6, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(34, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(79, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -138,7 +140,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertEquals(3, trafficVolumePerTypeAndZone_start.size()); Assertions.assertEquals(3, trafficVolumePerTypeAndZone_stop.size()); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area1", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area1", modesORvehTypes.get(0)); Assertions.assertEquals(7, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(31, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(69, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -151,7 +153,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertEquals(30, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(16, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area2", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area2", modesORvehTypes.get(0)); Assertions.assertEquals(7, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(53, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(129, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -164,7 +166,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertEquals(61, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(25, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea2_area3", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area3", modesORvehTypes.get(0)); Assertions.assertEquals(1, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(8, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(20, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -188,11 +190,15 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { assert(new File(output.resolve("calculatedData").toString()).mkdir()); Path inputDataDirectory = Path.of(utils.getPackageInputDirectory()); String usedLanduseConfiguration = "useExistingDataDistribution"; + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "goodsTraffic"; double sample = 1.; @@ -216,7 +222,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { } } - // test for "testArea1_area1" + // test for "area1" HashMap estimatesStart = new HashMap<>(); estimatesStart.put(1, 12.); estimatesStart.put(2, 30.); @@ -236,7 +242,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area1", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area1", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); if (modeORvehType.equals("vehTyp1")) { @@ -319,7 +325,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { Assertions.assertEquals(estimatesStop.get(i), sumStop, MatsimTestUtils.EPSILON); } - // test for "testArea1_area2" + // test for "area2" estimatesStart = new HashMap<>(); estimatesStart.put(1, 12.); estimatesStart.put(2, 37.); @@ -339,7 +345,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area2", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area2", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); } @@ -347,7 +353,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { Assertions.assertEquals(estimatesStop.get(i), sumStop, MatsimTestUtils.EPSILON); } - // test for "testArea2_area3" + // test for "area3" estimatesStart = new HashMap<>(); estimatesStart.put(1, 2.); estimatesStart.put(2, 7.); @@ -367,7 +373,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea2_area3", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area3", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); } @@ -390,9 +396,11 @@ void testAddingExistingScenarios() throws Exception { config.setContext(inputDataDirectory.resolve("config.xml").toUri().toURL()); Scenario scenario = ScenarioUtils.loadScenario(config); Map>> buildingsPerZone = new HashMap<>(); + String shapeFileZoneNameColumn = "name"; Map, Link>> regionLinksMap = GenerateSmallScaleCommercialTrafficDemand - .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem()), + .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem(), + shapeFileZoneNameColumn), buildingsPerZone); SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); @@ -416,7 +424,7 @@ void testAddingExistingScenarios() throws Exception { Assertions.assertEquals("exampleServiceCarrier", addedCarrier1.getAttributes().getAttribute("existingModel")); Assertions.assertEquals("car", addedCarrier1.getAttributes().getAttribute("networkMode")); Assertions.assertNull(addedCarrier1.getAttributes().getAttribute("vehicleType")); - Assertions.assertEquals("testArea2_area3", addedCarrier1.getAttributes().getAttribute("tourStartArea")); + Assertions.assertEquals("area3", addedCarrier1.getAttributes().getAttribute("tourStartArea")); Carrier addedCarrier2 = CarriersUtils.getCarriers(scenario).getCarriers().get(Id.create("exampleServiceCarrier_carrier2", Carrier.class)); Assertions.assertNotNull(addedCarrier2.getSelectedPlan()); @@ -430,7 +438,7 @@ void testAddingExistingScenarios() throws Exception { Assertions.assertEquals("exampleServiceCarrier", addedCarrier2.getAttributes().getAttribute("existingModel")); Assertions.assertEquals("car", addedCarrier2.getAttributes().getAttribute("networkMode")); Assertions.assertNull(addedCarrier2.getAttributes().getAttribute("vehicleType")); - Assertions.assertEquals("testArea2_area3", addedCarrier2.getAttributes().getAttribute("tourStartArea")); + Assertions.assertEquals("area3", addedCarrier2.getAttributes().getAttribute("tourStartArea")); Carrier addedCarrier3 = CarriersUtils.getCarriers(scenario).getCarriers().get(Id.create("exampleShipmentCarrier_carrier1", Carrier.class)); Assertions.assertNull(addedCarrier3.getSelectedPlan()); @@ -449,6 +457,8 @@ void testAddingExistingScenariosWithSample() throws Exception { Path shapeFileZonePath = inputDataDirectory.resolve("shp/testZones.shp"); String networkPath = "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"; double sample = 0.2; + String shapeFileZoneNameColumn = "name"; + Config config = ConfigUtils.createConfig(); config.global().setCoordinateSystem("EPSG:4326"); config.network().setInputFile(networkPath); @@ -457,7 +467,8 @@ void testAddingExistingScenariosWithSample() throws Exception { Scenario scenario = ScenarioUtils.loadScenario(config); Map>> buildingsPerZone = new HashMap<>(); Map, Link>> regionLinksMap = GenerateSmallScaleCommercialTrafficDemand - .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem()), + .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem(), + shapeFileZoneNameColumn), buildingsPerZone); SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); @@ -480,7 +491,7 @@ void testAddingExistingScenariosWithSample() throws Exception { Assertions.assertEquals("exampleServiceCarrier", addedCarrier1.getAttributes().getAttribute("existingModel")); Assertions.assertEquals("car", addedCarrier1.getAttributes().getAttribute("networkMode")); Assertions.assertNull(addedCarrier1.getAttributes().getAttribute("vehicleType")); - Assertions.assertEquals("testArea2_area3", addedCarrier1.getAttributes().getAttribute("tourStartArea")); + Assertions.assertEquals("area3", addedCarrier1.getAttributes().getAttribute("tourStartArea")); Carrier addedCarrier3 = CarriersUtils.getCarriers(scenario).getCarriers().get(Id.create("exampleShipmentCarrier_carrier1", Carrier.class)); Assertions.assertNull(addedCarrier3.getSelectedPlan()); @@ -504,6 +515,10 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { String networkPath = "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"; String usedTrafficType = "goodsTraffic"; double sample = 1.; + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); + ArrayList modesORvehTypes = new ArrayList<>( Arrays.asList("vehTyp1", "vehTyp2", "vehTyp3", "vehTyp4", "vehTyp5")); Config config = ConfigUtils.createConfig(); @@ -516,8 +531,9 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); Map> trafficVolumePerTypeAndZone_start = TrafficVolumeGeneration .createTrafficVolume_start(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); @@ -525,14 +541,14 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { .createTrafficVolume_stop(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); Map, Link>> regionLinksMap = GenerateSmallScaleCommercialTrafficDemand - .filterLinksForZones(scenario, getZoneIndex(inputDataDirectory), buildingsPerZone); + .filterLinksForZones(scenario, SCTUtils.getZoneIndex(inputDataDirectory), buildingsPerZone); SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); TrafficVolumeGeneration.reduceDemandBasedOnExistingCarriers(scenario, regionLinksMap, usedTrafficType, trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop); - // test for "testArea1_area1" + // test for "area1" HashMap estimatesStart = new HashMap<>(); estimatesStart.put(1, 12.); estimatesStart.put(2, 30.); @@ -552,7 +568,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area1", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area1", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); if (modeORvehType.equals("vehTyp3")) { @@ -575,7 +591,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { Assertions.assertEquals(estimatesStop.get(i), sumStop, MatsimTestUtils.EPSILON); } - // test for "testArea1_area2" + // test for "area2" estimatesStart = new HashMap<>(); estimatesStart.put(1, 12.); estimatesStart.put(2, 37.); @@ -595,7 +611,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area2", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area2", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); } @@ -603,7 +619,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { Assertions.assertEquals(estimatesStop.get(i), sumStop, MatsimTestUtils.EPSILON); } - // test for "testArea2_area3" + // test for "area3" estimatesStart = new HashMap<>(); estimatesStart.put(1, 2.); estimatesStart.put(2, 7.); @@ -623,7 +639,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea2_area3", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area3", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); if (modeORvehType.equals("vehTyp3")) { @@ -659,6 +675,10 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th String networkPath = "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"; String usedTrafficType = "commercialPersonTraffic"; double sample = 1.; + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); + ArrayList modesORvehTypes = new ArrayList<>( List.of("total")); Config config = ConfigUtils.createConfig(); @@ -671,8 +691,9 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); Map> trafficVolumePerTypeAndZone_start = TrafficVolumeGeneration .createTrafficVolume_start(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); @@ -680,7 +701,7 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th .createTrafficVolume_stop(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); Map, Link>> regionLinksMap = GenerateSmallScaleCommercialTrafficDemand - .filterLinksForZones(scenario, getZoneIndex(inputDataDirectory), buildingsPerZone); + .filterLinksForZones(scenario, SCTUtils.getZoneIndex(inputDataDirectory), buildingsPerZone); SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); @@ -690,7 +711,7 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th //because the reduction of the start volume in zone3 (purpose 2) is higher than the value, a start reduction will be distributed over other zones double sumOfStartOtherAreas = 0; - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area1", modesORvehTypes.get(0)); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area1", modesORvehTypes.get(0)); Assertions.assertEquals(30, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); sumOfStartOtherAreas += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2); Assertions.assertEquals(277, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -703,7 +724,7 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th Assertions.assertEquals(121, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(65, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area2", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area2", modesORvehTypes.get(0)); Assertions.assertEquals(30, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); sumOfStartOtherAreas += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2); Assertions.assertEquals(514, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -716,7 +737,7 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th Assertions.assertEquals(246, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(102, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea2_area3", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area3", modesORvehTypes.get(0)); Assertions.assertEquals(6, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(0, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); sumOfStartOtherAreas += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2); diff --git a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java similarity index 80% rename from contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java rename to contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java index adc41f61191..7190ba7350d 100644 --- a/contribs/application/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java @@ -59,10 +59,15 @@ void testTripDistributionCommercialPersonTrafficTraffic() throws IOException { String usedLanduseConfiguration = "useExistingDataDistribution"; String networkLocation = "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"; Network network = NetworkUtils.readNetwork(networkLocation); + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); + Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "commercialPersonTraffic"; double sample = 1.; @@ -75,16 +80,18 @@ 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("area1", "area2", "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<>()); - regionLinksMap.get("testArea1_area1").put(Id.createLinkId("i(8,6)"), network.getLinks().get(Id.createLinkId("i(8,6)"))); - regionLinksMap.put("testArea1_area2", new HashMap<>()); - regionLinksMap.get("testArea1_area2").put(Id.createLinkId("i(2,7)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); - regionLinksMap.put("testArea2_area3", new HashMap<>()); - regionLinksMap.get("testArea2_area3").put(Id.createLinkId("i(2,1)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); + regionLinksMap.put("area1", new HashMap<>()); + regionLinksMap.get("area1").put(Id.createLinkId("i(8,6)"), network.getLinks().get(Id.createLinkId("i(8,6)"))); + regionLinksMap.put("area2", new HashMap<>()); + regionLinksMap.get("area2").put(Id.createLinkId("i(2,7)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); + regionLinksMap.put("area3", new HashMap<>()); + regionLinksMap.get("area3").put(Id.createLinkId("i(2,1)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); for (String startZone : resultingDataPerZone.keySet()) { for (String stopZone : resultingDataPerZone.keySet()) { @@ -92,7 +99,7 @@ void testTripDistributionCommercialPersonTrafficTraffic() throws IOException { for (Integer purpose : trafficVolumePerTypeAndZone_start .get(TrafficVolumeGeneration.makeTrafficVolumeKey(startZone, modeORvehType)).keySet()) { odMatrix.setTripDistributionValue(startZone, stopZone, modeORvehType, purpose, usedTrafficType, - network, regionLinksMap, resistanceFactor); + network, regionLinksMap, resistanceFactor, shapeFileZoneNameColumn); } } } @@ -144,10 +151,14 @@ void testTripDistributionGoodsTraffic() throws IOException { String usedLanduseConfiguration = "useExistingDataDistribution"; String networkLocation = "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"; Network network = NetworkUtils.readNetwork(networkLocation); + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "goodsTraffic"; double sample = 1.; @@ -155,6 +166,8 @@ void testTripDistributionGoodsTraffic() throws IOException { ArrayList modesORvehTypes = new ArrayList( Arrays.asList("vehTyp1", "vehTyp2", "vehTyp3", "vehTyp4", "vehTyp5")); + ArrayList listOfZones = new ArrayList<>( List.of("area1", "area2", "area3")); + TrafficVolumeGeneration.setInputParameters(usedTrafficType); Map> trafficVolumePerTypeAndZone_start = TrafficVolumeGeneration @@ -162,15 +175,16 @@ 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<>()); - regionLinksMap.get("testArea1_area1").put(Id.createLinkId("i(8,6)"), network.getLinks().get(Id.createLinkId("i(8,6)"))); - regionLinksMap.put("testArea1_area2", new HashMap<>()); - regionLinksMap.get("testArea1_area2").put(Id.createLinkId("i(2,7)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); - regionLinksMap.put("testArea2_area3", new HashMap<>()); - regionLinksMap.get("testArea2_area3").put(Id.createLinkId("i(2,1)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); + regionLinksMap.put("area1", new HashMap<>()); + regionLinksMap.get("area1").put(Id.createLinkId("i(8,6)"), network.getLinks().get(Id.createLinkId("i(8,6)"))); + regionLinksMap.put("area2", new HashMap<>()); + regionLinksMap.get("area2").put(Id.createLinkId("i(2,7)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); + regionLinksMap.put("area3", new HashMap<>()); + regionLinksMap.get("area3").put(Id.createLinkId("i(2,1)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); for (String startZone : resultingDataPerZone.keySet()) { for (String stopZone : resultingDataPerZone.keySet()) { @@ -178,7 +192,7 @@ void testTripDistributionGoodsTraffic() throws IOException { for (Integer purpose : trafficVolumePerTypeAndZone_start .get(TrafficVolumeGeneration.makeTrafficVolumeKey(startZone, modeORvehType)).keySet()) { odMatrix.setTripDistributionValue(startZone, stopZone, modeORvehType, purpose, usedTrafficType, - network, regionLinksMap, resistanceFactor); + network, regionLinksMap, resistanceFactor, shapeFileZoneNameColumn); } } } 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..76905762d24 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_startPerZone_10pt.csv @@ -0,0 +1,4 @@ +zoneID mode/vehType 1 2 3 4 5 +area2 total 3 21 51 44 63 +area1 total 3 12 28 18 25 +area3 total 1 3 8 6 9 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..837a7d38659 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_stopPerZone_10pt.csv @@ -0,0 +1,4 @@ +zoneID mode/vehType 1 2 3 4 5 +area2 total 1 20 86 25 10 +area1 total 1 10 43 12 6 +area3 total 0 3 13 4 2 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..0a841cc7dd0 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/dataDistributionPerZone.csv @@ -0,0 +1,4 @@ +zoneID region Inhabitants Employee Employee Primary Sector Employee Construction Employee Secondary Sector Rest Employee Retail Employee Traffic/Parcels Employee Tertiary Sector Rest +area2 region1 4000 6500 500 1500 500 500 1500 2000 +area3 region2 800 1000 50 200 100 150 200 300 +area1 region1 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..1bc43756980 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose1.csv @@ -0,0 +1,4 @@ +O/D area2 area1 area3 +area2 1 0 0 +area1 0 1 0 +area3 0 0 0 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..5b49558b3a5 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose2.csv @@ -0,0 +1,4 @@ +O/D area2 area1 area3 +area2 8 6 0 +area1 5 4 1 +area3 0 0 0 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..04d2d8af059 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose3.csv @@ -0,0 +1,4 @@ +O/D area2 area1 area3 +area2 51 24 7 +area1 27 15 4 +area3 8 4 2 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..3d2f4777106 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose4.csv @@ -0,0 +1,4 @@ +O/D area2 area1 area3 +area2 16 7 2 +area1 7 3 1 +area3 2 2 1 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..ac996432028 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose5.csv @@ -0,0 +1,4 @@ +O/D area2 area1 area3 +area2 7 4 1 +area1 3 2 0 +area3 0 0 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/config_demand.xml b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/config_demand.xml new file mode 100644 index 00000000000..ef77da93664 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/config_demand.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/dataDistributionPerZone.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/dataDistributionPerZone.csv new file mode 100644 index 00000000000..0a841cc7dd0 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/dataDistributionPerZone.csv @@ -0,0 +1,4 @@ +zoneID region Inhabitants Employee Employee Primary Sector Employee Construction Employee Secondary Sector Rest Employee Retail Employee Traffic/Parcels Employee Tertiary Sector Rest +area2 region1 4000 6500 500 1500 500 500 1500 2000 +area3 region2 800 1000 50 200 100 150 200 300 +area1 region1 4000 3500 0 500 500 1000 500 1000 \ No newline at end of file diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/output_carriers.xml.gz b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/output_carriers.xml.gz similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/output_carriers.xml.gz rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/output_carriers.xml.gz diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/output_carriers.xml.gz b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/output_carriers.xml.gz similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/output_carriers.xml.gz rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/output_carriers.xml.gz diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/existingModels.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/existingModels.csv similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/existingModels.csv rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/existingModels.csv diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/investigationAreaData.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/investigationAreaData.csv new file mode 100644 index 00000000000..97fe8fd80b7 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/investigationAreaData.csv @@ -0,0 +1,3 @@ +Region Inhabitants Employee Employee Primary Sector Employee Construction Employee Secondary Sector Rest Employee Retail Employee Traffic/Parcels Employee Tertiary Sector Rest +region1 8000 10000 500 2000 1000 1500 2000 3000 +region2 800 1000 50 200 100 150 200 300 \ No newline at end of file diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.cpg b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.cpg similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.cpg rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.cpg diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.dbf b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.dbf similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.dbf rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.dbf diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.prj b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.prj similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.prj rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.prj diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.qmd b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.qmd similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.qmd rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.qmd diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.shp b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.shp similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.shp rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.shp diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.shx b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.shx similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.shx rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testBuildings.shx diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.cpg b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.cpg similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.cpg rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.cpg diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.dbf b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.dbf similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.dbf rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.dbf diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.prj b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.prj similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.prj rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.prj diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.qmd b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.qmd similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.qmd rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.qmd diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.shp b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.shp similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.shp rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.shp diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.shx b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.shx similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.shx rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testLanduse.shx diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.cpg b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.cpg similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.cpg rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.cpg diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.dbf b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.dbf new file mode 100644 index 0000000000000000000000000000000000000000..c97184381a41f9d0de4adfc94eab0598ade608bc GIT binary patch literal 280 zcmZRsVG?CxU|>jOhz63FATtFn<_BVN!MPAdQEGZ-ejb?Z3?c&{!f=vT0S*iyY7OB6 O)MFSyj5ea0iBbS8U?4^S literal 0 HcmV?d00001 diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.prj b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.prj similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.prj rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.prj diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.qmd b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.qmd new file mode 100644 index 00000000000..d8b7603dead --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.qmd @@ -0,0 +1,26 @@ + + + + + + dataset + + + + + + + + + + 0 + 0 + + + + + false + + + + diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.shp b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.shp new file mode 100644 index 0000000000000000000000000000000000000000..50121591ca3edcf4cfebddeeeb717c5a517ad0bc GIT binary patch literal 372 zcmZQzQ0HR64tBj@W?*0i$`#nWJ#H&gc0gf8GS4*s`UBe{*1cKIe%PVj?aYBTt3wXh zwWEkK0(lM~vlImV>@*Bh4tRX(v;VVcg#)@-AcY`xU?6w;UVpFh0T;=TC9>j&Fx0~I z!pwr1y(YKgndre)4h(4efo3uRG1wjGe(IComHr}Tg9C@4;nbJWs~nKsaUec2CZ9X^ p08EY}f4SNZ?hOtl|9@PR$Xw|F(+dk9nAr)tG9KkQKNcIH5v)gcG$ P+EGM}fIN`8G7t>_bVw39 literal 0 HcmV?d00001 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.cpg b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.cpg new file mode 100644 index 00000000000..3ad133c048f --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.cpg @@ -0,0 +1 @@ +UTF-8 \ No newline at end of file diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.dbf b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.dbf similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.dbf rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.dbf diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.prj b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.prj new file mode 100644 index 00000000000..f45cbadf007 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] \ No newline at end of file diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.qmd b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.qmd similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.qmd rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.qmd diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.shp b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.shp similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.shp rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.shp diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.shx b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.shx similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.shx rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testZones.shx 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..cedefa5d9a5ec188923a208878e0c7c869076d31 GIT binary patch literal 31240 zcmX7vQ($Dx7KP(X>||mm6Wg|J+qRudY))+3wmGqFPweD&{@YL8{cyTY)v4NReS0;2 z6i^=N@qJGCy*rOVvZ0sus;6zdLyT&tD4_|mvC+(=lj0TW*!N(cEUqg579~=@6(tlWfAB7!13AtKi9A^7uz@xikrF*Hme}+1s?2aI2l%-<1H0=?nXJJBzJ;iA^JhOSNzx4T8;p(((u+>|8JCRl|R%wNE z9If9b95J_>uP)IOUD<*A9U%=lNPL)q2eGaOa8|U5sg73<45>H}CiG$s&NNDp5tZ(h z6ZFK}%PzL33wO?Q3d|DTEyXD}IO=@WVSC?E?=aKLeEdTu&P7cPw4ZIrS<}Y6xD`XZ zE7A4uknd{Ox zHGmtX!@r$GXkgJ86p)5`;h%P+A39DR=Mo?l>+(E7^)VFv=0C{E%4dyP7vmG{wH@V5 z+6ygG%>;koX+FU|s3e)bQ;v916LwVGG&eQ^8)g2(-|106B00xL4w)fnVv6hI>;mle znTzlU*U#l=;xyl=2Fpqfl1c%5@BTi1-=~i*+W}CfTaE)z_52{h;|zu4AG&=lvJslf z!})xQxLWQ7J$MOU62v;uTs}xvH;iNM3~lQodcT*6cx|5JUqOZu!b;5O3DuFNlrV4Y z)ven?zAPjvzqDYJ({Hv6>HM)Sy<;&Z_SDF>W&yJMy z#O*!9+ObwxVVe>bILNz(&p60=P?e&ktOl0wwXIK+o4irtnxCO+@B1}n)0}lek``Q4 ze80>v!%kBdUmQbwE;2IWJI+puP2_qiZQtn8bXC#L;R%WyKkUo(AO&6Z_+V4DD8Oqc zJgKx5uahk-a^y#nEyxeGewM2!TVARb3rydg`tdAuH?%ieBe`gF9^-U4+ii!cOz=CV z9%k;Q?@WaT?+qh?NLV6;m6~I9^+I3nrkW*2F0w?$r4qM!PHP|x2``9>(~(G_@N~ZP zE#uD&rRc#)s4%%?K_30?8^H~OlhcnXTr;dDN5~!zG+b@Nqjyz%#V8p+) zUw}vvIsZej+PNetx{vz|JzZRFmtja|U_f2D2m5p|QUr&qgGdAb*vZcrO-4Aebw)k~??nCaLLyutOy}!JMe2$z$ zdRBJg@kUu>naEPd!&rjjI4%pN6;_x-EwN$O9uQtUd2S1p^c?DbE}i>n4{z?lsR1W? zFPr%Hwdg*wJ4%#Ihd|@2Cc{nD;ki@Q)bCREY`xCqT2FsI3M|+uqrBLkp?qbUX9rl4 z_QTpfgF$09znXch1Xfuby+58F1J02aQR`~sG`E6^trWAe%=$zS1>WbNE$5l*p7(RQ zp3gTr%=4G^iX`9G>vGe^)1Y&a0^P5-m?u{TtXeH3P27}L`=2ydMyo~(X4DN<6383p z9KJv4LwmraES5ViUYn?91#DvIF0<#ZRHB;QRDLNrdnI?fg)~}ZXZMFDPMCNQR zhDcX0a78uKBn>9%;sW)x%oYyU53j9Yc2_1_8y^dE4TH~a&<}EbS#)vz2%Io)*F2J> zzA<%irHedKbrVXojztm0E@>TI*un*Zx+E?c+}l@^X-GW`k35ExsSl9=v(ak2${X6$ zmrWYq7f@8fA~3$*7m%H(QosLK_~9XrbgH|YQ?8)SuXs(fIM*oML$f%2tn_PVIcCeQ zxd?l(Ua}~aG0|9B`Pm!-bef=$@=9Fci6m)r7I$hEdMO?TvZ7Fba zu`tljB4Od?YXK|yo0FhvdprfO8lk#rPl8sty=u1#Dx4i?4=^b#!n(2dx+|&Wa<1PM z%1bkI<^1vyqFFLOQE1gxN(Wd$s{9D^YGpzRi!F@&F_(ua@dMIC+)8?)Z2Mt3j~^)p zax;3CnUBuLJ=)kOwOOB^A{p&hz|Md0TK6IU#%X}o4_~G))XeiQk3@!OEo@!Bm8ev6 zOm4%fZlOBIxkN7inVo(*oI4*X5o)qqG-SW{uV41}E^?(%XL7(=1`t7>PJpH@2z4hl z#v_-(akD*Cvk^o>bB){%X#*-bq9}ehZ!L*~p5B@c3S;=&>zrLGP}JiCl=U{F)tHgn zAh+K3wAB1wd0tjl<`795gs!i`BA;H8${^{_F3l>hVK%5bRN4p$N?1h~2Zdm%eA)=P zyw_0`OFdNV1~)QFANdK`oKf$-oy6H7N=4q?^X?r$ z{s`0TK`O7E!t|E9M~*(y+~XT|g*8y`jnyPMqOy$i<{*>_D+GGTq*a#okOHUF3Z#94 zgO>Bc3f2~;2|P3F@wQ3I1l11h`^GePs4(}NmiJxi>8dNQ{gS>xHg@32l(*!bK(3rE z?oO{UEP8u>MMy-4RZyn>P%YitU4I5#I{HMX@`;kQT<4}F^*IGux=~X7v+D0qFB?c- zW2yz+>8$p#e6q(>rIO3c)!;^_O)L3>R`si>1-7@GRh@P+<>hpJiJMBwT3^T#^Apx( znWCG4$^nYx8pbLKf9z`}X-DXiHlo;_2Z{8p@Dv*%Z`t8byNCswPn;|i^X|6HR~>-f z(yOt1x$`3d@=>vfJ@T#jdVDSO(K1^W4ebHQ$%hubuX}REs$G-xttxsw-M<_uPILUU z4%g~uv#@pT_OX4WLz_l&j`@id3ofxuW@CCqNIf?dn+${!zjBn}Ot&peo}YyR!f|-D zU7g-%9XANIL|NE_sqr^PcckSL-`JqSg3~L--=;*%o~<409Kbc%S*Sz*<;s-##W9%= z>*=1-*=_*t^s=ciI!V6#HhH}#Veh!iL|S$-UVn3Bi&r}tf$MMre4dg!pd%=anonSU)CpQtuo??n*4&2+ z9N$&}Ro)hT5MXA7H-0fX+)WJYAaNbejPE;(XR}mVTP~t>00jeyOTDP#V{BTd7kujgJdGAt2N@ z)ktNjuKbH)=&0(7omPX1+K*!@NA1mCcmHgBBh#ZS>qvl*Bdn%4sl6ICH!gzL$|!Gp zw8!L;#uA5Ir7}<~_I41GEIj%hNFM~ER8mBLWA6=XH<*0)Z zLv{tdVK!u!ISm+;NX%@clTXUn5O$%)3pbG33AE0h_D*8_2aAk1o|5GD)R3X!E4NJ@ zwVsFGkLR~%UB~_(zEOUrmfKuFP^Z}{;U?i`RX=@pfT&RQnFuq+Y*SeApEKtU8TXGA z&}j0M@NVA4y~6fmH-Ij4XlVNIh*HETF_Z4Wf#{chD4Wh6U8Pq7N_G`$squHoZm_l_ zC>76CG$B1Tkd*sPaZHHk^j)*jIJ@0Y>g$-vjU_2~I6lpT^}?hU8;FUC3n7dH({U>f zf|B}*ZT{2)9$FKMRV+F&#|LgSuHvFVbL!x^+E71!s}=K5%IL*7<-Cr3IQ7mosaFV? zPhQ$I1uO$o=lWw$Ch)64?k4(F))u=ZQiK%LDCi~cJSg(p%*B^(2xZOOAO5qL=OF7X z)PcJguH&zrN+`3|olIW+h0G}RBDn!#9z1?mw@#nPQbn{xmt1KNpK+82G0ebJnAA%1 z+a;%32R4-#0?aJ4i$2v-b30glS^W6tQfvI!0>h0;z5>S^3!_&SRXmH!7kGo*X>K{Q zZ_kv>2dzew#e&yWtyD2(sof52H}{I`x<0iVid};%KPW86ROF>#2bHT($Fg1@uLwVp zj5$8%lM{M2PU+qnr&p>Db(u3Olc8VlRo&byTWiudDO!TAQ96243%9xrGYCWoNm*Xe zh@}_B#&rBx9{o~MGZn=~O15|D)*1Ch=j!uilXl$Dul&q|@r$hNTj zRT`=jB~U4o zD>FVyLJ(9xw{Oy=a~~hoQBXti*B5 zJVHx|Z4efEMw=_%f*4jH_i8jN|=H5nqy9l%`c)<0Pmp*J! zWCNa-!nMW+ZyB>qda73^lGjNaYugG8_^mvLJJ5da+(sC&o5MOioM13ne*y{YelHb` zKh3*Rt0LYr@ppfKcc&o`ZzKcrW<2-o(zKxQW#zbLInNo;6R{HdtSiP;Ktnt<7QLlhdQC zfH8_W{SrK0Qes--jFV?#x5|DEx&6$*A?>(Y?@kjA<3Qe*W)_w3F&&7EW~1?J8QK&R z{6%+;gok!t$=WgJxOy=baDH>X zG9A-i8weh@cNfGUsW|{5I&{-#75;n5gSBl%5-a7#l_YgWv5sF>0j;7o!5LR-X-pRb zy(UrR+f`7l(wMm`iZJ$X+8#)zTiCr>GGQU+t2k~QxG^oYKKxUbzASFwI9PM*YZIMV zy_Jd62UoUW*OE;;YX0N2HZ^|zD-4D zrkWMI)~2Wi4T8|GcTx5?X73sC04(*X2je7B8QKA5&l^~SN5Ps5Ws{LV$+L>Se2|8) zrhGk+gi8l7O393&M=Yg0sq3PrMT-}r^XZELz zGi;^%efRL54f|kVf)ufzKa-$x##Bw%-7sygJW}oeax9q$HmZfV&3ntDxk%OGkafSoM4Q^r+CW>sdI*H^$)_=MpDjY&=;1M7l97bl`#{{8d3qjR%sxF{ny& zYjupVDngxZns)f0=4hgFMSRdYM3ey|Jse;(=bRA{1AoYF%qi6OlwAvjRLUb3lG|^| zXvAM!z$LqkwH@j2@sM~s$GaXiJa`0G&wIy3sh?U*pB``Pt=Je=*Tfku(~jf|RfD8v zl?zo{1#g584ff#dgf>ivhfGU?S9=Dl=jKa-=i~iI{;c;3rF6JKvornaO0F zL8%x3j7;3rUw0U%tWFRiK*~{1jIH$~P8*_r7E2H4IFcmh0DKY9t)!U zR0e@Aav2hew3tLPSx6<--YLO-whU&ZWxxu^NbgVM(Ym0e5B|iqbs!vsKD0MGAXye( zH}Y|r^d<&^d0KPFW^5VB=sMj529h`t42<=!L102+YN>pD5@uVRc9dQccDk8!DS(5o z{U>L~NQ83QF!~@RtLTH?roT1xHgZA%$&Wmz{M^Y5oVLHwFUgilt&>~krmltoc)-w1z*1 z=x*L3XZv7k?LRJ~Mwc|1rai`BZ^^mk5^Ge*GWkRx5Vftd@oMUzkQ<*hdAB+tcGYk{ zky(hK1mgLkkVfsiBpnKPf`hON8t2?44fsCIoyB@`-gc1R0{MqG(ll@Si-Y7Ejy9?;WD#J8z ze%AB?pr3Cu3P2N=ykdlSPeg}z*#(Ha(eeUa$G-rpknM!J)3;z4)Bkc}%`8S(UgkBa zpk5rGRX{)CjAiOd9;Dt%sIlT0D2LA0^&lwbPl7tqe+>*m@5Q}mdk_!UBLC|24WtmQ zF-yWaFRCT{VYZd`U6eH9a8aZwIhOB6G|NwLQ(nLhlm|Mt{#7cqt|(q}8e#k$Mj@eg zsbNB#k0STSWXo3O4RDt83cPXleg!NUq@wYwU!ipl|$6f_TANNLwF1T=4yESH4^3>7|@DA*zbOI|TT6F>$n2OHifcKrNhSDPU99DUqoSZAfCAUcpl)(95^B zjeqAPikF1k(nk|jdRb$T%=6E0?K<{E=()>n6%u=ryn{Sfc`(<&y*gsB_K zAJ}prx&4PMXeJW1eM`@OSqmcjBw3s81CD(Ajcp^%%&;##{n5@6^o7x95*t?^{VDHx zQiL;F_2++P{4s961Xdjl@mHgWNFWrCmPXr+mWwcm8?mNby^GwJE=G8)muQIhMWuWa^l*1qGO$vlc?98zP8| zbD&)4O(jWgertMs{0c*7Y#{Z#4--MwnYs^??;k%gGy@C_qG|OBFff6X(MY)F;m|5| zo44eXcIWebBf)0rcc_AJq|lp{{574K=SJNzL3>;7N*{p-3$$ALhEM-^{Rug7xdrH1QN-VRxP6IHgGkF?Uwx5)&o{i` z<4M!Bf6a)Q66pq71XZ!1c%MIVtr9SrCC_#>=DS94YCU(^KuqB_7&La#~z%Q6KJHwScX)r{PVH zyBt7e6Sk2x3PY<$Avp&bFvjLn;$M>iAzY7Q;2*v+g0*kk7KkD|Y5^Rdct$_g64eA0 z;F^bCBr5+RsU;yO0MlfDS~~>*gfwOgdRxGX@xFt&RuR3b#6Bf>M%V)d2*+ZWA`LAC@h#*?i=E zMPY}ONjJ}q%TZojh14yb9Jx^V5jETtgfMJwbY?u6+P0JTpOk_MgZI}{hu(Hqw-J6k zE0B}Pd+(fJa*TR@>L6wak=;OBe_|yfEU8E6YlAPnTJ-zScluLr&;WOl@w$}uC8<%gFpjxj3e2-_Xsm?EvE9cij{_Zx}a{n)3tX&X?IL#RBnq{-yCnc57+&!dLX)~6a4@873yqu4KT5AQj1ARKK2X|;IljO;eUOxl`pB4&F8Eyj zL-387q3Ncf-pbT8;2=>g{SykeI=NhL1U=x+aiIKhShs-+`36<5J;TV3a(|(%F>~}6 zKwQ4-Ni+r+`qep3zcV=F+-}VNyxyshP$c>FQtt1p^Bm!*4=M`ZEeT=v6SQXuYTxsO z2z_Cm+}X|FI6`U5!No+Y$y3z8dnbL#J;HU}LIh+}7my$JLl$*&Z3x@8AZuy<{&Rm2 zwvmhfnD{ehKjqea4b|ga{Y!P(q^IhobMmCvQ8AzWj52-l4?ml6=hCzuU26OHJ3&X0 zbBj~7(0YvV$P?I15tD-YZrKbw*?0j zt;EjIN`ke&~iLs>X z{6RKlp*5*md^Vq5sx@VeDA63)>dzxHzWZrMXXP*P&&*32XROsD^XwW%Eo zJ55ndCoIdsQ`MwW<;qojhStM1$ceaAPIPu;Sq1n1w{k8mzw# z$Qkn}33g&+gM(ld%jRa_sF zNscN3cbyxR6(a277V6@5U~{9WghXKYb{gm~?Z5?`XvrKl4m2afFZtW{)d@$1zLNl# zy-n}pACQD?rVnlJ(5(j^hE7S9x;#j5S29Ood8sKr;^a)INZ-IjbMs1|%`J%7AgmZG zS-_-Pdl|QrDs^L;)P5P%IwB)SkWUiEL3w(X&-E6;s*ZYk17wW)rZ@e;p?Gz6Nmy|s zFB=w&#M9Q4-PPC5d5O05Tm@m7AUrV)Jw96MpMWb04--6bw6UYKp3#d;F!g5$std{i zGOhhT0itidq!oLnD779{izS&#Pc^q5b<=bNC0H-;aBM;Tku+0o`WGN;gTcW?FYtha zy#%_q5F`~khu?Egs9!kodjru`j6n3#+OE$Jr0jPN@vMlF!}Rt?2hSdG^4M{`&84s1 z_|n1c0Vr@J6(qAj4Gy7|woZe+6T;Uw0WE4*2$MxxyPKnA6rk;ayC9ZUl)SUeR#!|Xw!@NV@Mta!pTofSQaS}glMJ$w(v!OjUQI+u&a#xd zddKXq7mAjRx?NKEbS_27FSaSDNx@bV-X4(FRuoRQwcvq2h8I8ciSkHKIdzMAdGV&~ETTC3Fda!l zf$o@KIP!Hv0emfETcmr@!Y@2n%KJGwGa@Ug;bzaTu_gZpH2tj6Hvd*NGZ-?H);aODggyq2v23PQ@&& z+Gk}ZSUFZ4)V62VeHr7*1_IM})}(-x#ze)H!}~O1ATh!S`#GozxvJ)-cm(h4VQY{5 zPzoq`PxdER!Y49Nem=|*xaz2?@3+JrP5qbJ&$`6ntx^2GFD0&#TD=Um>YSixw7QNx z3nq@2Q`k=vJq2MM%~sb`=LdwAy-B;)!1tpWWuVALcTe`|YjvCxg<))io&bDo@~54z zK>e`o?k}2O#aO^wzatlR0m+gMKp|#MmGv*`+jQ(F=^-sFd{4Q3_deHtn`Qsoq`I8tpcugAbwSq*1xtzaGRn4Dg0DAkAj?i$a3+9m&rl~W9P=O@z#i58id7;s8fo7UUAq?DGHj26pQkxthUgN=9s z%$5vxpDHvt|7i?y2oD7TsmuCV9t?=4`}-Og;Y~41+Z@E+>f@+q#WIygjlTl74|HE4 zAEJM08t(%Ll`&uUcP6Gwm)OLAK}}T~`sOvc%6E{G@V%2RuK{LMj13NEwKJjL4ELrq z&6#pJTU9#3#Okq}bOxDG{(g?s%0+fEJw-l)(^JE>@^Vc`tR!7<&>W1|4vqs`p#6Ye znsr2LdHtCX26w;1i2m-e?#$WR6nz{DufHc>G zm&~OH=p6r*KTj?P&3B+3!s{o+;&+cdn*b#i1k!#xth6f;H z4{rZHi5xqBhU#0GJ0-_|^U(@9Mp3WdX(t)tqkz?S#B>!9Qe|S}1Y$%9gMvuhed3eo zM&jQ7%Zr-aoEh>ZPP#<>_K4X4a`v2MH-*L$RK*{HOQy6ClM1F7=>V5A{PQT?RG zIf$qT6ymE!!L}byfU|UQYNdZG_T*JVl?_q3Q7^1ta<0ZM^fzH2Zmq~-Wxu01^}D*G zs4*`daXkkOFq$vzChczseJyYA=2?rjc#1}jsiU)iODk&t+AD@se|~I_ACtL`$hEmq z~l^B6Kfy9Lp8{6)!v;L3zDIalSSKUhch+eM*W$cB>Vf0yE=C60aU zok58m`ub4Hm;k7Hz+ZhHpVpC)6XFWig{_Wj zp-Z3{s^g7pvnW7RNn=LBM^JF41!O>K;z1JA<1v8ImqtbB11S^2k*%!LgAB`|OL?2w zx>KQzN@WHo?FC?>CPhv1iw})X;;Nkpb?^a<2elUgQ*sj`1JyyC(%9>$iOvXc1|r)v zZxSz%NFjEo;8X1hjJ}7Nyu_(9j=QM@1uL$(z{Ca~@rrBi@2yl@ZuxV>Dovli<>R`p zv2e3Kr5BC2L1P`SGQaM$kSsP<)gz$7%0wZ@e;=dv4IPygVP*KMN+Q-az8P~Eq)UP% zB}pc1e`Ww+;$p z1Br~*9(i$A$!sblk9G*Flj9*K8d@nuzS0BGlu)NP%3pFkFjQNc2*lzncmD*=n}a96 zcBpKgD`Rg=w>^fOv2Hlbhn{&sX&n|$HFVF5Gh^YS_)G#^yKx2!&BJ#?3wwfJB4!aX zj6B-awM^jaKN^ukgZsNtVHsp1K_}C@BAIV5Vb<8EeMer|4;~ycRSm@p;+wV0D57(2 ztA9LG2Uf;fk04 z4!;-HEM5>+TzDHIOSmPJd~xoOU)^UeaFW+kam^2Bu2!C{2(g2a56QGW&7!0XM8nWF zK4#`%Pbb{h`pNNtuEK87#kfS#@~Z%CT+k_i*}Qe7m4zcY+I*U@kXgwgdjr4=A7C`C zc8hoV_*5&JO6&bdhh`Y#Gy|X&A(VZO~ zttgglBrFNAUkXvNWP}=oCWuyNH2IoU~=XVR&+s0yTXwEr)C z65)~&r$Zm`Bq{@uZ{JfASyB2F+0{B8S}LF0L6h7S1DcZYCchev{>%+$jY47e&s$)L z#Ta!4Oqd>pH}N#1EsoN|pRQIA3i})POL35bJMHKJ&G$6aqdxl#z!r!>a8uxI!txtm zOO9u|Eg2ckNql)}GEf|Su3Dui28qkeNF9GHa?s06BsnYJx98tnR8o@i)igQUxWg@? zd7E&DG^&m@dPJ<6+t+zOmyOek{}s3LNS8qy6i#k5HD3MY4U!~lD2?l#*YoT%avN7- zF>e04_f&W9$y!u;wjV31mMIASYhqrMJ@-Boguv<`8XyfI-u^EQ@Ei#ZJ^2~?AkzHd z?By)A-UG3K)z%4|6M&IaByo2y3}!KUIqwuC7!t+40}SH$9z-;WX83wJ3g*{6zlu;~bv*e`m>H?cC*6rVc>d}G|wl19kO{@pi~nG18E zSmQme{OTqv6};Ra8=GepKGL>E*27kR{&ZwDo)?7stRI1fn$(DU@nP&(#(n7QzvYO) z8<)6KHPgrG8B`rNRw-UOe+_vyKZxfVpG6`83w0ym+U6yZ!C{W}I_%2Cc z)MlV8N|oe*T;B6L(j@CuWh>_3mctA)Nom7dSsl74{%4!edKZ?R*!r}s?~kUeF3DfK zhFSvDB6a&tV`=rEnEMVqvzT03TWJ&Z zm|PXuby`P8qwo|tjx*vfR)sTu{^|n^37}MMxT8a=?GLFvIAeX^{@Y3g{_kqX@hm8jUtiF|G>4Y2hRJ0?=j)Fg)L zv0c#l9d}1I41-;H0;?>;HfKSS_*&GtV8SHof>#Dd5YRK+6w2zLPMDBEpw$qGgN+%{ zNTNuT#_Zmxm;Ja?Ej98_|NfSYk`2p_{>xgz+E(BA0%2@juZ1SeJUMKc$Mu6EXS&0q zZ|KZ4n@0h^xFT)uM$p4Mfl~QgX|HiVXvj+KLKZRK{cs+?6KU~;*JqpjU$Q-Xt zmCf`|y7kqCP2z0=Dl8^9B*6z$i>MeWU?1>R?34?5_Ki%7aCSuWm+O ze(!(AJ_QL1xL@vu5*E|H%=sshbX8Fwx}P%xB}0F?=$s0gbl8m0QUlzpyMc!GWQ~Ps z8*rt32^DsI)k3lI1uzT+woM^CVTWBIe5w{h$)iNaZ322VLhp$!mA0ij)Hwy&tXPGR$YfV} zq7DK9Vqn28j&ePuv3%mNpA?*mD=!+dV`7U6`gYbZJqiXSpa;*ye$FsCTxMdiAV3<~ zrjt8`E%f@8@n)Gq8D9Smzs&@9ZTjMDXB7R1xvV%P=YMTwPwL9{RvUyYI)47-YPqOO zDhi(^j!vX9A?SA!^lVr_`;XPQ2={558$2F*c|Z1OUsO{MIaO(qrC`?=ZW7f-r)b+3 z)4JM?;@h?EuX#?5%F%&JKlze6OY!i2!24mgfOm*`T=#R9s@8n`$6lmWaH)3Zd&$cL zbu#7}T+Rb72c}soi$-dN#BbntL{KgPXBXtZqQTnfZ%6Cy>@nG9o`O`2y|kKDrFTN- zyIr?)%Pb>c14p7fR&RQtCvnrTz(Pr$wIwt|MLu*S^mtap%$!$pS=51`!pUB?BaD#l zc_$>SKrTxD*wmP4;yO7zV+U%-m?#fiM+qZ7CE_ZxE zH2~nFTL&e!y7GG_3=D1Qlf#Y#R`I^WPDvugxv5#+Z3ZqRp4uW$3@E4eOJPx$@fF>%3RMlDb}_*9NW}>`}cTkNiQ${amS7fP)RET zAdP{4)BRJ6Ng4>`fPE059F|r+iISf-GQ#KWe9oS0Flm!1^cxvbfpk8jAyh;UXrfS< zbf~eb2T*qDyK}@RlCZV`BxU7Ql~=gpw~D69YJ-z`#7@PyY-4W;&(`en@LzD{JVq24 zdcHx^_&=EKKvc$o7%cyG5~h?YW5&){Kq$TalF_E``r;B`Ot%XX5@13$`x#OFGcBEY zEL)|aXjx~ZOY33GseqAFnz;=LiZP*p5*d+Ed4b0PPR+aPuU@fK!x)15vkH{_N zu@^>s8wB>5-R?4R!JEINAQFB=k+YS980v&_cM|~c9hi-HTw|St6Y#G;_3(!ua|i&U z*tR152T`)7rJNxOApp#-Z~u>sbiYd=!)1-cx>o&Fttv18fl^yXBX6x zqg)OqDk3+Vd9npSuYEpbQV|M%(Ki8&ul|_Yqej(cDzGz_)kYao4w(I8}b*YbZpW_|W>x=&?nK z(nY6pt#^)yR?coIZBk<%e*)-Paa6kMX(wf68DH*%4c$vS{Gi}11K%&?L)9xG>4;*r zAx{Nh4C+NF2}XzQB5%u~@VA=#R2xwxHB&ZlK#!~nuVef(8I|vR@QGG8zPMM;Fr+>) zdekz6heP5TOBV5{yBzt!I|2luRo#FKc@>Nz)X3v+1B5~OpLm?Rg_SQu^aCs2qh@{J zna*s5jvPY^C)aAeUNp!3wcIJDMXuEYePH$0K~d~_lgQ)uX8#be0toE-si6i$&0c6I zYT{b;SnHg9h6nUoL68Z1lLex?0eYDb+n|dEdkx!TtpKGHVG2AA0Rf8j6R@(M8g2W~ znDpNmqbaI#18Hc}d7alNI-oy3IWf$cnCj%4jz($e@+)$t?tU9SpVn`~M_m1F_y)fX z-)Kb2I36xny<_q^-b`LY{e~-JsO|F(%_z=nNj^BBVMPX0UsinGnI5!1s6x2jNv7H8 zy>ca^_%M)DFN(JadZ(b5yyzM?TQ(zBdQ1 zew>;nq+|w6q85^#nr_}vaUiv0Vm*p~-W?gH=(reL`>k{X256uszT%%k{a0K?58gCmBPujz-wGj0D4ET}xbgT5dv`QVX3WXy zOSbt{eGRlrwAmCwJo4Ih2heKhDJaVPDq)DM#R}~*)b=^iI`4Xl>_y8*GIGW$7Amne zqBU0HE9oqF*O9GCO0C}}`oIDd&9zLYq<)&V*#Rmh#D5{sNlK!u zSqKBrb^JRQV2Y_Zh*Cm7aE3`t;5jTzJ{N9oyjEWViwWCTOJb8A3hw?rq%>N@f~m#u zX~tZ;zSoxYXaQ+#6=(HH_>ue9iDo?FtZ6rp{HG2Cg4KW}k&D-5pnyC6>tJB775Su- zVQ`N4`>QJiQ?3JgX_a?)$tZU*>s^_a+73CQ9Z9(#Oa)~ zWVc$UKQ`;fG{L)JM%8VR$7D3P2$yQZ*0Ma@G_AWDBN%({uO|<^&B6=T#BY@AL))=Y zFcIh9n5V#|=FXX??ktqe;mS^5L`y7?q1$^b($5#4_haVo)p+#IaOW&1TntfX7-&xH zTm_Y-8CXtO-83r=0xdvg=EQGKj#7E$f`w>wbMtosT@w2sH{IqK89$}*vgYuLg#@Q>Ai2`<(CuD5q;aa{V2VoesMRR=q z7F}~p62fe&&qDZk_HQ_4z_ z`XRR&%lwewt?J>m8u0qNwPHhsN|bkvhKkfl zb!s$44ooZ}bULI;$Aio?3A3}a1q0G~omiMH(UyrJk>?YH#u-x@fT+uq#*Sl8&=GZA zpr0addtXDz8Al+@Sr>;?Lf~mD$Hb|A0$iTT-{&b-vv8|3_>6|<)q+d)yL|JvcCdRugBRwprsLUx%drGvRpW*AEm2*w*?|Eh7d`h@Jqf@_58lPIbRQ3e3oYYh&w+R zTN(C1m79k)%$A=7W>aUQcP9|Mr&9yjYB{q5g>-KlAMyPX&%%#G3b0WdIGYD=z(@a+J--Ft1H0QP9Wufxgcgz}i* z+rN{IhGhf9pOUtITW{`poY3g+f@D~aJ~Cu$uYsuka@r1@L?G_Ltg%lu8C^M02MJqw zQ3q*NA6TNKx$h)9EI9x2&Hw$@nznU}Oj4R+dyJeJL#)xmrZ?NdnMzQd$CW9y;}EK- zDu%{4d2^vi1!F_jASH%f?+_{WL$kMEiysyMlK#FkD+4ahtPHp~vvTW-=kTLa%o;Hu zqTKA2eHR{i>Vsn$X!*aMt}-gBu5AN?5+dCo(hQwLr$~1Jhsv7SR)Zeo8R+eMZ!1TTC99bVnknG%HjmF{B8AU9_#a_tUKTlVX-D6q0QbY znXEomk-07)l(Fj+a?PPYg%-!64KG8U(YH_fu`_rm*JH7Y>8LZli6C}Lth>(J_-M@_ z)A{f{6P0@=1EI#C5!nWinim~UjaiSQ*3k}D`H?5_r##m@a#+?aR*kr#^2*oqbhkBJ35}}mfG&^zVO9GnO|A0>J+S^v+uyQ9 z5#QgYL3`7=R5Aaft}I*^?M)r3g#PJ4q9!^K|P-HSpzf5SA zrw>f1t`6DbPa_ZsRnPY;i4$Zast{{#4UrH$aa9c z;J^BmeYu9}ADvDBgFqaValaP*2RbUMh2-}@@}M1Ed-gXRdd$h%fM}}^zCq#ZD850X z?B%MK2F*;MY)O*LkMGiVeBH8Ov-0)1Ghu&lry#!JbED~6mbkQ2S>Gc6ZKhMLE~mS` z&1+p?#<+YWxT7Uxt}Bb-k16+lfD@xLwnEZC46i~SW)ZizJ}|6d4Dq89jsG&9$*6y$ zT`)P^XM`h4IKyW(#Xs${ALHU=B`Ih-U?InjD!)PK!s%HLpfhe`8#lPWrvtW%KE zSlhR>ek5~52}AUD+RuxfvBTp7CVNj&dJo|q{ycm)y%jTMfD$q%VRsj%f8(4oPH@TO zr>(8gHO+;gS$|VJa|D`AEv7d)1OV;F9qt)#xUK_~tZIEKi2=!8Xc9v#0{pKP zHoag2jr~>J)LmGh@4NKwv?M80A4<%S4~ zv~IBj-yb07>yDC;q-wthUe)(i4cW&2y%y}ZosO;*fMS+FcUE!PZ)Z|YFR;ULDQKHo zNqqT`(-wXi0!L`m{9O2JtDy){Qrv(RoAWmge2UCcA`g7BCW`1VhD9!#cu;sNtJ~7w zol^y|!;GfA>kO~c?AI#zq8!@m5&#KLK$94e0NvZK)=}(@=DsxK zmGe-R`0pw%#gD?j4pDz31mQKlM?=VnjQ$3YccX|fSyZJH0Uvp z>@G*1zdX${Vw@J_v49s9DpACJYu2ByPGDZ8c`Z%y2AIomHG#RT0!d|h`euG#KPjNH zx7s{Kc%s`Z1j)7Tf&L3=sFpA;#bbb==ocm6xYtKq0FX|Z`;y^>nBz;j!+XTzoH*S= zRS%wBB@YS>{3GUO(&jgf#qXp6r62Y=j25eh1J7wP7qoxdka+zdw6xU{&V8|}LP_(r_}T}^Pgi7iEfu~*QL>WBn7 zqK6wuQSw@xLd46_7_^PT&{B!_h2430>~dVesQ#7?wI7X6y=p&dSL(Z&VDzSnLmw5= z@z4L{1YB-$cd=~JgK>AVR7#0QRscShQI4ZFPb9nGfW&=H%jjZvH|Q_dm&nGt6sg@z z&qa_kz9IHy0TzdW#m2v}yymwcnRfF~t$7Mi+Y-2-^S=N-iRf@cn_MjApdTDL6T%2M%fQcXBgDs=L3* zY$df`kquCA1<8MG;-rBM&zzA73}eQa4j*vym${GJ9oirj8wzuG6&jk?MmnP8ba z;eNjp>y~9LC{g-+^wzfJdt(g1GX{^#a(JiLd(L$;A2(vrQ;w%vS3idctbdxeC487c zD2`TK)ARR@%|i4KU$&dU7&`xBK>4&tQZb5~CMX&zK5gdsf8cFv#1tPL4b(*Uj|63p z8J__daR%P6ZQ2)Q*rqr5S>{6ej_eR216d(E5xEAgv3i6Y8@=?VQ7%A8M}NIp5>|LQFu# z&!I0!khGbM+NB}>u^VX6g^*3xM8TC^Zvq`n>J>-#ddmnVq5bpwca;}Lm%fZkq1F5T zuIym*rBw}dG%SwRwYGZ$Pwg16)F5%hj@_i}Q5+EA@z~V=OZsCHM75!#}R!AG`zppbmxOv35vt6yrIJ*0Jojk{zW_=bH0v4B_yrZGs=d1W3G~Zmr z7ZV8TC^{97H3e`tP{= zGq4Y*=tE}IJnOR2+c#cJvd6AG%rq0vDJ+DR0YDX^wfkv|R+wdL?9>parITNYjWvbO zQBTjd8$yGLQUgU0r2dqc;RUOm<3#{AwGPj61~a0|2gEi>|McKp9Y1AvBV9cU+?SrB z^f^_MC6{Ll?_-*K6Kmk+4uPR<9~udRdFh+x)@kwh1jrJf+zXV@WYgn&o5DE%HlL|` zoTDAc*+1&;?e7#OjN830w&l@pfYvhP$LZ~LrRZQd?=|(^Z%Q^Zz9WUkvR1EHoRlU8 z=tH&7WsC65wmuPy<2Hhg;q+s)b4!eLtBAoR7vBSl`u83OYC?h?-vdy3*vb&) z6;%`dyyAob(-q?^i$P|)S#uc4biQV!A2hAbL+A(#)-AIf84+B8y1%|+rMsr}kyTU; z8hSkXCrpN(pQsoOGiY%$l8D4YPb!RUn6IKg?5uy%?Em3DSi4Q!EaxVg|D<#qIbDMU z-4=A-yQN3=260v}NAls8@21uHEG%+-XO5Ep0`tykvQ2y>OrqBDd(?516%S+^Z`aa! zY$fy$<|sLSvL45PT- zak+3$6b=D;u-EMG52E|A=%u?}XEvq}GO|I%bg|74WOnPjg&*2-J2s7F$M8F<5%9O2 z^iS?t5e}LRdmoQ~V8ek(6Bo|isbztPoE<+%M9z*M5RsEuG$eAt!NVUczoZk1f`5SQ zbbJtwk~(OnLkccP*?U_p4Bj&lrc|`-mC^T6XD_o_GP>bJ zG1N32G4%UJt)Q5pMTQnF4IFHM14oFFqowS36nEE2cPV4##4B(hIZ4JXEQzKGO4VEc zDH}j|fH-cCQNYqk;cOK6_kerd9xokXQ~b=ig{xlp+4a2E4S048vq!7pf)4hy*GLJ32E|9XGd$OOYA66yFGi+dPj5N! zv3AY!ELRIJ8?&lHLGwJhvCawnYFF;e0nuY}wqtl6 z6?S~C)ts*{T4Mx_sfXEY@ywP6D{YgC&e?C`|TT+OBWu&QdtpeR9; zYqu9T&j)`m%P*% zo{A|ih^ntrfBY(g=_HK0cycAtX_A&Z5XNAAr3_G*U)4<*D$8>xj$$B5PTQIZ^}-V{ zK$fX>#iLuciUJkIg<0SAm77qrB0Kwl!09wHeOWt`v82yCWvk*nyN@-|HN43RkrG~H zK!_Y28Q?N}jE7hNu9Tyg^A5!EzP378PS{0`Cjnv|!YQ-PXRtq_S&j$I7nTu@s{Bi? zcP{|iw`=~NutFa5{kOO?4;6aeDHs+o7Yrh)Gd~O>!vfRcT8}Fl0AmUrP^DV=15gUA zG6YJ2ojc-;MdrA{@+>3E-o|h3LX#g2Z1f%pW0$iInRiOoFomL>vzhlFL#g@YL7+}z z*k&~9(7g}BPPOr+QKqthZfx$jG{4?ovIkADyIc(toTqMmfeGK6Zm^er>VpYp_q700 z7bd3u&5rIdBixJoP=!1eI+1k?I)JgoOsGSAmgy;)8DUomRIA$gog!eewnc%NdB?mX ztVC4#%uHFzOj<@}8YgH@Sx&lC`0&x`mgU2eM{!W3Yy6tE0_Sor&kO;M!$+2jC&&`zRbvQ>JPg=n&sH$zS%Ff3%l z#$~}+Ti=E2#QqM;MCZwFp9Y`0nyIX(*xlqRRnm0T81=c9Xq;e7X3Me%A)HUchM+tuHz zMK^?gYOS%By~)u67MSVuNQRa?^+=l6UY`;B-BqGtgq;-L5c8hL>G4b7o3@(O$juwT zg(e6Oz}{po%Lf1thb)_`%@zB?G3tJY(e#?v6sfQb$)EZs1Xz{*4zWLh{^K?#Y9@Jw#9_;N0YcSt(@+R zvlBv>B{7;EB~IbccfrgPuobmG^7d6=`dlgMQ z?w}dBY;VWBjHR~#@ixid16zP`=3yWN66MjFV(OWmK%~**UeP$Z&8M+;mtVN?cY5PS zeIgycjcoMk3r{_l zL4K1!yc~rKx#8bX$t<4Oa8DM^<74&I^s1m>0ya1Sa+x;k~pc5vhsO(hu8l`0-o|QLQtfia|WqAdgo#f z(A*&Bi8Ff7L`rn!evA{xL;yI*P=8BZi7ki7@7mJb%=txFaR#u%x()DyQNKfVxjmEt zm>}Zg(V=PA`01}{mZurrQ5)HGahJb4Q3F?|`?AE1w;U&U6^UiGlpbWAl0|#ME82^C z|7fbZhzoQ~3h4(~%CYc&901-+DApr=+@>E@a@G8|mJ!I4zbGDr?GGopV=Ts3$fufN zDzGExOVA?}pW)*J5i6jKxb^Ugpy*_n;pa`4a^NG9U3lB^X5dZ8SsK|ZI zsLA)H`5wX@{#IuX^FqlGW6V!I=T#vOZn?~vacVJi=ffxCJXXI?Mh~ohzwAMSUVqk$L9H1c5~0UgUQr3(}Us0Shlg|Zzs|aGLohy z+=&WU&UH0t+)=)ly<{LnM6pGd9B3uXagbJ`tQ3PjsQ@r!JEjwMg#S7TJ|VWkYLh;4 zrh(K8cg!^ekJ-@g>YEMUyOJoKvRZ%{<1ue;9ws9Ax+O8dHBNKvGyb_9t#(`sRyimA zv?70O0C#S8HXEj{rcm z3rbOj3AREVlUb58Ohl7e+!@jVT<8#}_E8A})&425(|f!rN;J;Rji=m)WD#uOS$BsT zVFj9r*jq&kTo2klJn756VkUC;vH`O4g4(%{g)wi^+@FUa`l@E6a|QtkK}klUS0P!+ zVS1O7w?8xnx()FtdOId!05&i__TO)rXzU*vqTxE%mTZpskuSo0n3WhH6705Ojzc6U zmiW6Ooj=M{dmbJtui6y}!(dnP3u0XhB`QbSb*olkw`W+pgvMS#F@?UfL6g?ZffDKe zb%sZ`UWyNsSN{hT^U_y8(w%zxYnT>v#Q+0@&VyQ z7}XKzNg*Te)Je1k0Ywbm*E@WSP&jNLSz(~x_!b*Fv40ONE~`4U|=pGi-Kf9?QzhaPb@_vJ^4@*+L9b%{8eN{dr85Wjq@~JIa>-?pc z2#qW>-nJ>s5qcd(+XgCeupucb-&NmeQVCExo2AJgpCA6G@&efpPkZJPGn`CBN=gD?i&Bi>OsO*jzP*vz7*t)$XtI|P2kX`FHzPmccB zD6bj&3!jmxrWK81E-BvlyM6b9aarb$&Ww(N*Il{ahv1SM1uZ}rKByfbBS>tID(^4@ zi1OJF2j2M$adZwe$_cFeNh1)bXKoZ4ty1EK#R6tBFd;CLfe9HFs`G@9$jq1@E!{Tf z0LN}{-PoPXU74`Z(SAH z;v*+dfZyxz#$0F={<+=!(9W|CLP1_Z?IK*+_@v{}=`6b4Q8EP_6rJDPCexC( zxuQv%++fqQ-2Nccr+zYjT&fCns5}FITj{Ri1c?}Od?1R&J z0J?!joXS5#6E->^QuOJEh!jKm0g>WdNjV@=6vI~I<}A~UsW3lABQn06nky0At&s_; zydIc|6X{*%tx%ScXKz1>-T3unFk_btL8?0_C~H1ctLy7YDC{D@Ai7J2es;a%uegv< zp~a6D#VZe=lmZnb-*|#dzP%Z1Mp*u=?7RWC6qnOIFyP8*NUh_Ptx4}^E3pEM%&qz< zKa?jiMyGe>0r%K8w#@!71F7+R0L3o7!pOEw;S?6%PZAO?W4Zc6=^6E>_UFLT0^U$Z ze+d_A?RW`Sbj@=Kmu*WRmx;`KgHLezC$ry6^_c*WtZ1JckeCz&^wc@ApJc)?Q+3qLB`vjcQq@h#T?CIfY0SqT7}*|PJ+_=23+kIeoUsKuRc zNwlPLPtDJs2L;#4I z$R#W;Bh)hl1%GdC|6rKP@-AI@-fzI=)BdnWe^>a1enXvC3ad%s`DiC?)irVHxp(aMXz+uHN3aOZ6_&3l4YIh58!{@F<4?61`!A{cN{ISy;-a>Z0W zE(J8WC}uLG9MWaXXZ-PvZ4r-%tk-G+Z~9&)D@!Einm$Vy-G^J)NsN3~J*x1yS~R)v zP|u9Q@L)xVSaN|jike)SlZMd<^ZJc3$@nJg-i>L?^gPHRY7;6K5rOw#=nWUH>VmnB4r;E21ctLl8?6 zljb_iVYt%L|HtY_q)ojvKsG#dMkkT^S|HsZ*(dXGwmcbT|4gD8JbgPN z3nkq^o$f&ZX+5U#&I>&K~bByX*kY!B8OH zDOZQh#=Oo*inZvIVO+}qu!CqDHZPq!MC5(9%y->Tim2PC$+J*S7hpJW$w85B)k);3i%>FI^Jo!f_uhS$B4(6g9E_VB2r=^ksPIam5JC;~1)xC| zw3GoFBux<$pg{^TWvsushf{W4uks}w2fU@&;g)wDlaSdKf$jtctC#;A|p33M}$e2}GfaWEJxp;UI`ZmEp zloK_k5-sxlp8uZfpD^#LAnj{J|Ir>7KF_{eE&NdT!+&VcQf~mtbTg%&%TKb`qzMab+_J= zP@{>2r}3irCg(rX@Tq|!m=VnGuz2A&3S;oLaT|M-@k}_R0{i}xGN8f`2PP@c<78cV zJqY`a#kX(lKNqB`eR*q}Y?DVYoypm4^jScKAZ4tvbB|tR!A@X4CFKtt$6|?xi9IB< zWCZtf+zFExAGU5JS?pDg&%c{dfQw(QR|QV)e;5KHyn4RGB~$LURis~~c<=S&bQ-D? z;aGjx&chXP;X&5jU(;{Dp#VbpWYErr%5R{=2NHn`^G9KtOjnWHMo+4t;ri@9sV@J_ z-TtP*RGjU|ZOL1cjmcwK54=axe879OuAet^WVWLJSxh79=A%VW{NaiQwwFq5^Xvz~ zQta5mX8~x#wbkhkEnum72xzozNw6nrd%p{WxJ9{Acnb1~wL_Bg`c6C?!T499AEk*z z+f6vWe);!eRy^J%&`HM77fImvsELx0pwGz*) z1gl%M!MgLDCU9BIVj_rZfgh5KAHaaAfF^50MS%^-ifnN9ew%Dkr+ z^}+;?kSW`)$x&mlkxsbA=8Ull`7bzV{pE#wG6&;5e6i*@6^}mL*ZK0ta;ZWKK?A+^ zLoefHQQ*6i9)cj(Xv@Bm*kCf+^q3iEBMJwKr)% z>-Kfm7aul2*!dPnSTu$E03E>k7fraf2LoM{hIg-tub@Gw^>1D$Yd!OVt7<~R2d$9u zQi5f3AuzJk76sq4ag~kER$WhKv_g9;Mt6Rfi+8d5T1z1cFEx;;rrtXirUA}Tx-esWgL7qMkJwOR{&INm0Q%Rn57Er}2Hhq?`x(RegYC3z z-lrSOcpZXq+h%ioD7eoqlkRd2aZQgap1vC!^h5g*#}U?10cvh*L+@L+#!hgvqL*QD zItSCSR@!S(+C+l4L*`Kxc}HtZe{&cqkJ;C!417qkQ2#a42X7}Wm{zr^)@;fa6=Y?pxM2bD2m3# zV885b<9qez`-l8Q5g?DV0oC^ya7-{X-Ezj>#-+n+$(Z{jZwe`n9`o{)?a|b`*)669 zNzPYW@G)`B9lvPosnWR>8G`HpHlV2rI2zk~qXSmZNwgl1G}mMq@BtUP{R~{eW}1qX zJJ6|XBMcxt?S6U7{?7&0q+q@-0(8lgWc zz9UrlLF~^fM@*-dFpa1}OK*#9?dU1LmPM_5r)Br_Hvp6p!TiK@IwH=Z2~1;G+u-bZ zcX9T{`i_70lS|aac-!E^fo;^qW{SIq!-td5)V+^-LCl%Q*7n7MG;8{{Z{kjbiO2~K zTt|$M)Jc3QD2-0~?(yJVs{F%c8r=hfGagt2!`P)?EOL^lLB#8y)-l*w2KsL|F1Umm z99J(M9SMg64}OPs&U;PTA+PIq9rV{3I-E2|1tiKhvhS~H4Or}l@d<~j)f=WGWDUhA z)a1VaYBfO!2fA2Y{30vvX}(r^KhLOsORhNo0j`fFs1!0c-^jX2%X1@#Wdd_EeVFDH z(|6GrU~WFwR6e>bH^XKxEqA#v?A^maCTsdm+u(R8nY&G5Xh!jg>Pv;u^vF8~Rdp); zHtz+AXnEj=U?T(qk?{Cx5a2pixh?*RbQ*Dla6R?ODDAr`umtk5HLsoDOl@BYDe_;m z5N^e}Y8DTGfH*VkuF_)Cl+BVV(F5pb7+AjfH=_F`1JJp^XiYIY zR+{B%j8`-^ml@*8H;~7t;&X?YU-nXYM&S{HT9wiA>{Mrw;(DD>2D{e<)em*j*6_^dOfMG%_v;LxagR3csv&(EJtKV!fuINQo&SFn)E)up z*eeZ@O8;HZo@m-_AW(HmUj1LWp&UvONIy)t5Xp@(fwri{Y#r$k+l+Jmw)OV!v=ke|FjD{^(cH2+QNAeAgAm0f`m3 zXa(jomyyeEY#^bvQh((lephJMBsSuPf3M(07!WnR7(lcfgl$kb@v>g)0DZ>XT?vOA zcfeF5|2PA3PLP$Gt=FSB=F{(`xt{TIIl$?80sUqJ7<^7$W)aZ)S>S73<72ef*tTx_=RY87DAl}h^pe8nRYb3V11HKNogDj7!D z6}_!x?6r*a>s&%$jR!Y_(~k4I`nA^+-JJ&Id~e6`+;61^@8OR-F4=+IMC-R3e~Qs~ zE+S3We2<#2ii^hYkq4ZLo!0pKhDCeWOkAz-^bFMJ$n*^C)gQZbPbol$L&-1>IpT9n z%+_>6&d7+$+ZX<}nVCc%I028mu6Jm8L)-RlNX2wj)fBM=8N?|B=Gs2!TY3)8nzcu^ z@Jvg_7eWj+Mseb6q5M?*fF=N#MK{p|4&p$gG_~@N6_LM5l%1l;yzbc-l1avyQUhh^ z+gg`i-jS@n&jj8ozi*Jh%1gRM1z5P-kGx3#7689*5Xb4S44fU+5*(cD*`jTccGYMViTSylwmgLr{Q z6a52tG@t&~ubm@Z=dowzyE<0nd@E%^0UiyZfJE1=R^$)Gzm2t)aW2`No6dJf@$j_!R62l(neX8rf~=>ELCVR>^%Wt zmSAD62WFaD%4XY`?_~As;|ekC-2o>o3U!>~jqe?_pPPUS1(qy@z~^@Bn-FR$3=Y8D zQ@fA>Yo00wOBEQdmQ4tj1)QRYfW{+N;vaU#U%--C`5DO9E?|+8z5pcvN}bjCky$(P z6N&@cCsidHh<6}<#H!!^-L>}aXnlfe(qTiYPqY=-+%J5c!`u%LnzLBvKA?a;CGyR= z{H-a=PAnFa@X6{!eEcOn^auS$GgYS)$f|Aa(uf|n{^XHJc>!eb67GPF+{cD39zH(6 z5?@#gId?E%_`t?Jz*pP)jN?trg&LLRrEf$2>Q>fn#Mq~wHQvr)!F}bryJ)oa{WI&6 zSi_AJ*rL_$G2Tc?$*jVwQAZDlA6dW00r9zxO(d)1`wl&XxDiCXwbwrRm_%;iM?>3| z9tJ)~s;Li1!PKX7pYgi5f9R&mlJE46Uj7q1*k7_W{zw$K7;t^2=;T|_kKFujHHX)S zNa0U^6k8b#KCj`?CIi$I#`zB_B5B$cpb$Eg_((ubff29#K!3SqfAgV;o5zPYT{bwB z@AAg}frLt>y7Y=D_5K>=hh8^`P5V_oOQt=u#_r^;R8jPZOcni z`9N7VM8&$rt3p8uoUYh;$mtqB22NK;i<N%Pei<0sbHGZ^*j~{ta2)Eg;ML>RSOI0mRZz z!17HS@@wO73E-tm_4$C8R=(^ToUv%x-S4bdhgJ3N6Tp?yx#b#=1I3qJ3vw`0DW7zpv^YmzETgl{^C~-0p$(<#%v+PKMK2w5iq<@uZy(=IlaDTAw5PX zxQzA?(v_(jW|C=nA5>ry1^lb89R|skdUGq%SV2dC8BM|(m`unyfXO6oEw~*)QSd^- zTA#;LZztgb$TmSl88oaq`s_)X*!{vU-MEYwHfRw%@`N|AEg|2L6rG+(Ye{E7;KPDF z=^si#UNW$aFg>D9cj?U=-v4uBsYqp%Nv%?1%Jn^rlW`%9mE2Zzgb)e zVlkSh#ow8t^l}$myR>6r9x; zPXTMG-0S6?8m2lMPpW6-ZvjU%xjv~5*1zRLf!jk({lSb^Yb8J>I{C^ZtkpQvD_iyL zAVkqARo(v090qXtT%YV{L{gzAijJ}b+R?^wW@*NajN%nDHW;}@PW!ihljeKG*4VQv zOmN*BV=9}TUKImC+Kk&&9KJ#RvxlNlQyTc=mgb9}r(d}3eWx$=S%g;0xUStImvs7- zCnMA@u)7xTwpC!$cJkQ5Z{PexG-L3qp;oJ5c&A%wZ?uf`(uiOcuK<;D$@YuUhV|%Y_|(oPtD595`Qb$ zCuLv%(u`~!`>1vd$^>xnC0cMx2LL8cR|U_y>&;RHS$UP>4VM?uQqe?%v~6)=Z>E_{ zFqGe_L5he8q2@IgVoYOVu!;o`-TTED4ns0`LlmNe8UKHD;vEwGaoS10pBR9nI2aPsomzoBx>-jr@fl^ap#VjLK;D@ccyI#ghjRy$NM z|IUd&wx@mRp8be3*QODl|CJjY23)}4XEMzp_ASjsL0iei6uSaxl}2;0znDv8APi`m znqQ)8+{@q@9$w~9KAOnOuct*RB*eEzZA9dfzs%GqIC3Z9vxRnYajmk2Za)=$&NJ1j zHuKjIod&x#JRNW20JVfI6mXb|qG?+{eDl1OBJ01gW_>&PRF+*#0*f88j!LV%XehkD z;96^d1i9T6IfZyfMh!5^!GTw!$N6=iS75L+t2w`gw^xWamS4^EK|JzxhoY`3RaeK0 z0O%)YUqiC$seRPsZ9L^kF5ZZu_218uWYYTsuCZ=N>Tj|B=+_Q@)NTKWJKxcLqa z6b7~Fv?OgkPg3REeTqf3&mv_{$1sb+j^#V&4+&XG>_tB(aa=H;@AYNQj9q={TpF1< zOXxie%C{^>bH>-L|M|)s8a%PG$@QNem=2m(_92;tR(WFSR&g#$Ki8en6)0Q?4BtqN zWZ7YF?qary6$9^Ub3&62dk6nAuV{vt)z>YYs*3V1(xfr8i9F!9;!we;1s(I6zd`y- zj^v(cKU|sC_0(S`vPespm3NYpZobxr-xvdseKtD4O|hxvR6R3VIB#NFoib3#niv8y evW$&0t#$tX&eBV~Yx?o}7y1P0nLEP-5$b;r8Y3bA literal 0 HcmV?d00001 diff --git a/contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml similarity index 100% rename from contribs/application/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml rename to contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml diff --git a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkConverter.java b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkConverter.java index e6522716ed4..0a806f1546b 100644 --- a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkConverter.java +++ b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkConverter.java @@ -18,7 +18,7 @@ import org.matsim.core.utils.geometry.CoordinateTransformation; import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.geometry.transformations.TransformationFactory; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.core.utils.io.IOUtils; import org.matsim.lanes.*; import org.xml.sax.SAXException; @@ -121,7 +121,7 @@ public static void main(String[] args) { */ private static Geometry calculateNetworkArea(Path shapeFile) { // only the first feature is used - return ((Geometry) ShapeFileReader.getAllFeatures(shapeFile.toString()).iterator().next().getDefaultGeometry()); + return ((Geometry) GeoFileReader.getAllFeatures(shapeFile.toString()).iterator().next().getDefaultGeometry()); } /** @@ -155,10 +155,28 @@ public Integer call() throws Exception { writeGeometry(handler, output.toAbsolutePath().toString().replace(".xml", "-linkGeometries.csv")); + writeFeatures(handler, output.toAbsolutePath().toString().replace(".xml", "-ft.csv")); + return 0; } - /** + /** + * Write csv with link properties. + */ + public void writeFeatures(SumoNetworkHandler handler, String output) { + + SumoNetworkFeatureExtractor props = new SumoNetworkFeatureExtractor(handler); + + try (CSVPrinter out = new CSVPrinter(IOUtils.getBufferedWriter(output), CSVFormat.DEFAULT)) { + out.printRecord(props.getHeader()); + props.print(out); + + } catch (IOException e) { + log.warn("Could not write property file.", e); + } + } + + /** * Calculates lane capacities, according to {@link LanesUtils}. */ public void calculateLaneCapacities(Network network, Lanes lanes) { diff --git a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java new file mode 100644 index 00000000000..7bf1154bf2d --- /dev/null +++ b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java @@ -0,0 +1,194 @@ +package org.matsim.contrib.sumo; + +import org.apache.commons.csv.CSVPrinter; +import org.matsim.contrib.osm.networkReader.LinkProperties; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Generates edge features from a network. These features might not be the same as in the network because they + * have been cleaned and preprocessed. + */ +class SumoNetworkFeatureExtractor { + private final SumoNetworkHandler handler; + + /** + * Maps junction id to incoming edges. + */ + private final Map> incomingEdges; + + private final Map osm = LinkProperties.createLinkProperties(); + + SumoNetworkFeatureExtractor(SumoNetworkHandler handler) { + this.handler = handler; + + incomingEdges = new HashMap<>(); + + for (SumoNetworkHandler.Edge edge : this.handler.edges.values()) { + incomingEdges.computeIfAbsent(edge.to, (k) -> new ArrayList<>()) + .add(edge); + } + } + + private static String getHighwayType(String type) { + if (type != null) + type = type.replaceFirst("^highway\\.", ""); + + if (type == null || type.isBlank()) + type = "unclassified"; + + return type; + } + + private static SumoNetworkHandler.Req or(SumoNetworkHandler.Req r1, SumoNetworkHandler.Req r2) { + BitSet response = (BitSet) r1.response().clone(); + BitSet foes = (BitSet) r1.foes().clone(); + response.or(r2.response()); + foes.or(r2.foes()); + return new SumoNetworkHandler.Req(response, foes); + } + + private static String calcPrio(int priority, List prios) { + double ref = (prios.size() - 1) / 2.0; + int cmp = prios.indexOf(priority); + + if (cmp > ref) + return "higher"; + else if (cmp < ref) + return "lower"; + else + return "equal"; + } + + private static String bool(boolean b) { + return b ? "1" : "0"; + } + + private static Set directionSet(SumoNetworkHandler.Connection c) { + // turn is ignored + String dirs = c.dir.toLowerCase().replace("t", ""); + Set set = new HashSet<>(); + for (int i = 0; i < dirs.length(); i++) { + set.add(dirs.charAt(i)); + } + return set; + } + + /** + * Get priority. Higher is more important. + */ + private int getPrio(SumoNetworkHandler.Edge edge) { + return -osm.getOrDefault(getHighwayType(edge.type), new LinkProperties(LinkProperties.LEVEL_UNCLASSIFIED, 1, 1, 1, true)).getHierarchyLevel(); + } + + public List getHeader() { + return List.of("linkId", "highway_type", "speed", "length", "num_lanes", "change_num_lanes", "change_speed", "num_to_links", "num_conns", + "num_response", "num_foes", "dir_multiple_s", "dir_l", "dir_r", "dir_s", "dir_exclusive", + "junction_type", "junction_inc_lanes", "priority_higher", "priority_equal", "priority_lower", + "is_secondary_or_higher", "is_primary_or_higher", "is_motorway", "is_link"); + } + + public void print(CSVPrinter out) { + handler.edges.keySet().stream().sorted().forEach(e -> { + try { + print(out, e, handler.edges.get(e)); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }); + } + + public void print(CSVPrinter out, String linkId, SumoNetworkHandler.Edge edge) throws IOException { + + String highwayType = getHighwayType(edge.type); + + SumoNetworkHandler.Junction junction = handler.junctions.get(edge.to); + List connections = handler.connections.computeIfAbsent(edge.id, (k) -> new ArrayList<>()); + + Set toEdges = connections.stream() + .filter(c -> !c.dir.equals("t")) + .map(c -> handler.edges.get(c.to)) + .collect(Collectors.toSet()); + + int maxLanes = toEdges.stream().mapToInt(e -> e.lanes.size()).max().orElse(1); + double maxSpeed = toEdges.stream().flatMap(e -> e.lanes.stream()).mapToDouble(l -> l.speed).max().orElse(edge.lanes.get(0).speed); + + List req = connections.stream() + .filter(c -> !c.dir.equals("t")) + .map(c -> c.reqIdx) + // Filter connections without junction + .filter(idx -> idx >= 0 && idx < junction.requests.size()) + .map(junction.requests::get).toList(); + + SumoNetworkHandler.Req aggr = req.stream().reduce(SumoNetworkFeatureExtractor::or) + .orElseGet(() -> new SumoNetworkHandler.Req(new BitSet(0), new BitSet(0))); + + Set dirs = new HashSet<>(); + boolean multipleDirS = false; + boolean exclusiveDirs = true; + for (SumoNetworkHandler.Connection c : connections) { + + Set d = directionSet(c); + if (dirs.contains('s') && d.contains('s')) + multipleDirS = true; + + Set intersection = new HashSet<>(dirs); // use the copy constructor + intersection.retainAll(d); + if (!intersection.isEmpty()) + exclusiveDirs = false; + + dirs.addAll(d); + } + + List prios = incomingEdges.get(junction.id).stream() + .map(this::getPrio).distinct().sorted() + .toList(); + String prio = calcPrio(getPrio(edge), prios); + + int incomingLanes = incomingEdges.get(junction.id).stream() + .mapToInt(e -> e.lanes.size()) + .sum(); + + boolean geq_secondary = switch (highwayType) { + case "secondary", "primary", "trunk", "motorway" -> true; + default -> false; + }; + + boolean geq_primary = switch (highwayType) { + case "primary", "trunk", "motorway" -> true; + default -> false; + }; + + out.print(linkId); + out.print(highwayType); + out.print(Math.max(8.33, edge.lanes.get(0).speed)); + out.print(edge.lanes.get(0).length); + out.print(edge.lanes.size()); + out.print(Math.max(-3, Math.min(3, maxLanes - edge.lanes.size()))); + out.print(maxSpeed - edge.lanes.get(0).speed); + out.print(toEdges.size()); + out.print(Math.min(6, handler.connections.get(edge.id).size())); + out.print(Math.min(12, aggr.response().cardinality())); + out.print(Math.min(12, aggr.foes().cardinality())); + out.print(bool(multipleDirS)); + out.print(bool(dirs.contains('l'))); + out.print(bool(dirs.contains('r'))); + out.print(bool(dirs.contains('s'))); + out.print(bool(exclusiveDirs)); + out.print(junction.type); + out.print(Math.min(12, incomingLanes)); + out.print(bool("higher".equals(prio))); + out.print(bool("equal".equals(prio))); + out.print(bool("lower".equals(prio))); + out.print(bool(geq_secondary)); + out.print(bool(geq_primary)); + out.print(bool("motorway".equals(highwayType))); + out.print(bool(highwayType.contains("link"))); + + out.println(); + } + +} diff --git a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkHandler.java b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkHandler.java index be4e6ade5ac..bfe6adb3158 100644 --- a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkHandler.java +++ b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkHandler.java @@ -20,438 +20,484 @@ */ public class SumoNetworkHandler extends DefaultHandler { - final double[] netOffset = new double[2]; - - /** - * All junctions. - */ - final Map junctions = new HashMap<>(); - - /** - * Edges mapped by id. - */ - final Map edges = new HashMap<>(); - - /** - * Map lane id to their edge. - */ - final Map lanes = new HashMap<>(); - - /** - * All connections mapped by the origin (from). - */ - final Map> connections = new HashMap<>(); - - /** - * Parsed link types. - */ - final Map types = new HashMap<>(); - - /** - * Stores current parsed edge. - */ - private Edge tmpEdge = null; - - private SumoNetworkHandler() { - } - - public Map getJunctions() { - return junctions; - } - - public Map getEdges() { - return edges; - } - - public Map getLanes() { - return lanes; - } - - public Map> getConnections() { - return connections; - } - - public Map getTypes() { - return types; - } + final double[] netOffset = new double[2]; + + /** + * All junctions. + */ + final Map junctions = new HashMap<>(); + + /** + * Edges mapped by id. + */ + final Map edges = new HashMap<>(); + + /** + * Map lane id to their edge. + */ + final Map lanes = new HashMap<>(); + + /** + * All connections mapped by the origin (from). + */ + final Map> connections = new HashMap<>(); + + /** + * Parsed link types. + */ + final Map types = new HashMap<>(); + + /** + * Stores current parsed edge. + */ + private Edge tmpEdge = null; + + /** + * Current parsed junction. + */ + private Junction tmpJunction = null; + + private SumoNetworkHandler() { + } + + /** + * Creates a new sumo handler by reading data from xml file. + */ + static SumoNetworkHandler read(File file) throws ParserConfigurationException, SAXException, IOException { + SAXParserFactory factory = SAXParserFactory.newInstance(); + SAXParser saxParser = factory.newSAXParser(); + SumoNetworkHandler sumoHandler = new SumoNetworkHandler(); + saxParser.parse(file, sumoHandler); + return sumoHandler; + } + + private static BitSet parseBitSet(String value) { + BitSet bitSet = new BitSet(value.length()); + for (int i = 0; i < value.length(); i++) { + if (value.charAt(i) == '1') + bitSet.set(i); + } + return bitSet; + } + + public Map getJunctions() { + return junctions; + } + + public Map getEdges() { + return edges; + } + + public Map getLanes() { + return lanes; + } + + public Map getTypes() { + return types; + } + + /** + * Merges another sumo network into this one. + * To work properly, this requires that edge und junction ids are the same in both networks. + * This function does not clean left over edges, when using this, a network cleaner should be user afterwards. + * + * @param other other network to merge into this one + * @param ct coordinate transformation to apply + */ + void merge(SumoNetworkHandler other, CoordinateTransformation ct) { + + Set notDeadEnd = other.junctions.entrySet().stream() + .filter((e) -> !"dead_end".equals(e.getValue().type)) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); + + // lanes length may get incorrect + // this uses the maximum length for merged edges + for (Map.Entry e : other.edges.entrySet()) { + if (edges.containsKey(e.getKey())) { + for (int i = 0; i < Math.min(e.getValue().lanes.size(), edges.get(e.getKey()).lanes.size()); i++) { + Lane l = e.getValue().lanes.remove(i); + Lane o = edges.get(e.getKey()).lanes.get(i); + e.getValue().lanes.add(i, l.withLength(Double.max(l.length, o.length))); + } + } + } + + edges.keySet().removeAll(other.edges.keySet()); + lanes.keySet().removeAll(other.lanes.keySet()); + + junctions.keySet().removeAll(notDeadEnd); + + // Re-project to new ct + other.edges.values().forEach(e -> e.proj(other.netOffset, netOffset, ct)); + other.junctions.values().forEach(j -> j.proj(other.netOffset, netOffset, ct)); - /** - * Creates a new sumo handler by reading data from xml file. - */ - static SumoNetworkHandler read(File file) throws ParserConfigurationException, SAXException, IOException { - SAXParserFactory factory = SAXParserFactory.newInstance(); - SAXParser saxParser = factory.newSAXParser(); - SumoNetworkHandler sumoHandler = new SumoNetworkHandler(); - saxParser.parse(file, sumoHandler); - return sumoHandler; - } + edges.putAll(other.edges); + lanes.putAll(other.lanes); + + other.junctions.forEach((k, v) -> { + if (notDeadEnd.contains(k)) + junctions.put(k, v); + else + junctions.putIfAbsent(k, v); + }); + + // connections are merged individually + for (Map.Entry> e : other.connections.entrySet()) { + + if (connections.containsKey(e.getKey())) { - /** - * Merges another sumo network into this one. - * To work properly, this requires that edge und junction ids are the same in both networks. - * This function does not clean left over edges, when using this, a network cleaner should be user afterwards. - * - * @param other other network to merge into this one - * @param ct coordinate transformation to apply - */ - void merge(SumoNetworkHandler other, CoordinateTransformation ct) { - - Set notDeadEnd = other.junctions.entrySet().stream() - .filter((e) -> !"dead_end".equals(e.getValue().type)) - .map(Map.Entry::getKey) - .collect(Collectors.toSet()); + // remove connections that point to edges that are also in the other network + connections.get(e.getKey()).removeIf(c -> other.edges.containsKey(c.to)); - // lanes length may get incorrect - // this uses the maximum length for merged edges - for (Map.Entry e : other.edges.entrySet()) { - if (edges.containsKey(e.getKey())) { - for (int i = 0; i < Math.min(e.getValue().lanes.size(), edges.get(e.getKey()).lanes.size()); i++) { - Lane l = e.getValue().lanes.remove(i); - Lane o = edges.get(e.getKey()).lanes.get(i); - e.getValue().lanes.add(i, l.withLength(Double.max(l.length, o.length))); - } - } - } + // add all other connections + connections.get(e.getKey()).addAll(e.getValue()); + + } else + connections.put(e.getKey(), e.getValue()); + + } + + connections.putAll(other.connections); + } + + Coord createCoord(double[] xy) { + return new Coord(xy[0] - netOffset[0], xy[1] - netOffset[1]); + } - edges.keySet().removeAll(other.edges.keySet()); - lanes.keySet().removeAll(other.lanes.keySet()); + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - junctions.keySet().removeAll(notDeadEnd); - // Re-project to new ct - other.edges.values().forEach(e -> e.proj(other.netOffset, netOffset, ct)); - other.junctions.values().forEach(j -> j.proj(other.netOffset, netOffset, ct)); + switch (qName) { - edges.putAll(other.edges); - lanes.putAll(other.lanes); + case "location": + String[] netOffsets = attributes.getValue("netOffset").split(","); + netOffset[0] = Double.parseDouble(netOffsets[0]); + netOffset[1] = Double.parseDouble(netOffsets[1]); - other.junctions.forEach((k, v) -> { - if (notDeadEnd.contains(k)) - junctions.put(k, v); - else - junctions.putIfAbsent(k, v); - }); + break; - // connections are merged individually - for (Map.Entry> e : other.connections.entrySet()) { + case "type": - if (connections.containsKey(e.getKey())) { + String typeId = attributes.getValue("id"); - // remove connections that point to edges that are also in the other network - connections.get(e.getKey()).removeIf(c -> other.edges.containsKey(c.to)); + types.put(typeId, new Type(typeId, attributes.getValue("allow"), attributes.getValue("disallow"), + Double.parseDouble(attributes.getValue("speed")))); - // add all other connections - connections.get(e.getKey()).addAll(e.getValue()); + break; - } else - connections.put(e.getKey(), e.getValue()); + case "edge": - } + // Internal edges are not needed + if ("internal".equals(attributes.getValue("function"))) + break; - connections.putAll(other.connections); - } + String shape = attributes.getValue("shape"); + tmpEdge = new Edge( + attributes.getValue("id"), + attributes.getValue("from"), + attributes.getValue("to"), + attributes.getValue("type"), + Integer.parseInt(attributes.getValue("priority")), + attributes.getValue("name"), + shape == null ? new String[0] : shape.split(" ") + ); - Coord createCoord(double[] xy) { - return new Coord(xy[0] - netOffset[0], xy[1] - netOffset[1]); - } + break; - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + case "lane": + // lane of internal edge + if (tmpEdge == null) + break; - switch (qName) { + Lane lane = new Lane( + attributes.getValue("id"), + Integer.parseInt(attributes.getValue("index")), + Double.parseDouble(attributes.getValue("length")), + Double.parseDouble(attributes.getValue("speed")) + ); - case "location": - String[] netOffsets = attributes.getValue("netOffset").split(","); - netOffset[0] = Double.parseDouble(netOffsets[0]); - netOffset[1] = Double.parseDouble(netOffsets[1]); + tmpEdge.lanes.add(lane); + lanes.put(lane.id, tmpEdge); - break; + break; - case "type": + case "param": - String typeId = attributes.getValue("id"); + if (tmpEdge == null) + break; - types.put(typeId, new Type(typeId, attributes.getValue("allow"), attributes.getValue("disallow"), - Double.parseDouble(attributes.getValue("speed")))); + String value = attributes.getValue("value"); - break; + switch (attributes.getValue("key")) { + case "origId": + tmpEdge.origId = value; + break; + case "origFrom": + tmpEdge.origFrom = value; + break; + case "origTo": + tmpEdge.origTo = value; + break; + } - case "edge": + break; - // Internal edges are not needed - if ("internal".equals(attributes.getValue("function"))) - break; + case "junction": - String shape = attributes.getValue("shape"); - tmpEdge = new Edge( - attributes.getValue("id"), - attributes.getValue("from"), - attributes.getValue("to"), - attributes.getValue("type"), - attributes.getValue("name"), - shape == null ? new String[0] : shape.split(" ") - ); + String inc = attributes.getValue("incLanes"); - break; + List lanes = Arrays.asList(inc.split(" ")); + String id = attributes.getValue("id"); + tmpJunction = new Junction( + id, + attributes.getValue("type"), + lanes, + new double[]{Double.parseDouble(attributes.getValue("x")), Double.parseDouble(attributes.getValue("y"))} + ); - case "lane": + junctions.put(id, tmpJunction); - // lane of internal edge - if (tmpEdge == null) - break; + break; - Lane lane = new Lane( - attributes.getValue("id"), - Integer.parseInt(attributes.getValue("index")), - Double.parseDouble(attributes.getValue("length")), - Double.parseDouble(attributes.getValue("speed")) - ); + case "request": - tmpEdge.lanes.add(lane); - lanes.put(lane.id, tmpEdge); + if (this.tmpJunction != null) + this.tmpJunction.requests.add( + new Req( + parseBitSet(attributes.getValue("response")), + parseBitSet(attributes.getValue("foes")) + ) + ); - break; + break; - case "param": + case "connection": - if (tmpEdge == null) - break; - - String value = attributes.getValue("value"); - - switch (attributes.getValue("key")) { - case "origId": - tmpEdge.origId = value; - break; - case "origFrom": - tmpEdge.origFrom = value; - break; - case "origTo": - tmpEdge.origTo = value; - break; - } - - break; - - case "junction": - - String inc = attributes.getValue("incLanes"); - - List lanes = Arrays.asList(inc.split(" ")); - String id = attributes.getValue("id"); - junctions.put(id, new Junction( - id, - attributes.getValue("type"), - lanes, - new double[]{Double.parseDouble(attributes.getValue("x")), Double.parseDouble(attributes.getValue("y"))} - )); - - break; - - case "connection": - - // aggregate edges split by sumo again - String from = attributes.getValue("from"); - String origin = from.split("#")[0]; - if (origin.startsWith("-")) - origin = origin.substring(1); - - connections.computeIfAbsent(origin, k -> new ArrayList<>()) - .add(new Connection(from, attributes.getValue("to"), - Integer.parseInt(attributes.getValue("fromLane")), - Integer.parseInt(attributes.getValue("toLane")), - attributes.getValue("dir"))); - - break; - - - } - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - if ("edge".equals(qName) && tmpEdge != null) { - edges.put(tmpEdge.id, tmpEdge); - tmpEdge = null; - } - } - - /** - * Edge from the SUMO network. - */ - static final class Edge { - - final String id; - final String from; - final String to; - final String type; - @Nullable - final String name; - - final List shape = new ArrayList<>(); - - final List lanes = new ArrayList<>(); - - String origId; - - @Nullable - String origFrom; - - @Nullable - String origTo; - - public Edge(String id, String from, String to, String type, String name, String[] shape) { - this.id = id; - this.from = from; - this.to = to; - this.type = type; - this.name = name; - - for (String coords : shape) { - String[] split = coords.split(","); - this.shape.add(new double[]{Double.parseDouble(split[0]), Double.parseDouble(split[1])}); - } - } - - /** - * Calculate edge length as max of lanes. - */ - public double getLength() { - return lanes.stream().mapToDouble(l -> l.length).max().orElseThrow(); - } - - @Override - public String toString() { - return "Edge{" + - "id='" + id + '\'' + - ", from='" + from + '\'' + - ", to='" + to + '\'' + - ", origId='" + origId + '\'' + - ", origFrom='" + origFrom + '\'' + - ", origTo='" + origTo + '\'' + - '}'; - } - - - /** - * Project edge geometry to new coordinate system. (in situ) - */ - private void proj(double[] fromOffset, double[] toOffset, CoordinateTransformation ct) { - for (double[] xy : shape) { - - Coord from = new Coord(xy[0] - fromOffset[0], xy[1] - fromOffset[1]); - Coord to = ct.transform(from); - - xy[0] = to.getX() + toOffset[0]; - xy[1] = to.getY() + toOffset[1]; - } - } - } - - static final class Lane { - - final String id; - final int index; - final double length; - final double speed; - - Lane(String id, int index, double length, double speed) { - this.id = id; - this.index = index; - this.length = length; - this.speed = speed; - } - - Lane withLength(double newLength) { - return new Lane(id, index, newLength, speed); - } - } - - static final class Junction { - - final String id; - final String type; - final List incLanes; - final double[] coord; - - Junction(String id, String type, List incLanes, double[] coord) { - this.id = id; - this.type = type; - this.incLanes = incLanes; - this.coord = coord; - } - - private void proj(double[] fromOffset, double[] toOffset, CoordinateTransformation ct) { - Coord from = new Coord(coord[0] - fromOffset[0], coord[1] - fromOffset[1]); - Coord to = ct.transform(from); - - coord[0] = to.getX() + toOffset[0]; - coord[1] = to.getY() + toOffset[1]; - } - } - - static final class Connection { - - final String from; - final String to; - final int fromLane; - final int toLane; - - // could be enum probably - final String dir; - - Connection(String from, String to, int fromLane, int toLane, String dir) { - this.from = from; - this.to = to; - this.fromLane = fromLane; - this.toLane = toLane; - this.dir = dir; - } - - @Override - public String toString() { - return "Connection{" + - "from='" + from + '\'' + - ", to='" + to + '\'' + - ", fromLane=" + fromLane + - ", toLane=" + toLane + - ", dir='" + dir + '\'' + - '}'; - } - } - - - static final class Type { - - final String id; - final Set allow = new HashSet<>(); - final Set disallow = new HashSet<>(); - final double speed; - - /** - * Set if id is highway.[type] - */ - final String highway; - - Type(String id, String allow, String disallow, double speed) { - this.id = id; - this.speed = speed; - if (allow != null) - Collections.addAll(this.allow, allow.split(" ")); - - if (disallow != null) - Collections.addAll(this.disallow, disallow.split(" ")); - - if (id.startsWith("highway.")) { - // split compound types - if (id.contains("|")) - id = id.split("\\|")[0]; - - highway = id.substring(8); - } else - highway = null; - - } - } + // aggregate edges split by sumo again + String from = attributes.getValue("from"); + Edge fromEdge = edges.get(from); + Junction j = fromEdge != null ? junctions.get(fromEdge.to) : null; + + Connection conn = new Connection(from, attributes.getValue("to"), + Integer.parseInt(attributes.getValue("fromLane")), + Integer.parseInt(attributes.getValue("toLane")), + attributes.getValue("dir"), j != null ? j.connIdx++ : -1); + + if (j != null) + j.connections.add(conn); + + connections.computeIfAbsent(from, k -> new ArrayList<>()).add(conn); + + break; + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if ("edge".equals(qName) && tmpEdge != null) { + edges.put(tmpEdge.id, tmpEdge); + tmpEdge = null; + } + } + + /** + * Edge from the SUMO network. + */ + static final class Edge { + + final String id; + final String from; + final String to; + final String type; + final int priority; + + @Nullable + final String name; + + final List shape = new ArrayList<>(); + + final List lanes = new ArrayList<>(); + + String origId; + + @Nullable + String origFrom; + + @Nullable + String origTo; + + public Edge(String id, String from, String to, String type, int priority, String name, String[] shape) { + this.id = id; + this.from = from; + this.to = to; + this.type = type; + this.priority = priority; + this.name = name; + + for (String coords : shape) { + String[] split = coords.split(","); + this.shape.add(new double[]{Double.parseDouble(split[0]), Double.parseDouble(split[1])}); + } + } + + /** + * Calculate edge length as max of lanes. + */ + public double getLength() { + return lanes.stream().mapToDouble(l -> l.length).max().orElseThrow(); + } + + @Override + public String toString() { + return "Edge{" + + "id='" + id + '\'' + + ", from='" + from + '\'' + + ", to='" + to + '\'' + + ", origId='" + origId + '\'' + + ", origFrom='" + origFrom + '\'' + + ", origTo='" + origTo + '\'' + + '}'; + } + + + /** + * Project edge geometry to new coordinate system. (in situ) + */ + private void proj(double[] fromOffset, double[] toOffset, CoordinateTransformation ct) { + for (double[] xy : shape) { + + Coord from = new Coord(xy[0] - fromOffset[0], xy[1] - fromOffset[1]); + Coord to = ct.transform(from); + + xy[0] = to.getX() + toOffset[0]; + xy[1] = to.getY() + toOffset[1]; + } + } + } + + static final class Lane { + + final String id; + final int index; + final double length; + final double speed; + + Lane(String id, int index, double length, double speed) { + this.id = id; + this.index = index; + this.length = length; + this.speed = speed; + } + + Lane withLength(double newLength) { + return new Lane(id, index, newLength, speed); + } + } + + record Req(BitSet response, BitSet foes) { + } + + static final class Junction { + + final String id; + final String type; + final List incLanes; + final double[] coord; + + final List requests = new ArrayList<>(); + final List connections = new ArrayList<>(); + + /** + * Mutable connection index. + */ + private int connIdx; + + Junction(String id, String type, List incLanes, double[] coord) { + this.id = id; + this.type = type; + this.incLanes = incLanes; + this.coord = coord; + } + + private void proj(double[] fromOffset, double[] toOffset, CoordinateTransformation ct) { + Coord from = new Coord(coord[0] - fromOffset[0], coord[1] - fromOffset[1]); + Coord to = ct.transform(from); + + coord[0] = to.getX() + toOffset[0]; + coord[1] = to.getY() + toOffset[1]; + } + } + + static final class Connection { + + final String from; + final String to; + final int fromLane; + final int toLane; + + // could be enum probably + final String dir; + + /** + * Request index on junction. + */ + final int reqIdx; + + Connection(String from, String to, int fromLane, int toLane, String dir, int reqIdx) { + this.from = from; + this.to = to; + this.fromLane = fromLane; + this.toLane = toLane; + this.dir = dir; + this.reqIdx = reqIdx; + } + + @Override + public String toString() { + return "Connection{" + + "from='" + from + '\'' + + ", to='" + to + '\'' + + ", fromLane=" + fromLane + + ", toLane=" + toLane + + ", dir='" + dir + '\'' + + '}'; + } + } + + + static final class Type { + + final String id; + final Set allow = new HashSet<>(); + final Set disallow = new HashSet<>(); + final double speed; + + /** + * Set if id is highway.[type] + */ + final String highway; + + Type(String id, String allow, String disallow, double speed) { + this.id = id; + this.speed = speed; + if (allow != null) + Collections.addAll(this.allow, allow.split(" ")); + + if (disallow != null) + Collections.addAll(this.disallow, disallow.split(" ")); + + if (id.startsWith("highway.")) { + // split compound types + if (id.contains("|")) + id = id.split("\\|")[0]; + + highway = id.substring(8); + } else + highway = null; + + } + } } diff --git a/contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkConverterTest.java b/contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkConverterTest.java index 2738f2927b7..d66ce733c45 100644 --- a/contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkConverterTest.java +++ b/contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkConverterTest.java @@ -25,37 +25,41 @@ public class SumoNetworkConverterTest { @Test void convert() throws Exception { - Path input = Files.createTempFile("sumo", ".xml"); - Path output = Files.createTempFile("matsim", ".xml"); + Path input = Files.createTempFile("sumo", ".xml"); + Path output = Files.createTempFile("matsim", ".xml"); - Files.copy(Resources.getResource("osm.net.xml").openStream(), input, StandardCopyOption.REPLACE_EXISTING); + Files.copy(Resources.getResource("osm.net.xml").openStream(), input, StandardCopyOption.REPLACE_EXISTING); - SumoNetworkConverter converter = SumoNetworkConverter.newInstance(List.of(input), output, "EPSG:4326", "EPSG:4326"); + SumoNetworkConverter converter = SumoNetworkConverter.newInstance(List.of(input), output, "EPSG:4326", "EPSG:4326"); - converter.call(); + converter.call(); - Network network = NetworkUtils.readNetwork(output.toString()); + Network network = NetworkUtils.readNetwork(output.toString()); - assert network.getNodes().size() == 21 : "Must contain 21 nodes"; - assert network.getNodes().containsKey(Id.createNodeId("251106770")) : "Must contain specific id"; + assert network.getNodes().size() == 21 : "Must contain 21 nodes"; + assert network.getNodes().containsKey(Id.createNodeId("251106770")) : "Must contain specific id"; - Path lanes = Path.of(output.toString().replace(".xml", "-lanes.xml")); + Path lanes = Path.of(output.toString().replace(".xml", "-lanes.xml")); - Config config = ConfigUtils.createConfig(); - Scenario scenario = ScenarioUtils.createScenario(config); + Config config = ConfigUtils.createConfig(); + Scenario scenario = ScenarioUtils.createScenario(config); - LanesReader reader = new LanesReader(scenario); - reader.readFile(lanes.toString()); + LanesReader reader = new LanesReader(scenario); + reader.readFile(lanes.toString()); - SortedMap, LanesToLinkAssignment> l2l = scenario.getLanes().getLanesToLinkAssignments(); + SortedMap, LanesToLinkAssignment> l2l = scenario.getLanes().getLanesToLinkAssignments(); - System.out.println(l2l); + System.out.println(l2l); - assert l2l.containsKey(Id.createLinkId("-160346478#3")) : "Must contain link id"; + assert l2l.containsKey(Id.createLinkId("-160346478#3")) : "Must contain link id"; - Path geometry = Path.of(output.toString().replace(".xml", "-linkGeometries.csv")); + Path geometry = Path.of(output.toString().replace(".xml", "-linkGeometries.csv")); - assert Files.exists(geometry) : "Geometries must exist"; + assert Files.exists(geometry) : "Geometries must exist"; - } -} \ No newline at end of file + Path fts = Path.of(output.toString().replace(".xml", "-ft.csv")); + + assert Files.exists(fts) : "Features must exists"; + + } +} diff --git a/contribs/taxi/src/test/java/org/matsim/contrib/etaxi/run/RunETaxiScenarioIT.java b/contribs/taxi/src/test/java/org/matsim/contrib/etaxi/run/RunETaxiScenarioIT.java index c086adedc50..5e029c8a29e 100644 --- a/contribs/taxi/src/test/java/org/matsim/contrib/etaxi/run/RunETaxiScenarioIT.java +++ b/contribs/taxi/src/test/java/org/matsim/contrib/etaxi/run/RunETaxiScenarioIT.java @@ -29,7 +29,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; /** * @author michalm @@ -73,8 +73,8 @@ private void runScenario(String configPath) { { String expected = utils.getInputDirectory() + "/output_events.xml.gz"; String actual = utils.getOutputDirectory() + "/output_events.xml.gz"; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles(expected, actual); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles(expected, actual); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } } diff --git a/contribs/taxi/src/test/java/org/matsim/contrib/taxi/optimizer/TaxiOptimizerTests.java b/contribs/taxi/src/test/java/org/matsim/contrib/taxi/optimizer/TaxiOptimizerTests.java index ca985585f82..3a3800467af 100644 --- a/contribs/taxi/src/test/java/org/matsim/contrib/taxi/optimizer/TaxiOptimizerTests.java +++ b/contribs/taxi/src/test/java/org/matsim/contrib/taxi/optimizer/TaxiOptimizerTests.java @@ -35,7 +35,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class TaxiOptimizerTests { public static void runBenchmark(boolean vehicleDiversion, AbstractTaxiOptimizerParams taxiOptimizerParams, MatsimTestUtils utils) { @@ -70,8 +70,8 @@ public static void runBenchmark(boolean vehicleDiversion, AbstractTaxiOptimizerP { String expected = utils.getInputDirectory() + "/output_events.xml.gz"; String actual = utils.getOutputDirectory() + "/output_events.xml.gz"; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles(expected, actual); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles(expected, actual); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } } diff --git a/contribs/vsp/pom.xml b/contribs/vsp/pom.xml index 701d3de1b86..c871cf3ebd9 100644 --- a/contribs/vsp/pom.xml +++ b/contribs/vsp/pom.xml @@ -184,7 +184,7 @@ org.openjfx javafx-graphics - 21.0.2 + 22 com.graphhopper 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)); diff --git a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java index 42c95fb70ad..3037716368c 100644 --- a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java +++ b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java @@ -27,6 +27,9 @@ import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.events.Event; import org.matsim.api.core.v01.events.LinkEnterEvent; +import org.matsim.api.core.v01.events.LinkLeaveEvent; +import org.matsim.api.core.v01.events.VehicleEntersTrafficEvent; +import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.Tour; @@ -55,15 +58,21 @@ public class FreightTimeAndDistanceAnalysisEventsHandler implements BasicEventHa private final Map, Double> vehicleId2TourDuration = new LinkedHashMap<>(); private final Map, Double> vehicleId2TourLength = new LinkedHashMap<>(); + private final Map, Double> vehicleId2TravelTime = new LinkedHashMap<>(); + private final Map, Id> vehicleId2CarrierId = new LinkedHashMap<>(); private final Map, Id> vehicleId2TourId = new LinkedHashMap<>(); - private final Map, Double> vehicleTypeId2SumOfDuration = new LinkedHashMap<>(); + private final Map, Double> vehicleTypeId2SumOfTourDuration = new LinkedHashMap<>(); private final Map, Double> vehicleTypeId2Mileage = new LinkedHashMap<>(); + private final Map, Double> vehicleTypeId2TravelTime = new LinkedHashMap<>(); + private final Map, VehicleType> vehicleId2VehicleType = new TreeMap<>(); private final Map tourStartTime = new LinkedHashMap<>(); + private final Map, Double> vehicleEnteredLinkTime = new LinkedHashMap<>(); + public FreightTimeAndDistanceAnalysisEventsHandler(Scenario scenario) { this.scenario = scenario; @@ -81,7 +90,7 @@ private void handleEvent(CarrierTourEndEvent event) { double tourDuration = event.getTime() - tourStartTime.get(key); vehicleId2TourDuration.put(event.getVehicleId(), tourDuration); VehicleType vehType = VehicleUtils.findVehicle(event.getVehicleId(), scenario).getType(); - vehicleTypeId2SumOfDuration.merge(vehType.getId(), tourDuration, Double::sum); + vehicleTypeId2SumOfTourDuration.merge(vehType.getId(), tourDuration, Double::sum); //Some general information for this vehicle vehicleId2CarrierId.putIfAbsent(event.getVehicleId(), event.getCarrierId()); @@ -93,23 +102,61 @@ private void handleEvent(CarrierTourEndEvent event) { private void handleEvent(LinkEnterEvent event) { final double distance = scenario.getNetwork().getLinks().get(event.getLinkId()).getLength(); vehicleId2TourLength.merge(event.getVehicleId(), distance, Double::sum); + vehicleEnteredLinkTime.put(event.getVehicleId(), event.getTime()); //Safe time when entering the link. final Id vehTypeId = VehicleUtils.findVehicle(event.getVehicleId(), scenario).getType().getId(); vehicleTypeId2Mileage.merge(vehTypeId, distance, Double::sum); } - @Override public void handleEvent(Event event) { + //If the vehicle leaves a link at the end, the travelTime is calculated and stored. + private void handleEvent(LinkLeaveEvent event){ + final Id vehicleId = event.getVehicleId(); + if (vehicleEnteredLinkTime.containsKey(vehicleId)){ + double tt = event.getTime() - vehicleEnteredLinkTime.get(vehicleId); + vehicleId2TravelTime.merge(vehicleId, tt, Double::sum); //per vehicle + + final Id vehTypeId = VehicleUtils.findVehicle(event.getVehicleId(), scenario).getType().getId(); + vehicleTypeId2TravelTime.merge(vehTypeId, tt, Double::sum); // per VehType + + vehicleEnteredLinkTime.remove(vehicleId); //remove from that list. + } + } + + //If the vehicle leaves a link because it reached its destination, the travelTime is calculated and stored. + private void handleEvent(VehicleLeavesTrafficEvent event){ + final Id vehicleId = event.getVehicleId(); + if (vehicleEnteredLinkTime.containsKey(vehicleId)){ + double tt = event.getTime() - vehicleEnteredLinkTime.get(vehicleId); + vehicleId2TravelTime.merge(vehicleId, tt, Double::sum);//per vehicle + + final Id vehTypeId = VehicleUtils.findVehicle(event.getVehicleId(), scenario).getType().getId(); + vehicleTypeId2TravelTime.merge(vehTypeId, tt, Double::sum); // per VehType + + vehicleEnteredLinkTime.remove(vehicleId); //remove from that list. + } + } + + private void handleEvent(VehicleEntersTrafficEvent event){ + vehicleEnteredLinkTime.put(event.getVehicleId(), event.getTime()); + } + @Override public void handleEvent(Event event) { if (event instanceof CarrierTourStartEvent carrierTourStartEvent) { handleEvent(carrierTourStartEvent); } else if (event instanceof CarrierTourEndEvent carrierTourEndEvent) { handleEvent(carrierTourEndEvent); } else if (event instanceof LinkEnterEvent linkEnterEvent) { handleEvent(linkEnterEvent); + } else if (event instanceof LinkLeaveEvent linkLeaveEvent) { + handleEvent(linkLeaveEvent); + } else if (event instanceof VehicleLeavesTrafficEvent vehicleLeavesTrafficEvent) { + handleEvent(vehicleLeavesTrafficEvent); + } else if (event instanceof VehicleEntersTrafficEvent vehicleEntersTrafficEvent) { + handleEvent(vehicleEntersTrafficEvent); } } - void writeTravelTimeAndDistance(String analysisOutputDirectory, Scenario scenario) throws IOException { + void writeTravelTimeAndDistancePerVehicle(String analysisOutputDirectory, Scenario scenario) throws IOException { log.info("Writing out Time & Distance & Costs ... perVehicle"); //Travel time and distance per vehicle String fileName = analysisOutputDirectory + "TimeDistance_perVehicle.tsv"; @@ -117,14 +164,19 @@ void writeTravelTimeAndDistance(String analysisOutputDirectory, Scenario scenari BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileName)); //Write headline: - bw1.write("vehicleId \t carrierId \t vehicleTypeId \t tourId \t tourDuration[s] \t travelDistance[m] \t " + - "costPerSecond[EUR/s] \t costPerMeter[EUR/m] \t fixedCosts[EUR] \t varCostsTime[EUR] \t varCostsDist[EUR] \t totalCosts[EUR]"); + bw1.write("vehicleId \t carrierId \t vehicleTypeId \t tourId \t " + + "tourDuration[s] \t tourDuration[h] \t" + + "travelDistance[m] \t travelDistance[km] \t " + + "travelTime[s] \t travelTime[h] \t" + + "costPerSecond[EUR/s] \t costPerMeter[EUR/m] \t fixedCosts[EUR] \t varCostsTime[EUR] \t varCostsDist[EUR] \t totalCosts[EUR]"); bw1.newLine(); for (Id vehicleId : vehicleId2VehicleType.keySet()) { final Double durationInSeconds = vehicleId2TourDuration.get(vehicleId); final Double distanceInMeters = vehicleId2TourLength.get(vehicleId); + final Double travelTimeInSeconds = vehicleId2TravelTime.get(vehicleId); + final VehicleType vehicleType = VehicleUtils.findVehicle(vehicleId, scenario).getType(); final Double costsPerSecond = vehicleType.getCostInformation().getCostsPerSecond(); @@ -141,7 +193,14 @@ void writeTravelTimeAndDistance(String analysisOutputDirectory, Scenario scenari bw1.write("\t" + vehicleId2TourId.get(vehicleId)); bw1.write("\t" + durationInSeconds); + bw1.write("\t" + durationInSeconds /3600); + bw1.write("\t" + distanceInMeters); + bw1.write("\t" + distanceInMeters/1000); + + bw1.write("\t" + travelTimeInSeconds); + bw1.write("\t" + travelTimeInSeconds /3600); + bw1.write("\t" + costsPerSecond); bw1.write("\t" + costsPerMeter); bw1.write("\t" + fixedCost); @@ -161,7 +220,6 @@ void writeTravelTimeAndDistancePerVehicleType(String analysisOutputDirectory, Sc log.info("Writing out Time & Distance & Costs ... perVehicleType"); //----- All VehicleTypes in CarriervehicleTypes container. Used so that even unused vehTypes appear in the output - TreeMap, VehicleType> vehicleTypesMap = new TreeMap<>(CarriersUtils.getCarrierVehicleTypes(scenario).getVehicleTypes()); //For the case that there are additional vehicle types found in the events. for (VehicleType vehicleType : vehicleId2VehicleType.values()) { @@ -171,34 +229,39 @@ void writeTravelTimeAndDistancePerVehicleType(String analysisOutputDirectory, Sc String fileName = analysisOutputDirectory + "TimeDistance_perVehicleType.tsv"; BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileName)); - //Write headline: - bw1.write("vehicleTypeId \t nuOfVehicles \t SumOfTourDuration[s] \t SumOfTravelDistances[m] \t " + + bw1.write("vehicleTypeId \t nuOfVehicles \t " + + "SumOfTourDuration[s] \t SumOfTourDuration[h] \t" + + "SumOfTravelDistances[m] \t SumOfTravelDistances[km] \t " + + "SumOfTravelTime[s] \t SumOfTravelTime[h] \t" + "costPerSecond[EUR/s] \t costPerMeter[EUR/m] \t fixedCosts[EUR/veh] \t" + "varCostsTime[EUR] \t varCostsDist[EUR] \t fixedCosts[EUR] \t totalCosts[EUR]"); bw1.newLine(); - for (VehicleType vehicleType : vehicleTypesMap.values()) { - long nuOfVehicles = vehicleId2VehicleType.values().stream().filter(vehType -> vehType.getId() == vehicleType.getId()).count(); final Double costRatePerSecond = vehicleType.getCostInformation().getCostsPerSecond(); final Double costRatePerMeter = vehicleType.getCostInformation().getCostsPerMeter(); final Double fixedCostPerVeh = vehicleType.getCostInformation().getFixedCosts(); - final Double sumOfDurationInSeconds = vehicleTypeId2SumOfDuration.getOrDefault(vehicleType.getId(), 0.); + final Double sumOfTourDurationInSeconds = vehicleTypeId2SumOfTourDuration.getOrDefault(vehicleType.getId(), 0.); final Double sumOfDistanceInMeters = vehicleTypeId2Mileage.getOrDefault(vehicleType.getId(), 0.); + final Double sumOfTravelTimeInSeconds = vehicleTypeId2TravelTime.getOrDefault(vehicleType.getId(), 0.); - final double sumOfVarCostsTime = sumOfDurationInSeconds * costRatePerSecond; + final double sumOfVarCostsTime = sumOfTourDurationInSeconds * costRatePerSecond; final double sumOfVarCostsDistance = sumOfDistanceInMeters * costRatePerMeter; final double sumOfFixCosts = nuOfVehicles * fixedCostPerVeh; bw1.write(vehicleType.getId().toString()); bw1.write("\t" + nuOfVehicles); - bw1.write("\t" + sumOfDurationInSeconds); + bw1.write("\t" + sumOfTourDurationInSeconds); + bw1.write("\t" + sumOfTourDurationInSeconds / 3600); bw1.write("\t" + sumOfDistanceInMeters); + bw1.write("\t" + sumOfDistanceInMeters / 1000); + bw1.write("\t" + sumOfTravelTimeInSeconds); + bw1.write("\t" + sumOfTravelTimeInSeconds / 3600); bw1.write("\t" + costRatePerSecond); bw1.write("\t" + costRatePerMeter); bw1.write("\t" + fixedCostPerVeh); diff --git a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java index 86249801bd0..44374d18dd7 100644 --- a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java +++ b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java @@ -120,7 +120,7 @@ public void runAnalysis() throws IOException { log.info("Analysis completed."); log.info("Writing output..."); - freightTimeAndDistanceAnalysisEventsHandler.writeTravelTimeAndDistance(analysisOutputDirectory, scenario); + freightTimeAndDistanceAnalysisEventsHandler.writeTravelTimeAndDistancePerVehicle(analysisOutputDirectory, scenario); freightTimeAndDistanceAnalysisEventsHandler.writeTravelTimeAndDistancePerVehicleType(analysisOutputDirectory, scenario); carrierLoadAnalysis.writeLoadPerVehicle(analysisOutputDirectory, scenario); } diff --git a/contribs/vsp/src/main/java/playground/vsp/analysis/modules/act2mode/ActivityToModeAnalysis.java b/contribs/vsp/src/main/java/playground/vsp/analysis/modules/act2mode/ActivityToModeAnalysis.java index 3c0e2d1c2d6..12055885daa 100644 --- a/contribs/vsp/src/main/java/playground/vsp/analysis/modules/act2mode/ActivityToModeAnalysis.java +++ b/contribs/vsp/src/main/java/playground/vsp/analysis/modules/act2mode/ActivityToModeAnalysis.java @@ -35,14 +35,14 @@ import org.matsim.core.events.handler.EventHandler; import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.gis.PointFeatureFactory; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.opengis.feature.simple.SimpleFeature; import playground.vsp.analysis.modules.AbstractAnalysisModule; /** * @author droeder - * + * * writeResultsPlanCoords() added by gleich * */ @@ -65,7 +65,7 @@ public class ActivityToModeAnalysis extends AbstractAnalysisModule { * @param sc, the scenario (it has to contain facilities!!!) * @param personsOfInterest, might be null, than all persons are processed * @param slotSize, timeSlotSize in seconds - * + * * output using Activity Coordinates from the plans instead of departure * and arrival links with writeResultsPlanCoords() */ @@ -100,24 +100,24 @@ public void postProcessData() { addAttribute("ActType", String.class). addAttribute("Mode", String.class). create(); - + //create features for departure this.departureSlotFeatures = new HashMap>(); for(ActivityToMode atm : this.handler.getDepartures()){ createFeatureAndAdd(atm, this.departureSlotFeatures, factory); } - + this.departureSlotFeaturesPlanCoord = new HashMap>(); for(ActivityToMode atm : this.handlerPlanCoord.getDepartures()){ createFeatureAndAdd(atm, this.departureSlotFeaturesPlanCoord, factory); } - + //create features for arrivals this.arrivalSlotFeatures = new HashMap>(); for(ActivityToMode atm : this.handler.getArrivals()){ createFeatureAndAdd(atm, this.arrivalSlotFeatures, factory); } - + this.arrivalSlotFeaturesPlanCoord = new HashMap>(); for(ActivityToMode atm : this.handlerPlanCoord.getArrivals()){ createFeatureAndAdd(atm, this.arrivalSlotFeaturesPlanCoord, factory); @@ -128,9 +128,9 @@ public void postProcessData() { /** * @param atm * @param departureSlotFeatures2 - * @param featureType + * @param featureType */ - private void createFeatureAndAdd(ActivityToMode atm, + private void createFeatureAndAdd(ActivityToMode atm, HashMap> slotFeatures, PointFeatureFactory factory) { Integer slice = (int) (atm.getTime() / this.slotSize); Set temp = slotFeatures.get(slice); @@ -149,22 +149,22 @@ private void createFeatureAndAdd(ActivityToMode atm, @Override public void writeResults(String outputFolder) { for(Entry> e: this.departureSlotFeatures.entrySet()){ - ShapeFileWriter.writeGeometries(e.getValue(), outputFolder + "departure_" + e.getKey().toString() + ".shp"); + GeoFileWriter.writeGeometries(e.getValue(), outputFolder + "departure_" + e.getKey().toString() + ".shp"); } for(Entry> e: this.departureSlotFeaturesPlanCoord.entrySet()){ - ShapeFileWriter.writeGeometries(e.getValue(), outputFolder + "departure_" + e.getKey().toString() + ".shp"); + GeoFileWriter.writeGeometries(e.getValue(), outputFolder + "departure_" + e.getKey().toString() + ".shp"); } for(Entry> e: this.arrivalSlotFeatures.entrySet()){ - ShapeFileWriter.writeGeometries(e.getValue(), outputFolder + "arrival_" + e.getKey().toString() + ".shp"); + GeoFileWriter.writeGeometries(e.getValue(), outputFolder + "arrival_" + e.getKey().toString() + ".shp"); } } - + public void writeResultsPlanCoords(String outputFolder) { for(Entry> e: this.departureSlotFeaturesPlanCoord.entrySet()){ - ShapeFileWriter.writeGeometries(e.getValue(), outputFolder + "departure_" + e.getKey().toString() + ".shp"); + GeoFileWriter.writeGeometries(e.getValue(), outputFolder + "departure_" + e.getKey().toString() + ".shp"); } for(Entry> e: this.arrivalSlotFeaturesPlanCoord.entrySet()){ - ShapeFileWriter.writeGeometries(e.getValue(), outputFolder + "arrival_" + e.getKey().toString() + ".shp"); + GeoFileWriter.writeGeometries(e.getValue(), outputFolder + "arrival_" + e.getKey().toString() + ".shp"); } } } diff --git a/contribs/vsp/src/main/java/playground/vsp/analysis/modules/networkAnalysis/NetworkAnalyzer.java b/contribs/vsp/src/main/java/playground/vsp/analysis/modules/networkAnalysis/NetworkAnalyzer.java index 7f036c0b858..4e41f3ae95f 100644 --- a/contribs/vsp/src/main/java/playground/vsp/analysis/modules/networkAnalysis/NetworkAnalyzer.java +++ b/contribs/vsp/src/main/java/playground/vsp/analysis/modules/networkAnalysis/NetworkAnalyzer.java @@ -43,7 +43,7 @@ import org.matsim.core.scenario.MutableScenario; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.opengis.feature.simple.SimpleFeature; import playground.vsp.analysis.modules.AbstractAnalysisModule; @@ -58,66 +58,66 @@ * (ii) types (redundant, dead end, exit road) * (2) link statistics * (3) accessibility computation (depending on walk travel time to the network) - * + * * @author dhosse - * + * */ public class NetworkAnalyzer extends AbstractAnalysisModule{ private Logger log = LogManager.getLogger(NetworkAnalyzer.class); - + private Scenario scenario; private Network network; - + private Map> nodeTypes; private Map geometricLengths; - + private List nodesWithHighDegrees; private List lengthBelowStorageCapacity; private Map smallClusterLinks; - + private Map> filesForExportInQGisProject; - + private double totalLength = 0; private double totalGLength = 0; - + private SimpleFeatureBuilder builder; - + private Geometry envelope; - + private final String deadEnd = "deadEnd"; private final String exit = "exit"; private final String redundant = "redundant"; - + private final String TXTfile = ".txt"; private final String QGSfile = ".qgs"; private final String SHPfile = ".shp"; - + private String targetCoordinateSystem; - + private boolean nodesChecked = false; private boolean linksChecked = false; - + private SpatialGrid freeSpeedGrid = null; - + /** * Creates a new analyzer for properties of a given network file. - * + * * @param networkInputFile The MATSim-Network file to analyse. * @param targetCoordinateSystem The coordinate system your network data is transformed to. */ public NetworkAnalyzer(String networkInputFile, String targetCoordinateSystem) { - + super(NetworkAnalyzer.class.getSimpleName()); this.scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); this.targetCoordinateSystem = targetCoordinateSystem; - + if(networkInputFile!=null){ new MatsimNetworkReader(this.scenario.getNetwork()).readFile(networkInputFile); this.network = this.scenario.getNetwork(); } - + } @Override @@ -132,29 +132,29 @@ public void preProcessData() { @Override public void postProcessData() { - + this.nodeTypes = new TreeMap>(); this.geometricLengths = new HashMap(); this.nodesWithHighDegrees = new ArrayList(); this.filesForExportInQGisProject = new HashMap>(); this.lengthBelowStorageCapacity = new ArrayList(); this.smallClusterLinks = new TreeMap(); - + this.envelope = new BoundingPolygon(network, 200).returnPolygon(); this.filesForExportInQGisProject.put("envelope", Polygon.class); - + if(isRoutable()){ continueWithRoutableNetwork(); - + log.info("total length of all network links: " + this.totalLength + " m"); log.info("total geometric length of all network links: " + this.totalGLength+ " m"); } - + } @Override public void writeResults(String outputFolder) { - + try { exportEnvelopeToShape(outputFolder); writeNodesFiles(outputFolder); @@ -164,28 +164,28 @@ public void writeResults(String outputFolder) { } catch (IOException e) { e.printStackTrace(); } - + } - + private void exportEnvelopeToShape(String outputFolder) { SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder(); typeBuilder.setName("shape"); typeBuilder.add("envelope",Polygon.class); typeBuilder.add("area",Double.class); - + this.builder = new SimpleFeatureBuilder(typeBuilder.buildFeatureType()); - + ArrayList features = new ArrayList(); - + SimpleFeature feature = this.builder.buildFeature(null, new Object[]{ this.envelope, this.envelope.getArea() }); - + features.add(feature); - ShapeFileWriter.writeGeometries(features, outputFolder+"envelope"+this.SHPfile); + GeoFileWriter.writeGeometries(features, outputFolder+"envelope"+this.SHPfile); } @@ -194,18 +194,18 @@ private void exportEnvelopeToShape(String outputFolder) { * @return True if the given network contains of only one cluster and false, if there is more than one. */ private boolean isRoutable(){ - + //the nodes that have already been inspected final Map visitedNodes = new TreeMap(); //a map to store the biggest cluster of the network Map biggestCluster = new TreeMap(); - + boolean stillSearching = true; Iterator iter = this.network.getNodes().values().iterator(); - + log.info(" checking " + this.network.getNodes().size() + " nodes and " + this.network.getLinks().size() + " links for dead-ends..."); - + //run as long as there are still unvisited nodes while (iter.hasNext() && stillSearching) { Node startNode = iter.next(); @@ -225,9 +225,9 @@ private boolean isRoutable(){ } } } - + for(Id nodeId : this.network.getNodes().keySet()){ - + if(!biggestCluster.containsKey(nodeId)){ Node node = this.network.getNodes().get(nodeId); for(Link l : node.getOutLinks().values()){ @@ -236,69 +236,69 @@ private boolean isRoutable(){ } } } - + } - + return false; - + } - + /** * If the network is routable, the analysis methods are running over the network. */ private void continueWithRoutableNetwork() { - + checkNodeAttributes(); checkLinkAttributes(); - + //create a bounding box for accessibility computation BoundingBox bbox = BoundingBox.createBoundingBox(this.scenario.getNetwork()); - + double resolution = 100; - + //set measuring points from which the accessibility is measured ZoneLayer> measuringPoints = NetworkAnalyzer.createGridLayerByGridSizeByNetwork(resolution, bbox.getBoundingBox()); //initialize grid that stores the accessibility values this.freeSpeedGrid = new SpatialGrid(bbox.getXMin(),bbox.getYMin(),bbox.getXMax(),bbox.getYMax(), resolution, Double.NaN); MutableScenario sc = (MutableScenario) this.scenario; - + //run accessibility computation new AccessibilityCalc(measuringPoints, freeSpeedGrid, sc,envelope).runAccessibilityComputation(); - + } - + /** * Parses all network nodes and classifies them into either exit road, dead end or redundant nodes. * Currently only for nodes with degree = 1. */ private void checkNodeAttributes() { - + log.info("analysing network nodes..."); - + int exit=0,red=0,de=0; - + this.nodeTypes.put(this.exit, new ArrayList()); this.nodeTypes.put(this.deadEnd, new ArrayList()); this.nodeTypes.put(this.redundant, new ArrayList()); - + //iterate over all network nodes for(Node node : this.network.getNodes().values()){ //if the node has any ingoing and outgoing links (at least one of a kind) investigate the node if(node.getInLinks().size()>0&&node.getOutLinks().size()>0){ - + //catches nodes with high degrees (here: more than five in- or outgoing links) if(node.getInLinks().size()>5||node.getOutLinks().size()>5) this.nodesWithHighDegrees.add(node.getId()); - + //if the node's degree equals 1, then classify it if(node.getInLinks().size()==1&&node.getOutLinks().size()==1){ //get the in- and the outgoing link of the node Link inLink = node.getInLinks().values().iterator().next(); Link outLink = node.getOutLinks().values().iterator().next(); - + //if the only possible moving direction from this node is backwards //(to the node you came from) and it lies outside the bounding polygon //then it's a node of an exit road @@ -312,7 +312,7 @@ private void checkNodeAttributes() { //if it's inside the polygon, it's a node of a dead end road this.nodeTypes.get(this.deadEnd).add(node.getId()); de++; - + } else{ //if all attributes of the ingoing link are equal to the //attributes of the outgoing link, then the node is redundant @@ -327,37 +327,37 @@ private void checkNodeAttributes() { } } } - + log.info("found " + exit + " exit road nodes, " + de + " dead end nodes and " + red + " redundant nodes..."); log.info("...done"); - + this.nodesChecked = true; - + } - + /** *Parses all network links to compute their geometric length (fromNode to toNode) and check if their storage capacity is sufficient for - *storing at least one vehicle (link length >= effektiveCellSize). + *storing at least one vehicle (link length >= effektiveCellSize). */ private void checkLinkAttributes() { - + log.info("analyzing network links..."); - + //the space needed to store a vehicle (+ additional space for the gaps to the vehicle ahead and the one following double cellWidth = ((Network)this.network).getEffectiveCellSize(); int writerIndex = 0; - + //iterate over all links for(Link link : this.network.getLinks().values()){ //compute geometric length (distance between from and to node) - double geometricLength = + double geometricLength = Math.sqrt(Math.pow(link.getToNode().getCoord().getX() - link.getFromNode().getCoord().getX(),2) + Math.pow(link.getToNode().getCoord().getY() - link.getFromNode().getCoord().getY(), 2)); - + this.geometricLengths.put(link.getId(), geometricLength); - + this.totalLength += link.getLength(); this.totalGLength += geometricLength; //if the length of the link is less than the effectiveCellSize then store the link and write a warning about that later @@ -370,7 +370,7 @@ private void checkLinkAttributes() { log.info("...done"); this.linksChecked = true; } - + private Map findCluster(final Node startNode, final Network network) { final Map nodeRoles = new HashMap(network.getNodes().size()); @@ -418,7 +418,7 @@ private Map findCluster(final Node startNode, final Network network) { return clusterNodes; } - + private static DoubleFlagRole getDoubleFlag(final Node n, final Map nodeRoles) { DoubleFlagRole r = nodeRoles.get(n); if (null == r) { @@ -427,56 +427,56 @@ private static DoubleFlagRole getDoubleFlag(final Node n, final Map> createGridLayerByGridSizeByNetwork(double gridSize, double [] boundingBox) { - + // log.info("Setting starting points for accessibility measure ..."); int skippedPoints = 0; int setPoints = 0; - + GeometryFactory factory = new GeometryFactory(); - + Set>> zones = new HashSet<>(); double xmin = boundingBox[0]; double ymin = boundingBox[1]; double xmax = boundingBox[2]; double ymax = boundingBox[3]; - - + + ProgressBar bar = new ProgressBar( (xmax-xmin)/gridSize ); - + // goes step by step from the min x and y coordinate to max x and y coordinate for(double x = xmin; x = xmin && + if (center_X <= xmax && center_X >= xmin && center_Y <= ymax && center_Y >= ymin) { - + Point point = factory.createPoint(new Coordinate(x, y)); - + Coordinate[] coords = new Coordinate[5]; coords[0] = point.getCoordinate(); coords[1] = new Coordinate(x, y + gridSize); @@ -487,11 +487,11 @@ public static ZoneLayer> createGridLayerByGridSizeByNetwork(double grid LinearRing linearRing = factory.createLinearRing(coords); Polygon polygon = factory.createPolygon(linearRing, null); // polygon.setSRID( srid ); // tnicolai: this is not needed to match the grid layer with locations / facilities from UrbanSim - + Zone> zone = new Zone>(polygon); zone.setAttribute( Id.create( setPoints, Zone.class ) ); zones.add(zone); - + setPoints++; } else skippedPoints++; @@ -500,24 +500,24 @@ public static ZoneLayer> createGridLayerByGridSizeByNetwork(double grid // log.info("Having " + setPoints + " inside the shape file boundary (and " + skippedPoints + " outside)."); // log.info("Done with setting starting points!"); - + ZoneLayer> layer = new ZoneLayer<>(zones); return layer; } - + /** * Calls the writing methods for node statistics after the analysis and classification - * - * @param outputFolder + * + * @param outputFolder * @throws IOException */ private void writeNodesFiles(String outputFolder) throws IOException { - + if(this.nodesChecked){ writeNodeStatisticsFile(outputFolder); exportNodesToShape(outputFolder); } - + } /** @@ -528,25 +528,25 @@ private void writeNodesFiles(String outputFolder) throws IOException { private void writeNodeStatisticsFile(String outputFolder) throws IOException { File file = new File(outputFolder+"nodeStatistics"+this.TXTfile); FileWriter writer = new FileWriter(file);; - + writer.write("ID\tinDegree\toutDegree"); - + for(Node n : this.network.getNodes().values()){ - + writer.write("\n"+n.getId()+"\t"+n.getInLinks().size()+"\t"+n.getOutLinks().size()); - + } writer.flush(); writer.close(); } - + /** * Writes the classified nodes to a shape file for visualisation in QGis. - * + * * @param outputFolder */ private void exportNodesToShape(String outputFolder){ - + SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder(); typeBuilder.setName("node"); typeBuilder.add("location",Point.class); @@ -554,32 +554,32 @@ private void exportNodesToShape(String outputFolder){ typeBuilder.add("type",String.class); typeBuilder.setCRS(MGC.getCRS(this.targetCoordinateSystem)); this.builder = new SimpleFeatureBuilder(typeBuilder.buildFeatureType()); - + Collection features = new ArrayList(); - + for(String nodeType : this.nodeTypes.keySet()){ for(Id nodeId : this.nodeTypes.get(nodeType)){ Point p = MGC.coord2Point(this.network.getNodes().get(nodeId).getCoord()); features.add(this.builder.buildFeature(null, new Object[]{p,nodeId.toString(),nodeType})); - + } - + } - + String destination = ""; - + if(features.size() > 0){ destination = "nodeTypes"; - + this.filesForExportInQGisProject.put(destination,Point.class); - - ShapeFileWriter.writeGeometries(features, outputFolder+destination+this.SHPfile); + + GeoFileWriter.writeGeometries(features, outputFolder+destination+this.SHPfile); } - + if(!(this.nodesWithHighDegrees.size() < 1)){ features.clear(); - + typeBuilder.setName("node"); typeBuilder.add("location",Point.class); typeBuilder.add("ID",String.class); @@ -587,42 +587,42 @@ private void exportNodesToShape(String outputFolder){ typeBuilder.add("out-degree",Integer.class); typeBuilder.setCRS(MGC.getCRS(this.targetCoordinateSystem)); this.builder = new SimpleFeatureBuilder(typeBuilder.buildFeatureType()); - + for(Id nodeId : this.nodesWithHighDegrees){ - + Point p = MGC.coord2Point(this.network.getNodes().get(nodeId).getCoord()); features.add(this.builder.buildFeature(null, new Object[]{p,nodeId.toString(), this.network.getNodes().get(nodeId).getInLinks().size(), this.network.getNodes().get(nodeId).getOutLinks().size()})); } - + destination = "highDegreeNodes"; - + this.filesForExportInQGisProject.put(destination, Point.class); - ShapeFileWriter.writeGeometries(features, outputFolder+destination+this.SHPfile); + GeoFileWriter.writeGeometries(features, outputFolder+destination+this.SHPfile); } - + } /** * Calls the writing methods for link statistics after analysis. - * + * * @param outputFolder * @throws IOException */ private void writeLinkFiles(String outputFolder) throws IOException { - + if(this.linksChecked){ writeLinkStatisticsFile(outputFolder); writeStorageCapacityWarningFile(outputFolder); } writeClustersAndNetwork2ESRIShape(outputFolder); - + } /** - * Writes a logfile with all warnings about links with insufficient storage capacity (link length < effectiveCellSize). - * + * Writes a logfile with all warnings about links with insufficient storage capacity (link length < effectiveCellSize). + * * @param outputFolder * @throws IOException */ @@ -631,7 +631,7 @@ private void writeStorageCapacityWarningFile(String outputFolder) throws IOExcep FileWriter writer; double cellWidth = ((Network)this.network).getEffectiveCellSize(); - + writer = new FileWriter(file); for(Link link : this.lengthBelowStorageCapacity){ writer.write("length of link " + link.getId() + " below min length for storage capacity of one vehicle (" + @@ -640,42 +640,42 @@ private void writeStorageCapacityWarningFile(String outputFolder) throws IOExcep writer.flush(); writer.close(); } - + /** * Writes the link statistics (length, geometric length, number of lanes, capacity) to a plain text file. - * + * * @param outputFolder * @throws IOException */ private void writeLinkStatisticsFile(String outputFolder) throws IOException{ - + File file = new File(outputFolder+"linkStatistics"+this.TXTfile); - - + + FileWriter writer = new FileWriter(file); - + writer.write("ID \t length \t geometricLength \t nlanes \t capacity"); - + for(Link l : this.network.getLinks().values()){ - + writer.write("\n"+ l.getId() + "\t"+l.getLength() + "\t" + this.geometricLengths.get(l.getId()) + "\t" + l.getNumberOfLanes() + "\t" + l.getCapacity()); - + } writer.flush(); writer.close(); - + } - + /** * Exports the network links and (if existing) the links contained in small clusters to an ESRI shapefile. * @param outputFolder */ private void writeClustersAndNetwork2ESRIShape(String outputFolder) { - + SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder(); typeBuilder.setName("shape"); typeBuilder.add("link",LineString.class); @@ -686,11 +686,11 @@ private void writeClustersAndNetwork2ESRIShape(String outputFolder) { typeBuilder.add("nlanes", String.class); typeBuilder.setCRS(MGC.getCRS(this.targetCoordinateSystem)); this.builder = new SimpleFeatureBuilder(typeBuilder.buildFeatureType()); - + ArrayList features = new ArrayList(); - + for(Link link : this.network.getLinks().values()){ - + SimpleFeature feature = this.builder.buildFeature(null, new Object[]{ new GeometryFactory().createLineString(new Coordinate[]{ new Coordinate(link.getFromNode().getCoord().getX(),link.getFromNode().getCoord().getY()), @@ -701,25 +701,25 @@ private void writeClustersAndNetwork2ESRIShape(String outputFolder) { link.getFreespeed(), link.getCapacity(), link.getNumberOfLanes() - + }); - + features.add(feature); - + } - + String destination = "network"; - + this.filesForExportInQGisProject.put(destination,LineString.class); - - ShapeFileWriter.writeGeometries(features, outputFolder+destination+this.SHPfile); - + + GeoFileWriter.writeGeometries(features, outputFolder+destination+this.SHPfile); + if(this.smallClusterLinks.size()>0){ - + features.clear(); - + for(Link link : this.smallClusterLinks.values()){ - + SimpleFeature feature = this.builder.buildFeature(null, new Object[]{ new GeometryFactory().createLineString(new Coordinate[]{ new Coordinate(link.getFromNode().getCoord().getX(),link.getFromNode().getCoord().getY()), @@ -731,31 +731,31 @@ private void writeClustersAndNetwork2ESRIShape(String outputFolder) { link.getCapacity(), link.getNumberOfLanes() }); - + features.add(feature); - + } - + destination = "smallClusters"; - + this.filesForExportInQGisProject.put(destination,LineString.class); - - ShapeFileWriter.writeGeometries(features, outputFolder+destination+this.SHPfile); - + + GeoFileWriter.writeGeometries(features, outputFolder+destination+this.SHPfile); + } } - + private void writeAccessibilityMap(String outputFolder){ - + try{ BufferedWriter writer = new BufferedWriter(new FileWriter(outputFolder+"/freeSpeedAccessibility.txt")); - + for(double x = this.freeSpeedGrid.getXmin(); x <= this.freeSpeedGrid.getXmax(); x += this.freeSpeedGrid.getResolution()) { writer.write(SpatialGridTableWriter.separator); writer.write(String.valueOf(x)); } writer.newLine(); - + for(double y = this.freeSpeedGrid.getYmin(); y <= this.freeSpeedGrid.getYmax() ; y += this.freeSpeedGrid.getResolution()) { writer.write(String.valueOf(y)); for(double x = this.freeSpeedGrid.getXmin(); x <= this.freeSpeedGrid.getXmax(); x += this.freeSpeedGrid.getResolution()) { @@ -774,7 +774,7 @@ private void writeAccessibilityMap(String outputFolder){ catch(IOException e){ e.printStackTrace(); } - + } - + } diff --git a/contribs/vsp/src/main/java/playground/vsp/analysis/modules/ptAccessibility/utils/PtAccesShapeWriter.java b/contribs/vsp/src/main/java/playground/vsp/analysis/modules/ptAccessibility/utils/PtAccesShapeWriter.java index e4c6db96362..f21e092ba84 100644 --- a/contribs/vsp/src/main/java/playground/vsp/analysis/modules/ptAccessibility/utils/PtAccesShapeWriter.java +++ b/contribs/vsp/src/main/java/playground/vsp/analysis/modules/ptAccessibility/utils/PtAccesShapeWriter.java @@ -34,7 +34,7 @@ import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.gis.PointFeatureFactory; import org.matsim.core.utils.gis.PolygonFeatureFactory; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.opengis.feature.simple.SimpleFeature; import playground.vsp.analysis.modules.ptAccessibility.activity.ActivityLocation; @@ -44,7 +44,7 @@ /** * @author droeder, aneumann * - * just a helper-class + * just a helper-class */ public class PtAccesShapeWriter { @@ -60,16 +60,16 @@ public static void writeMultiPolygons(Map mps, String file addAttribute("name", String.class). create(); Collection features = new ArrayList(); - + Object[] featureAttribs; for(Entry e: mps.entrySet()){ featureAttribs = new Object[1]; featureAttribs[0] = e.getKey(); features.add(factory.createPolygon(e.getValue(), featureAttribs, null)); } - ShapeFileWriter.writeGeometries(features, filename); + GeoFileWriter.writeGeometries(features, filename); } - + public static void writeActivityLocations(LocationMap locationMap, String outputFolder, String name, String targetCoordinateSystem, double gridSize){ PointFeatureFactory featureFactory = new PointFeatureFactory.Builder(). setCrs(MGC.getCRS(targetCoordinateSystem)). @@ -77,13 +77,13 @@ public static void writeActivityLocations(LocationMap locationMap, String output addAttribute("name", String.class). addAttribute("type", String.class). create(); - + PointFeatureFactory clusterFeatureFactory = new PointFeatureFactory.Builder(). setCrs(MGC.getCRS(targetCoordinateSystem)). setName(name). addAttribute("count", Integer.class). create(); - + for(Entry> type2LocationEntry: locationMap.getType2Locations().entrySet()){ if (!type2LocationEntry.getValue().isEmpty()) { try { @@ -94,44 +94,44 @@ public static void writeActivityLocations(LocationMap locationMap, String output type2LocationEntry.getKey() }, null)); } - - ShapeFileWriter.writeGeometries(features, outputFolder + "activityLocations_" + type2LocationEntry.getKey() + ".shp"); + + GeoFileWriter.writeGeometries(features, outputFolder + "activityLocations_" + type2LocationEntry.getKey() + ".shp"); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch(ServiceConfigurationError e){ e.printStackTrace(); } - + // cluster first write then - + try { Collection features = new ArrayList(); - + HashMap gridNodeId2GridNode = new HashMap(); - + // go through all acts of this type for(int i = 0; i < type2LocationEntry.getValue().size(); i++){ Coord coord = new Coord(type2LocationEntry.getValue().get(i).getCoord().x, type2LocationEntry.getValue().get(i).getCoord().y); String gridNodeId = GridNode.getGridNodeIdForCoord(coord, gridSize); - + if (gridNodeId2GridNode.get(gridNodeId) == null) { gridNodeId2GridNode.put(gridNodeId, new GridNode(gridNodeId)); } - + gridNodeId2GridNode.get(gridNodeId).addPoint(type2LocationEntry.getKey(), coord); } - + for (GridNode gridNode : gridNodeId2GridNode.values()) { features.add(clusterFeatureFactory.createPoint(new Coordinate(gridNode.getX(), gridNode.getY()), new Object[] {gridNode.getCountForType(type2LocationEntry.getKey())}, null)); } - - ShapeFileWriter.writeGeometries(features, outputFolder + "activityLocations_clustered_" + type2LocationEntry.getKey() + ".shp"); + + GeoFileWriter.writeGeometries(features, outputFolder + "activityLocations_clustered_" + type2LocationEntry.getKey() + ".shp"); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch(ServiceConfigurationError e){ e.printStackTrace(); } - + } else { log.info("No activities found for cluster " + type2LocationEntry.getKey()); } diff --git a/contribs/vsp/src/main/java/playground/vsp/analysis/modules/ptAccessibility/utils/PtAccessMapShapeWriter.java b/contribs/vsp/src/main/java/playground/vsp/analysis/modules/ptAccessibility/utils/PtAccessMapShapeWriter.java index 6605af703cc..615512e0fe6 100644 --- a/contribs/vsp/src/main/java/playground/vsp/analysis/modules/ptAccessibility/utils/PtAccessMapShapeWriter.java +++ b/contribs/vsp/src/main/java/playground/vsp/analysis/modules/ptAccessibility/utils/PtAccessMapShapeWriter.java @@ -31,20 +31,20 @@ import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.MultiPolygon; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.opengis.feature.simple.SimpleFeature; import playground.vsp.analysis.modules.ptAccessibility.stops.PtStopMap; /** * Calculates and writes buffers to shapes - * + * * @author aneumann */ public class PtAccessMapShapeWriter { private PtAccessMapShapeWriter() { - + } public static void writeAccessMap(Map> cluster2mode2area, int quadrantSegments, String outputFolder, String targetCoordinateSystem) { @@ -56,11 +56,11 @@ public static void writeAccessMap(Map> cluster Collections.sort(distancesSmallestFirst); HashMap> distance2mode2buffer = new HashMap>(); - + // Calculate buffer for all Multipolygons HashMap mode2buffer = null; int lastDistance = 0; - + for (Integer distance : distancesSmallestFirst) { if (mode2buffer == null) { // it's the frist and smallest one @@ -77,29 +77,29 @@ public static void writeAccessMap(Map> cluster mode2buffer = tempBuffers; lastDistance = distance.intValue(); } - + distance2mode2buffer.put(distance, mode2buffer); } - + writeGeometries(outputFolder + PtStopMap.FILESUFFIX + "_buffer", distance2mode2buffer, targetCoordinateSystem); - - - + + + // resort distances - largest first ArrayList distancesLargestFirst = new ArrayList(); for (Integer distance : distancesSmallestFirst) { distancesLargestFirst.add(0, distance); } - + HashMap> distance2mode2diffBuffer = new HashMap>(); HashMap lastMode2Buffer = null; Integer lastDist = null; - + // calculate Diff for all buffers for (Integer distance : distancesLargestFirst) { distance2mode2diffBuffer.put(distance, new HashMap()); - + if (lastMode2Buffer == null) { lastMode2Buffer = distance2mode2buffer.get(distance); lastDist = distance; @@ -113,12 +113,12 @@ public static void writeAccessMap(Map> cluster lastDist = distance; } } - + // add last (smallest) one as well for (Entry mode2BufferEntry : lastMode2Buffer.entrySet()) { distance2mode2diffBuffer.get(lastDist).put(mode2BufferEntry.getKey(), mode2BufferEntry.getValue()); } - + writeGeometries(outputFolder + PtStopMap.FILESUFFIX + "_diffBuffer", distance2mode2diffBuffer, targetCoordinateSystem); } @@ -130,10 +130,10 @@ private static void writeGeometries(String outputFolderAndFileName, HashMap bufferFeatures; Object[] bufferFeatureAttribs; - + for (Entry> distance2mode2bufferEntry : distance2mode2buffer.entrySet()) { bufferFeatures = new ArrayList(); HashMap mode2buffer = distance2mode2bufferEntry.getValue(); @@ -148,13 +148,13 @@ private static void writeGeometries(String outputFolderAndFileName, HashMap getAll(String targetCoordinateSystem) { SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder(); b.setCRS(MGC.getCRS(targetCoordinateSystem)); @@ -93,9 +93,9 @@ private Collection getAll(String targetCoordinateSystem) { b.add("pax_" + String.valueOf(i), Double.class); } SimpleFeatureBuilder builder = new SimpleFeatureBuilder(b.buildFeatureType()); - + Collection features = new ArrayList(); - + Object[] featureAttribs; for(Link link: this.sc.getNetwork().getLinks().values()){ featureAttribs = getFeatureAll(link,new Object[4 + this.handler.getMaxInterval()]); @@ -116,7 +116,7 @@ private Object[] getFeatureAll(Link link, Object[] objects) { Coordinate[] coord = new Coordinate[2]; coord[0] = new Coordinate(link.getFromNode().getCoord().getX(), link.getFromNode().getCoord().getY(), 0.); coord[1] = new Coordinate(link.getToNode().getCoord().getX(), link.getToNode().getCoord().getY(), 0.); - + objects[0] = new GeometryFactory().createLineString(coord); objects[1] = "all"; objects[2] = link.getId().toString(); @@ -138,11 +138,11 @@ private Collection getTransitLineFeatures(TransitLine l, String t for (int i = 0; i < this.handler.getMaxInterval(); i++){ b.add("pax_" + String.valueOf(i), Double.class); } - + SimpleFeatureBuilder builder = new SimpleFeatureBuilder(b.buildFeatureType()); - + Collection features = new ArrayList(); - + Object[] featureAttribs; for(Link link: this.sc.getNetwork().getLinks().values()){ featureAttribs = getLinkFeatureAttribs(link,l.getId(), new Object[4 + this.handler.getMaxInterval()]); @@ -169,7 +169,7 @@ private Object[] getLinkFeatureAttribs(Link link, Id lineId, Object Coordinate[] coord = new Coordinate[2]; coord[0] = new Coordinate(link.getFromNode().getCoord().getX(), link.getFromNode().getCoord().getY(), 0.); coord[1] = new Coordinate(link.getToNode().getCoord().getX(), link.getToNode().getCoord().getY(), 0.); - + objects[0] = new GeometryFactory().createLineString(coord); objects[1] = lineId.toString(); objects[2] = link.getId().toString(); @@ -185,7 +185,7 @@ public void writeResults(String outputFolder) { for(Entry, Collection> ee: this.lineId2features.entrySet()){ try{ if(ee.getValue().size() <= 0) continue; - ShapeFileWriter.writeGeometries(ee.getValue(), outputFolder + ee.getKey().toString()+ ".shp"); + GeoFileWriter.writeGeometries(ee.getValue(), outputFolder + ee.getKey().toString()+ ".shp"); }catch(ServiceConfigurationError e){ e.printStackTrace(); } diff --git a/contribs/vsp/src/main/java/playground/vsp/analysis/modules/transitSchedule2Shp/TransitSchedule2Shp.java b/contribs/vsp/src/main/java/playground/vsp/analysis/modules/transitSchedule2Shp/TransitSchedule2Shp.java index 94f8a049b8a..8423b07bc67 100644 --- a/contribs/vsp/src/main/java/playground/vsp/analysis/modules/transitSchedule2Shp/TransitSchedule2Shp.java +++ b/contribs/vsp/src/main/java/playground/vsp/analysis/modules/transitSchedule2Shp/TransitSchedule2Shp.java @@ -38,7 +38,7 @@ import org.matsim.api.core.v01.network.Network; import org.matsim.core.events.handler.EventHandler; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.matsim.core.utils.misc.Time; import org.matsim.pt.transitSchedule.api.TransitLine; import org.matsim.pt.transitSchedule.api.TransitRoute; @@ -51,9 +51,9 @@ * @author aneumann, droeder */ public class TransitSchedule2Shp extends AbstractAnalysisModule{ - + private static final Logger log = LogManager.getLogger(TransitSchedule2Shp.class); - + private Network network; private TransitSchedule schedule; private final String targetCoordinateSystem; @@ -72,12 +72,12 @@ public List getEventHandler() { @Override public void preProcessData() { - + } @Override public void postProcessData() { - + } @Override @@ -92,23 +92,23 @@ public void writeResults(String outputFolder) { Collection temp = getTransitLineFeatures(transitLine, this.targetCoordinateSystem); features.addAll(temp); try{ - ShapeFileWriter.writeGeometries(temp, outputFolder + transitLine.getId().toString() + ".shp"); + GeoFileWriter.writeGeometries(temp, outputFolder + transitLine.getId().toString() + ".shp"); }catch(ServiceConfigurationError e){ e.printStackTrace(); } } - // write a complete shape + // write a complete shape if(features.isEmpty()){ log.error("the transitschedule seems to be empty. No features are created, thus no shapefile will be written..."); return; } try{ - ShapeFileWriter.writeGeometries(features, outputFolder + "allLines.shp"); + GeoFileWriter.writeGeometries(features, outputFolder + "allLines.shp"); }catch(ServiceConfigurationError e){ e.printStackTrace(); } } - + private Collection getTransitLineFeatures(TransitLine transitLine, String targetCoordinateSystem) { SimpleFeatureTypeBuilder simpleFeatureBuilder = new SimpleFeatureTypeBuilder(); simpleFeatureBuilder.setCRS(MGC.getCRS(targetCoordinateSystem)); @@ -131,9 +131,9 @@ private Collection getTransitLineFeatures(TransitLine transitLine simpleFeatureBuilder.add("lastDep", String.class); simpleFeatureBuilder.add("timeOper", String.class); SimpleFeatureBuilder builder = new SimpleFeatureBuilder(simpleFeatureBuilder.buildFeatureType()); - + Collection features = new ArrayList(); - + Object[] routeFeatureAttributes; for(TransitRoute transitRoute: transitLine.getRoutes().values()){ routeFeatureAttributes = getRouteFeatureAttribs(transitRoute, transitLine.getId(), new Object[17]); @@ -147,25 +147,25 @@ private Collection getTransitLineFeatures(TransitLine transitLine } private Object[] getRouteFeatureAttribs(TransitRoute transitRoute, Id lineId, Object[] routeFeatureAttributes ) { - + List coords = new ArrayList(); // Create the polyline (lineString) - + // add the startLink Coord toNode = this.network.getLinks().get(transitRoute.getRoute().getStartLinkId()).getToNode().getCoord(); coords.add(new Coordinate(toNode.getX(), toNode.getY(), 0.)); - + // add the routeLinks for(Id linkId : transitRoute.getRoute().getLinkIds()){ toNode = this.network.getLinks().get(linkId).getToNode().getCoord(); coords.add(new Coordinate(toNode.getX(), toNode.getY(), 0.)); } - + //add the endlink toNode = this.network.getLinks().get(transitRoute.getRoute().getEndLinkId()).getToNode().getCoord(); coords.add(new Coordinate(toNode.getX(), toNode.getY(), 0.)); - + // create an array Coordinate[] coord = new Coordinate[coords.size()]; coord = coords.toArray(coord); @@ -173,7 +173,7 @@ private Object[] getRouteFeatureAttribs(TransitRoute transitRoute, Id counts, Map mo } } try{ - ShapeFileWriter.writeGeometries(features, file); + GeoFileWriter.writeGeometries(features, file); }catch(ServiceConfigurationError e){ e.printStackTrace(); } catch (UncheckedIOException e) { diff --git a/contribs/vsp/src/main/java/playground/vsp/analysis/utils/heatMap/HeatMap.java b/contribs/vsp/src/main/java/playground/vsp/analysis/utils/heatMap/HeatMap.java index 6bbf5bbb7ce..f8441de40be 100644 --- a/contribs/vsp/src/main/java/playground/vsp/analysis/utils/heatMap/HeatMap.java +++ b/contribs/vsp/src/main/java/playground/vsp/analysis/utils/heatMap/HeatMap.java @@ -35,7 +35,7 @@ import org.matsim.core.utils.collections.QuadTree; import org.matsim.core.utils.collections.Tuple; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.opengis.feature.simple.SimpleFeature; /** @@ -52,9 +52,9 @@ public class HeatMap { private double maxY = -Double.MAX_VALUE; private QuadTree tiles; private Integer gridSize; - + private class Tile{ - + private Polygon area; private Double value; @@ -78,34 +78,34 @@ public Tile(double minX, double maxX, double minY, double maxY) { this.area = factory.createPolygon(factory.createLinearRing(c), null); this.value = 0.; } - + public Coord getCentroid(){ return MGC.point2Coord(this.area.getCentroid()); } - + public Polygon getGeometry(){ return this.area; } - + public void add(Double d){ this.value += d; } - + public double getValue(){ return this.value; } } - + /** * a class to create a simple HeatMap from coordinates and corresponding values. - * + * * @param gridSize, the number of tiles of the HeatMap */ public HeatMap(Integer gridSize) { this.gridSize = gridSize; this.values = new ArrayList>(); } - + public void addValue(Coord coord, Double value){ this.values.add(new Tuple(coord, value)); findMinMax(coord); @@ -128,7 +128,7 @@ private void findMinMax(Coord coord) { this.minY = coord.getY(); } } - + public void createHeatMap(){ this.tiles = new QuadTree(minX, minY, maxX, maxY); Double dx, dy, inc; @@ -171,7 +171,7 @@ public void createHeatMap(){ t.add(v.getSecond()); } } - + private Collection getTiles() { return this.tiles.values(); } @@ -184,9 +184,9 @@ public static void writeHeatMapShape(String name, HeatMap heatmap, String file, b.add("name", String.class); b.add("count", Double.class); SimpleFeatureBuilder builder = new SimpleFeatureBuilder(b.buildFeatureType()); - + Collection features = new ArrayList(); - + Object[] featureAttribs; int i = 0; for(Tile t: heatmap.getTiles()){ @@ -205,7 +205,7 @@ public static void writeHeatMapShape(String name, HeatMap heatmap, String file, log.info("There are no tiles for " + name); } else { try{ - ShapeFileWriter.writeGeometries(features, file); + GeoFileWriter.writeGeometries(features, file); }catch(ServiceConfigurationError e){ e.printStackTrace(); } diff --git a/contribs/vsp/src/main/java/playground/vsp/andreas/utils/ana/RouteAllModesAsCar.java b/contribs/vsp/src/main/java/playground/vsp/andreas/utils/ana/RouteAllModesAsCar.java index e003b97fc9f..28ddbf7ab00 100644 --- a/contribs/vsp/src/main/java/playground/vsp/andreas/utils/ana/RouteAllModesAsCar.java +++ b/contribs/vsp/src/main/java/playground/vsp/andreas/utils/ana/RouteAllModesAsCar.java @@ -54,19 +54,19 @@ import org.matsim.core.router.util.LeastCostPathCalculator.Path; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.matsim.pt.PtConstants; import org.opengis.feature.simple.SimpleFeature; /** * Routes all modes of transport (except for transit_walk) as car modes and counts the number of trips per link. * Output as Shape - * + * * @author aneumann * */ public class RouteAllModesAsCar extends AbstractPersonFilter { - + private final static Logger log = LogManager.getLogger(RouteAllModesAsCar.class); private final Scenario sc; @@ -74,16 +74,16 @@ public class RouteAllModesAsCar extends AbstractPersonFilter { private HashMap link2totals = new HashMap(); private HashMap> mode2link2totals = new HashMap>(); - + public RouteAllModesAsCar(String networkFilename) { Gbl.startMeasurement(); Gbl.printMemoryUsage(); - + // read input data this.sc = ScenarioUtils.createScenario(ConfigUtils.createConfig()); this.sc.getConfig().network().setInputFile(networkFilename); ScenarioUtils.loadScenario(this.sc); - + FreespeedTravelTimeAndDisutility tC = new FreespeedTravelTimeAndDisutility(-6.0, 0.0, 0.0); this.routingAlgo = new DijkstraFactory().createPathCalculator(this.sc.getNetwork(), tC, tC); @SuppressWarnings("serial") @@ -99,7 +99,7 @@ public static void main(String[] args) { String networkFilename = args[1]; String popFilename = args[2]; String targetCoordinateSystem = args[3]; - + RouteAllModesAsCar routeAllModesAsCar = new RouteAllModesAsCar(networkFilename); routeAllModesAsCar.run(popFilename); routeAllModesAsCar.writeAsShape(outputDir, targetCoordinateSystem); @@ -115,15 +115,15 @@ private void writeAsShape(String outputDir, String targetCoordinateSystem) { for (String mode : this.mode2link2totals.keySet()) { typeBuilder.add("count " + mode, Double.class); } - + SimpleFeatureBuilder builder = new SimpleFeatureBuilder(typeBuilder.buildFeatureType()); - + Collection features = new ArrayList(); - + Object[] featureAttribs; - + for(Link link: this.sc.getNetwork().getLinks().values()){ - + featureAttribs = createLinkFeatureAttribs(link, new Object[3 + this.mode2link2totals.keySet().size()]); // skip links without count @@ -137,25 +137,25 @@ private void writeAsShape(String outputDir, String targetCoordinateSystem) { e1.printStackTrace(); } } - - ShapeFileWriter.writeGeometries(features, outputDir + "routeAllModesAsCar.shp"); + + GeoFileWriter.writeGeometries(features, outputDir + "routeAllModesAsCar.shp"); } private Object[] createLinkFeatureAttribs(Link link, Object[] objects) { if(this.link2totals.get(link) == null) { return null; } - + int total = this.link2totals.get(link).intValue(); - + Coordinate[] coord = new Coordinate[2]; coord[0] = new Coordinate(link.getFromNode().getCoord().getX(), link.getFromNode().getCoord().getY(), 0.); coord[1] = new Coordinate(link.getToNode().getCoord().getX(), link.getToNode().getCoord().getY(), 0.); - + objects[0] = new GeometryFactory().createLineString(coord); objects[1] = link.getId().toString(); objects[2] = total; - + int index = 3; for(String mode : this.mode2link2totals.keySet()){ if (this.mode2link2totals.get(mode).get(link) == null) { @@ -195,27 +195,27 @@ public void run(Person person) { count(); Activity lastAct = null; String currentMode = null; - + for (PlanElement planElement : person.getSelectedPlan().getPlanElements()) { if (planElement instanceof Activity) { Activity act = (Activity) planElement; - + if (act.getType().equalsIgnoreCase(PtConstants.TRANSIT_ACTIVITY_TYPE)) { continue; } - + if (lastAct == null) { lastAct = act; } else { Link lastLink = this.sc.getNetwork().getLinks().get(lastAct.getLinkId()); Link currentLink = this.sc.getNetwork().getLinks().get(act.getLinkId()); - + Path path = this.routingAlgo.calcLeastCostPath(lastLink.getToNode(), currentLink.getFromNode(), 0.0, null, null); this.storeLinks(currentMode, path.links); lastAct = act; } } - + if (planElement instanceof Leg) { Leg leg = (Leg) planElement; if (!leg.getMode().equalsIgnoreCase(TransportMode.transit_walk)) { @@ -228,11 +228,11 @@ public void run(Person person) { private void storeLinks(String currentMode, List links) { for (Link link : links) { this.addOne(this.link2totals, link); - + if (this.mode2link2totals.get(currentMode) == null) { this.mode2link2totals.put(currentMode, new HashMap()); } - + this.addOne(this.mode2link2totals.get(currentMode), link); } } diff --git a/contribs/vsp/src/main/java/playground/vsp/andreas/utils/ana/filterActsPerShape/WorkHomeShapeCounter.java b/contribs/vsp/src/main/java/playground/vsp/andreas/utils/ana/filterActsPerShape/WorkHomeShapeCounter.java index e32cc258ad3..c7489566966 100644 --- a/contribs/vsp/src/main/java/playground/vsp/andreas/utils/ana/filterActsPerShape/WorkHomeShapeCounter.java +++ b/contribs/vsp/src/main/java/playground/vsp/andreas/utils/ana/filterActsPerShape/WorkHomeShapeCounter.java @@ -25,7 +25,6 @@ import java.io.IOException; import java.util.HashMap; -import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.geotools.data.simple.SimpleFeatureIterator; @@ -40,74 +39,74 @@ import org.matsim.core.population.PersonUtils; import org.matsim.core.population.algorithms.AbstractPersonAlgorithm; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; public class WorkHomeShapeCounter extends AbstractPersonAlgorithm{ - + private static final Logger log = LogManager.getLogger(WorkHomeShapeCounter.class); private final Coord minXY; private final Coord maxXY; private String actTypeOne; private String actTypeTwo; - + private boolean initDone = false; private String shapeFile; private SimpleFeatureSource featureSource; private HashMap polygonCountMap = new HashMap(); private HashMap polyNameMap = new HashMap(); - + @Override public void run(Person person) { - + if(!this.initDone){ init(); } - + int nofPlans = person.getPlans().size(); - + for (int planId = 0; planId < nofPlans; planId++) { Plan plan = person.getPlans().get(planId); - + // search selected plan if (PersonUtils.isSelected(plan)) { - - // do something + + // do something for (PlanElement pEOne : plan.getPlanElements()) { if(pEOne instanceof Activity){ - - // check - actTypeOne in search area? - Activity actOne = (Activity) pEOne; + + // check - actTypeOne in search area? + Activity actOne = (Activity) pEOne; if(actOne.getType().equalsIgnoreCase(this.actTypeOne)){ // it is of type actTypeOne -> check coords - + if(actIsSituatedInGivenSearchArea(actOne)){ // act one ok, check type two; - + for (PlanElement pETwo : plan.getPlanElements()) { if(pETwo instanceof Activity){ - - Activity actTwo = (Activity) pETwo; + + Activity actTwo = (Activity) pETwo; if(actTwo.getType().equalsIgnoreCase(this.actTypeTwo)){ - - // act two ok - search corresponding shape + + // act two ok - search corresponding shape searchCorrespondingShape(actTwo); break; } - - } - } + + } + } break; - } - - } - + } + + } + } } - + } - } + } } public WorkHomeShapeCounter(Coord minXY, Coord maxXY, String actTypeOne, String actTypeTwo, String shapeFile){ @@ -130,14 +129,14 @@ public String toString() { } return strB.toString(); } - + public void toFile(String filename){ - + int numberOfActs = 0; for (Polygon poly : this.polygonCountMap.keySet()) { numberOfActs += this.polygonCountMap.get(poly).intValue(); } - + try { BufferedWriter writer = new BufferedWriter(new FileWriter(new File(filename))); writer.write("#Results with " + this.actTypeOne + " act in minXY " + this.minXY + " maxXY " + this.maxXY + " and " + this.actTypeTwo + " act located in"); writer.newLine(); @@ -159,10 +158,10 @@ public void toFile(String filename){ * Put all polygon in an iterable list */ private void init() { - + try { - this.featureSource = ShapeFileReader.readDataFile(this.shapeFile); - + this.featureSource = GeoFileReader.readDataFile(this.shapeFile); + SimpleFeatureIterator fIt = this.featureSource.getFeatures().features(); while (fIt.hasNext()) { SimpleFeature ft = fIt.next(); @@ -174,13 +173,13 @@ private void init() { this.polyNameMap.put(poly, (String) ft.getAttribute("Bezirk")); } } - } - + } + } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } - + this.initDone = true; } @@ -189,8 +188,8 @@ private boolean actIsSituatedInGivenSearchArea(Activity act) { if(this.minXY.getY() > act.getCoord().getY()){ return false;} if(this.maxXY.getX() < act.getCoord().getX()){ return false;} if(this.maxXY.getY() < act.getCoord().getY()){ return false;} - - return true; + + return true; } private void searchCorrespondingShape(Activity actTwo) { diff --git a/contribs/vsp/src/main/java/playground/vsp/andreas/utils/pop/FilterPopulationByShape.java b/contribs/vsp/src/main/java/playground/vsp/andreas/utils/pop/FilterPopulationByShape.java index 5b4ada222e5..63fede8cee6 100644 --- a/contribs/vsp/src/main/java/playground/vsp/andreas/utils/pop/FilterPopulationByShape.java +++ b/contribs/vsp/src/main/java/playground/vsp/andreas/utils/pop/FilterPopulationByShape.java @@ -52,53 +52,53 @@ import org.matsim.core.population.io.StreamingPopulationWriter; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; /** * Filters a given Population by a given shape - includes all routed modes - * + * * @author aneumann * */ public class FilterPopulationByShape implements LinkEnterEventHandler, PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler{ - + private final static Logger log = LogManager.getLogger(FilterPopulationByShape.class); private GeometryFactory factory; private Geometry areaToExclude; private Geometry areaToInclude; private TreeSet includeLinks; private TreeSet agentsToKeep; - + private HashMap> vehId2AgentIdsMap; - + public FilterPopulationByShape(String netFile, String popInFile, String eventsFile, String areaShapeFile, String popOutFile){ Gbl.startMeasurement(); Gbl.printMemoryUsage(); - + log.info("Network: " + netFile); log.info("Population: " + popInFile); log.info("Events: " + eventsFile); log.info("Shape: " + areaShapeFile); log.info("Population out: " + popOutFile); - + Scenario sc = ScenarioUtils.createScenario(ConfigUtils.createConfig()); sc.getConfig().network().setInputFile(netFile); ScenarioUtils.loadScenario(sc); - + this.factory = new GeometryFactory(); this.areaToExclude = this.factory.buildGeometry(new ArrayList()); this.createServiceAreaShp(areaShapeFile); this.includeLinks = new TreeSet(); - - log.info(sc.getNetwork().getLinks().values().size() + " links in given network"); + + log.info(sc.getNetwork().getLinks().values().size() + " links in given network"); for (Link link : sc.getNetwork().getLinks().values()) { if (this.linkToNodeInServiceArea(link)) { this.includeLinks.add(link.getId().toString()); } - } + } log.info(this.includeLinks.size() + " links in area of interest"); - + this.agentsToKeep = new TreeSet(); this.vehId2AgentIdsMap = new HashMap>(); EventsManager eventsManager = EventsUtils.createEventsManager(); @@ -108,17 +108,17 @@ public FilterPopulationByShape(String netFile, String popInFile, String eventsFi log.info("Found " + this.agentsToKeep.size() + " agent ids to keep."); Gbl.printMemoryUsage(); Gbl.printElapsedTime(); - + sc.getConfig().plans().setInputFile(popInFile); Population pop = (Population) sc.getPopulation(); StreamingDeprecated.setIsStreaming(pop, true); PopulationReader popReader = new PopulationReader(sc); StreamingPopulationWriter popWriter = new StreamingPopulationWriter(); popWriter.startStreaming(popOutFile); - + StreamingDeprecated.addAlgorithm(pop, new PersonIdFilter(this.agentsToKeep, popWriter)); Gbl.printMemoryUsage(); - + popReader.readFile(popInFile); PopulationUtils.printPlansCount(pop) ; popWriter.closeStreaming(); @@ -129,7 +129,7 @@ public FilterPopulationByShape(String netFile, String popInFile, String eventsFi @Override public void reset(int iteration) { // TODO Auto-generated method stub - + } @Override @@ -138,7 +138,7 @@ public void handleEvent(LinkEnterEvent event) { // link not of interest return; } - + if (this.vehId2AgentIdsMap.get(event.getVehicleId()) == null) { // it's a private car this.agentsToKeep.add(event.getDriverId()); @@ -150,7 +150,7 @@ public void handleEvent(LinkEnterEvent event) { @Override public void handleEvent(PersonLeavesVehicleEvent event) { - this.vehId2AgentIdsMap.get(event.getVehicleId()).remove(event.getPersonId()); + this.vehId2AgentIdsMap.get(event.getVehicleId()).remove(event.getPersonId()); } @Override @@ -158,8 +158,8 @@ public void handleEvent(PersonEntersVehicleEvent event) { if (this.vehId2AgentIdsMap.get(event.getVehicleId()) == null) { this.vehId2AgentIdsMap.put(event.getVehicleId(), new TreeSet()); } - - this.vehId2AgentIdsMap.get(event.getVehicleId()).add(event.getPersonId()); + + this.vehId2AgentIdsMap.get(event.getVehicleId()).add(event.getPersonId()); } private boolean linkToNodeInServiceArea(Link link) { @@ -172,12 +172,12 @@ private boolean linkToNodeInServiceArea(Link link) { } return false; } - + private void createServiceAreaShp(String serviceAreaFile) { - Collection features = ShapeFileReader.getAllFeatures(serviceAreaFile); + Collection features = GeoFileReader.getAllFeatures(serviceAreaFile); Collection include = new ArrayList(); Collection exclude = new ArrayList(); - + for (SimpleFeature f: features) { boolean incl = true; Geometry g = null; @@ -188,7 +188,7 @@ private void createServiceAreaShp(String serviceAreaFile) { g = (Geometry) o; } // TODO use a better way to get the attributes, maybe directly per index. - // Now the last attribute is used per default... + // Now the last attribute is used per default... else if (o instanceof String){ incl = Boolean.parseBoolean((String) o); } @@ -201,12 +201,12 @@ else if (o instanceof String){ } } } - this.areaToInclude = this.factory.createGeometryCollection( + this.areaToInclude = this.factory.createGeometryCollection( include.toArray(new Geometry[include.size()])).buffer(0); - this.areaToExclude = this.factory.createGeometryCollection( + this.areaToExclude = this.factory.createGeometryCollection( exclude.toArray(new Geometry[exclude.size()])).buffer(0); } - + public static void main(String[] args) { // Charlottenburg // String netFile = "e:/_shared-svn/andreas/paratransit/input/trb_2012/network.final.xml.gz"; @@ -214,22 +214,22 @@ public static void main(String[] args) { // String eventsFile = "e:/berlin-bvg09_runs/bvg.run189.10pct/ITERS/it.100/bvg.run189.10pct.100.events.xml.gz"; // String areaShapeFile = "e:/_shared-svn/andreas/paratransit/input/trb_2012/area/simulated_area.shp"; // String popOutFile = "e:/_shared-svn/andreas/paratransit/input/trb_2012/plans/bvg.run189.10pct.100.plans.selected_movedToTXL_diluted.xml.gz"; - + // Spandau // String netFile = "e:/_shared-svn/andreas/paratransit/input/trb_2012/network.final.xml.gz"; // String popInFile = "e:/berlin-bvg09_runs/bvg.run192.100pct/ITERS/it.100/bvg.run192.100pct.100.plans.selected.xml.gz"; // String eventsFile = "e:/berlin-bvg09_runs/bvg.run192.100pct/ITERS/it.100/bvg.run192.100pct.100.events.xml.gz"; // String areaShapeFile = "e:/_shared-svn/andreas/paratransit/input/trb_2012/area/spandau_area.shp"; // String popOutFile = "e:/_shared-svn/andreas/paratransit/input/trb_2012/plans/bvg.run192.100pct.100.plans.selected_spandau.xml.gz"; - + // Spandau neu String netFile = "e:/_shared-svn/andreas/paratransit/input/trb_2012/network.final.xml.gz"; String popInFile = "e:/_shared-svn/andreas/paratransit/input/trb_2012/plans/bvg.run189.10pct.100.plans.selected_movedToTXL.xml.gz"; String eventsFile = "e:/berlin-bvg09_runs/bvg.run189.10pct/ITERS/it.100/bvg.run189.10pct.100.events.xml.gz"; String areaShapeFile = "e:/_shared-svn/andreas/paratransit/input/trb_2012/area/spandau_area.shp"; String popOutFile = "e:/_shared-svn/andreas/paratransit/input/trb_2012/plans/bvg.run189.10pct.100.plans.selected_movedToTXL_spandau.xml.gz"; - + FilterPopulationByShape filter = new FilterPopulationByShape(netFile, popInFile, eventsFile, areaShapeFile, popOutFile); } - + } diff --git a/contribs/vsp/src/main/java/playground/vsp/andreas/utils/pt/transitSchedule2shape/DaShapeWriter.java b/contribs/vsp/src/main/java/playground/vsp/andreas/utils/pt/transitSchedule2shape/DaShapeWriter.java index 0a8aa167350..600ff620232 100644 --- a/contribs/vsp/src/main/java/playground/vsp/andreas/utils/pt/transitSchedule2shape/DaShapeWriter.java +++ b/contribs/vsp/src/main/java/playground/vsp/andreas/utils/pt/transitSchedule2shape/DaShapeWriter.java @@ -43,7 +43,7 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.core.utils.collections.Tuple; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.matsim.pt.transitSchedule.api.TransitLine; import org.matsim.pt.transitSchedule.api.TransitRoute; import org.matsim.pt.transitSchedule.api.TransitRouteStop; @@ -52,7 +52,7 @@ import org.opengis.feature.simple.SimpleFeature; /** - * + * * @author droeder * */ @@ -60,9 +60,9 @@ public class DaShapeWriter { private static final Logger log = LogManager.getLogger(DaShapeWriter.class); private static SimpleFeatureBuilder builder; - + private static GeometryFactory geometryFactory = new GeometryFactory(); - + public static void writeLinks2Shape(String fileName, Map links, Map> attributes, String targetCoordinateSystem){ if(attributes == null){ initLineFeatureType("links", null, true, targetCoordinateSystem); @@ -75,12 +75,12 @@ public static void writeLinks2Shape(String fileName, Map lin write(createLinkFeatures(links, attributes), fileName); } - + public static void writeNodes2Shape(String fileName, Map nodes, String targetCoordinateSystem){ initPointFeatureType("nodes", null, targetCoordinateSystem); write(createNodeFeatures(nodes), fileName); } - + public static void writeDefaultPoints2Shape(String fileName, String name, Map points, Map> attributes, String targetCoordinateSystem){ if(attributes == null){ initPointFeatureType(name, null, targetCoordinateSystem); @@ -92,10 +92,10 @@ public static void writeDefaultPoints2Shape(String fileName, String name, Map> points, Map> attributes, String targetCoordinateSystem){ for (SortedMap m : attributes.values()){ initLineFeatureType("distance", m, targetCoordinateSystem); break; } - + write(createPointDistanceFeatures(points,attributes), fileName); } /** @@ -140,7 +140,7 @@ public static void writePointDist2Shape (String fileName, Map> lineStrings, Map> attributes, String targetCoordinateSystem){ - + if(attributes == null){ initLineFeatureType(name, null, targetCoordinateSystem); }else{ @@ -149,10 +149,10 @@ public static void writeDefaultLineString2Shape(String fileName, String name, M break; } } - + write(createDefaultLineStringFeature(lineStrings, attributes), fileName); } - + public static void writeDefaultLineStrings2Shape(String fileName, String name, Map> lineStrings, String targetCoordinateSystem){ Map> map = new HashMap>(); SortedMap ls; @@ -165,20 +165,20 @@ public static void writeDefaultLineStrings2Shape(String fileName, String name, M } writeDefaultLineString2Shape(fileName, name, map, null, targetCoordinateSystem); } - + private static void write(Collection features, String shapeFileOutName){ if(features.isEmpty()){ log.error("can not write " + shapeFileOutName + ", because featurelist is empty..."); }else{ - ShapeFileWriter.writeGeometries(features, shapeFileOutName); - log.info(shapeFileOutName + " written!"); + GeoFileWriter.writeGeometries(features, shapeFileOutName); + log.info(shapeFileOutName + " written!"); } } - + private static void initLineFeatureType(String name, SortedMap attributes, String targetCoordinateSystem){ initLineFeatureType(name, attributes, false, targetCoordinateSystem); } - + private static void initLineFeatureType(String name, SortedMap attributes, boolean links, String targetCoordinateSystem) { SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder(); b.setName(name); @@ -198,7 +198,7 @@ private static void initLineFeatureType(String name, SortedMap a builder = new SimpleFeatureBuilder(b.buildFeatureType()); } - + private static void initPointFeatureType(String name, SortedMap attributes, String targetCoordinateSystem){ SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder(); b.setName(name); @@ -210,15 +210,15 @@ private static void initPointFeatureType(String name, SortedMap b.add(e.getKey(), e.getValue().getClass()); } } - + builder = new SimpleFeatureBuilder(b.buildFeatureType()); } - + private static Collection createRouteFeatures(TransitSchedule schedule, Collection lines2write, Map> attributes){ Collection features = new ArrayList(); SimpleFeature feature; Coordinate[] coord; - + for (TransitLine line : schedule.getTransitLines().values()){ if( (lines2write == null) || lines2write.contains(line.getId())){ for(TransitRoute route : line.getRoutes().values()){ @@ -239,7 +239,7 @@ private static Collection createRouteFeatures(TransitSchedule sch } return features; } - + private static Collection createLinkFeatures(Map links, Map> attributes) { Collection features = new ArrayList(); SimpleFeature feature; @@ -261,12 +261,12 @@ private static Collection createLinkFeatures(Map createPointDistanceFeatures(Map> points, Map> attributes){ Collection features = new ArrayList(); SimpleFeature feature; Coordinate[] coord; - + for(Entry> e : points.entrySet()) { coord = new Coordinate[2]; coord[0] = MGC.coord2Coordinate(e.getValue().getFirst()); @@ -274,14 +274,14 @@ private static Collection createPointDistanceFeatures(Map createStopFeatures(Map stops, Collection stops2write){ Collection features = new ArrayList(); SimpleFeature feature; - + for(TransitStopFacility stop : stops.values()){ if((stops2write == null) || stops2write.contains(stop.getId())){ feature = getPointFeature(stop.getCoord(), stop.getId().toString(), null); @@ -290,22 +290,22 @@ private static Collection createStopFeatures(Map createNodeFeatures(Map nodes){ Collection features = new ArrayList(); SimpleFeature feature; - + for(Node n : nodes.values()){ feature = getPointFeature(n.getCoord(), n.getId().toString(), null); features.add(feature); } return features; } - + private static Collection createDefaultPointFeature(Map points, Map> attributes){ Collection features = new ArrayList(); SimpleFeature feature; - + for(Entry e: points.entrySet()){ if(attributes == null){ feature = getPointFeature(e.getValue(), e.getKey(), null); @@ -314,15 +314,15 @@ private static Collection createDefaultPointFeature(Map createDefaultLineStringFeature(Map> lineStrings, Map> attributes) { Collection features = new ArrayList(); SimpleFeature feature; Coordinate[] coord; - + for(Entry> points : lineStrings.entrySet()){ if (points.getValue().size()<2){ log.error(points.getKey() + ": not enough points for a lineString. Need at least 2 points!"); @@ -336,20 +336,20 @@ private static Collection createDefaultLineStringFeature(Map attributes) { LineString s = geometryFactory.createLineString(c); Object[] attribs ; @@ -361,21 +361,21 @@ private static SimpleFeature getLineStringFeature(CoordinateArraySequence c, Str attribs[0] = s; attribs[1] = name; Integer count = 2; - + if(!(attributes == null)){ for(Object o : attributes.values()){ attribs[count] = o; count++; } } - + try { return builder.buildFeature(name, attribs); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } } - + private static SimpleFeature getPointFeature(Coord coord, String id, SortedMap attributes) { Point p = geometryFactory.createPoint(MGC.coord2Coordinate(coord)); Object [] attribs ; @@ -387,7 +387,7 @@ private static SimpleFeature getPointFeature(Coord coord, String id, SortedMap sha for (String shapeFile : shapeFileToFeatureKey.keySet()) { String key = shapeFileToFeatureKey.get(shapeFile); LOG.info("Processing zone file " + shapeFile + " with feature key " + key); - Collection features = ShapeFileReader.getAllFeatures(shapeFile); + Collection features = GeoFileReader.getAllFeatures(shapeFile); for (SimpleFeature feature : features) { Geometry geometry = (Geometry) feature.getDefaultGeometry(); String shapeId = Cemdap2MatsimUtils.removeLeadingZeroFromString((String) feature.getAttribute(key)); @@ -105,7 +105,7 @@ public CORINELandCoverCoordsModifier(String matsimPlans, Map sha this.sameHomeActivity = sameHomeActivity; if (this.sameHomeActivity) LOG.info("Home activities for a person will be at the same location."); - + this.homeActivityPrefix = homeActivityPrefix; } @@ -157,7 +157,7 @@ public static void main(String[] args) { public void process() { LOG.info("Start processing, this may take a while ... "); - + int personCounter = 0; for (Person person : population.getPersons().values()) { Coord homeLocationCoord = null; @@ -166,7 +166,7 @@ public void process() { if (personCounter%1000 == 0) { LOG.info("Person #" + personCounter); } - + for (Plan plan : person.getPlans()) { for (PlanElement planElement : plan.getPlanElements()) { if (planElement instanceof Activity) { diff --git a/contribs/vsp/src/main/java/playground/vsp/corineLandcover/CorineLandCoverData.java b/contribs/vsp/src/main/java/playground/vsp/corineLandcover/CorineLandCoverData.java index f9f10f9bcae..d8b0584a210 100644 --- a/contribs/vsp/src/main/java/playground/vsp/corineLandcover/CorineLandCoverData.java +++ b/contribs/vsp/src/main/java/playground/vsp/corineLandcover/CorineLandCoverData.java @@ -31,7 +31,7 @@ import org.locationtech.jts.geom.Point; import org.matsim.api.core.v01.Coord; import org.matsim.core.gbl.Gbl; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; /** @@ -57,7 +57,7 @@ public class CorineLandCoverData { public CorineLandCoverData( String corineLandCoverShapeFile, boolean simplifyGeometries, boolean combiningGeom) { LOGGER.info("Reading CORINE landcover shape file . . ."); - Collection landCoverFeatures = ShapeFileReader.getAllFeatures(corineLandCoverShapeFile); + Collection landCoverFeatures = GeoFileReader.getAllFeatures(corineLandCoverShapeFile); this.simplifyGeometries = simplifyGeometries; if (this.simplifyGeometries) LOGGER.warn("Geometries will be simplified such that number of vertices in each geometry is less than 1000. " + diff --git a/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/CommuterGenerator.java b/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/CommuterGenerator.java index 675e4edaf88..41c2466c84d 100644 --- a/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/CommuterGenerator.java +++ b/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/CommuterGenerator.java @@ -33,7 +33,7 @@ import org.matsim.core.utils.collections.Tuple; import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.geometry.transformations.TransformationFactory; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -42,11 +42,11 @@ * @author dgrether */ public class CommuterGenerator { - + private static final Logger log = LogManager.getLogger(CommuterGenerator.class); - + public static void main(String[] args) throws Exception { - + String baseDir = "../../../shared-svn/projects/cottbus/data/scenarios/cottbus_scenario/"; String networkFile = baseDir + "network_wgs84_utm33n.xml.gz"; boolean useLanduse = true; @@ -54,7 +54,7 @@ public static void main(String[] args) throws Exception { // String shapesOutputDirectory = populationOutputDirectory + "shapes_all_modes/"; String shapesOutputDirectory = populationOutputDirectory + "shapes/"; - + // String populationOutputFile = populationOutputDirectory + "commuter_population_wgs84_utm33n.xml.gz"; String populationOutputFile = populationOutputDirectory + "commuter_population_wgs84_utm33n_car_only.xml.gz"; OutputDirectoryLogging.initLoggingWithOutputDirectory(populationOutputDirectory); @@ -63,24 +63,24 @@ public static void main(String[] args) throws Exception { if (! shapes.exists() ) { shapes.mkdir(); } - + Config config1 = ConfigUtils.createConfig(); config1.network().setInputFile(networkFile); Scenario sc = ScenarioUtils.loadScenario(config1); - + CommuterDataReader cdr = new CommuterDataReader(); cdr.addFilterRange(12071000); cdr.addFilter("12052000"); //12052000 == cottbus stadt cdr.readFile("../../../shared-svn/studies/countries/de/pendler_nach_gemeinden/brandenburg_einpendler.csv"); // cdr.getCommuterRelations().add(new CommuterDataElement("12052000", "12052000", 1000)); - + String gemeindenBrandenburgShapeFile = "../../../shared-svn/studies/countries/de/brandenburg_gemeinde_kreisgrenzen/gemeinden/dlm_gemeinden.shp"; - ShapeFileReader gemeindenReader = new ShapeFileReader(); + GeoFileReader gemeindenReader = new GeoFileReader(); Collection gemeindenFeatures = gemeindenReader.readFileAndInitialize(gemeindenBrandenburgShapeFile); - - - - CommuterDemandWriter cdw = new CommuterDemandWriter(gemeindenFeatures, gemeindenReader.getCoordinateSystem(), + + + + CommuterDemandWriter cdw = new CommuterDemandWriter(gemeindenFeatures, gemeindenReader.getCoordinateSystem(), cdr.getCommuterRelations(), MGC.getCRS(TransformationFactory.WGS84_UTM33N)); //landuse if (useLanduse){ @@ -90,31 +90,31 @@ public static void main(String[] args) throws Exception { cdw.addLanduse("home", homeLanduse); cdw.addLanduse("work", workLanduse); } -// +// // cdw.setScalefactor(1.0); // all modes cdw.setScalefactor(0.55); //car mode share // cdw.setScalefactor(0.1); //testing - + cdw.computeDemand(sc); PopulationWriter populationWriter = new PopulationWriter(sc.getPopulation(), sc.getNetwork()); populationWriter.write(populationOutputFile); log.info("population written to " + populationOutputFile); - + //write some test output Config config = ConfigUtils.createConfig(); config.network().setInputFile(networkFile); config.plans().setInputFile(populationOutputFile); Scenario baseScenario = ScenarioUtils.loadScenario(config); - + String shapeFilename = shapesOutputDirectory + "commuter_population_home.shp"; new DgPopulation2ShapeWriter(baseScenario.getPopulation(), MGC.getCRS(TransformationFactory.WGS84_UTM33N)) .write("home", shapeFilename, MGC.getCRS(TransformationFactory.WGS84_UTM33N)); shapeFilename = shapesOutputDirectory + "commuter_population_work.shp"; new DgPopulation2ShapeWriter(baseScenario.getPopulation(), MGC.getCRS(TransformationFactory.WGS84_UTM33N)) .write("work", shapeFilename, MGC.getCRS(TransformationFactory.WGS84_UTM33N)); - + log.info("done!"); OutputDirectoryLogging.closeOutputDirLogging(); } diff --git a/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/DgLanduseReader.java b/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/DgLanduseReader.java index c500ee81af4..6a7b47969d3 100644 --- a/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/DgLanduseReader.java +++ b/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/DgLanduseReader.java @@ -23,7 +23,7 @@ import java.util.HashSet; import org.matsim.core.utils.collections.Tuple; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -33,9 +33,9 @@ * */ public class DgLanduseReader { - + public static final String BASE_DIR = "../../../shared-svn/studies/countries/de/berlin_brandenburg_corine_landcover/shapefiles/"; - + private static final String STADTGEFUEGE_KONTINUIERLICH = BASE_DIR + "clc06_c111.shp"; private static final String STADTGEFUEGE_NICHT_KONTINUIERLICH = BASE_DIR + "clc06_c112.shp"; private static final String INDUSTRIE_GEWERBEGEBIETE = BASE_DIR + "clc06_c121.shp"; @@ -45,33 +45,33 @@ public class DgLanduseReader { // private static final String MINERALE_ABBAUSTAETTEN = BASE_DIR + "clc06_c131.shp"; private static final String DEPONIEN = BASE_DIR + "clc06_c132.shp"; private static final String BAUSTELLEN = BASE_DIR + "clc06_c133.shp"; - - + + private static final String[] landuse_files_home = {STADTGEFUEGE_KONTINUIERLICH, STADTGEFUEGE_NICHT_KONTINUIERLICH}; // private static final String[] landuse_files_home = {STADTGEFUEGE_NICHT_KONTINUIERLICH}; - - private static final String[] landuse_files_work = {STADTGEFUEGE_KONTINUIERLICH, + + private static final String[] landuse_files_work = {STADTGEFUEGE_KONTINUIERLICH, STADTGEFUEGE_NICHT_KONTINUIERLICH, INDUSTRIE_GEWERBEGEBIETE, STRASSEN_SCHIENENNETZE_GEBAUEDE, HAFENGEBIET, FLUGHAEFEN, DEPONIEN, BAUSTELLEN - /* skip mines because they cause disproportional many work places and, thus, to much traffic in their region */ + /* skip mines because they cause disproportional many work places and, thus, to much traffic in their region */ // , MINERALE_ABBAUSTAETTEN }; // private static final String[] landuse_files_work = {INDUSTRIE_GEWERBEGEBIETE}; - + public Tuple,CoordinateReferenceSystem> readLanduseDataHome(){ return this.readLanduseData(landuse_files_home); } - + public Tuple,CoordinateReferenceSystem> readLanduseDataWork(){ return this.readLanduseData(landuse_files_work); } - + private Tuple, CoordinateReferenceSystem> readLanduseData(String[] shapefiles){ - ShapeFileReader shapeReader = new ShapeFileReader(); + GeoFileReader shapeReader = new GeoFileReader(); Collection allFeatures = new HashSet(); Collection currentFeatures = null; for (String filename : shapefiles){ diff --git a/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/DgPopulation2ShapeWriter.java b/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/DgPopulation2ShapeWriter.java index 9c8609b2540..943f51c177f 100644 --- a/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/DgPopulation2ShapeWriter.java +++ b/contribs/vsp/src/main/java/playground/vsp/demandde/commuterDemandCottbus/DgPopulation2ShapeWriter.java @@ -32,7 +32,7 @@ import org.matsim.api.core.v01.population.Population; import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.gis.PointFeatureFactory; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.opengis.feature.simple.SimpleFeature; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; @@ -44,7 +44,7 @@ */ public class DgPopulation2ShapeWriter { - + private Population pop; private CoordinateReferenceSystem popCrs; @@ -53,7 +53,7 @@ public DgPopulation2ShapeWriter(Population pop, CoordinateReferenceSystem crs){ this.pop = pop; this.popCrs = crs; } - + public void write(String activityType, String filename, CoordinateReferenceSystem targetCrs){ try { MathTransform transformation = CRS.findMathTransform(this.popCrs, targetCrs, true); @@ -66,7 +66,7 @@ public void write(String activityType, String filename, CoordinateReferenceSyste addAttribute("start_time", Double.class). addAttribute("end_time", Double.class). create(); - + List features = new ArrayList(); SimpleFeature f = null; for (Person p : this.pop.getPersons().values()){ @@ -75,7 +75,7 @@ public void write(String activityType, String filename, CoordinateReferenceSyste if (pe instanceof Activity){ Activity activity = (Activity) pe; if (activity.getType().compareTo(activityType) == 0){ - + String id = p.getId().toString(); String type = activity.getType(); Double startTime = activity.getStartTime().seconds(); @@ -83,20 +83,20 @@ public void write(String activityType, String filename, CoordinateReferenceSyste Coordinate actCoordinate = MGC.coord2Coordinate(activity.getCoord()); actCoordinate = JTS.transform(actCoordinate, actCoordinate, transformation); - + f = factory.createPoint(actCoordinate, new Object[] {id, type, startTime, endTime}, null); features.add(f); } } } } - - ShapeFileWriter.writeGeometries(features, filename); + + GeoFileWriter.writeGeometries(features, filename); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } - + } - + } diff --git a/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/GVPlanReader.java b/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/GVPlanReader.java index 9f162db4bd3..113c347994a 100644 --- a/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/GVPlanReader.java +++ b/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/GVPlanReader.java @@ -32,25 +32,25 @@ import org.matsim.core.scenario.MutableScenario; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.transformations.TransformationFactory; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; import playground.vsp.pipeline.PopulationReaderTask; import playground.vsp.pipeline.PopulationWriterTask; public class GVPlanReader { - - + + private static final String GV_NETWORK_FILENAME = "/Users/michaelzilske/workspace/prognose_2025/demand/network_cleaned_wgs84.xml.gz"; - + private static final String NETWORK_FILENAME = "/Users/michaelzilske/osm/motorway_germany.xml"; - + private static final String GV_PLANS = "/Users/michaelzilske/workspace/run1061/1061.output_plans.xml.gz"; - + private static final String FILTER_FILENAME = "/Users/michaelzilske/workspace/prognose_2025/demand/filter.shp"; - + private static final String LANDKREISE = "/Users/michaelzilske/workspace/prognose_2025/osm_zellen/landkreise.shp"; - + private static boolean isCoordInShape(Coord linkCoord, Collection features, GeometryFactory factory) { boolean found = false; Geometry geo = factory.createPoint(new Coordinate(linkCoord.getX(), linkCoord.getY())); @@ -62,21 +62,21 @@ private static boolean isCoordInShape(Coord linkCoord, Collection } return found; } - + public static void main(String[] args) { Scenario gvNetwork = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); new MatsimNetworkReader(gvNetwork.getNetwork()).readFile(GV_NETWORK_FILENAME); Scenario osmNetwork = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); new MatsimNetworkReader(osmNetwork.getNetwork()).readFile(NETWORK_FILENAME); Collection featuresInShape; - featuresInShape = new ShapeFileReader().readFileAndInitialize(FILTER_FILENAME); - + featuresInShape = new GeoFileReader().readFileAndInitialize(FILTER_FILENAME); + PopulationReaderTask populationReaderTask = new PopulationReaderTask(GV_PLANS, gvNetwork.getNetwork()); - + PersonDereferencerTask personDereferencerTask = new PersonDereferencerTask(); - + PersonGeoTransformatorTask personGeoTransformatorTask = new PersonGeoTransformatorTask(TransformationFactory.WGS84, TransformationFactory.DHDN_GK4); - + PersonRouterFilter personRouterFilter = new PersonRouterFilter(osmNetwork.getNetwork()); GeometryFactory factory = new GeometryFactory(); for (Node node : osmNetwork.getNetwork().getNodes().values()) { @@ -84,18 +84,18 @@ public static void main(String[] args) { personRouterFilter.getInterestingNodeIds().add(node.getId()); } } - + PersonVerschmiererTask personVerschmiererTask = new PersonVerschmiererTask(LANDKREISE); - + PopulationWriterTask populationWriterTask = new PopulationWriterTask("/Users/michaelzilske/workspace/prognose_2025/demand/naechster_versuch_gv.xml", gvNetwork.getNetwork()); - + populationReaderTask.setSink(personDereferencerTask); personDereferencerTask.setSink(personGeoTransformatorTask); personGeoTransformatorTask.setSink(personRouterFilter); personRouterFilter.setSink(personVerschmiererTask); personVerschmiererTask.setSink(populationWriterTask); - + populationReaderTask.run(); } - + } diff --git a/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/PendlerMatrixReader.java b/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/PendlerMatrixReader.java index 20126b4a8ed..1d53d1a7aa4 100644 --- a/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/PendlerMatrixReader.java +++ b/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/PendlerMatrixReader.java @@ -37,7 +37,7 @@ import org.matsim.core.scenario.MutableScenario; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.core.utils.io.tabularFileParser.TabularFileHandler; import org.matsim.core.utils.io.tabularFileParser.TabularFileParser; import org.matsim.core.utils.io.tabularFileParser.TabularFileParserConfig; @@ -80,7 +80,7 @@ public void run() { } private void readShape() { - Collection landkreise = ShapeFileReader.getAllFeatures(this.shapeFile); + Collection landkreise = GeoFileReader.getAllFeatures(this.shapeFile); ActivityFacilitiesFactory factory = ((MutableScenario)this.sc).getActivityFacilities().getFactory(); for (SimpleFeature landkreis : landkreise) { Integer gemeindeschluessel = Integer.parseInt((String) landkreis.getAttribute("gemeindesc")); diff --git a/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/Verschmierer.java b/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/Verschmierer.java index 183e69f3e48..4ccba3644f7 100644 --- a/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/Verschmierer.java +++ b/contribs/vsp/src/main/java/playground/vsp/demandde/pendlermatrix/Verschmierer.java @@ -29,25 +29,25 @@ import org.locationtech.jts.geom.Point; import org.matsim.api.core.v01.Coord; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; public class Verschmierer { - + private String filename; - + private Map zones = new HashMap(); private Random random = new Random(); - + public Verschmierer(String filename) { this.filename = filename; readShape(); } private void readShape() { - for (SimpleFeature landkreis : ShapeFileReader.getAllFeatures(filename)) { + for (SimpleFeature landkreis : GeoFileReader.getAllFeatures(filename)) { Integer gemeindeschluessel = Integer.parseInt((String) landkreis.getAttribute("gemeindesc")); zones.put(gemeindeschluessel, (Geometry) landkreis.getDefaultGeometry()); } @@ -72,7 +72,7 @@ public Coord shootIntoSameZoneOrLeaveInPlace(Coord coord) { return coord; } } - + private static Point getRandomPointInFeature(Random rnd, Geometry g) { Point p = null; double x, y; @@ -83,13 +83,13 @@ private static Point getRandomPointInFeature(Random rnd, Geometry g) { } while (!g.contains(p)); return p; } - + private Coord doShoot(Geometry zone) { Coord coord; Point point = getRandomPointInFeature(this.random , zone); coord = new Coord(point.getX(), point.getY()); return coord; } - - + + } diff --git a/contribs/vsp/src/main/java/playground/vsp/demandde/prognose2025/DemandMatrixReader.java b/contribs/vsp/src/main/java/playground/vsp/demandde/prognose2025/DemandMatrixReader.java index a59404b6d23..ba6cd54148d 100644 --- a/contribs/vsp/src/main/java/playground/vsp/demandde/prognose2025/DemandMatrixReader.java +++ b/contribs/vsp/src/main/java/playground/vsp/demandde/prognose2025/DemandMatrixReader.java @@ -41,7 +41,7 @@ import org.matsim.core.utils.geometry.CoordinateTransformation; import org.matsim.core.utils.geometry.geotools.MGC; import org.matsim.core.utils.geometry.transformations.TransformationFactory; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.core.utils.io.tabularFileParser.TabularFileHandler; import org.matsim.core.utils.io.tabularFileParser.TabularFileParser; import org.matsim.core.utils.io.tabularFileParser.TabularFileParserConfig; @@ -157,7 +157,7 @@ public void startRow(String[] row) { } private void readShape() { - Collection landkreise = ShapeFileReader.getAllFeatures(this.shapeFile); + Collection landkreise = GeoFileReader.getAllFeatures(this.shapeFile); final ActivityFacilitiesFactory factory = ((MutableScenario)this.sc).getActivityFacilities().getFactory(); for (SimpleFeature landkreis : landkreise) { Integer gemeindeschluessel = Integer.parseInt((String) landkreis.getAttribute("gemeindesc")); diff --git a/contribs/vsp/src/main/java/playground/vsp/ev/README.md b/contribs/vsp/src/main/java/playground/vsp/ev/README.md index f5bd6a45c42..3bde9544245 100644 --- a/contribs/vsp/src/main/java/playground/vsp/ev/README.md +++ b/contribs/vsp/src/main/java/playground/vsp/ev/README.md @@ -19,6 +19,8 @@ and if there is a charger on the home link, it does not search for a suitable ac The final SoC at the end of the iteration is maintained and transferred as the initial SoC to the next iteration. For this to work, vehicles that represent an EV need to be attached to a vehicle type that is tagged as EV by providing a specific attribute (see `MATSimVehicleWrappingEVSpecificationProvider.class`). +By default, _all_ of these (electric) vehicles are planned by to potentially get charged according to the above described logic. +However, one can prevent this on the vehicle level by `UrbanEVUtils.setChargingDuringActivities(vehicle, false)` when defining the input. ## A few notes to the current state of this package (and it's issues and TODOs) diff --git a/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVModule.java b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVModule.java index 84e59275d7b..cf03625932d 100644 --- a/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVModule.java +++ b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVModule.java @@ -20,6 +20,8 @@ package playground.vsp.ev; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.matsim.contrib.ev.EvModule; import org.matsim.contrib.ev.charging.ChargingModule; import org.matsim.contrib.ev.discharging.DischargingModule; @@ -31,9 +33,6 @@ import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.mobsim.qsim.AbstractQSimModule; - -import com.google.inject.Inject; -import com.google.inject.Singleton; import org.matsim.core.mobsim.qsim.components.QSimComponentsConfigGroup; public class UrbanEVModule extends AbstractModule { @@ -47,13 +46,6 @@ public class UrbanEVModule extends AbstractModule { QSimComponentsConfigGroup qsimComponentsConfig = ConfigUtils.addOrGetModule( config, QSimComponentsConfigGroup.class ); qsimComponentsConfig.addActiveComponent( EvModule.EV_COMPONENT ); -// UrbanEVConfigGroup urbanEVConfig = ConfigUtils.addOrGetModule( config, UrbanEVConfigGroup.class ); - -// if (urbanEVConfig == null) -// throw new IllegalArgumentException( -// "no config group of type " + UrbanEVConfigGroup.GROUP_NAME + " was specified in the config"); - // was this meaningful? I.e. do we want the code to fail if there is no such config group? kai, apr'23 - //standard EV stuff install(new ChargingInfrastructureModule()); install(new ChargingModule()); @@ -62,7 +54,6 @@ public class UrbanEVModule extends AbstractModule { install(new ElectricFleetModule()); //bind custom EVFleet stuff -// bind(ElectricFleetUpdater.class).in(Singleton.class); addControlerListenerBinding().to(ElectricFleetUpdater.class).in( Singleton.class ); // (this takes the matsim modal vehicles for each leg and gives them to the ElectricFleetSpecification. Don't know why it has to be in // this ad-hoc way. kai, apr'23) @@ -74,6 +65,7 @@ protected void configureQSim() { // bind(UrbanVehicleChargingHandler.class); addMobsimScopeEventHandlerBinding().to(UrbanVehicleChargingHandler.class); // (I think that this takes the plugin/plugout activities, and actually initiates the charging. kai, apr'23) + // yes it does, just like the regular VehicleChargingHandler in the ev contrib. schlenther, feb'24. } }); @@ -81,14 +73,6 @@ protected void configureQSim() { addMobsimListenerBinding().to(UrbanEVTripsPlanner.class); // (I think that this inserts the charging activities just before the mobsim starts (i.e. it is not in the plans). kai, apr'23) - //TODO find a better solution for this yyyy yes. We do not want automagic. kai, apr'23 done. kai, apr'23 -// Collection whileChargingActTypes = urbanEVConfig.getWhileChargingActivityTypes().isEmpty() ? -// config.planCalcScore().getActivityTypes() : -// urbanEVConfig.getWhileChargingActivityTypes(); - -// bind(ActivityWhileChargingFinder.class).toInstance(new ActivityWhileChargingFinder(whileChargingActTypes, -// urbanEVConfig.getMinWhileChargingActivityDuration_s())); - bind( ActivityWhileChargingFinder.class ).in( Singleton.class ); //bind custom analysis: @@ -98,16 +82,4 @@ protected void configureQSim() { addControlerListenerBinding().to(ActsWhileChargingAnalyzer.class); } -// private Set getOpenBerlinActivityTypes() { -// Set activityTypes = new HashSet<>(); -// for (long ii = 600; ii <= 97200; ii += 600) { -// activityTypes.add("home_" + ii + ".0"); -// activityTypes.add("work_" + ii + ".0"); -// activityTypes.add("leisure_" + ii + ".0"); -// activityTypes.add("shopping_" + ii + ".0"); -// activityTypes.add("other_" + ii + ".0"); -// } -// return activityTypes; -// } - } diff --git a/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVTripsPlanner.java b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVTripsPlanner.java index b68f4d5bcff..2b9b7dafc6d 100644 --- a/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVTripsPlanner.java +++ b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVTripsPlanner.java @@ -20,20 +20,12 @@ package playground.vsp.ev; -import static java.util.stream.Collectors.*; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.inject.Inject; +import com.sun.istack.Nullable; import jakarta.inject.Provider; - +import one.util.streamex.StreamEx; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import org.apache.logging.log4j.LogManager; @@ -43,18 +35,16 @@ import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; -import org.matsim.api.core.v01.population.Activity; -import org.matsim.api.core.v01.population.Leg; -import org.matsim.api.core.v01.population.Person; -import org.matsim.api.core.v01.population.Plan; -import org.matsim.api.core.v01.population.PlanElement; -import org.matsim.api.core.v01.population.PopulationFactory; +import org.matsim.api.core.v01.population.*; import org.matsim.contrib.common.util.StraightLineKnnFinder; import org.matsim.contrib.ev.charging.ChargingLogic; import org.matsim.contrib.ev.charging.ChargingPower; import org.matsim.contrib.ev.discharging.AuxEnergyConsumption; import org.matsim.contrib.ev.discharging.DriveEnergyConsumption; -import org.matsim.contrib.ev.fleet.*; +import org.matsim.contrib.ev.fleet.ElectricFleetSpecification; +import org.matsim.contrib.ev.fleet.ElectricFleetUtils; +import org.matsim.contrib.ev.fleet.ElectricVehicle; +import org.matsim.contrib.ev.fleet.ElectricVehicleSpecification; import org.matsim.contrib.ev.infrastructure.ChargerSpecification; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructureSpecification; import org.matsim.core.config.Config; @@ -69,11 +59,7 @@ import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.core.population.routes.NetworkRoute; -import org.matsim.core.router.LinkWrapperFacility; -import org.matsim.core.router.SingleModeNetworksCache; -import org.matsim.core.router.StageActivityTypeIdentifier; -import org.matsim.core.router.TripRouter; -import org.matsim.core.router.TripStructureUtils; +import org.matsim.core.router.*; import org.matsim.core.router.util.TravelTime; import org.matsim.core.utils.misc.OptionalTime; import org.matsim.core.utils.timing.TimeInterpretation; @@ -82,15 +68,15 @@ import org.matsim.utils.objectattributes.attributable.AttributesImpl; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleUtils; -import org.matsim.vehicles.Vehicles; import org.matsim.withinday.utils.EditPlans; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; -import com.google.inject.Inject; -import com.sun.istack.Nullable; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; -import one.util.streamex.StreamEx; +import static java.util.stream.Collectors.*; class UrbanEVTripsPlanner implements MobsimInitializedListener { @@ -100,9 +86,6 @@ class UrbanEVTripsPlanner implements MobsimInitializedListener { @Inject Scenario scenario; - @Inject - Vehicles vehicles; - @Inject private SingleModeNetworksCache singleModeNetworksCache; @@ -151,9 +134,10 @@ public void notifyMobsimInitialized(MobsimInitializedEvent e) { if (!(e.getQueueSimulation() instanceof QSim)) { throw new IllegalStateException(UrbanEVTripsPlanner.class + " only works with a mobsim of type " + QSim.class); } + UrbanEVConfigGroup configGroup = (UrbanEVConfigGroup)config.getModules().get(UrbanEVConfigGroup.GROUP_NAME); //collect all selected plans that contain ev legs and map them to the set of ev used Map>> selectedEVPlans = StreamEx.of(scenario.getPopulation().getPersons().values()) - .mapToEntry(p -> p.getSelectedPlan(), p -> getUsedEV(p.getSelectedPlan())) + .mapToEntry(p -> p.getSelectedPlan(), p -> getUsedEVToPreplan(p.getSelectedPlan())) .filterValues(evSet -> !evSet.isEmpty()) .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); @@ -169,16 +153,17 @@ public void notifyMobsimInitialized(MobsimInitializedEvent e) { * @param plan * @return */ - private Set> getUsedEV(Plan plan) { + private Set> getUsedEVToPreplan(Plan plan) { return TripStructureUtils.getLegs(plan) .stream() .map(leg -> VehicleUtils.getVehicleId(plan.getPerson(), leg.getMode())) - .filter(vehicleId -> isEV(vehicleId)) + .filter(vehicleId -> isEVAndToBeChargedWhileActivities(vehicleId)) .collect(toSet()); } - private boolean isEV(Id vehicleId) { - return this.electricFleetSpecification.getVehicleSpecifications().containsKey(Id.create(vehicleId, Vehicle.class)); + private boolean isEVAndToBeChargedWhileActivities(Id vehicleId) { + ElectricVehicleSpecification ev = this.electricFleetSpecification.getVehicleSpecifications().getOrDefault(Id.create(vehicleId, Vehicle.class), null); + return (ev != null && UrbanEVUtils.isChargingDuringActivities(ev)); } private void processPlans(Map>> selectedEVPlans) { diff --git a/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVUtils.java b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVUtils.java new file mode 100644 index 00000000000..4bf58d29f09 --- /dev/null +++ b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVUtils.java @@ -0,0 +1,67 @@ +/* *********************************************************************** * + * project: org.matsim.* + * Controler.java + * * + * *********************************************************************** * + * * + * copyright : (C) 2007 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package playground.vsp.ev; + +import org.matsim.contrib.ev.fleet.ElectricVehicleSpecification; +import org.matsim.vehicles.Vehicle; + +public final class UrbanEVUtils { + + public static final String PLAN_CHARGING_DURING_ACTS_ATTRIBUTE_NAME = "planChargingDuringActivities"; + + /** + * Checks whether {@code electricVehicleSpecification} should be charged during the drivers' activities.
      + * If this is the case, [@code {@link UrbanEVTripsPlanner} will pre-plan charging according to the driver's selected plan.
      + *

      + * Checks for the corresponding attribute with key={@code PLAN_CHARGING_DURING_ACTS_ATTRIBUTE_NAME} in the MATSim input vehicle. + * If the attribute was not provided, true is returned! + * This means that by default, all electricVehicleSpecifications are planned to get charged during activities and not during trips + * (planning for the latter is done by {@code org.matsim.contrib.ev.routing.EVNetworkRoutingModule}. + *

      + * @param electricVehicleSpecification + * @return + */ + public static boolean isChargingDuringActivities(ElectricVehicleSpecification electricVehicleSpecification) { + Object attribute = electricVehicleSpecification.getMatsimVehicle().getAttributes().getAttribute(PLAN_CHARGING_DURING_ACTS_ATTRIBUTE_NAME); + return attribute == null ? true : (Boolean) attribute; + } + + /** + * see description for {@code setChargingDuringActivities(Vehicle vehicle, boolean value)} + * @param electricVehicleSpecification + * @param value + */ + public static void setChargingDuringActivities(ElectricVehicleSpecification electricVehicleSpecification, boolean value) { + setChargingDuringActivities(electricVehicleSpecification.getMatsimVehicle(), value); + } + + /** + * defines whether the vehicle shall be included for planning recharging during the driver's activities (with {@code UrbanEVTripsPlanner}, or not.
      + * In the latter case, recharging may be planned to take place during a trip, if the vehicle is taken for a trip with a mode that is + * routed by {@code org.matsim.contrib.ev.routing.EVNetworkRoutingModule}. + * @param vehicle + * @param value + */ + public static void setChargingDuringActivities(Vehicle vehicle, boolean value) { + vehicle.getAttributes().putAttribute(PLAN_CHARGING_DURING_ACTS_ATTRIBUTE_NAME, value); + } + +} diff --git a/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/SynPopCreator.java b/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/SynPopCreator.java index bc8819bbdc9..3ec676d187d 100644 --- a/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/SynPopCreator.java +++ b/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/SynPopCreator.java @@ -39,7 +39,7 @@ import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.population.PopulationUtils; import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.core.utils.io.IOUtils; import org.matsim.households.Household; import org.matsim.households.HouseholdImpl; @@ -53,12 +53,12 @@ /** * This class creates a full population of a study region (in Germany) based on the Zensus and the Pendlerstatistik. People are assigned * places or residence and with demographic attributes based on the Zensus and with commuter relations based on the Pendlerstatistik. - * + * * @author dziemke */ public class SynPopCreator { private static final Logger LOG = LogManager.getLogger(SynPopCreator.class); - + private static final Random random = MatsimRandom.getLocalInstance(); // Make sure that stream of random variables is reproducible. // Storage objects @@ -71,7 +71,7 @@ public class SynPopCreator { // Optional (links municipality ID to LOR/PLZ IDs in that municipality) private final Map> spatialRefinementZoneIds = new HashMap<>(); private List idsOfMunicipalitiesForSpatialRefinement; - + // Parameters private String outputBase; private List idsOfFederalStatesIncluded; @@ -93,7 +93,7 @@ public class SynPopCreator { private int allEmployees = 0; private int allPersons = 0; private int allStudents = 0; - + public static void main(String[] args) { // Input and output files @@ -104,11 +104,11 @@ public static void main(String[] args) { String[] commuterFilesOutgoing = {commuterFileOutgoing1, commuterFileOutgoing2, commuterFileOutgoing3, commuterFileOutgoing4}; String censusFile = "../../shared-svn/studies/countries/de/open_berlin_scenario/input/zensus_2011/bevoelkerung/csv_Bevoelkerung/Zensus11_Datensatz_Bevoelkerung_BE_BB.csv"; String outputBase = "../../shared-svn/studies/countries/de/open_berlin_scenario/be_5/cemdap_input/505/"; - + // Parameters int numberOfPlansPerPerson = 10; // Note: Set this higher to a value higher than 1 if spatial refinement is used. List idsOfFederalStatesIncluded = Arrays.asList("11", "12"); // 11=Berlin, 12=Brandenburg - + // Default ratios are used for cases where information is missing, which is the case for smaller municipalities. double defaultAdultsToEmployeesRatio = 1.23; // Calibrated based on sum value from Zensus 2011. double defaultCensusEmployeesToCommutersRatio = 2.5; // This is an assumption, oriented on observed values, deliberately chosen slightly too high. @@ -126,14 +126,14 @@ public static void main(String[] args) { demandGeneratorCensus.generateDemand(); } - - public SynPopCreator(String[] commuterFilesOutgoing, String censusFile, String outputBase, int numberOfPlansPerPerson, + + public SynPopCreator(String[] commuterFilesOutgoing, String censusFile, String outputBase, int numberOfPlansPerPerson, List idsOfFederalStatesIncluded, double defaultAdultsToEmployeesRatio, double defaultEmployeesToCommutersRatio) { LogToOutputSaver.setOutputDirectory(outputBase); - + this.outputBase = outputBase; this.numberOfPlansPerPerson = numberOfPlansPerPerson; - + this.idsOfFederalStatesIncluded = idsOfFederalStatesIncluded; this.idsOfFederalStatesIncluded.stream().forEach(e -> { if (e.length()!=2) throw new IllegalArgumentException("Length of the id for each federal state must be equal to 2. This is not the case for "+ e); @@ -141,7 +141,7 @@ public SynPopCreator(String[] commuterFilesOutgoing, String censusFile, String o this.defaultAdultsToEmployeesRatio = defaultAdultsToEmployeesRatio; this.defaultEmployeesToCommutersRatio = defaultEmployeesToCommutersRatio; - + this.population = ScenarioUtils.createScenario(ConfigUtils.createConfig()).getPopulation(); this.households = new HashMap<>(); @@ -158,7 +158,7 @@ public SynPopCreator(String[] commuterFilesOutgoing, String censusFile, String o } } - + public void generateDemand() { if (this.shapeFileForSpatialRefinement != null && this.refinementFeatureKeyInShapefile != null ) { this.idsOfMunicipalitiesForSpatialRefinement.stream().forEach(e->spatialRefinementZoneIds.put(e, new ArrayList<>())); @@ -173,7 +173,7 @@ public void generateDemand() { } int counter = 1; - + for (String munId : relationsMap.keySet()) { // Loop over municipalities from commuter file Map relationsFromMunicipality = relationsMap.get(munId); @@ -300,7 +300,7 @@ public void generateDemand() { LOG.warn("Total number of employees: " + this.allEmployees); LOG.warn("Total population: " + this.allPersons); LOG.warn("Total number of students: " + this.allStudents); - + // Write output files if (this.writeCemdapInputFiles) { writeCemdapHouseholdsFile(this.households, this.outputBase + "households.dat.gz"); @@ -318,8 +318,8 @@ public void generateDemand() { } } } - - + + private Population clonePopulationAndAdjustLocations(Population inputPopulation){ Population clonedPopulation = ScenarioUtils.createScenario(ConfigUtils.createConfig()).getPopulation(); for (Person person : inputPopulation.getPersons().values()) { @@ -334,7 +334,7 @@ private Population clonePopulationAndAdjustLocations(Population inputPopulation) for(CEMDAPPersonAttributes attributeKey : CEMDAPPersonAttributes.values()){ clonedPerson.getAttributes().putAttribute(attributeKey.toString(), person.getAttributes().getAttribute(attributeKey.toString())); } - + // change locations or use spatially refined location if ((boolean) person.getAttributes().getAttribute(CEMDAPPersonAttributes.employed.toString())) { String locationOfWork = (String) person.getAttributes().getAttribute(CEMDAPPersonAttributes.locationOfWork.toString()); @@ -363,7 +363,7 @@ private Population clonePopulationAndAdjustLocations(Population inputPopulation) } - private void createHouseholdsAndPersons(int counter, String municipalityId, int numberOfPersons, Gender gender, int lowerAgeBound, int upperAgeBound, + private void createHouseholdsAndPersons(int counter, String municipalityId, int numberOfPersons, Gender gender, int lowerAgeBound, int upperAgeBound, double adultsToEmployeesRatio, List commuterRelationList) { for (int i = 0; i < numberOfPersons; i++) { this.allPersons++; @@ -375,7 +375,7 @@ private void createHouseholdsAndPersons(int counter, String municipalityId, int household.getAttributes().putAttribute(CEMDAPHouseholdAttributes.homeTSZLocation.toString(), getExactLocation(municipalityId)); household.getAttributes().putAttribute(CEMDAPHouseholdAttributes.numberOfChildren.toString(), 0); // None, ignore them in this version household.getAttributes().putAttribute(CEMDAPHouseholdAttributes.householdStructure.toString(), 1); // 1 = single, no children - + Id personId = Id.create(householdId + "01", Person.class); // TODO Currently only singel-person households Person person = this.population.getFactory().createPerson(personId); @@ -385,14 +385,14 @@ private void createHouseholdsAndPersons(int counter, String municipalityId, int employed = getEmployed(adultsToEmployeesRatio); } person.getAttributes().putAttribute(CEMDAPPersonAttributes.employed.toString(), employed); - + boolean student = false; if (lowerAgeBound < 30 && upperAgeBound > 17 && !employed) { // Younger and older people are never a student, employed people neither student = true; // TODO quite simplistic assumption, which may be improved later allStudents++; - } + } person.getAttributes().putAttribute(CEMDAPPersonAttributes.student.toString(), student); - + if (employed) { allEmployees++; if (commuterRelationList.size() == 0) { // No relations left in list, which employee could choose from @@ -419,22 +419,22 @@ private void createHouseholdsAndPersons(int counter, String municipalityId, int } else { person.getAttributes().putAttribute(CEMDAPPersonAttributes.locationOfSchool.toString(), "-99"); } - + person.getAttributes().putAttribute(CEMDAPPersonAttributes.hasLicense.toString(), true); // for CEMDAP's "driversLicence" variable person.getAttributes().putAttribute(CEMDAPPersonAttributes.gender.toString(), gender.name()); // for CEMDAP's "female" variable person.getAttributes().putAttribute(CEMDAPPersonAttributes.age.toString(), getAgeInBounds(lowerAgeBound, upperAgeBound)); person.getAttributes().putAttribute(CEMDAPPersonAttributes.parent.toString(), false); - + this.population.addPerson(person); - + List> personIds = new ArrayList<>(); // Does in current implementation (only 1 p/hh) not make much sense personIds.add(personId); household.setMemberIds(personIds); this.households.put(householdId, household); } - } - - + } + + private static void scaleRelations(Map relationsFromMunicipality, int employeesMale, int employeesFemale, double defaultEmployeesToCommutersRatio) { // Count all commuters starting in the given municipality @@ -460,7 +460,7 @@ private static void scaleRelations(Map relationsFrom } commutersFemale += relation.getTripsFemale(); } - + // Compute ratios double employeesToCommutersMaleRatio; double employeesToCommutersFemaleRatio; @@ -474,7 +474,7 @@ private static void scaleRelations(Map relationsFrom } else { employeesToCommutersFemaleRatio = defaultEmployeesToCommutersRatio; } - + // Scale for (CommuterRelationV2 relation : relationsFromMunicipality.values()) { relation.setTripsMale((int) Math.ceil(relation.getTripsMale() * employeesToCommutersMaleRatio)); @@ -532,15 +532,15 @@ private String getSpatiallyRefinedZone(String municipalityId) { private static boolean getEmployed(double adultsToEmployeesRatio) { return random.nextDouble() * adultsToEmployeesRatio < 1; } - - + + private static int getAgeInBounds(int lowerBound, int upperBound) { return (int) (lowerBound + random.nextDouble() * (upperBound - lowerBound + 1)); } private Map> readShapeForSpatialRefinement() { - Collection features = ShapeFileReader.getAllFeatures(this.shapeFileForSpatialRefinement); + Collection features = GeoFileReader.getAllFeatures(this.shapeFileForSpatialRefinement); for (SimpleFeature feature : features) { String municipality; @@ -554,14 +554,14 @@ private Map> readShapeForSpatialRefinement() { } return spatialRefinementZoneIds; } - - + + private void writeCemdapHouseholdsFile(Map, Household> households, String fileName) { BufferedWriter bufferedWriterHouseholds = null; try { bufferedWriterHouseholds = IOUtils.getBufferedWriter(fileName); - + for (Household household : households.values()) { int householdId = Integer.parseInt(household.getId().toString()); int numberOfAdults = (Integer) household.getAttributes().getAttribute(CEMDAPHouseholdAttributes.numberOfAdults.toString()); @@ -579,7 +579,7 @@ private void writeCemdapHouseholdsFile(Map, Household> households, + "\t" + 0); bufferedWriterHouseholds.newLine(); } - + } catch (IOException ex) { ex.printStackTrace(); } finally { @@ -594,43 +594,43 @@ private void writeCemdapHouseholdsFile(Map, Household> households, } LOG.info("Households file " + fileName + " written."); } - - + + private void writeCemdapPersonsFile(Population population, String fileName) { BufferedWriter bufferedWriterPersons = null; try { bufferedWriterPersons = IOUtils.getBufferedWriter(fileName); - + for (Person person : population.getPersons().values()) { Attributes attr = person.getAttributes(); int householdId = Integer.parseInt(attr.getAttribute(CEMDAPPersonAttributes.householdId.toString()).toString()); int personId = Integer.parseInt(person.getId().toString()); - + int employed; if ((boolean) attr.getAttribute(CEMDAPPersonAttributes.employed.toString())) { employed = 1; } else { employed = 0; } - + int student; if ((boolean) attr.getAttribute(CEMDAPPersonAttributes.student.toString())) { student = 1; } else { student = 0; } - + int driversLicence; if ((boolean) attr.getAttribute(CEMDAPPersonAttributes.hasLicense.toString())) { driversLicence = 1; } else { driversLicence = 0; } - + int locationOfWork = Integer.parseInt(attr.getAttribute(CEMDAPPersonAttributes.locationOfWork.toString()).toString()); int locationOfSchool = Integer.parseInt(attr.getAttribute(CEMDAPPersonAttributes.locationOfSchool.toString()).toString()); - + int female; if (Gender.valueOf((String) attr.getAttribute(CEMDAPPersonAttributes.gender.toString())) == Gender.male) { female = 0; @@ -639,25 +639,25 @@ private void writeCemdapPersonsFile(Population population, String fileName) { } else { throw new IllegalArgumentException("Gender must either be male or female."); } - + int age = (Integer) attr.getAttribute(CEMDAPPersonAttributes.age.toString()); - + int parent; if ((boolean) attr.getAttribute(CEMDAPPersonAttributes.parent.toString())) { parent = 1; } else { parent = 0; } - + // Altogether this creates 59 columns = number in query file bufferedWriterPersons.write(householdId + "\t" + personId + "\t" + employed + "\t" + student + "\t" + driversLicence + "\t" + locationOfWork + "\t" + locationOfSchool - + "\t" + female + "\t" + age + "\t" + parent + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 - + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 - + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 - + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 - + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 - + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + + "\t" + female + "\t" + age + "\t" + parent + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 ); bufferedWriterPersons.newLine(); } @@ -676,26 +676,26 @@ private void writeCemdapPersonsFile(Population population, String fileName) { LOG.info("Persons file " + fileName + " written."); } - + private static void writeMatsimPlansFile(Population population, String fileName) { PopulationWriter popWriter = new PopulationWriter(population); popWriter.write(fileName); } - - + + // Getters and setters public Population getPopulation() { return this.population; } - + public void setShapeFileForSpatialRefinement(String shapeFileForSpatialRefinement) { this.shapeFileForSpatialRefinement = shapeFileForSpatialRefinement; } - + public void setIdsOfMunicipalitiesForSpatialRefinement(List idsOfMunicipalitiesForSpatialRefinement) { this.idsOfMunicipalitiesForSpatialRefinement = idsOfMunicipalitiesForSpatialRefinement; } - + public void setRefinementFeatureKeyInShapefile(String refinementFeatureKeyInShapefile) { this.refinementFeatureKeyInShapefile = refinementFeatureKeyInShapefile; } @@ -703,7 +703,7 @@ public void setRefinementFeatureKeyInShapefile(String refinementFeatureKeyInShap public void setMunicipalityFeatureKeyInShapefile(String municipalityFeatureKeyInShapefile) { this.municipalityFeatureKeyInShapefile = municipalityFeatureKeyInShapefile; } - + public void setWriteCemdapInputFiles(boolean writeCemdapInputFiles) { this.writeCemdapInputFiles = writeCemdapInputFiles; } @@ -715,15 +715,15 @@ public void setWriteMatsimPlanFiles(boolean writeMatsimPlanFiles) { public void setIncludeChildren(boolean includeChildren) { this.includeChildren = includeChildren; } - + public List getAllPopulations() { if (!memorizeAllPopulations) { throw new RuntimeException("The corresponding container object has not been filles. 'memorizeAllPopulations' needs to be activated."); } return this.allPopulations; } - + public void setMemorizeAllPopulations(boolean memorizeAllPopulations) { this.memorizeAllPopulations = memorizeAllPopulations; } -} \ No newline at end of file +} diff --git a/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/SynPopCreatorChildren.java b/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/SynPopCreatorChildren.java index 9e4d748ddf8..71cec77ea8a 100644 --- a/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/SynPopCreatorChildren.java +++ b/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/SynPopCreatorChildren.java @@ -29,7 +29,7 @@ import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.population.PopulationUtils; import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.utils.objectattributes.ObjectAttributes; import org.opengis.feature.simple.SimpleFeature; import playground.vsp.openberlinscenario.Gender; @@ -40,7 +40,7 @@ /** * This class creates a children-only population of a study region (in Germany) based on the Zensus and the Pendlerstatistik. * Only meant as as supplement ot an already existing adults-only population. - * + * * @author dziemke */ public class SynPopCreatorChildren { @@ -91,14 +91,14 @@ public static void main(String[] args) { public SynPopCreatorChildren(String censusFile, String outputBase, List idsOfFederalStatesIncluded) { LogToOutputSaver.setOutputDirectory(outputBase); - + this.outputBase = outputBase; this.idsOfFederalStatesIncluded = idsOfFederalStatesIncluded; this.idsOfFederalStatesIncluded.stream().forEach(e -> { if (e.length()!=2) throw new IllegalArgumentException("Length of the id for each federal state must be equal to 2. This is not the case for "+ e); }); - + this.population = ScenarioUtils.createScenario(ConfigUtils.createConfig()).getPopulation(); // Read census @@ -107,7 +107,7 @@ public SynPopCreatorChildren(String censusFile, String outputBase, List this.municipalityList = censusReader.getMunicipalityList(); } - + public void generateDemand() { if (this.shapeFileForSpatialRefinement != null && this.refinementFeatureKeyInShapefile != null ) { this.idsOfMunicipalitiesForSpatialRefinement.stream().forEach(e->spatialRefinementZoneIds.put(e, new ArrayList<>())); @@ -122,7 +122,7 @@ public void generateDemand() { } int counter = counterInit; - + for (String munId : municipalityList) { int pop0_2Male = (int) this.municipalities.getAttribute(munId, CensusAttributes.pop0_2Male.toString()); int pop3_5Male = (int) this.municipalities.getAttribute(munId, CensusAttributes.pop3_5Male.toString()); @@ -159,8 +159,8 @@ public void generateDemand() { Population adjustedPopulation = clonePopulationAndAdjustLocations(this.population); writeMatsimPlansFile(adjustedPopulation, this.outputBase + "plans_children.xml.gz"); } - - + + private Population clonePopulationAndAdjustLocations(Population inputPopulation){ Population clonedPopulation = ScenarioUtils.createScenario(ConfigUtils.createConfig()).getPopulation(); for (Person person : inputPopulation.getPersons().values()) { @@ -217,15 +217,15 @@ private String getSpatiallyRefinedZone(String municipalityId) { List spatiallyRefinedZones = this.spatialRefinementZoneIds.get(municipalityId); return spatiallyRefinedZones.get(random.nextInt(spatiallyRefinedZones.size())); } - - + + private static int getAgeInBounds(int lowerBound, int upperBound) { return (int) (lowerBound + random.nextDouble() * (upperBound - lowerBound + 1)); } private Map> readShapeForSpatialRefinement() { - Collection features = ShapeFileReader.getAllFeatures(this.shapeFileForSpatialRefinement); + Collection features = GeoFileReader.getAllFeatures(this.shapeFileForSpatialRefinement); for (SimpleFeature feature : features) { String municipality; @@ -245,21 +245,21 @@ private static void writeMatsimPlansFile(Population population, String fileName) PopulationWriter popWriter = new PopulationWriter(population); popWriter.write(fileName); } - - + + // Getters and setters public Population getPopulation() { return this.population; } - + public void setShapeFileForSpatialRefinement(String shapeFileForSpatialRefinement) { this.shapeFileForSpatialRefinement = shapeFileForSpatialRefinement; } - + public void setIdsOfMunicipalitiesForSpatialRefinement(List idsOfMunicipalitiesForSpatialRefinement) { this.idsOfMunicipalitiesForSpatialRefinement = idsOfMunicipalitiesForSpatialRefinement; } - + public void setRefinementFeatureKeyInShapefile(String refinementFeatureKeyInShapefile) { this.refinementFeatureKeyInShapefile = refinementFeatureKeyInShapefile; } @@ -271,4 +271,4 @@ public void setMunicipalityFeatureKeyInShapefile(String municipalityFeatureKeyIn public void setWriteMatsimPlanFiles(boolean writeMatsimPlanFiles) { this.writeMatsimPlanFiles = writeMatsimPlanFiles; } -} \ No newline at end of file +} diff --git a/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/ZoneAndLOSGeneratorV2.java b/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/ZoneAndLOSGeneratorV2.java index 3949dadde8f..c97a9b2cbf6 100644 --- a/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/ZoneAndLOSGeneratorV2.java +++ b/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/input/ZoneAndLOSGeneratorV2.java @@ -35,7 +35,7 @@ import org.apache.logging.log4j.Logger; import org.locationtech.jts.geom.Geometry; import org.matsim.api.core.v01.Coord; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.core.utils.io.IOUtils; import org.opengis.feature.simple.SimpleFeature; @@ -56,7 +56,7 @@ public class ZoneAndLOSGeneratorV2 { private final Map> zone2ZoneDistanceMap = new HashMap<>(); private final Map> zone2ZoneAdjacencyMap = new HashMap<>(); private final String outputBase; - + // Parameters // private double defaultIntraZoneDistance = 1.72; // in miles; equals 2.76km. private double defaultIntraZoneDistance = 1.; // new, lower value @@ -72,7 +72,7 @@ public class ZoneAndLOSGeneratorV2 { // spatial refinement. Amit Nov'17 private List zoneIdsForSpatialRefinement; // this is filled if shape file for spatial refinement is provided. private double defaultIntraZoneDistanceForSpatialRefinement = Double.NaN; - + public static void main(String[] args) { // Input and output String commuterFileBase = "../../shared-svn/studies/countries/de/open_berlin_scenario/input/pendlerstatistik_2009/"; @@ -86,7 +86,7 @@ public static void main(String[] args) { // Parameters String featureKeyInShapefile = "ID"; - + ZoneAndLOSGeneratorV2 zoneAndLOSGeneratorV2 = new ZoneAndLOSGeneratorV2(commuterFilesOutgoing, shapeFile, outputBase, featureKeyInShapefile); zoneAndLOSGeneratorV2.generateSupply(); } @@ -99,7 +99,7 @@ public ZoneAndLOSGeneratorV2(String[] commuterFilesOutgoing, String shapeFile, S readMunicipalities(commuterFilesOutgoing); readShape(shapeFile, featureKeyInShapefile); } - + public void generateSupply() { compareIdsInShapefileAndCommuterFiles(); computeAndStoreZone2ZoneDistances(); @@ -108,7 +108,7 @@ public void generateSupply() { writeLOSFile("losoffpkam", false); writeLOSFile("lospeakam", true); } - + private void readMunicipalities(String[] commuterFilesOutgoing) { for (String commuterFileOutgoing : commuterFilesOutgoing) { CommuterFileReaderV2 commuterFileReader = new CommuterFileReaderV2(commuterFileOutgoing, "\t"); @@ -118,7 +118,7 @@ private void readMunicipalities(String[] commuterFilesOutgoing) { } private void readShape(String shapeFile, String featureKeyInShapeFile) { - Collection features = ShapeFileReader.getAllFeatures(shapeFile); + Collection features = GeoFileReader.getAllFeatures(shapeFile); for (SimpleFeature feature : features) { String id = (String) feature.getAttribute(featureKeyInShapeFile); Geometry geometry = (Geometry) feature.getDefaultGeometry(); @@ -126,7 +126,7 @@ private void readShape(String shapeFile, String featureKeyInShapeFile) { this.zoneMap.put(id, geometry); } } - + private void compareIdsInShapefileAndCommuterFiles() { LOG.info("Municipality set has " + municipalities.size() + " elements."); LOG.info("Zones set has " + zones.size() + " elements."); @@ -141,7 +141,7 @@ private void compareIdsInShapefileAndCommuterFiles() { } } } - + private void computeAndStoreZone2ZoneDistances() { LOG.info("Start distance and adjacency computations."); LOG.info(this.zones.size() * this.zones.size() + " computations will be performed."); @@ -159,23 +159,23 @@ private void computeAndStoreZone2ZoneDistances() { int adjacent; double distance_mi; double temp = 0.; - + if (originId.equals(destinationId)) { // internal traffic inside zone distance_mi = getIntraZonalDistance(originId) * beelineDistanceFactor; adjacent = 0; } else { Geometry originGeometry = this.zoneMap.get(originId); Coord originCoord = new Coord(originGeometry.getCentroid().getCoordinate().x, originGeometry.getCentroid().getCoordinate().y); - + Geometry destinationGeometry = this.zoneMap.get(destinationId); Coord destinationCoord = new Coord(destinationGeometry.getCentroid().getCoordinate().x, destinationGeometry.getCentroid().getCoordinate().y); - + double distanceX_m = Math.abs(originCoord.getX() - destinationCoord.getX()); double distanceY_m = Math.abs(originCoord.getY() - destinationCoord.getY()); double distance_m = Math.sqrt(distanceX_m * distanceX_m + distanceY_m * distanceY_m); - + distance_mi = distance_m / 1609.344 * beelineDistanceFactor; // Convert from meters to miles - + if (originGeometry.touches(destinationGeometry)) { adjacent = 1; } else { @@ -192,7 +192,7 @@ private void computeAndStoreZone2ZoneDistances() { } LOG.info("Finised distance and adjacency computations."); } - + private void writeZone2ZoneFile() { BufferedWriter bufferedWriterZone2Zone = null; try { @@ -201,7 +201,7 @@ private void writeZone2ZoneFile() { for (String destinationId : this.zones) { double distance_mi = this.zone2ZoneDistanceMap.get(originId).get(destinationId); int adjacent = this.zone2ZoneAdjacencyMap.get(originId).get(destinationId); - + // 4 columns bufferedWriterZone2Zone.write(originId + "\t" + destinationId + "\t" + adjacent + "\t" + distance_mi); bufferedWriterZone2Zone.newLine(); @@ -223,7 +223,7 @@ private void writeZone2ZoneFile() { } System.out.println("Zone2Zone file written."); } - + private void writeZonesFile() { BufferedWriter bufferedWriterZones = null; try { @@ -232,7 +232,7 @@ private void writeZonesFile() { // 45 columns bufferedWriterZones.write(Integer.parseInt(zoneId) + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 - + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0); @@ -254,7 +254,7 @@ private void writeZonesFile() { } System.out.println("Zones file written."); } - + private void writeLOSFile(String filename, boolean isPeak) { BufferedWriter bufferedWriterLos = null; try { @@ -262,15 +262,15 @@ private void writeLOSFile(String filename, boolean isPeak) { double temp = 0.0; for (String originId : this.zones) { for (String destinationId : this.zones) { - + int inSameZone = 0; if (originId.equals(destinationId)) { inSameZone = 1; } - + double distance_mi = this.zone2ZoneDistanceMap.get(originId).get(destinationId); int adjacent = this.zone2ZoneAdjacencyMap.get(originId).get(destinationId); - + double driveAloneIVTT_min; if (isPeak) { driveAloneIVTT_min = distance_mi * durantionDistancePeakRatio_min_mile; @@ -279,13 +279,13 @@ private void writeLOSFile(String filename, boolean isPeak) { } temp = Math.round(driveAloneIVTT_min * 100); // Round to two decimal places driveAloneIVTT_min = temp / 100; - + double driveAloneCost_USD = distance_mi * costDistanceRatio_USD_mile; temp = Math.round(driveAloneCost_USD * 100); // Round to two decimal places driveAloneCost_USD = temp / 100; - + // 14 columns - bufferedWriterLos.write(Integer.parseInt(originId) + "\t" + Integer.parseInt(destinationId) + + bufferedWriterLos.write(Integer.parseInt(originId) + "\t" + Integer.parseInt(destinationId) + "\t" + inSameZone + "\t" + adjacent + "\t" + distance_mi + "\t" + driveAloneIVTT_min + "\t" + 3.1 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + 0 + "\t" + driveAloneCost_USD + "\t" + driveAloneIVTT_min + "\t" + driveAloneCost_USD); @@ -334,22 +334,22 @@ public void setDefaultIntraZoneDistanceForSpatialRefinement(double defaultIntraZ public void setBeelineDistanceFactor(double beelineDistanceFactor) { this.beelineDistanceFactor = beelineDistanceFactor; } - + public void setDurantionDistanceOffPeakRatio_min_mile(double durantionDistanceOffPeakRatio_min_mile) { this.durantionDistanceOffPeakRatio_min_mile = durantionDistanceOffPeakRatio_min_mile; } - + public void setDurantionDistancePeakRatio_min_mile(double durantionDistancePeakRatio_min_mile) { this.durantionDistancePeakRatio_min_mile = durantionDistancePeakRatio_min_mile; } - + public void setCostDistanceRatio_USD_mile(double costDistanceRatio_USD_mile) { this.costDistanceRatio_USD_mile = costDistanceRatio_USD_mile; } public void setShapeFileForRefinement(String shapeFileForSpatialRefinement, String featureKeyInShapeFileForRefinement){ LOG.info("Using spatial refinement..."); - this.zoneIdsForSpatialRefinement = ShapeFileReader + this.zoneIdsForSpatialRefinement = GeoFileReader .getAllFeatures(shapeFileForSpatialRefinement) .stream() .map(feature -> feature.getAttribute(featureKeyInShapeFileForRefinement).toString()) diff --git a/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/output/CemdapOutput2MatsimPlansConverter.java b/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/output/CemdapOutput2MatsimPlansConverter.java index 52ebcdd4f33..b8be4c3a3a8 100644 --- a/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/output/CemdapOutput2MatsimPlansConverter.java +++ b/contribs/vsp/src/main/java/playground/vsp/openberlinscenario/cemdap/output/CemdapOutput2MatsimPlansConverter.java @@ -40,7 +40,7 @@ import org.matsim.api.core.v01.population.PopulationWriter; import org.matsim.core.config.ConfigUtils; import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.utils.objectattributes.ObjectAttributes; import org.opengis.feature.simple.SimpleFeature; @@ -55,7 +55,7 @@ public class CemdapOutput2MatsimPlansConverter { public static final String activityZoneId_attributeKey = "zoneId"; private static final Logger LOG = LogManager.getLogger(CemdapOutput2MatsimPlansConverter.class); - + public static void main(String[] args) throws IOException { // Local use @@ -84,7 +84,7 @@ public static void main(String[] args) throws IOException { boolean assignCoordinatesToActivities = true; // if set to false, the zone id will be attached to activity types and a fake coordinate will be given. boolean combiningGeoms = true; int activityDurationThreshold_s = Integer.MIN_VALUE; - + // Server use if (args.length != 0) { numberOfFirstCemdapOutputFile = Integer.parseInt(args[0]); @@ -106,14 +106,14 @@ public static void main(String[] args) throws IOException { Map shapeFileToFeatureKey = new HashMap<>(); shapeFileToFeatureKey.put(zonalShapeFile, zoneIdTag); - + convert(cemdapDataRoot, numberOfFirstCemdapOutputFile, numberOfPlans, outputDirectory, shapeFileToFeatureKey, allowVariousWorkAndEducationLocations, addStayHomePlan, useLandCoverData, landCoverFile, stopFile, activityFile, simplifyGeometries, combiningGeoms, assignCoordinatesToActivities, activityDurationThreshold_s); } - + public static void convert(String cemdapDataRoot, int numberOfFirstCemdapOutputFile, int numberOfPlans, String outputDirectory, Map shapeFileToFeatureKey, // ensures, unique shape files with same or different featureKey. Amit Nov'17 boolean allowVariousWorkAndEducationLocations, boolean addStayHomePlan, @@ -127,9 +127,9 @@ public static void convert(String cemdapDataRoot, int numberOfFirstCemdapOutputF } LogToOutputSaver.setOutputDirectory(outputDirectory); - + Scenario scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); - + // Find respective stops file Map cemdapStopsFilesMap = new HashMap<>(); for (int planNumber = 0; planNumber < numberOfPlans; planNumber++) { @@ -137,20 +137,20 @@ public static void convert(String cemdapDataRoot, int numberOfFirstCemdapOutputF String cemdapStopsFile = cemdapDataRoot + numberOfCurrentInputFile + "/" + stopFile; cemdapStopsFilesMap.put(planNumber, cemdapStopsFile); } - + // Create ObjectAttributes for each agent and each plan Map personZoneAttributesMap = new HashMap<>(); for (int planNumber = 0; planNumber < numberOfPlans; planNumber++) { ObjectAttributes personZoneAttributes = new ObjectAttributes(); personZoneAttributesMap.put(planNumber, personZoneAttributes); } - + Map, Coord> homeZones = new HashMap<>(); - + // Write all (geographic) features of planning area to a map Map zones = new HashMap<>(); for (Map.Entry entry : shapeFileToFeatureKey.entrySet()) { - for (SimpleFeature feature : ShapeFileReader.getAllFeatures(entry.getKey())) { + for (SimpleFeature feature : GeoFileReader.getAllFeatures(entry.getKey())) { Geometry geometry = (Geometry)feature.getDefaultGeometry(); String shapeId = Cemdap2MatsimUtils.removeLeadingZeroFromString((String) feature.getAttribute(entry.getValue())); // TODO check if removal of leading zero is always valid @@ -164,7 +164,7 @@ public static void convert(String cemdapDataRoot, int numberOfFirstCemdapOutputF } } } - + // Get all persons from activity file // List> personsIds = new LinkedList<>(); Map, String> personHomeMap = new HashMap<>(); @@ -175,14 +175,14 @@ public static void convert(String cemdapDataRoot, int numberOfFirstCemdapOutputF // cemdapPersonParser.parse(cemdapDataRoot + numberOfFirstCemdapOutputFile + "/" + cemdapChildrenFilename, personsIds); CemdapActivityParser cemdapActivityParser = new CemdapActivityParser(); cemdapActivityParser.parse(cemdapDataRoot + numberOfFirstCemdapOutputFile + "/" + activityFile, personHomeMap); - + Population population = scenario.getPopulation(); - + for (int planNumber = 0; planNumber < numberOfPlans; planNumber++) { CemdapStopsParser cemdapStopsParser = new CemdapStopsParser(); cemdapStopsParser.setActivityDurationThreshold_s(activityDurationThreshold_s); cemdapStopsParser.parse(cemdapStopsFilesMap.get(planNumber), planNumber, population, personZoneAttributesMap.get(planNumber), outputDirectory); - + // Commenting this for the time being; it does not do anything if the activity file is not considered on top of the stops file, dz,aa, sep'17 // Add a stay-home plan for those people who have no stops (i.e. no travel) in current stop file // Following is required to add persons who just stays at home. Such persons does not appear in the Stops.out file. dz, aa Oct'17 @@ -247,7 +247,7 @@ public static void convert(String cemdapDataRoot, int numberOfFirstCemdapOutputF // If applicable, add a stay-home plan for everybody if (addStayHomePlan) { numberOfPlans++; - + for (Person person : population.getPersons().values()) { Plan firstPlan = person.getPlans().get(0); // Get first (i.e. presumably "home") activity from agent's first plan @@ -261,7 +261,7 @@ public static void convert(String cemdapDataRoot, int numberOfFirstCemdapOutputF person.addPlan(stayHomePlan); } } - + // Check if number of plans that each agent has is correct for (Person person : scenario.getPopulation().getPersons().values()) { if (person.getPlans().size() < numberOfPlans) { @@ -271,7 +271,7 @@ public static void convert(String cemdapDataRoot, int numberOfFirstCemdapOutputF LOG.warn("Person with ID " + person.getId() + " has more than " + numberOfPlans + " plans"); } } - + // Write population file new File(outputDirectory).mkdir(); new PopulationWriter(scenario.getPopulation(), null).write(outputDirectory + "plans.xml.gz"); diff --git a/contribs/vsp/src/test/java/playground/vsp/ev/UrbanEVIT.java b/contribs/vsp/src/test/java/playground/vsp/ev/UrbanEVIT.java index 823fb89bf83..b96c04fb079 100644 --- a/contribs/vsp/src/test/java/playground/vsp/ev/UrbanEVIT.java +++ b/contribs/vsp/src/test/java/playground/vsp/ev/UrbanEVIT.java @@ -9,7 +9,7 @@ import org.matsim.core.events.EventsUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class UrbanEVIT { @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); @@ -38,8 +38,8 @@ void run() { { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals( EventsFileComparator.Result.FILES_ARE_EQUAL, result ); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result ); } } catch ( Exception ee ) { diff --git a/contribs/vsp/src/test/java/playground/vsp/ev/UrbanEVTests.java b/contribs/vsp/src/test/java/playground/vsp/ev/UrbanEVTests.java index a71bfc6ce8a..fcbff65ded3 100644 --- a/contribs/vsp/src/test/java/playground/vsp/ev/UrbanEVTests.java +++ b/contribs/vsp/src/test/java/playground/vsp/ev/UrbanEVTests.java @@ -1,11 +1,5 @@ package playground.vsp.ev; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -30,6 +24,13 @@ import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; // TODO translate and complete @@ -88,6 +89,12 @@ public static void run() { // EVUtils.setInitialEnergy(scenario.getVehicles().getVehicleTypes().get(Id.create("Not enough time so charging early", VehicleType.class)).getEngineInformation(), // 5.0); + //this guy shall not be pre-plan charging during activities + Id carNotToCharge = VehicleUtils.getVehicleIds( + scenario.getPopulation().getPersons().get(Id.createPersonId("Do not charge during activities"))) + .get(TransportMode.car); + UrbanEVUtils.setChargingDuringActivities(scenario.getVehicles().getVehicles().get(carNotToCharge), false); + ///controler with Urban EV module Controler controler = RunUrbanEVExample.prepareControler(scenario); handler = new UrbanEVTestHandler(); @@ -119,7 +126,7 @@ void testAgentsExecuteSameNumberOfActsAsPlanned() { } } Assertions.assertFalse(fail, - "the following persons do not execute the same amount of activities as they plan to:" + personsWithDifferingActCount); + "the following persons do not execute the same number of activities as they plan to:" + personsWithDifferingActCount); } @Test @@ -174,8 +181,8 @@ void testChargerSelectionShopping() { Assertions.assertEquals(1, plugins.size(), 0); ActivityStartEvent pluginActStart = plugins.get(0); - //starts at 10am at work and travels 8 links à 99s - Assertions.assertEquals(10 * 3600 + 8 * 99, pluginActStart.getTime(), MatsimTestUtils.EPSILON, "wrong charging start time"); + //starts at 10am at work and travels 8 links à 99s + 3s waiting time to enter traffic + Assertions.assertEquals(10 * 3600 + 8 * 99 + 3, pluginActStart.getTime(), MatsimTestUtils.EPSILON, "wrong charging start time"); Assertions.assertEquals("172", pluginActStart.getLinkId().toString(), "wrong charging start location"); List plugouts = this.handler.plugOutCntPerPerson.getOrDefault(Id.createPersonId("Charging during shopping"), List.of()); @@ -186,6 +193,15 @@ void testChargerSelectionShopping() { } + @Test + void testDoNotChargeDuringActivities() { + List plugins = this.handler.plugInCntPerPerson.getOrDefault(Id.createPersonId("Do not charge during activities"), List.of()); + Assertions.assertEquals(0, plugins.size(), 0); + + List plugouts = this.handler.plugOutCntPerPerson.getOrDefault(Id.createPersonId("Do not charge during activities"), List.of()); + Assertions.assertEquals(0, plugouts.size(), 0); + } + @Test void testLongDistance() { List plugins = this.handler.plugInCntPerPerson.getOrDefault(Id.createPersonId("Charger Selection long distance leg"), @@ -193,8 +209,8 @@ void testLongDistance() { Assertions.assertEquals(1, plugins.size(), 0); ActivityStartEvent pluginActStart = plugins.get(0); - //starts at 8 am and travels 19 links à 99s + 3s waiting time to enter traffic - Assertions.assertEquals(8 * 3600 + 19 * 99 + 3, pluginActStart.getTime(), MatsimTestUtils.EPSILON, "wrong charging start time"); + //starts at 8 am and travels 19 links à 99s + 7s waiting time to enter traffic + Assertions.assertEquals(8 * 3600 + 19 * 99 + 7, pluginActStart.getTime(), MatsimTestUtils.EPSILON, "wrong charging start time"); Assertions.assertEquals("89", pluginActStart.getLinkId().toString(), "wrong charging start location"); List plugouts = this.handler.plugOutCntPerPerson.getOrDefault(Id.createPersonId("Charger Selection long distance leg"), @@ -421,6 +437,50 @@ private static void overridePopulation(Scenario scenario) { scenario.getPopulation().addPerson(person2); } + { + Person person2a = factory.createPerson(Id.createPersonId("Do not charge during activities")); + + Plan plan2a = factory.createPlan(); + + Activity home21 = factory.createActivityFromLinkId("home", Id.createLinkId("1")); + home21.setEndTime(8 * 3600); + plan2a.addActivity(home21); + plan2a.addLeg(factory.createLeg(TransportMode.car)); + + Activity work21 = factory.createActivityFromLinkId("work", Id.createLinkId("176")); + work21.setEndTime(10 * 3600); + plan2a.addActivity(work21); + + plan2a.addLeg(factory.createLeg(TransportMode.car)); + + // Activity work22 = factory.createActivityFromLinkId("work", Id.createLinkId("60")); + // work22.setEndTime(12 * 3600); + // plan2a.addActivity(work22); + // + // plan2a.addLeg(factory.createLeg(TransportMode.car)); + + Activity shopping21 = factory.createActivityFromLinkId("shopping", Id.createLinkId("9")); + shopping21.setMaximumDuration(1200); + + plan2a.addActivity(shopping21); + + plan2a.addLeg(factory.createLeg(TransportMode.car)); + + Activity work23 = factory.createActivityFromLinkId("work", Id.createLinkId("5")); + work23.setEndTime(13 * 3600); + plan2a.addActivity(work23); + + plan2a.addLeg(factory.createLeg(TransportMode.car)); + + Activity home22 = factory.createActivityFromLinkId("home", Id.createLinkId("1")); + home22.setEndTime(15 * 3600); + plan2a.addActivity(home22); + person2a.addPlan(plan2a); + person2a.setSelectedPlan(plan2a); + + scenario.getPopulation().addPerson(person2a); + } + { Person person3 = factory.createPerson(Id.createPersonId("Charger Selection long distance leg")); diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java b/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java index 7c3527d08b4..6ddfef69d44 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java @@ -44,7 +44,7 @@ public class PtTripFareEstimatorTest { @Inject private ScoringParametersForPerson params; @Inject - private Map> tripEstimator; + private Map tripEstimator; private PtTripWithDistanceBasedFareEstimator estimator; @BeforeEach diff --git a/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicle.tsv b/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicle.tsv index a3716b50cdc..d39ab8f1eb1 100644 --- a/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicle.tsv +++ b/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicle.tsv @@ -1 +1 @@ -vehicleId carrierId vehicleTypeId tourId tourDuration[s] travelDistance[m] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR] varCostsTime[EUR] varCostsDist[EUR] totalCosts[EUR] +vehicleId carrierId vehicleTypeId tourId tourDuration[s] tourDuration[h] travelDistance[m] travelDistance[km] travelTime[s] travelTime[h] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR] varCostsTime[EUR] varCostsDist[EUR] totalCosts[EUR] diff --git a/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicleType.tsv b/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicleType.tsv index dacd1779828..2125ae69db1 100644 --- a/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicleType.tsv +++ b/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicleType.tsv @@ -1,2 +1,2 @@ -vehicleTypeId nuOfVehicles SumOfTourDuration[s] SumOfTravelDistances[m] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR/veh] varCostsTime[EUR] varCostsDist[EUR] fixedCosts[EUR] totalCosts[EUR] -light 0 0.0 60000.0 0.008 4.7E-4 84.0 0.0 28.2 0.0 28.2 +vehicleTypeId nuOfVehicles SumOfTourDuration[s] SumOfTourDuration[h] SumOfTravelDistances[m] SumOfTravelDistances[km] SumOfTravelTime[s] SumOfTravelTime[h] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR/veh] varCostsTime[EUR] varCostsDist[EUR] fixedCosts[EUR] totalCosts[EUR] +light 0 0.0 0.0 60000.0 60.0 8040.0 2.2333333333333334 0.008 4.7E-4 84.0 0.0 28.2 0.0 28.2 diff --git a/matsim/.gitignore b/matsim/.gitignore index 029e60cc779..a35b8f59ee1 100644 --- a/matsim/.gitignore +++ b/matsim/.gitignore @@ -3,7 +3,6 @@ test/output bin .settings -bin target output out @@ -11,3 +10,4 @@ src/main/java/.gitignore /output_fastCapacityUpdate_false/ /output_fastCapacityUpdate_true/ /nullevents.xml.gz +*.zst \ No newline at end of file diff --git a/matsim/pom.xml b/matsim/pom.xml index dd83fd128b5..dd950efc3be 100644 --- a/matsim/pom.xml +++ b/matsim/pom.xml @@ -127,7 +127,7 @@ it.unimi.dsi fastutil-core - 8.5.12 + 8.5.13 org.geotools @@ -144,6 +144,11 @@ gt-shapefile ${geotools.version} + + org.geotools + gt-geopkg + ${geotools.version} + org.geotools gt-epsg-hsql @@ -339,7 +344,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.6.0 + 3.7.1 src/main/assembly/assembly-release.xml diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java index ba79214ff73..3aa0443b9e0 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java @@ -65,6 +65,8 @@ public class RaptorParameters { private double transferPenaltyPerTravelTimeHour = 0.0; private double transferPenaltyMinimum = Double.NEGATIVE_INFINITY; private double transferPenaltyMaximum = Double.POSITIVE_INFINITY; + + private boolean useTransportModeUtilities = false; private final SwissRailRaptorConfigGroup config; @@ -159,5 +161,13 @@ public double getTransferPenaltyMaximum() { public void setTransferPenaltyMaximum(double transferPenaltyMaximum) { this.transferPenaltyMaximum = transferPenaltyMaximum; } + + public boolean isUseTransportModeUtilities() { + return useTransportModeUtilities; + } + + public void setUseTransportModeUtilities(boolean useTransportModeUtilities) { + this.useTransportModeUtilities = useTransportModeUtilities; + } } 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 09cef257e09..0242f5e91ab 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 @@ -588,6 +588,7 @@ private void exploreRoutes(RaptorParameters parameters, Person person) { CachingTransferProvider transferProvider = this.data.new CachingTransferProvider(); double marginalUtilityOfWaitingPt_utl_s = parameters.getMarginalUtilityOfWaitingPt_utl_s(); + boolean useTransportModeUtilities = parameters.isUseTransportModeUtilities(); int routeIndex = -1; for (int firstRouteStopIndex = this.improvedRouteStopIndices.nextSetBit(0); firstRouteStopIndex >= 0; firstRouteStopIndex = this.improvedRouteStopIndices.nextSetBit(firstRouteStopIndex+1)) { @@ -627,7 +628,8 @@ private void exploreRoutes(RaptorParameters parameters, Person person) { routeIndex = tmpRouteIndex; int firstDepartureTime = (boardingPE.firstDepartureTime == TIME_UNDEFINED) ? currentAgentBoardingTime : boardingPE.firstDepartureTime; - double marginalUtilityOfTravelTime_utl_s = parameters.getMarginalUtilityOfTravelTime_utl_s(boardingPE.toRouteStop.mode); + double marginalUtilityOfTravelTime_utl_s = parameters.getMarginalUtilityOfTravelTime_utl_s( + !useTransportModeUtilities ? boardingPE.toRouteStop.mode : boardingPE.toRouteStop.route.getTransportMode()); transferProvider.reset(boardingPE.transfer); for (int toRouteStopIndex = firstRouteStopIndex + 1; toRouteStopIndex < route.indexFirstRouteStop + route.countRouteStops; toRouteStopIndex++) { diff --git a/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysis2Shp.java b/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysis2Shp.java index 6c5516a6a42..99eeb4c0b20 100644 --- a/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysis2Shp.java +++ b/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysis2Shp.java @@ -32,7 +32,7 @@ import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Link; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.matsim.core.utils.io.IOUtils; import org.matsim.pt.transitSchedule.api.TransitLine; import org.opengis.feature.simple.SimpleFeature; @@ -104,7 +104,7 @@ public static void writePtStop2StopAnalysisByTransitLine2ShpFile( } // TODO: add stops? - ShapeFileWriter.writeGeometries(features, shpFileName); + GeoFileWriter.writeGeometries(features, shpFileName); } public static void writePtStop2StopAnalysisByTransitLine2CsvFile( diff --git a/matsim/src/main/java/org/matsim/core/config/ReflectiveConfigGroup.java b/matsim/src/main/java/org/matsim/core/config/ReflectiveConfigGroup.java index 3a00441d761..55da3166090 100644 --- a/matsim/src/main/java/org/matsim/core/config/ReflectiveConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/config/ReflectiveConfigGroup.java @@ -256,7 +256,10 @@ private static boolean checkType(Type type) { var rawType = pType.getRawType(); if (rawType.equals(List.class) || rawType.equals(Set.class)) { var typeArgument = pType.getActualTypeArguments()[0]; - return typeArgument.equals(String.class) || (typeArgument instanceof Class && ((Class) typeArgument).isEnum()); + return typeArgument.equals(String.class) || + typeArgument.equals(Double.class) || + typeArgument.equals(Integer.class) || + (typeArgument instanceof Class && ((Class) typeArgument).isEnum()); } if (rawType.equals(Class.class)) @@ -412,6 +415,11 @@ private Object fromString(String value, Class type, @Nullable Field paramFiel List> enumConstants = getEnumConstants(paramField); return stream.map(s -> stringToEnumValue(s, enumConstants)).collect(toImmutableSet()); } + if (paramField != null && isCollectionOfDoubleType(paramField)) + return stream.map(Double::parseDouble).collect(toImmutableSet()); + if (paramField != null && isCollectionOfIntegerType(paramField)) + return stream.map(Integer::parseInt).collect(toImmutableSet()); + return stream.collect(toImmutableSet()); } else if (type.equals(List.class)) { if (value.isBlank()) { @@ -422,6 +430,11 @@ private Object fromString(String value, Class type, @Nullable Field paramFiel List> enumConstants = getEnumConstants(paramField); return stream.map(s -> stringToEnumValue(s, enumConstants)).toList(); } + if (paramField != null && isCollectionOfDoubleType(paramField)) + return stream.map(Double::parseDouble).toList(); + if (paramField != null && isCollectionOfIntegerType(paramField)) + return stream.map(Integer::parseInt).toList(); + return stream.toList(); } else if (type.equals(Class.class)) { try { @@ -488,7 +501,9 @@ private String getParamField(Field paramField) { boolean accessible = enforceAccessible(paramField); try { var result = paramField.get(this); - if (result != null && isCollectionOfEnumsWithUniqueStringValues(paramField)) { + if (result != null && (isCollectionOfEnumsWithUniqueStringValues(paramField) || + isCollectionOfDoubleType(paramField) || + isCollectionOfIntegerType(paramField))) { result = ((Collection) result).stream() .map(Object::toString) // map enum values to string .collect(Collectors.toList()); @@ -674,6 +689,30 @@ private static boolean isCollectionOfEnumsWithUniqueStringValues(Field paramFiel return false; } + private static boolean isCollectionOfIntegerType(Field paramField) { + var type = paramField.getGenericType(); + if (type instanceof ParameterizedType pType) { + var rawType = pType.getRawType(); + if (rawType.equals(List.class) || rawType.equals(Set.class)) { + var typeArgument = pType.getActualTypeArguments()[0]; + return typeArgument.equals(Integer.class) || typeArgument.equals(Integer.TYPE); + } + } + return false; + } + + private static boolean isCollectionOfDoubleType(Field paramField) { + var type = paramField.getGenericType(); + if (type instanceof ParameterizedType pType) { + var rawType = pType.getRawType(); + if (rawType.equals(List.class) || rawType.equals(Set.class)) { + var typeArgument = pType.getActualTypeArguments()[0]; + return typeArgument.equals(Double.class) || typeArgument.equals(Double.TYPE); + } + } + return false; + } + private static boolean enumStringsAreUnique(Class enumClass) { T[] enumConstants = enumClass.getEnumConstants(); long uniqueStringValues = Arrays.stream(enumConstants) diff --git a/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java b/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java index 9cbde96f1e3..c84d9eee16c 100644 --- a/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java @@ -79,6 +79,8 @@ public enum CleanIterations { private static final String COMPRESSION_TYPE = "compressionType"; private static final String EVENT_TYPE_TO_CREATE_SCORING_FUNCTIONS = "createScoringFunctionType"; + private static final String MEMORY_OBSERVER_INTERVAL = "memoryObserverInterval"; + /*package*/ static final String MOBSIM = "mobsim"; public enum MobsimType {qsim, JDEQSim, hermes} @@ -109,6 +111,8 @@ public enum MobsimType {qsim, JDEQSim, hermes} private CleanIterations cleanItersAtEnd = CleanIterations.keep; + private int memoryObserverInterval = 60; + public ControllerConfigGroup() { super(GROUP_NAME); } @@ -151,6 +155,7 @@ public final Map getComments() { "to a file. `0' disables snapshots writing completely"); map.put(DUMP_DATA_AT_END, "true if at the end of a run, plans, network, config etc should be dumped to a file"); map.put(CLEAN_ITERS_AT_END, "Defines what should be done with the ITERS directory when a simulation finished successfully"); + map.put(MEMORY_OBSERVER_INTERVAL, "Defines the interval for printing memory usage to the log in [seconds]. Must be positive. Defaults to 60."); return map; } @@ -427,6 +432,17 @@ public EventTypeToCreateScoringFunctions getEventTypeToCreateScoringFunctions() public void setEventTypeToCreateScoringFunctions(EventTypeToCreateScoringFunctions eventTypeToCreateScoringFunctions) { this.eventTypeToCreateScoringFunctions = eventTypeToCreateScoringFunctions; } + + @StringGetter(MEMORY_OBSERVER_INTERVAL) + public int getMemoryObserverInterval() { + return memoryObserverInterval; + } + + @StringSetter(MEMORY_OBSERVER_INTERVAL) + public void setMemoryObserverInterval(int memoryObserverInterval) { + this.memoryObserverInterval = memoryObserverInterval; + } + // --- int writePlansUntilIteration = 1 ; public int getWritePlansUntilIteration() { @@ -450,5 +466,8 @@ protected void checkConsistency(Config config) { log.warn( "this is not recommended, as it might result in a directory containing output from several model runs" ); log.warn( "prefer the options "+OverwriteFileSetting.deleteDirectoryIfExists+" or "+OverwriteFileSetting.failIfDirectoryExists ); } + if(config.controller().getMemoryObserverInterval() < 0) { + log.warn("Memory observer interval is negative. Simulation will most likely crash."); + } } } diff --git a/matsim/src/main/java/org/matsim/core/controler/AbstractController.java b/matsim/src/main/java/org/matsim/core/controler/AbstractController.java index 93c1680a231..a1c008e31ba 100644 --- a/matsim/src/main/java/org/matsim/core/controler/AbstractController.java +++ b/matsim/src/main/java/org/matsim/core/controler/AbstractController.java @@ -73,7 +73,7 @@ final void setupOutputDirectory(OutputDirectoryHierarchy controlerIO) { } protected final void run(final Config config) { - MemoryObserver.start(60); + MemoryObserver.start(config.controller().getMemoryObserverInterval()); MatsimRuntimeModifications.MyRunnable runnable = new MatsimRuntimeModifications.MyRunnable() { @Override public void run() throws MatsimRuntimeModifications.UnexpectedShutdownException { diff --git a/matsim/src/main/java/org/matsim/core/events/EventsUtils.java b/matsim/src/main/java/org/matsim/core/events/EventsUtils.java index 1f2ba7e3d33..7601a9091ad 100644 --- a/matsim/src/main/java/org/matsim/core/events/EventsUtils.java +++ b/matsim/src/main/java/org/matsim/core/events/EventsUtils.java @@ -21,19 +21,26 @@ package org.matsim.core.events; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.controler.Injector; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.*; + +import java.io.File; public final class EventsUtils { + private static final Logger log = LogManager.getLogger(EventsUtils.class); + + /** * Create a events manager instance that guarantees causality of processed events across all handlers. */ - public static EventsManager createEventsManager() { + public static EventsManager createEventsManager() { return new EventsManagerImpl(); - } + } /** * Creates a parallel events manager, with no guarantees for the order of processed events between multiple handlers. @@ -43,11 +50,16 @@ public static EventsManager createParallelEventsManager() { } public static EventsManager createEventsManager(Config config) { - final EventsManager events = Injector.createInjector( config, new EventsManagerModule() ).getInstance( EventsManager.class ); + final EventsManager events = Injector.createInjector(config, new EventsManagerModule()).getInstance(EventsManager.class); // events.initProcessing(); return events; } + public static void readEvents(EventsManager events, String filename) { + new MatsimEventsReader(events).readFile(filename); + } + + /** * The SimStepParallelEventsManagerImpl can handle events from multiple threads. * The (Parallel)EventsMangerImpl cannot, therefore it has to be wrapped into a @@ -58,21 +70,68 @@ public static EventsManager getParallelFeedableInstance(EventsManager events) { return events; } else if (events instanceof ParallelEventsManager) { return events; - } - else if (events instanceof SynchronizedEventsManagerImpl) { + } else if (events instanceof SynchronizedEventsManagerImpl) { return events; } else { return new SynchronizedEventsManagerImpl(events); } } - public static void readEvents( EventsManager events, String filename ) { - new MatsimEventsReader(events).readFile(filename) ; + /** + * Create and write fingerprint file for events. + */ + public static FingerprintEventHandler createEventsFingerprint(String eventFile, String outputFingerprintFile) { + + FingerprintEventHandler handler = EventsFileFingerprintComparator.createFingerprintHandler(eventFile, null); + + EventFingerprint.write(outputFingerprintFile, handler.getEventFingerprint()); + + return handler; + } + + + /** + * Compares existing event file against fingerprint file. This will also create new fingerprint file along the input events. + * + * @param eventFile local events file + * @param compareFingerprintFile path or uri to fingerprint file + * + * @return comparison results + */ + public static ComparisonResult createAndCompareEventsFingerprint(File eventFile, String compareFingerprintFile) { + + String path = eventFile.getPath().replaceFirst("\\.xml[.a-zA-z0-9]*$", ""); + + FingerprintEventHandler handler = EventsFileFingerprintComparator.createFingerprintHandler(eventFile.toString(), compareFingerprintFile); + EventFingerprint.write(path + ".fp.zst", handler.getEventFingerprint()); + + if (handler.getComparisonMessage() != null) + log.warn(handler.getComparisonMessage()); + + return handler.getComparisonResult(); + } + + /** + * Compares existing event file against fingerprint file. This will also create new fingerprint file along the input events. + * + * @throws AssertionError if comparison fails + * @see #createAndCompareEventsFingerprint(File, String) + */ + public static void assertEqualEventsFingerprint(File eventFile, String compareFingerprintFile) { + + String path = eventFile.getPath().replaceFirst("\\.xml[.a-zA-z0-9]*$", ""); + + FingerprintEventHandler handler = EventsFileFingerprintComparator.createFingerprintHandler(eventFile.toString(), compareFingerprintFile); + EventFingerprint.write(path + ".fp.zst", handler.getEventFingerprint()); + + + if (handler.getComparisonResult() != ComparisonResult.FILES_ARE_EQUAL) + throw new AssertionError(handler.getComparisonMessage()); + } - public static EventsFileComparator.Result compareEventsFiles( String filename1, String filename2 ) { - EventsFileComparator.Result result = EventsFileComparator.compare( filename1, filename2 ); - return result ; + public static ComparisonResult compareEventsFiles(String filename1, String filename2) { + return EventsFileComparator.compare(filename1, filename2); } } 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/main/java/org/matsim/core/network/NetworkUtils.java b/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java index 239f189da42..9e98fbe2269 100644 --- a/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java +++ b/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java @@ -1018,4 +1018,8 @@ public static boolean addDisallowedNextLinks(Link link, String mode, List>> mSequences = new TreeMap<>(); - + try (FileInputStream fis = new FileInputStream(this.mpDbfFileName)) { DbaseFileReader r = new DbaseFileReader(fis.getChannel(), true, IOUtils.CHARSET_WINDOWS_ISO88591); // get header indices @@ -190,7 +190,7 @@ private void run2(final Network network) throws Exception { log.trace(" "+MP_ID_NAME+"-->"+mpIdNameIndex); log.trace(" "+MP_SEQNR_NAME+"-->"+mpSeqNrNameIndex); log.trace(" "+MP_TRPELID_NAME+"-->"+mpTrpelIDNameIndex); - + // create mp data structure // TreeMap> log.info(" parsing meneuver paths dbf file..."); @@ -218,7 +218,7 @@ private void run2(final Network network) throws Exception { // TreeMap>> log.info(" parsing meneuver shape file..."); TreeMap, ArrayList>> maneuvers = new TreeMap<>(); - SimpleFeatureSource fs = ShapeFileReader.readDataFile(this.mnShpFileName); + SimpleFeatureSource fs = GeoFileReader.readDataFile(this.mnShpFileName); SimpleFeatureIterator fIt = fs.getFeatures().features(); while (fIt.hasNext()) { SimpleFeature f = fIt.next(); @@ -256,8 +256,8 @@ else if ((featType == 9401) || (featType == 2104)) { int virtualLinksCnt = 0; for (Map.Entry, ArrayList>> entry : maneuvers.entrySet()) { Id nodeId = entry.getKey(); - if (network.getNodes().get(nodeId) == null) { - log.trace(" nodeid="+nodeId+": maneuvers exist for that node but node is missing. Ignoring and proceeding anyway..."); + if (network.getNodes().get(nodeId) == null) { + log.trace(" nodeid="+nodeId+": maneuvers exist for that node but node is missing. Ignoring and proceeding anyway..."); nodesIgnoredCnt++; } else { // node found @@ -282,7 +282,7 @@ else if ((featType == 9401) || (featType == 2104)) { inLink = n.getInLinks().get(Id.create(firstLinkid+"TF", Link.class)); } Link outLink = n.getOutLinks().get(Id.create(otherLinkId+"FT", Link.class)); - if (outLink == null) { + if (outLink == null) { outLink = n.getOutLinks().get(Id.create(otherLinkId+"TF", Link.class)); } if ((inLink != null) && (outLink != null)) { diff --git a/matsim/src/main/java/org/matsim/core/network/io/NetworkReaderTeleatlas.java b/matsim/src/main/java/org/matsim/core/network/io/NetworkReaderTeleatlas.java index 92d71b014bb..c4416bb5531 100644 --- a/matsim/src/main/java/org/matsim/core/network/io/NetworkReaderTeleatlas.java +++ b/matsim/src/main/java/org/matsim/core/network/io/NetworkReaderTeleatlas.java @@ -33,7 +33,7 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.core.api.internal.MatsimSomeReader; import org.matsim.core.network.NetworkUtils; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.opengis.feature.simple.SimpleFeature; import org.opengis.geometry.BoundingBox; @@ -47,7 +47,7 @@ *
    • nw.shp: junction shape file (typically called xyz________nw.shp) *
    • * - * + * * @author balmermi */ public final class NetworkReaderTeleatlas implements MatsimSomeReader { @@ -154,7 +154,7 @@ public final class NetworkReaderTeleatlas implements MatsimSomeReader { /** * Instantiate a new Tele Atlas MultiNet Shapefile reader based on the * junction and the network shape file. - * + * * @param network * MATSim network database in which the reader stores the data * @param jcShpFileName @@ -189,7 +189,7 @@ public void read() throws IOException { /** * Reads Tele Atlas MultiNet junction Shapefile given in * {@link #jcShpFileName}. - * + * *

      * It uses the following feature attributes: *

        @@ -212,7 +212,7 @@ public void read() throws IOException { *
      *

      * The MATSim {@link Node#type} is set as - * + * *
       	 * {@link Node#type} = {@link #NODE_FEATTYP_NAME}+"-"+{@link #NODE_JNCTTYP_NAME}
       	 * 
      @@ -220,7 +220,7 @@ public void read() throws IOException { */ private void readNodesFromJCshp() throws IOException { int nCnt = network.getNodes().size(); - SimpleFeatureSource fs = ShapeFileReader.readDataFile(jcShpFileName); + SimpleFeatureSource fs = GeoFileReader.readDataFile(jcShpFileName); SimpleFeatureIterator fIt = fs.getFeatures().features(); while (fIt.hasNext()) { SimpleFeature f = fIt.next(); @@ -258,7 +258,7 @@ private void readNodesFromJCshp() throws IOException { /** * Reads Tele Atlas MultiNet network Shapefile given in * {@link #nwShpFileName}. - * + * *

      * It uses the following feature attributes: *

        @@ -307,7 +307,7 @@ private void readNodesFromJCshp() throws IOException { * *
      • {@link #LINK_LANES_NAME} (Number of Lanes)
      • *
      - * + * * Conversion rules: *
        *
      • Links that refer to not existing from- or to-link will be ignored @@ -330,21 +330,21 @@ private void readNodesFromJCshp() throws IOException { * {@link #LINK_ID_NAME}+"TF", * {@link #LINK_ID_NAME}+"FT" resp.
      • *
      • The {@link Link#type} is set as: - * + * *
         	 * {@link Link#type} = {@link #LINK_FRCTYP_NAME}+"-"+{@link #LINK_FEATTYP_NAME}+"-"+{@link #LINK_FERRYTYP_NAME}
         	 * 
        - * + * *
      • *
      *

      - * + * * @throws IOException */ private void readLinksFromNWshp() throws IOException { int lCnt = network.getLinks().size(); int ignoreCnt = 0; - SimpleFeatureSource fs = ShapeFileReader.readDataFile(this.nwShpFileName); + SimpleFeatureSource fs = GeoFileReader.readDataFile(this.nwShpFileName); SimpleFeatureIterator fIt = fs.getFeatures().features(); while (fIt.hasNext()) { SimpleFeature f = fIt.next(); @@ -474,7 +474,7 @@ private void readLinksFromNWshp() throws IOException { /** * prints the variable settings to the STDOUT - * + * * @param prefix * a prefix for each line of the STDOUT */ diff --git a/matsim/src/main/java/org/matsim/core/population/PersonUtils.java b/matsim/src/main/java/org/matsim/core/population/PersonUtils.java index 9c64e247d87..8959899a9b5 100644 --- a/matsim/src/main/java/org/matsim/core/population/PersonUtils.java +++ b/matsim/src/main/java/org/matsim/core/population/PersonUtils.java @@ -27,8 +27,12 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.Plan; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; public final class PersonUtils { private PersonUtils() { @@ -225,4 +229,23 @@ public static TreeSet getTravelcards(Person person) { public static boolean isSelected(Plan plan) { return plan.getPerson().getSelectedPlan() == plan; } + + /** + * Attaches vehicle types to a person, so that the router knows which vehicle to use for which mode and person. + * @param modeToVehicleType mode string mapped to vehicle type ids. The provided map is copied and stored as unmodifiable map. + */ + public static void insertVehicleTypesIntoPersonAttributes(Person person, Map> modeToVehicleType ) { + VehicleUtils.insertVehicleTypesIntoPersonAttributes( person, modeToVehicleType ); + } + /** + * Attaches vehicle ids to a person, so that the router knows which vehicle to use for which mode and person. + * + * @param modeToVehicle mode string mapped to vehicle ids. The provided map is copied and stored as unmodifiable map. + * If a mode key already exists in the persons's attributes it is overridden. Otherwise, existing + * and provided values are merged into one map + * We use PersonVehicle Class in order to have a dedicated PersonVehicleAttributeConverter to/from XML + */ + public static void insertVehicleIdsIntoPersonAttributes(Person person, Map> modeToVehicle ) { + VehicleUtils.insertVehicleIdsIntoPersonAttributes( person, modeToVehicle ); + } } diff --git a/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java b/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java index 574f2f76e93..cae206c534b 100644 --- a/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java +++ b/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java @@ -77,6 +77,9 @@ import org.matsim.facilities.ActivityFacility; import org.matsim.utils.objectattributes.attributable.Attributes; import org.matsim.utils.objectattributes.attributable.AttributesUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; /** * @author nagel, ikaddoura @@ -1266,5 +1269,23 @@ public static Person findPerson( Id personId, Scenario scenario ) { return person ; } + /** + * Attaches vehicle types to a person, so that the router knows which vehicle to use for which mode and person. + * @param modeToVehicleType mode string mapped to vehicle type ids. The provided map is copied and stored as unmodifiable map. + */ + public static void insertVehicleTypesIntoPersonAttributes(Person person, Map> modeToVehicleType ) { + VehicleUtils.insertVehicleTypesIntoPersonAttributes( person, modeToVehicleType ); + } + /** + * Attaches vehicle ids to a person, so that the router knows which vehicle to use for which mode and person. + * + * @param modeToVehicle mode string mapped to vehicle ids. The provided map is copied and stored as unmodifiable map. + * If a mode key already exists in the persons's attributes it is overridden. Otherwise, existing + * and provided values are merged into one map + * We use PersonVehicle Class in order to have a dedicated PersonVehicleAttributeConverter to/from XML + */ + public static void insertVehicleIdsIntoPersonAttributes(Person person, Map> modeToVehicle ) { + VehicleUtils.insertVehicleIdsIntoPersonAttributes( person, modeToVehicle ); + } } diff --git a/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealer.java b/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealer.java index b576833d9fd..2522bd2a96e 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealer.java +++ b/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealer.java @@ -57,7 +57,7 @@ public class ReplanningAnnealer implements IterationStartsListener, StartupListe private final ReplanningAnnealerConfigGroup saConfig; private final int innovationStop; private final String sep; - private final EnumMap currentValues; + private final EnumMap> currentValuesPerSubpopulation; private int currentIter; private List header; @Inject @@ -67,7 +67,7 @@ public class ReplanningAnnealer implements IterationStartsListener, StartupListe public ReplanningAnnealer(Config config) { this.config = config; this.saConfig = ConfigUtils.addOrGetModule(config, ReplanningAnnealerConfigGroup.class); - this.currentValues = new EnumMap<>(AnnealParameterOption.class); + this.currentValuesPerSubpopulation = new EnumMap<>(AnnealParameterOption.class); this.innovationStop = getInnovationStop(config); this.sep = config.global().getDefaultDelimiter(); } @@ -83,17 +83,19 @@ private static boolean isInnovationStrategy(String strategyName) { @Override public void notifyStartup(StartupEvent event) { header = new ArrayList<>(); - for (AnnealingVariable av : this.saConfig.getAnnealingVariables().values()) { + for (AnnealingVariable av : this.saConfig.getAllAnnealingVariables()) { if (!av.getAnnealType().equals(AnnealOption.disabled)) { // check and fix initial value if needed checkAndFixStartValue(av, event); - this.currentValues.put(av.getAnnealParameter(), av.getStartValue()); - header.add(av.getAnnealParameter().name()); + var mapPerSubpopulation = this.currentValuesPerSubpopulation.computeIfAbsent(av.getAnnealParameter(),a-> new HashMap<>()); + mapPerSubpopulation.put(av.getSubpopulation(),av.getStartValue()); + String subpopulationString = av.getSubpopulation()!=null? "_"+av.getSubpopulation() :""; + header.add(av.getAnnealParameter().name()+subpopulationString); if (av.getAnnealParameter().equals(AnnealParameterOption.globalInnovationRate)) { header.addAll(this.config.replanning().getStrategySettings().stream() - .filter(s -> Objects.equals(av.getDefaultSubpopulation(), s.getSubpopulation())) - .map(ReplanningConfigGroup.StrategySettings::getStrategyName) + .filter(s -> Objects.equals(av.getSubpopulation(), s.getSubpopulation())) + .map(strategySettings -> strategySettings.getStrategyName()+subpopulationString) .collect(Collectors.toList())); } } else { // if disabled, better remove it @@ -114,34 +116,35 @@ public void notifyStartup(StartupEvent event) { public void notifyIterationStarts(IterationStartsEvent event) { this.currentIter = event.getIteration() - this.config.controller().getFirstIteration(); Map annealStats = new HashMap<>(); - for (AnnealingVariable av : this.saConfig.getAnnealingVariables().values()) { + List allVariables = this.saConfig.getAllAnnealingVariables(); + for (AnnealingVariable av : allVariables) { if (this.currentIter > 0) { switch (av.getAnnealType()) { case geometric: - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> v * av.getShapeFactor()); break; case exponential: int halfLifeIter = av.getHalfLife() <= 1.0 ? (int) (av.getHalfLife() * this.innovationStop) : (int) av.getHalfLife(); - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> av.getStartValue() / Math.exp((double) this.currentIter / halfLifeIter)); break; case msa: - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> av.getStartValue() / Math.pow(this.currentIter, av.getShapeFactor())); break; case sigmoid: halfLifeIter = av.getHalfLife() <= 1.0 ? (int) (av.getHalfLife() * this.innovationStop) : (int) av.getHalfLife(); - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> av.getEndValue() + (av.getStartValue() - av.getEndValue()) / (1 + Math.exp(av.getShapeFactor() * (this.currentIter - halfLifeIter)))); break; case linear: double slope = (av.getStartValue() - av.getEndValue()) / (this.config.controller().getFirstIteration() - this.innovationStop); - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> this.currentIter * slope + av.getStartValue()); break; case disabled: @@ -150,14 +153,16 @@ public void notifyIterationStarts(IterationStartsEvent event) { throw new IllegalArgumentException(); } - log.info("Annealling will be performed on parameter " + av.getAnnealParameter() + - ". Value: " + this.currentValues.get(av.getAnnealParameter())); + log.info("Annealling will be performed on parameter " + av.getAnnealParameter() +". Subpopulation: "+av.getSubpopulation()+ + ". Value: " +this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).get(av.getSubpopulation())); - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> Math.max(v, av.getEndValue())); } - double annealValue = this.currentValues.get(av.getAnnealParameter()); - annealStats.put(av.getAnnealParameter().name(), String.format(Locale.US, "%.4f", annealValue)); + double annealValue = this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).get(av.getSubpopulation()); + String subpopulationString = av.getSubpopulation()!=null? "_"+av.getSubpopulation() :""; + + annealStats.put(av.getAnnealParameter().name()+subpopulationString, String.format(Locale.US, "%.4f", annealValue)); anneal(event, av, annealValue, annealStats); } @@ -178,6 +183,8 @@ private void writeIterationstats(int currentIter, Map annealStat } private void anneal(IterationStartsEvent event, AnnealingVariable av, double annealValue, Map annealStats) { + String subpopulationString = av.getSubpopulation()!=null? "_"+av.getSubpopulation() :""; + switch (av.getAnnealParameter()) { case BrainExpBeta: this.config.scoring().setBrainExpBeta(annealValue); @@ -193,16 +200,17 @@ private void anneal(IterationStartsEvent event, AnnealingVariable av, double ann annealValue = 0.0; } List annealValues = annealReplanning(annealValue, - event.getServices().getStrategyManager(), av.getDefaultSubpopulation()); + event.getServices().getStrategyManager(), av.getSubpopulation()); int i = 0; for (ReplanningConfigGroup.StrategySettings ss : this.config.replanning().getStrategySettings()) { - if (Objects.equals(ss.getSubpopulation(), av.getDefaultSubpopulation())) { - annealStats.put(ss.getStrategyName(), String.format(Locale.US, "%.4f", annealValues.get(i))); + if (Objects.equals(ss.getSubpopulation(), av.getSubpopulation())) { + annealStats.put(ss.getStrategyName()+subpopulationString, String.format(Locale.US, "%.4f", annealValues.get(i))); i++; } } - annealStats.put(av.getAnnealParameter().name(), String.format(Locale.US, "%.4f", // update value in case of switchoff - getStrategyWeights(event.getServices().getStrategyManager(), av.getDefaultSubpopulation(), StratType.allInnovation))); + + annealStats.put(av.getAnnealParameter().name()+subpopulationString, String.format(Locale.US, "%.4f", // update value in case of switchoff + getStrategyWeights(event.getServices().getStrategyManager(), av.getSubpopulation(), StratType.allInnovation))); break; default: throw new IllegalArgumentException(); @@ -328,14 +336,14 @@ private void checkAndFixStartValue(ReplanningAnnealerConfigGroup.AnnealingVariab configValue = this.config.scoring().getLearningRate(); break; case globalInnovationRate: - double innovationWeights = getStrategyWeights(this.config, av.getDefaultSubpopulation(), StratType.allInnovation); - double selectorWeights = getStrategyWeights(this.config, av.getDefaultSubpopulation(), StratType.allSelectors); + double innovationWeights = getStrategyWeights(this.config, av.getSubpopulation(), StratType.allInnovation); + double selectorWeights = getStrategyWeights(this.config, av.getSubpopulation(), StratType.allSelectors); if (innovationWeights + selectorWeights != 1.0) { log.warn("Initial sum of strategy weights different from 1.0. Rescaling."); double innovationStartValue = av.getStartValue() == null ? innovationWeights : av.getStartValue(); - rescaleStartupWeights(innovationStartValue, this.config, event.getServices().getStrategyManager(), av.getDefaultSubpopulation()); + rescaleStartupWeights(innovationStartValue, this.config, event.getServices().getStrategyManager(), av.getSubpopulation()); } - configValue = getStrategyWeights(this.config, av.getDefaultSubpopulation(), StratType.allInnovation); + configValue = getStrategyWeights(this.config, av.getSubpopulation(), StratType.allInnovation); break; default: throw new IllegalArgumentException(); diff --git a/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealerConfigGroup.java b/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealerConfigGroup.java index c3a9421862f..3c13879d7ca 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealerConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealerConfigGroup.java @@ -20,7 +20,11 @@ package org.matsim.core.replanning.annealing; import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; + import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ReflectiveConfigGroup; @@ -81,27 +85,35 @@ public void addParameterSet(final ConfigGroup set) { addAnnealingVariable((AnnealingVariable) set); } - public Map getAnnealingVariables() { - final EnumMap map = - new EnumMap<>(AnnealParameterOption.class); - for (ConfigGroup pars : getParameterSets(AnnealingVariable.GROUP_NAME)) { - final AnnealParameterOption name = ((AnnealingVariable) pars).getAnnealParameter(); - final AnnealingVariable old = map.put(name, (AnnealingVariable) pars); - if (old != null) { - throw new IllegalStateException("several parameter sets for variable " + name); - } - } - return map; - } + public List getAllAnnealingVariables(){ + return getAnnealingVariablesPerSubpopulation().values().stream().flatMap(a->a.values().stream()).collect(Collectors.toList()); + } + public Map> getAnnealingVariablesPerSubpopulation() { + final EnumMap> map = + new EnumMap<>(AnnealParameterOption.class); + for (ConfigGroup pars : getParameterSets(AnnealingVariable.GROUP_NAME)) { + AnnealParameterOption name = ((AnnealingVariable) pars).getAnnealParameter(); + String subpopulation = ((AnnealingVariable) pars).getSubpopulation(); + var paramsPerSubpopulation = map.computeIfAbsent(name,a->new HashMap<>()); + final AnnealingVariable old = paramsPerSubpopulation.put(subpopulation, (AnnealingVariable) pars); + if (old != null) { + throw new IllegalStateException("several parameter sets for variable " + name + " and subpopulation "+subpopulation); + } + } + return map; + } public void addAnnealingVariable(final AnnealingVariable params) { - final AnnealingVariable previous = this.getAnnealingVariables().get(params.getAnnealParameter()); + var previousMap = this.getAnnealingVariablesPerSubpopulation().get(params.getAnnealParameter()); + if (previousMap!=null){ + AnnealingVariable previous = previousMap.get(params.getSubpopulation()); if (previous != null) { final boolean removed = removeParameterSet(previous); if (!removed) { throw new RuntimeException("problem replacing annealing variable"); } } + } super.addParameterSet(params); } @@ -117,11 +129,11 @@ public static class AnnealingVariable extends ReflectiveConfigGroup { private static final String START_VALUE = "startValue"; private static final String END_VALUE = "endValue"; private static final String ANNEAL_TYPE = "annealType"; - private static final String DEFAULT_SUBPOP = "defaultSubpopulation"; + private static final String SUBPOPULATION = "subpopulation"; private static final String ANNEAL_PARAM = "annealParameter"; private static final String HALFLIFE = "halfLife"; private static final String SHAPE_FACTOR = "shapeFactor"; - private String defaultSubpop = null; + private String subpopulation = null; private Double startValue = null; private double endValue = 0.0001; private double shapeFactor = 0.9; @@ -167,14 +179,14 @@ public void setAnnealType(AnnealOption annealType) { this.annealType = annealType; } - @StringGetter(DEFAULT_SUBPOP) - public String getDefaultSubpopulation() { - return this.defaultSubpop; + @StringGetter(SUBPOPULATION) + public String getSubpopulation() { + return this.subpopulation; } - @StringSetter(DEFAULT_SUBPOP) + @StringSetter(SUBPOPULATION) public void setDefaultSubpopulation(String defaultSubpop) { - this.defaultSubpop = defaultSubpop; + this.subpopulation = defaultSubpop; } @StringGetter(ANNEAL_PARAM) @@ -220,7 +232,7 @@ public Map getComments() { map.put(ANNEAL_TYPE, "options: linear, exponential, geometric, msa, sigmoid and disabled (no annealing)."); map.put(ANNEAL_PARAM, "list of config parameters that shall be annealed. Currently supported: globalInnovationRate, BrainExpBeta, PathSizeLogitBeta, learningRate. Default is globalInnovationRate"); - map.put(DEFAULT_SUBPOP, "subpopulation to have the global innovation rate adjusted. Not applicable when annealing with other parameters."); + map.put(SUBPOPULATION, "subpopulation to have the global innovation rate adjusted. Not applicable when annealing with other parameters."); map.put(START_VALUE, "start value for annealing."); map.put(END_VALUE, "final annealing value. When the annealing function reaches this value, further results remain constant."); return map; diff --git a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModule.java b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModule.java index 49da68730c1..1a24567b1dd 100644 --- a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModule.java +++ b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModule.java @@ -82,7 +82,7 @@ public final class NetworkRoutingInclAccessEgressModule implements RoutingModule private final Config config; private static boolean hasWarnedAccessEgress = false; - private RoutingConfigGroup.AccessEgressType accessEgressType; + private final RoutingConfigGroup.AccessEgressType accessEgressType; private final TimeInterpretation timeInterpretation; private final MultimodalLinkChooser multimodalLinkChooser; @@ -102,7 +102,7 @@ public final class NetworkRoutingInclAccessEgressModule implements RoutingModule final MultimodalLinkChooser multimodalLinkChooser) { this.multimodalLinkChooser = multimodalLinkChooser; Gbl.assertNotNull(scenario.getNetwork()); - Gbl.assertIf(scenario.getNetwork().getLinks().size() > 0); // otherwise network for mode probably not defined + Gbl.assertIf(!scenario.getNetwork().getLinks().isEmpty()); // otherwise network for mode probably not defined this.filteredNetwork = filteredNetwork; this.invertedNetwork = invertedNetwork; this.routeAlgo = routeAlgo; @@ -314,9 +314,7 @@ private List computeAccessTripFromFacilityToLinkIfNecessa } private static Activity createInteractionActivity(final Coord interactionCoord, final Id interactionLink, final String mode) { - Activity act = PopulationUtils.createStageActivityFromCoordLinkIdAndModePrefix(interactionCoord, interactionLink, mode); -// act.setMaximumDuration(0.0); // obsolete since this is hard-coded in InteractionActivity - return act; + return PopulationUtils.createStageActivityFromCoordLinkIdAndModePrefix(interactionCoord, interactionLink, mode); } private static void routeBushwhackingLeg(Person person, Leg leg, Coord fromCoord, Coord toCoord, double depTime, @@ -410,9 +408,16 @@ public String toString() { NetworkRoute route = this.populationFactory.getRouteFactories().createRoute(NetworkRoute.class, fromLink.getId(), toLink.getId()); route.setLinkIds(fromLink.getId(), NetworkUtils.getLinkIds(path.links), toLink.getId()); - route.setTravelTime((int) path.travelTime); + + double relPosOnDepartureLink = 1.0; + double relPosOnArrivalLink = 1.0; + + double maxSpeedOnToLink = Math.min(vehicle.getType().getMaximumVelocity(),toLink.getFreespeed()); + double travelTimeEstimateOnToLink = (toLink.getLength() / maxSpeedOnToLink) * relPosOnArrivalLink; + route.setTravelTime((int) (path.travelTime+travelTimeEstimateOnToLink)); + route.setTravelCost(path.travelCost); - route.setDistance(RouteUtils.calcDistance(route, 1.0, 1.0, this.filteredNetwork)); + route.setDistance(RouteUtils.calcDistance(route, relPosOnDepartureLink, relPosOnArrivalLink, this.filteredNetwork)); route.setVehicleId(vehicleId); leg.setRoute(route); travTime = (int) path.travelTime; diff --git a/matsim/src/main/java/org/matsim/core/utils/gis/GeoFileReader.java b/matsim/src/main/java/org/matsim/core/utils/gis/GeoFileReader.java new file mode 100644 index 00000000000..9938a3e1548 --- /dev/null +++ b/matsim/src/main/java/org/matsim/core/utils/gis/GeoFileReader.java @@ -0,0 +1,285 @@ +/* *********************************************************************** * + * project: org.matsim.* + * ShapeFileReader.java + * * + * *********************************************************************** * + * * + * copyright : (C) 2008 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.core.utils.gis; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.geotools.data.DataStore; +import org.geotools.data.DataStoreFinder; +import org.geotools.data.FileDataStore; +import org.geotools.data.FileDataStoreFinder; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.geometry.jts.ReferencedEnvelope; +import org.geotools.geopkg.GeoPkgDataStoreFactory; +import org.geotools.jdbc.JDBCDataStore; +import org.matsim.core.api.internal.MatsimSomeReader; +import org.matsim.core.gbl.Gbl; +import org.matsim.core.utils.misc.Counter; +import org.opengis.feature.Feature; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.Name; +import org.opengis.referencing.crs.CoordinateReferenceSystem; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URL; +import java.util.*; + +/** + * @author glaemmel + * @author dgrether + * @author mrieser // switch to GeoTools 2.7.3 + * @author nkuehnel / MOIA // add gpkg suuport + */ +public class GeoFileReader implements MatsimSomeReader { + private static final Logger log = LogManager.getLogger(GeoFileReader.class); + + private SimpleFeatureSource featureSource = null; + + private ReferencedEnvelope bounds = null; + + private DataStore dataStore = null; + + private SimpleFeatureCollection featureCollection = null; + + private SimpleFeatureType schema = null; + + private Collection featureSet = null; + + private CoordinateReferenceSystem crs; + + public static Collection getAllFeatures(final String filename) { + return getAllFeatures(filename, null); + } + + + public static Collection getAllFeatures(final String filename, Name layerName) { + try { + if(filename.endsWith(".shp")) { + File dataFile = new File(filename); + log.info("will try to read from " + dataFile.getAbsolutePath()); + Gbl.assertIf(dataFile.exists()); + FileDataStore dataStore = FileDataStoreFinder.getDataStore(dataFile); + return getSimpleFeatures(dataStore); + } else if(filename.endsWith(".gpkg")){ + Gbl.assertNotNull(layerName); + Map params = new HashMap<>(); + params.put(GeoPkgDataStoreFactory.DBTYPE.key, "geopkg"); + params.put(GeoPkgDataStoreFactory.DATABASE.key, filename); + params.put("read-only", true); + DataStore dataStore = DataStoreFinder.getDataStore(params); + return getSimpleFeatures(dataStore, layerName); + } else { + throw new RuntimeException("Unsupported file type."); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + + + public static Collection getAllFeatures(final URL url) { + try { + log.info( "will try to read from " + url.getPath() ) ; + return getSimpleFeatures(FileDataStoreFinder.getDataStore(url)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * Read all simple features from a data store. This method makes sure the store is closed afterwards. + * @return list of contained features. + */ + public static List getSimpleFeatures(FileDataStore dataStore) throws IOException { + SimpleFeatureSource featureSource = dataStore.getFeatureSource(); + List featureSet = getSimpleFeatures(featureSource); + dataStore.dispose(); + return featureSet; + } + + /** + * Read all simple features from a data store. This method makes sure the store is closed afterwards. + * @return list of contained features. + */ + public static List getSimpleFeatures(DataStore dataStore, Name layerName) throws IOException { + SimpleFeatureSource featureSource = dataStore.getFeatureSource(layerName); + Gbl.assertNotNull(featureSource); + List featureSet = getSimpleFeatures(featureSource); + dataStore.dispose(); + return featureSet; + } + + private static List getSimpleFeatures(SimpleFeatureSource featureSource) throws IOException { + SimpleFeatureIterator it = featureSource.getFeatures().features(); + List featureSet = new ArrayList<>(); + while (it.hasNext()) { + SimpleFeature ft = it.next(); + featureSet.add(ft); + } + it.close(); + return featureSet; + } + + public Collection readFileAndInitialize(final String filename) { + return readFileAndInitialize(filename, null); + } + + /** + * Reads all Features in the file into the returned Set and initializes the instance of this class. + */ + public Collection readFileAndInitialize(final String filename, Name layerName) throws UncheckedIOException { + try { + this.featureSource = GeoFileReader.readDataFile(filename, layerName); + this.init(); + SimpleFeature ft = null; + SimpleFeatureIterator it = this.featureSource.getFeatures().features(); + this.featureSet = new ArrayList(); + log.info("features to read #" + this.featureSource.getFeatures().size()); + Counter cnt = new Counter("features read #"); + while (it.hasNext()) { + ft = it.next(); + this.featureSet.add(ft); + cnt.incCounter(); + } + cnt.printCounter(); + it.close(); + return this.featureSet; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static SimpleFeatureSource readDataFile(final String filename) { + return readDataFile(filename, null); + } + + /** + * VERY IMPORTANT NOTE
      + *

      + * There are many ways to use that class in a wrong way. The safe way is the following: + *

      + *
       GeoFileReader geoFileReader = new GeoFileReader();
      +		 * geoFileReader.readFileAndInitialize(geoFile); 
      + *

      + * Then, get the features by + *

      + *
       Set<{@link Feature}> features = geoFileReader.getFeatureSet(); 
      + *

      + * If you need metadata you can use + *

      + *
       FeatureSource fs = geoFileReader.getFeatureSource(); 
      + *

      + * to get access to the feature source.
      + * BUT NEVER CALL fs.getFeatures(); !!! It can happen that you will read from disk again!!! + *

      + *

      + * Actually, the whole class must be fixed. But since it is anyway necessary to move to a more recent version of the geotools only this javadoc is added instead. + *

      + *

      + *

      + * The following old doc is kept here: + *

      + *

      + * Provides access to a shape or geopackage file and returns a FeatureSource containing all features. + * Take care access means on disk access, i.e. the FeatureSource is only a pointer to the information + * stored in the file. This can be horribly slow if invoked many times and throw exceptions if two many read + * operations to the same file are performed. In those cases it is recommended to use the method readDataFileToMemory + * of this class. + * + * @param filename File name of a shape or geopackage file (ending in *.shp or *.gpkg) + * @return FeatureSource containing all features. + * @throws UncheckedIOException if the file cannot be found or another error happens during reading + */ + public static SimpleFeatureSource readDataFile(final String filename, Name layerName) throws UncheckedIOException { + try { + log.warn("Unsafe method! store.dispose() is not called from within this method"); + SimpleFeatureSource featureSource; + if(filename.endsWith(".shp")) { + File dataFile = new File(filename); + FileDataStore store = FileDataStoreFinder.getDataStore(dataFile); + featureSource = store.getFeatureSource(); + } else if(filename.endsWith(".gpkg")) { + Gbl.assertNotNull(layerName); + Map params = new HashMap<>(); + params.put(GeoPkgDataStoreFactory.DBTYPE.key, "geopkg"); + params.put(GeoPkgDataStoreFactory.DATABASE.key, filename); + params.put("read-only", true); + + DataStore datastore = DataStoreFinder.getDataStore(params); + featureSource = datastore.getFeatureSource(layerName); + Gbl.assertNotNull(featureSource); + } else { + throw new RuntimeException("Unsupported file type."); + } + return featureSource; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private void init() { + try { + this.bounds = this.featureSource.getBounds(); + this.dataStore = (DataStore) this.featureSource.getDataStore(); + this.featureCollection = this.featureSource.getFeatures(); + this.schema = this.featureSource.getSchema(); + this.crs = this.featureSource.getSchema().getCoordinateReferenceSystem(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public SimpleFeatureSource getFeatureSource() { + return featureSource; + } + + public ReferencedEnvelope getBounds() { + return bounds; + } + + public DataStore getDataStore() { + return dataStore; + } + + public SimpleFeatureCollection getFeatureCollection() { + return featureCollection; + } + + public SimpleFeatureType getSchema() { + return schema; + } + + public Collection getFeatureSet() { + return featureSet; + } + + public CoordinateReferenceSystem getCoordinateSystem(){ + return this.crs; + } + + +} diff --git a/matsim/src/main/java/org/matsim/core/utils/gis/GeoFileWriter.java b/matsim/src/main/java/org/matsim/core/utils/gis/GeoFileWriter.java new file mode 100644 index 00000000000..26296281c56 --- /dev/null +++ b/matsim/src/main/java/org/matsim/core/utils/gis/GeoFileWriter.java @@ -0,0 +1,101 @@ +/* *********************************************************************** * + * project: org.matsim.* + * ShapeFileWriter.java + * * + * *********************************************************************** * + * * + * copyright : (C) 2007 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.core.utils.gis; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.geotools.data.DataStore; +import org.geotools.data.DataStoreFinder; +import org.geotools.data.FileDataStore; +import org.geotools.data.shapefile.ShapefileDataStore; +import org.geotools.data.simple.SimpleFeatureStore; +import org.geotools.feature.DefaultFeatureCollection; +import org.geotools.feature.NameImpl; +import org.geotools.geopkg.GeoPkgDataStoreFactory; +import org.geotools.jdbc.JDBCDataStoreFactory; +import org.matsim.core.api.internal.MatsimSomeWriter; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.Name; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URL; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * This is a simple utility class that provides methods to write Feature instances + * of the geotools framework to an ESRI shape or geopackage file. + * + * @author glaemmel + * @author nkuehnel / MOIA // add gpkg support + */ +public class GeoFileWriter implements MatsimSomeWriter { + + private static final Logger log = LogManager.getLogger(GeoFileWriter.class); + + public static void writeGeometries(final Collection features, final String filename) { + writeGeometries(features, filename, null); + } + + + public static void writeGeometries(final Collection features, final String filename, Name layerName) { + if (features.isEmpty()) { + throw new UncheckedIOException(new IOException("Cannot write empty collection")); + } + + try { + SimpleFeatureStore featureSource; + SimpleFeatureType featureType = features.iterator().next().getFeatureType(); + + if(filename.endsWith(".shp")) { + log.info("Writing shapefile to " + filename); + URL fileURL = (new File(filename)).toURI().toURL(); + FileDataStore datastore = new ShapefileDataStore(fileURL); + datastore.createSchema(featureType); + featureSource = (SimpleFeatureStore) datastore.getFeatureSource(); + } else if(filename.endsWith(".gpkg")){ + Map map = new HashMap<>(); + map.put(GeoPkgDataStoreFactory.DBTYPE.key, GeoPkgDataStoreFactory.DBTYPE.sample); + map.put(GeoPkgDataStoreFactory.DATABASE.key, filename); + map.put(JDBCDataStoreFactory.BATCH_INSERT_SIZE.key, 50); + DataStore datastore = DataStoreFinder.getDataStore(map); + datastore.createSchema(featureType); + if(layerName == null) { + layerName = new NameImpl(featureType.getTypeName()); + } + featureSource = (SimpleFeatureStore) datastore.getFeatureSource(layerName); + } else { + throw new RuntimeException("Unsupported file type."); + } + + DefaultFeatureCollection coll = new DefaultFeatureCollection(); + coll.addAll(features); + + featureSource.addFeatures(coll); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/matsim/src/main/java/org/matsim/core/utils/gis/ShapeFileReader.java b/matsim/src/main/java/org/matsim/core/utils/gis/ShapeFileReader.java index 33bb84d6982..d3ddd7a6c8c 100644 --- a/matsim/src/main/java/org/matsim/core/utils/gis/ShapeFileReader.java +++ b/matsim/src/main/java/org/matsim/core/utils/gis/ShapeFileReader.java @@ -20,28 +20,20 @@ package org.matsim.core.utils.gis; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.geotools.data.DataStore; import org.geotools.data.FileDataStore; -import org.geotools.data.FileDataStoreFinder; import org.geotools.data.simple.SimpleFeatureCollection; -import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.geometry.jts.ReferencedEnvelope; import org.matsim.core.api.internal.MatsimSomeReader; -import org.matsim.core.gbl.Gbl; -import org.matsim.core.utils.misc.Counter; import org.opengis.feature.Feature; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.referencing.crs.CoordinateReferenceSystem; -import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URL; -import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -50,41 +42,17 @@ * @author dgrether * @author mrieser // switch to GeoTools 2.7.3 */ +@Deprecated public class ShapeFileReader implements MatsimSomeReader { - private static final Logger log = LogManager.getLogger(ShapeFileReader.class); - private SimpleFeatureSource featureSource = null; - - private ReferencedEnvelope bounds = null; - - private DataStore dataStore = null; - - private SimpleFeatureCollection featureCollection = null; - - private SimpleFeatureType schema = null; - - private Collection featureSet = null; - - private CoordinateReferenceSystem crs; + private final GeoFileReader geoFileReader = new GeoFileReader(); public static Collection getAllFeatures(final String filename) { - try { - File dataFile = new File(filename); - log.info( "will try to read from " + dataFile.getAbsolutePath() ) ; - Gbl.assertIf( dataFile.exists() ); - return getSimpleFeatures(FileDataStoreFinder.getDataStore(dataFile)); - } catch (IOException e) { - throw new UncheckedIOException(e); - } + return GeoFileReader.getAllFeatures(filename, null); } public static Collection getAllFeatures(final URL url) { - try { - log.info( "will try to read from " + url.getPath() ) ; - return getSimpleFeatures(FileDataStoreFinder.getDataStore(url)); - } catch (IOException e) { - throw new UncheckedIOException(e); - } + return GeoFileReader.getAllFeatures(url); } /** @@ -92,42 +60,14 @@ public static Collection getAllFeatures(final URL url) { * @return list of contained features. */ public static List getSimpleFeatures(FileDataStore dataStore) throws IOException { - SimpleFeatureSource featureSource = dataStore.getFeatureSource(); - - SimpleFeatureIterator it = featureSource.getFeatures().features(); - List featureSet = new ArrayList<>(); - while (it.hasNext()) { - SimpleFeature ft = it.next(); - featureSet.add(ft); - } - it.close(); - dataStore.dispose(); - return featureSet; + return GeoFileReader.getSimpleFeatures(dataStore); } /** * Reads all Features in the file into the returned Set and initializes the instance of this class. */ public Collection readFileAndInitialize(final String filename) throws UncheckedIOException { - try { - this.featureSource = ShapeFileReader.readDataFile(filename); - this.init(); - SimpleFeature ft = null; - SimpleFeatureIterator it = this.featureSource.getFeatures().features(); - this.featureSet = new ArrayList(); - log.info("features to read #" + this.featureSource.getFeatures().size()); - Counter cnt = new Counter("features read #"); - while (it.hasNext()) { - ft = it.next(); - this.featureSet.add(ft); - cnt.incCounter(); - } - cnt.printCounter(); - it.close(); - return this.featureSet; - } catch (IOException e) { - throw new UncheckedIOException(e); - } + return geoFileReader.readFileAndInitialize(filename); } /** @@ -168,54 +108,35 @@ public Collection readFileAndInitialize(final String filename) th * @throws UncheckedIOException if the file cannot be found or another error happens during reading */ public static SimpleFeatureSource readDataFile(final String filename) throws UncheckedIOException { - try { - log.warn("Unsafe method! store.dispose() is not called from within this method"); - File dataFile = new File(filename); - FileDataStore store = FileDataStoreFinder.getDataStore(dataFile); - return store.getFeatureSource(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private void init() { - try { - this.bounds = this.featureSource.getBounds(); - this.dataStore = (DataStore) this.featureSource.getDataStore(); - this.featureCollection = this.featureSource.getFeatures(); - this.schema = this.featureSource.getSchema(); - this.crs = this.featureSource.getSchema().getCoordinateReferenceSystem(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } + return GeoFileReader.readDataFile(filename); } public SimpleFeatureSource getFeatureSource() { - return featureSource; + return geoFileReader.getFeatureSource(); } public ReferencedEnvelope getBounds() { - return bounds; + return geoFileReader.getBounds(); } public DataStore getDataStore() { - return dataStore; + return geoFileReader.getDataStore(); } public SimpleFeatureCollection getFeatureCollection() { - return featureCollection; + return geoFileReader.getFeatureCollection(); } public SimpleFeatureType getSchema() { - return schema; + return geoFileReader.getSchema(); } public Collection getFeatureSet() { - return featureSet; + return geoFileReader.getFeatureSet(); } public CoordinateReferenceSystem getCoordinateSystem(){ - return this.crs; + return geoFileReader.getCoordinateSystem(); } diff --git a/matsim/src/main/java/org/matsim/core/utils/gis/ShapeFileWriter.java b/matsim/src/main/java/org/matsim/core/utils/gis/ShapeFileWriter.java index 2bb2650f814..c0ea83390e9 100644 --- a/matsim/src/main/java/org/matsim/core/utils/gis/ShapeFileWriter.java +++ b/matsim/src/main/java/org/matsim/core/utils/gis/ShapeFileWriter.java @@ -20,19 +20,9 @@ package org.matsim.core.utils.gis; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.geotools.data.shapefile.ShapefileDataStore; -import org.geotools.data.simple.SimpleFeatureStore; -import org.geotools.feature.DefaultFeatureCollection; import org.matsim.core.api.internal.MatsimSomeWriter; import org.opengis.feature.simple.SimpleFeature; -import org.opengis.feature.simple.SimpleFeatureType; -import java.io.File; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.net.URL; import java.util.Collection; /** * This is a simple utility class that provides methods to write Feature instances @@ -40,31 +30,10 @@ * * @author glaemmel */ +@Deprecated public class ShapeFileWriter implements MatsimSomeWriter { - private static final Logger log = LogManager.getLogger(ShapeFileWriter.class); - public static void writeGeometries(final Collection features, final String filename) { - if (features.isEmpty()) { - throw new UncheckedIOException(new IOException("Cannot write empty collection")); - } - log.info("Writing shapefile to " + filename); - try { - URL fileURL = (new File(filename)).toURI().toURL(); - - ShapefileDataStore datastore = new ShapefileDataStore(fileURL); - SimpleFeature feature = features.iterator().next(); - datastore.createSchema(feature.getFeatureType()); - - DefaultFeatureCollection coll = new DefaultFeatureCollection(); - coll.addAll(features); - - SimpleFeatureType featureType = features.iterator().next().getFeatureType(); - datastore.createSchema(featureType); - SimpleFeatureStore featureSource = (SimpleFeatureStore) datastore.getFeatureSource(); - featureSource.addFeatures(coll); - } catch (IOException e) { - throw new RuntimeException(e); - } + GeoFileWriter.writeGeometries(features, filename); } } diff --git a/matsim/src/main/java/org/matsim/run/gui/ExeRunner.java b/matsim/src/main/java/org/matsim/run/gui/ExeRunner.java index 8e2f94c3109..fac8a5df38d 100644 --- a/matsim/src/main/java/org/matsim/run/gui/ExeRunner.java +++ b/matsim/src/main/java/org/matsim/run/gui/ExeRunner.java @@ -97,6 +97,13 @@ public void killProcess() { public void run() { var processBuilder = new ProcessBuilder(); processBuilder.environment().put("MATSIM_GUI", "true"); // add "MATSIM_GUI" to the inherited vars + + // Copy the MATSIM_GUI_ARGS environment variable to the process environment + // these arguments may be used internally by the matsim scenario + if (System.getProperty("MATSIM_GUI_ARGS") != null) { + processBuilder.environment().put("MATSIM_GUI_ARGS", System.getProperty("MATSIM_GUI_ARGS")); + } + if (workingDirectory != null) { processBuilder.directory(new File(workingDirectory)); } diff --git a/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/ComparisonResult.java b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/ComparisonResult.java new file mode 100644 index 00000000000..b5e10fa2d65 --- /dev/null +++ b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/ComparisonResult.java @@ -0,0 +1,6 @@ +package org.matsim.utils.eventsfilecomparison; + +/** + * Result of event file comparison. + */ +public enum ComparisonResult {FILES_ARE_EQUAL, DIFFERENT_NUMBER_OF_TIMESTEPS, DIFFERENT_TIMESTEPS, DIFFERENT_EVENT_ATTRIBUTES, MISSING_EVENT, WRONG_EVENT_COUNT, FILE_ERROR} diff --git a/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventFingerprint.java b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventFingerprint.java new file mode 100644 index 00000000000..74f254f746d --- /dev/null +++ b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventFingerprint.java @@ -0,0 +1,165 @@ +package org.matsim.utils.eventsfilecomparison; + +import it.unimi.dsi.fastutil.floats.FloatArrayList; +import it.unimi.dsi.fastutil.floats.FloatList; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import org.matsim.core.utils.io.IOUtils; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Map; + +/** + * Class holding reduced information about an events file. + * If two such fingerprint are different, one can conclude that the event files are semantically different. + *

      + * The fingerprint is based on the following information: + * - Array of all timestamps + * - Counts of each event type + * - Hash of string concatenation of all event strings + * + * Note: Events with the same timestamp are allowed to occur in any order. + */ +public final class EventFingerprint { + + /** + * Header for version 1, FP/1 + */ + static final int HEADER_V1 = 0x46502f31; + + final FloatList timeArray; + final Object2IntMap eventTypeCounter; + final byte[] hash; + + /** + * Builder for the hash. + */ + private final MessageDigest digest; + + private EventFingerprint(FloatList timeArray, Object2IntMap eventTypeCounter, byte[] hash) { + this.timeArray = timeArray; + this.eventTypeCounter = eventTypeCounter; + this.hash = hash; + this.digest = null; + } + + EventFingerprint() { + this.timeArray = new FloatArrayList(); + this.eventTypeCounter = new Object2IntOpenHashMap<>(); + this.hash = new byte[20]; + + try { + digest = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("Hashing not supported;"); + } + } + + public static void write(String filePath, EventFingerprint eventFingerprint) { + try (DataOutputStream dataOutputStream = new DataOutputStream(IOUtils.getOutputStream(IOUtils.getFileUrl(filePath), false))) { + // Write header and version + dataOutputStream.writeInt(EventFingerprint.HEADER_V1); + + // Write time array size and elements + dataOutputStream.writeInt(eventFingerprint.timeArray.size()); + for (float time : eventFingerprint.timeArray) { + dataOutputStream.writeFloat(time); + } + + // Write event type counter map size and elements + dataOutputStream.writeInt(eventFingerprint.eventTypeCounter.size()); + for (Map.Entry entry : eventFingerprint.eventTypeCounter.entrySet()) { + dataOutputStream.writeUTF(entry.getKey()); + dataOutputStream.writeInt(entry.getValue()); + } + + // Hash should always be computed at this point + assert !Arrays.equals(eventFingerprint.hash, new byte[20]) : "Hash was not computed"; + + // Write byte hash + dataOutputStream.write(eventFingerprint.hash); + + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static EventFingerprint read(String fingerprintPath) throws IOException { + EventFingerprint eventFingerprint; + + try (DataInputStream dataInputStream = new DataInputStream(IOUtils.getInputStream(IOUtils.getFileUrl(fingerprintPath)))) { + // Read header and version + int fileHeader = dataInputStream.readInt(); + + if (fileHeader != EventFingerprint.HEADER_V1) { + throw new IllegalArgumentException("Invalid fingerprint file header"); + } + + // Read time array + int timeArraySize = dataInputStream.readInt(); + FloatList timeArray = new FloatArrayList(); + for (int i = 0; i < timeArraySize; i++) { + timeArray.add(dataInputStream.readFloat()); + } + + // Read event type counter map + int eventTypeCounterSize = dataInputStream.readInt(); + Object2IntMap eventTypeCounter = new Object2IntOpenHashMap<>(); + for (int i = 0; i < eventTypeCounterSize; i++) { + String eventType = dataInputStream.readUTF(); + int count = dataInputStream.readInt(); + eventTypeCounter.put(eventType, count); + } + + // Read string hash + byte[] hash = dataInputStream.readNBytes(20); + + // Create EventFingerprint object + eventFingerprint = new EventFingerprint(timeArray, eventTypeCounter, hash); + } + + return eventFingerprint; + } + + void addTimeStamp(double timestamp) { + timeArray.add((float) timestamp); + } + + void addEventType(String str) { + // Increment the count for the given string + eventTypeCounter.mergeInt(str, 1, Integer::sum); + } + + void addHashCode(String stringToAdd) { + if (stringToAdd == null) { + return; + } + + digest.update(stringToAdd.getBytes(StandardCharsets.UTF_8)); + } + + byte[] computeHash() { + if (this.digest == null) + throw new IllegalStateException("Hash was from from input and can not be computed"); + + byte[] digest = this.digest.digest(); + System.arraycopy(digest, 0, hash, 0, hash.length); + return hash; + } + + @Override + public String toString() { + return "EventFingerprint{" + + "timeArray=" + timeArray.size() + + ", eventTypeCounter=" + eventTypeCounter + + ", hash=" + Arrays.toString(hash) + + '}'; + } +} diff --git a/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventsFileComparator.java b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventsFileComparator.java index 66c44705ca7..0b759f11e95 100644 --- a/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventsFileComparator.java +++ b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventsFileComparator.java @@ -37,8 +37,6 @@ public final class EventsFileComparator { private static final Logger log = LogManager.getLogger(EventsFileComparator.class); - public enum Result { FILES_ARE_EQUAL, DIFFERENT_NUMBER_OF_TIMESTEPS, DIFFERENT_TIMESTEPS, MISSING_EVENT, WRONG_EVENT_COUNT } - private boolean ignoringCoordinates = false; public EventsFileComparator setIgnoringCoordinates( boolean ignoringCoordinates ){ this.ignoringCoordinates = ignoringCoordinates; @@ -62,13 +60,13 @@ public static void main(String[] args) { * * @param filename1 name of the first event file * @param filename2 name of the second event file - * @return Result.FILES_ARE_EQUAL if the events files are equal, or some error code (see {@link Result}) if not. + * @return Result.FILES_ARE_EQUAL if the events files are equal, or some error code (see {@link ComparisonResult}) if not. */ - public static Result compare(final String filename1, final String filename2) { + public static ComparisonResult compare(final String filename1, final String filename2) { return new EventsFileComparator().runComparison( filename1, filename2 ); } - public Result runComparison( final String filename1, final String filename2 ) { + public ComparisonResult runComparison(final String filename1, final String filename2 ) { // (need method name different from pre-existing static method. kai, feb'20) EventsComparator comparator = new EventsComparator( ); @@ -90,8 +88,8 @@ public Result runComparison( final String filename1, final String filename2 ) { e.printStackTrace(); } - Result retCode = comparator.retCode; - if (retCode == Result.FILES_ARE_EQUAL) { + ComparisonResult retCode = comparator.retCode; + if (retCode == ComparisonResult.FILES_ARE_EQUAL) { log.info("Event files are semantically equivalent."); } else { log.warn("Event files differ."); @@ -103,7 +101,7 @@ private static class EventsComparator implements Runnable { private Worker worker1 = null; private Worker worker2 = null; - private volatile Result retCode = null ; + private volatile ComparisonResult retCode = null ; /*package*/ void setWorkers(final Worker w1, final Worker w2) { this.worker1 = w1; @@ -114,13 +112,13 @@ private static class EventsComparator implements Runnable { public void run() { if (this.worker1.getCurrentTime() != this.worker2.getCurrentTime()) { log.warn("Differnt time steps in event files!"); - setExitCode(Result.DIFFERENT_TIMESTEPS); + setExitCode(ComparisonResult.DIFFERENT_TIMESTEPS); return; } if (this.worker1.isFinished() != this.worker2.isFinished()) { log.warn("Events files have different number of time steps!"); - setExitCode(Result.DIFFERENT_NUMBER_OF_TIMESTEPS); + setExitCode(ComparisonResult.DIFFERENT_NUMBER_OF_TIMESTEPS); return; } @@ -141,7 +139,7 @@ public void run() { log.warn("The event:"); log.warn(entry.getKey()); log.warn("is missing in events file:" + worker2.getEventsFile()); - setExitCode(Result.MISSING_EVENT); + setExitCode(ComparisonResult.MISSING_EVENT); problem = true; if (logCounter == 50) { log.warn(Gbl.FUTURE_SUPPRESSED); @@ -152,7 +150,7 @@ public void run() { log.warn( "Wrong event count for: " + entry.getKey() + "\n" + entry.getValue().getCount() + " times in file:" + worker1.getEventsFile() + "\n" + counter.getCount() + " times in file:" + worker2.getEventsFile() ); - setExitCode( Result.WRONG_EVENT_COUNT ); + setExitCode( ComparisonResult.WRONG_EVENT_COUNT ); problem = true; } } @@ -168,7 +166,7 @@ public void run() { log.warn("The event:"); log.warn(e.getKey()); log.warn("is missing in events file:" + worker1.getEventsFile()); - setExitCode(Result.MISSING_EVENT); + setExitCode(ComparisonResult.MISSING_EVENT); problem = true; if (logCounter == 50) { log.warn(Gbl.FUTURE_SUPPRESSED); @@ -182,17 +180,25 @@ public void run() { } if (this.worker1.isFinished()) { - setExitCode(Result.FILES_ARE_EQUAL); + setExitCode(ComparisonResult.FILES_ARE_EQUAL); } } - private void setExitCode(final Result errCode) { + private void setExitCode(final ComparisonResult errCode) { this.retCode= errCode; - if (errCode != Result.FILES_ARE_EQUAL) { + if (errCode != ComparisonResult.FILES_ARE_EQUAL) { this.worker1.interrupt(); this.worker2.interrupt(); } } } + /** + * Don't use this enum. See deprecation message. + * @deprecated Use {@link ComparisonResult} instead. This enum is not used anymore and empty now. + */ + @Deprecated + public enum Result { + } + } diff --git a/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparator.java b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparator.java new file mode 100644 index 00000000000..2152758b215 --- /dev/null +++ b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparator.java @@ -0,0 +1,124 @@ +package org.matsim.utils.eventsfilecomparison; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.events.EventsUtils; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Arrays; + +/** + * Utility class for comparing events and fingerprints. + */ +public final class EventsFileFingerprintComparator { + + private static final Logger log = LogManager.getLogger(EventsFileComparator.class); + + private EventsFileFingerprintComparator() { + } + + + /** + * Create and compare event fingerprints and return the handler holding resulting information. + */ + public static FingerprintEventHandler createFingerprintHandler(final String eventsfile, @Nullable String compareFingerprint) { + + EventFingerprint fp = null; + Exception err = null; + if (compareFingerprint != null) { + try { + fp = EventFingerprint.read(compareFingerprint); + } catch (Exception e) { + log.warn("Could not read compare fingerprint from file: {}", compareFingerprint, e); + fp = new EventFingerprint(); + err = e; + } + } + + FingerprintEventHandler handler = new FingerprintEventHandler(fp); + + EventsManager manager = EventsUtils.createEventsManager(); + + manager.addHandler(handler); + + EventsUtils.readEvents(manager, eventsfile); + + manager.finishProcessing(); + handler.finishProcessing(); + + // File error overwrite any other error + if (err != null) { + handler.setComparisonResult(ComparisonResult.FILE_ERROR); + handler.setComparisonMessage(err.getMessage()); + } + + return handler; + } + + public static ComparisonResult compareFingerprints(final String fp1, final String fp2) { + + EventFingerprint fingerprint1; + EventFingerprint fingerprint2; + try { + fingerprint1 = EventFingerprint.read(fp1); + fingerprint2 = EventFingerprint.read(fp2); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + String logMessage = ""; + //Check if time array size is the same + if (fingerprint1.timeArray.size() != fingerprint2.timeArray.size()) { + logMessage = "Different number of timesteps"; + log.warn(logMessage); + return ComparisonResult.DIFFERENT_NUMBER_OF_TIMESTEPS; + } + + //Check if both time arrays have the same timesteps + if (!Arrays.equals(fingerprint1.timeArray.toFloatArray(), fingerprint2.timeArray.toFloatArray())) { + logMessage = "Different timesteps"; + log.warn(logMessage); + return ComparisonResult.DIFFERENT_TIMESTEPS; + } + + + //Check which event type counts are different among 2 fingerprints + boolean countDiffers = false; + for (Object2IntMap.Entry entry1 : fingerprint1.eventTypeCounter.object2IntEntrySet()) { + String key = entry1.getKey(); + int count1 = entry1.getIntValue(); + int count2 = fingerprint2.eventTypeCounter.getInt(key); + if (count1 != count2) { + countDiffers = true; + + if (!logMessage.isEmpty()) + logMessage += "\n"; + + logMessage += "Count for event type '%s' differs: %d != %d".formatted(key, count1, count2); + } + } + if (countDiffers) { + log.warn(logMessage); + return ComparisonResult.WRONG_EVENT_COUNT; + } + + + //Check if total hash is the same + byte[] hash1 = fingerprint1.hash; + byte[] hash2 = fingerprint2.hash; + if (!Arrays.equals(hash1, hash2)) { + + logMessage = String.format("Difference occurred hash codes hash of first file is %s, hash of second is %s", Arrays.toString(hash1), Arrays.toString(hash2)); + + log.warn(logMessage); + return ComparisonResult.DIFFERENT_EVENT_ATTRIBUTES; + } + + return ComparisonResult.FILES_ARE_EQUAL; + + } +} diff --git a/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/FingerprintEventHandler.java b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/FingerprintEventHandler.java new file mode 100644 index 00000000000..8e12c10a53c --- /dev/null +++ b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/FingerprintEventHandler.java @@ -0,0 +1,212 @@ +package org.matsim.utils.eventsfilecomparison; + +import it.unimi.dsi.fastutil.floats.FloatListIterator; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import org.matsim.api.core.v01.events.Event; +import org.matsim.core.events.handler.BasicEventHandler; + +import java.util.*; + +/** + * Handler for creating and comparing {@link EventFingerprint}. + */ +public final class FingerprintEventHandler implements BasicEventHandler { + + /** + * Generated finger print. + */ + private final EventFingerprint eventFingerprint = new EventFingerprint(); + + /** + * Precision for timestamp comparison. + */ + private static final float EPS = 1e-8f; + + /** + * Accumulate all event strings for same timestamps. + */ + private final List hashAccumulationList = new ArrayList<>(); + + /** + * Existing fingerprint for comparison against event file. Can be null, then no comparison is performed. + */ + private final EventFingerprint compareFingerprint; + + private FloatListIterator iterator = null; + + /** + * Result of the comparison. + */ + private ComparisonResult comparisonResult; + private String comparisonMessage; + + public FingerprintEventHandler() { + this.compareFingerprint = null; + } + + public FingerprintEventHandler(EventFingerprint compareFingerprint) { + this.compareFingerprint = compareFingerprint; + this.comparisonResult = null; + } + + public EventFingerprint getEventFingerprint() { + return eventFingerprint; + } + + public ComparisonResult getComparisonResult() { + return comparisonResult; + } + + void setComparisonResult(ComparisonResult comparisonResult) { + this.comparisonResult = comparisonResult; + } + + public String getComparisonMessage() { + return comparisonMessage; + } + + void setComparisonMessage(String comparisonMessage) { + this.comparisonMessage = comparisonMessage; + } + + @Override + public void handleEvent(Event event) { + + + String lexicographicSortedString = toLexicographicSortedString(event); + + if (compareFingerprint != null) { + if (iterator == null) { + this.iterator = compareFingerprint.timeArray.iterator(); + } + + if (this.comparisonResult == null) { + if (iterator.hasNext()) { + float entry = iterator.nextFloat(); + //Comparing floats with precision + if (Math.abs((float) event.getTime() - entry) >= EPS) { + this.comparisonResult = ComparisonResult.DIFFERENT_TIMESTEPS; + this.comparisonMessage = "Difference occurred in this event time=" + event.getTime() + lexicographicSortedString; + } + } else { + this.comparisonResult = ComparisonResult.DIFFERENT_TIMESTEPS; + this.comparisonMessage = "Additional event time=" + event.getTime() + lexicographicSortedString; + } + } + } + + eventFingerprint.addEventType(event.getEventType()); + + + //First timestep, nothing to accumulate + if (eventFingerprint.timeArray.isEmpty()) { + hashAccumulationList.add(lexicographicSortedString); + } else { + float lastTime = eventFingerprint.timeArray.getFloat(eventFingerprint.timeArray.size() - 1); + //If new time is the same as previous, add to accumulation list, event hash calculation is not ready + if (lastTime == event.getTime()) { + hashAccumulationList.add(lexicographicSortedString); + } + //if new time differs from previous, all hash can be calculated + else { + accumulateHash(); + hashAccumulationList.add(lexicographicSortedString); + } + } + + eventFingerprint.addTimeStamp(event.getTime()); + + //eventFingerprint.addHashCode(lexicographicSortedString); + } + + private void accumulateHash() { + + Collections.sort(hashAccumulationList); + + for (String str : hashAccumulationList) { + eventFingerprint.addHashCode(str); + } + + hashAccumulationList.clear(); + } + + /** + *

      + * Finish processing of the events file and return comparison result (if compare fingerprint was present). + * If the result is not equal it will generate a {@link #comparisonMessage}. + */ + void finishProcessing() { + + if (!hashAccumulationList.isEmpty()) { + accumulateHash(); + } + + byte[] hash = eventFingerprint.computeHash(); + + //hash = eventFingerprint.computeHash(); + + if (compareFingerprint == null) + return; + + //Handling EventTypeCounter differences + for (Object2IntMap.Entry entry1 : compareFingerprint.eventTypeCounter.object2IntEntrySet()) { + String key = entry1.getKey(); + int count1 = entry1.getIntValue(); + int count2 = eventFingerprint.eventTypeCounter.getInt(key); + if (count1 != count2) { + comparisonMessage = comparisonMessage == null ? "" : comparisonMessage; + + comparisonResult = (comparisonResult == null ? ComparisonResult.WRONG_EVENT_COUNT : comparisonResult); + + if (!comparisonMessage.isEmpty()) + comparisonMessage += "\n"; + + comparisonMessage += "Count for event type '%s' differs: %d (in fingerprint) != %d (in events)".formatted(key, count1, count2); + } + } + + // Difference was found in {@link EventFingerprint#eventTypeCounter} + if (comparisonResult != null) { + return; + } + + // only check hash if there was no difference up until here + if (!Arrays.equals(hash, compareFingerprint.hash)) { + comparisonResult = ComparisonResult.DIFFERENT_EVENT_ATTRIBUTES; + comparisonMessage = "Difference occurred in this hash of 2 files"; + return; + } + + comparisonResult = ComparisonResult.FILES_ARE_EQUAL; + } + + private String toLexicographicSortedString(Event event) { + List strings = new ArrayList(); + for (Map.Entry e : event.getAttributes().entrySet()) { + StringBuilder tmp = new StringBuilder(); + final String key = e.getKey(); + + // don't look at certain attributes + switch (key) { + case Event.ATTRIBUTE_X: + case Event.ATTRIBUTE_Y: + case Event.ATTRIBUTE_TIME: + continue; + } + + tmp.append(key); + tmp.append("="); + tmp.append(e.getValue()); + strings.add(tmp.toString()); + } + Collections.sort(strings); + StringBuilder eventStr = new StringBuilder(); + for (String str : strings) { + eventStr.append(" | "); + eventStr.append(str); + } + + eventStr.append(" | "); + return eventStr.toString(); + } +} diff --git a/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/Worker.java b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/Worker.java index 004a0a5e347..81c9cddf32a 100644 --- a/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/Worker.java +++ b/matsim/src/main/java/org/matsim/utils/eventsfilecomparison/Worker.java @@ -144,6 +144,7 @@ private String toLexicographicSortedString(Event event) { switch( key ){ case Event.ATTRIBUTE_X: case Event.ATTRIBUTE_Y: + case Event.ATTRIBUTE_TIME: continue; } } @@ -159,6 +160,7 @@ private String toLexicographicSortedString(Event event) { eventStr.append(" | "); eventStr.append(str); } + eventStr.append(" | ") ; return eventStr.toString(); } diff --git a/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/network/Links2ESRIShape.java b/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/network/Links2ESRIShape.java index f27a0195ba1..d8c8d452eb4 100755 --- a/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/network/Links2ESRIShape.java +++ b/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/network/Links2ESRIShape.java @@ -33,7 +33,7 @@ import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.opengis.feature.simple.SimpleFeature; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -74,7 +74,7 @@ public void write() { features.add(this.featureGenerator.getFeature(link)); } log.info("writing features to shape file... " + this.filename); - ShapeFileWriter.writeGeometries(features, this.filename); + GeoFileWriter.writeGeometries(features, this.filename); log.info("done writing shape file."); } diff --git a/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/network/Nodes2ESRIShape.java b/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/network/Nodes2ESRIShape.java index 90b48753450..003c08d7a34 100644 --- a/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/network/Nodes2ESRIShape.java +++ b/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/network/Nodes2ESRIShape.java @@ -35,7 +35,7 @@ import org.matsim.core.scenario.MutableScenario; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.opengis.feature.simple.SimpleFeature; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -56,11 +56,11 @@ public class Nodes2ESRIShape { private final String filename; private SimpleFeatureBuilder builder; - + public Nodes2ESRIShape(final Network network, final String filename, final String coordinateSystem) { this(network, filename, MGC.getCRS(coordinateSystem)); } - + public Nodes2ESRIShape(Network network, String filename, CoordinateReferenceSystem crs) { this.network = network; this.filename = filename; @@ -72,7 +72,7 @@ public void write() { for (Node node : NetworkUtils.getSortedNodes(this.network)) { features.add(getFeature(node)); } - ShapeFileWriter.writeGeometries(features, this.filename); + GeoFileWriter.writeGeometries(features, this.filename); } diff --git a/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/plans/SelectedPlans2ESRIShape.java b/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/plans/SelectedPlans2ESRIShape.java index dfaee197ecc..f40dc653e51 100755 --- a/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/plans/SelectedPlans2ESRIShape.java +++ b/matsim/src/main/java/org/matsim/utils/gis/matsim2esri/plans/SelectedPlans2ESRIShape.java @@ -51,7 +51,7 @@ import org.matsim.core.scenario.MutableScenario; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileWriter; +import org.matsim.core.utils.gis.GeoFileWriter; import org.opengis.feature.simple.SimpleFeature; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -112,7 +112,7 @@ public void write() { drawOutputSample(); if (this.writeActs) { writeActs(); - } + } if (this.writeLegs) { writeLegs(); } @@ -143,7 +143,7 @@ private void writeActs() throws IOException { } } - ShapeFileWriter.writeGeometries(fts, outputFile); + GeoFileWriter.writeGeometries(fts, outputFile); } private void writeLegs() throws IOException { @@ -164,7 +164,7 @@ private void writeLegs() throws IOException { } } } - ShapeFileWriter.writeGeometries(fts, outputFile); + GeoFileWriter.writeGeometries(fts, outputFile); } private SimpleFeature getActFeature(final String id, final Activity act) { @@ -176,7 +176,7 @@ private SimpleFeature getActFeature(final String id, final Activity act) { double ry = MatsimRandom.getRandom().nextDouble() * this.actBlurFactor; Coord cc = this.network.getLinks().get(act.getLinkId()).getCoord(); Coord c = new Coord(cc.getX() + rx, cc.getY() + ry); - + try { return this.actBuilder.buildFeature(null, new Object [] {MGC.coord2Point(c), id, type, linkId, startTime, endTime}); } catch (IllegalArgumentException e) { @@ -235,7 +235,7 @@ private void initFeatureType() { actBuilder.add("LINK_ID", String.class); actBuilder.add("START_TIME", Double.class); actBuilder.add("END_TIME", Double.class); - + SimpleFeatureTypeBuilder legBuilder = new SimpleFeatureTypeBuilder(); legBuilder.setName("leg"); legBuilder.setCRS(this.crs); diff --git a/matsim/src/main/java/org/matsim/utils/gis/shp2matsim/ShpGeometryUtils.java b/matsim/src/main/java/org/matsim/utils/gis/shp2matsim/ShpGeometryUtils.java index bee189e3e24..4c5d56e9f98 100644 --- a/matsim/src/main/java/org/matsim/utils/gis/shp2matsim/ShpGeometryUtils.java +++ b/matsim/src/main/java/org/matsim/utils/gis/shp2matsim/ShpGeometryUtils.java @@ -29,11 +29,11 @@ import org.locationtech.jts.geom.prep.PreparedGeometryFactory; import org.matsim.api.core.v01.Coord; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; public class ShpGeometryUtils { public static List loadGeometries(URL url) { - return ShapeFileReader.getAllFeatures(url) + return GeoFileReader.getAllFeatures(url) .stream() .map(sf -> (Geometry)sf.getDefaultGeometry()) .collect(Collectors.toList()); @@ -41,7 +41,7 @@ public static List loadGeometries(URL url) { public static List loadPreparedGeometries(URL url) { PreparedGeometryFactory factory = new PreparedGeometryFactory(); - return ShapeFileReader.getAllFeatures(url) + return GeoFileReader.getAllFeatures(url) .stream() .map(sf -> factory.create((Geometry)sf.getDefaultGeometry())) .collect(Collectors.toList()); diff --git a/matsim/src/main/java/org/matsim/utils/objectattributes/ObjectAttributesConverter.java b/matsim/src/main/java/org/matsim/utils/objectattributes/ObjectAttributesConverter.java index d8d8f8e6f3d..52a342140d0 100644 --- a/matsim/src/main/java/org/matsim/utils/objectattributes/ObjectAttributesConverter.java +++ b/matsim/src/main/java/org/matsim/utils/objectattributes/ObjectAttributesConverter.java @@ -64,6 +64,7 @@ public ObjectAttributesConverter() { this.converters.put(PersonVehicles.class.getName(), new PersonVehiclesAttributeConverter()); this.converters.put(DisallowedNextLinks.class.getName(), new DisallowedNextLinksAttributeConverter()); this.converters.put(PersonVehicleTypes.class.getName(), new PersonVehicleTypesAttributeConverter()); + this.converters.put(StringDoubleMap.class.getName(), new StringDoubleMapConverter()); } //this is for reading diff --git a/matsim/src/main/java/org/matsim/utils/objectattributes/StringDoubleMap.java b/matsim/src/main/java/org/matsim/utils/objectattributes/StringDoubleMap.java new file mode 100644 index 00000000000..4125ea0e1dc --- /dev/null +++ b/matsim/src/main/java/org/matsim/utils/objectattributes/StringDoubleMap.java @@ -0,0 +1,14 @@ +package org.matsim.utils.objectattributes; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class StringDoubleMap extends LinkedHashMap { + public StringDoubleMap() { + super(); + } + + public StringDoubleMap(Map map) { + super(map); + } +} diff --git a/matsim/src/main/java/org/matsim/utils/objectattributes/attributeconverters/StringConverter.java b/matsim/src/main/java/org/matsim/utils/objectattributes/attributeconverters/StringConverter.java index 07ede6e8bd5..bf9a209818a 100644 --- a/matsim/src/main/java/org/matsim/utils/objectattributes/attributeconverters/StringConverter.java +++ b/matsim/src/main/java/org/matsim/utils/objectattributes/attributeconverters/StringConverter.java @@ -21,6 +21,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.matsim.utils.objectattributes.AttributeConverter; @@ -29,19 +30,15 @@ * @author mrieser */ public class StringConverter implements AttributeConverter { - private final Map stringCache = new HashMap(1000); + private final Map stringCache = new ConcurrentHashMap<>(1000); + @Override public String convert(String value) { - String s = this.stringCache.get(value); - if (s == null) { - s = value; - this.stringCache.put(s, s); - } - return s; + return stringCache.computeIfAbsent(value, k -> k); } @Override public String convertToString(Object o) { return (String) o; } -} \ No newline at end of file +} diff --git a/matsim/src/main/java/org/matsim/utils/objectattributes/attributeconverters/StringDoubleMapConverter.java b/matsim/src/main/java/org/matsim/utils/objectattributes/attributeconverters/StringDoubleMapConverter.java new file mode 100644 index 00000000000..06578bdc186 --- /dev/null +++ b/matsim/src/main/java/org/matsim/utils/objectattributes/attributeconverters/StringDoubleMapConverter.java @@ -0,0 +1,38 @@ +package org.matsim.utils.objectattributes.attributeconverters; + +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.utils.objectattributes.AttributeConverter; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.MapType; +import com.fasterxml.jackson.databind.type.TypeFactory; +import org.matsim.utils.objectattributes.StringDoubleMap; + +public class StringDoubleMapConverter implements AttributeConverter { + private static final Logger LOG = LogManager.getLogger(StringDoubleMapConverter.class); + private static final ObjectMapper mapper = new ObjectMapper(); + private static final MapType mapType = TypeFactory.defaultInstance().constructMapType(Map.class, String.class, + Double.class); + + @Override + public StringDoubleMap convert(String value) { + try { + return new StringDoubleMap(mapper.readValue(value, mapType)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + @Override + public String convertToString(Object o) { + if (!(o instanceof StringDoubleMap)) { + LOG.error("Object is not of type StringDoubleMap: {}", o.getClass()); + return null; + } + + return new StringStringMapConverter().convertToString(o); + } +} diff --git a/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java b/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java index 0141e814600..6c0a9b289ba 100644 --- a/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java +++ b/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java @@ -141,9 +141,9 @@ public static Map> getVehicleIds(Person person) { var personVehicles = (PersonVehicles) person.getAttributes().getAttribute(VehicleUtils.VEHICLE_ATTRIBUTE_KEY); if (personVehicles == null) { throw new RuntimeException("Could not retrieve vehicle id from person: " + person.getId().toString() + - ". \nIf you are not using config.qsim().getVehicleSource() with 'defaultVehicle' or 'modeVehicleTypesFromVehiclesData' you have to provide " + - "a vehicle for each mode for each person. Attach a PersonVehicles instance (containing a map of mode:String -> id:Id) with key 'vehicles' as person attribute to each person." + - "\n VehicleUtils.insertVehicleIdIntoAttributes does this for you."); + ". \nIf you are not using config.qsim().getVehicleSource() with 'defaultVehicle' or 'modeVehicleTypesFromVehiclesData' you have to provide " + + "a vehicle for each mode for each person. Attach a PersonVehicles instance (containing a map of mode:String -> id:Id) with key 'vehicles' as person attribute to each person." + + "\n VehicleUtils.insertVehicleIdIntoAttributes does this for you."); } return personVehicles.getModeVehicles(); } @@ -167,23 +167,37 @@ public static Id getVehicleId(Person person, String mode) { Map> vehicleIds = getVehicleIds(person); if (!vehicleIds.containsKey(mode)) { throw new RuntimeException("Could not retrieve vehicle id from person: " + person.getId().toString() + " for mode: " + mode + - ". \nIf you are not using config.qsim().getVehicleSource() with 'defaultVehicle' or 'modeVehicleTypesFromVehiclesData' you have to provide " + - "a vehicle for each mode for each person. Attach a PersonVehicles instance (containing a map of mode:String -> id:Id) with key 'vehicles' as person attribute to each person." + - "\n VehicleUtils.insertVehicleIdIntoAttributes does this for you." + ". \nIf you are not using config.qsim().getVehicleSource() with 'defaultVehicle' or 'modeVehicleTypesFromVehiclesData' you have to provide " + + "a vehicle for each mode for each person. Attach a PersonVehicles instance (containing a map of mode:String -> id:Id) with key 'vehicles' as person attribute to each person." + + "\n VehicleUtils.insertVehicleIdIntoAttributes does this for you." ); } return vehicleIds.get(mode); } - /** + /** * Attaches vehicle ids to a person, so that the router knows which vehicle to use for which mode and person. * * @param modeToVehicle mode string mapped to vehicle ids. The provided map is copied and stored as unmodifiable map. * If a mode key already exists in the persons's attributes it is overridden. Otherwise, existing * and provided values are merged into one map * We use PersonVehicle Class in order to have a dedicated PersonVehicleAttributeConverter to/from XML + * + * @deprecated inline to more expressive method */ - public static void insertVehicleIdsIntoAttributes(Person person, Map> modeToVehicle) { + @Deprecated + public static void insertVehicleIdsIntoAttributes(Person person, Map> modeToVehicle){ + insertVehicleIdsIntoPersonAttributes( person, modeToVehicle ); + } + /** + * Attaches vehicle ids to a person, so that the router knows which vehicle to use for which mode and person. + * + * @param modeToVehicle mode string mapped to vehicle ids. The provided map is copied and stored as unmodifiable map. + * If a mode key already exists in the persons's attributes it is overridden. Otherwise, existing + * and provided values are merged into one map + * We use PersonVehicle Class in order to have a dedicated PersonVehicleAttributeConverter to/from XML + */ + public static void insertVehicleIdsIntoPersonAttributes(Person person, Map> modeToVehicle) { Object attr = person.getAttributes().getAttribute(VEHICLE_ATTRIBUTE_KEY); // copy in case it's a UnmodifiableMap Map> modeToVehicleCopy = new HashMap<>(modeToVehicle); @@ -200,8 +214,17 @@ public static void insertVehicleIdsIntoAttributes(Person person, Map> modeToVehicleType) { + insertVehicleTypesIntoPersonAttributes( person, modeToVehicleType ); + } + /** + * Attaches vehicle types to a person, so that the router knows which vehicle to use for which mode and person. + * @param modeToVehicleType mode string mapped to vehicle type ids. The provided map is copied and stored as unmodifiable map. + */ + public static void insertVehicleTypesIntoPersonAttributes(Person person, Map> modeToVehicleType) { Object attr = person.getAttributes().getAttribute(VEHICLE_TYPES_ATTRIBUTE_KEY); Map> modeToTypesCopy = new HashMap<>(modeToVehicleType); @@ -273,7 +296,7 @@ public static Double getFuelConsumption(VehicleType vehicleType) { } public static void setFuelConsumption(VehicleType vehicleType, double literPerMeter) { - setFuelConsumption(vehicleType.getEngineInformation(), literPerMeter); + setFuelConsumption(vehicleType.getEngineInformation(), literPerMeter); } //******** EngineInformation attributes ************ @@ -307,11 +330,11 @@ public static void setHbefaEmissionsConcept( EngineInformation engineInformation } public static Double getEnergyConsumptionKWhPerMeter(EngineInformation engineInformation) { - return (Double) engineInformation.getAttributes().getAttribute(ENERGYCONSUMPTION); - } + return (Double) engineInformation.getAttributes().getAttribute(ENERGYCONSUMPTION); + } public static void setEnergyConsumptionKWhPerMeter(EngineInformation engineInformation, double energyConsumptionKWhPerMeter) { - engineInformation.getAttributes().putAttribute(ENERGYCONSUMPTION, energyConsumptionKWhPerMeter); + engineInformation.getAttributes().putAttribute(ENERGYCONSUMPTION, energyConsumptionKWhPerMeter); } public static Double getEnergyCapacity(EngineInformation engineInformation) { diff --git a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java index 98431e35cc7..567c6ace568 100644 --- a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java +++ b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java @@ -33,6 +33,7 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.PlanElement; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; @@ -337,7 +338,7 @@ void testLineChange() { assertEquals(Math.ceil(expectedTravelTime), actualTravelTime, MatsimTestUtils.EPSILON); } @Test - void testLineChangeWithDifferentUtils() { + void testLineChangeWithDifferentModeChangeUtils() { Fixture f = new Fixture(); f.init(); f.blueLine.getRoutes().values().forEach(transitRoute -> transitRoute.setTransportMode(TransportMode.ship)); @@ -355,6 +356,48 @@ void testLineChangeWithDifferentUtils() { //changing from train to ship is so expensive that direct walk is cheaper assertNull(legs); } + + @Test + void testLineChangeWithDifferentTravelTimeUtils() { + Fixture f = new Fixture(); + f.init(); + f.blueLine.getRoutes().values().forEach(transitRoute -> transitRoute.setTransportMode("bus")); + SwissRailRaptorConfigGroup swissRailRaptorConfigGroup = ConfigUtils.addOrGetModule(f.config, SwissRailRaptorConfigGroup.class); + swissRailRaptorConfigGroup.setTransferWalkMargin(0); + RaptorParameters raptorParams = RaptorUtils.createParameters(f.config); + SwissRailRaptorData data = SwissRailRaptorData.create(f.schedule, null, RaptorUtils.createStaticConfig(f.config), f.network, null); + TransitRouter router = new SwissRailRaptor.Builder(data, f.config).with(new RaptorParametersForPerson() { + @Override + public RaptorParameters getRaptorParameters(Person person) { + return raptorParams; + } + }).build(); + + // from C to G (see Fixture), competing between red line (express) and blue line (regular) + Coord fromCoord = new Coord(12000, 5000); + Coord toCoord = new Coord(28000, 5000); + + // default case + List legs = router.calcRoute(DefaultRoutingRequest.withoutAttributes(new FakeFacility(fromCoord), new FakeFacility(toCoord), 6.0*3600 - 60.0, null)); + assertEquals(3, legs.size()); + assertEquals("red", ((TransitPassengerRoute) ((Leg) legs.get(1)).getRoute()).getLineId().toString()); + + // routing by transport mode, same costs, choose red (train) again + raptorParams.setUseTransportModeUtilities(true); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("train", -1e-3); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("bus", -1e-3); + legs = router.calcRoute(DefaultRoutingRequest.withoutAttributes(new FakeFacility(fromCoord), new FakeFacility(toCoord), 6.0*3600 - 60.0, null)); + assertEquals(3, legs.size()); + assertEquals("red", ((TransitPassengerRoute) ((Leg) legs.get(1)).getRoute()).getLineId().toString()); + + // routing by transport mode, train is quicker, but more costly now, so choose blue (bus) + raptorParams.setUseTransportModeUtilities(true); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("train", -1e-2); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("bus", -1e-3); + legs = router.calcRoute(DefaultRoutingRequest.withoutAttributes(new FakeFacility(fromCoord), new FakeFacility(toCoord), 6.0*3600 - 60.0, null)); + assertEquals(3, legs.size()); + assertEquals("blue", ((TransitPassengerRoute) ((Leg) legs.get(1)).getRoute()).getLineId().toString()); + } @Test void testFasterAlternative() { diff --git a/matsim/src/test/java/org/matsim/core/config/ReflectiveConfigGroupTest.java b/matsim/src/test/java/org/matsim/core/config/ReflectiveConfigGroupTest.java index 17b8278da9e..9e0f1e55fb1 100644 --- a/matsim/src/test/java/org/matsim/core/config/ReflectiveConfigGroupTest.java +++ b/matsim/src/test/java/org/matsim/core/config/ReflectiveConfigGroupTest.java @@ -37,6 +37,7 @@ import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.population.Person; import org.matsim.core.config.ReflectiveConfigGroup.InconsistentModuleException; import org.matsim.testcases.MatsimTestUtils; @@ -70,6 +71,7 @@ void testDumpAndRead() { dumpedModule.enumSetField = Set.of(MyEnum.VALUE2); dumpedModule.setField = ImmutableSet.of("a", "b", "c"); dumpedModule.listField = List.of("1", "2", "3"); + dumpedModule.ints = List.of(1, 2, 3); assertEqualAfterDumpAndRead(dumpedModule); } @@ -166,6 +168,7 @@ void testComments() { expectedComments.put("enumListField", "list of enum"); expectedComments.put("enumSetField", "set of enum"); expectedComments.put("setField", "set"); + expectedComments.put("ints", "list of ints"); assertThat(new MyModule().getComments()).isEqualTo(expectedComments); } @@ -324,7 +327,7 @@ void testFailUnsupportedType_StringCollections() { void testFailUnsupportedType_NonStringList() { assertThatThrownBy(() -> new ReflectiveConfigGroup("name") { @Parameter("field") - private List stuff; + private List stuff; }).isInstanceOf(InconsistentModuleException.class); } @@ -472,6 +475,10 @@ private static class MyModule extends ReflectiveConfigGroup { @Parameter private Set enumSetField; + @Comment("list of ints") + @Parameter + private List ints; + // Object fields: // Id: string representation is toString private Id idField; 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) { diff --git a/matsim/src/test/java/org/matsim/core/replanning/annealing/ReplanningAnnealerTest.java b/matsim/src/test/java/org/matsim/core/replanning/annealing/ReplanningAnnealerTest.java index d16b44098a6..760d3e430e2 100644 --- a/matsim/src/test/java/org/matsim/core/replanning/annealing/ReplanningAnnealerTest.java +++ b/matsim/src/test/java/org/matsim/core/replanning/annealing/ReplanningAnnealerTest.java @@ -39,6 +39,19 @@ public class ReplanningAnnealerTest { "8;0.1000;0.0500;0.0500;0.9000\n" + "9;0.0500;0.0250;0.0250;0.9500\n" + "10;0.0000;0.0000;0.0000;1.0000\n"; + + private String expectedLinearAnnealMultipleSubpopulations = "it;globalInnovationRate_otherAnnealer;ChangeExpBeta_otherAnnealer;TimeAllocationMutator_otherAnnealer;globalInnovationRate_subpop;ReRoute_subpop;SubtourModeChoice_subpop;ChangeExpBeta_subpop\n" + + "0;0.8000;0.2000;0.8000;0.5000;0.2500;0.2500;0.5000\n" + + "1;0.7200;0.2800;0.7200;0.4500;0.2250;0.2250;0.5500\n" + + "2;0.6400;0.3600;0.6400;0.4000;0.2000;0.2000;0.6000\n" + + "3;0.5600;0.4400;0.5600;0.3500;0.1750;0.1750;0.6500\n" + + "4;0.4800;0.5200;0.4800;0.3000;0.1500;0.1500;0.7000\n" + + "5;0.4000;0.6000;0.4000;0.2500;0.1250;0.1250;0.7500\n" + + "6;0.3200;0.6800;0.3200;0.2000;0.1000;0.1000;0.8000\n" + + "7;0.2400;0.7600;0.2400;0.1500;0.0750;0.0750;0.8500\n" + + "8;0.1600;0.8400;0.1600;0.1000;0.0500;0.0500;0.9000\n" + + "9;0.0800;0.9200;0.0800;0.0500;0.0250;0.0250;0.9500\n" + + "10;0.0000;1.0000;0.0000;0.0000;0.0000;0.0000;1.0000\n"; private String expectedMsaAnneal = "it;globalInnovationRate;ReRoute;SubtourModeChoice;ChangeExpBeta\n" + "0;0.5000;0.2500;0.2500;0.5000\n" + @@ -360,21 +373,65 @@ void testSubpopulationAnneal() throws IOException { this.saConfigVar.setStartValue(0.5); this.saConfigVar.setDefaultSubpopulation(targetSubpop); this.config.replanning().getStrategySettings().forEach(s -> s.setSubpopulation(targetSubpop)); - ReplanningConfigGroup.StrategySettings s = new ReplanningConfigGroup.StrategySettings(); - s.setStrategyName("TimeAllocationMutator"); - s.setWeight(0.25); - s.setSubpopulation("noAnneal"); - this.config.replanning().addStrategySettings(s); + + String otherAnnealerSubpopulation = "otherAnnealer"; + String othertargetSubpop = otherAnnealerSubpopulation; + ReplanningAnnealerConfigGroup.AnnealingVariable saConfigVar2 = new ReplanningAnnealerConfigGroup.AnnealingVariable(); + saConfigVar2.setAnnealType("linear"); + saConfigVar2.setEndValue(0.0); + saConfigVar2.setStartValue(0.8); + saConfigVar2.setDefaultSubpopulation(othertargetSubpop); + this.config.replanningAnnealer().addParameterSet(saConfigVar2); + + ReplanningConfigGroup.StrategySettings s = new ReplanningConfigGroup.StrategySettings(); + s.setStrategyName("TimeAllocationMutator"); + s.setWeight(0.25); + s.setSubpopulation(otherAnnealerSubpopulation); + ReplanningConfigGroup.StrategySettings s2 = new ReplanningConfigGroup.StrategySettings(); + s2.setStrategyName("ChangeExpBeta"); // shouldn't be affected + s2.setWeight(0.5); + s2.setSubpopulation(otherAnnealerSubpopulation); + this.config.replanning().addStrategySettings(s2); + this.config.replanning().addStrategySettings(s); + + + ReplanningConfigGroup.StrategySettings noAnnealSettings = new ReplanningConfigGroup.StrategySettings(); + noAnnealSettings.setStrategyName("TimeAllocationMutator"); + noAnnealSettings.setWeight(0.25); + noAnnealSettings.setSubpopulation("noAnneal"); + this.config.replanning().addStrategySettings(noAnnealSettings); Controler controler = new Controler(this.scenario); controler.run(); - Assertions.assertEquals(expectedLinearAnneal, readResult(controler.getControlerIO().getOutputFilename(FILENAME_ANNEAL))); + Assertions.assertEquals(expectedLinearAnnealMultipleSubpopulations, readResult(controler.getControlerIO().getOutputFilename(FILENAME_ANNEAL))); StrategyManager sm = controler.getInjector().getInstance(StrategyManager.class); List weights = sm.getWeights(targetSubpop); + List weights2 = sm.getWeights(otherAnnealerSubpopulation); Assertions.assertEquals(1.0, weights.stream().mapToDouble(Double::doubleValue).sum(), 1e-4); + Assertions.assertEquals(1.0, weights2.stream().mapToDouble(Double::doubleValue).sum(), 1e-4); } + @Test + void testNullSubpopulationAnneal() throws IOException { + String targetSubpop = null; + this.saConfigVar.setAnnealType("linear"); + this.saConfigVar.setEndValue(0.0); + this.saConfigVar.setStartValue(0.5); + this.saConfigVar.setDefaultSubpopulation(targetSubpop); + this.config.replanning().getStrategySettings().forEach(s -> s.setSubpopulation(targetSubpop)); + + Controler controler = new Controler(this.scenario); + controler.run(); + + Assertions.assertEquals(expectedLinearAnneal, readResult(controler.getControlerIO().getOutputFilename(FILENAME_ANNEAL))); + + StrategyManager sm = controler.getInjector().getInstance(StrategyManager.class); + List weights = sm.getWeights(targetSubpop); + + Assertions.assertEquals(1.0, weights.stream().mapToDouble(Double::doubleValue).sum(), 1e-4); + } + } diff --git a/matsim/src/test/java/org/matsim/core/utils/gis/ShapeFileReaderTest.java b/matsim/src/test/java/org/matsim/core/utils/gis/GeoFileReaderTest.java similarity index 78% rename from matsim/src/test/java/org/matsim/core/utils/gis/ShapeFileReaderTest.java rename to matsim/src/test/java/org/matsim/core/utils/gis/GeoFileReaderTest.java index 1a07451aa7b..d74ae57c395 100644 --- a/matsim/src/test/java/org/matsim/core/utils/gis/ShapeFileReaderTest.java +++ b/matsim/src/test/java/org/matsim/core/utils/gis/GeoFileReaderTest.java @@ -24,6 +24,7 @@ import java.io.IOException; import org.geotools.data.FeatureSource; +import org.geotools.feature.NameImpl; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -31,8 +32,9 @@ /** * @author mrieser / senozon + * @author nkuehnel / MOIA // add gpkg test */ -public class ShapeFileReaderTest { +public class GeoFileReaderTest { @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); @@ -41,9 +43,19 @@ public class ShapeFileReaderTest { * @throws IOException */ @Test - void testPlusInFilename() throws IOException { + void testShp() throws IOException { String filename = "src/test/resources/" + utils.getInputDirectory() + "test+test.shp"; - FeatureSource fs = ShapeFileReader.readDataFile(filename); + FeatureSource fs = GeoFileReader.readDataFile(filename); + Assertions.assertEquals(3, fs.getFeatures().size()); + } + + /** + * @throws IOException + */ + @Test + void testGpkg() throws IOException { + String filename = "src/test/resources/" + utils.getInputDirectory() + "test+test.gpkg"; + FeatureSource fs = GeoFileReader.readDataFile(filename, new NameImpl("testtest")); Assertions.assertEquals(3, fs.getFeatures().size()); } } diff --git a/matsim/src/test/java/org/matsim/core/utils/gis/ShapeFileWriterTest.java b/matsim/src/test/java/org/matsim/core/utils/gis/GeoFileWriterTest.java similarity index 70% rename from matsim/src/test/java/org/matsim/core/utils/gis/ShapeFileWriterTest.java rename to matsim/src/test/java/org/matsim/core/utils/gis/GeoFileWriterTest.java index 70c19d22d88..3c4d1de3994 100644 --- a/matsim/src/test/java/org/matsim/core/utils/gis/ShapeFileWriterTest.java +++ b/matsim/src/test/java/org/matsim/core/utils/gis/GeoFileWriterTest.java @@ -29,6 +29,7 @@ import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.feature.NameImpl; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.referencing.crs.DefaultGeographicCRS; @@ -45,7 +46,7 @@ import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; -public class ShapeFileWriterTest { +public class GeoFileWriterTest { @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); @@ -55,16 +56,16 @@ void testShapeFileWriter() throws IOException{ String inFile = "src/test/resources/" + utils.getInputDirectory() + "test.shp"; String outFile = utils.getOutputDirectory() + "/test.shp"; - SimpleFeatureSource s = ShapeFileReader.readDataFile(inFile); + SimpleFeatureSource s = GeoFileReader.readDataFile(inFile); SimpleFeatureCollection fts = s.getFeatures(); SimpleFeatureIterator it = fts.features(); SimpleFeature ft = it.next(); Geometry g = (Geometry) ft.getDefaultGeometry(); List fc = new ArrayList<>(); fc.add(ft); - ShapeFileWriter.writeGeometries(fc, outFile); + GeoFileWriter.writeGeometries(fc, outFile); - SimpleFeatureSource s1 = ShapeFileReader.readDataFile(outFile); + SimpleFeatureSource s1 = GeoFileReader.readDataFile(outFile); SimpleFeatureCollection fts1 = s1.getFeatures(); SimpleFeatureIterator it1 = fts1.features(); SimpleFeature ft1 = it1.next(); @@ -74,6 +75,31 @@ void testShapeFileWriter() throws IOException{ } + @Test + void testGeopackageFileWriter() throws IOException{ + + String inFile = "src/test/resources/" + utils.getInputDirectory() + "test.gpkg"; + + String outFile = utils.getOutputDirectory() + "/test.gpkg"; + SimpleFeatureSource s = GeoFileReader.readDataFile(inFile, new NameImpl("test")); + SimpleFeatureCollection fts = s.getFeatures(); + SimpleFeatureIterator it = fts.features(); + SimpleFeature ft = it.next(); + Geometry g = (Geometry) ft.getDefaultGeometry(); + List fc = new ArrayList<>(); + fc.add(ft); + GeoFileWriter.writeGeometries(fc, outFile); + + SimpleFeatureSource s1 = GeoFileReader.readDataFile(outFile, new NameImpl("test")); + SimpleFeatureCollection fts1 = s1.getFeatures(); + SimpleFeatureIterator it1 = fts1.features(); + SimpleFeature ft1 = it1.next(); + Geometry g1 = (Geometry) ft1.getDefaultGeometry(); + + Assertions.assertEquals(g.getCoordinates().length, g1.getCoordinates().length); + + } + @Test void testShapeFileWriterWithSelfCreatedContent() throws IOException { String outFile = utils.getOutputDirectory() + "/test.shp"; @@ -94,9 +120,42 @@ void testShapeFileWriterWithSelfCreatedContent() throws IOException { Geometry g0 = (Geometry) features.iterator().next().getDefaultGeometry(); - ShapeFileWriter.writeGeometries(features, outFile); + GeoFileWriter.writeGeometries(features, outFile); + + SimpleFeatureSource s1 = GeoFileReader.readDataFile(outFile); + SimpleFeatureCollection fts1 = s1.getFeatures(); + SimpleFeatureIterator it1 = fts1.features(); + SimpleFeature ft1 = it1.next(); + Geometry g1 = (Geometry) ft1.getDefaultGeometry(); + + Assertions.assertEquals(g0.getCoordinates().length, g1.getCoordinates().length); + + + } + + @Test + void testGeopackageFileWriterWithSelfCreatedContent() throws IOException { + String outFile = utils.getOutputDirectory() + "/test2.gpkg"; + SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder(); + b.setName("EvacuationArea"); + b.setCRS(DefaultGeographicCRS.WGS84); + b.add("the_geom", MultiPolygon.class); + b.add("name", String.class); + SimpleFeatureType ft = b.buildFeatureType(); + + GeometryFactory geofac = new GeometryFactory(); + LinearRing lr = geofac.createLinearRing(new Coordinate[]{new Coordinate(0,0),new Coordinate(0,1),new Coordinate(1,1),new Coordinate(0,0)}); + Polygon p = geofac.createPolygon(lr,null); + MultiPolygon mp = geofac.createMultiPolygon(new Polygon[]{p}); + Collection features = new ArrayList(); + features.add(SimpleFeatureBuilder.build(ft, new Object[]{mp,"test_name"},"fid")); + + + Geometry g0 = (Geometry) features.iterator().next().getDefaultGeometry(); + + GeoFileWriter.writeGeometries(features, outFile); - SimpleFeatureSource s1 = ShapeFileReader.readDataFile(outFile); + SimpleFeatureSource s1 = GeoFileReader.readDataFile(outFile, new NameImpl("EvacuationArea")); SimpleFeatureCollection fts1 = s1.getFeatures(); SimpleFeatureIterator it1 = fts1.features(); SimpleFeature ft1 = it1.next(); @@ -125,9 +184,9 @@ void testShapeFileWriterWithSelfCreatedContent_withMatsimFactory_Polygon() throw Geometry g0 = (Geometry) f.getDefaultGeometry(); - ShapeFileWriter.writeGeometries(features, outFile); + GeoFileWriter.writeGeometries(features, outFile); - SimpleFeatureSource s1 = ShapeFileReader.readDataFile(outFile); + SimpleFeatureSource s1 = GeoFileReader.readDataFile(outFile); SimpleFeatureCollection fts1 = s1.getFeatures(); SimpleFeatureIterator it1 = fts1.features(); SimpleFeature ft1 = it1.next(); @@ -154,9 +213,9 @@ void testShapeFileWriterWithSelfCreatedContent_withMatsimFactory_Polyline() thro Geometry g0 = (Geometry) f.getDefaultGeometry(); - ShapeFileWriter.writeGeometries(features, outFile); + GeoFileWriter.writeGeometries(features, outFile); - SimpleFeatureSource s1 = ShapeFileReader.readDataFile(outFile); + SimpleFeatureSource s1 = GeoFileReader.readDataFile(outFile); SimpleFeatureCollection fts1 = s1.getFeatures(); SimpleFeatureIterator it1 = fts1.features(); SimpleFeature ft1 = it1.next(); @@ -182,9 +241,9 @@ void testShapeFileWriterWithSelfCreatedContent_withMatsimFactory_Point() throws Geometry g0 = (Geometry) f.getDefaultGeometry(); - ShapeFileWriter.writeGeometries(features, outFile); + GeoFileWriter.writeGeometries(features, outFile); - SimpleFeatureSource s1 = ShapeFileReader.readDataFile(outFile); + SimpleFeatureSource s1 = GeoFileReader.readDataFile(outFile); SimpleFeatureCollection fts1 = s1.getFeatures(); SimpleFeatureIterator it1 = fts1.features(); SimpleFeature ft1 = it1.next(); diff --git a/matsim/src/test/java/org/matsim/examples/EquilTest.java b/matsim/src/test/java/org/matsim/examples/EquilTest.java index 96794010292..31f714c3d34 100644 --- a/matsim/src/test/java/org/matsim/examples/EquilTest.java +++ b/matsim/src/test/java/org/matsim/examples/EquilTest.java @@ -41,6 +41,7 @@ import org.matsim.core.scenario.ScenarioUtils; import org.matsim.testcases.MatsimTestUtils; import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class EquilTest { private static final Logger log = LogManager.getLogger( EquilTest.class ) ; @@ -84,7 +85,7 @@ void testEquil(boolean isUsingFastCapacityUpdate) { writer.closeFile(); - final EventsFileComparator.Result result = new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( referenceFileName , eventsFileName ); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result, "different event files." ); + final ComparisonResult result = new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( referenceFileName , eventsFileName ); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result, "different event files." ); } } diff --git a/matsim/src/test/java/org/matsim/examples/OnePercentBerlin10sIT.java b/matsim/src/test/java/org/matsim/examples/OnePercentBerlin10sIT.java index 89237ec5b1a..f6d862c5785 100644 --- a/matsim/src/test/java/org/matsim/examples/OnePercentBerlin10sIT.java +++ b/matsim/src/test/java/org/matsim/examples/OnePercentBerlin10sIT.java @@ -41,6 +41,7 @@ import org.matsim.core.scenario.ScenarioUtils; import org.matsim.testcases.MatsimTestUtils; import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class OnePercentBerlin10sIT { @@ -92,7 +93,7 @@ void testOnePercent10sQSim() { writer.closeFile(); System.out.println("reffile: " + referenceEventsFileName); - assertEquals( EventsFileComparator.Result.FILES_ARE_EQUAL, + assertEquals( ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( referenceEventsFileName, eventsFileName ), "different event files" ); @@ -137,7 +138,7 @@ void testOnePercent10sQSimTryEndTimeThenDuration() { writer.closeFile(); - assertEquals( EventsFileComparator.Result.FILES_ARE_EQUAL, + assertEquals( ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( referenceEventsFileName, eventsFileName ), "different event files" ); diff --git a/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java b/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java index 87696593899..112bcaaddaf 100644 --- a/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java +++ b/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java @@ -32,6 +32,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.core.utils.misc.CRCChecksum; import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; import java.io.BufferedReader; import java.io.File; @@ -316,7 +317,7 @@ public static void assertEqualFilesLineByLine(String inputFilename, String outpu } public static void assertEqualEventsFiles( String filename1, String filename2 ) { - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL ,EventsFileComparator.compare(filename1, filename2) ); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL ,EventsFileComparator.compare(filename1, filename2) ); } public static void assertEqualFilesBasedOnCRC( String filename1, String filename2 ) { diff --git a/matsim/src/test/java/org/matsim/utils/eventsfilecomparison/EventsFileComparatorTest.java b/matsim/src/test/java/org/matsim/utils/eventsfilecomparison/EventsFileComparatorTest.java index 6618b85dc17..9a52ac8593e 100644 --- a/matsim/src/test/java/org/matsim/utils/eventsfilecomparison/EventsFileComparatorTest.java +++ b/matsim/src/test/java/org/matsim/utils/eventsfilecomparison/EventsFileComparatorTest.java @@ -20,7 +20,7 @@ package org.matsim.utils.eventsfilecomparison; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.matsim.utils.eventsfilecomparison.EventsFileComparator.Result.*; +import static org.matsim.utils.eventsfilecomparison.ComparisonResult.*; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; diff --git a/matsim/src/test/java/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest.java b/matsim/src/test/java/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest.java new file mode 100644 index 00000000000..a14100b52d1 --- /dev/null +++ b/matsim/src/test/java/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest.java @@ -0,0 +1,143 @@ +package org.matsim.utils.eventsfilecomparison; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.core.events.EventsUtils; +import org.matsim.testcases.MatsimTestUtils; + +import java.io.File; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class EventsFileFingerprintComparatorTest { + + @RegisterExtension + MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + void testEqual() { + + assertThat(EventsUtils.createAndCompareEventsFingerprint( + new File(utils.getClassInputDirectory(), "events_correct.xml"), + new File(utils.getClassInputDirectory(), "correct.fp.zst").toString() + )).isEqualTo(ComparisonResult.FILES_ARE_EQUAL); + + // Check if file has been created + assertThat(new File(utils.getClassInputDirectory(), "events_correct.fp.zst")) + .exists() + .size().isGreaterThan(0); + + } + + @Test + void testDiffTimesteps() { + + assertThat(EventsUtils.createAndCompareEventsFingerprint( + new File(utils.getClassInputDirectory(), "events.diff-num-timestamps.xml"), + new File(utils.getClassInputDirectory(), "correct.fp.zst").toString() + )).isEqualTo(ComparisonResult.DIFFERENT_TIMESTEPS); + + + } + + @Test + void testDiffCounts() { + + assertThat(EventsUtils.createAndCompareEventsFingerprint( + new File(utils.getClassInputDirectory(), "events.diff-type-count.xml"), + new File(utils.getClassInputDirectory(), "correct.fp.zst").toString() + )).isEqualTo(ComparisonResult.WRONG_EVENT_COUNT); + + } + + @Test + void testDiffContent() { + assertThat(EventsUtils.createAndCompareEventsFingerprint( + new File(utils.getClassInputDirectory(), "events.diff-hash.xml"), + new File(utils.getClassInputDirectory(), "correct.fp.zst").toString() + )).isEqualTo(ComparisonResult.DIFFERENT_EVENT_ATTRIBUTES); + } + + @Test + void testAdditionalEvent() { + assertThat(EventsUtils.createAndCompareEventsFingerprint( + new File(utils.getClassInputDirectory(), "events.one-more-event.xml"), + new File(utils.getClassInputDirectory(), "correct.fp.zst").toString() + )).isEqualTo(ComparisonResult.DIFFERENT_TIMESTEPS); + } + + @Test + void testAttributeOrder() { + assertThat(EventsUtils.createAndCompareEventsFingerprint( + new File(utils.getClassInputDirectory(), "events.attribute-order.xml"), + new File(utils.getClassInputDirectory(), "correct.fp.zst").toString() + )).isEqualTo(ComparisonResult.FILES_ARE_EQUAL); + } + + @Test + void testEventOrder() { + assertThat(EventsUtils.compareEventsFiles( + new File(utils.getClassInputDirectory(), "events_correct.xml").toString(), + new File(utils.getClassInputDirectory(), "events.event-order-wrong_logic.xml").toString() + )).isEqualTo(ComparisonResult.FILES_ARE_EQUAL); + + assertThat(EventsUtils.createAndCompareEventsFingerprint( + new File(utils.getClassInputDirectory(), "events.event-order-wrong_logic.xml"), + new File(utils.getClassInputDirectory(), "correct.fp.zst").toString() + )).isEqualTo(ComparisonResult.FILES_ARE_EQUAL); + + } + + + @Test + void testEqualFingerprints() { + + EventsUtils.createEventsFingerprint(new File(utils.getClassInputDirectory(), "events_correct.xml").toString(), new File(utils.getClassInputDirectory(), "events.fp.zst").toString()); + + assertThat(EventsFileFingerprintComparator.compareFingerprints( + new File(utils.getClassInputDirectory(), "events.fp.zst").toString(), + new File(utils.getClassInputDirectory(), "correct.fp.zst").toString() + )).isEqualTo(ComparisonResult.FILES_ARE_EQUAL); + + + } + + @Test + void testDiffTimestepsFingerprints() { + + assertThat(EventsFileFingerprintComparator.compareFingerprints( + new File(utils.getClassInputDirectory(), "events.diff-num-timestamps.fp.zst").toString(), + new File(utils.getClassInputDirectory(), "correct.fp.zst").toString() + )).isEqualTo(ComparisonResult.DIFFERENT_NUMBER_OF_TIMESTEPS); + + + } + + @Test + void testDiffCountsFingerprints() { + + assertThat(EventsFileFingerprintComparator.compareFingerprints( + new File(utils.getClassInputDirectory(), "events.diff-type-count.fp.zst").toString(), + new File(utils.getClassInputDirectory(), "correct.fp.zst").toString() + )).isEqualTo(ComparisonResult.WRONG_EVENT_COUNT); + + } + + @Test + void assertion() { + + AssertionError err = assertThrows(AssertionError.class, () -> { + EventsUtils.assertEqualEventsFingerprint( + new File(utils.getClassInputDirectory(), "events.diff-num-timestamps.xml"), + new File(utils.getClassInputDirectory(), "correct.fp.zst").toString() + ); + }); + + assertThat(err).message().isEqualTo(""" + Difference occurred in this event time=48067.0 | link=1 | type=entered link | vehicle=5 |\s + Count for event type 'entered link' differs: 2 (in fingerprint) != 1 (in events) + Count for event type 'vehicle leaves traffic' differs: 1 (in fingerprint) != 0 (in events)"""); + + } +} diff --git a/matsim/src/test/java/org/matsim/utils/gis/matsim2esri/network/Network2ESRIShapeTest.java b/matsim/src/test/java/org/matsim/utils/gis/matsim2esri/network/Network2ESRIShapeTest.java index 6700340ee8f..ad21f1e38cd 100755 --- a/matsim/src/test/java/org/matsim/utils/gis/matsim2esri/network/Network2ESRIShapeTest.java +++ b/matsim/src/test/java/org/matsim/utils/gis/matsim2esri/network/Network2ESRIShapeTest.java @@ -31,7 +31,7 @@ import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.testcases.MatsimTestUtils; import org.opengis.feature.simple.SimpleFeature; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -60,7 +60,7 @@ void testPolygonCapacityShape() { builder.setCoordinateReferenceSystem(crs); new Links2ESRIShape(network,outputFileP, builder).write(); - Collection writtenFeatures = ShapeFileReader.getAllFeatures(outputFileP); + Collection writtenFeatures = GeoFileReader.getAllFeatures(outputFileP); Assertions.assertEquals(network.getLinks().size(), writtenFeatures.size()); } @@ -83,7 +83,7 @@ void testPolygonLanesShape() { builder.setCoordinateReferenceSystem(crs); new Links2ESRIShape(network,outputFileP, builder).write(); - Collection writtenFeatures = ShapeFileReader.getAllFeatures(outputFileP); + Collection writtenFeatures = GeoFileReader.getAllFeatures(outputFileP); Assertions.assertEquals(network.getLinks().size(), writtenFeatures.size()); } @@ -106,7 +106,7 @@ void testPolygonFreespeedShape() { builder.setCoordinateReferenceSystem(crs); new Links2ESRIShape(network,outputFileP, builder).write(); - Collection writtenFeatures = ShapeFileReader.getAllFeatures(outputFileP); + Collection writtenFeatures = GeoFileReader.getAllFeatures(outputFileP); Assertions.assertEquals(network.getLinks().size(), writtenFeatures.size()); } @@ -129,7 +129,7 @@ void testLineStringShape() { builder.setCoordinateReferenceSystem(crs); new Links2ESRIShape(network,outputFileShp, builder).write(); - Collection writtenFeatures = ShapeFileReader.getAllFeatures(outputFileShp); + Collection writtenFeatures = GeoFileReader.getAllFeatures(outputFileShp); Assertions.assertEquals(network.getLinks().size(), writtenFeatures.size()); } @@ -145,7 +145,7 @@ void testNodesShape() { new Nodes2ESRIShape(network,outputFileShp, "DHDN_GK4").write(); - Collection writtenFeatures = ShapeFileReader.getAllFeatures(outputFileShp); + Collection writtenFeatures = GeoFileReader.getAllFeatures(outputFileShp); Assertions.assertEquals(network.getNodes().size(), writtenFeatures.size()); } } diff --git a/matsim/src/test/java/org/matsim/utils/gis/matsim2esri/plans/SelectedPlans2ESRIShapeTest.java b/matsim/src/test/java/org/matsim/utils/gis/matsim2esri/plans/SelectedPlans2ESRIShapeTest.java index f5ec5a13be3..c619704622b 100755 --- a/matsim/src/test/java/org/matsim/utils/gis/matsim2esri/plans/SelectedPlans2ESRIShapeTest.java +++ b/matsim/src/test/java/org/matsim/utils/gis/matsim2esri/plans/SelectedPlans2ESRIShapeTest.java @@ -34,7 +34,7 @@ import org.matsim.core.population.io.PopulationReader; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.ShapeFileReader; +import org.matsim.core.utils.gis.GeoFileReader; import org.matsim.testcases.MatsimTestUtils; import org.opengis.feature.simple.SimpleFeature; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -66,7 +66,7 @@ void testSelectedPlansActsShape() throws IOException { sp.setWriteLegs(false); sp.write(); - Collection writtenFeatures = ShapeFileReader.getAllFeatures(outShp); + Collection writtenFeatures = GeoFileReader.getAllFeatures(outShp); Assertions.assertEquals(2235, writtenFeatures.size()); } @@ -91,7 +91,7 @@ void testSelectedPlansLegsShape() throws IOException { sp.setWriteLegs(true); sp.write(); - Collection writtenFeatures = ShapeFileReader.getAllFeatures(outShp); + Collection writtenFeatures = GeoFileReader.getAllFeatures(outShp); Assertions.assertEquals(1431, writtenFeatures.size()); } diff --git a/matsim/src/test/java/org/matsim/utils/objectattributes/attributeconverters/StringDoubleMapConverterTest.java b/matsim/src/test/java/org/matsim/utils/objectattributes/attributeconverters/StringDoubleMapConverterTest.java new file mode 100644 index 00000000000..e749b41e22e --- /dev/null +++ b/matsim/src/test/java/org/matsim/utils/objectattributes/attributeconverters/StringDoubleMapConverterTest.java @@ -0,0 +1,16 @@ +package org.matsim.utils.objectattributes.attributeconverters; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class StringDoubleMapConverterTest { + + @Test + void test() { + var expectedString = "{\"a\":0.1,\"b\":0.2}"; + var converter = new StringDoubleMapConverter(); + var serializedString = converter.convertToString(converter.convert(expectedString)); + assertEquals(expectedString, serializedString); + } +} \ No newline at end of file diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testGpkg/test+test.gpkg b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testGpkg/test+test.gpkg new file mode 100644 index 0000000000000000000000000000000000000000..3b7e9a7b3fa422e63191ce24eee6b686585e3b13 GIT binary patch literal 106496 zcmeI5TWlNId4NgD5+zGE?M-ZM*3s?}6P08=x=@s?izPXO%3$ssir zIm4Y9S&|VXkhHr=fFKVk+7x+cyJ-5*7HIR5v_+BZLm!&$LxG@8(4a}4f*`;?EV3=O zMYm}BpSh4TyvVe@U9W?mHaVPg{&VI(-}%pfE+fv#-b{#^KuWSwVxhyE<+D@6%#EQT{ zr77aRb=VV&+BPRjs-S4iGOHOjnqx^W6OYB%3<)&Hx630yuCwdu3`^pvESt%ZbgDI7 zfPe&HqpLSaCVdMM#NsKEWfSabj%1?oEE|koPiJxr2^e}2St1($Qbizv799csa#xfq zye6omAWN#I@S>zG60?+g@koJ}Bv~Ub38W&ZD$%xiiG%|oa_a^Qng&zstqF(x5($T{ z5;nDV^l7i>(oMiP+6m)5S*~&w;jU2Oc56jYqZ!hDA-3dDN0{GOqx|I(X~;YxP(#Ou z0cumB9nL8yPMh=+nKEH6oi$+gbpi7sEwXW4)28b%AG19+6l-gZUEn)j9rpOf$K9_j z=xw3d&YI89ScVt9o?uCHED7qFa1vh?NRGXoBdIjJ^N9pw(=?vSv9#sa;~cG|Q|z`N zmbW!<08NQ??_)H`_HmsO*2H~iUi+LX-V?}LI!_B!SILMxXdk(nPGxi8Qc^im+u<~= zN;Wd_WHhr$o@Y1h3>aGz3o*82B}i7SayDAjyTxOv<{UyK!>)rnNv*P312?!MO^`Iz zhB_3wcBbE#9e2A#sVMBLFIS)^<@jAq*3Y@-YU0ApA!m=DJ?-($&bnVUbZU<0RH4O> z)3Biv&4EhTaX3xF4vkS2l@p7twObV>Zoj2=Xy`#}D8JuM7D8KPopn*xs_Oez8BO)9 z=MBZ9y;Gxxjq|+}P;98*w>8^!4FmbsTBh|e{EExt@y*S- zzxZ6E!IuTODrm|9SCA{aRY}#Wzd3NAwXT~*I#)Jhs@?kRYBSK^QwF*sjyAgssS9>1$*1Bs^U%>ZTCqbO+BlV$ zoE2{q?y6}wTT_91bX$rK_WSP4ooGw-N--^hn{I0pr{e<;o|WN!ny)Z;c(Kppo1AnX zZZ!;3E-O%5hQrepum|+F8l*kiRxc+wo|3?8yNUo;*_9f-%Nn~L%_oemD-`YT_vI%~ z#AUy(+3xH?p5u@Aczl6?`_;Wh*&OAvPI_C*WJTEx?SulsXp!e=Q*z2MVi9@`u_OwL z5n)&_Qxw#KBGxn!M#FlKZ52HbU@E+-aRnIGmZ5`$F=H;CY;=*t5)8uVxTJ|yAs86j z93QKWj}>!cHx|c|i({o1157}Y_X431WB23?v3qc)YIEEWWpmg~{X%PFP-t_YJ;%d% z*Sd3EIMwe<22QMDs}{_LV4e0Y^md=rFnlX1oxu*!xz$mxTkm_1Lk;6->IZb&Zwl*a zHI*g_qxWbt80+9s?LLu_l`=1h_n?W`adsO{@P!1B01`j~NB{{S0VIF~kN^@u0*{ZtXI!3T*M))S zs(DywhN+!UB(RQCR`}YsSRmOcFNzY}(;~3QDJX(e5D3g4HKDro zYwP8?>bl^5Zl`gT0tj;&_5{6?gofu)apQa|Ow3-dF6Cc6Q5_|oyUhRBu3+=`Or)I-3*qT$U5DFo zC}aXA_}Xp}5~twi=nYWK2$rR?8O}ztxpo@Q7#deB$w|0fswaUJR9F(wt5_wXM2bQ| ztnw8&QY}^eHsQ8FO!jJRTTo=NNaz1<@9Qr3k1r&E1dsp{Kmter2_OL^fCP{L5&u_#CY2_OL^fCP{L5GfCP{L5Wl=C01`j~NB{{S0VIF~kN^@u0!RP}bW4EV z|Ht`%x3o|W2_OL^fCP{L5`UU?*E7L|0lEVP-`TB1dsp{Kmter z2_OL^fCP{L53@qt&u znj)6Vf>N&SlsQeT2watipndDGCl*>Sf^l#0T>`f^3o1diX;Wc{3L zZo6E#Ippl|>afQ*KJI>PLH9|`@y+LFtmYrRo?uCHED7qFa1vh?NRGXoBdIjJ^N9pw zD=O?4!%~l2k8^mdPO;m9Sl-r1OSIlA7~Z*kT&ILJaUa^}KBtQJ1hSUS(*o61G9nM! zN3Nz**&Mj`RF2ekI8CdPjZ8cl&1{nA*-bkG#@0qdj4fFSl2xmmjTY^7;;~e74k40Z z*TJo)R@tn98@dHekTlhXIuts7_O!=0JL`Vc$g;U!I8|uz<1}pO#M-11_R=_O)Lv#r zRa8zawpLD6l(_vCxHR;jHI(0PCkvsivQCs`t*X9nESsuH&l`$IJNZTh8Rc!Q9JR)4 zB46PYp~R^NDhZl`q1aHrZ)>*eb_(QM+bXS(;a6N9k8f_y{l(`R?Ug=%Ssbgpd1$hlp^u4keh)P!~doowSC$;DHfv=P-?U9~mHR@2bd=*4I$ zRlD`s)n;JWL>cIcIGWrpq%PR4B%g}k%)@x8(Fh&#&_t=c!i1}OjeZL&`u~2%w%|uHYKMFBNoBwizQJ|j0nSenWCT;6tSj>FsaZx zT&w7T08`;rjVr+HpbY&R%w}@&WTS^8mS7Mj86{1u3c>K9rYgF>4F?KvLCyVjlS!l`~=GH_xITeV;| z1nabKp||^_hT&UDPr*EPfX-!)dfj^8dmL&QM^itb+kR76PphdkNf^CHo3T^}k81ac zjI5M-NxTQ$k!2ZmFKds2h9fIQ=&IUw-$kJ$N}`@clQ}lqUFgiwO)Gv_?- z_5V>{w)a1K{=%Jhec$_+!#ih$p`W{!hCXxp`-A(A`M*vOl77W^?V9^=R41rtiXd>- z9)pI@S7aFCb&R;+VCnBD=MU=n)W<2dVH+dK(8A=<;i;!RzL62jjagb)$MeoBS;2l1 zB>s|E^ta2JMDsb=BoR_3S$l6s{M3p1iN1p(L;SYnp`%ToF;&0XXaMDgu9Z52t*OL=u{9If?DV5u*{R9pk?how zN1g3sUaosTS#EyBbLkeW*)4Qx^X4Liv0Cu3hT1NZI?a|fWpicXaha+^*|rN%?N^me zwHwRIH=Z)s`nqHLkcR3|_e17U9lAXNN|&qmA0O<-$5GPnxfC54cqL}SZ#Vcch+Bgd zYY1cB7->6PGE(?SbUg7G{rdq`W7T*0vio>US3{p%3Hz`ps={2ySo~_7 ze#BAuCfSxbdCNK%Q_rd0(w1$0VDKr!8nx zZ$Rd4BUN~LSC9%q)9F)=2GkT8q^lDQqzuvD|Mz--&*lB8_iy2VFC>5jkN^@u0!RP} zAOR$R1dsp{KmthMgCgMXJ>^<=$2MH|^rJVw@Uu5=zxUd=<=g*!jn4nw zUib~bJ0Dcx@H$8U2_OL^fCP{L5NB{{S0VIF~kN^@u0!RP}AOR%s#1IgB`>(nJd!zcVM&Jo6y#87P{I61kuw>JU5>aOvH9lk6~z)$Tb)tXQUPftyLqVZD_D-ryBxj4S3 z(1$kl^aoll<+$!6Uf{Ft{*epgFOOOicKXwEJ%8gTJNomY9_SK!I$ig1S*je+=l}P5 zzvl9O*ZVc^&z_hnMn#bT5!-aTol@7ZN}MNB{{S0VIF~kN^@u0(Jsl-hc;c z{q83rsMid3fA8P_Hx2LP$~XT0bMXGW8Q$}~e_9maU0C_6FMI~xpEbjKzxU=)72Z25 zU;aA<-kKSX2PA+5kiZ8{fX@G2@Q^`#Apsxb@sh8?+*XZ@OOu=4E_0#|MXV}S3Ga_f4lE|?|=1vvgaZQocKCUhCIHjSKY4} zJB&JhgwWx~3yt7s96J?uNK1nC-#~C`L9PkJxpSw!BVuE(&(;k=6?u;ni`-qlvMX2{ zw=$Yo6;zF{*2r2k$L8WmR^I?Ol}{wd8oM6NCtyc!cHx|c| zi({o1157}Y_X431Q!R2Ou_C}VtlaBa(KusUSX(T!noebNnJ8?YOA1O=;i@H(EA5c= zbcT(`QsjAdlLQ-?hG4hdbvDDMR$)6`2P4>WHPo6}t!-v?El$oZbTkz7_yPgE$VY>xdQ9$DE0B@-fDmU64aq?0@Mb{YtNAE>!d}fqp(1GT zPu1w#!gA7H%|;4qujVy2!RA;3n~FE@)ht(vEn78TXJhdc=%}Yz&!m$b_Fsn0o--_g zidZJ;#M*?PZozz&u&K49i@)W$v^p|yeCvcV?bZOdF!LaVGLu-Pvi44IEmd6|GP+Ds z>@7n#eGh8emd_-f)f;0vL-&Y2VOQ!0Kmp)_^{X?DYa1I$ACHddU|y}>7fj^A!9?CS zFtBU4PNus}yB`3L!%{w+n|&Xh|D<8O$@|vP^n=&YbaNf86LY8ZHjT4xNYKJQP%Cy+ z6K&ASCk(sw-j_-E!I^~LeXC1J0n zYv|4)Sea&ET(OaeuClbNPIu@ z2|5A|=X-d5)Z>dr-G}4)xTDRs^yWaSbBxdGdOL1dZ)V{SN^((<{YbP(QTgLRFRI(BY|PJ-$d};LsTFx4C4SAoKDs#51{kG(mD5E67js*?1~O^gLh` z$&jij?ZYR(Pd`QJK>vOaS{~{5-Ms8}=}$p3w>al_HCaFB^nq&q;cY4xZVLG5;oiqR zbUXFqvBoI3A>SnZ5eL1dND|a@IBEV-&$uDf81)u~k|>FqC`-;!DAQ&vY#-~FVUSx8 zNIn(6nP=@vFr*+?cB_(pF@`uV9ts`xT=HDH1*5-9rr$CToG~WlN&>I#DgsxKcO{Lp zT$gpUNLYj0t`b|`tnE107|xo5MV+l&R^aNACPyO7S)NORR)Mi zK~ZT^_@>r)P2?+Z??*jQi3BHig>_k}^4hZh){dr=&;|E)w3Qf}j;&_0TmD3G#a6&VwB4dWf(affiIHSQ+h)?4HK^AxNOyUi=3Hf|Y-KA;kgdS0 znwcxrq03zJ*=UU2%C4q2z#?zR(3oL@%U58kUaiRzv}PigNMwzGse^S+KpjLgY}B+z zdV2kO`u5iN!W1(eo}Xgi2nV1-tBBpm#{A4oWctdTJ4=(aHRufpnov!Ve`jXpGCeF; zpdf&VT!u!uTU~~B0uA7@B*VPFq=JvoMXiJ?IG^H5WM+1HY0~)Kh=B-tEgAt|t#DX- z*@jc9%c2o&hFAhcK`kg^jV^So7>#sk(jI2XQALCT72^wvEFDx=OwA1)ol#bzhGm#( zbUo&#B2(aA>Q-aMS&6`M$_iiG77L{cUtZCaU14dmDNvV%qS}3t?%F0zN42D{uV~=! zmh?_wg+5jP&s>)-j~scOeMK3}mhLW4?;>Jr(L{2$qKRvAl^3O?c{5Va-hKiVnOuvL z9pPZve=`=(axbu%Y&@OvuQ>aLrAZJolxrkkn(TO)Gu|J#+}_t+-q+y+Uq}E6AOR$R z1dsp{Kmter2_OL^fCP}h;~_B7GvFI>xt857{ZCA+zhRi3nw}Y-ii}TP$%W?@BlC;1 WS0?7e3orJ7mXlO|up9Zg7yl1EbSwJ+ literal 0 HcmV?d00001 diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileReaderTest/testPlusInFilename/test+test.dbf b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testShp/test+test.dbf similarity index 100% rename from matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileReaderTest/testPlusInFilename/test+test.dbf rename to matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testShp/test+test.dbf diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileReaderTest/testPlusInFilename/test+test.prj b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testShp/test+test.prj similarity index 100% rename from matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileReaderTest/testPlusInFilename/test+test.prj rename to matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testShp/test+test.prj diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileReaderTest/testPlusInFilename/test+test.qpj b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testShp/test+test.qpj similarity index 100% rename from matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileReaderTest/testPlusInFilename/test+test.qpj rename to matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testShp/test+test.qpj diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileReaderTest/testPlusInFilename/test+test.shp b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testShp/test+test.shp similarity index 100% rename from matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileReaderTest/testPlusInFilename/test+test.shp rename to matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testShp/test+test.shp diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileReaderTest/testPlusInFilename/test+test.shx b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testShp/test+test.shx similarity index 100% rename from matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileReaderTest/testPlusInFilename/test+test.shx rename to matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileReaderTest/testShp/test+test.shx diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testGeopackageFileWriter/test.gpkg b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testGeopackageFileWriter/test.gpkg new file mode 100644 index 0000000000000000000000000000000000000000..f3221c7739c3ee74206a8b11d8602e4eb8afbb69 GIT binary patch literal 106496 zcmeI5Z)_XMb-z;^#Jj{ngXnGlj{a2hZrLRH=w+rGB@<>rz$Z zq0v-n$9mhAO8OQr$(pF@Zkd%V7teDfpG_tbT$Tjg@!j$Wk}KTROqL_bbdJmBNhaNy zE=WLvaPgIEB%8Sb2@=UP$#E%eB~P;PWR45PuVk`$mIO_`h$0hRxKkBLutSGnkld4$ zs-TM+DJrt2tAZr!7fG|0M)gQhkYzA+s@qAW0v8?ucSEQjwK-@6J8c-BFS?%^CX>tpF%3d+B8k3^BnE@tvE+7IV^Td zlqy>~H~?2-!~2*WvU}WN3G31hbgvy=lkSUTHB+D!YN=#K?skt{$)t06a4G3Lso&*w zy++ov$+dWPgS^ab*cq_4E*55O$;yzdR^x57sCP>y((W9>B+Fd|camP=awcwYN4hBM znhkY0{LSBYia1Lv@lvr&2D{mwOJVNDFZ_hN1ts#>Z09B3hCta0u1!+UhI&EK2GIj zXT#fsd+OS5Ybx@OZcEAGLI3UfBWrs3MfoklUlnDt9$rNSQ-dI6gS&FH9ea z%U*7?-`Rt_2cPKk`h!8w>)Y+RIqGFy^mo?Din1Hp5fy^jqQKLxn za-udlQOZwTyEw6SaiV-H$OdI)I~WeLc2CX{y9Z}$HpdN7HizvR7dktGO1lFcIUdHl zww&wYi9!Eb@W>XnTA|qytjmGL{@#`>=2J?_lc~cRs>nP55tjV87(hskAjY)s3jPxx(?qZu`J1wk%h|~n|24) zKm8p1^7+Q#cmLR5GN<6zsV%s`7ZN}MNB{{S0VIF~kN^@u0!RP}JU#-y$9OL@<3nd_ z1=whYrJYzJu#Zzwh5D9MB)M!Zok?>IE3WmyE@Z41B^mB%5!mDuRZ%XA1lEtbSlj%q z_3~a~#yw~6wo54rD%^{c;0{}}kl(g4Z+(DUAePV(g&chBFUrH`nen~{(%uU<5;?Lk zOVulhx>V%WbBWV$C%8;vCAS$cBLggKeH7M=OFpu=FdJZV>u`rJlU!|!T!_stL}K%7 zba7!SIyWDU#^x@>*mxm-Et5^=H#P$_=Kvd+pNY)`Zr|<_b0HSJKx62g1P)3|sG=xu zOU11KJJUscVR0rx#bFmGzZocr6%Yr>shP<9>|89m7@dnOF3!ff>981yMhzWqCZUok zSm5i85+qK;&CzS1ni;Ifm1Z~>&*i&mJZoxPwIrwEcBzpBc2HqUz-VHPNHQsjMX4rK z;hk!!8Mg_yMABrh)we`dkxF#^@A19Kz<+!p0VIF~kN^@u0!RP}AOR$R1dsp{Kmw1O zK*2LI{=)d!WiPz?U{gkK{s|52;AnbuCOSJg6Puj5kdMq?oQqzZiA^oc&E9(Jy$$7C zd&$>c`oV8r^!+sXS-74E2w#c7^$&mi<#&E~`t6fYFOTnk82FDbB!C2v01`j~NB{{S z0VIF~kN^@u0!ZLPM!?%YK1_EGaQ*)wYgnuf5fx009B!C2v01`j~ zNB{{S0VIF~kN^@u0>>mUdScvs_8;91z~}!RlOBpA0VIF~kN^@u0!RP}AOR$R1dsp{ zc!~(v|Nfsj{S+yVsv-d-fCP{L5s&uQO{sRPEHy`~Lh)VRGm}L|3IsMN}*GyA@uS zsv=(#AZW*W+m=fD7T>6s1YLB?tYo=(o+J5eGLhi2BcVX|I9xnVzspvL>p!8{6@)nt8OaCet}Cn}0-%W}c4`<7a%{GuOd7 z&mD&GzM|Cls(4SVKCEqaHbv8~-lKGtu zxHNRPGgR2=CJUjRvQCs0y{3I&EM3iHz|+ZeBo@nztZO~i@LhY7nN$GCTm9Xy90+h+uAL1 zcw@6>&fPk8D-(UUE_M?*%r@?md@{X3J5j6G)jET0Ee(B*7Dj8S*{#p6HVe}x%D_;> z(d8PDx@fnOLOOZ90Q04GCv?a|7p3yDv*B&RJ@rhtH5K_sx25Fpp#S##k+#%ol%_@S z(XKXeGC6eotjsaQUBd9*vjblL^t5Mhvu&74MTOQf{gt7BJz%iYAnnn%b~(cFltn>r zs3MfoklTa9Dt9#wr;`~YPdGj}=r2qkiOXJYv)|c+ya%7?^ZJ89&+FUmx;g4)UG#U> z$%?WY+7T6km5jjCuH=+qr4l%OsVs@A8DUy4TN1URD%Euf78S;TYgIiMWUGRv^F>%4 zRA79A)l5FQ)*j)AB^ZK5Mp>6?VkkJVF*#A2oG9fdu3em1yEsw46=Z|5vKQuhUdq66Wa9WiEAyN45JzR#7X0EZv9U$g+%< zm$gSh$5GT03{_o+?~+)SWXZ_FWsYvU3y%%`3p32zU{3wr*d6bK!O)3+@Be(?Eb~3) z#@Kg8|9I^6(Pu{fY{Y-^Plt0otp5!W1MVL_=k1k3JxG6^aj*-}pa2Px zKv^mUT9Xj_oGf0*XOd}1wZ_@U8xo*yEI{l>8L}i`%O$+O;WyXJmkwK>*r$pQyWH!N zhkL;XTM>4t$F}5iC{b%@#zsU%1wRa~$=Hi%ullIT8T%2AM9ZzUU-DU#?U|m~KIH1p zUiK5V{ zb>z`v` zQsZiMeb*SzO|fvedAGyLFbiwq^;CR?qm!@bGDTTb%AX@Mh9LNLFA) zrgWQavZe?X2=5YOZLl}qRShcQR)U5-d$bBv`};-7yxN^tUAM8lQK=4Ab9$qCE#@+Z&57aR)X{HCPLon`7WtckF|) zt(>}Tec9Ge&fRdWsC2CGZ982R=;cL`ICrS_^Us*G5WFdhH$^+{Et_M(q-TKHzc!p$XZqiU6ZSrr-20ZY z@!nf=Ul9Tm@XjZH>U;4wKX~a!?|k{kKZJMBAQa)DKmE-QG~l0Czx&+{kpAZXu70x& zQdTZjs)3(>?Y}Y*|KH=E*ZvXWt=zx!tAn4e!1Z50_l~e`E6tssx&D8b@x2R$;R^{M z0VIF~kN^@u0!RP}AOR$R1dsp{_%IRhdiuwQ>0hAH^?(1V?=ilw`&Qr$Uq}E6AOR$R z1dsp{Kmter2_OL^fCQc@0#g6rB__Ci&iG~sJY_{N9?$^KcM;(mL`CzVb5`({uGcS4 zPj7E;Pr>)f>q7CaP!Xr#>-N)HT`WeTGt-}Je_g~%1mB!4O>V37!A*UG!H%LF*R6G-c-wOk< zd0^b@@3wbf{{8=ZjPJdt92u&Q1dsp{Kmter2_OL^fCP{L5&<_t97&g}b zBa;mL#}^Vn0!RP}AOR$R1dsp{Kmv9Gf3)s7!F=&k5JaETMPHt`zW?pdzxDlp3NQcY z$L}ov=eSzleP{GvN544w{K!{F&Yt}8@TT|IgTEe-Pe}c5_I(XRp7htjTG;Eq zbjkBZ#5g(C@hyl$zCF8rd{;_nI7 zhG-qa%IZ=L9_%30>SQ&Z=km!l&N#X^T}Y+KDt9$rNaaaL)73H+36Q%sb zwTlyL7bnWMf^1M$wu9j?TPyKpsVYJlR_?8=Xq)W-SxbwfvkUK!guMP>&~s4eY)?nw z&mZ1)1QctbuvNCk*YA?`Y;rB0-7sny&#gF6b!pyKV+855L^M$kQl`*ya!F82d_$Fp z^R(C+v=^`Mx=)O4=cB`8MW%OZRmiCMgc4^CZOLGG?{d&MReFE^kW-~gVpY`P-}|2` zZAx0FO0RM$F3%A-MBRR>v{Ef~94dW@)B&qF+e-zSqE-#8bK#veXcbS+T_$PnhN+8jGPdn7 zYLd(u9W9fkr&k|wR(6lo20)=!$!xn^^LXon;Ryr6>uX0si1iL3_JKfvbHfb^y&W6g zBMOHFJb_1zzxFB9Am@&3i)im{5p}o4Rnk0{-PO5T1_Hh0|IIQT%|SclXFqAw|H1Z= z^^f#k|Hubh|Kl0ulV@Q2ivh!9KbSrQuzB`#FMLf&3$ImGr@sry;&zA2?yW;x8D?R8 zUr)tXI67ozx_I|j;;8}*{igq^K8W!HsT$jzH53g?NhO<5yB#7wakHlIa97(!#WiB{fOjf#1Ro{VmD6#^>Ge zVV~n zBq5{jM@{HkinN8=)5wxomSjnn6xlhgW4lZ)?UUyU%o>X#DWsFv3!GgEmK2q0qb3`L zvBX(;IJ_sH@t(=R6sy1KaGGztIpO2WqM$cakuNF@S?8(W>E?UhH<9IrIwp?h{IEG2 zGgvAW6-twJQPwq*q!zJ<^-~;Y>TQ5e;8!Vuprer*z^+e$Gcb9^q0r1 z@S%yU3R`Zn<#!*s!sm}!;q~VSscCN*cG>J2n)qsiKGM*2`4NX@yCOrfP!m~586NZ9 zU_8U;nc?&B3tvb82_OL^fCP{L51T2A;KNFF(DLn2yA^cGM41K+O(l3-PLV=EQ_KBlExdA zf@!N#lH>}6wLa4DqN>rP@JXu+x+GNLwu`o_5g9J-iB}c1Cg_&~H}2{N2}5xEuD+b$ zGKrOJZZmKrks}MU0hUYWxHVXdLWrVPOC%w}%3GI;B)6;SVvR%=7iNhlYhvwARSd9e zAk1Zt6b|K8LDnQa9Jt++cw#;_)3fZte5_~LNMx?}j3XE3XM4|i{z8-rbE#BvJ(o$Y zws~HN%`Ze^^K5i+VJbQ|AC1Q5F2vXrmrmrb!D=0i@c^lXNIM*P=!T(t**$>n~72;u~h=5 z4%RsZZ4l3L@uoe}%PUthH#a92XV}Te!VC-V@CH<96LIUgM1Y-*MK9dGy);dGgVBMY z3)NNS_h*;S)3?i2s0bh;=b=+JYL}s(KnFN4E3iXQ*1$&?qE# z;o7E~j%vx+iP6E|Eg6HrGJUH4o6MQ>FYNoAV?_nbmYyuo8X^*_@zh$Qs!OX%O_1cZ z=6ygTd;0}6W i#3pAh3J$U{C=`CxBd@y_u&`- literal 0 HcmV?d00001 diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.dbf b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.dbf similarity index 100% rename from matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.dbf rename to matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.dbf diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.prj b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.prj similarity index 100% rename from matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.prj rename to matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.prj diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.qix b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.qix similarity index 100% rename from matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.qix rename to matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.qix diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.qpj b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.qpj similarity index 100% rename from matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.qpj rename to matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.qpj diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.shp b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.shp similarity index 100% rename from matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.shp rename to matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.shp diff --git a/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.shx b/matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.shx similarity index 100% rename from matsim/src/test/resources/test/input/org/matsim/core/utils/gis/ShapeFileWriterTest/testShapeFileWriter/test.shx rename to matsim/src/test/resources/test/input/org/matsim/core/utils/gis/GeoFileWriterTest/testShapeFileWriter/test.shx diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/correct.fp.zst b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/correct.fp.zst new file mode 100644 index 0000000000000000000000000000000000000000..7bf62ca48e26975c0b7ed02c29daada8427db755 GIT binary patch literal 196 zcmdPcs{fZE;s`543a49uz99nx1Gn1>9tJ*l>%$E0wpu_w7XwdfUP)?EYKlTmW?nW> zgo%MYv8X7sEHMYjVPxP;Ni9e$Dk&{WWlKyhNzF?U4oEF3&d+lN=_(FO&B#p75i3*3 zNlh$EEmkNgN=!@3O!nc-NlhzZWZ(d5DJ}tO2N|WY!Q$}xlNm+}6d&AQ7IO5A#^z7U oc^OokHBQWsU_9V_{@bCh@EMC;v)-J}J)Oh7gH=4b3}^%c07D-^;{X5v literal 0 HcmV?d00001 diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.attribute-order.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.attribute-order.xml new file mode 100644 index 00000000000..6885fa8af5d --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.attribute-order.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-hash.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-hash.xml new file mode 100644 index 00000000000..4ae06c2369f --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-hash.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-num-timestamps.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-num-timestamps.xml new file mode 100644 index 00000000000..422b58d651d --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-num-timestamps.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-type-count.fp.zst b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-type-count.fp.zst new file mode 100644 index 0000000000000000000000000000000000000000..6437b813ac0fd615f3a74dea6c4492d7f5cca149 GIT binary patch literal 194 zcmdPcs{fZEVhbyS2&Y?sz99nx1Gn1>9tJ*l>%$E0wpu_w7XwdfUP)?EYKlTmW?nW> zgpq+gv8X7sEHQ^OCAA>2sHC(gl`S#3BsDKZI3TsCI6u!7q@g%0H6t@QN32XCCpEDw zwOFB~C^0Q9GuekTCpE2viGc&CrMLvB9b{yoZfn9FuFS{f&vgpd+TJXxYGnS-$Drb@ nabku9;{oUM-wt(!&sgl5_2zW$OkUpLf(JY?x literal 0 HcmV?d00001 diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-type-count.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-type-count.xml new file mode 100644 index 00000000000..31662fae9c0 --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-type-count.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order-wrong_logic.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order-wrong_logic.xml new file mode 100644 index 00000000000..1112364be0c --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order-wrong_logic.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order.xml new file mode 100644 index 00000000000..c4b9bbf33de --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.one-more-event.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.one-more-event.xml new file mode 100644 index 00000000000..663754db63f --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.one-more-event.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events_correct.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events_correct.xml new file mode 100644 index 00000000000..4b2bbbd1b92 --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events_correct.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 3ad76d1e35e..1c0ee40790c 100644 --- a/pom.xml +++ b/pom.xml @@ -30,12 +30,12 @@ 17 - 2.22.1 - 29.2 + 2.23.1 + 29.5 0.49.2 1.19.0 7.0.0 - 2.16.1 + 2.16.2 2.5.0 5.10.2 @@ -118,7 +118,7 @@ org.apache.commons commons-compress - 1.25.0 + 1.26.1 commons-logging @@ -128,13 +128,18 @@ commons-codec commons-codec - 1.16.0 + 1.16.1 org.apache.commons commons-text 1.11.0 + + commons-io + commons-io + 2.15.1 + com.opencsv opencsv @@ -187,7 +192,7 @@ org.glassfish.jaxb jaxb-bom - 4.0.4 + 4.0.5 pom import @@ -195,7 +200,7 @@ com.google.errorprone error_prone_annotations - 2.24.1 + 2.26.1 @@ -207,7 +212,7 @@ com.fasterxml.woodstox woodstox-core - 6.6.0 + 6.6.1 @@ -232,7 +237,7 @@ org.slf4j slf4j-api - 2.0.11 + 2.0.12 @@ -298,7 +303,7 @@ it.unimi.dsi fastutil - 8.5.12 + 8.5.13 @@ -311,13 +316,13 @@ org.mockito mockito-core - 5.10.0 + 5.11.0 test org.mockito mockito-junit-jupiter - 5.10.0 + 5.11.0 test @@ -342,7 +347,7 @@ net.bytebuddy byte-buddy - 1.14.11 + 1.14.12 test @@ -354,7 +359,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.12.1 + 3.13.0 org.apache.maven.plugins