From 2e03c9b3ea5a4776d6dca51309bd1194bfe97f56 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Tue, 23 Jan 2024 15:50:49 +0100 Subject: [PATCH 01/51] include planType in GenericWorstPlanForRemovalSelector. Has still one compileError. --- .../GenericWorstPlanForRemovalSelector.java | 112 +++++++++++------- 1 file changed, 70 insertions(+), 42 deletions(-) diff --git a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java index 116cd309427..953a8d48123 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java +++ b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java @@ -25,54 +25,82 @@ import org.matsim.api.core.v01.population.BasicPlan; import org.matsim.api.core.v01.population.HasPlansAndId; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** - *

Selects the worst plan of a person (most likely for removal). + *

Selects the worst plan of a person (most likely for removal), but respects + * the set plan types in a way the no plan is selected that is the last one of + * its type.

+ *

(I would say that it can select the last of its type if it finds nothing else. However, this algo should only + * be used if an agent has more plans than maxPlansPerAgent, so make sure that that parameter is set large enough for + * your purposes. kai, oct'09)

*

Plans without a score are seen as worst and selected accordingly.

* * @author mrieser */ public class GenericWorstPlanForRemovalSelector implements PlanSelector { - private static final String UNDEFINED_TYPE = "undefined"; - - @Override - public T selectPlan(HasPlansAndId person) { - - T worst = null; - double worstScore = Double.POSITIVE_INFINITY; - for (T plan : person.getPlans()) { - - // if this plan has no score yet: - if (plan.getScore() == null || plan.getScore().isNaN() ) { - // say that the plan without score now is the "worst": - worst = plan; - - // make sure that this one remains the selected plan: - worstScore = Double.NEGATIVE_INFINITY; - - // otherwise do the usual logic to find the plan with the minimum score: - } else if (plan.getScore() < worstScore) { - worst = plan; - worstScore = plan.getScore(); - } - // (otherwise we just keep "worst=null") - - } - - if (worst == null) { - // there is exactly one plan, or we have of each plan-type exactly one. - // select the one with worst score globally, or the first one with score=null - for (T plan : person.getPlans()) { - if (plan.getScore() == null || plan.getScore().isNaN() ) { - return plan; - } - if (plan.getScore() < worstScore) { - worst = plan; - worstScore = plan.getScore(); - } - } - } - return worst; - } + private static final String UNDEFINED_TYPE = "undefined"; + + @Override + public T selectPlan(HasPlansAndId person) { + + // hashmap that returns "Integer" count for given plans type: + Map typeCounts = new ConcurrentHashMap(); + + // count how many plans per type an agent has: + for (T plan : person.getPlans()) { + String type = plan.getType(); + if ( type==null ) { + type = UNDEFINED_TYPE ; + } + typeCounts.merge( type, 1, ( a, b ) -> a + b ); + } + + T worst = null; + double worstScore = Double.POSITIVE_INFINITY; + for (T plan : person.getPlans()) { + + String type = plan.getType(); + if ( type==null ) { + type = UNDEFINED_TYPE; + } + if ( typeCounts.get( type ) > 1) { + // (if we have more than one plan of the same type:) + + // if this plan has no score yet: + if (plan.getScore() == null || plan.getScore().isNaN() ) { + // say that the plan without score now is the "worst": + worst = plan; + + // make sure that this one remains the selected plan: + worstScore = Double.NEGATIVE_INFINITY; + + // otherwise do the usual logic to find the plan with the minimum score: + } else if (plan.getScore() < worstScore) { + worst = plan; + worstScore = plan.getScore(); + } + } + // (otherwise we just keep "worst=null") + + } + + if (worst == null) { + // there is exactly one plan, or we have of each plan-type exactly one. + // select the one with worst score globally, or the first one with score=null + for (T plan : person.getPlans()) { + if (plan.getScore() == null || plan.getScore().isNaN() ) { + return plan; + } + if (plan.getScore() < worstScore) { + worst = plan; + worstScore = plan.getScore(); + } + } + } + return worst; + } } From 4254dc4d81f763d058974dc36abf244b36c5d88c Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 22 Feb 2024 09:11:50 +0100 Subject: [PATCH 02/51] reorganize shape files input to reduce preprocessing of the shape files --- ...rateSmallScaleCommercialTrafficDemand.java | 22 +- .../LanduseBuildingAnalysis.java | 69 ++--- .../SmallScaleCommercialTrafficUtils.java | 33 ++- .../TrafficVolumeGeneration.java | 2 +- .../TripDistributionMatrix.java | 46 ++-- .../LanduseBuildingAnalysisTest.java | 255 +++++++++--------- ...nerateSmallScaleCommercialTrafficTest.java | 6 + .../SCTUtils.java | 7 +- .../SmallScaleCommercialTrafficUtilsTest.java | 16 +- .../TrafficVolumeGenerationTest.java | 75 +++--- .../TripDistributionMatrixTest.java | 37 +-- .../dataDistributionPerZone.csv | 8 +- .../investigationAreaData.csv | 6 +- .../shp/testRegions.cpg | 1 + .../shp/testRegions.dbf | Bin 0 -> 280 bytes .../shp/testRegions.prj | 1 + .../shp/testRegions.qmd | 26 ++ .../shp/testRegions.shp | Bin 0 -> 372 bytes .../shp/testRegions.shx | Bin 0 -> 116 bytes 19 files changed, 363 insertions(+), 247 deletions(-) create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.cpg create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.dbf create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.prj 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 diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java index 46ec4a745b6..6cc38e81e97 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java @@ -135,9 +135,18 @@ 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; @@ -169,6 +178,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,19 +235,23 @@ public Integer call() throws Exception { if (!Files.exists(shapeFileZonePath)) { throw new Exception("Required districts shape file {} not found" + shapeFileZonePath.toString()); } + if (!Files.exists(shapeFileRegionsPath)) { + throw new Exception("Required regions shape file {} not found" + shapeFileRegionsPath.toString()); + } Path inputDataDirectory = Path.of(config.getContext().toURI()).getParent(); ShpOptions shpZones = new ShpOptions(shapeFileZonePath, shapeCRS, StandardCharsets.UTF_8); - indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS); + indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS, shapeFileZoneNameColumn); indexBuildings = SmallScaleCommercialTrafficUtils.getIndexBuildings(shapeFileBuildingsPath, shapeCRS); indexLanduse = SmallScaleCommercialTrafficUtils.getIndexLanduse(shapeFileLandusePath, shapeCRS); + indexInvestigationAreaRegions = SmallScaleCommercialTrafficUtils.getIndexRegions(shapeFileRegionsPath, shapeCRS, regionsShapeRegionColumn); Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, usedLanduseConfiguration.toString(), indexLanduse, indexZones, - indexBuildings, buildingsPerZone); - + indexBuildings, indexInvestigationAreaRegions, shapeFileZoneNameColumn, buildingsPerZone); + //TODO regionLinksMap umbenennen, da es alle Links einer Zone enthält Map, Link>> regionLinksMap = filterLinksForZones(scenario, indexZones, buildingsPerZone); switch (usedSmallScaleCommercialTrafficType) { @@ -971,7 +985,7 @@ private TripDistributionMatrix createTripDistribution( Collections.shuffle(listOfZones); for (String stopZone : listOfZones) { odMatrix.setTripDistributionValue(startZone, stopZone, modeORvehType, purpose, smallScaleCommercialTrafficType, - network, regionLinksMap, resistanceFactor); + network, regionLinksMap, resistanceFactor, shapeFileZoneNameColumn); } } } diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java index faffac894c1..4104b09983a 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java @@ -56,11 +56,12 @@ public class LanduseBuildingAnalysis { static Map> createInputDataDistribution(Path output, Map> landuseCategoriesAndDataConnection, Path inputDataDirectory, String usedLanduseConfiguration, Index indexLanduse, Index indexZones, - Index indexBuildings, Map>> buildingsPerZone) + Index indexBuildings, Index indexInvestigationAreaRegions, + String shapeFileZoneNameColumn, Map>> buildingsPerZone) 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", @@ -91,7 +92,7 @@ static Map> createInputDataDistribution(Path ou .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), @@ -109,18 +110,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); createResultingDataForLanduseInZones(landuseCategoriesPerZone, investigationAreaData, resultingDataPerZone, - landuseCategoriesAndDataConnection); + landuseCategoriesAndDataConnection, zoneIdRegionConnection); SmallScaleCommercialTrafficUtils.writeResultOfDataDistribution(resultingDataPerZone, outputFileInOutputFolder, - zoneIdNameConnection); + zoneIdRegionConnection); } return resultingDataPerZone; @@ -131,10 +132,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 +150,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 +162,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 +177,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 +194,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,10 +217,10 @@ 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"); @@ -227,12 +228,20 @@ private static void createLanduseDistribution(Map 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")); + // TODO comment + 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")) { @@ -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/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java index 1ea26e82ee3..690b4f68920 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java @@ -77,12 +77,15 @@ 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"); + return shpZones.createIndex(shapeCRS, shapeFileZoneNameColumn); } /** @@ -107,14 +110,28 @@ static Index getIndexBuildings(Path shapeFileBuildingsPath, String shapeCRS) { 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 shpLanduse = new ShpOptions(shapeFileRegionsPath, shapeCRS, StandardCharsets.UTF_8); + return shpLanduse.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); } @@ -158,11 +175,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 +187,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); diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java index 7e9e591eabc..3ae24470958 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java @@ -221,7 +221,7 @@ private static void writeCSVTrafficVolume(Map, Link>> regionLinksMap, double resistanceFactor) { + Map, Link>> regionLinksMap, 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 resistanceValue = getResistanceFunktionValue(startZone, stopZone, network, regionLinksMap, resistanceFactor, shapeFileZoneNameColumn); double gravityConstantA = getGravityConstant(stopZone, trafficVolume_start, modeORvehType, purpose, network, regionLinksMap, - resistanceFactor); + resistanceFactor, shapeFileZoneNameColumn); roundingError.computeIfAbsent(stopZone, (k) -> new Object2DoubleOpenHashMap<>()); //Bisher: Gravity model mit fixem Zielverkehr @@ -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 regionLinksMap 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>> regionLinksMap, + 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; @@ -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 regionLinksMap 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>> regionLinksMap, 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); + regionLinksMap, resistanceFactor, shapeFileZoneNameColumn); sum = sum + (volume * resistanceValue); } } diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java index be97112e74c..7762b156cc5 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java @@ -51,18 +51,20 @@ void testReadOfDataDistributionPerZoneAndBuildingAnalysis() throws IOException { assert(new File(output.resolve("calculatedData").toString()).mkdir()); Path inputDataDirectory = Path.of(utils.getPackageInputDirectory()); String usedLanduseConfiguration = "useExistingDataDistribution"; + String shapeFileZoneNameColumn = "name"; // Test if the reading of the existing data distribution works correctly Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); 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); @@ -86,60 +88,64 @@ 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 @@ -149,12 +155,12 @@ void testReadOfDataDistributionPerZoneAndBuildingAnalysis() throws IOException { 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); @@ -184,7 +190,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); @@ -208,7 +214,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); @@ -238,18 +244,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"; // Analyze resultingData per zone Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); 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); @@ -273,60 +281,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 index 62127e7e2f5..75665b3a809 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java @@ -55,7 +55,10 @@ void testMainRunAndResults() { 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 landuseShapeFileName = utils.getPackageInputDirectory() + "/shp/testLanduse.shp"; String shapeCRS = "EPSG:4326"; @@ -68,7 +71,10 @@ void testMainRunAndResults() { "--landuseConfiguration", landuseConfiguration, "--smallScaleCommercialTrafficType", smallScaleCommercialTrafficType, "--includeExistingModels", + "--regionsShapeFileName", regionsShapeFileName, + "--regionsShapeRegionColumn", regionsShapeRegionColumn, "--zoneShapeFileName", zoneShapeFileName, + "--zoneShapeFileNameColumn", zoneShapeFileNameColumn, "--buildingsShapeFileName", buildingsShapeFileName, "--landuseShapeFileName", landuseShapeFileName, "--shapeCRS", shapeCRS); diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SCTUtils.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SCTUtils.java index 7b16b902d08..843a690196d 100644 --- a/contribs/small-scale-traffic-generation/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/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java index 61d3f759aac..5aa06d111fc 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java @@ -59,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/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java index b1646548777..cfac585157a 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java @@ -60,11 +60,13 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { assert(new File(output.resolve("calculatedData").toString()).mkdir()); Path inputDataDirectory = Path.of(utils.getPackageInputDirectory()); String usedLanduseConfiguration = "useExistingDataDistribution"; + String shapeFileZoneNameColumn = "name"; Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); String usedTrafficType = "commercialPersonTraffic"; @@ -86,7 +88,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); @@ -99,7 +101,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); @@ -112,7 +114,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); @@ -136,7 +138,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); @@ -149,7 +151,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); @@ -162,7 +164,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); @@ -186,11 +188,13 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { assert(new File(output.resolve("calculatedData").toString()).mkdir()); Path inputDataDirectory = Path.of(utils.getPackageInputDirectory()); String usedLanduseConfiguration = "useExistingDataDistribution"; + String shapeFileZoneNameColumn = "name"; Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); String usedTrafficType = "goodsTraffic"; double sample = 1.; @@ -214,7 +218,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { } } - // test for "testArea1_area1" + // test for "area1" HashMap estimatesStart = new HashMap<>(); estimatesStart.put(1, 12.); estimatesStart.put(2, 30.); @@ -234,7 +238,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")) { @@ -317,7 +321,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.); @@ -337,7 +341,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); } @@ -345,7 +349,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.); @@ -365,7 +369,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); } @@ -388,9 +392,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); @@ -414,7 +420,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()); @@ -428,7 +434,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()); @@ -447,6 +453,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); @@ -455,7 +463,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); @@ -478,7 +487,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()); @@ -502,6 +511,8 @@ 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"; + ArrayList modesORvehTypes = new ArrayList<>( Arrays.asList("vehTyp1", "vehTyp2", "vehTyp3", "vehTyp4", "vehTyp5")); Config config = ConfigUtils.createConfig(); @@ -515,7 +526,8 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); Map> trafficVolumePerTypeAndZone_start = TrafficVolumeGeneration .createTrafficVolume_start(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); @@ -530,7 +542,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { 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.); @@ -550,7 +562,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")) { @@ -573,7 +585,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.); @@ -593,7 +605,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); } @@ -601,7 +613,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.); @@ -621,7 +633,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")) { @@ -657,6 +669,8 @@ 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"; + ArrayList modesORvehTypes = new ArrayList<>( List.of("total")); Config config = ConfigUtils.createConfig(); @@ -670,7 +684,8 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); Map> trafficVolumePerTypeAndZone_start = TrafficVolumeGeneration .createTrafficVolume_start(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); @@ -688,7 +703,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); @@ -701,7 +716,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); @@ -714,7 +729,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/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java index adc41f61191..3c449937d90 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java @@ -59,10 +59,13 @@ 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"; + Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); String usedTrafficType = "commercialPersonTraffic"; double sample = 1.; @@ -79,12 +82,12 @@ void testTripDistributionCommercialPersonTrafficTraffic() throws IOException { .newInstance(getZoneIndex(inputDataDirectory), trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, usedTrafficType).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 +95,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 +147,12 @@ 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"; Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); String usedTrafficType = "goodsTraffic"; double sample = 1.; @@ -165,12 +170,12 @@ void testTripDistributionGoodsTraffic() throws IOException { .newInstance(getZoneIndex(inputDataDirectory), trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, usedTrafficType).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 +183,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/dataDistributionPerZone.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/dataDistributionPerZone.csv index 70857ece6c1..0a841cc7dd0 100644 --- 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 @@ -1,4 +1,4 @@ -areaID areaName Inhabitants Employee Employee Primary Sector Employee Construction Employee Secondary Sector Rest Employee Retail Employee Traffic/Parcels Employee Tertiary Sector Rest -testArea1_area2 area2 4000 6500 500 1500 500 500 1500 2000 -testArea2_area3 area3 800 1000 50 200 100 150 200 300 -testArea1_area1 area1 4000 3500 0 500 500 1000 500 1000 \ No newline at end of file +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/investigationAreaData.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/investigationAreaData.csv index e8dd1cb57ff..97fe8fd80b7 100644 --- 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 @@ -1,3 +1,3 @@ -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 +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/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.cpg b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.cpg new file mode 100644 index 00000000000..3ad133c048f --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.cpg @@ -0,0 +1 @@ +UTF-8 \ No newline at end of file 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/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.prj b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.prj new file mode 100644 index 00000000000..f45cbadf007 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.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/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 From 678d802f06290479415150bf059fe7ca9f6f8920 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 22 Feb 2024 09:12:48 +0100 Subject: [PATCH 03/51] use recent methods --- .../SmallScaleCommercialTrafficUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java index 690b4f68920..d862d842dad 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java @@ -273,8 +273,8 @@ else if (subpopulation.contains("goodsTraffic")) Id 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); } From 63455403e38b531e8fcd6f63ccd9e9f27b4fdb91 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 22 Feb 2024 16:07:22 +0100 Subject: [PATCH 04/51] adjust test --- .../TripDistributionMatrixTest.java | 4 ++-- ...icVolume_commercialPersonTraffic_startPerZone_10pt.csv | 8 ++++---- ...ficVolume_commercialPersonTraffic_stopPerZone_10pt.csv | 8 ++++---- .../calculatedData/dataDistributionPerZone.csv | 8 ++++---- .../odMatrix_commercialPersonTraffic_total_purpose1.csv | 8 ++++---- .../odMatrix_commercialPersonTraffic_total_purpose2.csv | 8 ++++---- .../odMatrix_commercialPersonTraffic_total_purpose3.csv | 8 ++++---- .../odMatrix_commercialPersonTraffic_total_purpose4.csv | 8 ++++---- .../odMatrix_commercialPersonTraffic_total_purpose5.csv | 8 ++++---- 9 files changed, 34 insertions(+), 34 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java index 51ec2149f3e..76f6c0b6cd8 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java @@ -78,7 +78,7 @@ void testTripDistributionCommercialPersonTrafficTraffic() throws IOException { .createTrafficVolume_start(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); Map> trafficVolumePerTypeAndZone_stop = TrafficVolumeGeneration .createTrafficVolume_stop(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); - ArrayList listOfZones = new ArrayList<>( List.of("testArea1_area1", "testArea1_area2", "testArea2_area3")); + ArrayList listOfZones = new ArrayList<>( List.of("area1", "area2", "area3")); final TripDistributionMatrix odMatrix = TripDistributionMatrix.Builder .newInstance(getZoneIndex(inputDataDirectory), trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, usedTrafficType, listOfZones).build(); @@ -162,7 +162,7 @@ void testTripDistributionGoodsTraffic() throws IOException { ArrayList modesORvehTypes = new ArrayList( Arrays.asList("vehTyp1", "vehTyp2", "vehTyp3", "vehTyp4", "vehTyp5")); - ArrayList listOfZones = new ArrayList<>( List.of("testArea1_area1", "testArea1_area2", "testArea2_area3")); + ArrayList listOfZones = new ArrayList<>( List.of("area1", "area2", "area3")); TrafficVolumeGeneration.setInputParameters(usedTrafficType); 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 index bfdf8e63f8c..d946fd0733e 100644 --- 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 @@ -1,4 +1,4 @@ -areaID mode/vehType 1 2 3 4 5 -testArea2_area3 total 1 3 8 6 9 -testArea1_area2 total 3 21 51 44 63 -testArea1_area1 total 3 12 28 18 25 +zoneID mode/vehType 1 2 3 4 5 +area3 total 1 3 8 6 9 +area2 total 3 21 51 44 63 +area1 total 3 12 28 18 25 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_stopPerZone_10pt.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_stopPerZone_10pt.csv index 0c53286d73b..b9bc1b4faed 100644 --- 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 @@ -1,4 +1,4 @@ -areaID mode/vehType 1 2 3 4 5 -testArea2_area3 total 0 3 13 4 2 -testArea1_area2 total 1 20 86 25 10 -testArea1_area1 total 1 10 43 12 6 +zoneID mode/vehType 1 2 3 4 5 +area3 total 0 3 13 4 2 +area2 total 1 20 86 25 10 +area1 total 1 10 43 12 6 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/dataDistributionPerZone.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/dataDistributionPerZone.csv index 70857ece6c1..0a841cc7dd0 100644 --- 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 @@ -1,4 +1,4 @@ -areaID areaName Inhabitants Employee Employee Primary Sector Employee Construction Employee Secondary Sector Rest Employee Retail Employee Traffic/Parcels Employee Tertiary Sector Rest -testArea1_area2 area2 4000 6500 500 1500 500 500 1500 2000 -testArea2_area3 area3 800 1000 50 200 100 150 200 300 -testArea1_area1 area1 4000 3500 0 500 500 1000 500 1000 \ No newline at end of file +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 index 38573c7f4c0..05a9702515f 100644 --- 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 @@ -1,4 +1,4 @@ - testArea2_area3 testArea1_area2 testArea1_area1 -testArea2_area3 0 0 0 -testArea1_area2 0 1 0 -testArea1_area1 0 0 1 + area3 area2 area1 +area3 0 0 0 +area2 0 1 0 +area1 0 0 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose2.csv index 30cf57e5fc3..2d38380ff79 100644 --- 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 @@ -1,4 +1,4 @@ - testArea2_area3 testArea1_area2 testArea1_area1 -testArea2_area3 0 0 0 -testArea1_area2 0 8 7 -testArea1_area1 1 5 3 + area3 area2 area1 +area3 0 0 0 +area2 0 8 7 +area1 1 5 3 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose3.csv index 44108374c44..b2faebe2b79 100644 --- 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 @@ -1,4 +1,4 @@ - testArea2_area3 testArea1_area2 testArea1_area1 -testArea2_area3 2 7 3 -testArea1_area2 7 52 25 -testArea1_area1 4 27 15 + area3 area2 area1 +area3 2 7 3 +area2 7 52 25 +area1 4 27 15 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose4.csv index 6cebadd2f70..315a6675069 100644 --- 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 @@ -1,4 +1,4 @@ - testArea2_area3 testArea1_area2 testArea1_area1 -testArea2_area3 0 2 2 -testArea1_area2 2 17 7 -testArea1_area1 2 6 3 + area3 area2 area1 +area3 0 2 2 +area2 2 17 7 +area1 2 6 3 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose5.csv index 5d7cb865fbf..3024476606f 100644 --- 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 @@ -1,4 +1,4 @@ - testArea2_area3 testArea1_area2 testArea1_area1 -testArea2_area3 0 0 0 -testArea1_area2 1 7 4 -testArea1_area1 1 3 2 + area3 area2 area1 +area3 0 0 0 +area2 1 7 4 +area1 1 3 2 From 58f3f2f7ec1e20ea6e78bf59ca470000b812650d Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 22 Feb 2024 16:07:58 +0100 Subject: [PATCH 05/51] typo --- .../RunGenerateSmallScaleCommercialTrafficTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java index be8228818e9..52a9ab55185 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java @@ -115,11 +115,11 @@ void testMainRunAndResults() { } Assertions.assertEquals(population.getPersons().size(), countedTours, 0); - for (File caculatedFile : Objects.requireNonNull( + for (File calculatedFile : Objects.requireNonNull( Objects.requireNonNull(new File(utils.getOutputDirectory() + "calculatedData").listFiles()))) { MatsimTestUtils.assertEqualFilesLineByLine( - utils.getPackageInputDirectory() + "calculatedData/" + caculatedFile.getName(), - caculatedFile.getAbsolutePath()); + utils.getPackageInputDirectory() + "calculatedData/" + calculatedFile.getName(), + calculatedFile.getAbsolutePath()); } // compare events From ae0bc3eaef6cbb32f4fc28c0a2021e35b16f774f Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 22 Feb 2024 16:08:30 +0100 Subject: [PATCH 06/51] add missing parameter --- .../GenerateSmallScaleCommercialTrafficDemand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java index 836a90894c5..1cde92e04aa 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java @@ -241,7 +241,7 @@ public Integer call() throws Exception { } Path inputDataDirectory = Path.of(config.getContext().toURI()).getParent(); - indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS); + indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS, shapeFileZoneNameColumn); indexBuildings = SmallScaleCommercialTrafficUtils.getIndexBuildings(shapeFileBuildingsPath, shapeCRS); indexLanduse = SmallScaleCommercialTrafficUtils.getIndexLanduse(shapeFileLandusePath, shapeCRS); indexInvestigationAreaRegions = SmallScaleCommercialTrafficUtils.getIndexRegions(shapeFileRegionsPath, shapeCRS, regionsShapeRegionColumn); From 81ad86260f9f162270ffdf789110646d6f20f2de Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 22 Feb 2024 21:26:34 +0100 Subject: [PATCH 07/51] adjust tests for new structure of generation --- ...nerateSmallScaleCommercialTrafficTest.java | 66 ++++++++++++++++-- ...mercialPersonTraffic_startPerZone_10pt.csv | 2 +- ...mmercialPersonTraffic_stopPerZone_10pt.csv | 2 +- ...commercialPersonTraffic_total_purpose1.csv | 6 +- ...commercialPersonTraffic_total_purpose2.csv | 6 +- ...commercialPersonTraffic_total_purpose3.csv | 8 +-- ...commercialPersonTraffic_total_purpose4.csv | 8 +-- ...commercialPersonTraffic_total_purpose5.csv | 8 +-- .../test.output_events.xml.gz | Bin 35753 -> 31240 bytes 9 files changed, 82 insertions(+), 24 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java index 52a9ab55185..ad41064119a 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java @@ -19,6 +19,11 @@ * *********************************************************************** */ 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; @@ -30,13 +35,18 @@ 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.EventsFileComparator; +import java.io.BufferedReader; import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; /** @@ -117,15 +127,63 @@ void testMainRunAndResults() { for (File calculatedFile : Objects.requireNonNull( Objects.requireNonNull(new File(utils.getOutputDirectory() + "calculatedData").listFiles()))) { - MatsimTestUtils.assertEqualFilesLineByLine( - utils.getPackageInputDirectory() + "calculatedData/" + calculatedFile.getName(), - calculatedFile.getAbsolutePath()); + 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 expected = utils.getPackageInputDirectory() + "test.output_events.xml.gz"; String actual = utils.getOutputDirectory() + "test.output_events.xml.gz" ; EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); Assertions.assertEquals( EventsFileComparator.Result.FILES_ARE_EQUAL, result ); } + + /** + * 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/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 index d946fd0733e..76905762d24 100644 --- 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 @@ -1,4 +1,4 @@ zoneID mode/vehType 1 2 3 4 5 -area3 total 1 3 8 6 9 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 index b9bc1b4faed..837a7d38659 100644 --- 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 @@ -1,4 +1,4 @@ zoneID mode/vehType 1 2 3 4 5 -area3 total 0 3 13 4 2 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/odMatrix_commercialPersonTraffic_total_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose1.csv index 05a9702515f..1bc43756980 100644 --- 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 @@ -1,4 +1,4 @@ - area3 area2 area1 +O/D area2 area1 area3 +area2 1 0 0 +area1 0 1 0 area3 0 0 0 -area2 0 1 0 -area1 0 0 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose2.csv index 2d38380ff79..5b49558b3a5 100644 --- 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 @@ -1,4 +1,4 @@ - area3 area2 area1 +O/D area2 area1 area3 +area2 8 6 0 +area1 5 4 1 area3 0 0 0 -area2 0 8 7 -area1 1 5 3 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose3.csv index b2faebe2b79..04d2d8af059 100644 --- 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 @@ -1,4 +1,4 @@ - area3 area2 area1 -area3 2 7 3 -area2 7 52 25 -area1 4 27 15 +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 index 315a6675069..3d2f4777106 100644 --- 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 @@ -1,4 +1,4 @@ - area3 area2 area1 -area3 0 2 2 -area2 2 17 7 -area1 2 6 3 +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 index 3024476606f..ac996432028 100644 --- 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 @@ -1,4 +1,4 @@ - area3 area2 area1 -area3 0 0 0 -area2 1 7 4 -area1 1 3 2 +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/test.output_events.xml.gz b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz index a3f7231747b670ea68e7ba42dd8450140bb559ba..cedefa5d9a5ec188923a208878e0c7c869076d31 100644 GIT binary patch literal 31240 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 literal 35753 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 From 0a286030c64a8960dd280757ab3a12cd9cf88795 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 22 Feb 2024 21:26:47 +0100 Subject: [PATCH 08/51] add column name --- .../TripDistributionMatrix.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java index 991c6d9a39d..c2a032545b5 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java @@ -605,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"); From 7c8b142639290030c227b7df9602d0cbda2cc538 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 22 Feb 2024 21:32:38 +0100 Subject: [PATCH 09/51] change name --- ...rateSmallScaleCommercialTrafficDemand.java | 21 ++++++++-------- .../SmallScaleCommercialTrafficUtils.java | 16 ++++++------- .../TrafficVolumeGeneration.java | 20 ++++++++-------- .../TripDistributionMatrix.java | 24 +++++++++---------- 4 files changed, 40 insertions(+), 41 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java index 1cde92e04aa..15455c08a70 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java @@ -250,19 +250,18 @@ public Integer call() throws Exception { .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, usedLanduseConfiguration.toString(), indexLanduse, indexZones, indexBuildings, indexInvestigationAreaRegions, shapeFileZoneNameColumn, buildingsPerZone); - //TODO regionLinksMap umbenennen, da es alle Links einer Zone enthält - Map, Link>> regionLinksMap = filterLinksForZones(scenario, indexZones, buildingsPerZone); + Map, Link>> linksPerZone = filterLinksForZones(scenario, indexZones, buildingsPerZone); switch (usedSmallScaleCommercialTrafficType) { case commercialPersonTraffic, goodsTraffic -> - createCarriersAndDemand(output, scenario, resultingDataPerZone, regionLinksMap, + createCarriersAndDemand(output, scenario, resultingDataPerZone, linksPerZone, usedSmallScaleCommercialTrafficType.toString(), includeExistingModels); case completeSmallScaleCommercialTraffic -> { - createCarriersAndDemand(output, scenario, resultingDataPerZone, regionLinksMap, "commercialPersonTraffic", + createCarriersAndDemand(output, scenario, resultingDataPerZone, linksPerZone, "commercialPersonTraffic", includeExistingModels); includeExistingModels = false; // because already included in the step before - createCarriersAndDemand(output, scenario, resultingDataPerZone, regionLinksMap, "goodsTraffic", + createCarriersAndDemand(output, scenario, resultingDataPerZone, linksPerZone, "goodsTraffic", includeExistingModels); } default -> throw new RuntimeException("No traffic type selected."); @@ -274,7 +273,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) @@ -438,7 +437,7 @@ private void solveSeparatedVRPs(Scenario originalScenario, Map> resultingDataPerZone, - Map, Link>> regionLinksMap, String smallScaleCommercialTrafficType, + Map, Link>> linksPerZone, String smallScaleCommercialTrafficType, boolean includeExistingModels) throws Exception { ArrayList modesORvehTypes; @@ -458,13 +457,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, smallScaleCommercialTrafficType, scenario, output, regionLinksMap); - createCarriers(scenario, odMatrix, resultingDataPerZone, smallScaleCommercialTrafficType, regionLinksMap); + trafficVolumePerTypeAndZone_stop, smallScaleCommercialTrafficType, scenario, output, linksPerZone); + createCarriers(scenario, odMatrix, resultingDataPerZone, smallScaleCommercialTrafficType, linksPerZone); } /** diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java index d862d842dad..1b43d411522 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java @@ -135,11 +135,11 @@ static void writeResultOfDataDistribution(Map> log.info("The data distribution is finished and written to: " + outputFileInOutputFolder); } - static Id findNearestPossibleLink(String zone, List noPossibleLinks, Map, Link>> regionLinksMap, + 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()) @@ -157,7 +157,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) { @@ -314,7 +314,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(); @@ -515,7 +515,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); } @@ -543,9 +543,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/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java index 3d4588c5300..b376d16d176 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java @@ -267,13 +267,13 @@ static void setInputParameters(String smallScaleCommercialTrafficType) { * Reduces the traffic volumes based on the added existing models. * * @param scenario scenario - * @param regionLinksMap links for each zone + * @param linksPerZone links for each zone * @param smallScaleCommercialTrafficType used trafficType (commercialPersonTraffic or goodsTraffic) * @param trafficVolumePerTypeAndZone_start trafficVolume for start potentials for each zone * @param trafficVolumePerTypeAndZone_stop trafficVolume for stop potentials for each zone */ static void reduceDemandBasedOnExistingCarriers(Scenario scenario, - 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); diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java index c2a032545b5..f577c73deaa 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java @@ -289,18 +289,18 @@ private TripDistributionMatrix(Builder builder) { * @param modeORvehType selected mode or vehicle type * @param purpose selected purpose * @param smallScaleCommercialTrafficType goodsTraffic or commercialPersonTraffic - * @param regionLinksMap links in each zone - * @param shapeFileZoneNameColumn Name of the unique column of the name/Id of each zone in the zones shape file + * @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, String shapeFileZoneNameColumn) { + 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, shapeFileZoneNameColumn); - double gravityConstantA = getGravityConstant(stopZone, trafficVolume_start, modeORvehType, purpose, network, regionLinksMap, + 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<>()); @@ -339,10 +339,10 @@ Integer getTripDistributionValue(String startZone, String stopZone, String modeO * * @param startZone start zone * @param stopZone stop zone - * @param regionLinksMap links for each 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, + 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 @@ -371,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); @@ -450,13 +450,13 @@ private VehicleImpl getExampleVehicle(Location fromId) { * @param trafficVolume volume of the traffic * @param modeORvehType selected mode or vehicle type * @param purpose selected purpose - * @param regionLinksMap links for each 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 * @return gravity constant */ private double getGravityConstant(String baseZone, Map> trafficVolume, String modeORvehType, - Integer purpose, Network network, Map, Link>> regionLinksMap, double resistanceFactor, String shapeFileZoneNameColumn) { + Integer purpose, Network network, Map, Link>> linksPerZone, double resistanceFactor, String shapeFileZoneNameColumn) { GravityConstantKey gravityKey = makeGravityKey(baseZone, modeORvehType, purpose); if (!gravityConstantACache.containsKey(gravityKey)) { @@ -468,7 +468,7 @@ private double getGravityConstant(String baseZone, continue; else { double resistanceValue = getResistanceFunktionValue(baseZone, trafficVolumeKey.getZone(), network, - regionLinksMap, resistanceFactor, shapeFileZoneNameColumn); + linksPerZone, resistanceFactor, shapeFileZoneNameColumn); sum = sum + (volume * resistanceValue); } } From 2cf9f4cb7f7eef5ba1cd81ed68f2812e6af1c271 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 27 Feb 2024 16:06:18 +0100 Subject: [PATCH 10/51] add comment --- .../GenerateSmallScaleCommercialTrafficDemand.java | 2 +- .../SmallScaleCommercialTrafficUtils.java | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java index 15455c08a70..7ffec55f486 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java @@ -36,7 +36,6 @@ 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.gbl.MatsimRandom; @@ -101,6 +100,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 { diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java index 1b43d411522..0b355bdc7c5 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java @@ -135,6 +135,15 @@ static void writeResultOfDataDistribution(Map> log.info("The data distribution is finished and written to: " + outputFileInOutputFolder); } + /** 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; @@ -206,7 +215,6 @@ private static void writeCSVWithCategoryHeader(Map Date: Wed, 6 Mar 2024 07:16:45 +0100 Subject: [PATCH 11/51] feat: transit routing by transport mode utilities --- .../routing/pt/raptor/RaptorParameters.java | 10 +++++ .../pt/raptor/SwissRailRaptorCore.java | 4 +- .../pt/raptor/SwissRailRaptorTest.java | 45 ++++++++++++++++++- 3 files changed, 57 insertions(+), 2 deletions(-) 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/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() { From c1e3335f0a987a4c375137d06f166b604e5a475b Mon Sep 17 00:00:00 2001 From: Joschka Bischoff Date: Thu, 7 Mar 2024 14:29:23 +0100 Subject: [PATCH 12/51] fully support subpopulations in ReplanningAnnealer --- .../annealing/ReplanningAnnealer.java | 62 +++++++++++-------- .../ReplanningAnnealerConfigGroup.java | 54 +++++++++------- .../annealing/ReplanningAnnealerTest.java | 49 +++++++++++++-- 3 files changed, 111 insertions(+), 54 deletions(-) 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/test/java/org/matsim/core/replanning/annealing/ReplanningAnnealerTest.java b/matsim/src/test/java/org/matsim/core/replanning/annealing/ReplanningAnnealerTest.java index d16b44098a6..bc83393f8cb 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 getExpectedLinearAnnealMultipleSubpopulations = "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,45 @@ 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(getExpectedLinearAnnealMultipleSubpopulations, 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); } } From 2644bf9f4835945a315fc3bb5a7bd928c706ed68 Mon Sep 17 00:00:00 2001 From: Joschka Bischoff Date: Thu, 7 Mar 2024 14:53:17 +0100 Subject: [PATCH 13/51] add test with explicitly set null subpopulation --- .../annealing/ReplanningAnnealerTest.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) 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 bc83393f8cb..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 @@ -40,7 +40,7 @@ public class ReplanningAnnealerTest { "9;0.0500;0.0250;0.0250;0.9500\n" + "10;0.0000;0.0000;0.0000;1.0000\n"; - private String getExpectedLinearAnnealMultipleSubpopulations = "it;globalInnovationRate_otherAnnealer;ChangeExpBeta_otherAnnealer;TimeAllocationMutator_otherAnnealer;globalInnovationRate_subpop;ReRoute_subpop;SubtourModeChoice_subpop;ChangeExpBeta_subpop\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" + @@ -404,7 +404,7 @@ void testSubpopulationAnneal() throws IOException { Controler controler = new Controler(this.scenario); controler.run(); - Assertions.assertEquals(getExpectedLinearAnnealMultipleSubpopulations, 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); @@ -414,4 +414,24 @@ void testSubpopulationAnneal() throws IOException { 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); + } + } From 29519a5bd2b2b623e396d4a973c1d7f807a6f922 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Tue, 12 Mar 2024 12:20:24 +0100 Subject: [PATCH 14/51] make memory observer interval configurable --- .../config/groups/ControllerConfigGroup.java | 19 +++++++++++++++++++ .../core/controler/AbstractController.java | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) 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 { From 84bd1810cc03ec05126ffba9073cf9ee7fabe302 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 21:05:38 +0000 Subject: [PATCH 15/51] build(deps): bump com.google.errorprone:error_prone_annotations Bumps [com.google.errorprone:error_prone_annotations](https://github.com/google/error-prone) from 2.25.0 to 2.26.1. - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.25.0...v2.26.1) --- updated-dependencies: - dependency-name: com.google.errorprone:error_prone_annotations dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 097895e66b4..8ab3815ad40 100644 --- a/pom.xml +++ b/pom.xml @@ -200,7 +200,7 @@ com.google.errorprone error_prone_annotations - 2.25.0 + 2.26.1 From d7bd8fed4c1567976626994b868ef73820ea7a68 Mon Sep 17 00:00:00 2001 From: marecabo <23156476+marecabo@users.noreply.github.com> Date: Wed, 13 Mar 2024 09:56:23 +0100 Subject: [PATCH 16/51] Pass person and vehicle to travel time query in FISS --- .../java/org/matsim/contrib/drt/extension/fiss/FISS.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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..9dbd91f2f0a 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 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)); From 1aa9b21a447e09ccf8198a21701966efbdf1b930 Mon Sep 17 00:00:00 2001 From: marecabo <23156476+marecabo@users.noreply.github.com> Date: Wed, 13 Mar 2024 09:58:14 +0100 Subject: [PATCH 17/51] Tiny code lint --- .../java/org/matsim/contrib/drt/extension/fiss/FISS.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 9dbd91f2f0a..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 @@ -101,7 +101,7 @@ public boolean handleDeparture(double now, MobsimAgent agent, Id linkId) { // 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, person, vehicle); @@ -112,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); From 9dd01da8d63910b4ead35b0ff93423a7a44f799b Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Wed, 13 Mar 2024 16:21:41 +0100 Subject: [PATCH 18/51] initial h3 implementation for drt zonal systems --- contribs/drt-extensions/pom.xml | 7 +- .../drt/extension/h3/drtZone/H3GridUtils.java | 113 ++++++++++++ .../h3/drtZone/H3ModeZonalSystemModule.java | 59 ++++++ .../drt/extension/h3/drtZone/H3Utils.java | 27 +++ .../extension/h3/drtZone/H3ZonalSystem.java | 75 ++++++++ .../h3/RunDrtWithH3ZonalSystemIT.java | 88 +++++++++ .../h3/drtZone/H3DrtZonalSystemTest.java | 170 ++++++++++++++++++ .../drt/analysis/zonal/DrtGridUtils.java | 13 +- .../zonal/DrtModeZonalSystemModule.java | 16 +- .../analysis/zonal/DrtZonalSystemTest.java | 6 +- 10 files changed, 556 insertions(+), 18 deletions(-) create mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3GridUtils.java create mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ModeZonalSystemModule.java create mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3Utils.java create mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ZonalSystem.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 diff --git a/contribs/drt-extensions/pom.xml b/contribs/drt-extensions/pom.xml index 3e2cbf8dcf7..130ecb31138 100644 --- a/contribs/drt-extensions/pom.xml +++ b/contribs/drt-extensions/pom.xml @@ -48,11 +48,16 @@ 16.0-SNAPSHOT test - + org.mockito mockito-core + + com.uber + h3 + 4.1.1 + diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3GridUtils.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3GridUtils.java new file mode 100644 index 00000000000..ad1e94e43a1 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3GridUtils.java @@ -0,0 +1,113 @@ +package org.matsim.contrib.drt.extension.h3.drtZone; + +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.contrib.zone.util.NetworkWithZonesUtils; +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/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ModeZonalSystemModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ModeZonalSystemModule.java new file mode 100644 index 00000000000..69a41bfa12e --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ModeZonalSystemModule.java @@ -0,0 +1,59 @@ +package org.matsim.contrib.drt.extension.h3.drtZone; + +import com.google.common.base.Preconditions; +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; +import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystemParams; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.core.config.ConfigGroup; + +import java.util.Map; + +import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtils.filterGridWithinServiceArea; +import static org.matsim.utils.gis.shp2matsim.ShpGeometryUtils.loadPreparedGeometries; + +/** + * @author nkuehnel / MOIA + */ +public class H3ModeZonalSystemModule extends AbstractDvrpModeModule { + + private final DrtConfigGroup drtCfg; + private final String crs; + private final int resolution; + + public H3ModeZonalSystemModule(DrtConfigGroup drtCfg, String crs, int resolution) { + super(drtCfg.getMode()); + this.drtCfg = drtCfg; + this.crs = crs; + this.resolution = resolution; + } + @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: + throw new IllegalArgumentException("Cannot use H3 system with self-provided shapefile"); + case GridFromNetwork: + Preconditions.checkNotNull(params.cellSize); + Map gridFromNetwork = H3GridUtils.createH3GridFromNetwork(network, resolution, crs); + var gridZones = + switch (drtCfg.operationalScheme) { + case stopbased, door2door -> gridFromNetwork; + case serviceAreaBased -> filterGridWithinServiceArea(gridFromNetwork, + loadPreparedGeometries(ConfigGroup.getInputFileURL(getConfig().getContext(), + drtCfg.drtServiceAreaShapeFile))); + }; + return H3ZonalSystem.createFromPreparedGeometries(network, gridZones, crs, resolution); + + default: + throw new RuntimeException("Unsupported zone generation"); + } + })).asEagerSingleton(); + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3Utils.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3Utils.java new file mode 100644 index 00000000000..9e9e13524c9 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3Utils.java @@ -0,0 +1,27 @@ +package org.matsim.contrib.drt.extension.h3.drtZone; + +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 = 15; + + + public static H3Core getInstance() { + if(h3 == null) { + try { + h3 = H3Core.newInstance(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return h3; + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ZonalSystem.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ZonalSystem.java new file mode 100644 index 00000000000..edb9eaa6374 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ZonalSystem.java @@ -0,0 +1,75 @@ +package org.matsim.contrib.drt.extension.h3.drtZone; + +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; +import org.matsim.contrib.drt.analysis.zonal.DrtZone; +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 final class H3ZonalSystem { + + static final Logger log = LogManager.getLogger(H3ZonalSystem.class); + + + public static DrtZonalSystem 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 DrtZone(id, geometries.get(id), links)) + .collect(toList()); + + return new DrtZonalSystem(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/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..55933793765 --- /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.drt.analysis.DrtEventSequenceCollector; +import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; +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.extension.h3.drtZone.H3ModeZonalSystemModule; +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()) { + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new H3ModeZonalSystemModule(drtConfig, config.global().getCoordinateSystem(), 9)); + install(new AbstractDvrpModeModule(drtConfig.mode) { + @Override + public void install() { + bindModal(DrtZonalWaitTimesAnalyzer.class).toProvider(modalProvider( + getter -> new DrtZonalWaitTimesAnalyzer(drtConfig, getter.getModal(DrtEventSequenceCollector.class), + getter.getModal(DrtZonalSystem.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..5cb88e3d851 --- /dev/null +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/drtZone/H3DrtZonalSystemTest.java @@ -0,0 +1,170 @@ +/* + * *********************************************************************** * + * 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.drt.analysis.zonal.DrtZonalSystem; +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; + +/** + * @author nkuehnel / MOIA + */ +public class H3DrtZonalSystemTest { + + @Test + void test_Holzkirchen_Resolution3() { + Network network = getNetwork(); + String crs = TransformationFactory.DHDN_GK4; + int resolution = 3; + DrtZonalSystem drtZonalSystem = H3ZonalSystem.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + assertThat(drtZonalSystem.getZones().containsKey("831f8dfffffffff")).isTrue(); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo("831f8dfffffffff"); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo("831f8dfffffffff"); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo("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; + DrtZonalSystem drtZonalSystem = H3ZonalSystem.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + assertThat(drtZonalSystem.getZones().containsKey("851f88b7fffffff")).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey("851f8d6bfffffff")).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey("851f88a7fffffff")).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey("851f89d3fffffff")).isTrue(); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo("851f8d6bfffffff"); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo("851f88b7fffffff"); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo("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; + DrtZonalSystem drtZonalSystem = H3ZonalSystem.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + assertThat(drtZonalSystem.getZones().containsKey("861f8d697ffffff")).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey("861f8d687ffffff")).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey("861f8d69fffffff")).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey("861f88a6fffffff")).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey("861f88a6fffffff")).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey("861f89d37ffffff")).isTrue(); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo("861f8d697ffffff"); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo("861f88b47ffffff"); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo("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; + DrtZonalSystem drtZonalSystem = H3ZonalSystem.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo("8a1f8d6930b7fff"); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo("8a1f88b4025ffff"); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo("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; + DrtZonalSystem drtZonalSystem = H3ZonalSystem.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo("8c1f8d6930b63ff"); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo("8c1f88b4025d1ff"); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo("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/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..c8e9acfde42 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 @@ -74,21 +74,18 @@ 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..ef95ba40843 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 @@ -21,11 +21,12 @@ 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.analysis.zonal.DrtGridUtils.filterGridWithinServiceArea; import static org.matsim.contrib.drt.run.DrtConfigGroup.OperationalScheme; import static org.matsim.utils.gis.shp2matsim.ShpGeometryUtils.loadPreparedGeometries; import java.util.List; +import java.util.Map; import org.locationtech.jts.geom.prep.PreparedGeometry; import org.matsim.api.core.v01.network.Network; @@ -66,11 +67,14 @@ public void install() { case GridFromNetwork: Preconditions.checkNotNull(params.cellSize); - var gridZones = drtCfg.operationalScheme == OperationalScheme.serviceAreaBased ? - createGridFromNetworkWithinServiceArea(network, params.cellSize, - loadPreparedGeometries(ConfigGroup.getInputFileURL(getConfig().getContext(), - drtCfg.drtServiceAreaShapeFile))) : - createGridFromNetwork(network, 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))); + }; return DrtZonalSystem.createFromPreparedGeometries(network, gridZones); default: 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..9baafffb23f 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 @@ -62,7 +62,7 @@ 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); + Map grid = DrtGridUtils.filterGridWithinServiceArea(DrtGridUtils.createGridFromNetwork(createNetwork(), 100), serviceArea); DrtZonalSystem zonalSystem = createFromPreparedGeometries(createNetwork(), grid); @@ -70,7 +70,7 @@ void test_gridWithinServiceArea(){ //link 'da' is outside of the service area Id id = Id.createLinkId("da"); - assertThat(zonalSystem.getZoneForLinkId(id) == null); + assertThat(zonalSystem.getZoneForLinkId(id) == null).isTrue(); } @Test @@ -78,7 +78,7 @@ 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); + Map grid = DrtGridUtils.filterGridWithinServiceArea(DrtGridUtils.createGridFromNetwork(createNetwork(), 100), serviceArea); DrtZonalSystem zonalSystem = createFromPreparedGeometries(createNetwork(), grid); From 5f4ad5edf50bbbabff70d6fe1e99f97c86658448 Mon Sep 17 00:00:00 2001 From: steffenaxer <26229392+steffenaxer@users.noreply.github.com> Date: Wed, 13 Mar 2024 22:18:29 +0100 Subject: [PATCH 19/51] Use computeIfAbsent for stringCache --- .../attributeconverters/StringConverter.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) 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 3a600e82bc1..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 @@ -31,14 +31,10 @@ */ public class StringConverter implements AttributeConverter { 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 From 95bdede72e0ca054756e73d40475bc9b20789170 Mon Sep 17 00:00:00 2001 From: rakow Date: Mon, 18 Mar 2024 11:25:42 +0100 Subject: [PATCH 20/51] Event fingerprints and comparison (#3165) * started work on fingerprint comparator * added compare function, fixed hashtoadd * fixed compare function, added printFingerprint * changed structure, added compression, changed hash logic * added tests for comparison, added folders for input files * added hash order logic, also javadoc, also fixed minor errors * cleaned up tests, improved API * remove extra new line from error messages * update test * add deprecation message to old enum * handle file errors as separate comparison result * fix capital I in folder name --------- Co-authored-by: zlukich --- .../contrib/bicycle/run/BicycleTest.java | 2 +- .../events/VehicleLeavesTrafficEventTest.java | 6 +- ...unAverageEmissionToolOfflineExampleIT.java | 18 +- .../contrib/ev/example/RunEvExampleTest.java | 10 +- ...nEvExampleWithLTHConsumptionModelTest.java | 10 +- .../usecases/chessboard/RunChessboardIT.java | 6 +- .../run/RunParkingSearchScenarioIT.java | 10 +- .../run/RunWithParkingProxyIT.java | 6 +- .../run/RoadPricingByConfigfileTest.java | 4 +- .../builder/TravelTimeFourWaysTest.java | 5 +- .../signals/integration/SignalSystemsIT.java | 9 +- ...nerateSmallScaleCommercialTrafficTest.java | 6 +- .../contrib/etaxi/run/RunETaxiScenarioIT.java | 6 +- .../taxi/optimizer/TaxiOptimizerTests.java | 6 +- .../java/playground/vsp/ev/UrbanEVIT.java | 6 +- matsim/.gitignore | 2 +- .../org/matsim/core/events/EventsUtils.java | 81 ++++++- .../ComparisonResult.java | 6 + .../EventFingerprint.java | 165 ++++++++++++++ .../EventsFileComparator.java | 38 ++-- .../EventsFileFingerprintComparator.java | 124 ++++++++++ .../FingerprintEventHandler.java | 212 ++++++++++++++++++ .../utils/eventsfilecomparison/Worker.java | 2 + .../java/org/matsim/examples/EquilTest.java | 5 +- .../examples/OnePercentBerlin10sIT.java | 5 +- .../org/matsim/testcases/MatsimTestUtils.java | 3 +- .../EventsFileComparatorTest.java | 2 +- .../EventsFileFingerprintComparatorTest.java | 143 ++++++++++++ .../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 ++ 38 files changed, 918 insertions(+), 91 deletions(-) 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/test/java/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest.java 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/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/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/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/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/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/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java index d88d2318fd1..b5e92503851 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java @@ -34,7 +34,7 @@ import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.FreightCarriersConfigGroup; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; import java.io.File; import java.util.Objects; @@ -119,7 +119,7 @@ void testMainRunAndResults() { // compare events String expected = utils.getPackageInputDirectory() + "test.output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "test.output_events.xml.gz" ; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals( EventsFileComparator.Result.FILES_ARE_EQUAL, result ); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result ); } } 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/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/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/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/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/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/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 From 4180bcd90c5daa59688a6ad7d2edef9b8308ad2b Mon Sep 17 00:00:00 2001 From: Chengqi Lu <43133404+luchengqi7@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:58:17 +0100 Subject: [PATCH 21/51] Remove the need of binding to use DRT detour constraints (#3171) * Refactoring work * Update DrtOfferAcceptor.java * Remove original DEFAULT_ACCEPTOR * Improve binding --- .../edrt/run/EDrtModeOptimizerQSimModule.java | 12 +++++++----- .../drt/optimizer/DrtModeOptimizerQSimModule.java | 8 +++++--- ...ferAcceptor.java => DefaultOfferAcceptor.java} | 15 +++++++++++++-- .../contrib/drt/passenger/DrtOfferAcceptor.java | 3 --- .../matsim/contrib/drt/run/DrtConfigGroup.java | 8 +++++++- .../drt/optimizer/MaxDetourConstraintTest.java | 13 ------------- .../DefaultUnplannedRequestInserterTest.java | 3 ++- 7 files changed, 34 insertions(+), 28 deletions(-) rename contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/{MaxDetourOfferAcceptor.java => DefaultOfferAcceptor.java} (62%) 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/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/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/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/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)); } From b739ee890cf833fecae596ab5c898a04e4885706 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Mon, 18 Mar 2024 12:01:34 +0100 Subject: [PATCH 22/51] install drt zonalsystem module independently of the rebalancing module --- .../contrib/drt/optimizer/rebalancing/RebalancingModule.java | 1 - .../src/main/java/org/matsim/contrib/drt/run/DrtModeModule.java | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) 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/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)); From b89ad74a799c2eb37b1af14d09796e5c2eb66731 Mon Sep 17 00:00:00 2001 From: marecabo <23156476+marecabo@users.noreply.github.com> Date: Mon, 18 Mar 2024 12:28:36 +0100 Subject: [PATCH 23/51] Move estimateWaitingTime(List elements) to PTWaitingTimeEstimator interface --- .../utils/PTWaitingTimeEstimator.java | 19 +++++++++++++++++++ .../utils/ScheduleWaitingTimeEstimator.java | 19 ------------------- 2 files changed, 19 insertions(+), 19 deletions(-) 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..a253763488a 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,10 @@ package org.matsim.contribs.discrete_mode_choice.components.utils; +import java.util.List; + +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.pt.routes.TransitPassengerRoute; /** @@ -11,5 +16,19 @@ * @author sebhoerl */ public interface PTWaitingTimeEstimator { + double estimateWaitingTime(double departureTime, TransitPassengerRoute route); + + default double estimateWaitingTime(List elements) { + double totalWaitingTime = 0.0; + + for (PlanElement element : elements) { + if (element instanceof Leg leg && leg.getMode().equals(TransportMode.pt)) { + TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); + totalWaitingTime += this.estimateWaitingTime(leg.getDepartureTime().seconds(), route); + } + } + + return totalWaitingTime; + } } 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..78e9d45ee97 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,8 +8,6 @@ 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.Leg; -import org.matsim.api.core.v01.population.PlanElement; import org.matsim.core.utils.collections.Tuple; import org.matsim.core.utils.misc.OptionalTime; import org.matsim.core.utils.misc.Time; @@ -54,23 +52,6 @@ private Tuple, Id> createId(TransitLine transitLin return new Tuple<>(transitLine.getId(), transitRoute.getId()); } - 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); - } - } - } - - return totalWaitingTime; - } - @Override public double estimateWaitingTime(double agentDepartureTime, TransitPassengerRoute route) { TransitLine transitLine = transitSchedule.getTransitLines().get(route.getLineId()); From 4258f24f15a85523a9cf9e9d7b5136ab9682d1f7 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Mon, 18 Mar 2024 12:31:46 +0100 Subject: [PATCH 24/51] ensure zonal params are present --- .../zonal/DrtModeZonalSystemModule.java | 78 ++++++++++--------- 1 file changed, 40 insertions(+), 38 deletions(-) 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..986f75177a5 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 @@ -53,53 +53,55 @@ 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(DrtZonalSystem.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 DrtZonalSystem.createFromPreparedGeometries(network, EntryStream.of(preparedGeometries).mapKeys(i -> (i + 1) + "").toMap()); - case GridFromNetwork: - Preconditions.checkNotNull(params.cellSize); - var gridZones = drtCfg.operationalScheme == OperationalScheme.serviceAreaBased ? + case GridFromNetwork: + Preconditions.checkNotNull(params.cellSize); + var gridZones = drtCfg.operationalScheme == OperationalScheme.serviceAreaBased ? createGridFromNetworkWithinServiceArea(network, params.cellSize, - loadPreparedGeometries(ConfigGroup.getInputFileURL(getConfig().getContext(), - drtCfg.drtServiceAreaShapeFile))) : + 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( + 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( "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(DrtZonalSystem.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(DrtZonalSystem.class)))).asEagerSingleton(); + addControlerListenerBinding().to(modalKey(DrtZonalWaitTimesAnalyzer.class)); + } } } From e1ba68d7b9d8a70ae14dae4f7d34bd8dbf322643 Mon Sep 17 00:00:00 2001 From: marecabo <23156476+marecabo@users.noreply.github.com> Date: Mon, 18 Mar 2024 12:44:56 +0100 Subject: [PATCH 25/51] Do not use default method in interface --- .../utils/NullWaitingTimeEstimator.java | 10 ++++++++++ .../utils/PTWaitingTimeEstimator.java | 14 +------------- .../utils/ScheduleWaitingTimeEstimator.java | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 13 deletions(-) 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 a253763488a..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 @@ -2,8 +2,6 @@ import java.util.List; -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.pt.routes.TransitPassengerRoute; @@ -19,16 +17,6 @@ public interface PTWaitingTimeEstimator { double estimateWaitingTime(double departureTime, TransitPassengerRoute route); - default double estimateWaitingTime(List elements) { - double totalWaitingTime = 0.0; + double estimateWaitingTime(List elements); - for (PlanElement element : elements) { - if (element instanceof Leg leg && leg.getMode().equals(TransportMode.pt)) { - TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); - totalWaitingTime += this.estimateWaitingTime(leg.getDepartureTime().seconds(), route); - } - } - - return totalWaitingTime; - } } 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 78e9d45ee97..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,9 @@ 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; import org.matsim.core.utils.misc.OptionalTime; import org.matsim.core.utils.misc.Time; @@ -52,6 +55,20 @@ 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.getMode().equals(TransportMode.pt)) { + TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); + totalWaitingTime += this.estimateWaitingTime(leg.getDepartureTime().seconds(), route); + } + } + + return totalWaitingTime; + } + @Override public double estimateWaitingTime(double agentDepartureTime, TransitPassengerRoute route) { TransitLine transitLine = transitSchedule.getTransitLines().get(route.getLineId()); From 4e5ddd51667b78741377ce436d0e376c5cd8b445 Mon Sep 17 00:00:00 2001 From: rakow Date: Tue, 19 Mar 2024 12:55:19 +0100 Subject: [PATCH 26/51] Network freespeed estimation models (#3172) * feature writer for sumo networks, classes for network parameter estimation * several improvements * better param name * added detailed evaluation to eval class * update output names * add pre-trained reference models * fix typos * added tests and improved naming * added comments and references * better name for the package * fix package name * small fix in a different prepare method --- .../traveltime/SampleValidationRoutes.java | 20 +- .../application/options/InputOptions.java | 4 + .../network/CreateNetworkFromSumo.java | 2 + .../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 +- .../params/ApplyNetworkParamsTest.java | 45 + .../prepare/network/params/osm.net.xml | 1759 ++++++++ .../modechoice/search/ModeChoiceSearch.java | 7 +- .../contrib/sumo/SumoNetworkConverter.java | 20 +- .../sumo/SumoNetworkFeatureExtractor.java | 194 + .../contrib/sumo/SumoNetworkHandler.java | 842 ++-- .../sumo/SumoNetworkConverterTest.java | 44 +- 29 files changed, 15217 insertions(+), 442 deletions(-) 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/prepare/network/params/ApplyNetworkParamsTest.java create mode 100644 contribs/application/test/input/org/matsim/application/prepare/network/params/osm.net.xml create mode 100644 contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java 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/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/prepare/network/CreateNetworkFromSumo.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateNetworkFromSumo.java index 62f21e24314..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 @@ -120,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/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/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/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/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkConverter.java b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkConverter.java index ec30ee33eb3..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 @@ -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"; + + } +} From 60f57adafee491ce15c60b26ea9043f7004b36fd Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Tue, 19 Mar 2024 16:18:01 +0100 Subject: [PATCH 27/51] refactor zones and move them to common contrib add zonal systems params for h3 --- contribs/common/pom.xml | 10 ++ .../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 | 65 ++++++++++ .../contrib/common/zones/h3}/H3GridUtils.java | 3 +- .../contrib/common/zones/h3}/H3Utils.java | 4 +- .../common/zones/h3/H3ZoneSystemUtils.java} | 28 +++-- contribs/drt-extensions/pom.xml | 5 - .../h3/drtZone/H3ModeZonalSystemModule.java | 59 ---------- .../h3/RunDrtWithH3ZonalSystemIT.java | 8 +- .../h3/drtZone/H3DrtZonalSystemTest.java | 67 ++++++----- contribs/drt/pom.xml | 8 +- .../drt/analysis/zonal/DrtGridUtils.java | 9 +- .../zonal/DrtModeZonalSystemModule.java | 66 +++++++---- .../drt/analysis/zonal/DrtZonalSystem.java | 111 ------------------ .../analysis/zonal/DrtZonalSystemParams.java | 17 ++- .../zonal/DrtZonalWaitTimesAnalyzer.java | 47 ++++---- .../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 +++--- .../DrtModeFeedforwardRebalanceModule.java | 8 +- ...astHeuristicZonalRelocationCalculator.java | 14 +-- .../FeedforwardRebalancingStrategy.java | 49 ++++---- .../Feedforward/FeedforwardSignalHandler.java | 28 ++--- .../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 +- .../analysis/zonal/DrtZonalSystemTest.java | 25 ++-- .../RandomDrtZoneTargetLinkSelectorTest.java | 4 +- ...eviousIterationDrtDemandEstimatorTest.java | 14 ++- ...ualVehicleDensityTargetCalculatorTest.java | 24 ++-- ...ToPopulationRatioTargetCalculatorTest.java | 87 +++++++------- 48 files changed, 663 insertions(+), 673 deletions(-) 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 rename contribs/{drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone => common/src/main/java/org/matsim/contrib/common/zones/h3}/H3GridUtils.java (97%) rename contribs/{drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone => common/src/main/java/org/matsim/contrib/common/zones/h3}/H3Utils.java (78%) rename contribs/{drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ZonalSystem.java => common/src/main/java/org/matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java} (73%) delete mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ModeZonalSystemModule.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 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/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..26a9a6d31d6 --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemUtils.java @@ -0,0 +1,65 @@ +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/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3GridUtils.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3GridUtils.java similarity index 97% rename from contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3GridUtils.java rename to contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3GridUtils.java index ad1e94e43a1..9139e56442b 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3GridUtils.java +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3GridUtils.java @@ -1,4 +1,4 @@ -package org.matsim.contrib.drt.extension.h3.drtZone; +package org.matsim.contrib.common.zones.h3; import com.uber.h3core.AreaUnit; import com.uber.h3core.H3Core; @@ -13,7 +13,6 @@ 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.contrib.zone.util.NetworkWithZonesUtils; import org.matsim.core.network.NetworkUtils; import org.matsim.core.utils.geometry.CoordUtils; import org.matsim.core.utils.geometry.CoordinateTransformation; diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3Utils.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3Utils.java similarity index 78% rename from contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3Utils.java rename to contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3Utils.java index 9e9e13524c9..3bc44478ebf 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3Utils.java +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3Utils.java @@ -1,4 +1,4 @@ -package org.matsim.contrib.drt.extension.h3.drtZone; +package org.matsim.contrib.common.zones.h3; import com.uber.h3core.H3Core; @@ -11,7 +11,7 @@ public final class H3Utils { private static H3Core h3; - public final static int MAX_RES = 15; + public final static int MAX_RES = 16; public static H3Core getInstance() { diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ZonalSystem.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java similarity index 73% rename from contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ZonalSystem.java rename to contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java index edb9eaa6374..24c2aeea603 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ZonalSystem.java +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java @@ -1,4 +1,4 @@ -package org.matsim.contrib.drt.extension.h3.drtZone; +package org.matsim.contrib.common.zones.h3; import com.uber.h3core.H3Core; import com.uber.h3core.util.LatLng; @@ -7,10 +7,13 @@ 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.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.core.utils.geometry.CoordinateTransformation; import org.matsim.core.utils.geometry.transformations.TransformationFactory; @@ -24,15 +27,15 @@ /** * @author nkuehnel / MOIA */ -public final class H3ZonalSystem { +public class H3ZoneSystemUtils { - static final Logger log = LogManager.getLogger(H3ZonalSystem.class); + static final Logger log = LogManager.getLogger(H3ZoneSystemUtils.class); - public static DrtZonalSystem createFromPreparedGeometries(Network network, - Map geometries, - String crs, - int resolution) { + public static ZoneSystem createFromPreparedGeometries(Network network, + Map geometries, + String crs, + int resolution) { //geometries without links are skipped CoordinateTransformation ct = TransformationFactory.getCoordinateTransformation(crs, TransformationFactory.WGS84); @@ -45,11 +48,12 @@ public static DrtZonalSystem createFromPreparedGeometries(Network network, + 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 DrtZone(id, geometries.get(id), links)) + List zones = EntryStream.of(linksByGeometryId) + .mapKeyValue((id, links) -> new ZoneImpl(Id.create(id, Zone.class), geometries.get(id), links) { + }) .collect(toList()); - return new DrtZonalSystem(zones); + return new ZoneSystemImpl(zones); } /** diff --git a/contribs/drt-extensions/pom.xml b/contribs/drt-extensions/pom.xml index 130ecb31138..d3ccd511acd 100644 --- a/contribs/drt-extensions/pom.xml +++ b/contribs/drt-extensions/pom.xml @@ -53,11 +53,6 @@ org.mockito mockito-core - - com.uber - h3 - 4.1.1 - diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ModeZonalSystemModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ModeZonalSystemModule.java deleted file mode 100644 index 69a41bfa12e..00000000000 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/h3/drtZone/H3ModeZonalSystemModule.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.matsim.contrib.drt.extension.h3.drtZone; - -import com.google.common.base.Preconditions; -import org.locationtech.jts.geom.prep.PreparedGeometry; -import org.matsim.api.core.v01.network.Network; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystemParams; -import org.matsim.contrib.drt.run.DrtConfigGroup; -import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; -import org.matsim.core.config.ConfigGroup; - -import java.util.Map; - -import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtils.filterGridWithinServiceArea; -import static org.matsim.utils.gis.shp2matsim.ShpGeometryUtils.loadPreparedGeometries; - -/** - * @author nkuehnel / MOIA - */ -public class H3ModeZonalSystemModule extends AbstractDvrpModeModule { - - private final DrtConfigGroup drtCfg; - private final String crs; - private final int resolution; - - public H3ModeZonalSystemModule(DrtConfigGroup drtCfg, String crs, int resolution) { - super(drtCfg.getMode()); - this.drtCfg = drtCfg; - this.crs = crs; - this.resolution = resolution; - } - @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: - throw new IllegalArgumentException("Cannot use H3 system with self-provided shapefile"); - case GridFromNetwork: - Preconditions.checkNotNull(params.cellSize); - Map gridFromNetwork = H3GridUtils.createH3GridFromNetwork(network, resolution, crs); - var gridZones = - switch (drtCfg.operationalScheme) { - case stopbased, door2door -> gridFromNetwork; - case serviceAreaBased -> filterGridWithinServiceArea(gridFromNetwork, - loadPreparedGeometries(ConfigGroup.getInputFileURL(getConfig().getContext(), - drtCfg.drtServiceAreaShapeFile))); - }; - return H3ZonalSystem.createFromPreparedGeometries(network, gridZones, crs, resolution); - - default: - throw new RuntimeException("Unsupported zone generation"); - } - })).asEagerSingleton(); - } -} diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java index 55933793765..86595942ed2 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java @@ -4,12 +4,11 @@ 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.DrtZonalSystem; 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.extension.h3.drtZone.H3ModeZonalSystemModule; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; @@ -46,16 +45,17 @@ 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 H3ModeZonalSystemModule(drtConfig, config.global().getCoordinateSystem(), 9)); install(new AbstractDvrpModeModule(drtConfig.mode) { @Override public void install() { bindModal(DrtZonalWaitTimesAnalyzer.class).toProvider(modalProvider( getter -> new DrtZonalWaitTimesAnalyzer(drtConfig, getter.getModal(DrtEventSequenceCollector.class), - getter.getModal(DrtZonalSystem.class)))).asEagerSingleton(); + getter.getModal(ZoneSystem.class)))).asEagerSingleton(); addControlerListenerBinding().to(modalKey(DrtZonalWaitTimesAnalyzer.class)); } }); 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 index 5cb88e3d851..293fa254280 100644 --- 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 @@ -24,7 +24,9 @@ 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.drt.analysis.zonal.DrtZonalSystem; +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; @@ -35,6 +37,7 @@ 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 @@ -46,17 +49,17 @@ void test_Holzkirchen_Resolution3() { Network network = getNetwork(); String crs = TransformationFactory.DHDN_GK4; int resolution = 3; - DrtZonalSystem drtZonalSystem = H3ZonalSystem.createFromPreparedGeometries(network, + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); - assertThat(drtZonalSystem.getZones().containsKey("831f8dfffffffff")).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("831f8dfffffffff"))).isTrue(); // center of Holzkirchen - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo("831f8dfffffffff"); + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("831f8dfffffffff")); // Thanning (Western border of network) - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo("831f8dfffffffff"); + 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("831f89fffffffff"); + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("831f89fffffffff")); //check all links are mapped for (Link link : network.getLinks().values()) { @@ -69,20 +72,20 @@ void test_Holzkirchen_Resolution5() { Network network = getNetwork(); String crs = TransformationFactory.DHDN_GK4; int resolution = 5; - DrtZonalSystem drtZonalSystem = H3ZonalSystem.createFromPreparedGeometries(network, + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); - assertThat(drtZonalSystem.getZones().containsKey("851f88b7fffffff")).isTrue(); - assertThat(drtZonalSystem.getZones().containsKey("851f8d6bfffffff")).isTrue(); - assertThat(drtZonalSystem.getZones().containsKey("851f88a7fffffff")).isTrue(); - assertThat(drtZonalSystem.getZones().containsKey("851f89d3fffffff")).isTrue(); + 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("851f8d6bfffffff"); + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("851f8d6bfffffff")); // Thanning (Western border of network) - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo("851f88b7fffffff"); + 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("851f89d3fffffff"); + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("851f89d3fffffff")); //check all links are mapped for (Link link : network.getLinks().values()) { @@ -95,22 +98,22 @@ void test_Holzkirchen_Resolution6() { Network network = getNetwork(); String crs = TransformationFactory.DHDN_GK4; int resolution = 6; - DrtZonalSystem drtZonalSystem = H3ZonalSystem.createFromPreparedGeometries(network, + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); - assertThat(drtZonalSystem.getZones().containsKey("861f8d697ffffff")).isTrue(); - assertThat(drtZonalSystem.getZones().containsKey("861f8d687ffffff")).isTrue(); - assertThat(drtZonalSystem.getZones().containsKey("861f8d69fffffff")).isTrue(); - assertThat(drtZonalSystem.getZones().containsKey("861f88a6fffffff")).isTrue(); - assertThat(drtZonalSystem.getZones().containsKey("861f88a6fffffff")).isTrue(); - assertThat(drtZonalSystem.getZones().containsKey("861f89d37ffffff")).isTrue(); + 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("861f8d697ffffff"); + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("861f8d697ffffff")); // Thanning (Western border of network) - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo("861f88b47ffffff"); + 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("861f89d07ffffff"); + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("861f89d07ffffff")); //check all links are mapped for (Link link : network.getLinks().values()) { @@ -123,15 +126,15 @@ void test_Holzkirchen_Resolution10() { Network network = getNetwork(); String crs = TransformationFactory.DHDN_GK4; int resolution = 10; - DrtZonalSystem drtZonalSystem = H3ZonalSystem.createFromPreparedGeometries(network, + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); // center of Holzkirchen - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo("8a1f8d6930b7fff"); + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("8a1f8d6930b7fff")); // Thanning (Western border of network) - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo("8a1f88b4025ffff"); + 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("8a1f89d06d5ffff"); + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("8a1f89d06d5ffff")); //check all links are mapped for (Link link : network.getLinks().values()) { @@ -144,15 +147,15 @@ void test_Holzkirchen_Resolution12() { Network network = getNetwork(); String crs = TransformationFactory.DHDN_GK4; int resolution = 12; - DrtZonalSystem drtZonalSystem = H3ZonalSystem.createFromPreparedGeometries(network, + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); // center of Holzkirchen - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo("8c1f8d6930b63ff"); + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("8c1f8d6930b63ff")); // Thanning (Western border of network) - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo("8c1f88b4025d1ff"); + 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("8c1f89d06d581ff"); + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("8c1f89d06d581ff")); //check all links are mapped for (Link link : network.getLinks().values()) { 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/zonal/DrtGridUtils.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtGridUtils.java index c8e9acfde42..c27203c6ce5 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 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 5875d9451ca..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,25 +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.filterGridWithinServiceArea; -import static org.matsim.contrib.drt.run.DrtConfigGroup.OperationalScheme; -import static org.matsim.utils.gis.shp2matsim.ShpGeometryUtils.loadPreparedGeometries; - -import java.util.List; -import java.util.Map; - +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) @@ -57,26 +58,41 @@ public void install() { if (drtCfg.getZonalSystemParams().isPresent()) { DrtZonalSystemParams params = drtCfg.getZonalSystemParams().get(); - bindModal(DrtZonalSystem.class).toProvider(modalProvider(getter -> { + bindModal(ZoneSystem.class).toProvider(modalProvider(getter -> { Network network = getter.getModal(Network.class); switch (params.zonesGeneration) { - case ShapeFile: + 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: + 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))); - }; - return DrtZonalSystem.createFromPreparedGeometries(network, gridZones); + var gridZones = + switch (drtCfg.operationalScheme) { + case stopbased, door2door -> gridFromNetwork; + case serviceAreaBased -> filterGridWithinServiceArea(gridFromNetwork, + loadPreparedGeometries(ConfigGroup.getInputFileURL(getConfig().getContext(), + 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"); @@ -86,7 +102,7 @@ public void install() { bindModal(DrtZoneTargetLinkSelector.class).toProvider(modalProvider(getter -> { switch (params.targetLinkSelection) { case mostCentral: - return new MostCentralDrtZoneTargetLinkSelector(getter.getModal(DrtZonalSystem.class)); + return new MostCentralDrtZoneTargetLinkSelector(getter.getModal(ZoneSystem.class)); case random: return new RandomDrtZoneTargetLinkSelector(); default: @@ -98,13 +114,13 @@ public void install() { //zonal analysis bindModal(ZonalIdleVehicleXYVisualiser.class).toProvider(modalProvider( getter -> new ZonalIdleVehicleXYVisualiser(getter.get(MatsimServices.class), drtCfg.getMode(), - getter.getModal(DrtZonalSystem.class)))).asEagerSingleton(); + getter.getModal(ZoneSystem.class)))).asEagerSingleton(); addControlerListenerBinding().to(modalKey(ZonalIdleVehicleXYVisualiser.class)); addEventHandlerBinding().to(modalKey(ZonalIdleVehicleXYVisualiser.class)); bindModal(DrtZonalWaitTimesAnalyzer.class).toProvider(modalProvider( getter -> new DrtZonalWaitTimesAnalyzer(drtCfg, getter.getModal(DrtEventSequenceCollector.class), - getter.getModal(DrtZonalSystem.class)))).asEagerSingleton(); + 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 129c952ec09..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,12 +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.*; - import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -34,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; @@ -47,17 +44,23 @@ 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; @@ -73,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(); @@ -83,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) @@ -125,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()); @@ -136,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); } @@ -194,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()); @@ -216,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/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/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/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 9baafffb23f..10f50c6d9df 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 @@ -63,14 +64,14 @@ void test_gridWithinServiceArea(){ Coordinate max = new Coordinate(1500, 1500); List serviceArea = createServiceArea(min,max); Map grid = DrtGridUtils.filterGridWithinServiceArea(DrtGridUtils.createGridFromNetwork(createNetwork(), 100), serviceArea); - DrtZonalSystem zonalSystem = createFromPreparedGeometries(createNetwork(), + 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).isTrue(); + Assertions.assertThat(zonalSystem.getZoneForLinkId(id) == null).isTrue(); } @Test @@ -79,7 +80,7 @@ void test_noZonesWithoutLinks(){ Coordinate max = new Coordinate(2500, 2500); List serviceArea = createServiceArea(min,max); Map grid = DrtGridUtils.filterGridWithinServiceArea(DrtGridUtils.createGridFromNetwork(createNetwork(), 100), serviceArea); - DrtZonalSystem zonalSystem = createFromPreparedGeometries(createNetwork(), + 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/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); } } From f9abe3968b1a8a398a86281d5c306ca52e610670 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Tue, 19 Mar 2024 16:21:29 +0100 Subject: [PATCH 28/51] adjust zonal system test --- .../matsim/contrib/drt/analysis/zonal/DrtZonalSystemTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 10f50c6d9df..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 @@ -71,7 +71,7 @@ void test_gridWithinServiceArea(){ //link 'da' is outside of the service area Id id = Id.createLinkId("da"); - Assertions.assertThat(zonalSystem.getZoneForLinkId(id) == null).isTrue(); + Assertions.assertThat(zonalSystem.getZoneForLinkId(id)).isNull(); } @Test From 170c111d991d21c2c4c2d8a86a2905d99fc1fdc8 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Tue, 19 Mar 2024 16:23:27 +0100 Subject: [PATCH 29/51] improve formatting --- .../org/matsim/contrib/common/zones/ZoneSystemUtils.java | 3 +-- .../matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) 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 index 26a9a6d31d6..d1e3e6f2094 100644 --- 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 @@ -21,8 +21,7 @@ public final class ZoneSystemUtils { private ZoneSystemUtils() {} - public static ZoneSystem createFromPreparedGeometries(Network network, - Map geometries) { + public static ZoneSystem createFromPreparedGeometries(Network network, Map geometries) { //geometries without links are skipped Map> linksByGeometryId = StreamEx.of(network.getLinks().values()) 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 index 24c2aeea603..f496d62cc5d 100644 --- 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 @@ -32,10 +32,8 @@ public class H3ZoneSystemUtils { static final Logger log = LogManager.getLogger(H3ZoneSystemUtils.class); - public static ZoneSystem createFromPreparedGeometries(Network network, - Map geometries, - String crs, - int resolution) { + public static ZoneSystem createFromPreparedGeometries(Network network, Map geometries, + String crs, int resolution) { //geometries without links are skipped CoordinateTransformation ct = TransformationFactory.getCoordinateTransformation(crs, TransformationFactory.WGS84); From 0d5b2766b49e44528173b0bbfa8aac79e0093afa Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 19 Mar 2024 16:27:01 +0100 Subject: [PATCH 30/51] add input parameter for selecting needed column names of input shapes --- ...rateSmallScaleCommercialTrafficDemand.java | 29 +++++++++------- .../SmallScaleCommercialTrafficUtils.java | 34 +++++++++++++------ ...nerateSmallScaleCommercialTrafficTest.java | 4 +++ 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java index 7ffec55f486..1a2191b1542 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java @@ -37,23 +37,16 @@ import org.matsim.api.core.v01.population.Leg; import org.matsim.application.MATSimAppCommand; import org.matsim.application.options.ShpOptions.Index; -import org.matsim.core.config.consistency.UnmaterializedConfigGroupChecker; -import org.matsim.core.gbl.MatsimRandom; -import org.matsim.core.scenario.ProjectionUtils; -import org.matsim.core.utils.geometry.CoordUtils; -import org.matsim.core.utils.geometry.CoordinateTransformation; -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.*; @@ -151,9 +150,15 @@ private enum SmallScaleCommercialTrafficType { @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; @@ -242,8 +247,8 @@ public Integer call() throws Exception { Path inputDataDirectory = Path.of(config.getContext().toURI()).getParent(); indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS, shapeFileZoneNameColumn); - indexBuildings = SmallScaleCommercialTrafficUtils.getIndexBuildings(shapeFileBuildingsPath, shapeCRS); - indexLanduse = SmallScaleCommercialTrafficUtils.getIndexLanduse(shapeFileLandusePath, shapeCRS); + indexBuildings = SmallScaleCommercialTrafficUtils.getIndexBuildings(shapeFileBuildingsPath, shapeCRS, shapeFileBuildingTypeColumn); + indexLanduse = SmallScaleCommercialTrafficUtils.getIndexLanduse(shapeFileLandusePath, shapeCRS, shapeFileLanduseTypeColumn); indexInvestigationAreaRegions = SmallScaleCommercialTrafficUtils.getIndexRegions(shapeFileRegionsPath, shapeCRS, regionsShapeRegionColumn); Map> resultingDataPerZone = LanduseBuildingAnalysis diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java index 0b355bdc7c5..f00dcd020e5 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java @@ -85,32 +85,42 @@ public class SmallScaleCommercialTrafficUtils { static Index getIndexZones(Path shapeFileZonePath, String shapeCRS, String shapeFileZoneNameColumn) { ShpOptions shpZones = new ShpOptions(shapeFileZonePath, shapeCRS, StandardCharsets.UTF_8); + 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."); - ShpOptions shpLanduse = new ShpOptions(shapeFileBuildingsPath, shapeCRS, StandardCharsets.UTF_8); - return shpLanduse.createIndex(shapeCRS, "type"); + return shpBuildings.createIndex(shapeCRS, shapeFileBuildingTypeColumn); } - /** * Creates and return the Index of the regions shape. * @@ -120,8 +130,10 @@ static Index getIndexBuildings(Path shapeFileBuildingsPath, String shapeCRS) { * @return indexRegions */ public static Index getIndexRegions(Path shapeFileRegionsPath, String shapeCRS, String regionsShapeRegionColumn) { - ShpOptions shpLanduse = new ShpOptions(shapeFileRegionsPath, shapeCRS, StandardCharsets.UTF_8); - return shpLanduse.createIndex(shapeCRS, 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); } /** diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java index f23d6c57ad7..a521917e8de 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java @@ -72,7 +72,9 @@ void testMainRunAndResults() { 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"; @@ -89,7 +91,9 @@ void testMainRunAndResults() { "--zoneShapeFileName", zoneShapeFileName, "--zoneShapeFileNameColumn", zoneShapeFileNameColumn, "--buildingsShapeFileName", buildingsShapeFileName, + "--shapeFileBuildingTypeColumn", shapeFileBuildingTypeColumn, "--landuseShapeFileName", landuseShapeFileName, + "--shapeFileLanduseTypeColumn", shapeFileLanduseTypeColumn, "--shapeCRS", shapeCRS, "--nameOutputPopulation", resultPopulation, "--pathOutput", output); From 9956761f6f3e2fc0293fd3e370aa36aa0d0103cc Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Tue, 19 Mar 2024 16:32:06 +0100 Subject: [PATCH 31/51] improve formatting further --- .../org/matsim/contrib/drt/analysis/zonal/DrtGridUtils.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 c27203c6ce5..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 @@ -82,8 +82,7 @@ public static Map createGridFromNetwork(Network networ * @param serviceAreaGeoms geometries that define the service area * @return */ - public static Map filterGridWithinServiceArea(Map grid, - List serviceAreaGeoms) { + 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 "); From cf1ae7bfa6060acdd9bf48e66e5100b626e148e4 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 19 Mar 2024 22:45:58 +0100 Subject: [PATCH 32/51] add comment --- .../LanduseBuildingAnalysis.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java index 4104b09983a..b0af262a7b8 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java @@ -227,9 +227,8 @@ private static void createLanduseDistribution(Map landuseFeatures = indexLanduse.getAllFeatures(); List zonesFeatures = indexZones.getAllFeatures(); - for (SimpleFeature singleZone : zonesFeatures) { - // TODO comment + // get the region of the zone Coord middleCoordOfZone = MGC.point2Coord(((Geometry) singleZone.getDefaultGeometry()).getCentroid()); String regionName = indexInvestigationAreaRegions.query(middleCoordOfZone); if (regionName != null) { From 4616b1ea68870e2cec4f5fa5e9c6ce7b185c5257 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 20 Mar 2024 09:34:06 +0100 Subject: [PATCH 33/51] make the path of input data configurable --- ...rateSmallScaleCommercialTrafficDemand.java | 12 +++++-- .../LanduseBuildingAnalysis.java | 31 ++++++++++--------- .../LanduseBuildingAnalysisTest.java | 14 +++++---- ...nerateSmallScaleCommercialTrafficTest.java | 9 ++++-- .../TrafficVolumeGenerationTest.java | 24 +++++++++----- .../TripDistributionMatrixTest.java | 12 ++++--- 6 files changed, 64 insertions(+), 38 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java index 1a2191b1542..e5b6a27b774 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java @@ -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; @@ -244,7 +250,6 @@ public Integer call() throws Exception { if (!Files.exists(shapeFileRegionsPath)) { throw new Exception("Required regions shape file {} not found" + shapeFileRegionsPath.toString()); } - Path inputDataDirectory = Path.of(config.getContext().toURI()).getParent(); indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS, shapeFileZoneNameColumn); indexBuildings = SmallScaleCommercialTrafficUtils.getIndexBuildings(shapeFileBuildingsPath, shapeCRS, shapeFileBuildingTypeColumn); @@ -252,9 +257,10 @@ public Integer call() throws Exception { indexInvestigationAreaRegions = SmallScaleCommercialTrafficUtils.getIndexRegions(shapeFileRegionsPath, shapeCRS, regionsShapeRegionColumn); Map> resultingDataPerZone = LanduseBuildingAnalysis - .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, + .createInputDataDistribution(output, landuseCategoriesAndDataConnection, usedLanduseConfiguration.toString(), indexLanduse, indexZones, - indexBuildings, indexInvestigationAreaRegions, shapeFileZoneNameColumn, buildingsPerZone); + indexBuildings, indexInvestigationAreaRegions, shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, + pathToExistingDataDistributionToZones); Map, Link>> linksPerZone = filterLinksForZones(scenario, indexZones, buildingsPerZone); switch (usedSmallScaleCommercialTrafficType) { diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java index b0af262a7b8..7e26668438e 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysis.java @@ -54,11 +54,14 @@ 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, Index indexInvestigationAreaRegions, - String shapeFileZoneNameColumn, Map>> buildingsPerZone) - throws IOException { + String shapeFileZoneNameColumn, + Map>> buildingsPerZone, + Path pathToInvestigationAreaData, + Path pathToExistingDataDistributionToZones) + throws IOException { Map> resultingDataPerZone = new HashMap<>(); Map zoneIdRegionConnection = new HashMap<>(); @@ -81,13 +84,12 @@ 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); @@ -101,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 { @@ -115,7 +117,7 @@ static Map> createInputDataDistribution(Path ou buildingsPerZone, shapeFileZoneNameColumn, zoneIdRegionConnection); Map> investigationAreaData = new HashMap<>(); - readAreaData(investigationAreaData, inputDataDirectory); + readAreaData(investigationAreaData, pathToInvestigationAreaData); createResultingDataForLanduseInZones(landuseCategoriesPerZone, investigationAreaData, resultingDataPerZone, landuseCategoriesAndDataConnection, zoneIdRegionConnection); @@ -287,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) { diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java index 7762b156cc5..fa640744c92 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/LanduseBuildingAnalysisTest.java @@ -52,13 +52,15 @@ void testReadOfDataDistributionPerZoneAndBuildingAnalysis() throws IOException { 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, + usedLanduseConfiguration, SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), - SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); Assertions.assertEquals(3, resultingDataPerZone.size(), MatsimTestUtils.EPSILON); @@ -245,13 +247,13 @@ void testLanduseDistribution() throws IOException { 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, + usedLanduseConfiguration, SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), - SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, null); Assertions.assertEquals(3, resultingDataPerZone.size(), MatsimTestUtils.EPSILON); diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java index a521917e8de..c664ba46440 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java @@ -45,6 +45,7 @@ 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; @@ -60,7 +61,9 @@ public class RunGenerateSmallScaleCommercialTrafficTest { @Test void testMainRunAndResults() { - String inputDataDirectory = utils.getPackageInputDirectory() + "config_demand.xml"; + 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"; @@ -79,7 +82,9 @@ void testMainRunAndResults() { String resultPopulation = "testPopulation.xml.gz"; new GenerateSmallScaleCommercialTrafficDemand().execute( - inputDataDirectory, + pathToConfig, + "--pathToInvestigationAreaData", pathToInvestigationAreaData.toString(), + "--pathToExistingDataDistributionToZones", pathToExistingDataDistributionToZones.toString(), "--sample", sample, "--jspritIterations", jspritIterations, "--creationOption", creationOption, diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java index cfac585157a..b680e568ffb 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java @@ -61,12 +61,14 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { 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, + usedLanduseConfiguration, SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), - SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "commercialPersonTraffic"; @@ -189,12 +191,14 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { 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, + usedLanduseConfiguration, SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), - SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "goodsTraffic"; double sample = 1.; @@ -512,6 +516,8 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { 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")); @@ -525,9 +531,9 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, + usedLanduseConfiguration, SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), - SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); Map> trafficVolumePerTypeAndZone_start = TrafficVolumeGeneration .createTrafficVolume_start(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); @@ -670,6 +676,8 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th 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")); @@ -683,9 +691,9 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, + usedLanduseConfiguration, SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), - SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); Map> trafficVolumePerTypeAndZone_start = TrafficVolumeGeneration .createTrafficVolume_start(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java index 76f6c0b6cd8..7190ba7350d 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java @@ -60,12 +60,14 @@ void testTripDistributionCommercialPersonTrafficTraffic() throws IOException { 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, + usedLanduseConfiguration, getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), - SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "commercialPersonTraffic"; double sample = 1.; @@ -150,11 +152,13 @@ void testTripDistributionGoodsTraffic() throws IOException { 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, + usedLanduseConfiguration, getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), - SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone); + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "goodsTraffic"; double sample = 1.; From 44594808e9e2a1c5a460f17ce8e29e839ed603cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 08:58:08 +0000 Subject: [PATCH 34/51] build(deps): bump org.apache.maven.plugins:maven-compiler-plugin Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.12.1 to 3.13.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.1...maven-compiler-plugin-3.13.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8ab3815ad40..1c0ee40790c 100644 --- a/pom.xml +++ b/pom.xml @@ -359,7 +359,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.12.1 + 3.13.0 org.apache.maven.plugins From e561c36d4cc53bd8a36af483e92d9cd2efbba8d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 09:19:50 +0000 Subject: [PATCH 35/51] build(deps): bump com.google.protobuf:protobuf-java Bumps [com.google.protobuf:protobuf-java](https://github.com/protocolbuffers/protobuf) from 3.25.3 to 4.26.0. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl) - [Commits](https://github.com/protocolbuffers/protobuf/commits) --- updated-dependencies: - dependency-name: com.google.protobuf:protobuf-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- contribs/hybridsim/pom.xml | 2 +- contribs/protobuf/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contribs/hybridsim/pom.xml b/contribs/hybridsim/pom.xml index 57b42a70d8a..b276eda7285 100644 --- a/contribs/hybridsim/pom.xml +++ b/contribs/hybridsim/pom.xml @@ -10,7 +10,7 @@ hybridsim - 3.25.3 + 4.26.0 1.62.2 diff --git a/contribs/protobuf/pom.xml b/contribs/protobuf/pom.xml index 9e13515761a..202864deec5 100644 --- a/contribs/protobuf/pom.xml +++ b/contribs/protobuf/pom.xml @@ -11,7 +11,7 @@ protobuf - 3.25.3 + 4.26.0 From 3247f8bd8e3a70150fe31f5f62c5ed0ef69ed5f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 09:54:54 +0000 Subject: [PATCH 36/51] build(deps): bump org.apache.maven.plugins:maven-assembly-plugin Bumps [org.apache.maven.plugins:maven-assembly-plugin](https://github.com/apache/maven-assembly-plugin) from 3.7.0 to 3.7.1. - [Release notes](https://github.com/apache/maven-assembly-plugin/releases) - [Commits](https://github.com/apache/maven-assembly-plugin/compare/maven-assembly-plugin-3.7.0...maven-assembly-plugin-3.7.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-assembly-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- matsim/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matsim/pom.xml b/matsim/pom.xml index ba989fc0dff..dd950efc3be 100644 --- a/matsim/pom.xml +++ b/matsim/pom.xml @@ -344,7 +344,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.7.0 + 3.7.1 src/main/assembly/assembly-release.xml From ed9ee16645fcffbab4ee9f09a5485d9ee8dab8c0 Mon Sep 17 00:00:00 2001 From: rakow Date: Wed, 20 Mar 2024 13:48:15 +0100 Subject: [PATCH 37/51] Railsim maintenance (#3179) * cosmetics - Write debug files of RailsimEngineTest to test output directory. - Add some comments to clarify steps in the engine. * add some comments * comments and typo * add integration test for train following case with fixed block and moving block logic * adjust integration test: fixed block vs. moving block logic - Replace small segments in moving block track with a few long segments. * adjust integration test: regularize fixed block vs. moving block segments * adjust integration test: use same link lengths for fixed block vs. moving block segments --------- Co-authored-by: Merlin Unterfinger --- .../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 ++++++ 14 files changed, 348 insertions(+), 47 deletions(-) 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 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 + + + + + + + + + + + + + + + + + + + + + From 2e85ac920356af4de1744a449fd3b83f404210f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 14:18:22 +0000 Subject: [PATCH 38/51] build(deps): bump org.openjfx:javafx-graphics from 21.0.2 to 22 Bumps org.openjfx:javafx-graphics from 21.0.2 to 22. --- updated-dependencies: - dependency-name: org.openjfx:javafx-graphics dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- contribs/vsp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribs/vsp/pom.xml b/contribs/vsp/pom.xml index 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 From 34ae812e9776c524711f14419288daf1476354fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 09:06:48 +0000 Subject: [PATCH 39/51] build(deps): bump com.google.guava:guava from 33.0.0-jre to 33.1.0-jre Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.0.0-jre to 33.1.0-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1c0ee40790c..fd3d8a7352e 100644 --- a/pom.xml +++ b/pom.xml @@ -103,7 +103,7 @@ com.google.guava guava - 33.0.0-jre + 33.1.0-jre org.apache.commons From 4e058dab9046b1d33a5940dbf696f2960d7d7c82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20K=C3=BChnel?= Date: Thu, 21 Mar 2024 13:52:59 +0100 Subject: [PATCH 40/51] Add utility class for ev events reader (#3181) * add utility class for ev events reading --- .../contrib/ev/charging/ChargingEndEvent.java | 10 ++++++ .../ev/charging/ChargingStartEvent.java | 10 ++++++ .../ev/charging/EnergyChargedEvent.java | 15 +++++++-- .../ev/charging/QueuedAtChargerEvent.java | 9 ++++++ .../ev/charging/QuitQueueAtChargerEvent.java | 9 ++++++ .../DrivingEnergyConsumptionEvent.java | 13 ++++++++ .../IdlingEnergyConsumptionEvent.java | 13 ++++++++ .../contrib/ev/util/EvEventsReader.java | 31 +++++++++++++++++++ 8 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 contribs/ev/src/main/java/org/matsim/contrib/ev/util/EvEventsReader.java diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEndEvent.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEndEvent.java index e1222d14be2..74543d6e783 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEndEvent.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEndEvent.java @@ -23,6 +23,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.Event; +import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.vehicles.Vehicle; @@ -68,4 +69,13 @@ public Map getAttributes() { attr.put(ATTRIBUTE_CHARGE, charge + ""); return attr; } + + public static ChargingEndEvent convert(GenericEvent genericEvent) { + Map attributes = genericEvent.getAttributes(); + double time = genericEvent.getTime(); + Id vehicleId = Id.createVehicleId(attributes.get(ChargingEndEvent.ATTRIBUTE_VEHICLE)); + Id chargerId = Id.create(attributes.get(ChargingEndEvent.ATTRIBUTE_CHARGER), Charger.class); + double charge = Double.parseDouble(attributes.get(ChargingEndEvent.ATTRIBUTE_CHARGE)); + return new ChargingEndEvent(time, chargerId, vehicleId, charge); + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStartEvent.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStartEvent.java index 3305f40ecdd..f6a4a28f774 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStartEvent.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStartEvent.java @@ -23,6 +23,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.Event; +import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.vehicles.Vehicle; @@ -68,4 +69,13 @@ public Map getAttributes() { attr.put(ATTRIBUTE_CHARGE, charge + ""); return attr; } + + public static ChargingStartEvent convert(GenericEvent genericEvent) { + Map attributes = genericEvent.getAttributes(); + double time = genericEvent.getTime(); + Id vehicleId = Id.createVehicleId(attributes.get(ChargingStartEvent.ATTRIBUTE_VEHICLE)); + Id chargerId = Id.create(attributes.get(ChargingStartEvent.ATTRIBUTE_CHARGER), Charger.class); + double charge = Double.parseDouble(attributes.get(ChargingStartEvent.ATTRIBUTE_CHARGE)); + return new ChargingStartEvent(time, chargerId, vehicleId, charge); + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/EnergyChargedEvent.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/EnergyChargedEvent.java index c60dfae9b67..cd56f0acbea 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/EnergyChargedEvent.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/EnergyChargedEvent.java @@ -20,13 +20,14 @@ package org.matsim.contrib.ev.charging; -import java.util.Map; - import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.Event; +import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.vehicles.Vehicle; +import java.util.Map; + /** * @author Michal Maciejewski (michalm) */ @@ -80,4 +81,14 @@ public Map getAttributes() { attr.put(ATTRIBUTE_END_CHARGE, endCharge + ""); return attr; } + + public static EnergyChargedEvent convert(GenericEvent genericEvent) { + Map attributes = genericEvent.getAttributes(); + double time = genericEvent.getTime(); + Id vehicleId = Id.createVehicleId(attributes.get(EnergyChargedEvent.ATTRIBUTE_VEHICLE)); + Id chargerId = Id.create(attributes.get(EnergyChargedEvent.ATTRIBUTE_CHARGER), Charger.class); + double energy = Double.parseDouble(attributes.get(EnergyChargedEvent.ATTRIBUTE_ENERGY)); + double endCharge = Double.parseDouble(attributes.get(EnergyChargedEvent.ATTRIBUTE_END_CHARGE)); + return new EnergyChargedEvent(time, chargerId, vehicleId, energy, endCharge); + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/QueuedAtChargerEvent.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/QueuedAtChargerEvent.java index b24089b7d15..77f90a67166 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/QueuedAtChargerEvent.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/QueuedAtChargerEvent.java @@ -23,6 +23,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.Event; +import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.vehicles.Vehicle; @@ -60,4 +61,12 @@ public Map getAttributes() { attr.put(ATTRIBUTE_VEHICLE, vehicleId.toString()); return attr; } + + public static QueuedAtChargerEvent convert(GenericEvent genericEvent) { + Map attributes = genericEvent.getAttributes(); + double time = genericEvent.getTime(); + Id vehicleId = Id.createVehicleId(attributes.get(QueuedAtChargerEvent.ATTRIBUTE_VEHICLE)); + Id chargerId = Id.create(attributes.get(QueuedAtChargerEvent.ATTRIBUTE_CHARGER), Charger.class); + return new QueuedAtChargerEvent(time, chargerId, vehicleId); + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/QuitQueueAtChargerEvent.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/QuitQueueAtChargerEvent.java index d38ad2323e1..3eab78fbde8 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/QuitQueueAtChargerEvent.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/QuitQueueAtChargerEvent.java @@ -23,6 +23,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.Event; +import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.vehicles.Vehicle; @@ -60,4 +61,12 @@ public Map getAttributes() { attr.put(ATTRIBUTE_VEHICLE, vehicleId.toString()); return attr; } + + public static QuitQueueAtChargerEvent convert(GenericEvent genericEvent) { + Map attributes = genericEvent.getAttributes(); + double time = genericEvent.getTime(); + Id vehicleId = Id.createVehicleId(attributes.get(QuitQueueAtChargerEvent.ATTRIBUTE_VEHICLE)); + Id chargerId = Id.create(attributes.get(QuitQueueAtChargerEvent.ATTRIBUTE_CHARGER), Charger.class); + return new QuitQueueAtChargerEvent(time, chargerId, vehicleId); + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DrivingEnergyConsumptionEvent.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DrivingEnergyConsumptionEvent.java index 3289446a72e..e18b3ed0bbd 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DrivingEnergyConsumptionEvent.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DrivingEnergyConsumptionEvent.java @@ -21,9 +21,12 @@ package org.matsim.contrib.ev.discharging; import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.api.core.v01.network.Link; import org.matsim.vehicles.Vehicle; +import java.util.Map; + /** * @author Michal Maciejewski (michalm) */ @@ -38,4 +41,14 @@ public DrivingEnergyConsumptionEvent(double time, Id vehicleId, Id attributes = genericEvent.getAttributes(); + double time = genericEvent.getTime(); + Id vehicleId = Id.createVehicleId(attributes.get(DrivingEnergyConsumptionEvent.ATTRIBUTE_VEHICLE)); + Id linkId = Id.createLinkId(attributes.get(DrivingEnergyConsumptionEvent.ATTRIBUTE_LINK)); + double energy = Double.parseDouble(attributes.get(DrivingEnergyConsumptionEvent.ATTRIBUTE_ENERGY)); + double endCharge = Double.parseDouble(attributes.get(DrivingEnergyConsumptionEvent.ATTRIBUTE_END_CHARGE)); + return new DrivingEnergyConsumptionEvent(time, vehicleId, linkId, energy, endCharge); + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdlingEnergyConsumptionEvent.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdlingEnergyConsumptionEvent.java index fcb625ad7b6..d1e31c33841 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdlingEnergyConsumptionEvent.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdlingEnergyConsumptionEvent.java @@ -21,9 +21,12 @@ package org.matsim.contrib.ev.discharging; import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.api.core.v01.network.Link; import org.matsim.vehicles.Vehicle; +import java.util.Map; + /** * @author Michal Maciejewski (michalm) */ @@ -38,4 +41,14 @@ public IdlingEnergyConsumptionEvent(double time, Id vehicleId, Id public String getEventType() { return EVENT_TYPE; } + + public static IdlingEnergyConsumptionEvent convert(GenericEvent genericEvent) { + Map attributes = genericEvent.getAttributes(); + double time = genericEvent.getTime(); + Id vehicleId = Id.createVehicleId(attributes.get(IdlingEnergyConsumptionEvent.ATTRIBUTE_VEHICLE)); + Id linkId = Id.createLinkId(attributes.get(IdlingEnergyConsumptionEvent.ATTRIBUTE_LINK)); + double energy = Double.parseDouble(attributes.get(IdlingEnergyConsumptionEvent.ATTRIBUTE_ENERGY)); + double endCharge = Double.parseDouble(attributes.get(IdlingEnergyConsumptionEvent.ATTRIBUTE_END_CHARGE)); + return new IdlingEnergyConsumptionEvent(time, vehicleId, linkId, energy, endCharge); + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/util/EvEventsReader.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/util/EvEventsReader.java new file mode 100644 index 00000000000..46854443c9e --- /dev/null +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/util/EvEventsReader.java @@ -0,0 +1,31 @@ +package org.matsim.contrib.ev.util; + +import org.matsim.contrib.ev.charging.*; +import org.matsim.contrib.ev.discharging.DrivingEnergyConsumptionEvent; +import org.matsim.contrib.ev.discharging.IdlingEnergyConsumptionEvent; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.events.MatsimEventsReader; + +/** + * @author nkuehnel / MOIA + */ +public final class EvEventsReader { + + private EvEventsReader(){} + + public static void registerEvEventMappers(MatsimEventsReader reader) { + reader.addCustomEventMapper(DrivingEnergyConsumptionEvent.EVENT_TYPE, DrivingEnergyConsumptionEvent::convert); + reader.addCustomEventMapper(IdlingEnergyConsumptionEvent.EVENT_TYPE, IdlingEnergyConsumptionEvent::convert); + reader.addCustomEventMapper(EnergyChargedEvent.EVENT_TYPE, EnergyChargedEvent::convert); + reader.addCustomEventMapper(ChargingStartEvent.EVENT_TYPE, ChargingStartEvent::convert); + reader.addCustomEventMapper(ChargingEndEvent.EVENT_TYPE, ChargingEndEvent::convert); + reader.addCustomEventMapper(QueuedAtChargerEvent.EVENT_TYPE, QueuedAtChargerEvent::convert); + reader.addCustomEventMapper(QuitQueueAtChargerEvent.EVENT_TYPE, QuitQueueAtChargerEvent::convert); + } + + public static MatsimEventsReader createEvEventsReader(EventsManager eventsManager) { + MatsimEventsReader reader = new MatsimEventsReader(eventsManager); + registerEvEventMappers(reader); + return reader; + } +} From 3968f96d4e87c5bc538297f2ce1649ee8e10bdbb Mon Sep 17 00:00:00 2001 From: Michal Maciejewski Date: Sun, 24 Mar 2024 22:28:43 +0100 Subject: [PATCH 41/51] add j2objc-annotations to dependency management --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index fd3d8a7352e..56a3ce82ee7 100644 --- a/pom.xml +++ b/pom.xml @@ -344,6 +344,12 @@ 0.43.1 + + com.google.j2objc + j2objc-annotations + 3.0.0 + + net.bytebuddy byte-buddy From 7b7e9842e8d21c027f5a97813f3ac94570d39633 Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Mon, 25 Mar 2024 10:28:01 +0100 Subject: [PATCH 42/51] add "type" to BasicPlan since the generic plans handling infrastructure now contains (some of) the functionality for it. (Recall: The last plan of a type is not removed.) --- .../api/core/v01/population/BasicPlan.java | 15 ++++++++-- .../matsim/api/core/v01/population/Plan.java | 30 ++++++++----------- .../GenericWorstPlanForRemovalSelector.java | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java b/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java index e19d7bbea3a..c8263d2264a 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java @@ -21,10 +21,19 @@ package org.matsim.api.core.v01.population; +import org.matsim.core.replanning.selectors.GenericWorstPlanForRemovalSelector; + public interface BasicPlan { - public abstract void setScore(Double score); + void setScore( Double score ); + + Double getScore(); - public abstract Double getScore(); + /** + * Plan type, which may be used to ensure there is at least one plan of a certain type. + */ + default String getType() { + return GenericWorstPlanForRemovalSelector.UNDEFINED_TYPE; + } -} \ No newline at end of file +} diff --git a/matsim/src/main/java/org/matsim/api/core/v01/population/Plan.java b/matsim/src/main/java/org/matsim/api/core/v01/population/Plan.java index 6329b62a626..ea9bc7d3e04 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/population/Plan.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/population/Plan.java @@ -38,33 +38,27 @@ */ public interface Plan extends MatsimPopulationObject, Customizable, BasicPlan, Attributable, Identifiable { - public abstract List getPlanElements(); + List getPlanElements(); - public abstract void addLeg(final Leg leg); + void addLeg( final Leg leg ); - public abstract void addActivity(final Activity act); + void addActivity( final Activity act ); - - /** - * Plan type, which may be used to ensure there is at least one plan of a certain type. - */ - public abstract String getType(); - - public abstract void setType(final String type); + void setType( final String type ); - public abstract void setPlanId(Id planId); + void setPlanId( Id planId ); - public abstract Id getId(); + Id getId(); - public abstract int getIterationCreated(); + int getIterationCreated(); - public abstract void setIterationCreated(int iteration); + void setIterationCreated( int iteration ); - public abstract String getPlanMutator(); + String getPlanMutator(); - public abstract void setPlanMutator(String planMutator); + void setPlanMutator( String planMutator ); - public abstract Person getPerson(); + Person getPerson(); /** * Sets the reference to the person. @@ -72,7 +66,7 @@ public interface Plan extends MatsimPopulationObject, Customizable, BasicPlan, A * sure that the bidirectional reference is set correctly if * you are using this method!. */ - public abstract void setPerson(Person person); + void setPerson( Person person ); } diff --git a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java index 953a8d48123..49d4971caa1 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java +++ b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java @@ -41,7 +41,7 @@ */ public class GenericWorstPlanForRemovalSelector implements PlanSelector { - private static final String UNDEFINED_TYPE = "undefined"; + public static final String UNDEFINED_TYPE = "undefined"; @Override public T selectPlan(HasPlansAndId person) { From 03a43ee29c039fbac7aed2fb5797c8f1272e8ff8 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Mon, 25 Mar 2024 15:39:39 +0100 Subject: [PATCH 43/51] Rename UNDEFINED_Type to UNDEFINED_PLAN_TYPE (is ok, because was private before) and move it to BasicPlan. --- .../org/matsim/api/core/v01/population/BasicPlan.java | 10 +++++----- .../selectors/GenericWorstPlanForRemovalSelector.java | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java b/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java index c8263d2264a..5bcf541d5a3 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java @@ -21,11 +21,11 @@ package org.matsim.api.core.v01.population; -import org.matsim.core.replanning.selectors.GenericWorstPlanForRemovalSelector; - public interface BasicPlan { - void setScore( Double score ); + String UNDEFINED_PLAN_TYPE = "undefined"; + + void setScore(Double score ); Double getScore(); @@ -33,7 +33,7 @@ public interface BasicPlan { * Plan type, which may be used to ensure there is at least one plan of a certain type. */ default String getType() { - return GenericWorstPlanForRemovalSelector.UNDEFINED_TYPE; + return UNDEFINED_PLAN_TYPE; } - + } diff --git a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java index 49d4971caa1..61e2df24a2e 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java +++ b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java @@ -28,6 +28,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import static org.matsim.api.core.v01.population.BasicPlan.UNDEFINED_PLAN_TYPE; + /** *

Selects the worst plan of a person (most likely for removal), but respects * the set plan types in a way the no plan is selected that is the last one of @@ -41,8 +43,6 @@ */ public class GenericWorstPlanForRemovalSelector implements PlanSelector { - public static final String UNDEFINED_TYPE = "undefined"; - @Override public T selectPlan(HasPlansAndId person) { @@ -53,7 +53,7 @@ public T selectPlan(HasPlansAndId person) { for (T plan : person.getPlans()) { String type = plan.getType(); if ( type==null ) { - type = UNDEFINED_TYPE ; + type = UNDEFINED_PLAN_TYPE; } typeCounts.merge( type, 1, ( a, b ) -> a + b ); } @@ -64,7 +64,7 @@ public T selectPlan(HasPlansAndId person) { String type = plan.getType(); if ( type==null ) { - type = UNDEFINED_TYPE; + type = UNDEFINED_PLAN_TYPE; } if ( typeCounts.get( type ) > 1) { // (if we have more than one plan of the same type:) From b79d817508369afb2b349cf05fb8d9f98359e631 Mon Sep 17 00:00:00 2001 From: simei94 <67737999+simei94@users.noreply.github.com> Date: Mon, 25 Mar 2024 16:39:29 -0600 Subject: [PATCH 44/51] add triggerPattern option to dashboard header (#3182) Co-authored-by: rakow --- .../src/main/java/org/matsim/simwrapper/Header.java | 5 +++++ .../src/test/java/org/matsim/simwrapper/SimWrapperTest.java | 1 + .../test/input/org/matsim/simwrapper/dashboard-0.yaml | 1 + 3 files changed, 7 insertions(+) diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/Header.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/Header.java index 0488d281a88..ebb5e7e75cb 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/Header.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/Header.java @@ -21,4 +21,9 @@ public final class Header { */ public Boolean fullScreen; + /** + * Set the dashboard to appear only when a certain file / directory is present. + */ + public String triggerPattern; + } diff --git a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/SimWrapperTest.java b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/SimWrapperTest.java index 0deaec7949c..90e51b7045c 100644 --- a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/SimWrapperTest.java +++ b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/SimWrapperTest.java @@ -27,6 +27,7 @@ void vizElementsTest() throws IOException { header.title = "Simwrapper Test Dashboard"; header.description = "Test All Simwrapper Plug-Ins Dashboard"; header.tab = "Header Tab"; + header.triggerPattern = "*example.csv"; layout.row("first") .el(Area.class, (viz, data) -> { diff --git a/contribs/simwrapper/test/input/org/matsim/simwrapper/dashboard-0.yaml b/contribs/simwrapper/test/input/org/matsim/simwrapper/dashboard-0.yaml index 1d5b7a2ff87..9f155e5cb64 100644 --- a/contribs/simwrapper/test/input/org/matsim/simwrapper/dashboard-0.yaml +++ b/contribs/simwrapper/test/input/org/matsim/simwrapper/dashboard-0.yaml @@ -2,6 +2,7 @@ header: tab: Header Tab title: Simwrapper Test Dashboard description: Test All Simwrapper Plug-Ins Dashboard + triggerPattern: '*example.csv' layout: first: - type: area From 00c5c3075fb30e0c8dd7ce198f564616d4a6383e Mon Sep 17 00:00:00 2001 From: rakow Date: Tue, 26 Mar 2024 14:47:51 +0100 Subject: [PATCH 45/51] Consider truck vehicle type in SUMO network converter (#3185) * improve sumo vehicle type handling * catch errors as warnings * formatting --- .../network/params/ApplyNetworkParams.java | 10 +- .../contrib/sumo/SumoNetworkConverter.java | 675 +++++++++--------- .../contrib/sumo/SumoNetworkHandler.java | 34 +- 3 files changed, 390 insertions(+), 329 deletions(-) diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java index 48f6310fad0..deef01dfe5e 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java @@ -98,7 +98,13 @@ public Integer call() throws Exception { for (Link link : network.getLinks().values()) { Feature ft = features.get(link.getId()); - applyChanges(link, ft.junctionType(), ft.features()); + + try { + applyChanges(link, ft.junctionType(), ft.features()); + } catch (IllegalArgumentException e) { + warn++; + log.warn("Error processing link {}", link.getId(), e); + } } log.warn("Observed {} warnings out of {} links", warn, network.getLinks().size()); @@ -132,7 +138,7 @@ private void applyChanges(Link link, String junctionType, Object2DoubleMap 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); + default -> 0; }; if (perLane < cap * threshold) { 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 0a806f1546b..1f311fc663a 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 @@ -9,7 +9,10 @@ import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.TransportMode; -import org.matsim.api.core.v01.network.*; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.NetworkFactory; +import org.matsim.api.core.v01.network.Node; import org.matsim.contrib.osm.networkReader.LinkProperties; import org.matsim.contrib.osm.networkReader.OsmTags; import org.matsim.core.network.NetworkUtils; @@ -43,122 +46,139 @@ */ public class SumoNetworkConverter implements Callable { - private static final Logger log = LogManager.getLogger(SumoNetworkConverter.class); - - @CommandLine.Parameters(arity = "1..*", paramLabel = "INPUT", description = "Input file(s)") - private List input; - - @CommandLine.Option(names = "--output", description = "Output xml file", required = true) - private Path output; - - @CommandLine.Option(names = "--shp", description = "Optional shape file used for filtering") - private Path shapeFile; - - @CommandLine.Option(names = "--from-crs", description = "Coordinate system of input data", required = true) - private String fromCRS; - - @CommandLine.Option(names = "--to-crs", description = "Desired output coordinate system", required = true) - private String toCRS; - - @CommandLine.Option(names = "--free-speed-factor", description = "Free-speed reduction for urban links", defaultValue = "0.9") - private double freeSpeedFactor = LinkProperties.DEFAULT_FREESPEED_FACTOR; - - private SumoNetworkConverter(List input, Path output, Path shapeFile, String fromCRS, String toCRS, double freeSpeedFactor) { - this.input = input; - this.output = output; - this.shapeFile = shapeFile; - this.fromCRS = fromCRS; - this.toCRS = toCRS; - this.freeSpeedFactor = freeSpeedFactor; - } - - private SumoNetworkConverter() { - } - - /** - * Creates a new converter instance. - * - * @param input List of input files, if multiple they will be merged - * @param output output path - * @param fromCRS coordinate system of input data - * @param toCRS desired coordinate system of network - */ - public static SumoNetworkConverter newInstance(List input, Path output, String fromCRS, String toCRS) { - return new SumoNetworkConverter(input, output, null, fromCRS, toCRS, LinkProperties.DEFAULT_FREESPEED_FACTOR); - } - - /** - * Creates a new converter instance, with a shape file for filtering. - * - * @param shapeFile only include links in this shape file. - * @see #newInstance(List, Path, String, String) - */ - public static SumoNetworkConverter newInstance(List input, Path output, Path shapeFile, String fromCRS, String toCRS) { - return new SumoNetworkConverter(input, output, shapeFile, fromCRS, toCRS, LinkProperties.DEFAULT_FREESPEED_FACTOR); - } - - /** - * Creates a new instance. - * @see #newInstance(List, Path, Path, String, String, double) - */ - public static SumoNetworkConverter newInstance(List input, Path output, Path shapeFile, String inputCRS, String targetCRS, double freeSpeedFactor) { - return new SumoNetworkConverter(input, output, shapeFile, inputCRS, targetCRS, freeSpeedFactor); - } - - /** - * Reads network from input file. - */ - public static SumoNetworkHandler readNetwork(File input) throws IOException, SAXException, ParserConfigurationException { - return SumoNetworkHandler.read(input); - } - - public static void main(String[] args) { - System.exit(new CommandLine(new SumoNetworkConverter()).execute(args)); - } - - /** - * Network area based on the cut-out. - */ - private static Geometry calculateNetworkArea(Path shapeFile) { - // only the first feature is used - return ((Geometry) GeoFileReader.getAllFeatures(shapeFile.toString()).iterator().next().getDefaultGeometry()); - } - - /** - * Execute the converter, which includes conversion and writing the files - * - * @see #convert(Network, Lanes) . - */ - @Override - public Integer call() throws Exception { - - Network network = NetworkUtils.createNetwork(); - Lanes lanes = LanesUtils.createLanesContainer(); - - SumoNetworkHandler handler = convert(network, lanes); - - calculateLaneCapacities(network, lanes); - - // This needs to run without errors, otherwise network is broken - network.getLinks().values().forEach(link -> { - LanesToLinkAssignment l2l = lanes.getLanesToLinkAssignments().get(link.getId()); - if (l2l != null) - LanesUtils.createLanes(link, l2l); - }); + private static final Logger log = LogManager.getLogger(SumoNetworkConverter.class); + + @CommandLine.Parameters(arity = "1..*", paramLabel = "INPUT", description = "Input file(s)") + private List input; + + @CommandLine.Option(names = "--output", description = "Output xml file", required = true) + private Path output; + + @CommandLine.Option(names = "--shp", description = "Optional shape file used for filtering") + private Path shapeFile; + + @CommandLine.Option(names = "--from-crs", description = "Coordinate system of input data", required = true) + private String fromCRS; + + @CommandLine.Option(names = "--to-crs", description = "Desired output coordinate system", required = true) + private String toCRS; + + @CommandLine.Option(names = "--free-speed-factor", description = "Free-speed reduction for urban links", defaultValue = "0.9") + private double freeSpeedFactor = LinkProperties.DEFAULT_FREESPEED_FACTOR; + + private SumoNetworkConverter(List input, Path output, Path shapeFile, String fromCRS, String toCRS, double freeSpeedFactor) { + this.input = input; + this.output = output; + this.shapeFile = shapeFile; + this.fromCRS = fromCRS; + this.toCRS = toCRS; + this.freeSpeedFactor = freeSpeedFactor; + } + + private SumoNetworkConverter() { + } + + /** + * Creates a new converter instance. + * + * @param input List of input files, if multiple they will be merged + * @param output output path + * @param fromCRS coordinate system of input data + * @param toCRS desired coordinate system of network + */ + public static SumoNetworkConverter newInstance(List input, Path output, String fromCRS, String toCRS) { + return new SumoNetworkConverter(input, output, null, fromCRS, toCRS, LinkProperties.DEFAULT_FREESPEED_FACTOR); + } + + /** + * Creates a new converter instance, with a shape file for filtering. + * + * @param shapeFile only include links in this shape file. + * @see #newInstance(List, Path, String, String) + */ + public static SumoNetworkConverter newInstance(List input, Path output, Path shapeFile, String fromCRS, String toCRS) { + return new SumoNetworkConverter(input, output, shapeFile, fromCRS, toCRS, LinkProperties.DEFAULT_FREESPEED_FACTOR); + } + + /** + * Creates a new instance. + * + * @see #newInstance(List, Path, Path, String, String, double) + */ + public static SumoNetworkConverter newInstance(List input, Path output, Path shapeFile, String inputCRS, String targetCRS, double freeSpeedFactor) { + return new SumoNetworkConverter(input, output, shapeFile, inputCRS, targetCRS, freeSpeedFactor); + } + + /** + * Reads network from input file. + */ + public static SumoNetworkHandler readNetwork(File input) throws IOException, SAXException, ParserConfigurationException { + return SumoNetworkHandler.read(input); + } + + public static void main(String[] args) { + System.exit(new CommandLine(new SumoNetworkConverter()).execute(args)); + } + + /** + * Network area based on the cut-out. + */ + private static Geometry calculateNetworkArea(Path shapeFile) { + // only the first feature is used + return ((Geometry) GeoFileReader.getAllFeatures(shapeFile.toString()).iterator().next().getDefaultGeometry()); + } + + /** + * Determine if a mode is allowed on a link. + */ + private static boolean isModeAllowed(String mode, SumoNetworkHandler.Edge edge, SumoNetworkHandler.Type type) { + + // Check edge attributes first + if (edge.lanes.stream().anyMatch(l -> l.allow != null && l.allow.contains(mode))) + return true; + + if (edge.lanes.stream().allMatch(l -> l.disallow != null && l.disallow.contains(mode))) + return false; + + // Type allows this mode + return type.allow.contains(mode) || (type.allow.isEmpty() && !type.disallow.contains(mode)); + } + + /** + * Execute the converter, which includes conversion and writing the files + * + * @see #convert(Network, Lanes) . + */ + @Override + public Integer call() throws Exception { + + Network network = NetworkUtils.createNetwork(); + Lanes lanes = LanesUtils.createLanesContainer(); + + SumoNetworkHandler handler = convert(network, lanes); + + calculateLaneCapacities(network, lanes); + + // This needs to run without errors, otherwise network is broken + network.getLinks().values().forEach(link -> { + LanesToLinkAssignment l2l = lanes.getLanesToLinkAssignments().get(link.getId()); + if (l2l != null) + LanesUtils.createLanes(link, l2l); + }); if (toCRS != null) ProjectionUtils.putCRS(network, toCRS); NetworkUtils.writeNetwork(network, output.toAbsolutePath().toString()); - new LanesWriter(lanes).write(output.toAbsolutePath().toString().replace(".xml", "-lanes.xml")); + new LanesWriter(lanes).write(output.toAbsolutePath().toString().replace(".xml", "-lanes.xml")); - writeGeometry(handler, output.toAbsolutePath().toString().replace(".xml", "-linkGeometries.csv")); + writeGeometry(handler, output.toAbsolutePath().toString().replace(".xml", "-linkGeometries.csv")); writeFeatures(handler, output.toAbsolutePath().toString().replace(".xml", "-ft.csv")); - return 0; - } + return 0; + } /** * Write csv with link properties. @@ -177,278 +197,287 @@ public void writeFeatures(SumoNetworkHandler handler, String output) { } /** - * Calculates lane capacities, according to {@link LanesUtils}. - */ - public void calculateLaneCapacities(Network network, Lanes lanes) { - for (LanesToLinkAssignment l2l : lanes.getLanesToLinkAssignments().values()) { - Link link = network.getLinks().get(l2l.getLinkId()); - for (Lane lane : l2l.getLanes().values()) { - calculateAndSetCapacity(lane, - lane.getToLaneIds() == null || lane.getToLaneIds().isEmpty(), link, network); - } - } - } + * Calculates lane capacities, according to {@link LanesUtils}. + */ + public void calculateLaneCapacities(Network network, Lanes lanes) { + for (LanesToLinkAssignment l2l : lanes.getLanesToLinkAssignments().values()) { + Link link = network.getLinks().get(l2l.getLinkId()); + for (Lane lane : l2l.getLanes().values()) { + calculateAndSetCapacity(lane, + lane.getToLaneIds() == null || lane.getToLaneIds().isEmpty(), link, network); + } + } + } - /** - * Writes link geometries. - */ - public void writeGeometry(SumoNetworkHandler handler, String path) { - try (BufferedWriter out = IOUtils.getBufferedWriter(path)) { - CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT.withHeader("LinkId", "Geometry")); + /** + * Writes link geometries. + */ + public void writeGeometry(SumoNetworkHandler handler, String path) { + try (BufferedWriter out = IOUtils.getBufferedWriter(path)) { + CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT.withHeader("LinkId", "Geometry")); - for (Map.Entry e : handler.getEdges().entrySet()) { + for (Map.Entry e : handler.getEdges().entrySet()) { - SumoNetworkHandler.Edge edge = e.getValue(); + SumoNetworkHandler.Edge edge = e.getValue(); - // Create straight line for edges without shape - if (edge.shape.isEmpty()) { + // Create straight line for edges without shape + if (edge.shape.isEmpty()) { - SumoNetworkHandler.Junction f = handler.getJunctions().get(edge.from); - SumoNetworkHandler.Junction t = handler.getJunctions().get(edge.to); - if (f == null || t == null) - continue; + SumoNetworkHandler.Junction f = handler.getJunctions().get(edge.from); + SumoNetworkHandler.Junction t = handler.getJunctions().get(edge.to); + if (f == null || t == null) + continue; - edge.shape.add(f.coord); - edge.shape.add(t.coord); - } + edge.shape.add(f.coord); + edge.shape.add(t.coord); + } - printer.printRecord( - e.getKey(), - edge.shape.stream().map(d -> { - Coord p = handler.createCoord(d); - return String.format(Locale.US,"(%f,%f)", p.getX(), p.getY()); - }).collect(Collectors.joining(",")) - ); + printer.printRecord( + e.getKey(), + edge.shape.stream().map(d -> { + Coord p = handler.createCoord(d); + return String.format(Locale.US, "(%f,%f)", p.getX(), p.getY()); + }).collect(Collectors.joining(",")) + ); - } + } - } catch (IOException e) { - log.error("Could not write link geometries", e); - } - } + } catch (IOException e) { + log.error("Could not write link geometries", e); + } + } - /** - * Perform the actual conversion on given input data. - * - * @param network results will be added into this network. - * @param lanes resulting lanes are added into this object. - * @return internal handler used for conversion - */ - public SumoNetworkHandler convert(Network network, Lanes lanes) throws ParserConfigurationException, SAXException, IOException { + /** + * Perform the actual conversion on given input data. + * + * @param network results will be added into this network. + * @param lanes resulting lanes are added into this object. + * @return internal handler used for conversion + */ + public SumoNetworkHandler convert(Network network, Lanes lanes) throws ParserConfigurationException, SAXException, IOException { - log.info("Parsing SUMO network"); + log.info("Parsing SUMO network"); - SumoNetworkHandler sumoHandler = SumoNetworkHandler.read(input.get(0).toFile()); - log.info("Parsed {} edges with {} junctions", sumoHandler.edges.size(), sumoHandler.junctions.size()); - - for (int i = 1; i < input.size(); i++) { - - CoordinateTransformation ct = TransformationFactory.getCoordinateTransformation(fromCRS, toCRS); - - File file = input.get(i).toFile(); - SumoNetworkHandler other = SumoNetworkHandler.read(file); - - writeInductionLoops(file, other); + SumoNetworkHandler sumoHandler = SumoNetworkHandler.read(input.get(0).toFile()); + log.info("Parsed {} edges with {} junctions", sumoHandler.edges.size(), sumoHandler.junctions.size()); - log.info("Merging {} edges with {} junctions from {} into base network", other.edges.size(), other.junctions.size(), file); - sumoHandler.merge(other, ct); - } + for (int i = 1; i < input.size(); i++) { - NetworkFactory f = network.getFactory(); - LanesFactory lf = lanes.getFactory(); + CoordinateTransformation ct = TransformationFactory.getCoordinateTransformation(fromCRS, toCRS); - Map linkProperties = LinkProperties.createLinkProperties(); + File file = input.get(i).toFile(); + SumoNetworkHandler other = SumoNetworkHandler.read(file); - // add additional service tag - linkProperties.put(OsmTags.SERVICE, new LinkProperties(LinkProperties.LEVEL_LIVING_STREET, 1,15 / 3.6, 450, false)); + writeInductionLoops(file, other); - for (SumoNetworkHandler.Edge edge : sumoHandler.edges.values()) { + log.info("Merging {} edges with {} junctions from {} into base network", other.edges.size(), other.junctions.size(), file); + sumoHandler.merge(other, ct); + } - // skip railways and unknowns - if (edge.type == null || !edge.type.startsWith("highway")) - continue; + NetworkFactory f = network.getFactory(); + LanesFactory lf = lanes.getFactory(); - Link link = f.createLink(Id.createLinkId(edge.id), - createNode(network, sumoHandler, edge.from), - createNode(network, sumoHandler, edge.to) - ); + Map linkProperties = LinkProperties.createLinkProperties(); - if (edge.name != null) - link.getAttributes().putAttribute("name", edge.name); + // add additional service tag + linkProperties.put(OsmTags.SERVICE, new LinkProperties(LinkProperties.LEVEL_LIVING_STREET, 1, 15 / 3.6, 450, false)); - link.getAttributes().putAttribute(NetworkUtils.TYPE, edge.type); + for (SumoNetworkHandler.Edge edge : sumoHandler.edges.values()) { - link.setNumberOfLanes(edge.lanes.size()); - Set modes = Sets.newHashSet(TransportMode.car, TransportMode.ride); + // skip railways and unknowns + if (edge.type == null || !edge.type.startsWith("highway")) + continue; - SumoNetworkHandler.Type type = sumoHandler.types.get(edge.type); + Link link = f.createLink(Id.createLinkId(edge.id), + createNode(network, sumoHandler, edge.from), + createNode(network, sumoHandler, edge.to) + ); - if (type.allow.contains("bicycle") || (type.allow.isEmpty() && !type.disallow.contains("bicycle"))) - modes.add(TransportMode.bike); + if (edge.name != null) + link.getAttributes().putAttribute("name", edge.name); - link.setAllowedModes(modes); - link.setLength(edge.getLength()); - LanesToLinkAssignment l2l = lf.createLanesToLinkAssignment(link.getId()); + link.getAttributes().putAttribute(NetworkUtils.TYPE, edge.type); - for (SumoNetworkHandler.Lane lane : edge.lanes) { - Lane mLane = lf.createLane(Id.create(lane.id, Lane.class)); - mLane.setAlignment(lane.index); - mLane.setStartsAtMeterFromLinkEnd(lane.length); - l2l.addLane(mLane); - } + link.setNumberOfLanes(edge.lanes.size()); + Set modes = Sets.newHashSet(TransportMode.car, TransportMode.ride); - // set link prop based on MATSim defaults - LinkProperties prop = linkProperties.get(type.highway); - double speed = type.speed; + SumoNetworkHandler.Type type = sumoHandler.types.get(edge.type); - // incoming lane connected to the others - // this is needed by matsim for lanes to work properly - if (edge.lanes.size() >= 1) { - Lane inLane = lf.createLane(Id.create(link.getId() + "_in", Lane.class)); - inLane.setStartsAtMeterFromLinkEnd(link.getLength()); - inLane.setAlignment(0); - l2l.getLanes().keySet().forEach(inLane::addToLaneId); - l2l.addLane(inLane); + // Determine allowed modes + if (!isModeAllowed("passenger", edge, type)) { + modes.remove(TransportMode.car); + modes.remove(TransportMode.ride); + } - double laneSpeed = edge.lanes.get(0).speed; - if (!Double.isNaN(laneSpeed) && laneSpeed > 0) { - // use speed info of first lane - // in general lanes do not have different speeds - speed = edge.lanes.get(0).speed; - } - } + if (isModeAllowed("bicycle", edge, type)) + modes.add(TransportMode.bike); - link.getAttributes().putAttribute(NetworkUtils.ALLOWED_SPEED, speed); + if (isModeAllowed("truck", edge, type)) + modes.add(TransportMode.truck); - if (prop == null) { - log.warn("Skipping unknown link type: {}", type.highway); - continue; - } + link.setAllowedModes(modes); + link.setLength(edge.getLength()); + LanesToLinkAssignment l2l = lf.createLanesToLinkAssignment(link.getId()); - link.setFreespeed(LinkProperties.calculateSpeedIfSpeedTag(speed, freeSpeedFactor)); - link.setCapacity(LinkProperties.getLaneCapacity(link.getLength(), prop) * link.getNumberOfLanes()); + for (SumoNetworkHandler.Lane lane : edge.lanes) { + Lane mLane = lf.createLane(Id.create(lane.id, Lane.class)); + mLane.setAlignment(lane.index); + mLane.setStartsAtMeterFromLinkEnd(lane.length); + l2l.addLane(mLane); + } - lanes.addLanesToLinkAssignment(l2l); - network.addLink(link); - } + // set link prop based on MATSim defaults + LinkProperties prop = linkProperties.get(type.highway); + double speed = type.speed; - if (shapeFile != null) { - Geometry shp = calculateNetworkArea(shapeFile); + // incoming lane connected to the others + // this is needed by matsim for lanes to work properly + if (edge.lanes.size() >= 1) { + Lane inLane = lf.createLane(Id.create(link.getId() + "_in", Lane.class)); + inLane.setStartsAtMeterFromLinkEnd(link.getLength()); + inLane.setAlignment(0); + l2l.getLanes().keySet().forEach(inLane::addToLaneId); + l2l.addLane(inLane); - // remove lanes outside survey area - for (Node node : network.getNodes().values()) { - if (!shp.contains(MGC.coord2Point(node.getCoord()))) { - node.getOutLinks().keySet().forEach(l -> lanes.getLanesToLinkAssignments().remove(l)); - node.getInLinks().keySet().forEach(l -> lanes.getLanesToLinkAssignments().remove(l)); - } - } - } + double laneSpeed = edge.lanes.get(0).speed; + if (!Double.isNaN(laneSpeed) && laneSpeed > 0) { + // use speed info of first lane + // in general lanes do not have different speeds + speed = edge.lanes.get(0).speed; + } + } - // clean up network - new NetworkCleaner().run(network); + link.getAttributes().putAttribute(NetworkUtils.ALLOWED_SPEED, speed); - // also clean lanes - lanes.getLanesToLinkAssignments().keySet().removeIf(l2l -> !network.getLinks().containsKey(l2l)); + if (prop == null) { + log.warn("Skipping unknown link type: {}", type.highway); + continue; + } - for (List connections : sumoHandler.connections.values()) { - for (SumoNetworkHandler.Connection conn : connections) { + link.setFreespeed(LinkProperties.calculateSpeedIfSpeedTag(speed, freeSpeedFactor)); + link.setCapacity(LinkProperties.getLaneCapacity(link.getLength(), prop) * link.getNumberOfLanes()); - Id fromLink = Id.createLinkId(conn.from); - Id toLink = Id.createLinkId(conn.to); + lanes.addLanesToLinkAssignment(l2l); + network.addLink(link); + } - LanesToLinkAssignment l2l = lanes.getLanesToLinkAssignments().get(fromLink); + if (shapeFile != null) { + Geometry shp = calculateNetworkArea(shapeFile); - // link was removed - if (l2l == null) - continue; + // remove lanes outside survey area + for (Node node : network.getNodes().values()) { + if (!shp.contains(MGC.coord2Point(node.getCoord()))) { + node.getOutLinks().keySet().forEach(l -> lanes.getLanesToLinkAssignments().remove(l)); + node.getInLinks().keySet().forEach(l -> lanes.getLanesToLinkAssignments().remove(l)); + } + } + } - Lane lane = l2l.getLanes().values().stream().filter(l -> l.getAlignment() == conn.fromLane).findFirst().orElse(null); - if (lane == null) { - log.warn("Could not find from lane in network for {}", conn); - continue; - } + // clean up network + new NetworkCleaner().run(network); - lane.addToLinkId(toLink); - } - } + // also clean lanes + lanes.getLanesToLinkAssignments().keySet().removeIf(l2l -> !network.getLinks().containsKey(l2l)); - int removed = 0; - - Iterator it = lanes.getLanesToLinkAssignments().values().iterator(); + for (List connections : sumoHandler.connections.values()) { + for (SumoNetworkHandler.Connection conn : connections) { - // lanes needs to have a target, if missing we need to chose one - while (it.hasNext()) { - LanesToLinkAssignment l2l = it.next(); - - for (Lane lane : l2l.getLanes().values()) { - if (lane.getToLinkIds() == null && lane.getToLaneIds() == null) { - // chose first reachable link from this lane - Collection out = network.getLinks().get(l2l.getLinkId()).getToNode().getOutLinks().values(); - out.forEach(l -> lane.addToLinkId(l.getId())); - - log.warn("No target for lane {}, chosen {}", lane.getId(), out); - } - } - - Set> targets = l2l.getLanes().values().stream() - .filter(l -> l.getToLinkIds() != null) - .map(Lane::getToLinkIds).flatMap(List::stream) - .collect(Collectors.toSet()); - - // remove superfluous lanes (both pointing to same link with not alternative) - if (targets.size() == 1 && network.getLinks().get(l2l.getLinkId()).getToNode().getOutLinks().size() <= 1) { - it.remove(); - removed++; - } - } - - log.info("Removed {} superfluous lanes, total={}", removed, lanes.getLanesToLinkAssignments().size()); - return sumoHandler; - } - - private void writeInductionLoops(File file, SumoNetworkHandler other) throws IOException { - Path loops = Path.of(file.getAbsolutePath().replace(".xml", "_loops.xml")); - BufferedWriter writer = Files.newBufferedWriter(loops); + Id fromLink = Id.createLinkId(conn.from); + Id toLink = Id.createLinkId(conn.to); - log.info("Writing induction loop definition {}", loops); - writer.write("\n"); + LanesToLinkAssignment l2l = lanes.getLanesToLinkAssignments().get(fromLink); - // ignore duplicated - Set written = new HashSet<>(); + // link was removed + if (l2l == null) + continue; - for (SumoNetworkHandler.Edge edge : other.edges.values()) { - for (SumoNetworkHandler.Lane lane : edge.lanes) { - if (!written.contains(lane.id)) { - writer.write(String.format(" \n", lane.id, lane.id)); - written.add(lane.id); - } + Lane lane = l2l.getLanes().values().stream().filter(l -> l.getAlignment() == conn.fromLane).findFirst().orElse(null); + if (lane == null) { + log.warn("Could not find from lane in network for {}", conn); + continue; + } - } - } + lane.addToLinkId(toLink); + } + } + + int removed = 0; + + Iterator it = lanes.getLanesToLinkAssignments().values().iterator(); + + // lanes needs to have a target, if missing we need to chose one + while (it.hasNext()) { + LanesToLinkAssignment l2l = it.next(); + + for (Lane lane : l2l.getLanes().values()) { + if (lane.getToLinkIds() == null && lane.getToLaneIds() == null) { + // chose first reachable link from this lane + Collection out = network.getLinks().get(l2l.getLinkId()).getToNode().getOutLinks().values(); + out.forEach(l -> lane.addToLinkId(l.getId())); - writer.write(""); + log.warn("No target for lane {}, chosen {}", lane.getId(), out); + } + } - writer.close(); - } + Set> targets = l2l.getLanes().values().stream() + .filter(l -> l.getToLinkIds() != null) + .map(Lane::getToLinkIds).flatMap(List::stream) + .collect(Collectors.toSet()); - private Node createNode(Network network, SumoNetworkHandler sumoHandler, String nodeId) { + // remove superfluous lanes (both pointing to same link with not alternative) + if (targets.size() == 1 && network.getLinks().get(l2l.getLinkId()).getToNode().getOutLinks().size() <= 1) { + it.remove(); + removed++; + } + } + + log.info("Removed {} superfluous lanes, total={}", removed, lanes.getLanesToLinkAssignments().size()); + return sumoHandler; + } - Id id = Id.createNodeId(nodeId); - Node node = network.getNodes().get(id); - if (node != null) - return node; + private void writeInductionLoops(File file, SumoNetworkHandler other) throws IOException { + Path loops = Path.of(file.getAbsolutePath().replace(".xml", "_loops.xml")); + BufferedWriter writer = Files.newBufferedWriter(loops); - SumoNetworkHandler.Junction junction = sumoHandler.junctions.get(nodeId); - if (junction == null) - throw new IllegalStateException("Junction not in network:" + nodeId); + log.info("Writing induction loop definition {}", loops); + writer.write("\n"); - Coord coord = sumoHandler.createCoord(junction.coord); - node = network.getFactory().createNode(id, coord); - node.getAttributes().putAttribute("type", junction.type); + // ignore duplicated + Set written = new HashSet<>(); - network.addNode(node); - return node; - } + for (SumoNetworkHandler.Edge edge : other.edges.values()) { + for (SumoNetworkHandler.Lane lane : edge.lanes) { + if (!written.contains(lane.id)) { + writer.write(String.format(" \n", lane.id, lane.id)); + written.add(lane.id); + } + + } + } + + writer.write(""); + + writer.close(); + } + + private Node createNode(Network network, SumoNetworkHandler sumoHandler, String nodeId) { + + Id id = Id.createNodeId(nodeId); + Node node = network.getNodes().get(id); + if (node != null) + return node; + + SumoNetworkHandler.Junction junction = sumoHandler.junctions.get(nodeId); + if (junction == null) + throw new IllegalStateException("Junction not in network:" + nodeId); + + Coord coord = sumoHandler.createCoord(junction.coord); + node = network.getFactory().createNode(id, coord); + node.getAttributes().putAttribute("type", junction.type); + + network.addNode(node); + return node; + } } 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 bfe6adb3158..65de2df3a94 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 @@ -80,6 +80,20 @@ private static BitSet parseBitSet(String value) { return bitSet; } + /** + * Parse mode list from attribute. + */ + private static Set parseModes(String modes) { + if (modes == null) + return null; + + return Arrays.stream(modes.split(" ")) + .filter(s -> !s.isEmpty()) + .map(String::trim) + .map(String::intern) + .collect(Collectors.toSet()); + } + public Map getJunctions() { return junctions; } @@ -99,7 +113,7 @@ public Map getTypes() { /** * 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. + * This function does not clean left over edges, when using this, a network cleaner should be used afterward. * * @param other other network to merge into this one * @param ct coordinate transformation to apply @@ -216,7 +230,9 @@ public void startElement(String uri, String localName, String qName, Attributes attributes.getValue("id"), Integer.parseInt(attributes.getValue("index")), Double.parseDouble(attributes.getValue("length")), - Double.parseDouble(attributes.getValue("speed")) + Double.parseDouble(attributes.getValue("speed")), + parseModes(attributes.getValue("allow")), + parseModes(attributes.getValue("disallow")) ); tmpEdge.lanes.add(lane); @@ -385,15 +401,25 @@ static final class Lane { final double length; final double speed; - Lane(String id, int index, double length, double speed) { + /** + * Allowed vehicle types on this lane. + */ + @Nullable + final Set allow; + @Nullable + final Set disallow; + + Lane(String id, int index, double length, double speed, @Nullable Set allow, @Nullable Set disallow) { this.id = id; this.index = index; this.length = length; this.speed = speed; + this.allow = allow; + this.disallow = disallow; } Lane withLength(double newLength) { - return new Lane(id, index, newLength, speed); + return new Lane(id, index, newLength, speed, allow, disallow); } } From 42e4d844b14f51d6ad1b3ad88cfb1af877342d95 Mon Sep 17 00:00:00 2001 From: rakow Date: Tue, 26 Mar 2024 18:27:20 +0100 Subject: [PATCH 46/51] more flexible filter for shp option index (#3186) --- .../org/matsim/application/options/LanduseOptions.java | 3 ++- .../java/org/matsim/application/options/ShpOptions.java | 7 ++++--- .../freight/tripGeneration/DefaultLocationCalculator.java | 5 ++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/contribs/application/src/main/java/org/matsim/application/options/LanduseOptions.java b/contribs/application/src/main/java/org/matsim/application/options/LanduseOptions.java index f1afcf2b63e..a4623c14237 100644 --- a/contribs/application/src/main/java/org/matsim/application/options/LanduseOptions.java +++ b/contribs/application/src/main/java/org/matsim/application/options/LanduseOptions.java @@ -8,6 +8,7 @@ import javax.annotation.Nullable; import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.util.Objects; import java.util.Set; import java.util.function.Supplier; @@ -49,7 +50,7 @@ public synchronized ShpOptions.Index getIndex(String queryCRS) { ShpOptions landShp = new ShpOptions(landuse, null, StandardCharsets.UTF_8); - index = landShp.createIndex(queryCRS, attr, filter); + index = landShp.createIndex(queryCRS, attr, ft-> filter == null || filter.contains(Objects.toString(ft.getAttribute(attr)))); log.info("Read {} features for landuse", index.size()); 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 ab40fd1f3c8..79069264296 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 @@ -38,6 +38,7 @@ import java.util.Collection; import java.util.List; import java.util.Set; +import java.util.function.Predicate; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -203,7 +204,7 @@ public Geometry getGeometry() { * @param attr the attribute to query from the shape file * @param filter filter features by attribute values */ - public Index createIndex(String queryCRS, String attr, Set filter) { + public Index createIndex(String queryCRS, String attr, Predicate filter) { if (!isDefined()) throw new IllegalStateException("Shape file path not specified"); @@ -308,7 +309,7 @@ public final class Index { * @param ct coordinate transform from query to target crs * @param attr attribute for the result of {@link #query(Coord)} */ - Index(CoordinateTransformation ct, ShapefileDataStore ds, String attr, @Nullable Set filter) throws IOException { + Index(CoordinateTransformation ct, ShapefileDataStore ds, String attr, @Nullable Predicate filter) throws IOException { if (shpCharset != null) ds.setCharset(shpCharset); @@ -321,7 +322,7 @@ public final class Index { continue; } - if (filter != null && !filter.contains(ft.getAttribute(attr))) + if (filter != null && !filter.test(ft)) continue; Geometry geom = (Geometry) ft.getDefaultGeometry(); diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/DefaultLocationCalculator.java b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/DefaultLocationCalculator.java index 81d4782f2a6..2cffcf00170 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/DefaultLocationCalculator.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/DefaultLocationCalculator.java @@ -56,7 +56,10 @@ private void prepareMapping() throws IOException { } } } - ShpOptions.Index index = shp.createIndex("EPSG:25832", "NUTS_ID", relevantNutsIds); // network CRS: EPSG:25832 + + // network CRS: EPSG:25832 + ShpOptions.Index index = shp.createIndex("EPSG:25832", "NUTS_ID", + ft -> relevantNutsIds.contains(Objects.toString(ft.getAttribute("NUTS_ID")))); logger.info("Reading land use data..."); ShpOptions.Index landIndex = landUse.getIndex("EPSG:25832"); //TODO From 41847dfe97b9b79cc3c632bb89c4b3e2295122e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:52:29 +0000 Subject: [PATCH 47/51] build(deps): bump com.fasterxml.woodstox:woodstox-core Bumps [com.fasterxml.woodstox:woodstox-core](https://github.com/FasterXML/woodstox) from 6.6.1 to 6.6.2. - [Commits](https://github.com/FasterXML/woodstox/compare/woodstox-core-6.6.1...woodstox-core-6.6.2) --- updated-dependencies: - dependency-name: com.fasterxml.woodstox:woodstox-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 56a3ce82ee7..773d108babb 100644 --- a/pom.xml +++ b/pom.xml @@ -212,7 +212,7 @@ com.fasterxml.woodstox woodstox-core - 6.6.1 + 6.6.2 From e8580dbc2212eb9b86dd7ccbe39db5c91726db70 Mon Sep 17 00:00:00 2001 From: rakow Date: Wed, 27 Mar 2024 20:09:31 +0100 Subject: [PATCH 48/51] App contrib maintenance (#3191) * improve csv and shp options * improve count options file format * add log message * update bast counts test * remove lane functionality from sumo converter, use DisallowedLinks instead --- .../application/options/CountsOption.java | 126 ------------ .../application/options/CountsOptions.java | 155 +++++++++++++++ .../application/options/CsvOptions.java | 2 +- .../application/options/ShpOptions.java | 23 +-- .../counts/CreateCountsFromBAStData.java | 10 +- .../network/CreateNetworkFromSumo.java | 34 +--- .../counts/CreateCountsFromBAStDataTest.java | 12 +- .../application/prepare/counts/ignored.csv | 1 - .../application/prepare/counts/manual.csv | 2 - .../application/prepare/counts/mapping.csv | 4 + .../contrib/sumo/SumoNetworkConverter.java | 182 ++++++------------ .../sumo/SumoNetworkConverterTest.java | 23 +-- 12 files changed, 253 insertions(+), 321 deletions(-) delete mode 100644 contribs/application/src/main/java/org/matsim/application/options/CountsOption.java create mode 100644 contribs/application/src/main/java/org/matsim/application/options/CountsOptions.java delete mode 100644 contribs/application/test/input/org/matsim/application/prepare/counts/ignored.csv delete mode 100644 contribs/application/test/input/org/matsim/application/prepare/counts/manual.csv create mode 100644 contribs/application/test/input/org/matsim/application/prepare/counts/mapping.csv diff --git a/contribs/application/src/main/java/org/matsim/application/options/CountsOption.java b/contribs/application/src/main/java/org/matsim/application/options/CountsOption.java deleted file mode 100644 index bea5678c997..00000000000 --- a/contribs/application/src/main/java/org/matsim/application/options/CountsOption.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.matsim.application.options; - -import org.apache.commons.csv.CSVFormat; -import org.apache.commons.csv.CSVRecord; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.network.Link; -import picocli.CommandLine; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; -import java.util.stream.Collectors; - -/** - * Common options when working with counts data. - */ -public final class CountsOption { - - @CommandLine.Option(names = "--ignored-counts", description = "path to csv with count station ids to ignore") - private Path ignored; - - @CommandLine.Option(names = "--manual-matched-counts", description = "path to csv with manual matched count stations and link ids") - private Path manual; - - private Set ignoredCounts = null; - - private Map> manualMatchedCounts = null; - - public CountsOption() { - } - - public CountsOption(@Nullable Path ignored, @Nullable Path manual) { - this.ignored = ignored; - this.manual = manual; - } - - /** - * Get list of ignored count ids. - */ - public Set getIgnored() { - readIgnored(); - return ignoredCounts; - } - - /** - * Return mapping of count id to specified link id. - */ - public Map> getManualMatched() { - readManualMatched(); - return manualMatchedCounts; - } - - private void readManualMatched() { - - // Already read - if (manualMatchedCounts != null) - return; - - if (manual == null) { - manualMatchedCounts = new HashMap<>(); - return; - } - - try (var reader = Files.newBufferedReader(manual)) { - List records = CSVFormat.Builder.create() - .setAllowMissingColumnNames(true) - .setDelimiter(';') - .build() - .parse(reader) - .getRecords(); - - manualMatchedCounts = records.stream().collect( - Collectors.toMap( - r -> r.get(0), - r -> Id.createLinkId(r.get(1)) - ) - ); - - } catch (IOException e) { - throw new UncheckedIOException(e); - } - - } - - private void readIgnored() { - // Already read the counts - if (ignoredCounts != null) - return; - - if (ignored == null) { - ignoredCounts = new HashSet<>(); - return; - } - - try { - ignoredCounts = new HashSet<>(Files.readAllLines(ignored)); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - /** - * Check whether station id should be ignored. - */ - public boolean isIgnored(String stationId) { - readIgnored(); - return ignoredCounts.contains(stationId); - } - - /** - * Return manually matched link id. - * - * @return null if not matched - */ - public Id isManuallyMatched(String stationId) { - readManualMatched(); - - if (manualMatchedCounts.isEmpty() || !manualMatchedCounts.containsKey(stationId)) - return null; - - return manualMatchedCounts.get(stationId); - } -} diff --git a/contribs/application/src/main/java/org/matsim/application/options/CountsOptions.java b/contribs/application/src/main/java/org/matsim/application/options/CountsOptions.java new file mode 100644 index 00000000000..3056bfd1a3e --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/options/CountsOptions.java @@ -0,0 +1,155 @@ +package org.matsim.application.options; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.io.IOUtils; +import picocli.CommandLine; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.*; + +/** + * Common options when working with counts data. + */ +public final class CountsOptions { + + private static final Logger log = LogManager.getLogger(CountsOptions.class); + + @CommandLine.Option(names = "--counts-mapping", description = "Path to csv with count station ids to ignore") + private String input; + + private Map> manualMatchedCounts = null; + private Set ignoredCounts = null; + + public CountsOptions() { + } + + public CountsOptions(@Nullable String input) { + this.input = input; + } + + /** + * Get list of ignored count ids. + */ + public Set getIgnored() { + readMapping(); + return ignoredCounts; + } + + /** + * Return mapping of count id to specified link id. + */ + public Map> getManualMatched() { + readMapping(); + return manualMatchedCounts; + } + + private synchronized void readMapping() { + + // Already read + if (manualMatchedCounts != null) + return; + + manualMatchedCounts = new HashMap<>(); + ignoredCounts = new HashSet<>(); + + // No input file + if (input == null) + return; + + try (var reader = IOUtils.getBufferedReader(input)) { + CSVFormat format = CSVFormat.Builder.create() + .setAllowMissingColumnNames(true) + .setDelimiter(CsvOptions.detectDelimiter(input)) + .setHeader() + .setSkipHeaderRecord(true) + .build(); + + try (CSVParser csv = new CSVParser(reader, format)) { + Schema schema = parseSchema(csv.getHeaderNames()); + + log.info("Using schema for counts mapping: {}", schema); + + for (CSVRecord row : csv) { + + String stationId = row.get(schema.stationColumn); + manualMatchedCounts.put(stationId, Id.createLinkId(row.get(schema.linkColumn))); + + if (schema.usingColumn != null) { + + String value = row.get(schema.usingColumn).strip().toLowerCase(); + boolean val = value.equals("y") || value.equals("x") || value.equals("true"); + + if (schema.isWhiteList && !val) + ignoredCounts.add(stationId); + else if (!schema.isWhiteList && val) + ignoredCounts.add(stationId); + } + } + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + } + + /** + * Check whether station id should be ignored. + */ + public boolean isIgnored(String stationId) { + readMapping(); + return ignoredCounts.contains(stationId); + } + + /** + * Return manually matched link id. + * + * @return null if not matched + */ + public Id isManuallyMatched(String stationId) { + readMapping(); + + if (manualMatchedCounts.isEmpty() || !manualMatchedCounts.containsKey(stationId)) + return null; + + return manualMatchedCounts.get(stationId); + } + + private Schema parseSchema(List header) { + + List names = header.stream() + .map(String::toLowerCase) + .map(String::strip) + .map(s -> s.replace("_", "")) + .toList(); + + int linkId = names.indexOf("linkid"); + + if (linkId < 0) + throw new IllegalArgumentException("Link id column not found in csv: " + header); + + int using = names.indexOf("using"); + int ignore = names.indexOf("ignore"); + + // first or second column for station id + int station = linkId == 0 ? 1 : 0; + + if (using > 0) + return new Schema(header.get(station), header.get(linkId), header.get(using), true); + + if (ignore > 0) + return new Schema(header.get(station), header.get(linkId), header.get(ignore), false); + + return new Schema(header.get(station), header.get(linkId), null, false); + } + + private record Schema(String stationColumn, String linkColumn, String usingColumn, boolean isWhiteList) { + } +} 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 a022a6f5771..1b2d6575450 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 @@ -80,7 +80,7 @@ public static Character detectDelimiter(String path) throws IOException { * Get the CSV format defined by the options. */ public CSVFormat getFormat() { - CSVFormat.Builder format = this.csvFormat.getFormat().builder().setSkipHeaderRecord(true); + CSVFormat.Builder format = this.csvFormat.getFormat().builder().setHeader().setSkipHeaderRecord(true); if (csvDelimiter != null) format = format.setDelimiter(csvDelimiter); 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 79069264296..7962c3d8d80 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 @@ -369,8 +369,15 @@ public SimpleFeature queryFeature(Coord coord) { List result = index.query(new Envelope(p)); for (SimpleFeature ft : result) { Geometry geom = (Geometry) ft.getDefaultGeometry(); - if (geom.contains(MGC.coordinate2Point(p))) - return ft; + + // Catch Exception for invalid, too complex geometries + try { + if (geom.contains(MGC.coordinate2Point(p))) + return ft; + } catch (TopologyException e) { + if (geom.convexHull().contains(MGC.coordinate2Point(p))) + return ft; + } } return null; @@ -381,17 +388,7 @@ public SimpleFeature queryFeature(Coord coord) { */ @SuppressWarnings("unchecked") public boolean contains(Coord coord) { - - Coordinate p = MGC.coord2Coordinate(ct.transform(coord)); - - List result = index.query(new Envelope(p)); - for (SimpleFeature ft : result) { - Geometry geom = (Geometry) ft.getDefaultGeometry(); - if (geom.contains(MGC.coordinate2Point(p))) - return true; - } - - return false; + return queryFeature(coord) != null; } /** diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/counts/CreateCountsFromBAStData.java b/contribs/application/src/main/java/org/matsim/application/prepare/counts/CreateCountsFromBAStData.java index dd02f6572ee..f4db223e183 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/counts/CreateCountsFromBAStData.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/counts/CreateCountsFromBAStData.java @@ -11,7 +11,7 @@ import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; import org.matsim.application.MATSimAppCommand; -import org.matsim.application.options.CountsOption; +import org.matsim.application.options.CountsOptions; import org.matsim.application.options.CrsOptions; import org.matsim.application.options.ShpOptions; import org.matsim.core.config.groups.NetworkConfigGroup; @@ -63,7 +63,7 @@ public class CreateCountsFromBAStData implements MATSimAppCommand { @CommandLine.Mixin private final ShpOptions shp = new ShpOptions(); @CommandLine.Mixin - private final CountsOption counts = new CountsOption(); + private final CountsOptions counts = new CountsOptions(); @CommandLine.Mixin private final CrsOptions crs = new CrsOptions("EPSG:25832"); @CommandLine.Option(names = "--network", description = "path to MATSim network", required = true) @@ -284,7 +284,7 @@ private void readHourlyTrafficVolume(Path pathToDisaggregatedData, Map index, BAStCountStation station, CountsOption counts) { + private void match(Network network, NetworkIndex index, BAStCountStation station, CountsOptions counts) { Id manuallyMatched = counts.isManuallyMatched(station.getId()); Link matched; @@ -330,7 +330,7 @@ private List> createRoadTypeFilter(List types) { return filter; } - private void matchBAStWithNetwork(String pathToNetwork, Map stations, CountsOption countsOption, CrsOptions crs) { + private void matchBAStWithNetwork(String pathToNetwork, Map stations, CountsOptions countsOption, CrsOptions crs) { if (crs.getTargetCRS() != null) throw new RuntimeException("Please don't specify --target-crs. Only use --input-crs to determinate the network crs!"); @@ -366,7 +366,7 @@ private void matchBAStWithNetwork(String pathToNetwork, Map readBAStCountStations(Path pathToAggregatedData, ShpOptions shp, CountsOption counts) { + private Map readBAStCountStations(Path pathToAggregatedData, ShpOptions shp, CountsOptions counts) { List stations = new ArrayList<>(); 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 1a7272bf277..5542ed01d6a 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 @@ -55,9 +55,6 @@ public final class CreateNetworkFromSumo implements MATSimAppCommand { @CommandLine.Option(names = "--output", description = "Output xml file", required = true) private Path output; - @CommandLine.Mixin - private final ShpOptions shp = new ShpOptions(); - @CommandLine.Mixin private final CrsOptions crs = new CrsOptions(); @@ -67,6 +64,9 @@ public final class CreateNetworkFromSumo implements MATSimAppCommand { @CommandLine.Option(names = "--free-speed-factor", description = "Free-speed reduction for urban links") private double freeSpeedFactor = LinkProperties.DEFAULT_FREESPEED_FACTOR; + @CommandLine.Option(names = "--lane-restrictions", description = "Define how restricted lanes are handled: ${COMPLETION-CANDIDATES}", defaultValue = "IGNORE") + private SumoNetworkConverter.LaneRestriction laneRestriction = SumoNetworkConverter.LaneRestriction.IGNORE; + public static void main(String[] args) { System.exit(new CommandLine(new CreateNetworkFromSumo()).execute(args)); } @@ -74,29 +74,11 @@ public static void main(String[] args) { @Override public Integer call() throws Exception { -// 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); + SumoNetworkConverter converter = SumoNetworkConverter.newInstance(input, output, crs.getInputCRS(), crs.getTargetCRS(), freeSpeedFactor, laneRestriction); Network network = NetworkUtils.createNetwork(); - Lanes lanes = LanesUtils.createLanesContainer(); - - SumoNetworkHandler handler = converter.convert(network, lanes); - - converter.calculateLaneCapacities(network, lanes); - // This needs to run without errors, otherwise network is broken - network.getLinks().values().forEach(link -> { - LanesToLinkAssignment l2l = lanes.getLanesToLinkAssignments().get(link.getId()); - if (l2l != null) - LanesUtils.createLanes(link, l2l); - }); + SumoNetworkHandler handler = converter.convert(network); if (capacities != null) { @@ -105,10 +87,8 @@ public Integer call() throws Exception { log.info("Read lane capacities from {}, containing {} lanes", capacities, map.size()); int n = setLinkCapacities(network, map); - int n2 = setLaneCapacities(lanes, map); - - log.info("Unmatched links: {}, lanes: {}", n, n2); + log.info("Unmatched links: {}", n); } if (crs.getTargetCRS() != null) @@ -116,10 +96,8 @@ public Integer call() throws Exception { NetworkUtils.writeNetwork(network, output.toAbsolutePath().toString()); new NetworkWriter(network).write(output.toAbsolutePath().toString()); - new LanesWriter(lanes).write(output.toAbsolutePath().toString().replace(".xml", "-lanes.xml")); 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/test/java/org/matsim/application/prepare/counts/CreateCountsFromBAStDataTest.java b/contribs/application/src/test/java/org/matsim/application/prepare/counts/CreateCountsFromBAStDataTest.java index c74d59b7801..1545ef4395d 100644 --- a/contribs/application/src/test/java/org/matsim/application/prepare/counts/CreateCountsFromBAStDataTest.java +++ b/contribs/application/src/test/java/org/matsim/application/prepare/counts/CreateCountsFromBAStDataTest.java @@ -22,8 +22,7 @@ public class CreateCountsFromBAStDataTest { String countsOutput = "test-counts.xml.gz"; - String ignoredCounts = "ignored.csv"; - String manualMatchedCounts = "manual.csv"; + String mapping = "mapping.csv"; String wrongManualMatchedCounts = "wrong_manual.csv"; String network = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("berlin"), "network.xml.gz").toString(); @@ -61,9 +60,6 @@ void testCreateCountsFromBAStData() { assertThat(counts.getMeasureLocations()) .hasSize(24); - assertThat(counts.getCounts()) - .hasSize(24); - for (Map.Entry, MeasurementLocation> e : counts.getMeasureLocations().entrySet()) { assertThat(e.getValue().hasMeasurableForMode(Measurable.VOLUMES, TransportMode.car)) .isTrue(); @@ -105,7 +101,7 @@ void testWithIgnoredStations() { "--shp-crs=" + shpCrs, "--year=2021", "--output=" + out2, - "--ignored-counts=" + utils.getPackageInputDirectory() + ignoredCounts, + "--counts-mapping=" + utils.getPackageInputDirectory() + mapping, }; new CreateCountsFromBAStData().execute(args2); @@ -140,7 +136,7 @@ void testManualMatchedCounts() { "--shp-crs=" + shpCrs, "--year=2021", "--output=" + out, - "--manual-matched-counts=" + utils.getPackageInputDirectory() + manualMatchedCounts, + "--counts-mapping=" + utils.getPackageInputDirectory() + mapping, }; new CreateCountsFromBAStData().execute(args); @@ -178,7 +174,7 @@ void testManualMatchingWithWrongInput() { "--shp-crs=" + shpCrs, "--year=2021", "--output=" + out, - "--manual-matched-counts=" + utils.getPackageInputDirectory() + wrongManualMatchedCounts, + "--counts-mapping=" + utils.getPackageInputDirectory() + wrongManualMatchedCounts, }; Assertions.assertThrows(RuntimeException.class, () -> new CreateCountsFromBAStData().execute(args)); diff --git a/contribs/application/test/input/org/matsim/application/prepare/counts/ignored.csv b/contribs/application/test/input/org/matsim/application/prepare/counts/ignored.csv deleted file mode 100644 index a43b7bf6621..00000000000 --- a/contribs/application/test/input/org/matsim/application/prepare/counts/ignored.csv +++ /dev/null @@ -1 +0,0 @@ -2012 diff --git a/contribs/application/test/input/org/matsim/application/prepare/counts/manual.csv b/contribs/application/test/input/org/matsim/application/prepare/counts/manual.csv deleted file mode 100644 index 58488f11a34..00000000000 --- a/contribs/application/test/input/org/matsim/application/prepare/counts/manual.csv +++ /dev/null @@ -1,2 +0,0 @@ -2012_1;4205 -2012_2;4219 diff --git a/contribs/application/test/input/org/matsim/application/prepare/counts/mapping.csv b/contribs/application/test/input/org/matsim/application/prepare/counts/mapping.csv new file mode 100644 index 00000000000..c6503661752 --- /dev/null +++ b/contribs/application/test/input/org/matsim/application/prepare/counts/mapping.csv @@ -0,0 +1,4 @@ +station,linkId,Using +2012_1,4205,x +2012_2,4219,x +2014,xxx, \ No newline at end of file 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 1f311fc663a..592243b1310 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 @@ -15,15 +15,14 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.contrib.osm.networkReader.LinkProperties; import org.matsim.contrib.osm.networkReader.OsmTags; +import org.matsim.core.network.DisallowedNextLinks; import org.matsim.core.network.NetworkUtils; import org.matsim.core.network.algorithms.NetworkCleaner; import org.matsim.core.scenario.ProjectionUtils; 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.GeoFileReader; import org.matsim.core.utils.io.IOUtils; -import org.matsim.lanes.*; import org.xml.sax.SAXException; import picocli.CommandLine; @@ -37,8 +36,6 @@ import java.util.concurrent.Callable; import java.util.stream.Collectors; -import static org.matsim.lanes.LanesUtils.calculateAndSetCapacity; - /** * Converter for sumo networks * @@ -54,9 +51,6 @@ public class SumoNetworkConverter implements Callable { @CommandLine.Option(names = "--output", description = "Output xml file", required = true) private Path output; - @CommandLine.Option(names = "--shp", description = "Optional shape file used for filtering") - private Path shapeFile; - @CommandLine.Option(names = "--from-crs", description = "Coordinate system of input data", required = true) private String fromCRS; @@ -66,14 +60,18 @@ public class SumoNetworkConverter implements Callable { @CommandLine.Option(names = "--free-speed-factor", description = "Free-speed reduction for urban links", defaultValue = "0.9") private double freeSpeedFactor = LinkProperties.DEFAULT_FREESPEED_FACTOR; - private SumoNetworkConverter(List input, Path output, Path shapeFile, String fromCRS, String toCRS, double freeSpeedFactor) { + @CommandLine.Option(names = "--lane-restrictions", description = "Define how restricted lanes are handled: ${COMPLETION-CANDIDATES}", defaultValue = "IGNORE") + private LaneRestriction laneRestriction = LaneRestriction.IGNORE; + + private SumoNetworkConverter(List input, Path output, String fromCRS, String toCRS, double freeSpeedFactor, + LaneRestriction laneRestriction) { this.input = input; this.output = output; - this.shapeFile = shapeFile; this.fromCRS = fromCRS; this.toCRS = toCRS; this.freeSpeedFactor = freeSpeedFactor; - } + this.laneRestriction = laneRestriction; + } private SumoNetworkConverter() { } @@ -87,26 +85,27 @@ private SumoNetworkConverter() { * @param toCRS desired coordinate system of network */ public static SumoNetworkConverter newInstance(List input, Path output, String fromCRS, String toCRS) { - return new SumoNetworkConverter(input, output, null, fromCRS, toCRS, LinkProperties.DEFAULT_FREESPEED_FACTOR); + return new SumoNetworkConverter(input, output, fromCRS, toCRS, LinkProperties.DEFAULT_FREESPEED_FACTOR, LaneRestriction.IGNORE); } + /** - * Creates a new converter instance, with a shape file for filtering. + * Creates a new instance. * - * @param shapeFile only include links in this shape file. - * @see #newInstance(List, Path, String, String) + * @see #newInstance(List, Path, String, String, double) */ - public static SumoNetworkConverter newInstance(List input, Path output, Path shapeFile, String fromCRS, String toCRS) { - return new SumoNetworkConverter(input, output, shapeFile, fromCRS, toCRS, LinkProperties.DEFAULT_FREESPEED_FACTOR); + public static SumoNetworkConverter newInstance(List input, Path output, String inputCRS, String targetCRS, double freeSpeedFactor) { + return new SumoNetworkConverter(input, output, inputCRS, targetCRS, freeSpeedFactor, LaneRestriction.IGNORE); } /** * Creates a new instance. * - * @see #newInstance(List, Path, Path, String, String, double) + * @see #newInstance(List, Path, String, String, double) */ - public static SumoNetworkConverter newInstance(List input, Path output, Path shapeFile, String inputCRS, String targetCRS, double freeSpeedFactor) { - return new SumoNetworkConverter(input, output, shapeFile, inputCRS, targetCRS, freeSpeedFactor); + public static SumoNetworkConverter newInstance(List input, Path output, String inputCRS, String targetCRS, + double freeSpeedFactor, LaneRestriction laneRestriction) { + return new SumoNetworkConverter(input, output, inputCRS, targetCRS, freeSpeedFactor, laneRestriction); } /** @@ -147,32 +146,20 @@ private static boolean isModeAllowed(String mode, SumoNetworkHandler.Edge edge, /** * Execute the converter, which includes conversion and writing the files * - * @see #convert(Network, Lanes) . + * @see #convert(Network). */ @Override public Integer call() throws Exception { Network network = NetworkUtils.createNetwork(); - Lanes lanes = LanesUtils.createLanesContainer(); - SumoNetworkHandler handler = convert(network, lanes); - - calculateLaneCapacities(network, lanes); - - // This needs to run without errors, otherwise network is broken - network.getLinks().values().forEach(link -> { - LanesToLinkAssignment l2l = lanes.getLanesToLinkAssignments().get(link.getId()); - if (l2l != null) - LanesUtils.createLanes(link, l2l); - }); + SumoNetworkHandler handler = convert(network); if (toCRS != null) ProjectionUtils.putCRS(network, toCRS); NetworkUtils.writeNetwork(network, output.toAbsolutePath().toString()); - new LanesWriter(lanes).write(output.toAbsolutePath().toString().replace(".xml", "-lanes.xml")); - writeGeometry(handler, output.toAbsolutePath().toString().replace(".xml", "-linkGeometries.csv")); writeFeatures(handler, output.toAbsolutePath().toString().replace(".xml", "-ft.csv")); @@ -196,19 +183,6 @@ public void writeFeatures(SumoNetworkHandler handler, String output) { } } - /** - * Calculates lane capacities, according to {@link LanesUtils}. - */ - public void calculateLaneCapacities(Network network, Lanes lanes) { - for (LanesToLinkAssignment l2l : lanes.getLanesToLinkAssignments().values()) { - Link link = network.getLinks().get(l2l.getLinkId()); - for (Lane lane : l2l.getLanes().values()) { - calculateAndSetCapacity(lane, - lane.getToLaneIds() == null || lane.getToLaneIds().isEmpty(), link, network); - } - } - } - /** * Writes link geometries. */ @@ -252,10 +226,9 @@ public void writeGeometry(SumoNetworkHandler handler, String path) { * Perform the actual conversion on given input data. * * @param network results will be added into this network. - * @param lanes resulting lanes are added into this object. * @return internal handler used for conversion */ - public SumoNetworkHandler convert(Network network, Lanes lanes) throws ParserConfigurationException, SAXException, IOException { + public SumoNetworkHandler convert(Network network) throws ParserConfigurationException, SAXException, IOException { log.info("Parsing SUMO network"); @@ -276,7 +249,6 @@ public SumoNetworkHandler convert(Network network, Lanes lanes) throws ParserCon } NetworkFactory f = network.getFactory(); - LanesFactory lf = lanes.getFactory(); Map linkProperties = LinkProperties.createLinkProperties(); @@ -299,7 +271,6 @@ public SumoNetworkHandler convert(Network network, Lanes lanes) throws ParserCon link.getAttributes().putAttribute(NetworkUtils.TYPE, edge.type); - link.setNumberOfLanes(edge.lanes.size()); Set modes = Sets.newHashSet(TransportMode.car, TransportMode.ride); SumoNetworkHandler.Type type = sumoHandler.types.get(edge.type); @@ -318,28 +289,33 @@ public SumoNetworkHandler convert(Network network, Lanes lanes) throws ParserCon link.setAllowedModes(modes); link.setLength(edge.getLength()); - LanesToLinkAssignment l2l = lf.createLanesToLinkAssignment(link.getId()); - for (SumoNetworkHandler.Lane lane : edge.lanes) { - Lane mLane = lf.createLane(Id.create(lane.id, Lane.class)); - mLane.setAlignment(lane.index); - mLane.setStartsAtMeterFromLinkEnd(lane.length); - l2l.addLane(mLane); + if (laneRestriction == LaneRestriction.REDUCE_CAR_LANES) { + + int size = edge.lanes.size(); + + SumoNetworkHandler.Lane lane = edge.lanes.get(0); + edge.lanes.removeIf(l -> l.allow != null && !l.allow.contains("passenger")); + + // Keep at least one lane + if (edge.lanes.isEmpty()) + edge.lanes.add(lane); + + int restricted = size - edge.lanes.size(); + if (restricted > 0) { + link.getAttributes().putAttribute("restricted_lanes", restricted); + } } + link.setNumberOfLanes(edge.lanes.size()); + // set link prop based on MATSim defaults LinkProperties prop = linkProperties.get(type.highway); double speed = type.speed; // incoming lane connected to the others // this is needed by matsim for lanes to work properly - if (edge.lanes.size() >= 1) { - Lane inLane = lf.createLane(Id.create(link.getId() + "_in", Lane.class)); - inLane.setStartsAtMeterFromLinkEnd(link.getLength()); - inLane.setAlignment(0); - l2l.getLanes().keySet().forEach(inLane::addToLaneId); - l2l.addLane(inLane); - + if (!edge.lanes.isEmpty()) { double laneSpeed = edge.lanes.get(0).speed; if (!Double.isNaN(laneSpeed) && laneSpeed > 0) { // use speed info of first lane @@ -358,81 +334,44 @@ public SumoNetworkHandler convert(Network network, Lanes lanes) throws ParserCon link.setFreespeed(LinkProperties.calculateSpeedIfSpeedTag(speed, freeSpeedFactor)); link.setCapacity(LinkProperties.getLaneCapacity(link.getLength(), prop) * link.getNumberOfLanes()); - lanes.addLanesToLinkAssignment(l2l); network.addLink(link); } - if (shapeFile != null) { - Geometry shp = calculateNetworkArea(shapeFile); - - // remove lanes outside survey area - for (Node node : network.getNodes().values()) { - if (!shp.contains(MGC.coord2Point(node.getCoord()))) { - node.getOutLinks().keySet().forEach(l -> lanes.getLanesToLinkAssignments().remove(l)); - node.getInLinks().keySet().forEach(l -> lanes.getLanesToLinkAssignments().remove(l)); - } - } - } - // clean up network new NetworkCleaner().run(network); - // also clean lanes - lanes.getLanesToLinkAssignments().keySet().removeIf(l2l -> !network.getLinks().containsKey(l2l)); + Set> ignored = new HashSet<>(); - for (List connections : sumoHandler.connections.values()) { - for (SumoNetworkHandler.Connection conn : connections) { + for (Map.Entry> kv : sumoHandler.connections.entrySet()) { - Id fromLink = Id.createLinkId(conn.from); - Id toLink = Id.createLinkId(conn.to); + Link link = network.getLinks().get(Id.createLinkId(kv.getKey())); - LanesToLinkAssignment l2l = lanes.getLanesToLinkAssignments().get(fromLink); + if (link != null) { + Set> outLinks = link.getToNode().getOutLinks().keySet(); + Set> allowed = kv.getValue().stream().map(c -> Id.createLinkId(c.to)).collect(Collectors.toSet()); - // link was removed - if (l2l == null) - continue; + Sets.SetView> diff = Sets.difference(outLinks, allowed); - Lane lane = l2l.getLanes().values().stream().filter(l -> l.getAlignment() == conn.fromLane).findFirst().orElse(null); - if (lane == null) { - log.warn("Could not find from lane in network for {}", conn); + if (outLinks.size() == diff.size()) { + ignored.add(link.getId()); continue; } - lane.addToLinkId(toLink); - } - } - - int removed = 0; - - Iterator it = lanes.getLanesToLinkAssignments().values().iterator(); - - // lanes needs to have a target, if missing we need to chose one - while (it.hasNext()) { - LanesToLinkAssignment l2l = it.next(); + if (!diff.isEmpty()) { + DisallowedNextLinks disallowed = new DisallowedNextLinks(); + for (Id id : diff) { + disallowed.addDisallowedLinkSequence(TransportMode.car, List.of(id)); + } - for (Lane lane : l2l.getLanes().values()) { - if (lane.getToLinkIds() == null && lane.getToLaneIds() == null) { - // chose first reachable link from this lane - Collection out = network.getLinks().get(l2l.getLinkId()).getToNode().getOutLinks().values(); - out.forEach(l -> lane.addToLinkId(l.getId())); - - log.warn("No target for lane {}, chosen {}", lane.getId(), out); + NetworkUtils.setDisallowedNextLinks(link, disallowed); } } + } - Set> targets = l2l.getLanes().values().stream() - .filter(l -> l.getToLinkIds() != null) - .map(Lane::getToLinkIds).flatMap(List::stream) - .collect(Collectors.toSet()); - - // remove superfluous lanes (both pointing to same link with not alternative) - if (targets.size() == 1 && network.getLinks().get(l2l.getLinkId()).getToNode().getOutLinks().size() <= 1) { - it.remove(); - removed++; - } + if (!ignored.isEmpty()) { + log.warn("Ignored turn restrictions for {} links with no connections: {}", ignored.size(), ignored); } - log.info("Removed {} superfluous lanes, total={}", removed, lanes.getLanesToLinkAssignments().size()); return sumoHandler; } @@ -480,4 +419,11 @@ private Node createNode(Network network, SumoNetworkHandler sumoHandler, String return node; } + /** + * How restricted lanes should be handled. + */ + public enum LaneRestriction { + IGNORE, REDUCE_CAR_LANES + } + } 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 d66ce733c45..2bb89ec4caa 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 @@ -3,21 +3,15 @@ import com.google.common.io.Resources; import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; -import org.matsim.core.config.Config; -import org.matsim.core.config.ConfigUtils; import org.matsim.core.network.NetworkUtils; -import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.lanes.LanesReader; -import org.matsim.lanes.LanesToLinkAssignment; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.List; -import java.util.SortedMap; public class SumoNetworkConverterTest { @@ -39,19 +33,10 @@ void convert() throws Exception { 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")); + Link link = network.getLinks().get(Id.createLinkId("-461905066#1")); - Config config = ConfigUtils.createConfig(); - Scenario scenario = ScenarioUtils.createScenario(config); - - LanesReader reader = new LanesReader(scenario); - reader.readFile(lanes.toString()); - - SortedMap, LanesToLinkAssignment> l2l = scenario.getLanes().getLanesToLinkAssignments(); - - System.out.println(l2l); - - assert l2l.containsKey(Id.createLinkId("-160346478#3")) : "Must contain link id"; + List>> disallowed = NetworkUtils.getDisallowedNextLinks(link).getDisallowedLinkSequences(TransportMode.car); + assert disallowed.contains(List.of(Id.createLinkId("461905066#0"))) : "Must contain disallowed link sequence"; Path geometry = Path.of(output.toString().replace(".xml", "-linkGeometries.csv")); From b243edcac35d842c1854d85a9f6aff345bca3c0f Mon Sep 17 00:00:00 2001 From: Ricardo Ewert <60344745+rewertvsp@users.noreply.github.com> Date: Thu, 28 Mar 2024 13:02:10 +0100 Subject: [PATCH 49/51] use configurable parameter for zone name column (#3192) * use configurable parameter for zone name column * make methods static again --- .../GenerateSmallScaleCommercialTrafficDemand.java | 12 +++++++----- .../SmallScaleCommercialTrafficUtilsTest.java | 2 +- .../TrafficVolumeGenerationTest.java | 8 ++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java index e5b6a27b774..566a1214142 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java @@ -261,7 +261,7 @@ public Integer call() throws Exception { usedLanduseConfiguration.toString(), indexLanduse, indexZones, indexBuildings, indexInvestigationAreaRegions, shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); - Map, Link>> linksPerZone = filterLinksForZones(scenario, indexZones, buildingsPerZone); + Map, Link>> linksPerZone = filterLinksForZones(scenario, indexZones, buildingsPerZone, shapeFileZoneNameColumn); switch (usedSmallScaleCommercialTrafficType) { case commercialPersonTraffic, goodsTraffic -> @@ -909,7 +909,8 @@ private Id findPossibleLink(String zone, String selectedCategory, List, Link>> filterLinksForZones(Scenario scenario, Index indexZones, - Map>> buildingsPerZone) throws URISyntaxException { + Map>> buildingsPerZone, + String shapeFileZoneNameColumn) throws URISyntaxException { Map, Link>> regionLinksMap = new HashMap<>(); List links; log.info("Filtering and assign links to zones. This take some time..."); @@ -936,7 +937,7 @@ static Map, Link>> filterLinksForZones(Scenario scenario, I .computeIfAbsent((String) l.getAttributes().getAttribute("zone"), (k) -> new HashMap<>()) .put(l.getId(), l)); if (regionLinksMap.size() != indexZones.size()) - findNearestLinkForZonesWithoutLinks(networkToChange, regionLinksMap, indexZones, buildingsPerZone); + findNearestLinkForZonesWithoutLinks(networkToChange, regionLinksMap, indexZones, buildingsPerZone, shapeFileZoneNameColumn); return regionLinksMap; } @@ -946,9 +947,10 @@ static Map, Link>> filterLinksForZones(Scenario scenario, I */ private static void findNearestLinkForZonesWithoutLinks(Network networkToChange, Map, Link>> regionLinksMap, Index shpZones, - Map>> buildingsPerZone) { + Map>> buildingsPerZone, + String shapeFileZoneNameColumn) { for (SimpleFeature singleArea : shpZones.getAllFeatures()) { - String zoneID = (String) singleArea.getAttribute("areaID"); + String zoneID = (String) singleArea.getAttribute(shapeFileZoneNameColumn); if (!regionLinksMap.containsKey(zoneID) && buildingsPerZone.get(zoneID) != null) { for (List buildingList : buildingsPerZone.get(zoneID).values()) { for (SimpleFeature building : buildingList) { diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java index 5aa06d111fc..9af01ede414 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtilsTest.java @@ -64,7 +64,7 @@ void findZoneOfLinksTest() throws IOException, URISyntaxException { Map, Link>> regionLinksMap = GenerateSmallScaleCommercialTrafficDemand .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem(), shapeFileZoneNameColumn), - buildingsPerZone); + buildingsPerZone, shapeFileZoneNameColumn); Assertions.assertEquals(3, regionLinksMap.size(), MatsimTestUtils.EPSILON); Assertions.assertEquals(60, regionLinksMap.get("area1").size(), MatsimTestUtils.EPSILON); diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java index b680e568ffb..7b51453072a 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGenerationTest.java @@ -401,7 +401,7 @@ void testAddingExistingScenarios() throws Exception { Map, Link>> regionLinksMap = GenerateSmallScaleCommercialTrafficDemand .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem(), shapeFileZoneNameColumn), - buildingsPerZone); + buildingsPerZone, shapeFileZoneNameColumn); SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); @@ -469,7 +469,7 @@ void testAddingExistingScenariosWithSample() throws Exception { Map, Link>> regionLinksMap = GenerateSmallScaleCommercialTrafficDemand .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem(), shapeFileZoneNameColumn), - buildingsPerZone); + buildingsPerZone, shapeFileZoneNameColumn); SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); @@ -541,7 +541,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { .createTrafficVolume_stop(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); Map, Link>> regionLinksMap = GenerateSmallScaleCommercialTrafficDemand - .filterLinksForZones(scenario, SCTUtils.getZoneIndex(inputDataDirectory), buildingsPerZone); + .filterLinksForZones(scenario, SCTUtils.getZoneIndex(inputDataDirectory), buildingsPerZone, shapeFileZoneNameColumn); SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); @@ -701,7 +701,7 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th .createTrafficVolume_stop(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); Map, Link>> regionLinksMap = GenerateSmallScaleCommercialTrafficDemand - .filterLinksForZones(scenario, SCTUtils.getZoneIndex(inputDataDirectory), buildingsPerZone); + .filterLinksForZones(scenario, SCTUtils.getZoneIndex(inputDataDirectory), buildingsPerZone, shapeFileZoneNameColumn); SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); From e465d1d725f12e5322bf81b96e88412a45be408d Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 28 Mar 2024 13:25:35 +0100 Subject: [PATCH 50/51] update README.md --- contribs/README.md | 1 + contribs/small-scale-traffic-generation/README.md | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/contribs/README.md b/contribs/README.md index f29f739c4ef..4507e513d46 100644 --- a/contribs/README.md +++ b/contribs/README.md @@ -46,6 +46,7 @@ The MATSim core development team cannot make any guarantee that these extensions | [shared_mobility](shared_mobility/README.md) | Simulate human-driven shared mobility (i.e., micromobility) | [signals](signals/README.md) | Simulate traffic lights microscopically | [simwrapper](simwrapper/README.md) | Creates dashboards automatically with [SimWrapper](https://simwrapper.github.io/) +| [small-scale-traffic-generation](small-scale-traffic-generation/README.md) | Tool to generate small-scale commercial traffic | [socnetsim](socnetsim/README.md) | Social network simulation | [sumo](sumo/README.md) | Converter and integrations for [SUMO](https://sumo.dlr.de/]) | [taxi](taxi/README.md) | Taxi service functionality diff --git a/contribs/small-scale-traffic-generation/README.md b/contribs/small-scale-traffic-generation/README.md index 23eda473092..4007ba0457b 100644 --- a/contribs/small-scale-traffic-generation/README.md +++ b/contribs/small-scale-traffic-generation/README.md @@ -21,18 +21,18 @@ The tool provides two different model types of small-scale commercial traffic. T - The generation model uses only open data. - zone shape file: - contains the zones for each region - - should contain columns: `areaID`, `region` + - the user can define the column of the name of the zone - 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: + - Regions + - shape contains the regions related to the regions in the structure data + - the user can define the column of the name of the region - Landuse - - should contain the following columns: `fclass` + - the user can define the column of landuse categories - Buildings - - should contain the following columns: `type`, `levels`, `area` -- Remarks: - - The zone shape file and the structure data should have the same regions. + - should contain the following columns: `levels`, `area` + - the user can define the column of the buildings categories ## Usage For generating the traffic, the following steps are necessary: From 9db3e93a1c0c6d50ae61407d5b3a557ca073744a Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 28 Mar 2024 13:25:56 +0100 Subject: [PATCH 51/51] add contrib to workflow --- .github/workflows/verify-push.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/verify-push.yaml b/.github/workflows/verify-push.yaml index a0d383b992d..865c39583fe 100644 --- a/.github/workflows/verify-push.yaml +++ b/.github/workflows/verify-push.yaml @@ -66,6 +66,7 @@ jobs: - contribs/simwrapper - contribs/sbb-extensions - contribs/simulatedannealing + - contribs/small-scale-traffic-generation - benchmark steps: