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: 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/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java index e7f7879587e..1d2579355ef 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java @@ -141,7 +141,7 @@ public Integer call() throws Exception { .sample(false) .separator(CsvOptions.detectDelimiter(input.getPath("trips.csv"))).build()); - // Trip filter with start and end + // Trip filter with start AND end if (shp.isDefined() && filter == LocationFilter.trip_start_and_end) { Geometry geometry = shp.getGeometry(); GeometryFactory f = new GeometryFactory(); @@ -156,6 +156,22 @@ public Integer call() throws Exception { } } + trips = trips.where(Selection.with(idx.toIntArray())); +// trip filter with start OR end + } else if (shp.isDefined() && filter == LocationFilter.trip_start_or_end) { + Geometry geometry = shp.getGeometry(); + GeometryFactory f = new GeometryFactory(); + IntList idx = new IntArrayList(); + + for (int i = 0; i < trips.rowCount(); i++) { + Row row = trips.row(i); + Point start = f.createPoint(new Coordinate(row.getDouble("start_x"), row.getDouble("start_y"))); + Point end = f.createPoint(new Coordinate(row.getDouble("end_x"), row.getDouble("end_y"))); + if (geometry.contains(start) || geometry.contains(end)) { + idx.add(i); + } + } + trips = trips.where(Selection.with(idx.toIntArray())); } @@ -416,6 +432,7 @@ private void writeTripPurposes(Table trips) { */ enum LocationFilter { trip_start_and_end, + trip_start_or_end, home, none } 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/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/InputOptions.java b/contribs/application/src/main/java/org/matsim/application/options/InputOptions.java index bd7f268a248..eae4b3a7c21 100644 --- a/contribs/application/src/main/java/org/matsim/application/options/InputOptions.java +++ b/contribs/application/src/main/java/org/matsim/application/options/InputOptions.java @@ -113,6 +113,10 @@ public Network getNetwork() { return NetworkUtils.readNetwork(networkPath); } + public String getNetworkPath() { + return networkPath; + } + public Population getPopulation() { if (!spec.requirePopulation()) throw new IllegalArgumentException("Population can not be accessed unless, requirePopulation=true."); diff --git a/contribs/application/src/main/java/org/matsim/application/options/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..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 @@ -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(); @@ -368,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; @@ -380,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/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 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..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,9 +96,9 @@ 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/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..deef01dfe5e --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java @@ -0,0 +1,183 @@ +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()); + + 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()); + + 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 -> 0; + }; + + 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/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/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/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/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/bicycle/src/test/java/org/matsim/contrib/bicycle/run/BicycleTest.java b/contribs/bicycle/src/test/java/org/matsim/contrib/bicycle/run/BicycleTest.java index 961e43f0182..222834c746b 100644 --- a/contribs/bicycle/src/test/java/org/matsim/contrib/bicycle/run/BicycleTest.java +++ b/contribs/bicycle/src/test/java/org/matsim/contrib/bicycle/run/BicycleTest.java @@ -65,7 +65,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.matsim.utils.eventsfilecomparison.EventsFileComparator.Result.FILES_ARE_EQUAL; +import static org.matsim.utils.eventsfilecomparison.ComparisonResult.FILES_ARE_EQUAL; /** * @author dziemke diff --git a/contribs/common/pom.xml b/contribs/common/pom.xml index 05952b173e1..106a9e01e46 100644 --- a/contribs/common/pom.xml +++ b/contribs/common/pom.xml @@ -18,5 +18,15 @@ org.assertj assertj-core + + one.util + streamex + 0.8.2 + + + com.uber + h3 + 4.1.1 + diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/Zone.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/Zone.java new file mode 100644 index 00000000000..dbf0c77caf8 --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/Zone.java @@ -0,0 +1,19 @@ +package org.matsim.contrib.common.zones; + +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.matsim.api.core.v01.BasicLocation; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Identifiable; +import org.matsim.api.core.v01.network.Link; + +import javax.annotation.Nullable; +import java.util.List; + +public interface Zone extends BasicLocation, Identifiable { + @Nullable + PreparedGeometry getPreparedGeometry(); + + Coord getCentroid(); + + List getLinks(); +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneImpl.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneImpl.java new file mode 100644 index 00000000000..64b4a009733 --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneImpl.java @@ -0,0 +1,65 @@ +package org.matsim.contrib.common.zones; + +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.geometry.geotools.MGC; + +import javax.annotation.Nullable; +import java.util.List; + +public class ZoneImpl implements Zone { + + private final Id id; + @Nullable + private final PreparedGeometry preparedGeometry; //null for virtual/dummy zones + private final List links; + private final Coord centroid; + + public ZoneImpl(Id id, PreparedGeometry preparedGeometry, List links) { + this(id, preparedGeometry, links, MGC.point2Coord(preparedGeometry.getGeometry().getCentroid())); + } + + private ZoneImpl(Id id, @Nullable PreparedGeometry preparedGeometry, List links, Coord centroid) { + this.id = id; + this.preparedGeometry = preparedGeometry; + this.links = links; + this.centroid = centroid; + } + + @Override + public Id getId() { + return id; + } + + @Override + public Coord getCoord() { + return centroid; + } + + @Override + @Nullable + public PreparedGeometry getPreparedGeometry() { + return preparedGeometry; + } + + @Override + public Coord getCentroid() { + return centroid; + } + + @Override + public List getLinks() { + return links; + } + + boolean isDummy() { + return preparedGeometry == null; + } + + public static ZoneImpl createDummyZone(Id id, List links, Coord centroid) { + return new ZoneImpl(id, null, links, centroid); + } + +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystem.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystem.java new file mode 100644 index 00000000000..11299b67ad6 --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystem.java @@ -0,0 +1,14 @@ +package org.matsim.contrib.common.zones; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; + +import javax.annotation.Nullable; +import java.util.Map; + +public interface ZoneSystem { + @Nullable + Zone getZoneForLinkId(Id linkId); + + Map, Zone> getZones(); +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemImpl.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemImpl.java new file mode 100644 index 00000000000..958575ecf40 --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemImpl.java @@ -0,0 +1,43 @@ +package org.matsim.contrib.common.zones; + +import org.apache.commons.lang3.tuple.Pair; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdMap; +import org.matsim.api.core.v01.network.Link; + +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +public class ZoneSystemImpl implements ZoneSystem { + + private final Map, Zone> zones = new IdMap<>(Zone.class); + private final IdMap link2zone = new IdMap<>(Link.class); + + public ZoneSystemImpl(Collection zones) { + zones.forEach(zone -> this.zones.put(zone.getId(), zone)); + zones.stream() + .flatMap(zone -> zone.getLinks().stream().map(link -> Pair.of(link.getId(), zone))) + .forEach(idZonePair -> link2zone.put(idZonePair.getKey(), idZonePair.getValue())); + } + + /** + * @param linkId + * @return the the {@code DrtZone} that contains the {@code linkId}. If the given link's {@code Coord} borders two or more cells, the allocation to a cell is random. + * Result may be null in case the given link is outside of the service area. + */ + @Override + @Nullable + public Zone getZoneForLinkId(Id linkId) { + return link2zone.get(linkId); + } + + /** + * @return the zones + */ + @Override + public Map, Zone> getZones() { + return Collections.unmodifiableMap(zones); + } +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemUtils.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemUtils.java new file mode 100644 index 00000000000..d1e3e6f2094 --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/ZoneSystemUtils.java @@ -0,0 +1,64 @@ +package org.matsim.contrib.common.zones; + +import one.util.streamex.EntryStream; +import one.util.streamex.StreamEx; +import org.locationtech.jts.geom.Point; +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.utils.geometry.geotools.MGC; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static java.util.stream.Collectors.toList; + +public final class ZoneSystemUtils { + + + private ZoneSystemUtils() {} + + public static ZoneSystem createFromPreparedGeometries(Network network, Map geometries) { + + //geometries without links are skipped + Map> linksByGeometryId = StreamEx.of(network.getLinks().values()) + .mapToEntry(l -> getGeometryIdForLink(l, geometries), l -> l) + .filterKeys(Objects::nonNull) + .grouping(toList()); + + //the zonal system contains only zones that have at least one link + List zones = EntryStream.of(linksByGeometryId) + .mapKeyValue((id, links) -> new ZoneImpl(Id.create(id, Zone.class), geometries.get(id), links)) + .collect(toList()); + + return new ZoneSystemImpl(zones); + } + + /** + * @param link + * @return the the {@code PreparedGeometry} that contains the {@code linkId}. + * If a given link's {@code Coord} borders two or more cells, the allocation to a cell is random. + * Result may be null in case the given link is outside of the service area. + */ + @Nullable + private static String getGeometryIdForLink(Link link, Map geometries) { + Point linkCoord = MGC.coord2Point(link.getToNode().getCoord()); + return geometries.entrySet() + .stream() + .filter(e -> e.getValue().intersects(linkCoord)) + .findAny() + .map(Map.Entry::getKey) + .orElse(null); + } + + public static Id createZoneId(String id) { + return Id.create(id, Zone.class); + } + + public static Id createZoneId(long id) { + return Id.create(id, Zone.class); + } +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3GridUtils.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3GridUtils.java new file mode 100644 index 00000000000..9139e56442b --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3GridUtils.java @@ -0,0 +1,112 @@ +package org.matsim.contrib.common.zones.h3; + +import com.uber.h3core.AreaUnit; +import com.uber.h3core.H3Core; +import com.uber.h3core.LengthUnit; +import com.uber.h3core.util.LatLng; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Polygon; +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.locationtech.jts.geom.prep.PreparedGeometryFactory; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.geometry.CoordinateTransformation; +import org.matsim.core.utils.geometry.transformations.TransformationFactory; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author nkuehnel / MOIA + */ +public class H3GridUtils { + + static final Logger log = LogManager.getLogger(H3GridUtils.class); + + public static Map createH3GridFromNetwork(Network network, int resolution, String crs) { + + H3Core h3 = H3Utils.getInstance(); + + log.info("start creating H3 grid from network at resolution " + resolution); + double hexagonEdgeLengthAvg = h3.getHexagonEdgeLengthAvg(resolution, LengthUnit.m); + log.info("Average edge length: " + hexagonEdgeLengthAvg + " meters."); + log.info("Average centroid distance: " + hexagonEdgeLengthAvg * Math.sqrt(3) + " meters."); + log.info("Average hexagon area: " + h3.getHexagonAreaAvg(resolution, AreaUnit.m2) + " m^2"); + + double[] boundingbox = NetworkUtils.getBoundingBox(network.getNodes().values()); + double minX = boundingbox[0]; + double maxX = boundingbox[2]; + double minY = boundingbox[1]; + double maxY = boundingbox[3]; + + GeometryFactory gf = new GeometryFactory(); + PreparedGeometryFactory preparedGeometryFactory = new PreparedGeometryFactory(); + Map grid = new HashMap<>(); + CoordinateTransformation toLatLong = TransformationFactory.getCoordinateTransformation(crs, TransformationFactory.WGS84); + CoordinateTransformation fromLatLong = TransformationFactory.getCoordinateTransformation(TransformationFactory.WGS84, crs); + + List boundingBoxPoints = new ArrayList<>(); + + Coord bottomLeft = toLatLong.transform(new Coord(minX, minY)); + Coord topLeft = toLatLong.transform(new Coord(minX, maxY)); + Coord topRight = toLatLong.transform(new Coord(maxX, maxY)); + Coord bottomRight = toLatLong.transform(new Coord(maxX, minY)); + + boundingBoxPoints.add(coordToLatLng(bottomLeft)); + boundingBoxPoints.add(coordToLatLng(topLeft)); + boundingBoxPoints.add(coordToLatLng(topRight)); + boundingBoxPoints.add(coordToLatLng(bottomRight)); + boundingBoxPoints.add(coordToLatLng(bottomLeft)); + + long millis = System.currentTimeMillis(); + + //get cells in a finer resolution to catch links at the border + List h3Grid = h3.polygonToCellAddresses(boundingBoxPoints, Collections.emptyList(), Math.min(H3Utils.MAX_RES, resolution)); + h3Grid = h3Grid + .parallelStream() + //also include neighbors with distance 1 + .flatMap(h3Id -> h3.gridDisk(h3Id, 1).stream()) + .distinct() + .toList(); + + if(h3Grid.isEmpty()) { + // bounding box too small to cover even a single H3 cell for a significant part. Use bounding box coords directly. + h3Grid = boundingBoxPoints.stream().map(corner -> h3.latLngToCellAddress(corner.lat, corner.lng, resolution)).distinct().toList(); + } + + log.info("Obtained " + h3Grid.size() + " H3 cells in " + (System.currentTimeMillis() - millis) + " ms."); + + + for (String h3Id : h3Grid) { + List coordinateList = h3.cellToBoundary(h3Id) + .stream() + .map(latLng -> CoordUtils.createGeotoolsCoordinate(fromLatLong.transform(latLngToCoord(latLng)))) + .collect(Collectors.toList()); + + if (!coordinateList.isEmpty()) { + coordinateList.add(coordinateList.get(0)); + } + + Polygon polygon = new Polygon(gf.createLinearRing(coordinateList.toArray(new Coordinate[0])), null, gf); + grid.put(h3Id, preparedGeometryFactory.create(polygon)); + } + + log.info("finished creating H3 grid from network."); + return grid; + } + + public static LatLng coordToLatLng(Coord coord) { + //invert coordinate order + return new LatLng(coord.getY(), coord.getX()); + } + + public static Coord latLngToCoord(LatLng latLng) { + //invert coordinate order + return new Coord(latLng.lng, latLng.lat); + } +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3Utils.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3Utils.java new file mode 100644 index 00000000000..3bc44478ebf --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3Utils.java @@ -0,0 +1,27 @@ +package org.matsim.contrib.common.zones.h3; + +import com.uber.h3core.H3Core; + +import java.io.IOException; + +/** + * @author nkuehnel / MOIA + */ +public final class H3Utils { + + private static H3Core h3; + + public final static int MAX_RES = 16; + + + public static H3Core getInstance() { + if(h3 == null) { + try { + h3 = H3Core.newInstance(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return h3; + } +} diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java new file mode 100644 index 00000000000..f496d62cc5d --- /dev/null +++ b/contribs/common/src/main/java/org/matsim/contrib/common/zones/h3/H3ZoneSystemUtils.java @@ -0,0 +1,77 @@ +package org.matsim.contrib.common.zones.h3; + +import com.uber.h3core.H3Core; +import com.uber.h3core.util.LatLng; +import one.util.streamex.EntryStream; +import one.util.streamex.StreamEx; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneImpl; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.ZoneSystemImpl; +import org.matsim.core.utils.geometry.CoordinateTransformation; +import org.matsim.core.utils.geometry.transformations.TransformationFactory; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static java.util.stream.Collectors.toList; + +/** + * @author nkuehnel / MOIA + */ +public class H3ZoneSystemUtils { + + static final Logger log = LogManager.getLogger(H3ZoneSystemUtils.class); + + + public static ZoneSystem createFromPreparedGeometries(Network network, Map geometries, + String crs, int resolution) { + + //geometries without links are skipped + CoordinateTransformation ct = TransformationFactory.getCoordinateTransformation(crs, TransformationFactory.WGS84); + Map> linksByGeometryId = StreamEx.of(network.getLinks().values()) + .mapToEntry(l -> getGeometryIdForLink(l, geometries, resolution, ct), l -> l) + .filterKeys(Objects::nonNull) + .grouping(toList()); + + log.info("Network filtered zone system contains " + linksByGeometryId.size() + " zones for " + + network.getLinks().size() + " links and " + network.getNodes().size() + " nodes."); + + //the zonal system contains only zones that have at least one link + List zones = EntryStream.of(linksByGeometryId) + .mapKeyValue((id, links) -> new ZoneImpl(Id.create(id, Zone.class), geometries.get(id), links) { + }) + .collect(toList()); + + return new ZoneSystemImpl(zones); + } + + /** + * @param ct + * @param link + * @return the the {@code PreparedGeometry} that contains the {@code linkId}. + * If a given link's {@code Coord} borders two or more cells, the allocation to a cell is random. + * Result may be null in case the given link is outside of the service area. + *

+ * Careful: does not work if grid contains different levels of h3 resolutions. + */ + @Nullable + private static String getGeometryIdForLink(Link link, Map geometries, int resolution, CoordinateTransformation ct) { + H3Core h3 = H3Utils.getInstance(); + LatLng latLng = H3GridUtils.coordToLatLng(ct.transform(link.getToNode().getCoord())); + String s = h3.latLngToCellAddress(latLng.lat, latLng.lng, resolution); + if (geometries.containsKey(s)) { + return s; + } else { + return null; + } + } +} diff --git a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/NullWaitingTimeEstimator.java b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/NullWaitingTimeEstimator.java index 445451713ca..e003a9f09e9 100644 --- a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/NullWaitingTimeEstimator.java +++ b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/NullWaitingTimeEstimator.java @@ -1,5 +1,8 @@ package org.matsim.contribs.discrete_mode_choice.components.utils; +import java.util.List; + +import org.matsim.api.core.v01.population.PlanElement; import org.matsim.pt.routes.TransitPassengerRoute; /** @@ -9,8 +12,15 @@ * @author sebhoerl */ public class NullWaitingTimeEstimator implements PTWaitingTimeEstimator { + @Override public double estimateWaitingTime(double agentDepartureTime, TransitPassengerRoute route) { return 0.0; } + + @Override + public double estimateWaitingTime(List elements) { + return 0.0; + } + } diff --git a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/PTWaitingTimeEstimator.java b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/PTWaitingTimeEstimator.java index 2b4da256f0b..25804cddb95 100644 --- a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/PTWaitingTimeEstimator.java +++ b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/PTWaitingTimeEstimator.java @@ -1,5 +1,8 @@ package org.matsim.contribs.discrete_mode_choice.components.utils; +import java.util.List; + +import org.matsim.api.core.v01.population.PlanElement; import org.matsim.pt.routes.TransitPassengerRoute; /** @@ -11,5 +14,9 @@ * @author sebhoerl */ public interface PTWaitingTimeEstimator { + double estimateWaitingTime(double departureTime, TransitPassengerRoute route); + + double estimateWaitingTime(List elements); + } diff --git a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/ScheduleWaitingTimeEstimator.java b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/ScheduleWaitingTimeEstimator.java index 2ab5bfe10ca..6fc60d7ad73 100644 --- a/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/ScheduleWaitingTimeEstimator.java +++ b/contribs/discrete_mode_choice/src/main/java/org/matsim/contribs/discrete_mode_choice/components/utils/ScheduleWaitingTimeEstimator.java @@ -8,6 +8,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.PlanElement; import org.matsim.core.utils.collections.Tuple; @@ -54,17 +55,14 @@ private Tuple, Id> createId(TransitLine transitLin return new Tuple<>(transitLine.getId(), transitRoute.getId()); } + @Override public double estimateWaitingTime(List elements) { double totalWaitingTime = 0.0; for (PlanElement element : elements) { - if (element instanceof Leg) { - Leg leg = (Leg) element; - - if (leg.getMode().equals("pt")) { - TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); - totalWaitingTime += estimateWaitingTime(leg.getDepartureTime().seconds(), route); - } + if (element instanceof Leg leg && leg.getMode().equals(TransportMode.pt)) { + TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); + totalWaitingTime += this.estimateWaitingTime(leg.getDepartureTime().seconds(), route); } } diff --git a/contribs/drt-extensions/pom.xml b/contribs/drt-extensions/pom.xml index 3e2cbf8dcf7..d3ccd511acd 100644 --- a/contribs/drt-extensions/pom.xml +++ b/contribs/drt-extensions/pom.xml @@ -48,7 +48,7 @@ 16.0-SNAPSHOT test - + org.mockito mockito-core diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java index 71ee5abe1c1..b617a93a0d3 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java @@ -44,6 +44,7 @@ import org.matsim.contrib.drt.optimizer.insertion.UnplannedRequestInserter; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; +import org.matsim.contrib.drt.passenger.DefaultOfferAcceptor; import org.matsim.contrib.drt.prebooking.PrebookingActionCreator; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.schedule.DrtTaskFactory; @@ -178,7 +179,8 @@ public EmptyVehicleRelocator get() { getter.getModal(StopTimeCalculator.class), scheduleWaitBeforeDrive))) .asEagerSingleton(); - bindModal(DrtOfferAcceptor.class).toInstance(DrtOfferAcceptor.DEFAULT_ACCEPTOR); + bindModal(DefaultOfferAcceptor.class).toProvider(modalProvider(getter -> new DefaultOfferAcceptor(drtCfg.maxAllowedPickupDelay))); + bindModal(DrtOfferAcceptor.class).to(modalKey(DefaultOfferAcceptor.class)); bindModal(ScheduleTimingUpdater.class).toProvider(modalProvider( getter -> new ScheduleTimingUpdater(getter.get(MobsimTimer.class), @@ -187,11 +189,11 @@ public EmptyVehicleRelocator get() { bindModal(VrpLegFactory.class).toProvider(modalProvider(getter -> { DvrpConfigGroup dvrpCfg = getter.get(DvrpConfigGroup.class); MobsimTimer timer = getter.get(MobsimTimer.class); - + // Makes basic DrtActionCreator create legs with consumption tracker return v -> EDrtActionCreator.createLeg(dvrpCfg.mobsimMode, v, timer); })).in(Singleton.class); - + bindModal(EDrtActionCreator.class).toProvider(modalProvider(getter -> { VrpAgentLogic.DynActionCreator delegate = drtCfg.getPrebookingParams().isPresent() ? getter.getModal(PrebookingActionCreator.class) @@ -201,9 +203,9 @@ public EmptyVehicleRelocator get() { // + adds ChargingActivity return new EDrtActionCreator(delegate, getter.get(MobsimTimer.class)); })).asEagerSingleton(); - + bindModal(VrpAgentLogic.DynActionCreator.class).to(modalKey(EDrtActionCreator.class)); - + bindModal(VrpOptimizer.class).to(modalKey(DrtOptimizer.class)); } } diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java new file mode 100644 index 00000000000..86595942ed2 --- /dev/null +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java @@ -0,0 +1,88 @@ +package org.matsim.contrib.drt.extension.h3; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.application.MATSimApplication; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; +import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystemParams; +import org.matsim.contrib.drt.analysis.zonal.DrtZonalWaitTimesAnalyzer; +import org.matsim.contrib.drt.extension.DrtTestScenario; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.testcases.MatsimTestUtils; + +import java.io.File; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author nkuehnel / MOIA + */ +public class RunDrtWithH3ZonalSystemIT { + + @RegisterExtension + private MatsimTestUtils utils = new MatsimTestUtils(); + + private Controler controler; + + @BeforeEach + public void setUp() throws Exception { + + Config config = DrtTestScenario.loadConfig(utils); + config.controller().setLastIteration(0); + + controler = MATSimApplication.prepare(new DrtTestScenario(controller -> prepare(controller, config), RunDrtWithH3ZonalSystemIT::prepare), config); + } + + private static void prepare(Controler controler, Config config) { + + MultiModeDrtConfigGroup drtConfigs = ConfigUtils.addOrGetModule(config, MultiModeDrtConfigGroup.class); + for (DrtConfigGroup drtConfig : drtConfigs.getModalElements()) { + drtConfig.getZonalSystemParams().get().h3Resolution = 9; + drtConfig.getZonalSystemParams().get().zonesGeneration = DrtZonalSystemParams.ZoneGeneration.H3; + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new AbstractDvrpModeModule(drtConfig.mode) { + @Override + public void install() { + bindModal(DrtZonalWaitTimesAnalyzer.class).toProvider(modalProvider( + getter -> new DrtZonalWaitTimesAnalyzer(drtConfig, getter.getModal(DrtEventSequenceCollector.class), + getter.getModal(ZoneSystem.class)))).asEagerSingleton(); + addControlerListenerBinding().to(modalKey(DrtZonalWaitTimesAnalyzer.class)); + } + }); + } + }); + + } + } + + private static void prepare(Config config) { + MultiModeDrtConfigGroup drtConfigs = ConfigUtils.addOrGetModule(config, MultiModeDrtConfigGroup.class); + for (DrtConfigGroup drtConfig : drtConfigs.getModalElements()) { + DrtZonalSystemParams params = drtConfig.getZonalSystemParams().orElseThrow(); + params.cellSize = 1.; + params.zonesGeneration = DrtZonalSystemParams.ZoneGeneration.GridFromNetwork; + } + } + + @Test + void run() { + String out = utils.getOutputDirectory(); + controler.run(); + + assertThat(new File(out, "kelheim-mini-drt.drt_waitStats_drt_zonal.gpkg")) + .exists() + .isNotEmpty(); + + } +} + diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/drtZone/H3DrtZonalSystemTest.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/drtZone/H3DrtZonalSystemTest.java new file mode 100644 index 00000000000..293fa254280 --- /dev/null +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/drtZone/H3DrtZonalSystemTest.java @@ -0,0 +1,173 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) 2020 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** * + */ + +package org.matsim.contrib.drt.extension.h3.drtZone; + +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.h3.H3GridUtils; +import org.matsim.contrib.common.zones.h3.H3ZoneSystemUtils; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.utils.geometry.transformations.TransformationFactory; +import org.matsim.examples.ExamplesUtils; + +import java.net.URL; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.matsim.contrib.common.zones.ZoneSystemUtils.createZoneId; + +/** + * @author nkuehnel / MOIA + */ +public class H3DrtZonalSystemTest { + + @Test + void test_Holzkirchen_Resolution3() { + Network network = getNetwork(); + String crs = TransformationFactory.DHDN_GK4; + int resolution = 3; + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("831f8dfffffffff"))).isTrue(); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("831f8dfffffffff")); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo(createZoneId("831f8dfffffffff")); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("831f89fffffffff")); + + //check all links are mapped + for (Link link : network.getLinks().values()) { + assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId())); + } + } + + @Test + void test_Holzkirchen_Resolution5() { + Network network = getNetwork(); + String crs = TransformationFactory.DHDN_GK4; + int resolution = 5; + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("851f88b7fffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("851f8d6bfffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("851f88a7fffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("851f89d3fffffff"))).isTrue(); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("851f8d6bfffffff")); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo(createZoneId("851f88b7fffffff")); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("851f89d3fffffff")); + + //check all links are mapped + for (Link link : network.getLinks().values()) { + assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId())); + } + } + + @Test + void test_Holzkirchen_Resolution6() { + Network network = getNetwork(); + String crs = TransformationFactory.DHDN_GK4; + int resolution = 6; + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f8d697ffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f8d687ffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f8d69fffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f88a6fffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f88a6fffffff"))).isTrue(); + assertThat(drtZonalSystem.getZones().containsKey(createZoneId("861f89d37ffffff"))).isTrue(); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("861f8d697ffffff")); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo(createZoneId("861f88b47ffffff")); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("861f89d07ffffff")); + + //check all links are mapped + for (Link link : network.getLinks().values()) { + assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId())); + } + } + + @Test + void test_Holzkirchen_Resolution10() { + Network network = getNetwork(); + String crs = TransformationFactory.DHDN_GK4; + int resolution = 10; + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("8a1f8d6930b7fff")); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo(createZoneId("8a1f88b4025ffff")); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("8a1f89d06d5ffff")); + + //check all links are mapped + for (Link link : network.getLinks().values()) { + assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId())); + } + } + + @Test + void test_Holzkirchen_Resolution12() { + Network network = getNetwork(); + String crs = TransformationFactory.DHDN_GK4; + int resolution = 12; + ZoneSystem drtZonalSystem = H3ZoneSystemUtils.createFromPreparedGeometries(network, + H3GridUtils.createH3GridFromNetwork(network, resolution, crs), crs, resolution); + + // center of Holzkirchen + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).getId()).isEqualTo(createZoneId("8c1f8d6930b63ff")); + // Thanning (Western border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).getId()).isEqualTo(createZoneId("8c1f88b4025d1ff")); + // between Gross- and Kleinpienzenau (Southeastern border of network) + assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).getId()).isEqualTo(createZoneId("8c1f89d06d581ff")); + + //check all links are mapped + for (Link link : network.getLinks().values()) { + assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId())); + } + } + + + static Network getNetwork() { + Network network = NetworkUtils.createNetwork(); + URL holzkirchen = ConfigGroup.getInputFileURL(ExamplesUtils.getTestScenarioURL("holzkirchen"), "holzkirchenNetwork.xml.gz"); + new MatsimNetworkReader(network).parse(holzkirchen); + return network; + } +} diff --git a/contribs/drt/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 b33136cec26..75101e4bc6c 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtGridUtils.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtGridUtils.java @@ -22,10 +22,7 @@ */ package org.matsim.contrib.drt.analysis.zonal; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import one.util.streamex.EntryStream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.locationtech.jts.geom.Coordinate; @@ -37,7 +34,9 @@ import org.matsim.core.network.NetworkUtils; import org.matsim.core.utils.misc.Counter; -import one.util.streamex.EntryStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * @author jbischoff @@ -74,21 +73,17 @@ public static Map createGridFromNetwork(Network networ } /** - * First creates a grid based on the network bounding box. Then removes all zones that do not intersect the service area. + * Takes an existing grid and removes all zones that do not intersect the service area. * Result may contain zones that are barely included in the service area. But as passengers may walk into the service area, * it seems appropriate that the DrtZonalSystem, which is used for demand estimation, is larger than the service area. * The {@code cellsize} indirectly determines, how much larger the DrtZonalSystem may get. * - * @param network - * @param cellsize + * @param grid a pre-computed grid of zones * @param serviceAreaGeoms geometries that define the service area * @return */ - public static Map createGridFromNetworkWithinServiceArea(Network network, double cellsize, - List serviceAreaGeoms) { - Map grid = createGridFromNetwork(network, cellsize); - log.info("total number of created grid zones = " + grid.size()); - + public static Map filterGridWithinServiceArea(Map grid, List serviceAreaGeoms) { + log.info("total number of initial grid zones = " + grid.size()); log.info("searching for grid zones within the drt service area..."); Counter counter = new Counter("dealt with zone "); Map zonesWithinServiceArea = EntryStream.of(grid) diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtModeZonalSystemModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtModeZonalSystemModule.java index 8d81ba21749..bd3e6b7ddc6 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtModeZonalSystemModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtModeZonalSystemModule.java @@ -20,24 +20,26 @@ package org.matsim.contrib.drt.analysis.zonal; -import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtils.createGridFromNetwork; -import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtils.createGridFromNetworkWithinServiceArea; -import static org.matsim.contrib.drt.run.DrtConfigGroup.OperationalScheme; -import static org.matsim.utils.gis.shp2matsim.ShpGeometryUtils.loadPreparedGeometries; - -import java.util.List; - +import com.google.common.base.Preconditions; +import one.util.streamex.EntryStream; import org.locationtech.jts.geom.prep.PreparedGeometry; import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.ZoneSystemUtils; +import org.matsim.contrib.common.zones.h3.H3GridUtils; +import org.matsim.contrib.common.zones.h3.H3ZoneSystemUtils; import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; import org.matsim.core.config.ConfigGroup; import org.matsim.core.controler.MatsimServices; -import com.google.common.base.Preconditions; +import java.util.List; +import java.util.Map; -import one.util.streamex.EntryStream; +import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtils.createGridFromNetwork; +import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtils.filterGridWithinServiceArea; +import static org.matsim.utils.gis.shp2matsim.ShpGeometryUtils.loadPreparedGeometries; /** * @author Michal Maciejewski (michalm) @@ -53,53 +55,73 @@ public DrtModeZonalSystemModule(DrtConfigGroup drtCfg) { @Override public void install() { - DrtZonalSystemParams params = drtCfg.getZonalSystemParams().orElseThrow(); - - bindModal(DrtZonalSystem.class).toProvider(modalProvider(getter -> { - Network network = getter.getModal(Network.class); - switch (params.zonesGeneration) { - case ShapeFile: - final List preparedGeometries = loadPreparedGeometries( + if (drtCfg.getZonalSystemParams().isPresent()) { + DrtZonalSystemParams params = drtCfg.getZonalSystemParams().get(); + + bindModal(ZoneSystem.class).toProvider(modalProvider(getter -> { + Network network = getter.getModal(Network.class); + switch (params.zonesGeneration) { + case ShapeFile: { + final List preparedGeometries = loadPreparedGeometries( ConfigGroup.getInputFileURL(getConfig().getContext(), params.zonesShapeFile)); - return DrtZonalSystem.createFromPreparedGeometries(network, + return ZoneSystemUtils.createFromPreparedGeometries(network, EntryStream.of(preparedGeometries).mapKeys(i -> (i + 1) + "").toMap()); - - case GridFromNetwork: - Preconditions.checkNotNull(params.cellSize); - var gridZones = drtCfg.operationalScheme == OperationalScheme.serviceAreaBased ? - createGridFromNetworkWithinServiceArea(network, params.cellSize, + } + + case GridFromNetwork: { + Preconditions.checkNotNull(params.cellSize); + Map gridFromNetwork = createGridFromNetwork(network, params.cellSize); + var gridZones = + switch (drtCfg.operationalScheme) { + case stopbased, door2door -> gridFromNetwork; + case serviceAreaBased -> filterGridWithinServiceArea(gridFromNetwork, loadPreparedGeometries(ConfigGroup.getInputFileURL(getConfig().getContext(), - drtCfg.drtServiceAreaShapeFile))) : - createGridFromNetwork(network, params.cellSize); - return DrtZonalSystem.createFromPreparedGeometries(network, gridZones); - - default: - throw new RuntimeException("Unsupported zone generation"); - } - })).asEagerSingleton(); - - bindModal(DrtZoneTargetLinkSelector.class).toProvider(modalProvider(getter -> { - switch (params.targetLinkSelection) { - case mostCentral: - return new MostCentralDrtZoneTargetLinkSelector(getter.getModal(DrtZonalSystem.class)); - case random: - return new RandomDrtZoneTargetLinkSelector(); - default: - throw new RuntimeException( + drtCfg.drtServiceAreaShapeFile))); + }; + return ZoneSystemUtils.createFromPreparedGeometries(network, gridZones); + } + + case H3: + Preconditions.checkNotNull(params.h3Resolution); + String crs = getConfig().global().getCoordinateSystem(); + Map gridFromNetwork = H3GridUtils.createH3GridFromNetwork(network, params.h3Resolution, crs); + var gridZones = + switch (drtCfg.operationalScheme) { + case stopbased, door2door -> gridFromNetwork; + case serviceAreaBased -> filterGridWithinServiceArea(gridFromNetwork, + loadPreparedGeometries(ConfigGroup.getInputFileURL(getConfig().getContext(), + drtCfg.drtServiceAreaShapeFile))); + }; + return H3ZoneSystemUtils.createFromPreparedGeometries(network, gridZones, crs, params.h3Resolution); + + default: + throw new RuntimeException("Unsupported zone generation"); + } + })).asEagerSingleton(); + + bindModal(DrtZoneTargetLinkSelector.class).toProvider(modalProvider(getter -> { + switch (params.targetLinkSelection) { + case mostCentral: + return new MostCentralDrtZoneTargetLinkSelector(getter.getModal(ZoneSystem.class)); + case random: + return new RandomDrtZoneTargetLinkSelector(); + default: + throw new RuntimeException( "Unsupported target link selection = " + params.targetLinkSelection); - } - })).asEagerSingleton(); + } + })).asEagerSingleton(); - //zonal analysis - bindModal(ZonalIdleVehicleXYVisualiser.class).toProvider(modalProvider( + //zonal analysis + bindModal(ZonalIdleVehicleXYVisualiser.class).toProvider(modalProvider( getter -> new ZonalIdleVehicleXYVisualiser(getter.get(MatsimServices.class), drtCfg.getMode(), - getter.getModal(DrtZonalSystem.class)))).asEagerSingleton(); - addControlerListenerBinding().to(modalKey(ZonalIdleVehicleXYVisualiser.class)); - addEventHandlerBinding().to(modalKey(ZonalIdleVehicleXYVisualiser.class)); + getter.getModal(ZoneSystem.class)))).asEagerSingleton(); + addControlerListenerBinding().to(modalKey(ZonalIdleVehicleXYVisualiser.class)); + addEventHandlerBinding().to(modalKey(ZonalIdleVehicleXYVisualiser.class)); - bindModal(DrtZonalWaitTimesAnalyzer.class).toProvider(modalProvider( + bindModal(DrtZonalWaitTimesAnalyzer.class).toProvider(modalProvider( getter -> new DrtZonalWaitTimesAnalyzer(drtCfg, getter.getModal(DrtEventSequenceCollector.class), - getter.getModal(DrtZonalSystem.class)))).asEagerSingleton(); - addControlerListenerBinding().to(modalKey(DrtZonalWaitTimesAnalyzer.class)); + getter.getModal(ZoneSystem.class)))).asEagerSingleton(); + addControlerListenerBinding().to(modalKey(DrtZonalWaitTimesAnalyzer.class)); + } } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystem.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystem.java deleted file mode 100644 index 33647f30d80..00000000000 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystem.java +++ /dev/null @@ -1,111 +0,0 @@ -/* *********************************************************************** * - * project: org.matsim.* - * * - * *********************************************************************** * - * * - * copyright : (C) 2017 by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** */ - -package org.matsim.contrib.drt.analysis.zonal; - -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toMap; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; - -import javax.annotation.Nullable; - -import org.apache.commons.lang3.tuple.Pair; -import org.locationtech.jts.geom.Point; -import org.locationtech.jts.geom.prep.PreparedGeometry; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.network.Link; -import org.matsim.api.core.v01.network.Network; -import org.matsim.core.utils.geometry.geotools.MGC; - -import one.util.streamex.EntryStream; -import one.util.streamex.StreamEx; - -/** - * @author jbischoff - * @author Michal Maciejewski (michalm) - * @author Tilmann Schlenther (tschlenther) - */ -public class DrtZonalSystem { - - public static DrtZonalSystem createFromPreparedGeometries(Network network, - Map geometries) { - - //geometries without links are skipped - Map> linksByGeometryId = StreamEx.of(network.getLinks().values()) - .mapToEntry(l -> getGeometryIdForLink(l, geometries), l -> l) - .filterKeys(Objects::nonNull) - .grouping(toList()); - - //the zonal system contains only zones that have at least one link - List zones = EntryStream.of(linksByGeometryId) - .mapKeyValue((id, links) -> new DrtZone(id, geometries.get(id), links)) - .collect(toList()); - - return new DrtZonalSystem(zones); - } - - /** - * @param link - * @return the the {@code PreparedGeometry} that contains the {@code linkId}. - * If a given link's {@code Coord} borders two or more cells, the allocation to a cell is random. - * Result may be null in case the given link is outside of the service area. - */ - @Nullable - private static String getGeometryIdForLink(Link link, Map geometries) { - Point linkCoord = MGC.coord2Point(link.getToNode().getCoord()); - return geometries.entrySet() - .stream() - .filter(e -> e.getValue().intersects(linkCoord)) - .findAny() - .map(Entry::getKey) - .orElse(null); - } - - private final Map zones; - private final Map, DrtZone> link2zone; - - public DrtZonalSystem(Collection zones) { - this.zones = zones.stream().collect(toMap(DrtZone::getId, z -> z)); - this.link2zone = zones.stream() - .flatMap(zone -> zone.getLinks().stream().map(link -> Pair.of(link.getId(), zone))) - .collect(toMap(Pair::getKey, Pair::getValue)); - } - - /** - * @param linkId - * @return the the {@code DrtZone} that contains the {@code linkId}. If the given link's {@code Coord} borders two or more cells, the allocation to a cell is random. - * Result may be null in case the given link is outside of the service area. - */ - @Nullable - public DrtZone getZoneForLinkId(Id linkId) { - return link2zone.get(linkId); - } - - /** - * @return the zones - */ - public Map getZones() { - return zones; - } -} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemParams.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemParams.java index 01230c1e115..4dd0860b578 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemParams.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemParams.java @@ -22,6 +22,7 @@ import javax.annotation.Nullable; +import org.matsim.contrib.common.zones.h3.H3Utils; import org.matsim.core.config.Config; import org.matsim.core.config.ReflectiveConfigGroup; @@ -40,10 +41,10 @@ public DrtZonalSystemParams() { super(SET_NAME); } - public enum ZoneGeneration {GridFromNetwork, ShapeFile} + public enum ZoneGeneration {GridFromNetwork, ShapeFile, H3} @Parameter - @Comment("Logic for generation of zones for the DRT zonal system. Value can be: [GridFromNetwork, ShapeFile].") + @Comment("Logic for generation of zones for the DRT zonal system. Value can be: [GridFromNetwork, ShapeFile, H3].") @NotNull public ZoneGeneration zonesGeneration = null; @@ -59,6 +60,14 @@ public enum ZoneGeneration {GridFromNetwork, ShapeFile} @Nullable public String zonesShapeFile = null; + @Parameter + @Comment("allows to configure H3 hexagonal zones. Used with zonesGeneration=H3. " + + "Range from 0 (122 cells worldwide) to 15 (569 E^12 cells). " + + "Usually meaningful between resolution 6 (3.7 km avg edge length) " + + "and 10 (70 m avg edge length). ") + @Nullable + public Integer h3Resolution = null; + public enum TargetLinkSelection {random, mostCentral} @Parameter("zoneTargetLinkSelection") @@ -75,5 +84,9 @@ protected void checkConsistency(Config config) { "cellSize must not be null when zonesGeneration is " + ZoneGeneration.GridFromNetwork); Preconditions.checkArgument(zonesGeneration != ZoneGeneration.ShapeFile || zonesShapeFile != null, "zonesShapeFile must not be null when zonesGeneration is " + ZoneGeneration.ShapeFile); + Preconditions.checkArgument(zonesGeneration != ZoneGeneration.H3 || h3Resolution != null, + "H3 resolution must not be null when zonesGeneration is " + ZoneGeneration.H3); + Preconditions.checkArgument(h3Resolution == null || h3Resolution >= 0 && h3Resolution <= H3Utils.MAX_RES, + "H3 resolution must not be null when zonesGeneration is " + ZoneGeneration.H3); } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalWaitTimesAnalyzer.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalWaitTimesAnalyzer.java index 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/DrtModeOptimizerQSimModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/DrtModeOptimizerQSimModule.java index 8534468ce81..92336f544c4 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/DrtModeOptimizerQSimModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/DrtModeOptimizerQSimModule.java @@ -37,6 +37,7 @@ import org.matsim.contrib.drt.optimizer.insertion.selective.SelectiveInsertionSearchQSimModule; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; +import org.matsim.contrib.drt.passenger.DefaultOfferAcceptor; import org.matsim.contrib.drt.prebooking.PrebookingActionCreator; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.schedule.DrtStayTaskEndTimeCalculator; @@ -138,7 +139,7 @@ public EmptyVehicleRelocator get() { }).asEagerSingleton(); bindModal(DrtScheduleInquiry.class).to(DrtScheduleInquiry.class).asEagerSingleton(); - + boolean scheduleWaitBeforeDrive = drtCfg.getPrebookingParams().map(p -> p.scheduleWaitBeforeDrive).orElse(false); bindModal(RequestInsertionScheduler.class).toProvider(modalProvider( getter -> new DefaultRequestInsertionScheduler(getter.getModal(Fleet.class), @@ -147,7 +148,8 @@ public EmptyVehicleRelocator get() { getter.getModal(StopTimeCalculator.class), scheduleWaitBeforeDrive))) .asEagerSingleton(); - bindModal(DrtOfferAcceptor.class).toInstance(DrtOfferAcceptor.DEFAULT_ACCEPTOR); + bindModal(DefaultOfferAcceptor.class).toProvider(modalProvider(getter -> new DefaultOfferAcceptor(drtCfg.maxAllowedPickupDelay))); + bindModal(DrtOfferAcceptor.class).to(modalKey(DefaultOfferAcceptor.class)); bindModal(ScheduleTimingUpdater.class).toProvider(modalProvider( getter -> new ScheduleTimingUpdater(getter.get(MobsimTimer.class), @@ -160,7 +162,7 @@ public EmptyVehicleRelocator get() { return v -> VrpLegFactory.createWithOnlineTracker(dvrpCfg.mobsimMode, v, OnlineTrackerListener.NO_LISTENER, timer); })).in(Singleton.class); - + if (drtCfg.getPrebookingParams().isEmpty()) { bindModal(VrpAgentLogic.DynActionCreator.class).to(modalKey(DrtActionCreator.class)); } else { diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/DrtModeFeedforwardRebalanceModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/DrtModeFeedforwardRebalanceModule.java index 5980ec233ad..db9f1f45bce 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/DrtModeFeedforwardRebalanceModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/DrtModeFeedforwardRebalanceModule.java @@ -22,7 +22,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.analysis.zonal.DrtZoneTargetLinkSelector; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; @@ -56,7 +56,7 @@ public void install() { @Override protected void configureQSim() { bindModal(RebalancingStrategy.class).toProvider(modalProvider( - getter -> new FeedforwardRebalancingStrategy(getter.getModal(DrtZonalSystem.class), + getter -> new FeedforwardRebalancingStrategy(getter.getModal(ZoneSystem.class), getter.getModal(Fleet.class), generalParams, strategySpecificParams, getter.getModal(FeedforwardSignalHandler.class), getter.getModal(DrtZoneTargetLinkSelector.class), @@ -67,11 +67,11 @@ protected void configureQSim() { // Create PreviousIterationDepartureRecoder (this will be created only once) bindModal(FeedforwardSignalHandler.class).toProvider(modalProvider( - getter -> new FeedforwardSignalHandler(getter.getModal(DrtZonalSystem.class), strategySpecificParams, + getter -> new FeedforwardSignalHandler(getter.getModal(ZoneSystem.class), strategySpecificParams, getter.getModal(NetDepartureReplenishDemandEstimator.class)))).asEagerSingleton(); bindModal(NetDepartureReplenishDemandEstimator.class).toProvider(modalProvider( - getter -> new NetDepartureReplenishDemandEstimator(getter.getModal(DrtZonalSystem.class), drtCfg, + getter -> new NetDepartureReplenishDemandEstimator(getter.getModal(ZoneSystem.class), drtCfg, strategySpecificParams))).asEagerSingleton(); bindModal(FastHeuristicZonalRelocationCalculator.class).toProvider(modalProvider( diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FastHeuristicZonalRelocationCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FastHeuristicZonalRelocationCalculator.java index bb7a1e5b0e6..b3af6a40713 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FastHeuristicZonalRelocationCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FastHeuristicZonalRelocationCalculator.java @@ -1,11 +1,7 @@ package org.matsim.contrib.drt.optimizer.rebalancing.Feedforward; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; import org.matsim.contrib.drt.analysis.zonal.DrtZoneTargetLinkSelector; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy.Relocation; import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus; @@ -14,6 +10,10 @@ import org.matsim.contrib.drt.optimizer.rebalancing.plusOne.LinkBasedRelocationCalculator; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + public class FastHeuristicZonalRelocationCalculator implements ZonalRelocationCalculator { private final DrtZoneTargetLinkSelector drtZoneTargetLinkSelector; @@ -25,13 +25,13 @@ public FastHeuristicZonalRelocationCalculator(DrtZoneTargetLinkSelector drtZoneT @Override public List calcRelocations(List vehicleSurplus, - Map> rebalancableVehiclesPerZone) { + Map> rebalancableVehiclesPerZone) { List targetLinks = new ArrayList<>(); List selectedRebalancableVehicles = new ArrayList<>(); for (DrtZoneVehicleSurplus drtZoneVehicleSurplus : vehicleSurplus) { int surplus = drtZoneVehicleSurplus.surplus; - DrtZone zone = drtZoneVehicleSurplus.zone; + Zone zone = drtZoneVehicleSurplus.zone; if (surplus > 0) { List rebalancableVehiclesInZone = rebalancableVehiclesPerZone.get(zone); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardRebalancingStrategy.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardRebalancingStrategy.java index fa2e4d84547..3d61a38ee3a 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardRebalancingStrategy.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardRebalancingStrategy.java @@ -1,30 +1,25 @@ package org.matsim.contrib.drt.optimizer.rebalancing.Feedforward; -import static java.util.stream.Collectors.toSet; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.analysis.zonal.DrtZoneTargetLinkSelector; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingUtils; -import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus; +import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.AggregatedMinCostRelocationCalculator; import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.TransportProblem.Flow; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.Fleet; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toSet; + /** * This strategy is created based on the Feedforward Fluidic rebalancing * algorithm in AMoDeus. The algorithm send rebalancing vehicles based on the @@ -41,7 +36,7 @@ public class FeedforwardRebalancingStrategy implements RebalancingStrategy { private static final Logger log = LogManager.getLogger(FeedforwardRebalancingStrategy.class); - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final Fleet fleet; private final RebalancingParams generalParams; @@ -56,9 +51,9 @@ public class FeedforwardRebalancingStrategy implements RebalancingStrategy { private final DrtZoneTargetLinkSelector drtZoneTargetLinkSelector; private final FastHeuristicZonalRelocationCalculator fastHeuristicRelocationCalculator; - private final Map>> feedforwardSignal; + private final Map>> feedforwardSignal; - public FeedforwardRebalancingStrategy(DrtZonalSystem zonalSystem, Fleet fleet, RebalancingParams generalParams, + public FeedforwardRebalancingStrategy(ZoneSystem zonalSystem, Fleet fleet, RebalancingParams generalParams, FeedforwardRebalancingStrategyParams strategySpecificParams, FeedforwardSignalHandler feedforwardSignalHandler, DrtZoneTargetLinkSelector drtZoneTargetLinkSelector, FastHeuristicZonalRelocationCalculator fastHeuristicRelocationCalculator) { @@ -90,22 +85,22 @@ public FeedforwardRebalancingStrategy(DrtZonalSystem zonalSystem, Fleet fleet, R public List calcRelocations(Stream rebalancableVehicles, double time) { List relocationList = new ArrayList<>(); int timeBin = (int)Math.floor((time + feedforwardSignalLead) / timeBinSize); - Map> rebalancableVehiclesPerZone = RebalancingUtils + Map> rebalancableVehiclesPerZone = RebalancingUtils .groupRebalancableVehicles(zonalSystem, generalParams, rebalancableVehicles, time); - Map> actualRebalancableVehiclesPerZone = new HashMap<>(); + Map> actualRebalancableVehiclesPerZone = new HashMap<>(); // Feedback part if (feedbackSwitch) { - List vehicleSurplusList = new ArrayList<>(); - Map> soonRebalancableVehiclesPerZone = RebalancingUtils + List vehicleSurplusList = new ArrayList<>(); + Map> soonRebalancableVehiclesPerZone = RebalancingUtils .groupSoonIdleVehicles(zonalSystem, generalParams, fleet, time); - for (DrtZone zone : zonalSystem.getZones().values()) { + for (Zone zone : zonalSystem.getZones().values()) { int rebalancable = rebalancableVehiclesPerZone.getOrDefault(zone, List.of()).size(); int soonIdle = soonRebalancableVehiclesPerZone.getOrDefault(zone, List.of()).size(); int surplus = rebalancable + soonIdle - minNumVehiclesPerZone; - vehicleSurplusList.add(new DrtZoneVehicleSurplus(zone, Math.min(surplus, rebalancable))); + vehicleSurplusList.add(new AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus(zone, Math.min(surplus, rebalancable))); } relocationList.addAll( @@ -113,7 +108,7 @@ public List calcRelocations(Stream rebalancab // Connection between feedback and feedforward part Set relocatedVehicles = relocationList.stream().map(relocation -> relocation.vehicle) .collect(toSet()); - for (DrtZone zone : rebalancableVehiclesPerZone.keySet()) { + for (Zone zone : rebalancableVehiclesPerZone.keySet()) { actualRebalancableVehiclesPerZone.put(zone, rebalancableVehiclesPerZone.get(zone).stream() .filter(v -> !relocatedVehicles.contains(v)).collect(Collectors.toList())); } @@ -125,9 +120,9 @@ public List calcRelocations(Stream rebalancab // assign rebalance vehicles based on the rebalance plan if (feedforwardSignal.containsKey(timeBin)) { // Generate relocations based on the "rebalancePlanCore" - for (Flow rebalanceInfo : feedforwardSignal.get(timeBin)) { - DrtZone departureZone = rebalanceInfo.origin(); - DrtZone arrivalZone = rebalanceInfo.destination(); + for (Flow rebalanceInfo : feedforwardSignal.get(timeBin)) { + Zone departureZone = rebalanceInfo.origin(); + Zone arrivalZone = rebalanceInfo.destination(); int vehicleToSend = (int) Math.floor(scaling * rebalanceInfo.amount() + rnd.nextDouble()); // Note: we use probability to solve the problem of non-integer value of // vehileToSend after scaling. diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardSignalHandler.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardSignalHandler.java index d670f9be2ec..a8557441636 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardSignalHandler.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/Feedforward/FeedforwardSignalHandler.java @@ -1,16 +1,9 @@ package org.matsim.contrib.drt.optimizer.rebalancing.Feedforward; -import static java.util.stream.Collectors.toList; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.ToDoubleFunction; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.NetDepartureReplenishDemandEstimator; import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus; import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.TransportProblem; @@ -18,10 +11,17 @@ import org.matsim.core.controler.events.IterationStartsEvent; import org.matsim.core.controler.listener.IterationStartsListener; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.ToDoubleFunction; + +import static java.util.stream.Collectors.toList; + public class FeedforwardSignalHandler implements IterationStartsListener { private static final Logger log = LogManager.getLogger(FeedforwardSignalHandler.class); - private final DrtZonalSystem zonalSystem; - private final Map>> feedforwardSignal = new HashMap<>(); + private final ZoneSystem zonalSystem; + private final Map>> feedforwardSignal = new HashMap<>(); private final int timeBinSize; private final NetDepartureReplenishDemandEstimator netDepartureReplenishDemandEstimator; @@ -30,7 +30,7 @@ public class FeedforwardSignalHandler implements IterationStartsListener { /** * Constructor */ - public FeedforwardSignalHandler(DrtZonalSystem zonalSystem, + public FeedforwardSignalHandler(ZoneSystem zonalSystem, FeedforwardRebalancingStrategyParams strategySpecificParams, NetDepartureReplenishDemandEstimator netDepartureReplenishDemandEstimator) { this.zonalSystem = zonalSystem; @@ -45,7 +45,7 @@ private void calculateFeedforwardSignal() { int numOfTimeBin = simulationEndTime * 3600 / timeBinSize; log.info("Start calculating rebalnace plan now"); for (int t = 0; t < numOfTimeBin; t++) { - ToDoubleFunction netDepartureInputFunction = netDepartureReplenishDemandEstimator.getExpectedDemandForTimeBin(t); + ToDoubleFunction netDepartureInputFunction = netDepartureReplenishDemandEstimator.getExpectedDemandForTimeBin(t); List vehicleSurpluses = zonalSystem.getZones() .values() .stream() @@ -59,7 +59,7 @@ private void calculateFeedforwardSignal() { log.info("Rebalance plan calculation is now complete! "); } - public Map>> getFeedforwardSignal() { + public Map>> getFeedforwardSignal() { return feedforwardSignal; } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingModule.java index b9c008bc3a1..ef148776efd 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingModule.java @@ -46,7 +46,6 @@ public RebalancingModule(DrtConfigGroup drtCfg) { public void install() { if (drtCfg.getRebalancingParams().isPresent()) { RebalancingParams rebalancingParams = drtCfg.getRebalancingParams().get(); - install(new DrtModeZonalSystemModule(drtCfg)); if (rebalancingParams.getRebalancingStrategyParams() instanceof MinCostFlowRebalancingStrategyParams) { install(new DrtModeMinCostFlowRebalancingModule(drtCfg)); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingUtils.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingUtils.java index da0a741d5e0..8584026e706 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingUtils.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/RebalancingUtils.java @@ -26,9 +26,11 @@ import java.util.Map; import java.util.stream.Stream; +import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneImpl; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.Fleet; import org.matsim.contrib.dvrp.schedule.Schedule; @@ -40,14 +42,14 @@ * @author Michal Maciejewski (michalm) */ public class RebalancingUtils { - public static Map> groupRebalancableVehicles(DrtZonalSystem zonalSystem, - RebalancingParams params, Stream rebalancableVehicles, double time) { - Map> rebalancableVehiclesPerZone = new HashMap<>(); + public static Map> groupRebalancableVehicles(ZoneSystem zonalSystem, + RebalancingParams params, Stream rebalancableVehicles, double time) { + Map> rebalancableVehiclesPerZone = new HashMap<>(); rebalancableVehicles.filter(v -> v.getServiceEndTime() > time + params.minServiceTime).forEach(v -> { Link link = ((StayTask)v.getSchedule().getCurrentTask()).getLink(); - DrtZone zone = zonalSystem.getZoneForLinkId(link.getId()); + Zone zone = zonalSystem.getZoneForLinkId(link.getId()); if (zone == null) { - zone = DrtZone.createDummyZone("single-vehicle-zone-" + v.getId(), List.of(link), + zone = ZoneImpl.createDummyZone(Id.create("single-vehicle-zone-" + v.getId(), Zone.class), List.of(link), link.getToNode().getCoord()); } rebalancableVehiclesPerZone.computeIfAbsent(zone, z -> new ArrayList<>()).add(v); @@ -56,16 +58,16 @@ public static Map> groupRebalancableVehicles(DrtZonal } // also include vehicles being right now relocated or recharged - public static Map> groupSoonIdleVehicles(DrtZonalSystem zonalSystem, + public static Map> groupSoonIdleVehicles(ZoneSystem zonalSystem, RebalancingParams params, Fleet fleet, double time) { - Map> soonIdleVehiclesPerZone = new HashMap<>(); + Map> soonIdleVehiclesPerZone = new HashMap<>(); for (DvrpVehicle v : fleet.getVehicles().values()) { Schedule s = v.getSchedule(); StayTask stayTask = (StayTask)Schedules.getLastTask(s); if (stayTask.getStatus() == Task.TaskStatus.PLANNED && stayTask.getBeginTime() < time + params.maxTimeBeforeIdle && v.getServiceEndTime() > time + params.minServiceTime) { - DrtZone zone = zonalSystem.getZoneForLinkId(stayTask.getLink().getId()); + Zone zone = zonalSystem.getZoneForLinkId(stayTask.getLink().getId()); if (zone != null) { soonIdleVehiclesPerZone.computeIfAbsent(zone, z -> new ArrayList<>()).add(v); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/NetDepartureReplenishDemandEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/NetDepartureReplenishDemandEstimator.java index 2529a02b8d3..cc1c0b41dd5 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/NetDepartureReplenishDemandEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/NetDepartureReplenishDemandEstimator.java @@ -1,13 +1,8 @@ package org.matsim.contrib.drt.optimizer.rebalancing.demandestimator; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.function.ToDoubleFunction; - import org.matsim.api.core.v01.Id; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.optimizer.rebalancing.Feedforward.FeedforwardRebalancingStrategyParams; import org.matsim.contrib.drt.passenger.events.DrtRequestSubmittedEvent; import org.matsim.contrib.drt.passenger.events.DrtRequestSubmittedEventHandler; @@ -18,20 +13,25 @@ import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEvent; import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEventHandler; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.ToDoubleFunction; + public class NetDepartureReplenishDemandEstimator implements PassengerRequestScheduledEventHandler, DrtRequestSubmittedEventHandler, PassengerRequestRejectedEventHandler { - private record Trip(int timeBin, DrtZone fromZone, DrtZone toZone) { + private record Trip(int timeBin, Zone fromZone, Zone toZone) { } - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final String mode; private final int timeBinSize; - private final Map> currentZoneNetDepartureMap = new HashMap<>(); - private final Map> previousZoneNetDepartureMap = new HashMap<>(); + private final Map> currentZoneNetDepartureMap = new HashMap<>(); + private final Map> previousZoneNetDepartureMap = new HashMap<>(); private final Map, Trip> potentialDrtTripsMap = new HashMap<>(); - public NetDepartureReplenishDemandEstimator(DrtZonalSystem zonalSystem, DrtConfigGroup drtCfg, + public NetDepartureReplenishDemandEstimator(ZoneSystem zonalSystem, DrtConfigGroup drtCfg, FeedforwardRebalancingStrategyParams strategySpecificParams) { this.zonalSystem = zonalSystem; mode = drtCfg.getMode(); @@ -52,8 +52,8 @@ public void handleEvent(DrtRequestSubmittedEvent event) { if (event.getMode().equals(mode)) { // At the submission time, this is only a potential trip. int timeBin = (int)Math.floor(event.getTime() / timeBinSize); - DrtZone departureZoneId = zonalSystem.getZoneForLinkId(event.getFromLinkId()); - DrtZone arrivalZoneId = zonalSystem.getZoneForLinkId(event.getToLinkId()); + Zone departureZoneId = zonalSystem.getZoneForLinkId(event.getFromLinkId()); + Zone arrivalZoneId = zonalSystem.getZoneForLinkId(event.getToLinkId()); potentialDrtTripsMap.put(event.getRequestId(), new Trip(timeBin, departureZoneId, arrivalZoneId)); } } @@ -78,7 +78,7 @@ public void updateForNextIteration() { potentialDrtTripsMap.clear(); } - public ToDoubleFunction getExpectedDemandForTimeBin(int timeBin) { + public ToDoubleFunction getExpectedDemandForTimeBin(int timeBin) { var expectedDemandForTimeBin = previousZoneNetDepartureMap.getOrDefault(timeBin, Collections.emptyMap()); return zone -> expectedDemandForTimeBin.getOrDefault(zone, 0); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimator.java index 003c1649507..f6d2f17745d 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimator.java @@ -23,20 +23,19 @@ */ package org.matsim.contrib.drt.optimizer.rebalancing.demandestimator; -import java.util.HashMap; -import java.util.Map; -import java.util.function.ToDoubleFunction; - +import com.google.common.base.Preconditions; import org.apache.commons.lang3.mutable.MutableInt; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.events.PersonDepartureEvent; import org.matsim.api.core.v01.events.handler.PersonDepartureEventHandler; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.run.DrtConfigGroup; -import com.google.common.base.Preconditions; +import java.util.HashMap; +import java.util.Map; +import java.util.function.ToDoubleFunction; /** * Aggregates PersonDepartureEvents per iteration for the given mode and returns the numbers from the previous iteration @@ -48,13 +47,13 @@ public final class PreviousIterationDrtDemandEstimator implements ZonalDemandEstimator, PersonDepartureEventHandler { private static final Logger logger = LogManager.getLogger(PreviousIterationDrtDemandEstimator.class); - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final String mode; private final int timeBinSize; - private Map> currentIterationDepartures = new HashMap<>(); - private Map> previousIterationDepartures = new HashMap<>(); + private Map> currentIterationDepartures = new HashMap<>(); + private Map> previousIterationDepartures = new HashMap<>(); - public PreviousIterationDrtDemandEstimator(DrtZonalSystem zonalSystem, DrtConfigGroup drtCfg, + public PreviousIterationDrtDemandEstimator(ZoneSystem zonalSystem, DrtConfigGroup drtCfg, int demandEstimationPeriod) { this.zonalSystem = zonalSystem; mode = drtCfg.getMode(); @@ -70,7 +69,7 @@ public void reset(int iteration) { @Override public void handleEvent(PersonDepartureEvent event) { if (event.getLegMode().equals(mode)) { - DrtZone zone = zonalSystem.getZoneForLinkId(event.getLinkId()); + Zone zone = zonalSystem.getZoneForLinkId(event.getLinkId()); if (zone == null) { //might be that somebody walks into the service area or that service area is larger/different than DrtZonalSystem... logger.warn("No zone found for linkId " + event.getLinkId().toString()); @@ -87,10 +86,10 @@ public void handleEvent(PersonDepartureEvent event) { private static final MutableInt ZERO = new MutableInt(0); @Override - public ToDoubleFunction getExpectedDemand(double fromTime, double estimationPeriod) { + public ToDoubleFunction getExpectedDemand(double fromTime, double estimationPeriod) { Preconditions.checkArgument(estimationPeriod == timeBinSize);//TODO add more flexibility later int timeBin = getBinForTime(fromTime); - Map expectedDemandForTimeBin = previousIterationDepartures.getOrDefault(timeBin, Map.of()); + Map expectedDemandForTimeBin = previousIterationDepartures.getOrDefault(timeBin, Map.of()); return zone -> expectedDemandForTimeBin.getOrDefault(zone, ZERO).intValue(); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/ZonalDemandEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/ZonalDemandEstimator.java index 42d75e30f6e..9faee8637bd 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/ZonalDemandEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/ZonalDemandEstimator.java @@ -23,14 +23,14 @@ */ package org.matsim.contrib.drt.optimizer.rebalancing.demandestimator; -import java.util.function.ToDoubleFunction; +import org.matsim.contrib.common.zones.Zone; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import java.util.function.ToDoubleFunction; /** * @author jbischoff * @author Michal Maciejewski (michalm) */ public interface ZonalDemandEstimator { - ToDoubleFunction getExpectedDemand(double fromTime, double estimationPeriod); + ToDoubleFunction getExpectedDemand(double fromTime, double estimationPeriod); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/AggregatedMinCostRelocationCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/AggregatedMinCostRelocationCalculator.java index 4a16cb05b5d..14130e4d152 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/AggregatedMinCostRelocationCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/AggregatedMinCostRelocationCalculator.java @@ -25,7 +25,7 @@ import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; import org.matsim.contrib.drt.analysis.zonal.DrtZoneTargetLinkSelector; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy.Relocation; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; @@ -39,10 +39,10 @@ */ public class AggregatedMinCostRelocationCalculator implements ZonalRelocationCalculator { public static class DrtZoneVehicleSurplus { - public final DrtZone zone; + public final Zone zone; public final int surplus; - public DrtZoneVehicleSurplus(DrtZone zone, int surplus) { + public DrtZoneVehicleSurplus(Zone zone, int surplus) { this.zone = zone; this.surplus = surplus; } @@ -56,14 +56,14 @@ public AggregatedMinCostRelocationCalculator(DrtZoneTargetLinkSelector targetLin @Override public List calcRelocations(List vehicleSurplus, - Map> rebalancableVehiclesPerZone) { + Map> rebalancableVehiclesPerZone) { return calcRelocations(rebalancableVehiclesPerZone, TransportProblem.solveForVehicleSurplus(vehicleSurplus)); } - private List calcRelocations(Map> rebalancableVehiclesPerZone, - List> flows) { + private List calcRelocations(Map> rebalancableVehiclesPerZone, + List> flows) { List relocations = new ArrayList<>(); - for (TransportProblem.Flow flow : flows) { + for (TransportProblem.Flow flow : flows) { List rebalancableVehicles = rebalancableVehiclesPerZone.get(flow.origin()); Link targetLink = targetLinkSelector.selectTargetLink(flow.destination()); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/DrtModeMinCostFlowRebalancingModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/DrtModeMinCostFlowRebalancingModule.java index d624e6a000a..eeef009b3da 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/DrtModeMinCostFlowRebalancingModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/DrtModeMinCostFlowRebalancingModule.java @@ -21,17 +21,13 @@ package org.matsim.contrib.drt.optimizer.rebalancing.mincostflow; import org.matsim.api.core.v01.population.Population; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.analysis.zonal.DrtZoneTargetLinkSelector; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.PreviousIterationDrtDemandEstimator; import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.ZonalDemandEstimator; -import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.DemandEstimatorAsTargetCalculator; -import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.EqualRebalancableVehicleDistributionTargetCalculator; -import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.EqualVehicleDensityTargetCalculator; -import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.EqualVehiclesToPopulationRatioTargetCalculator; -import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.RebalancingTargetCalculator; +import org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator.*; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.dvrp.fleet.Fleet; import org.matsim.contrib.dvrp.fleet.FleetSpecification; @@ -59,7 +55,7 @@ public void install() { protected void configureQSim() { bindModal(RebalancingStrategy.class).toProvider(modalProvider( getter -> new MinCostFlowRebalancingStrategy(getter.getModal(RebalancingTargetCalculator.class), - getter.getModal(DrtZonalSystem.class), getter.getModal(Fleet.class), + getter.getModal(ZoneSystem.class), getter.getModal(Fleet.class), getter.getModal(ZonalRelocationCalculator.class), params))).asEagerSingleton(); switch (strategyParams.rebalancingTargetCalculatorType) { @@ -71,19 +67,19 @@ protected void configureQSim() { case EqualRebalancableVehicleDistribution: bindModal(RebalancingTargetCalculator.class).toProvider(modalProvider(getter -> new EqualRebalancableVehicleDistributionTargetCalculator( getter.getModal(ZonalDemandEstimator.class), - getter.getModal(DrtZonalSystem.class), strategyParams.demandEstimationPeriod))).asEagerSingleton(); + getter.getModal(ZoneSystem.class), strategyParams.demandEstimationPeriod))).asEagerSingleton(); break; case EqualVehicleDensity: bindModal(RebalancingTargetCalculator.class).toProvider(modalProvider( - getter -> new EqualVehicleDensityTargetCalculator(getter.getModal(DrtZonalSystem.class), + getter -> new EqualVehicleDensityTargetCalculator(getter.getModal(ZoneSystem.class), getter.getModal(FleetSpecification.class)))).asEagerSingleton(); break; case EqualVehiclesToPopulationRatio: bindModal(RebalancingTargetCalculator.class).toProvider(modalProvider( getter -> new EqualVehiclesToPopulationRatioTargetCalculator( - getter.getModal(DrtZonalSystem.class), getter.get(Population.class), + getter.getModal(ZoneSystem.class), getter.get(Population.class), getter.getModal(FleetSpecification.class)))).asEagerSingleton(); break; @@ -101,7 +97,7 @@ protected void configureQSim() { switch (strategyParams.zonalDemandEstimatorType) { case PreviousIterationDemand: bindModal(PreviousIterationDrtDemandEstimator.class).toProvider(modalProvider( - getter -> new PreviousIterationDrtDemandEstimator(getter.getModal(DrtZonalSystem.class), drtCfg, + getter -> new PreviousIterationDrtDemandEstimator(getter.getModal(ZoneSystem.class), drtCfg, strategyParams.demandEstimationPeriod))).asEagerSingleton(); bindModal(ZonalDemandEstimator.class).to(modalKey(PreviousIterationDrtDemandEstimator.class)); addEventHandlerBinding().to(modalKey(PreviousIterationDrtDemandEstimator.class)); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategy.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategy.java index b08dcb56e01..4e06666ed05 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategy.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategy.java @@ -25,8 +25,8 @@ import java.util.function.ToDoubleFunction; import java.util.stream.Stream; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingUtils; @@ -41,13 +41,13 @@ public class MinCostFlowRebalancingStrategy implements RebalancingStrategy { private final RebalancingTargetCalculator rebalancingTargetCalculator; - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final Fleet fleet; private final ZonalRelocationCalculator relocationCalculator; private final RebalancingParams params; public MinCostFlowRebalancingStrategy(RebalancingTargetCalculator rebalancingTargetCalculator, - DrtZonalSystem zonalSystem, Fleet fleet, ZonalRelocationCalculator relocationCalculator, + ZoneSystem zonalSystem, Fleet fleet, ZonalRelocationCalculator relocationCalculator, RebalancingParams params) { this.rebalancingTargetCalculator = rebalancingTargetCalculator; this.zonalSystem = zonalSystem; @@ -58,20 +58,20 @@ public MinCostFlowRebalancingStrategy(RebalancingTargetCalculator rebalancingTar @Override public List calcRelocations(Stream rebalancableVehicles, double time) { - Map> rebalancableVehiclesPerZone = RebalancingUtils.groupRebalancableVehicles( + Map> rebalancableVehiclesPerZone = RebalancingUtils.groupRebalancableVehicles( zonalSystem, params, rebalancableVehicles, time); if (rebalancableVehiclesPerZone.isEmpty()) { return List.of(); } - Map> soonIdleVehiclesPerZone = RebalancingUtils.groupSoonIdleVehicles(zonalSystem, + Map> soonIdleVehiclesPerZone = RebalancingUtils.groupSoonIdleVehicles(zonalSystem, params, fleet, time); return calculateMinCostRelocations(time, rebalancableVehiclesPerZone, soonIdleVehiclesPerZone); } private List calculateMinCostRelocations(double time, - Map> rebalancableVehiclesPerZone, - Map> soonIdleVehiclesPerZone) { - ToDoubleFunction targetFunction = rebalancingTargetCalculator.calculate(time, + Map> rebalancableVehiclesPerZone, + Map> soonIdleVehiclesPerZone) { + ToDoubleFunction targetFunction = rebalancingTargetCalculator.calculate(time, rebalancableVehiclesPerZone); var minCostFlowRebalancingStrategyParams = (MinCostFlowRebalancingStrategyParams)params.getRebalancingStrategyParams(); double alpha = minCostFlowRebalancingStrategyParams.targetAlpha; diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/TransportProblem.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/TransportProblem.java index b48f0f2e635..ca019b03ea2 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/TransportProblem.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/TransportProblem.java @@ -26,19 +26,19 @@ import org.apache.commons.lang3.tuple.Pair; import org.matsim.contrib.common.util.DistanceUtils; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; import graphs.flows.MinCostFlow; import graphs.flows.MinCostFlow.Edge; +import org.matsim.contrib.common.zones.Zone; /** * @author michalm */ public class TransportProblem { - public static List> solveForVehicleSurplus( + public static List> solveForVehicleSurplus( List vehicleSurplus) { - List> supply = new ArrayList<>(); - List> demand = new ArrayList<>(); + List> supply = new ArrayList<>(); + List> demand = new ArrayList<>(); for (AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus s : vehicleSurplus) { if (s.surplus > 0) { supply.add(Pair.of(s.zone, s.surplus)); @@ -46,10 +46,10 @@ public static List> solveForVehicleSurplus( demand.add(Pair.of(s.zone, -s.surplus)); } } - return new TransportProblem(TransportProblem::calcStraightLineDistance).solve(supply, demand); + return new TransportProblem(TransportProblem::calcStraightLineDistance).solve(supply, demand); } - private static int calcStraightLineDistance(DrtZone zone1, DrtZone zone2) { + private static int calcStraightLineDistance(Zone zone1, Zone zone2) { return (int)DistanceUtils.calculateDistance(zone1.getCentroid(), zone2.getCentroid()); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/ZonalRelocationCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/ZonalRelocationCalculator.java index 8ccfd234b23..a01e6afbfae 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/ZonalRelocationCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/ZonalRelocationCalculator.java @@ -18,14 +18,14 @@ package org.matsim.contrib.drt.optimizer.rebalancing.mincostflow; -import java.util.List; -import java.util.Map; - -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy.Relocation; import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.AggregatedMinCostRelocationCalculator.DrtZoneVehicleSurplus; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; +import java.util.List; +import java.util.Map; + /** * @author michalm */ @@ -36,5 +36,5 @@ public interface ZonalRelocationCalculator { * @return vehicle relocations */ List calcRelocations(List vehicleSurplus, - Map> rebalancableVehiclesPerZone); + Map> rebalancableVehiclesPerZone); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/DemandEstimatorAsTargetCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/DemandEstimatorAsTargetCalculator.java index 611299b55bf..1ce22dd43e7 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/DemandEstimatorAsTargetCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/DemandEstimatorAsTargetCalculator.java @@ -20,14 +20,14 @@ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.ZonalDemandEstimator; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; + import java.util.List; import java.util.Map; import java.util.function.ToDoubleFunction; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; -import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.ZonalDemandEstimator; -import org.matsim.contrib.dvrp.fleet.DvrpVehicle; - /** * @author michalm */ @@ -41,8 +41,8 @@ public DemandEstimatorAsTargetCalculator(ZonalDemandEstimator demandEstimator, d } @Override - public ToDoubleFunction calculate(double time, - Map> rebalancableVehiclesPerZone) { + public ToDoubleFunction calculate(double time, + Map> rebalancableVehiclesPerZone) { return demandEstimator.getExpectedDemand(time, demandEstimationPeriod); } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualRebalancableVehicleDistributionTargetCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualRebalancableVehicleDistributionTargetCalculator.java index c3975986dce..e03314a8d07 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualRebalancableVehicleDistributionTargetCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualRebalancableVehicleDistributionTargetCalculator.java @@ -20,19 +20,19 @@ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; -import static java.util.stream.Collectors.toSet; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.ZonalDemandEstimator; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.ToDoubleFunction; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; -import org.matsim.contrib.drt.optimizer.rebalancing.demandestimator.ZonalDemandEstimator; -import org.matsim.contrib.dvrp.fleet.DvrpVehicle; +import static java.util.stream.Collectors.toSet; /** * TODO add some description @@ -43,24 +43,24 @@ public class EqualRebalancableVehicleDistributionTargetCalculator implements Reb private static final Logger log = LogManager.getLogger(EqualRebalancableVehicleDistributionTargetCalculator.class); private final ZonalDemandEstimator demandEstimator; - private final DrtZonalSystem zonalSystem; + private final ZoneSystem zonalSystem; private final double demandEstimationPeriod; public EqualRebalancableVehicleDistributionTargetCalculator(ZonalDemandEstimator demandEstimator, - DrtZonalSystem zonalSystem, double demandEstimationPeriod) { + ZoneSystem zonalSystem, double demandEstimationPeriod) { this.demandEstimator = demandEstimator; this.zonalSystem = zonalSystem; this.demandEstimationPeriod = demandEstimationPeriod; } @Override - public ToDoubleFunction calculate(double time, - Map> rebalancableVehiclesPerZone) { + public ToDoubleFunction calculate(double time, + Map> rebalancableVehiclesPerZone) { int numAvailableVehicles = rebalancableVehiclesPerZone.values().stream().mapToInt(List::size).sum(); - ToDoubleFunction currentDemandEstimator = demandEstimator.getExpectedDemand(time, + ToDoubleFunction currentDemandEstimator = demandEstimator.getExpectedDemand(time, demandEstimationPeriod); - Set activeZones = zonalSystem.getZones() + Set activeZones = zonalSystem.getZones() .values() .stream() .filter(zone -> currentDemandEstimator.applyAsDouble(zone) > 0) diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculator.java index 03b6b8879f4..64a0e6bd0bc 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculator.java @@ -23,19 +23,18 @@ */ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.ToDoubleFunction; - +import com.google.common.base.Preconditions; import jakarta.validation.constraints.NotNull; - -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdMap; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.FleetSpecification; -import com.google.common.base.Preconditions; +import java.util.List; +import java.util.Map; +import java.util.function.ToDoubleFunction; /** * This class does not really calculate the expected demand but aims to @@ -46,32 +45,32 @@ */ public final class EqualVehicleDensityTargetCalculator implements RebalancingTargetCalculator { - private final Map zoneAreaShares = new HashMap<>(); + private final Map, Double> zoneAreaShares = new IdMap<>(Zone.class); private final FleetSpecification fleetSpecification; - public EqualVehicleDensityTargetCalculator(@NotNull DrtZonalSystem zonalSystem, + public EqualVehicleDensityTargetCalculator(@NotNull ZoneSystem zonalSystem, @NotNull FleetSpecification fleetSpecification) { initAreaShareMap(zonalSystem); this.fleetSpecification = fleetSpecification; } @Override - public ToDoubleFunction calculate(double time, - Map> rebalancableVehiclesPerZone) { - return zone -> zoneAreaShares.getOrDefault(zone, 0.) * fleetSpecification.getVehicleSpecifications().size(); + public ToDoubleFunction calculate(double time, + Map> rebalancableVehiclesPerZone) { + return zone -> zoneAreaShares.getOrDefault(zone.getId(), 0.) * fleetSpecification.getVehicleSpecifications().size(); } - private void initAreaShareMap(DrtZonalSystem zonalSystem) { + private void initAreaShareMap(ZoneSystem zonalSystem) { double areaSum = zonalSystem.getZones() .values() .stream() .mapToDouble(z -> z.getPreparedGeometry().getGeometry().getArea()) .sum(); - for (DrtZone zone : zonalSystem.getZones().values()) { + for (Zone zone : zonalSystem.getZones().values()) { double areaShare = zone.getPreparedGeometry().getGeometry().getArea() / areaSum; Preconditions.checkState(areaShare >= 0. && areaShare <= 1.); - zoneAreaShares.put(zone, areaShare); + zoneAreaShares.put(zone.getId(), areaShare); } } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculator.java index 51c23a64db5..7968af6e705 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculator.java @@ -23,26 +23,25 @@ */ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; -import static java.util.stream.Collectors.collectingAndThen; -import static java.util.stream.Collectors.counting; - -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.ToDoubleFunction; -import java.util.stream.Collectors; - import jakarta.validation.constraints.NotNull; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Population; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.FleetSpecification; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.ToDoubleFunction; +import java.util.stream.Collectors; + +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.counting; + /** * Calculates population size per zone by counting first activites per zone in the selected plans. * Returns the share of population of the total population inside the drt service area for the given zone multiplied with the overall fleet size. @@ -55,11 +54,11 @@ public final class EqualVehiclesToPopulationRatioTargetCalculator implements Reb private static final Logger log = LogManager.getLogger(EqualVehiclesToPopulationRatioTargetCalculator.class); private final int fleetSize; - private final Map activitiesPerZone; + private final Map activitiesPerZone; private final int totalNrActivities; - public EqualVehiclesToPopulationRatioTargetCalculator(DrtZonalSystem zonalSystem, Population population, - @NotNull FleetSpecification fleetSpecification) { + public EqualVehiclesToPopulationRatioTargetCalculator(ZoneSystem zonalSystem, Population population, + @NotNull FleetSpecification fleetSpecification) { log.debug("nr of zones: " + zonalSystem.getZones().size() + "\t nr of persons = " + population.getPersons() .size()); fleetSize = fleetSpecification.getVehicleSpecifications().size(); @@ -68,7 +67,7 @@ public EqualVehiclesToPopulationRatioTargetCalculator(DrtZonalSystem zonalSystem log.debug("nr of persons that have their first activity inside the service area = " + this.totalNrActivities); } - private Map countFirstActsPerZone(DrtZonalSystem zonalSystem, Population population) { + private Map countFirstActsPerZone(ZoneSystem zonalSystem, Population population) { return population.getPersons() .values() .stream() @@ -79,8 +78,8 @@ private Map countFirstActsPerZone(DrtZonalSystem zonalSystem, } @Override - public ToDoubleFunction calculate(double time, - Map> rebalancableVehiclesPerZone) { + public ToDoubleFunction calculate(double time, + Map> rebalancableVehiclesPerZone) { if (totalNrActivities == 0) { return zoneId -> 0; } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/RebalancingTargetCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/RebalancingTargetCalculator.java index e7b2e36d1c4..c89ac8677e6 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/RebalancingTargetCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/RebalancingTargetCalculator.java @@ -20,16 +20,16 @@ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; + import java.util.List; import java.util.Map; import java.util.function.ToDoubleFunction; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; -import org.matsim.contrib.dvrp.fleet.DvrpVehicle; - /** * @author Michal Maciejewski (michalm) */ public interface RebalancingTargetCalculator { - ToDoubleFunction calculate(double time, Map> rebalancableVehiclesPerZone); + ToDoubleFunction calculate(double time, Map> rebalancableVehiclesPerZone); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/MaxDetourOfferAcceptor.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DefaultOfferAcceptor.java similarity index 62% rename from contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/MaxDetourOfferAcceptor.java rename to contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DefaultOfferAcceptor.java index fe2dfb25834..9eeed624139 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/MaxDetourOfferAcceptor.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DefaultOfferAcceptor.java @@ -2,13 +2,24 @@ import java.util.Optional; -public class MaxDetourOfferAcceptor implements DrtOfferAcceptor{ +public class DefaultOfferAcceptor implements DrtOfferAcceptor{ private final double maxAllowedPickupDelay; - public MaxDetourOfferAcceptor(double maxAllowedPickupDelay) { + /** + * Generate Default offer acceptor with max allowed pickup delay. + * @param maxAllowedPickupDelay: maximum allowed delay since the initially assigned pickup time. + */ + public DefaultOfferAcceptor(double maxAllowedPickupDelay) { this.maxAllowedPickupDelay = maxAllowedPickupDelay; } + /** + * Generate Default offer acceptor. + */ + public DefaultOfferAcceptor() { + this.maxAllowedPickupDelay = Double.POSITIVE_INFINITY; + } + @Override public Optional acceptDrtOffer(DrtRequest request, double departureTime, double arrivalTime) { double updatedLatestStartTime = Math.min(departureTime diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DrtOfferAcceptor.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DrtOfferAcceptor.java index 4118169fe70..68ab4751459 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DrtOfferAcceptor.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/passenger/DrtOfferAcceptor.java @@ -26,9 +26,6 @@ * @author Michal Maciejewski (michalm) */ public interface DrtOfferAcceptor { - DrtOfferAcceptor DEFAULT_ACCEPTOR = (request, departureTime, arrivalTime) -> Optional.of( - AcceptedDrtRequest.createFromOriginalRequest(request)); - /** * @param request drt request * @param departureTime offered departure time for the new request diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingActionCreator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingActionCreator.java index aa29bc7253f..90276503de8 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingActionCreator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingActionCreator.java @@ -2,6 +2,9 @@ import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.getBaseTypeOrElseThrow; +import java.util.List; + +import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; import org.matsim.contrib.drt.prebooking.abandon.AbandonVoter; import org.matsim.contrib.drt.schedule.DrtStopTask; import org.matsim.contrib.drt.schedule.DrtTaskBaseType; @@ -47,11 +50,42 @@ public DynAction createAction(DynAgent dynAgent, DvrpVehicle vehicle, double now if (getBaseTypeOrElseThrow(task).equals(DrtTaskBaseType.STOP)) { DrtStopTask stopTask = (DrtStopTask) task; + int incomingCapacity = getIncomingOccupancy(vehicle, stopTask); + return new PrebookingStopActivity(passengerHandler, dynAgent, stopTask, stopTask.getDropoffRequests(), stopTask.getPickupRequests(), DrtActionCreator.DRT_STOP_NAME, () -> stopTask.getEndTime(), - stopDurationProvider, vehicle, prebookingManager, abandonVoter); + stopDurationProvider, vehicle, prebookingManager, abandonVoter, incomingCapacity); } return delegate.createAction(dynAgent, vehicle, now); } + + private int getIncomingOccupancy(DvrpVehicle vehicle, DrtStopTask referenceTask) { + int incomingOccupancy = 0; + + List tasks = vehicle.getSchedule().getTasks(); + + int index = tasks.size() - 1; + while (index >= 0) { + Task task = tasks.get(index); + + if (task instanceof DrtStopTask) { + DrtStopTask stopTask = (DrtStopTask) task; + + incomingOccupancy += stopTask.getDropoffRequests().values().stream() + .mapToInt(AcceptedDrtRequest::getPassengerCount).sum(); + + incomingOccupancy -= stopTask.getPickupRequests().values().stream() + .mapToInt(AcceptedDrtRequest::getPassengerCount).sum(); + + if (task == referenceTask) { + return incomingOccupancy; + } + } + + index--; + } + + throw new IllegalStateException(); + } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java index 747e1ae77f2..268521d4ada 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java @@ -48,12 +48,13 @@ public class PrebookingStopActivity extends FirstLastSimStepDynActivity implemen private final AbandonVoter abandonVoter; private final Supplier endTime; + private int onboard; public PrebookingStopActivity(PassengerHandler passengerHandler, DynAgent driver, StayTask task, Map, ? extends AcceptedDrtRequest> dropoffRequests, Map, ? extends AcceptedDrtRequest> pickupRequests, String activityType, Supplier endTime, PassengerStopDurationProvider stopDurationProvider, DvrpVehicle vehicle, - PrebookingManager prebookingManager, AbandonVoter abandonVoter) { + PrebookingManager prebookingManager, AbandonVoter abandonVoter, int initialOccupancy) { super(activityType); this.passengerHandler = passengerHandler; this.driver = driver; @@ -64,12 +65,13 @@ public PrebookingStopActivity(PassengerHandler passengerHandler, DynAgent driver this.prebookingManager = prebookingManager; this.abandonVoter = abandonVoter; this.endTime = endTime; + this.onboard = initialOccupancy; } @Override protected boolean isLastStep(double now) { - boolean pickupsReady = updatePickupRequests(now); boolean dropoffsReady = updateDropoffRequests(now); + boolean pickupsReady = updatePickupRequests(now); return pickupsReady && dropoffsReady && now >= endTime.get(); } @@ -97,6 +99,7 @@ private boolean updateDropoffRequests(double now) { if (entry.getValue() <= now) { // Request should leave now passengerHandler.dropOffPassengers(driver, entry.getKey(), now); prebookingManager.notifyDropoff(entry.getKey()); + onboard -= dropoffRequests.get(entry.getKey()).getPassengerCount(); iterator.remove(); } } @@ -128,12 +131,18 @@ private boolean updatePickupRequests(double now) { var enterIterator = enterTimes.entrySet().iterator(); while (enterIterator.hasNext()) { + if (onboard >= vehicle.getCapacity()) { + // only let people enter if there is currently free capacity + break; + } + var entry = enterIterator.next(); if (entry.getValue() <= now) { // let agent enter now Verify.verify(passengerHandler.tryPickUpPassengers(this, driver, entry.getKey(), now)); enteredRequests.add(entry.getKey()); + onboard += pickupRequests.get(entry.getKey()).getPassengerCount(); enterIterator.remove(); } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtConfigGroup.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtConfigGroup.java index 7fb685bd92e..93597ab6271 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtConfigGroup.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtConfigGroup.java @@ -133,7 +133,7 @@ public static DrtConfigGroup getSingleModeDrtConfig(Config config) { @Comment( "Defines the maximum delay allowed from the initial scheduled pick up time. Once the initial pickup time is offered, the latest promised" + "pickup time is calculated based on initial scheduled pickup time + maxAllowedPickupDelay. " - + "By default, this limit is disabled. If enabled, a value between 120 and 240 is a good choice.") + + "By default, this limit is disabled. If enabled, a value between 0 and 240 is a good choice.") @PositiveOrZero public double maxAllowedPickupDelay = Double.POSITIVE_INFINITY;// [s] @@ -323,6 +323,12 @@ protected void checkConsistency(Config config) { if (useModeFilteredSubnetwork) { DvrpModeRoutingNetworkModule.checkUseModeFilteredSubnetworkAllowed(config, mode); } + + if ((maxDetourAlpha != Double.POSITIVE_INFINITY && maxDetourBeta != Double.POSITIVE_INFINITY) || maxAbsoluteDetour != Double.POSITIVE_INFINITY) { + Verify.verify(maxAllowedPickupDelay != Double.POSITIVE_INFINITY, "Detour constraints are activated, " + + "maxAllowedPickupDelay must be specified! A value between 0 and 240 seconds can be a good choice for maxAllowedPickupDelay."); + } + } @Override diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtModeModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtModeModule.java index a0cb1fc007c..f667841b104 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtModeModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtModeModule.java @@ -25,6 +25,7 @@ import com.google.inject.name.Names; import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; +import org.matsim.contrib.drt.analysis.zonal.DrtModeZonalSystemModule; import org.matsim.contrib.drt.fare.DrtFareHandler; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingModule; import org.matsim.contrib.drt.prebooking.analysis.PrebookingModeAnalysisModule; @@ -65,6 +66,7 @@ public void install() { null : ConfigGroup.getInputFileURL(getConfig().getContext(), drtCfg.vehiclesFile), drtCfg.changeStartLinkToLastLinkInSchedule)); + install(new DrtModeZonalSystemModule(drtCfg)); install(new RebalancingModule(drtCfg)); install(new DrtModeRoutingModule(drtCfg)); diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemTest.java index a49cc10a3d0..e17d38c7901 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalSystemTest.java @@ -20,11 +20,7 @@ package org.matsim.contrib.drt.analysis.zonal; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtilsTest.createNetwork; -import static org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem.createFromPreparedGeometries; - +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; @@ -33,11 +29,16 @@ import org.locationtech.jts.geom.prep.PreparedGeometryFactory; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.common.zones.ZoneSystem; import java.util.ArrayList; import java.util.List; import java.util.Map; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.matsim.contrib.common.zones.ZoneSystemUtils.createFromPreparedGeometries; +import static org.matsim.contrib.drt.analysis.zonal.DrtGridUtilsTest.createNetwork; + /** * @author Michal Maciejewski (michalm) */ @@ -45,16 +46,16 @@ public class DrtZonalSystemTest { @Test void test_cellSize100() { - DrtZonalSystem drtZonalSystem = createFromPreparedGeometries(createNetwork(), + ZoneSystem drtZonalSystem = createFromPreparedGeometries(createNetwork(), DrtGridUtils.createGridFromNetwork(createNetwork(), 100)); - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId("ab")).getId()).isEqualTo("10"); + Assertions.assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId("ab")).getId().toString()).isEqualTo("10"); } @Test void test_cellSize700() { - DrtZonalSystem drtZonalSystem = createFromPreparedGeometries(createNetwork(), + ZoneSystem drtZonalSystem = createFromPreparedGeometries(createNetwork(), DrtGridUtils.createGridFromNetwork(createNetwork(), 700)); - assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId("ab")).getId()).isEqualTo("2"); + Assertions.assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId("ab")).getId().toString()).isEqualTo("2"); } @Test @@ -62,15 +63,15 @@ void test_gridWithinServiceArea(){ Coordinate min = new Coordinate(-500, 500); Coordinate max = new Coordinate(1500, 1500); List serviceArea = createServiceArea(min,max); - Map grid = DrtGridUtils.createGridFromNetworkWithinServiceArea(createNetwork(), 100, serviceArea); - DrtZonalSystem zonalSystem = createFromPreparedGeometries(createNetwork(), + Map grid = DrtGridUtils.filterGridWithinServiceArea(DrtGridUtils.createGridFromNetwork(createNetwork(), 100), serviceArea); + ZoneSystem zonalSystem = createFromPreparedGeometries(createNetwork(), grid); assertEquals(2, zonalSystem.getZones().size()); //link 'da' is outside of the service area Id id = Id.createLinkId("da"); - assertThat(zonalSystem.getZoneForLinkId(id) == null); + Assertions.assertThat(zonalSystem.getZoneForLinkId(id)).isNull(); } @Test @@ -78,8 +79,8 @@ void test_noZonesWithoutLinks(){ Coordinate min = new Coordinate(1500, 1500); Coordinate max = new Coordinate(2500, 2500); List serviceArea = createServiceArea(min,max); - Map grid = DrtGridUtils.createGridFromNetworkWithinServiceArea(createNetwork(), 100, serviceArea); - DrtZonalSystem zonalSystem = createFromPreparedGeometries(createNetwork(), + Map grid = DrtGridUtils.filterGridWithinServiceArea(DrtGridUtils.createGridFromNetwork(createNetwork(), 100), serviceArea); + ZoneSystem zonalSystem = createFromPreparedGeometries(createNetwork(), grid); //service area is off the network - so we should have 0 zones.. diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelectorTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelectorTest.java index fa38b72749b..f77e5fa57a3 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelectorTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/analysis/zonal/RandomDrtZoneTargetLinkSelectorTest.java @@ -30,6 +30,8 @@ import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneImpl; import org.matsim.testcases.fakes.FakeLink; import org.mockito.ArgumentCaptor; @@ -45,7 +47,7 @@ public class RandomDrtZoneTargetLinkSelectorTest { @Test void testSelectTargetLink_fourLinks() { - DrtZone zone = DrtZone.createDummyZone("zone", List.of(link0, link1, link2, link3), null); + Zone zone = ZoneImpl.createDummyZone(Id.create("zone", Zone.class), List.of(link0, link1, link2, link3), null); //fake random sequence IntUnaryOperator random = mock(IntUnaryOperator.class); diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/MaxDetourConstraintTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/MaxDetourConstraintTest.java index 895f3a096f2..83ffce4ddb5 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/MaxDetourConstraintTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/MaxDetourConstraintTest.java @@ -2,12 +2,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; -import org.matsim.contrib.drt.passenger.MaxDetourOfferAcceptor; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.run.DrtControlerCreator; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; -import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; @@ -29,7 +26,6 @@ public void testMaxDetourConstraint() { URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_drt_config.xml"); Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(), new OTFVisConfigGroup()); - MultiModeDrtConfigGroup multiModeDrtConfigGroup = MultiModeDrtConfigGroup.get(config); DrtConfigGroup drtConfigGroup = DrtConfigGroup.getSingleModeDrtConfig(config); // Max wait time @@ -50,15 +46,6 @@ public void testMaxDetourConstraint() { Controler controler = DrtControlerCreator.createControler(config, false); - for (DrtConfigGroup drtCfg : multiModeDrtConfigGroup.getModalElements()) { - controler.addOverridingQSimModule(new AbstractDvrpModeQSimModule(drtCfg.mode) { - @Override - protected void configureQSim() { - bindModal(DrtOfferAcceptor.class).toProvider(modalProvider(getter -> new MaxDetourOfferAcceptor(drtCfg.maxAllowedPickupDelay))); - } - }); - } - controler.run(); } } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserterTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserterTest.java index 58637acaddc..2396c4da810 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserterTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserterTest.java @@ -42,6 +42,7 @@ import org.matsim.contrib.drt.optimizer.DrtRequestInsertionRetryQueue; import org.matsim.contrib.drt.optimizer.VehicleEntry; import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; +import org.matsim.contrib.drt.passenger.DefaultOfferAcceptor; import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; import org.matsim.contrib.drt.passenger.DrtRequest; import org.matsim.contrib.drt.schedule.DefaultDrtStopTask; @@ -285,7 +286,7 @@ private DefaultUnplannedRequestInserter newInserter(Fleet fleet, double now, VehicleEntry.EntryFactory vehicleEntryFactory, DrtRequestInsertionRetryQueue insertionRetryQueue, DrtInsertionSearch insertionSearch, RequestInsertionScheduler insertionScheduler) { return new DefaultUnplannedRequestInserter(mode, fleet, () -> now, eventsManager, insertionScheduler, - vehicleEntryFactory, insertionRetryQueue, insertionSearch, DrtOfferAcceptor.DEFAULT_ACCEPTOR, + vehicleEntryFactory, insertionRetryQueue, insertionSearch, new DefaultOfferAcceptor(), forkJoinPoolExtension.forkJoinPool, StaticPassengerStopDurationProvider.of(10.0, 0.0)); } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimatorTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimatorTest.java index 954959480ba..0b93d725f48 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimatorTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/demandestimator/PreviousIterationDrtDemandEstimatorTest.java @@ -30,8 +30,10 @@ import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.events.PersonDepartureEvent; import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneImpl; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.ZoneSystemImpl; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.testcases.fakes.FakeLink; @@ -46,9 +48,9 @@ public class PreviousIterationDrtDemandEstimatorTest { private final Link link1 = new FakeLink(Id.createLinkId("link_1")); private final Link link2 = new FakeLink(Id.createLinkId("link_2")); - private final DrtZone zone1 = DrtZone.createDummyZone("zone_1", List.of(link1), new Coord()); - private final DrtZone zone2 = DrtZone.createDummyZone("zone_2", List.of(link2), new Coord()); - private final DrtZonalSystem zonalSystem = new DrtZonalSystem(List.of(zone1, zone2)); + private final Zone zone1 = ZoneImpl.createDummyZone(Id.create("zone_1", Zone.class), List.of(link1), new Coord()); + private final Zone zone2 = ZoneImpl.createDummyZone(Id.create("zone_2", Zone.class), List.of(link2), new Coord()); + private final ZoneSystem zonalSystem = new ZoneSystemImpl(List.of(zone1, zone2)); @Test void noDepartures() { @@ -170,7 +172,7 @@ private PersonDepartureEvent departureEvent(double time, Link link, String mode) return new PersonDepartureEvent(time, null, link.getId(), mode, mode); } - private void assertDemand(PreviousIterationDrtDemandEstimator estimator, double fromTime, DrtZone zone, + private void assertDemand(PreviousIterationDrtDemandEstimator estimator, double fromTime, Zone zone, double expectedDemand) { assertThat(estimator.getExpectedDemand(fromTime, ESTIMATION_PERIOD).applyAsDouble(zone)).isEqualTo( expectedDemand); diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculatorTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculatorTest.java index 4f51cb334a5..e1ef42a98d1 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculatorTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehicleDensityTargetCalculatorTest.java @@ -20,17 +20,14 @@ package org.matsim.contrib.drt.optimizer.rebalancing.targetcalculator; -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Map; -import java.util.function.ToDoubleFunction; - +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.ZoneSystemUtils; import org.matsim.contrib.drt.analysis.zonal.DrtGridUtils; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.FleetSpecification; @@ -42,6 +39,11 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; +import java.util.Map; +import java.util.function.ToDoubleFunction; + +import static org.assertj.core.api.Assertions.assertThat; + /** * @author Michal Maciejewski (michalm) */ @@ -53,7 +55,7 @@ public class EqualVehicleDensityTargetCalculatorTest { private final Network network = NetworkUtils.readNetwork( config.network().getInputFileURL(config.getContext()).toString()); - private final DrtZonalSystem zonalSystem = DrtZonalSystem.createFromPreparedGeometries(network, + private final ZoneSystem zonalSystem = ZoneSystemUtils.createFromPreparedGeometries(network, DrtGridUtils.createGridFromNetwork(network, 500.)); @Test @@ -91,8 +93,8 @@ private FleetSpecification createFleetSpecification(int count) { return fleetSpecification; } - private void assertTarget(ToDoubleFunction targetFunction, DrtZonalSystem zonalSystem, String zoneId, - double expectedValue) { - assertThat(targetFunction.applyAsDouble(zonalSystem.getZones().get(zoneId))).isEqualTo(expectedValue); + private void assertTarget(ToDoubleFunction targetFunction, ZoneSystem zonalSystem, Id zoneId, + double expectedValue) { + Assertions.assertThat(targetFunction.applyAsDouble(zonalSystem.getZones().get(zoneId))).isEqualTo(expectedValue); } } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculatorTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculatorTest.java index 7d1044fcd6e..7c24bd07c26 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculatorTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/targetcalculator/EqualVehiclesToPopulationRatioTargetCalculatorTest.java @@ -33,9 +33,10 @@ import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.Population; import org.matsim.api.core.v01.population.PopulationFactory; +import org.matsim.contrib.common.zones.Zone; +import org.matsim.contrib.common.zones.ZoneSystem; +import org.matsim.contrib.common.zones.ZoneSystemUtils; import org.matsim.contrib.drt.analysis.zonal.DrtGridUtils; -import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystem; -import org.matsim.contrib.drt.analysis.zonal.DrtZone; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.FleetSpecification; @@ -59,7 +60,7 @@ public class EqualVehiclesToPopulationRatioTargetCalculatorTest { private final Network network = NetworkUtils.readNetwork( config.network().getInputFileURL(config.getContext()).toString()); - private final DrtZonalSystem zonalSystem = DrtZonalSystem.createFromPreparedGeometries(network, + private final ZoneSystem zonalSystem = ZoneSystemUtils.createFromPreparedGeometries(network, DrtGridUtils.createGridFromNetwork(network, 500.)); private final Population population = PopulationUtils.createPopulation(config); @@ -67,34 +68,36 @@ public class EqualVehiclesToPopulationRatioTargetCalculatorTest { @Test void testCalculate_oneVehiclePerZone() { - initPopulation(Map.of("2", 1, "4", 1, "8", 1)); + initPopulation(Map.of(ZoneSystemUtils.createZoneId("2"), 1, ZoneSystemUtils.createZoneId("4"), 1, ZoneSystemUtils.createZoneId("8"), 1)); + var targetFunction = new EqualVehiclesToPopulationRatioTargetCalculator(zonalSystem, population, createFleetSpecification(8)).calculate(0, Map.of()); - assertTarget(targetFunction, zonalSystem, "1", 0); - assertTarget(targetFunction, zonalSystem, "2", 8. * (1. / 3)); - assertTarget(targetFunction, zonalSystem, "3", 0); - assertTarget(targetFunction, zonalSystem, "4", 8. * (1. / 3)); - assertTarget(targetFunction, zonalSystem, "5", 0); - assertTarget(targetFunction, zonalSystem, "6", 0); - assertTarget(targetFunction, zonalSystem, "7", 0); - assertTarget(targetFunction, zonalSystem, "8", 8. * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("1", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("2", Zone.class), 8. * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("3", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("4", Zone.class), 8. * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("5", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("6", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("7", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("8", Zone.class), 8. * (1. / 3)); } @Test void testCalculate_twoVehiclesPerZone() { - initPopulation(Map.of("2", 1, "4", 1, "8", 1)); + initPopulation(Map.of(ZoneSystemUtils.createZoneId("2"), 1, ZoneSystemUtils.createZoneId("4"), 1, ZoneSystemUtils.createZoneId("8"), 1)); + var targetFunction = new EqualVehiclesToPopulationRatioTargetCalculator(zonalSystem, population, createFleetSpecification(16)).calculate(0, Map.of()); - assertTarget(targetFunction, zonalSystem, "1", 0); - assertTarget(targetFunction, zonalSystem, "2", 16 * (1. / 3)); - assertTarget(targetFunction, zonalSystem, "3", 0); - assertTarget(targetFunction, zonalSystem, "4", 16 * (1. / 3)); - assertTarget(targetFunction, zonalSystem, "5", 0); - assertTarget(targetFunction, zonalSystem, "6", 0); - assertTarget(targetFunction, zonalSystem, "7", 0); - assertTarget(targetFunction, zonalSystem, "8", 16. * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("1", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("2", Zone.class), 16 * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("3", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("4", Zone.class), 16 * (1. / 3)); + assertTarget(targetFunction, zonalSystem, Id.create("5", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("6", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("7", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("8", Zone.class), 16. * (1. / 3)); } @Test @@ -103,30 +106,30 @@ void testCalculate_noPopulation() { var targetFunction = new EqualVehiclesToPopulationRatioTargetCalculator(zonalSystem, population, createFleetSpecification(16)).calculate(0, Map.of()); - assertTarget(targetFunction, zonalSystem, "1", 0); - assertTarget(targetFunction, zonalSystem, "2", 0); - assertTarget(targetFunction, zonalSystem, "3", 0); - assertTarget(targetFunction, zonalSystem, "4", 0); - assertTarget(targetFunction, zonalSystem, "5", 0); - assertTarget(targetFunction, zonalSystem, "6", 0); - assertTarget(targetFunction, zonalSystem, "7", 0); - assertTarget(targetFunction, zonalSystem, "8", 0); + assertTarget(targetFunction, zonalSystem, Id.create("1", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("2", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("3", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("4", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("5", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("6", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("7", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("8", Zone.class), 0); } @Test void testCalculate_unevenDistributionOfActivitiesInPopulatedZones() { - initPopulation(Map.of("2", 2, "4", 4, "8", 8)); + initPopulation(Map.of(ZoneSystemUtils.createZoneId("2"), 2, ZoneSystemUtils.createZoneId("4"), 4, ZoneSystemUtils.createZoneId("8"), 8)); var targetFunction = new EqualVehiclesToPopulationRatioTargetCalculator(zonalSystem, population, createFleetSpecification(16)).calculate(0, Map.of()); - assertTarget(targetFunction, zonalSystem, "1", 0); - assertTarget(targetFunction, zonalSystem, "2", 16 * (2. / 14)); - assertTarget(targetFunction, zonalSystem, "3", 0); - assertTarget(targetFunction, zonalSystem, "4", 16 * (4. / 14)); - assertTarget(targetFunction, zonalSystem, "5", 0); - assertTarget(targetFunction, zonalSystem, "6", 0); - assertTarget(targetFunction, zonalSystem, "7", 0); - assertTarget(targetFunction, zonalSystem, "8", 16 * (8. / 14)); + assertTarget(targetFunction, zonalSystem, Id.create("1", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("2", Zone.class), 16 * (2. / 14)); + assertTarget(targetFunction, zonalSystem, Id.create("3", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("4", Zone.class), 16 * (4. / 14)); + assertTarget(targetFunction, zonalSystem, Id.create("5", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("6", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("7", Zone.class), 0); + assertTarget(targetFunction, zonalSystem, Id.create("8", Zone.class), 16 * (8. / 14)); } private FleetSpecification createFleetSpecification(int count) { @@ -149,7 +152,7 @@ private FleetSpecification createFleetSpecification(int count) { * 2 4 6 8 * 1 3 5 7 */ - private void initPopulation(Map populationPerZone) { + private void initPopulation(Map, Integer> populationPerZone) { populationPerZone.forEach((zoneId, population) -> { for (int i = 0; i < population; i++) { createAndAddPerson(zoneId + "_" + i, zoneId); @@ -157,7 +160,7 @@ private void initPopulation(Map populationPerZone) { }); } - private void createAndAddPerson(String id, String zoneId) { + private void createAndAddPerson(String id, Id zoneId) { Id linkId = zonalSystem.getZones().get(zoneId).getLinks().get(0).getId(); Person person = factory.createPerson(Id.createPersonId(id)); Plan plan = factory.createPlan(); @@ -166,8 +169,8 @@ private void createAndAddPerson(String id, String zoneId) { population.addPerson(person); } - private void assertTarget(ToDoubleFunction targetFunction, DrtZonalSystem zonalSystem, String zoneId, - double expectedValue) { + private void assertTarget(ToDoubleFunction targetFunction, ZoneSystem zonalSystem, Id zoneId, + double expectedValue) { assertThat(targetFunction.applyAsDouble(zonalSystem.getZones().get(zoneId))).isEqualTo(expectedValue); } } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTest.java index 152ac850766..8a2f236a7b0 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTest.java @@ -4,12 +4,15 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.contrib.drt.passenger.DrtRequest; import org.matsim.contrib.drt.prebooking.PrebookingTestEnvironment.RequestInfo; import org.matsim.contrib.drt.prebooking.logic.AttributeBasedPrebookingLogic; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; import org.matsim.contrib.drt.stops.StaticPassengerStopDurationProvider; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; import org.matsim.core.controler.Controler; import org.matsim.testcases.MatsimTestUtils; @@ -566,7 +569,7 @@ void destinationEqualsPrebookedOrigin_twoRequests() { assertEquals(8000.0 + 60.0 + 1.0, requestInfo.pickupTime, 1e-3); assertEquals(8230.0, requestInfo.dropoffTime, 1e-3); } - + { RequestInfo requestInfo = environment.getRequestInfo().get("requestC"); assertEquals(2.0, requestInfo.submissionTime, 1e-3); @@ -576,7 +579,7 @@ void destinationEqualsPrebookedOrigin_twoRequests() { assertEquals(4, environment.getTaskInfo().get("vehicleA").stream().filter(t -> t.type.equals("STOP")).count()); } - + @Test void destinationEqualsPrebookedOrigin_oneRequest() { /*- @@ -614,4 +617,147 @@ void destinationEqualsPrebookedOrigin_oneRequest() { assertEquals(4, environment.getTaskInfo().get("vehicleA").stream().filter(t -> t.type.equals("STOP")).count()); } + + @Test + void intraStopTiming_pickupTooEarly() { + /*- + * In this test, we cover the intra stop timing when we use customizable stop + * durations. Before the fix, there was a bug described by the following + * situation: + * + * - We look for an insertion for a pickup + * - We find an existing stop that already contains some dropoffs + * - Inserting the pickup overall will fit (assuming that the persons are dropped off, then picked up) + * - But because of variable stop durations, the pickup happens *before* the dropoffs + * - Leading to a few seconds in which the occupancy is higher than the vehicle capacity + * + * This test led to a VerifyException in VehicleOccupancyProfileCalculator.processOccupancyChange + */ + + PrebookingTestEnvironment environment = new PrebookingTestEnvironment(utils) // + .addVehicle("vehicleA", 1, 1) // + .setVehicleCapacity(2) // + .addRequest("requestA1", 1, 1, 8, 8, 2000.0, 1.0) // forward + .addRequest("requestA2", 1, 1, 8, 8, 2000.0, 2.0) // forward + .addRequest("requestB1", 8, 8, 1, 1, 2356.0, 3.0) // backward + .configure(300.0, 2.0, 1800.0, 60.0) // + .endTime(12.0 * 3600.0); + + Controler controller = environment.build(); + installPrebooking(controller); + + controller.addOverridingModule(new AbstractDvrpModeModule("drt") { + @Override + public void install() { + bindModal(PassengerStopDurationProvider.class).toInstance(new PassengerStopDurationProvider() { + @Override + public double calcPickupDuration(DvrpVehicle vehicle, DrtRequest request) { + if (request.getPassengerIds().get(0).toString().startsWith("requestA")) { + return 60.0; + } else { + return 30.0; // shorter than the dropoff duration (see below) + } + } + + @Override + public double calcDropoffDuration(DvrpVehicle vehicle, DrtRequest request) { + return 60.0; + } + }); + } + }); + + controller.run(); + + { + RequestInfo requestInfo = environment.getRequestInfo().get("requestA1"); + assertEquals(1.0, requestInfo.submissionTime, 1e-3); + assertEquals(2000.0 + 60.0 + 1.0, requestInfo.pickupTime, 1e-3); + assertEquals(2356.0 + 60.0, requestInfo.dropoffTime, 1e-3); + } + + { + RequestInfo requestInfo = environment.getRequestInfo().get("requestA2"); + assertEquals(2.0, requestInfo.submissionTime, 1e-3); + assertEquals(2000.0 + 60.0 + 1.0, requestInfo.pickupTime, 1e-3); + assertEquals(2356.0 + 60.0, requestInfo.dropoffTime, 1e-3); + } + + { + RequestInfo requestInfo = environment.getRequestInfo().get("requestB1"); + assertEquals(3.0, requestInfo.submissionTime, 1e-3); + assertEquals(2356.0 + 60.0, requestInfo.pickupTime, 1e-3); // NOT 30s because we need to wait for the dropoffs + assertEquals(2753.0 + 60.0, requestInfo.dropoffTime, 1e-3); + } + + assertEquals(3, environment.getTaskInfo().get("vehicleA").stream().filter(t -> t.type.equals("STOP")).count()); + } + + @Test + void intraStopTiming_dropoffTooLate() { + /*- + * Inverse situation of the previous test: A new request is inserted, but the dropoff + * happens too late compared to the pickups in the following stop task. + * + * This test led to a VerifyException in VehicleOccupancyProfileCalculator.processOccupancyChange + */ + + PrebookingTestEnvironment environment = new PrebookingTestEnvironment(utils) // + .addVehicle("vehicleA", 1, 1) // + .setVehicleCapacity(2) // + .addRequest("requestA", 1, 1, 8, 8, 2000.0, 1.0) // forward + .addRequest("requestB1", 8, 8, 1, 1, 2356.0, 2.0) // backward + .addRequest("requestB2", 8, 8, 1, 1, 2356.0, 3.0) // backward + .configure(300.0, 2.0, 1800.0, 60.0) // + .endTime(12.0 * 3600.0); + + Controler controller = environment.build(); + installPrebooking(controller); + + controller.addOverridingModule(new AbstractDvrpModeModule("drt") { + @Override + public void install() { + bindModal(PassengerStopDurationProvider.class).toInstance(new PassengerStopDurationProvider() { + @Override + public double calcPickupDuration(DvrpVehicle vehicle, DrtRequest request) { + return 60.0; + } + + @Override + public double calcDropoffDuration(DvrpVehicle vehicle, DrtRequest request) { + if (request.getPassengerIds().get(0).toString().equals("requestA")) { + return 90.0; // longer than the pickups + } else { + return 60.0; + } + } + }); + } + }); + + controller.run(); + + { + RequestInfo requestInfo = environment.getRequestInfo().get("requestA"); + assertEquals(1.0, requestInfo.submissionTime, 1e-3); + assertEquals(2000.0 + 60.0 + 1.0, requestInfo.pickupTime, 1e-3); + assertEquals(2356.0 + 90.0, requestInfo.dropoffTime, 1e-3); + } + + { + RequestInfo requestInfo = environment.getRequestInfo().get("requestB1"); + assertEquals(2.0, requestInfo.submissionTime, 1e-3); + assertEquals(2356.0 + 60.0, requestInfo.pickupTime, 1e-3); + assertEquals(2753.0 + 60.0 + 30.0, requestInfo.dropoffTime, 1e-3); // +30 because we wait for dropoff of A for B2 to enter + } + + { + RequestInfo requestInfo = environment.getRequestInfo().get("requestB2"); + assertEquals(3.0, requestInfo.submissionTime, 1e-3); + assertEquals(2356.0 + 60.0 + 30.0, requestInfo.pickupTime, 1e-3); // +30 because we wait for dropoff of A + assertEquals(2753.0 + 60.0 + 30.0, requestInfo.dropoffTime, 1e-3); // +30 because we wait for dropoff of A + } + + assertEquals(3, environment.getTaskInfo().get("vehicleA").stream().filter(t -> t.type.equals("STOP")).count()); + } } 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/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; + } +} diff --git a/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleTest.java b/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleTest.java index e8bb29fea1c..87644405c7d 100644 --- a/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleTest.java +++ b/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleTest.java @@ -10,7 +10,7 @@ import org.matsim.core.events.EventsUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class RunEvExampleTest{ @@ -39,8 +39,8 @@ public class RunEvExampleTest{ { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } catch ( Exception ee ) { @@ -72,8 +72,8 @@ public class RunEvExampleTest{ { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } catch ( Exception ee ) { diff --git a/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModelTest.java b/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModelTest.java index ffc5f81e296..447b79966ad 100644 --- a/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModelTest.java +++ b/contribs/ev/src/test/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModelTest.java @@ -10,11 +10,7 @@ import org.matsim.core.events.EventsUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; - -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class RunEvExampleWithLTHConsumptionModelTest{ @@ -43,8 +39,8 @@ void runTest(){ { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals( EventsFileComparator.Result.FILES_ARE_EQUAL, result ); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result ); } } catch ( Exception ee ) { diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT.java index ced181d3172..b195b3b89d7 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT.java @@ -32,7 +32,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class RunChessboardIT { @@ -60,8 +60,8 @@ void runChessboard() { { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); - Assertions.assertEquals( EventsFileComparator.Result.FILES_ARE_EQUAL, result ); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result ); } } catch (Exception ee ) { ee.printStackTrace(); diff --git a/contribs/hybridsim/pom.xml b/contribs/hybridsim/pom.xml index 57b42a70d8a..511f16993b9 100644 --- a/contribs/hybridsim/pom.xml +++ b/contribs/hybridsim/pom.xml @@ -10,8 +10,8 @@ hybridsim - 3.25.3 - 1.62.2 + 4.26.1 + 1.63.0 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/parking/src/test/java/org/matsim/contrib/parking/parkingchoice/run/RunParkingSearchScenarioIT.java b/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingchoice/run/RunParkingSearchScenarioIT.java index fa0dc4f5ffd..e3959961195 100644 --- a/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingchoice/run/RunParkingSearchScenarioIT.java +++ b/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingchoice/run/RunParkingSearchScenarioIT.java @@ -33,7 +33,7 @@ import org.matsim.core.events.EventsUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; /** * @author jbischoff @@ -108,8 +108,8 @@ void testRunParkingDistanceMemoryStrategy() { { String expected = utils.getInputDirectory() + "/output_events.xml.gz"; String actual = utils.getOutputDirectory() + "/output_events.xml.gz"; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles(expected, actual); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles(expected, actual); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } catch (Exception e) { e.printStackTrace(); @@ -146,8 +146,8 @@ void testRunParkingNearestParkingSpotStrategy() { { String expected = utils.getInputDirectory() + "/output_events.xml.gz"; String actual = utils.getOutputDirectory() + "/output_events.xml.gz"; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles(expected, actual); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles(expected, actual); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } catch (Exception e) { e.printStackTrace(); diff --git a/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingproxy/run/RunWithParkingProxyIT.java b/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingproxy/run/RunWithParkingProxyIT.java index 6d17839c44c..e87a4afbaba 100644 --- a/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingproxy/run/RunWithParkingProxyIT.java +++ b/contribs/parking/src/test/java/org/matsim/contrib/parking/parkingproxy/run/RunWithParkingProxyIT.java @@ -30,7 +30,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator.Result; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class RunWithParkingProxyIT { private static final Logger log = LogManager.getLogger(RunWithParkingProxyIT.class); @@ -50,8 +50,8 @@ void testMain(){ { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - Result result = EventsUtils.compareEventsFiles( expected, actual ); - if(!result.equals(Result.FILES_ARE_EQUAL)) { + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + if(!result.equals(ComparisonResult.FILES_ARE_EQUAL)) { throw new RuntimeException("Events comparison ended with result " + result.name()); } } diff --git a/contribs/protobuf/pom.xml b/contribs/protobuf/pom.xml index 9e13515761a..0cf9ae143fc 100644 --- a/contribs/protobuf/pom.xml +++ b/contribs/protobuf/pom.xml @@ -11,7 +11,7 @@ protobuf - 3.25.3 + 4.26.1 diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngine.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngine.java index ff98123051a..3b20be8ca7c 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngine.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngine.java @@ -55,7 +55,7 @@ final class RailsimEngine implements Steppable { * Additional safety distance in meter that is added to the reservation distance. * Ensure that trains always have enough distance to progress. */ - private static double SAFETY_DIST = 10; + private static final double SAFETY_DIST = 10; private static final Logger log = LogManager.getLogger(RailsimEngine.class); private final EventsManager eventsManager; private final RailsimConfigGroup config; @@ -193,7 +193,7 @@ private void blockTrack(double time, UpdateEvent event) { updatePosition(time, event); if (!blockLinkTracks(time, state)) { - + // train needs to stop decideTargetSpeed(event, state); event.checkReservation = time + config.pollInterval; @@ -388,7 +388,7 @@ private void enterLink(double time, UpdateEvent event) { return; } - // Train stopped and reserves next links + // Train stopped exactly at the end of the link and tries to enter the next link if (FuzzyUtils.equals(state.speed, 0) && !blockLinkTracks(time, state)) { RailLink currentLink = state.route.get(state.routeIdx); @@ -766,6 +766,7 @@ private double retrieveAllowedMaxSpeed(TrainState state) { double maxSpeed = resources.getLink(state.headLink).getAllowedFreespeed(state.driver); + // get minium allowed speed on all links occupied by the train for (int i = state.routeIdx - 1; i >= 0; i--) { RailLink link = state.route.get(i); maxSpeed = Math.min(maxSpeed, link.getAllowedFreespeed(state.driver)); @@ -780,7 +781,7 @@ private double retrieveAllowedMaxSpeed(TrainState state) { /** * Remove all trains from simulation and generate events at the end of the day. * - * @param now end of day time + * @param now end of daytime */ void clearTrains(double now) { diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/UpdateEvent.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/UpdateEvent.java index a8a2c246ddd..1fc5a29b1ef 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/UpdateEvent.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/UpdateEvent.java @@ -55,6 +55,9 @@ final class UpdateEvent implements Comparable { this.unblockLink = null; } + /** + * Update event to unblock a link after minimum headway time. + */ UpdateEvent(TrainState state, RailLink unblockLink, double time) { this.state = state; this.unblockLink = unblockLink; diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/deadlocks/SimpleDeadlockAvoidance.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/deadlocks/SimpleDeadlockAvoidance.java index 6ad95f76623..c92e0788325 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/deadlocks/SimpleDeadlockAvoidance.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/deadlocks/SimpleDeadlockAvoidance.java @@ -43,14 +43,15 @@ public void onReserve(double time, RailResource resource, TrainPosition position RailLink link = position.getRoute(i); RailResource r = link.getResource(); // // Iterate through route until requested resource is present - if (r == resource) { resourceFound = true; } + // all resources before requested resource can be ignored if (!resourceFound) continue; + // check for all conflict points at and beyond the resource if (isConflictPoint(r)) { Reservation reservation = conflictPoints.computeIfAbsent(r, k -> new Reservation()); @@ -63,6 +64,7 @@ public void onReserve(double time, RailResource resource, TrainPosition position reservation.trains.add(position.getDriver()); } else + // as soon as we find an avoidance point we can stop reserving break; } diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/disposition/SimpleDisposition.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/disposition/SimpleDisposition.java index 7bb0642bfad..3e1094fc776 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/disposition/SimpleDisposition.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/disposition/SimpleDisposition.java @@ -111,7 +111,7 @@ public DispositionResponse requestNextSegment(double time, TrainPosition positio } } - return new DispositionResponse(reserveDist, stop ? 0 : Double.POSITIVE_INFINITY, detour); + return new DispositionResponse(reserveDist, stop ? 0 : Double.POSITIVE_INFINITY, null); } private Detour checkDetour(double time, List segment, TrainPosition position) { diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailLink.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailLink.java index 06be3f5556e..8702b955afa 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailLink.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailLink.java @@ -28,7 +28,7 @@ import java.util.Objects; /** - * Rail links which can has multiple tracks and corresponds to exactly one link. + * Rail links can have multiple tracks and corresponds to exactly one link. */ public final class RailLink implements HasLinkId { private final Id id; diff --git a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailResourceManager.java b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailResourceManager.java index 9a04894bf00..14b90ad151d 100644 --- a/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailResourceManager.java +++ b/contribs/railsim/src/main/java/ch/sbb/matsim/contrib/railsim/qsimengine/resources/RailResourceManager.java @@ -47,7 +47,7 @@ public final class RailResourceManager { public static final int ANY_TRACK = -1; /** - * Constant to indicate than any track is allowed as long as the opposing direction is not blocked. + * Constant to indicate that any track is allowed as long as the opposing direction is not blocked. */ public static final int ANY_TRACK_NON_BLOCKING = -2; diff --git a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java index 6a61f5d0f16..b139bfd423b 100644 --- a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java +++ b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/integration/RailsimIntegrationTest.java @@ -243,6 +243,11 @@ void testMicroTrainFollowingVaryingSpeed() { EventsCollector collector = runSimulation(new File(utils.getPackageInputDirectory(), "microTrainFollowingVaryingSpeed")); } + @Test + void testMicroTrainFollowingFixedVsMovingBlock() { + EventsCollector collector = runSimulation(new File(utils.getPackageInputDirectory(), "microTrainFollowingFixedVsMovingBlock")); + } + @Test void testMicroStationSameLink() { EventsCollector collector = runSimulation(new File(utils.getPackageInputDirectory(), "microStationSameLink")); diff --git a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimDeadlockTest.java b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimDeadlockTest.java index ddd998ee3f1..bc7d7cfca00 100644 --- a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimDeadlockTest.java +++ b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimDeadlockTest.java @@ -67,7 +67,7 @@ public void deadlock() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "HG", "DC"); test.doSimStepUntil(250); -// test.debugFiles(collector, "deadLock"); + test.debugFiles(collector, utils.getOutputDirectory() + "/deadLock"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 240, "y1y", 0) @@ -93,7 +93,7 @@ public void deadLockAvoidancePoint() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "HG", "CD"); test.doSimStepUntil(250); -// test.debugFiles(collector, "deadLockAvoidancePoint"); + test.debugFiles(collector, utils.getOutputDirectory() + "/deadLockAvoidancePoint"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 240, "y1y", 0) @@ -118,7 +118,7 @@ public void avoidancePoint() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "HG", "CD"); test.doSimStepUntil(800); - test.debugFiles(collector, "avoidancePoint"); + test.debugFiles(collector, utils.getOutputDirectory() + "/avoidancePoint"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 420, "EF", 0) @@ -147,7 +147,7 @@ public void tooSmall() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2b", 0, "HG", "CD"); test.doSimStepUntil(1500); -// test.debugFiles(collector, "tooSmall"); + test.debugFiles(collector, utils.getOutputDirectory() + "/tooSmall"); RailsimTestUtils.assertThat(collector) @@ -166,7 +166,7 @@ public void oneWay() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "HG", "CD"); test.doSimStepUntil(800); -// test.debugFiles(collector, "oneWay"); + test.debugFiles(collector, utils.getOutputDirectory() + "/oneWay"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 350, "EF", 0) @@ -185,7 +185,7 @@ public void twoWay() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2b", 0, "HG", "CD"); test.doSimStepUntil(800); -// test.debugFiles(collector, "twoWay"); + test.debugFiles(collector, utils.getOutputDirectory() + "/twoWay"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1a", 350, "EF", 0) @@ -217,7 +217,7 @@ public void movingBlock() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2b", 0, "HG", "CD"); test.doSimStepUntil(1500); -// test.debugFiles(collector, "movingBlock"); + test.debugFiles(collector, utils.getOutputDirectory() + "/movingBlock"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1a", 670, "EF", 0) diff --git a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineMovingBlockTest.java b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineMovingBlockTest.java index ae31cac7539..134959bb6a2 100644 --- a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineMovingBlockTest.java +++ b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineMovingBlockTest.java @@ -71,11 +71,9 @@ public void multipleTrains() { test.doSimStepUntil(5_000); -// test.debugFiles(collector, "movingBlock"); + test.debugFiles(collector, utils.getOutputDirectory() + "/movingBlock"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 2370, 200, 0) - .hasTrainState("cargo", 3268, 200, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 2370, 200, 0).hasTrainState("cargo", 3268, 200, 0) .hasTrainState("sprinter", 3345, 200, 0); test = getTestEngine("networkMovingBlocks.xml"); @@ -84,10 +82,9 @@ public void multipleTrains() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 120, "l1-2", "l6-7"); test.doStateUpdatesUntil(5_000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/movingBlock_detailed"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 2370, 200, 0) - .hasTrainState("cargo", 3268, 200, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 2370, 200, 0).hasTrainState("cargo", 3268, 200, 0) .hasTrainState("sprinter", 3345, 200, 0); } @@ -100,22 +97,18 @@ public void opposite() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter2", 400, "l6-5", "l2-1"); test.doSimStepUntil(2_000); -// test.debugFiles(collector, "opposite"); + test.debugFiles(collector, utils.getOutputDirectory() + "/opposite"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("sprinter2", 1368, 200, 0) - .hasTrainState("sprinter", 1559, 200, 0); + RailsimTestUtils.assertThat(collector).hasTrainState("sprinter2", 1368, 200, 0).hasTrainState("sprinter", 1559, 200, 0); test = getTestEngine("networkMovingBlocks.xml"); RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 0, "l1-2", "l6-7"); RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter2", 400, "l6-5", "l2-1"); test.doStateUpdatesUntil(2_000, 5); -// test.debugFiles(collector, "opposite_detailed"); + test.debugFiles(collector, utils.getOutputDirectory() + "/opposite_detailed"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("sprinter2", 1368, 200, 0) - .hasTrainState("sprinter", 1559, 200, 0); + RailsimTestUtils.assertThat(collector).hasTrainState("sprinter2", 1368, 200, 0).hasTrainState("sprinter", 1559, 200, 0); } @@ -130,11 +123,9 @@ public void multiTrack() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 120, "l1-2", "l6-7"); test.doSimStepUntil(5_000); -// test.debugFiles(collector, "multiTrack"); + test.debugFiles(collector, utils.getOutputDirectory() + "/multiTrack"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 2370, 200, 0) - .hasTrainState("cargo", 3268, 200, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 2370, 200, 0).hasTrainState("cargo", 3268, 200, 0) .hasTrainState("sprinter", 1984, 200, 0); test = getTestEngine("networkMovingBlocks.xml", l -> RailsimUtils.setTrainCapacity(l, 3)); @@ -144,10 +135,9 @@ public void multiTrack() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 120, "l1-2", "l6-7"); test.doStateUpdatesUntil(5_000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/multiTrack_detailed"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 2370, 200, 0) - .hasTrainState("cargo", 3268, 200, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 2370, 200, 0).hasTrainState("cargo", 3268, 200, 0) .hasTrainState("sprinter", 1984, 200, 0); } @@ -162,11 +152,9 @@ public void mixed() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 0, "1-2", "20-21"); test.doSimStepUntil(2_000); - test.debugFiles(collector, "mixed"); + test.debugFiles(collector, utils.getOutputDirectory() + "/mixed"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 1418, 1000, 0) - .hasTrainState("cargo", 1241, 1000, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 1418, 1000, 0).hasTrainState("cargo", 1241, 1000, 0) .hasTrainState("sprinter", 1324, 1000, 0); test = getTestEngine("networkMixedTypes.xml"); @@ -175,10 +163,9 @@ public void mixed() { RailsimTestUtils.createDeparture(test, TestVehicle.Sprinter, "sprinter", 0, "1-2", "20-21"); test.doStateUpdatesUntil(2_000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/mixed_detailed"); - RailsimTestUtils.assertThat(collector) - .hasTrainState("regio", 1418, 1000, 0) - .hasTrainState("cargo", 1241, 1000, 0) + RailsimTestUtils.assertThat(collector).hasTrainState("regio", 1418, 1000, 0).hasTrainState("cargo", 1241, 1000, 0) .hasTrainState("sprinter", 1324, 1000, 0); } diff --git a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineTest.java b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineTest.java index 6d0d67ad81b..cd25d4536ac 100644 --- a/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineTest.java +++ b/contribs/railsim/src/test/java/ch/sbb/matsim/contrib/railsim/qsimengine/RailsimEngineTest.java @@ -42,7 +42,7 @@ public class RailsimEngineTest { @RegisterExtension - private MatsimTestUtils utils = new MatsimTestUtils(); + private final MatsimTestUtils utils = new MatsimTestUtils(); private EventsManager eventsManager; private RailsimTestUtils.EventCollector collector; @@ -84,6 +84,7 @@ void testSimple() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "train", 0, "l1-2", "l5-6"); test.doSimStepUntil(400); + test.debugFiles(collector, utils.getOutputDirectory() + "/simple"); RailsimTestUtils.assertThat(collector) .hasSizeGreaterThan(5) @@ -94,6 +95,7 @@ void testSimple() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "train", 0, "l1-2", "l5-6"); test.doStateUpdatesUntil(400, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/simple_detailed"); RailsimTestUtils.assertThat(collector) .hasSizeGreaterThan(5) @@ -111,6 +113,7 @@ void testCongested() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio", 60, "l1-2", "l5-6"); test.doSimStepUntil(600); + test.debugFiles(collector, utils.getOutputDirectory() + "/congested"); RailsimTestUtils.assertThat(collector) .hasTrainState("cargo", 359, 2000, 0) @@ -127,6 +130,7 @@ void testCongestedWithHeadway() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio", 60, "l1-2", "l5-6"); test.doSimStepUntil(600); + test.debugFiles(collector, utils.getOutputDirectory() + "/congestedWithHeadway"); RailsimTestUtils.assertThat(collector) .hasTrainState("cargo", 359, 2000, 0) @@ -144,6 +148,7 @@ void testOpposite() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "l8-7", "l2-1"); test.doSimStepUntil(600); + test.debugFiles(collector, utils.getOutputDirectory() + "/opposite"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1", 293, 600, 0) @@ -156,6 +161,7 @@ void testOpposite() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "l8-7", "l2-1"); test.doStateUpdatesUntil(600, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/opposite_detailed"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1", 293, 600, 0) @@ -171,6 +177,7 @@ void testVaryingSpeedOne() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio", 0, "t1_IN-t1_OUT", "t3_IN-t3_OUT"); test.doSimStepUntil(10000); + test.debugFiles(collector, utils.getOutputDirectory() + "/varyingSpeedOne"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 7599, 0, 2.7777777) @@ -181,6 +188,7 @@ void testVaryingSpeedOne() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio", 0, "t1_IN-t1_OUT", "t3_IN-t3_OUT"); test.doStateUpdatesUntil(10000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/varyingSpeedOne_detailed"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio", 7599, 0, 2.7777777) @@ -198,6 +206,7 @@ void testVaryingSpeedMany() { } test.doSimStepUntil(30000); + test.debugFiles(collector, utils.getOutputDirectory() + "/varyingSpeedMany"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio0", 7599, 0, 2.7777777) @@ -212,6 +221,7 @@ void testVaryingSpeedMany() { } test.doStateUpdatesUntil(30000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/varyingSpeedMany_detailed"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio0", 7599, 0, 2.7777777) @@ -229,6 +239,7 @@ void testTrainFollowing() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "1-2", "20-21"); test.doSimStepUntil(5000); + test.debugFiles(collector, utils.getOutputDirectory() + "/trainFollowing"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1", 1138, 1000, 0) @@ -239,6 +250,7 @@ void testTrainFollowing() { RailsimTestUtils.createDeparture(test, TestVehicle.Regio, "regio2", 0, "1-2", "20-21"); test.doStateUpdatesUntil(5000, 1); + test.debugFiles(collector, utils.getOutputDirectory() + "/trainFollowing_detailed"); RailsimTestUtils.assertThat(collector) .hasTrainState("regio1", 1138, 1000, 0) @@ -254,7 +266,7 @@ void testMicroTrainFollowingVaryingSpeed() { RailsimTestUtils.createDeparture(test, TestVehicle.Cargo, "cargo2", 15, "1-2", "20-21"); test.doSimStepUntil(3000); -// test.debugFiles(collector, "microVarying"); + test.debugFiles(collector, utils.getOutputDirectory() + "/microVarying"); RailsimTestUtils.assertThat(collector) .hasTrainState("cargo1", 1278, 1000, 0) @@ -265,7 +277,7 @@ void testMicroTrainFollowingVaryingSpeed() { RailsimTestUtils.createDeparture(test, TestVehicle.Cargo, "cargo1", 0, "1-2", "20-21"); RailsimTestUtils.createDeparture(test, TestVehicle.Cargo, "cargo2", 15, "1-2", "20-21"); test.doStateUpdatesUntil(3000, 1); -// test.debugFiles(collector, "microVarying_detailed"); + test.debugFiles(collector, utils.getOutputDirectory() + "/microVarying_detailed"); RailsimTestUtils.assertThat(collector) .hasTrainState("cargo1", 1278, 1000, 0) diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/config.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/config.xml new file mode 100644 index 00000000000..da3761b5c4e --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/config.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/trainNetwork.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/trainNetwork.xml new file mode 100644 index 00000000000..9787942945a --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/trainNetwork.xml @@ -0,0 +1,144 @@ + + + + + + Atlantis + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixedBlock + 5 + + + + + fixedBlock + 1 + + + + + fixedBlock + 1 + + + + + fixedBlock + 1 + + + + + fixedBlock + 1 + + + + + fixedBlock + 1 + + + + + fixedBlock + 5 + + + + + + + movingBlock + 5 + + + + + movingBlock + 1 + + + + + movingBlock + 1 + + + + + movingBlock + 1 + + + + + movingBlock + 1 + + + + + movingBlock + 1 + + + + + movingBlock + 5 + + + + + + + + diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitSchedule.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitSchedule.xml new file mode 100644 index 00000000000..104bc96ace6 --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitSchedule.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + rail + + + + + + + + + + + + + + + + + + + + + + rail + + + + + + + + + + + + + + + + + + + + diff --git a/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitVehicles.xml b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitVehicles.xml new file mode 100644 index 00000000000..5e4675ae4ae --- /dev/null +++ b/contribs/railsim/test/input/ch/sbb/matsim/contrib/railsim/integration/microTrainFollowingFixedVsMovingBlock/transitVehicles.xml @@ -0,0 +1,48 @@ + + + + + + + 0.1 + 0.1 + + + + + + + + + + + + + + + + + + 0.4 + 0.1 + + + + + + + + + + + + + + + + + + + + + diff --git a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/run/RoadPricingByConfigfileTest.java b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/run/RoadPricingByConfigfileTest.java index 70b4bc9344d..e59e74dd90b 100644 --- a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/run/RoadPricingByConfigfileTest.java +++ b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/run/RoadPricingByConfigfileTest.java @@ -32,7 +32,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; /** * @author vsp-gleich @@ -55,7 +55,7 @@ final void testMain() { { String expected = utils.getInputDirectory() + "/output_events.xml.gz" ; String actual = utils.getOutputDirectory() + "/output_events.xml.gz" ; - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, EventsUtils.compareEventsFiles( expected, actual )); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, EventsUtils.compareEventsFiles( expected, actual )); } { final Population expected = PopulationUtils.createPopulation( ConfigUtils.createConfig() ); diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java index 9e341d444a6..ba97489f89e 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java @@ -38,8 +38,7 @@ import org.matsim.core.scenario.ScenarioUtils; import org.matsim.testcases.MatsimTestUtils; import org.matsim.utils.eventsfilecomparison.EventsFileComparator; - -import static org.matsim.utils.eventsfilecomparison.EventsFileComparator.*; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; /** * @author aneumann @@ -125,7 +124,7 @@ private void runQSimWithSignals(final Scenario scenario) { eventsXmlWriter.closeFile(); // Assert.assertEquals("different events files", EventsFileComparator.compareAndReturnInt(this.testUtils.getInputDirectory() + EVENTSFILE, eventsOut), 0); - Assertions.assertEquals( Result.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( this.testUtils.getInputDirectory() + EVENTSFILE, eventsOut ) ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( this.testUtils.getInputDirectory() + EVENTSFILE, eventsOut ) ); } } diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/integration/SignalSystemsIT.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/integration/SignalSystemsIT.java index 49e8af1f140..b44a5cf35ea 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/integration/SignalSystemsIT.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/integration/SignalSystemsIT.java @@ -36,6 +36,7 @@ import org.matsim.core.scenario.ScenarioUtils; import org.matsim.testcases.MatsimTestUtils; import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; import java.io.File; @@ -88,7 +89,7 @@ void testSignalSystems() { //iteration 0 String iterationOutput = controlerOutputDir + "ITERS/it.0/"; - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( inputDirectory + "0.events.xml.gz", iterationOutput + "0.events.xml.gz"), "different events files after iteration 0 " @@ -113,7 +114,7 @@ void testSignalSystems() { //iteration 10 String iterationOutput = controlerOutputDir + "ITERS/it.10/"; - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( inputDirectory + "10.events.xml.gz", iterationOutput + "10.events.xml.gz" ), "different event files after iteration 10" ); @@ -181,7 +182,7 @@ void testSignalSystemsWTryEndTimeThenDuration() { //iteration 0 String iterationOutput = controlerOutputDir + "ITERS/it.0/"; - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( inputDirectory + "0.events.xml.gz", iterationOutput + "0.events.xml.gz"), "different events files after iteration 0 " @@ -206,7 +207,7 @@ void testSignalSystemsWTryEndTimeThenDuration() { //iteration 10 String iterationOutput = controlerOutputDir + "ITERS/it.10/"; - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, new EventsFileComparator().setIgnoringCoordinates( true ).runComparison( inputDirectory + "10.events.xml.gz", iterationOutput + "10.events.xml.gz"), "different event files after iteration 10" ); diff --git a/contribs/simwrapper/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 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: 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 b15a3d7d99c..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 @@ -36,25 +36,17 @@ import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Leg; import org.matsim.application.MATSimAppCommand; -import org.matsim.application.options.ShpOptions; import org.matsim.application.options.ShpOptions.Index; -import org.matsim.core.config.consistency.UnmaterializedConfigGroupChecker; -import org.matsim.core.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; @@ -64,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; @@ -77,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.*; @@ -101,6 +99,7 @@ public class GenerateSmallScaleCommercialTrafficDemand implements MATSimAppComma // Option 3: Leerkamp (nur in RVR Modell). + // Option: Add prepare class with OSM Analyse and create facility file with results private static final Logger log = LogManager.getLogger(GenerateSmallScaleCommercialTrafficDemand.class); private enum CreationOption { @@ -118,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; @@ -136,15 +141,30 @@ private enum SmallScaleCommercialTrafficType { @CommandLine.Option(names = "--includeExistingModels", description = "If models for some segments exist they can be included.") private boolean includeExistingModels; + @CommandLine.Option(names = "--regionsShapeFileName", description = "Path of the region shape file.") + private Path shapeFileRegionsPath; + + @CommandLine.Option(names = "--regionsShapeRegionColumn", description = "Name of the region column in the region shape file.") + private String regionsShapeRegionColumn; + @CommandLine.Option(names = "--zoneShapeFileName", description = "Path of the zone shape file.") private Path shapeFileZonePath; + @CommandLine.Option(names = "--zoneShapeFileNameColumn", description = "Name of the unique column of the name/Id of each zone in the zones shape file.") + private String shapeFileZoneNameColumn; + @CommandLine.Option(names = "--buildingsShapeFileName", description = "Path of the buildings shape file") private Path shapeFileBuildingsPath; + @CommandLine.Option(names = "--shapeFileBuildingTypeColumn", description = "Name of the unique column of the building type in the buildings shape file.") + private String shapeFileBuildingTypeColumn; + @CommandLine.Option(names = "--landuseShapeFileName", description = "Path of the landuse shape file") private Path shapeFileLandusePath; + @CommandLine.Option(names = "--shapeFileLanduseTypeColumn", description = "Name of the unique column of the landuse type in the landuse shape file.") + private String shapeFileLanduseTypeColumn; + @CommandLine.Option(names = "--shapeCRS", description = "CRS of the three input shape files (zones, landuse, buildings") private String shapeCRS; @@ -170,6 +190,7 @@ private enum SmallScaleCommercialTrafficType { private Index indexZones; private Index indexBuildings; private Index indexLanduse; + private Index indexInvestigationAreaRegions; public static void main(String[] args) { System.exit(new CommandLine(new GenerateSmallScaleCommercialTrafficDemand()).execute(args)); @@ -226,29 +247,32 @@ public Integer call() throws Exception { if (!Files.exists(shapeFileZonePath)) { throw new Exception("Required districts shape file {} not found" + shapeFileZonePath.toString()); } - Path inputDataDirectory = Path.of(config.getContext().toURI()).getParent(); + if (!Files.exists(shapeFileRegionsPath)) { + throw new Exception("Required regions shape file {} not found" + shapeFileRegionsPath.toString()); + } - indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS); - indexBuildings = SmallScaleCommercialTrafficUtils.getIndexBuildings(shapeFileBuildingsPath, shapeCRS); - indexLanduse = SmallScaleCommercialTrafficUtils.getIndexLanduse(shapeFileLandusePath, shapeCRS); + indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS, shapeFileZoneNameColumn); + indexBuildings = SmallScaleCommercialTrafficUtils.getIndexBuildings(shapeFileBuildingsPath, shapeCRS, shapeFileBuildingTypeColumn); + indexLanduse = SmallScaleCommercialTrafficUtils.getIndexLanduse(shapeFileLandusePath, shapeCRS, shapeFileLanduseTypeColumn); + indexInvestigationAreaRegions = SmallScaleCommercialTrafficUtils.getIndexRegions(shapeFileRegionsPath, shapeCRS, regionsShapeRegionColumn); Map> resultingDataPerZone = LanduseBuildingAnalysis - .createInputDataDistribution(output, landuseCategoriesAndDataConnection, inputDataDirectory, + .createInputDataDistribution(output, landuseCategoriesAndDataConnection, usedLanduseConfiguration.toString(), indexLanduse, indexZones, - indexBuildings, buildingsPerZone); - - Map, Link>> regionLinksMap = filterLinksForZones(scenario, indexZones, buildingsPerZone); + indexBuildings, indexInvestigationAreaRegions, shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, + pathToExistingDataDistributionToZones); + Map, Link>> linksPerZone = filterLinksForZones(scenario, indexZones, buildingsPerZone, shapeFileZoneNameColumn); 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."); @@ -260,7 +284,7 @@ public Integer call() throws Exception { new CarrierPlanWriter(CarriersUtils.addOrGetCarriers(scenario)) .write(scenario.getConfig().controller().getOutputDirectory() + "/" + scenario.getConfig().controller().getRunId() + ".output_CarrierDemand.xml"); - solveSeparatedVRPs(scenario, regionLinksMap); + solveSeparatedVRPs(scenario, linksPerZone); } } if (config.controller().getRunId() == null) @@ -424,7 +448,7 @@ private void solveSeparatedVRPs(Scenario originalScenario, Map> resultingDataPerZone, - Map, Link>> regionLinksMap, String smallScaleCommercialTrafficType, + Map, Link>> linksPerZone, String smallScaleCommercialTrafficType, boolean includeExistingModels) throws Exception { ArrayList modesORvehTypes; @@ -444,13 +468,13 @@ else if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) .createTrafficVolume_stop(resultingDataPerZone, output, sample, modesORvehTypes, smallScaleCommercialTrafficType); if (includeExistingModels) { - SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); - TrafficVolumeGeneration.reduceDemandBasedOnExistingCarriers(scenario, regionLinksMap, smallScaleCommercialTrafficType, + SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, linksPerZone); + TrafficVolumeGeneration.reduceDemandBasedOnExistingCarriers(scenario, linksPerZone, smallScaleCommercialTrafficType, trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop); } final TripDistributionMatrix odMatrix = createTripDistribution(trafficVolumePerTypeAndZone_start, - trafficVolumePerTypeAndZone_stop, smallScaleCommercialTrafficType, scenario, output, regionLinksMap); - createCarriers(scenario, odMatrix, resultingDataPerZone, smallScaleCommercialTrafficType, regionLinksMap); + trafficVolumePerTypeAndZone_stop, smallScaleCommercialTrafficType, scenario, output, linksPerZone); + createCarriers(scenario, odMatrix, resultingDataPerZone, smallScaleCommercialTrafficType, linksPerZone); } /** @@ -885,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..."); @@ -912,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; } @@ -922,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) { @@ -970,7 +996,7 @@ private TripDistributionMatrix createTripDistribution( Collections.shuffle(listOfZones, rnd); for (String stopZone : listOfZones) { odMatrix.setTripDistributionValue(startZone, stopZone, modeORvehType, purpose, smallScaleCommercialTrafficType, - network, regionLinksMap, resistanceFactor); + network, regionLinksMap, resistanceFactor, shapeFileZoneNameColumn); } } } diff --git a/contribs/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..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,13 +54,17 @@ public class LanduseBuildingAnalysis { * used OSM data. */ static Map> createInputDataDistribution(Path output, - Map> landuseCategoriesAndDataConnection, Path inputDataDirectory, + Map> landuseCategoriesAndDataConnection, String usedLanduseConfiguration, Index indexLanduse, Index indexZones, - Index indexBuildings, Map>> buildingsPerZone) - throws IOException { + Index indexBuildings, Index indexInvestigationAreaRegions, + String shapeFileZoneNameColumn, + Map>> buildingsPerZone, + Path pathToInvestigationAreaData, + Path pathToExistingDataDistributionToZones) + throws IOException { Map> resultingDataPerZone = new HashMap<>(); - Map zoneIdNameConnection = new HashMap<>(); + Map zoneIdRegionConnection = new HashMap<>(); Path outputFileInOutputFolder = output.resolve("calculatedData").resolve("dataDistributionPerZone.csv"); landuseCategoriesAndDataConnection.put("Inhabitants", @@ -80,18 +84,17 @@ static Map> createInputDataDistribution(Path ou Arrays.asList("commercial", "embassy", "foundation", "government", "office", "townhall"))); if (usedLanduseConfiguration.equals("useExistingDataDistribution")) { - Path existingDataDistribution = inputDataDirectory.resolve("dataDistributionPerZone.csv"); - if (!Files.exists(existingDataDistribution)) { - log.error("Required data per zone file {} not found", existingDataDistribution); + if (!Files.exists(pathToExistingDataDistributionToZones)) { + log.error("Required data per zone file {} not found", pathToExistingDataDistributionToZones); } - try (BufferedReader reader = IOUtils.getBufferedReader(existingDataDistribution.toString())) { + try (BufferedReader reader = IOUtils.getBufferedReader(pathToExistingDataDistributionToZones.toString())) { CSVParser parse = CSVFormat.Builder.create(CSVFormat.DEFAULT).setDelimiter('\t').setHeader() .setSkipHeaderRecord(true).build().parse(reader); for (CSVRecord record : parse) { - String zoneID = record.get("areaID"); + String zoneID = record.get("zoneID"); resultingDataPerZone.put(zoneID, new Object2DoubleOpenHashMap<>()); for (int n = 2; n < parse.getHeaderMap().size(); n++) { resultingDataPerZone.get(zoneID).mergeDouble(parse.getHeaderNames().get(n), @@ -100,8 +103,8 @@ static Map> createInputDataDistribution(Path ou } } log.info("Data distribution for " + resultingDataPerZone.size() + " zones was imported from " + - existingDataDistribution); - Files.copy(existingDataDistribution, outputFileInOutputFolder, StandardCopyOption.COPY_ATTRIBUTES); + pathToExistingDataDistributionToZones); + Files.copy(pathToExistingDataDistributionToZones, outputFileInOutputFolder, StandardCopyOption.COPY_ATTRIBUTES); } else { @@ -109,18 +112,18 @@ static Map> createInputDataDistribution(Path ou log.info("New analyze for data distribution is started. The used method is: " + usedLanduseConfiguration); Map> landuseCategoriesPerZone = new HashMap<>(); - createLanduseDistribution(landuseCategoriesPerZone, indexLanduse, indexZones, + createLanduseDistribution(landuseCategoriesPerZone, indexLanduse, indexZones, indexInvestigationAreaRegions, usedLanduseConfiguration, indexBuildings, landuseCategoriesAndDataConnection, - buildingsPerZone, zoneIdNameConnection); + buildingsPerZone, shapeFileZoneNameColumn, zoneIdRegionConnection); Map> investigationAreaData = new HashMap<>(); - readAreaData(investigationAreaData, inputDataDirectory); + readAreaData(investigationAreaData, pathToInvestigationAreaData); createResultingDataForLanduseInZones(landuseCategoriesPerZone, investigationAreaData, resultingDataPerZone, - landuseCategoriesAndDataConnection); + landuseCategoriesAndDataConnection, zoneIdRegionConnection); SmallScaleCommercialTrafficUtils.writeResultOfDataDistribution(resultingDataPerZone, outputFileInOutputFolder, - zoneIdNameConnection); + zoneIdRegionConnection); } return resultingDataPerZone; @@ -131,10 +134,10 @@ static Map> createInputDataDistribution(Path ou * and the original data. */ private static void createResultingDataForLanduseInZones( - Map> landuseCategoriesPerZone, - Map> investigationAreaData, - Map> resultingDataPerZone, - Map> landuseCategoriesAndDataConnection) { + Map> landuseCategoriesPerZone, + Map> investigationAreaData, + Map> resultingDataPerZone, + Map> landuseCategoriesAndDataConnection, Map zoneIdRegionConnection) { Map> totalSquareMetersPerCategory = new HashMap>(); Map> totalEmployeesInCategoriesPerZone = new HashMap>(); @@ -149,7 +152,7 @@ private static void createResultingDataForLanduseInZones( // connects the collected landuse data with the needed categories for (String zoneId : landuseCategoriesPerZone.keySet()) { - String investigationArea = zoneId.split("_")[0]; + String regionOfZone = zoneIdRegionConnection.get(zoneId); resultingDataPerZone.put(zoneId, new Object2DoubleOpenHashMap<>()); for (String categoryLanduse : landuseCategoriesPerZone.get(zoneId).keySet()) for (String categoryData : landuseCategoriesAndDataConnection.keySet()) { @@ -161,7 +164,7 @@ private static void createResultingDataForLanduseInZones( if (categoryLanduse.equals("commercial")) additionalArea = additionalArea * 0.5; resultingDataPerZone.get(zoneId).mergeDouble(categoryData, additionalArea, Double::sum); - totalSquareMetersPerCategory.get(investigationArea).mergeDouble(categoryData, additionalArea, + totalSquareMetersPerCategory.get(regionOfZone).mergeDouble(categoryData, additionalArea, Double::sum); } } @@ -176,12 +179,12 @@ private static void createResultingDataForLanduseInZones( .forEach(c -> checkPercentages.computeIfAbsent(c, k -> new Object2DoubleOpenHashMap<>())); for (String zoneId : resultingDataPerZone.keySet()) for (String categoryData : resultingDataPerZone.get(zoneId).keySet()) { - String investigationArea = zoneId.split("_")[0]; + String regionOfZone = zoneIdRegionConnection.get(zoneId); double newValue = resultingDataPerZone.get(zoneId).getDouble(categoryData) - / totalSquareMetersPerCategory.get(investigationArea).getDouble(categoryData); + / totalSquareMetersPerCategory.get(regionOfZone).getDouble(categoryData); resultingDataPerZone.get(zoneId).replace(categoryData, resultingDataPerZone.get(zoneId).getDouble(categoryData), newValue); - checkPercentages.get(investigationArea).mergeDouble(categoryData, + checkPercentages.get(regionOfZone).mergeDouble(categoryData, resultingDataPerZone.get(zoneId).getDouble(categoryData), Double::sum); } // tests the result @@ -193,21 +196,21 @@ private static void createResultingDataForLanduseInZones( } // calculates the data per zone and category data for (String zoneId : resultingDataPerZone.keySet()) { - String investigationArea = zoneId.split("_")[0]; + String regionOfZone = zoneIdRegionConnection.get(zoneId); for (String categoryData : resultingDataPerZone.get(zoneId).keySet()) { double percentageValue = resultingDataPerZone.get(zoneId).getDouble(categoryData); - int inputDataForCategory = investigationAreaData.get(investigationArea).get(categoryData); + int inputDataForCategory = investigationAreaData.get(regionOfZone).get(categoryData); double resultingNumberPerCategory = percentageValue * inputDataForCategory; resultingDataPerZone.get(zoneId).replace(categoryData, percentageValue, resultingNumberPerCategory); - totalEmployeesPerCategories.get(investigationArea).mergeDouble(categoryData, resultingNumberPerCategory, + totalEmployeesPerCategories.get(regionOfZone).mergeDouble(categoryData, resultingNumberPerCategory, Double::sum); if (!categoryData.equals("Inhabitants")) - totalEmployeesInCategoriesPerZone.get(investigationArea).mergeDouble(zoneId, + totalEmployeesInCategoriesPerZone.get(regionOfZone).mergeDouble(zoneId, resultingNumberPerCategory, Double::sum); } - if (totalEmployeesInCategoriesPerZone.get(investigationArea).getDouble(zoneId) != 0) + if (totalEmployeesInCategoriesPerZone.get(regionOfZone).getDouble(zoneId) != 0) resultingDataPerZone.get(zoneId).mergeDouble("Employee", - totalEmployeesInCategoriesPerZone.get(investigationArea).getDouble(zoneId), Double::sum); + totalEmployeesInCategoriesPerZone.get(regionOfZone).getDouble(zoneId), Double::sum); } } @@ -216,23 +219,30 @@ private static void createResultingDataForLanduseInZones( * the sum of this category in all zones of the zone shape file */ private static void createLanduseDistribution(Map> landuseCategoriesPerZone, - Index indexLanduse, Index indexZones, String usedLanduseConfiguration, + Index indexLanduse, Index indexZones, Index indexInvestigationAreaRegions, String usedLanduseConfiguration, Index indexBuildings, Map> landuseCategoriesAndDataConnection, Map>> buildingsPerZone, - Map zoneIdNameConnection) { + String shapeFileZoneNameColumn, Map zoneIdRegionConnection) { List neededLanduseCategories = List.of("residential", "industrial", "commercial", "retail", "farmyard", "farmland", "construction"); List landuseFeatures = indexLanduse.getAllFeatures(); List zonesFeatures = indexZones.getAllFeatures(); - - for (SimpleFeature singleZone : zonesFeatures) { - Object2DoubleMap landusePerCategory = new Object2DoubleOpenHashMap<>(); - landuseCategoriesPerZone.put((String) singleZone.getAttribute("areaID"), landusePerCategory); - zoneIdNameConnection.put((String) singleZone.getAttribute("areaID"), - (String) singleZone.getAttribute("name")); + // get the region of the zone + Coord middleCoordOfZone = MGC.point2Coord(((Geometry) singleZone.getDefaultGeometry()).getCentroid()); + String regionName = indexInvestigationAreaRegions.query(middleCoordOfZone); + if (regionName != null) { + Object2DoubleMap landusePerCategory = new Object2DoubleOpenHashMap<>(); + String zoneID = (String) singleZone.getAttribute(shapeFileZoneNameColumn); + var previousValue = landuseCategoriesPerZone.putIfAbsent(zoneID, landusePerCategory); + if (previousValue != null) { + throw new IllegalStateException( + "Key " + zoneID + " already exists in the zone map. This should not happen. Please check if the data in the column " + shapeFileZoneNameColumn + " is unique."); + } + zoneIdRegionConnection.put(zoneID, regionName); + } } if (usedLanduseConfiguration.equals("useOSMBuildingsAndLanduse")) { @@ -279,14 +289,13 @@ private static void createLanduseDistribution(Map> areaData, Path inputDataDirectory) + private static void readAreaData(Map> areaData, Path pathToInvestigationAreaData) throws IOException { - Path areaDataPath = inputDataDirectory.resolve("investigationAreaData.csv"); - if (!Files.exists(areaDataPath)) { - log.error("Required input data file {} not found", areaDataPath); + if (!Files.exists(pathToInvestigationAreaData)) { + log.error("Required input data file {} not found", pathToInvestigationAreaData); } - try (CSVParser parser = new CSVParser(Files.newBufferedReader(areaDataPath), + try (CSVParser parser = new CSVParser(Files.newBufferedReader(pathToInvestigationAreaData), CSVFormat.Builder.create(CSVFormat.TDF).setHeader().setSkipHeaderRecord(true).build())) { for (CSVRecord record : parser) { @@ -295,7 +304,7 @@ private static void readAreaData(Map> areaData, Pat if (parser.getHeaderMap().get(csvRecord) > 0) lookUpTable.put(csvRecord, Integer.valueOf(record.get(csvRecord))); } - areaData.put(record.get("Area"), lookUpTable); + areaData.put(record.get("Region"), lookUpTable); } } } diff --git a/contribs/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..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 @@ -77,52 +77,90 @@ public class SmallScaleCommercialTrafficUtils { /** * Creates and return the Index of the zone shape. * + * @param shapeFileZonePath Path to the shape file of the zones + * @param shapeCRS CRS of the shape file + * @param shapeFileZoneNameColumn Column name of the zone in the shape file * @return indexZones */ - static Index getIndexZones(Path shapeFileZonePath, String shapeCRS) { + static Index getIndexZones(Path shapeFileZonePath, String shapeCRS, String shapeFileZoneNameColumn) { ShpOptions shpZones = new ShpOptions(shapeFileZonePath, shapeCRS, StandardCharsets.UTF_8); - return shpZones.createIndex(shapeCRS, "areaID"); + if (shpZones.readFeatures().iterator().next().getAttribute(shapeFileZoneNameColumn) == null) + throw new NullPointerException("The column '" + shapeFileZoneNameColumn + "' does not exist in the zones shape file. Please check the input."); + return shpZones.createIndex(shapeCRS, shapeFileZoneNameColumn); } /** * Creates and return the Index of the landuse shape. * - * @return indexLanduse + * @param shapeFileLandusePath Path to the shape file of the landuse + * @param shapeCRS CRS of the shape file + * @param shapeFileLanduseTypeColumn Column name of the landuse in the shape file + * @return indexLanduse */ - static Index getIndexLanduse(Path shapeFileLandusePath, String shapeCRS) { - + static Index getIndexLanduse(Path shapeFileLandusePath, String shapeCRS, String shapeFileLanduseTypeColumn) { ShpOptions shpLanduse = new ShpOptions(shapeFileLandusePath, shapeCRS, StandardCharsets.UTF_8); - return shpLanduse.createIndex(shapeCRS, "fclass"); + if (shpLanduse.readFeatures().iterator().next().getAttribute(shapeFileLanduseTypeColumn) == null) + throw new NullPointerException("The column '" + shapeFileLanduseTypeColumn + "' does not exist in the landuse shape file. Please check the input."); + return shpLanduse.createIndex(shapeCRS, shapeFileLanduseTypeColumn); } /** * Creates and return the Index of the building shape. * - * @return indexBuildings + * @param shapeFileBuildingsPath Path to the shape file of the buildings + * @param shapeCRS CRS of the shape file + * @param shapeFileBuildingTypeColumn Column name of the building in the shape file + * @return indexBuildings */ - static Index getIndexBuildings(Path shapeFileBuildingsPath, String shapeCRS) { + static Index getIndexBuildings(Path shapeFileBuildingsPath, String shapeCRS, String shapeFileBuildingTypeColumn) { + ShpOptions shpBuildings = new ShpOptions(shapeFileBuildingsPath, shapeCRS, StandardCharsets.UTF_8); + if (shpBuildings.readFeatures().iterator().next().getAttribute(shapeFileBuildingTypeColumn) == null) + throw new NullPointerException("The column '" + shapeFileBuildingTypeColumn + "' does not exist in the building shape file. Please check the input."); + + return shpBuildings.createIndex(shapeCRS, shapeFileBuildingTypeColumn); + } - ShpOptions shpLanduse = new ShpOptions(shapeFileBuildingsPath, shapeCRS, StandardCharsets.UTF_8); - return shpLanduse.createIndex(shapeCRS, "type"); + /** + * Creates and return the Index of the regions shape. + * + * @param shapeFileRegionsPath Path to the shape file of the regions + * @param shapeCRS CRS of the shape file + * @param regionsShapeRegionColumn Column name of the region in the shape file + * @return indexRegions + */ + public static Index getIndexRegions(Path shapeFileRegionsPath, String shapeCRS, String regionsShapeRegionColumn) { + ShpOptions shpRegions = new ShpOptions(shapeFileRegionsPath, shapeCRS, StandardCharsets.UTF_8); + if (shpRegions.readFeatures().iterator().next().getAttribute(regionsShapeRegionColumn) == null) + throw new NullPointerException("The column '" + regionsShapeRegionColumn + "' does not exist in the region shape file. Please check the input."); + return shpRegions.createIndex(shapeCRS, regionsShapeRegionColumn); } /** * Writes a csv file with the result of the distribution per zone of the input data. */ static void writeResultOfDataDistribution(Map> resultingDataPerZone, - Path outputFileInOutputFolder, Map zoneIdNameConnection) + Path outputFileInOutputFolder, Map zoneIdRegionConnection) throws IOException { - writeCSVWithCategoryHeader(resultingDataPerZone, outputFileInOutputFolder, zoneIdNameConnection); + writeCSVWithCategoryHeader(resultingDataPerZone, outputFileInOutputFolder, zoneIdRegionConnection); log.info("The data distribution is finished and written to: " + outputFileInOutputFolder); } - static Id findNearestPossibleLink(String zone, List noPossibleLinks, Map, Link>> regionLinksMap, + /** Finds the nearest possible link for the building polygon. + * @param zone + * @param noPossibleLinks + * @param linksPerZone + * @param newLink + * @param centroidPointOfBuildingPolygon + * @param numberOfPossibleLinks + * @return + */ + static Id findNearestPossibleLink(String zone, List noPossibleLinks, Map, Link>> linksPerZone, Id newLink, Coord centroidPointOfBuildingPolygon, int numberOfPossibleLinks) { double minDistance = Double.MAX_VALUE; searchLink: - for (Link possibleLink : regionLinksMap.get(zone).values()) { + for (Link possibleLink : linksPerZone.get(zone).values()) { if (possibleLink.getToNode().getOutLinks() == null) continue; if (noPossibleLinks != null && numberOfPossibleLinks > noPossibleLinks.size()) @@ -140,7 +178,7 @@ static Id findNearestPossibleLink(String zone, List noPossibleLink } } if (newLink == null && numberOfPossibleLinks > 0) { - for (Link possibleLink : regionLinksMap.get(zone).values()) { + for (Link possibleLink : linksPerZone.get(zone).values()) { double distance = NetworkUtils.getEuclideanDistance(centroidPointOfBuildingPolygon, (Coord) possibleLink.getAttributes().getAttribute("newCoord")); if (distance < minDistance) { @@ -158,11 +196,11 @@ static Id findNearestPossibleLink(String zone, List noPossibleLink */ private static void writeCSVWithCategoryHeader(Map> resultingDataPerZone, Path outputFileInInputFolder, - Map zoneIdNameConnection) throws MalformedURLException { + Map zoneIdRegionConnection) throws MalformedURLException { BufferedWriter writer = IOUtils.getBufferedWriter(outputFileInInputFolder.toUri().toURL(), StandardCharsets.UTF_8, true); try { - String[] header = new String[]{"areaID", "areaName", "Inhabitants", "Employee", "Employee Primary Sector", + String[] header = new String[]{"zoneID", "region", "Inhabitants", "Employee", "Employee Primary Sector", "Employee Construction", "Employee Secondary Sector Rest", "Employee Retail", "Employee Traffic/Parcels", "Employee Tertiary Sector Rest"}; JOIN.appendTo(writer, header); @@ -170,9 +208,9 @@ private static void writeCSVWithCategoryHeader(Map row = new ArrayList<>(); row.add(zone); - row.add(zoneIdNameConnection.get(zone)); + row.add(zoneIdRegionConnection.get(zone)); for (String category : header) { - if (!category.equals("areaID") && !category.equals("areaName")) + if (!category.equals("zoneID") && !category.equals("region")) row.add(String.valueOf((int) Math.round(resultingDataPerZone.get(zone).getDouble(category)))); } JOIN.appendTo(writer, row); @@ -189,7 +227,6 @@ private static void writeCSVWithCategoryHeader(Map vehicleId = Id.createVehicleId(person.getId().toString()); - VehicleUtils.insertVehicleIdsIntoAttributes(newPerson, Map.of(mode, vehicleId)); - VehicleUtils.insertVehicleTypesIntoAttributes(newPerson, Map.of(mode, allVehicles.getVehicles().get(vehicleId).getType().getId())); + VehicleUtils.insertVehicleIdsIntoPersonAttributes(newPerson, Map.of(mode, vehicleId)); + VehicleUtils.insertVehicleTypesIntoPersonAttributes(newPerson, Map.of(mode, allVehicles.getVehicles().get(vehicleId).getType().getId())); population.addPerson(newPerson); } @@ -297,7 +334,7 @@ static String getSampleNameOfOutputFolder(double sample) { * dispersedTraffic will be added additionally. */ static void readExistingModels(Scenario scenario, double sampleScenario, - Map, Link>> regionLinksMap) throws Exception { + Map, Link>> linksPerZone) throws Exception { Path existingModelsFolder = Path.of(scenario.getConfig().getContext().toURI()).getParent().resolve("existingModels"); String locationOfExistingModels = existingModelsFolder.resolve("existingModels.csv").toString(); @@ -498,7 +535,7 @@ else if (!carrier.getShipments().isEmpty()) List startAreas = new ArrayList<>(); for (ScheduledTour tour : newCarrier.getSelectedPlan().getScheduledTours()) { - String tourStartZone = findZoneOfLink(tour.getTour().getStartLinkId(), regionLinksMap); + String tourStartZone = findZoneOfLink(tour.getTour().getStartLinkId(), linksPerZone); if (!startAreas.contains(tourStartZone)) startAreas.add(tourStartZone); } @@ -526,9 +563,9 @@ else if (!carrier.getShipments().isEmpty()) /** * Find the zone where the link is located */ - static String findZoneOfLink(Id linkId, Map, Link>> regionLinksMap) { - for (String area : regionLinksMap.keySet()) { - if (regionLinksMap.get(area).containsKey(linkId)) + static String findZoneOfLink(Id linkId, Map, Link>> linksPerZone) { + for (String area : linksPerZone.keySet()) { + if (linksPerZone.get(area).containsKey(linkId)) return area; } return null; diff --git a/contribs/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 a4633cfaf10..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 @@ -221,7 +221,7 @@ private static void writeCSVTrafficVolume(Map, Link>> regionLinksMap, String smallScaleCommercialTrafficType, + Map, Link>> linksPerZone, String smallScaleCommercialTrafficType, Map> trafficVolumePerTypeAndZone_start, Map> trafficVolumePerTypeAndZone_stop) { @@ -290,11 +290,11 @@ static void reduceDemandBasedOnExistingCarriers(Scenario scenario, if (carrier.getSelectedPlan() != null) { for (ScheduledTour tour : carrier.getSelectedPlan().getScheduledTours()) { String startZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(tour.getTour().getStartLinkId(), - regionLinksMap); + linksPerZone); for (TourElement tourElement : tour.getTour().getTourElements()) { if (tourElement instanceof ServiceActivity service) { String stopZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(service.getLocation(), - regionLinksMap); + linksPerZone); try { reduceVolumeForThisExistingJobElement(trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, modeORvehType, purpose, startZone, stopZone); @@ -306,9 +306,9 @@ static void reduceDemandBasedOnExistingCarriers(Scenario scenario, } if (tourElement instanceof Pickup pickup) { startZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(pickup.getShipment().getFrom(), - regionLinksMap); + linksPerZone); String stopZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(pickup.getShipment().getTo(), - regionLinksMap); + linksPerZone); try { reduceVolumeForThisExistingJobElement(trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, modeORvehType, purpose, startZone, stopZone); @@ -325,13 +325,13 @@ static void reduceDemandBasedOnExistingCarriers(Scenario scenario, List possibleStartAreas = new ArrayList<>(); for (CarrierVehicle vehicle : carrier.getCarrierCapabilities().getCarrierVehicles().values()) { possibleStartAreas - .add(SmallScaleCommercialTrafficUtils.findZoneOfLink(vehicle.getLinkId(), regionLinksMap)); + .add(SmallScaleCommercialTrafficUtils.findZoneOfLink(vehicle.getLinkId(), linksPerZone)); } for (CarrierService service : carrier.getServices().values()) { String startZone = (String) possibleStartAreas.toArray()[MatsimRandom.getRandom() .nextInt(possibleStartAreas.size())]; String stopZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(service.getLocationLinkId(), - regionLinksMap); + linksPerZone); try { reduceVolumeForThisExistingJobElement(trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, modeORvehType, purpose, startZone, stopZone); @@ -344,9 +344,9 @@ static void reduceDemandBasedOnExistingCarriers(Scenario scenario, } else if (!carrier.getShipments().isEmpty()) { for (CarrierShipment shipment : carrier.getShipments().values()) { String startZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(shipment.getFrom(), - regionLinksMap); + linksPerZone); String stopZone = SmallScaleCommercialTrafficUtils.findZoneOfLink(shipment.getTo(), - regionLinksMap); + linksPerZone); try { reduceVolumeForThisExistingJobElement(trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, modeORvehType, purpose, startZone, stopZone); 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 ce06aa2b34c..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 @@ -284,23 +284,24 @@ private TripDistributionMatrix(Builder builder) { * Calculates the traffic volume between two zones for a specific modeORvehType * and purpose. * - * @param startZone start zone - * @param stopZone stop zone - * @param modeORvehType selected mode or vehicle type - * @param purpose selected purpose + * @param startZone start zone + * @param stopZone stop zone + * @param modeORvehType selected mode or vehicle type + * @param purpose selected purpose * @param smallScaleCommercialTrafficType goodsTraffic or commercialPersonTraffic - * @param regionLinksMap links in each zone + * @param linksPerZone links in each zone + * @param shapeFileZoneNameColumn Name of the unique column of the name/Id of each zone in the zones shape file */ void setTripDistributionValue(String startZone, String stopZone, String modeORvehType, Integer purpose, String smallScaleCommercialTrafficType, Network network, - Map, Link>> regionLinksMap, double resistanceFactor) { + Map, Link>> linksPerZone, double resistanceFactor, String shapeFileZoneNameColumn) { double volumeStart = trafficVolume_start.get(TrafficVolumeGeneration.makeTrafficVolumeKey(startZone, modeORvehType)).getDouble(purpose); double volumeStop = trafficVolume_stop.get(TrafficVolumeGeneration.makeTrafficVolumeKey(stopZone, modeORvehType)).getDouble(purpose); int roundedVolume; if (volumeStart != 0 && volumeStop != 0) { - double resistanceValue = getResistanceFunktionValue(startZone, stopZone, network, regionLinksMap, resistanceFactor); - double gravityConstantA = getGravityConstant(stopZone, trafficVolume_start, modeORvehType, purpose, network, regionLinksMap, - resistanceFactor); + double resistanceValue = getResistanceFunktionValue(startZone, stopZone, network, linksPerZone, resistanceFactor, shapeFileZoneNameColumn); + double gravityConstantA = getGravityConstant(stopZone, trafficVolume_start, modeORvehType, purpose, network, linksPerZone, + resistanceFactor, shapeFileZoneNameColumn); roundingError.computeIfAbsent(stopZone, (k) -> new Object2DoubleOpenHashMap<>()); //Bisher: Gravity model mit fixem Zielverkehr @@ -336,11 +337,13 @@ Integer getTripDistributionValue(String startZone, String stopZone, String modeO /** * Calculates the values of the resistance function between two zones. * - * @param startZone start zone - * @param stopZone stop zone - * @param regionLinksMap links for each zone + * @param startZone start zone + * @param stopZone stop zone + * @param linksPerZone links for each zone + * @param shapeFileZoneNameColumn Name of the unique column of the name/Id of each zone in the zones shape file */ - private Double getResistanceFunktionValue(String startZone, String stopZone, Network network, Map, Link>> regionLinksMap, double resistanceFactor) { + private Double getResistanceFunktionValue(String startZone, String stopZone, Network network, Map, Link>> linksPerZone, + double resistanceFactor, String shapeFileZoneNameColumn) { //if false the calculation is faster; e.g. for debugging boolean useNetworkRoutesForResistanceFunction = true; @@ -353,11 +356,11 @@ private Double getResistanceFunktionValue(String startZone, String stopZone, Net } if (!resistanceFunktionCache.containsKey(makeResistanceFunktionKey(startZone, stopZone))) for (SimpleFeature startZoneFeature : zonesFeatures) { - String zone1 = String.valueOf(startZoneFeature.getAttribute("areaID")); + String zone1 = String.valueOf(startZoneFeature.getAttribute(shapeFileZoneNameColumn)); if (!startZone.equals(zone1)) continue; for (SimpleFeature stopZoneFeature : zonesFeatures) { - String zone2 = String.valueOf(stopZoneFeature.getAttribute("areaID")); + String zone2 = String.valueOf(stopZoneFeature.getAttribute(shapeFileZoneNameColumn)); if (!stopZone.equals(zone2)) continue; double distance = Double.MAX_VALUE; @@ -368,8 +371,8 @@ private Double getResistanceFunktionValue(String startZone, String stopZone, Net } else { if (useNetworkRoutesForResistanceFunction) { - Location startLocation = Location.newInstance(regionLinksMap.get(startZone).keySet().iterator().next().toString()); - Location stopLocation = Location.newInstance(regionLinksMap.get(stopZone).keySet().iterator().next().toString()); + Location startLocation = Location.newInstance(linksPerZone.get(startZone).keySet().iterator().next().toString()); + Location stopLocation = Location.newInstance(linksPerZone.get(stopZone).keySet().iterator().next().toString()); Vehicle exampleVehicle = getExampleVehicle(startLocation); // distance = netBasedCosts.getDistance(startLocation, stopLocation, 21600., exampleVehicle); travelCosts = netBasedCosts.getTransportCost(startLocation, stopLocation, 21600., null, exampleVehicle); @@ -443,16 +446,17 @@ private VehicleImpl getExampleVehicle(Location fromId) { /** * Calculates the gravity constant. * - * @param baseZone base zone - * @param trafficVolume volume of the traffic - * @param modeORvehType selected mode or vehicle type - * @param purpose selected purpose - * @param regionLinksMap links for each zone + * @param baseZone base zone + * @param trafficVolume volume of the traffic + * @param modeORvehType selected mode or vehicle type + * @param purpose selected purpose + * @param linksPerZone links for each zone + * @param shapeFileZoneNameColumn Name of the unique column of the name/Id of each zone in the zones shape file * @return gravity constant */ private double getGravityConstant(String baseZone, Map> trafficVolume, String modeORvehType, - Integer purpose, Network network, Map, Link>> regionLinksMap, double resistanceFactor) { + Integer purpose, Network network, Map, Link>> linksPerZone, double resistanceFactor, String shapeFileZoneNameColumn) { GravityConstantKey gravityKey = makeGravityKey(baseZone, modeORvehType, purpose); if (!gravityConstantACache.containsKey(gravityKey)) { @@ -464,7 +468,7 @@ private double getGravityConstant(String baseZone, continue; else { double resistanceValue = getResistanceFunktionValue(baseZone, trafficVolumeKey.getZone(), network, - regionLinksMap, resistanceFactor); + linksPerZone, resistanceFactor, shapeFileZoneNameColumn); sum = sum + (volume * resistanceValue); } } @@ -601,7 +605,7 @@ void writeODMatrices(Path output, String smallScaleCommercialTrafficType) throws try { List headerRow = new ArrayList<>(); - headerRow.add(""); + headerRow.add("O/D"); headerRow.addAll(usedZones); JOIN.appendTo(writer, headerRow); writer.write("\n"); diff --git a/contribs/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..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 @@ -51,18 +51,22 @@ void testReadOfDataDistributionPerZoneAndBuildingAnalysis() throws IOException { assert(new File(output.resolve("calculatedData").toString()).mkdir()); Path inputDataDirectory = Path.of(utils.getPackageInputDirectory()); String usedLanduseConfiguration = "useExistingDataDistribution"; - + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); // Test if the reading of the existing data distribution works correctly + Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); Assertions.assertEquals(3, resultingDataPerZone.size(), MatsimTestUtils.EPSILON); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea1_area1")); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea1_area2")); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea2_area3")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area1")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area2")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area3")); for (String zone : resultingDataPerZone.keySet()) { Object2DoubleMap categories = resultingDataPerZone.get(zone); @@ -86,60 +90,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 +157,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 +192,7 @@ void testReadOfDataDistributionPerZoneAndBuildingAnalysis() throws IOException { Assertions.assertEquals(6, builingsPerArea1.get("Employee").size(), MatsimTestUtils.EPSILON); // test for area2 - Map> builingsPerArea2 = buildingsPerZone.get("testArea1_area2"); + Map> builingsPerArea2 = buildingsPerZone.get("area2"); Assertions.assertEquals(8, builingsPerArea2.size(), MatsimTestUtils.EPSILON); List employeeRetail = builingsPerArea2.get("Employee Retail"); Assertions.assertEquals(2, employeeRetail.size(), MatsimTestUtils.EPSILON); @@ -208,7 +216,7 @@ void testReadOfDataDistributionPerZoneAndBuildingAnalysis() throws IOException { Assertions.assertEquals(8, builingsPerArea2.get("Employee").size(), MatsimTestUtils.EPSILON); // test for area3 - Map> builingsPerArea3 = buildingsPerZone.get("testArea2_area3"); + Map> builingsPerArea3 = buildingsPerZone.get("area3"); Assertions.assertEquals(8, builingsPerArea3.size(), MatsimTestUtils.EPSILON); List tertiaryRetail = builingsPerArea3.get("Employee Tertiary Sector Rest"); Assertions.assertEquals(1, tertiaryRetail.size(), MatsimTestUtils.EPSILON); @@ -238,18 +246,20 @@ void testLanduseDistribution() throws IOException { assert(new File(output.resolve("calculatedData").toString()).mkdir()); Path inputDataDirectory = Path.of(utils.getPackageInputDirectory()); String usedLanduseConfiguration = "useOSMBuildingsAndLanduse"; - + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); // Analyze resultingData per zone Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, null); Assertions.assertEquals(3, resultingDataPerZone.size(), MatsimTestUtils.EPSILON); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea1_area1")); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea1_area2")); - Assertions.assertTrue(resultingDataPerZone.containsKey("testArea2_area3")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area1")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area2")); + Assertions.assertTrue(resultingDataPerZone.containsKey("area3")); for (String zone : resultingDataPerZone.keySet()) { Object2DoubleMap categories = resultingDataPerZone.get(zone); @@ -273,60 +283,63 @@ void testLanduseDistribution() throws IOException { Assertions.assertEquals(categories.getDouble("Employee"), employeeSum, MatsimTestUtils.EPSILON); - if (zone.equals("testArea1_area1")) { - Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(3500, resultingDataPerZone.get(zone).getDouble("Employee"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(0, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Retail"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), - MatsimTestUtils.EPSILON); - } - if (zone.equals("testArea1_area2")) { - Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(6500, resultingDataPerZone.get(zone).getDouble("Employee"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Retail"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(2000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), - MatsimTestUtils.EPSILON); - } - if (zone.equals("testArea2_area3")) { - Assertions.assertEquals(800, resultingDataPerZone.get(zone).getDouble("Inhabitants"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(50, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Construction"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(100, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(150, resultingDataPerZone.get(zone).getDouble("Employee Retail"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), - MatsimTestUtils.EPSILON); - Assertions.assertEquals(300, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), - MatsimTestUtils.EPSILON); - } + switch (zone) { + case "area1" -> { + Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(3500, resultingDataPerZone.get(zone).getDouble("Employee"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(0, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Retail"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), + MatsimTestUtils.EPSILON); + } + case "area2" -> { + Assertions.assertEquals(4000, resultingDataPerZone.get(zone).getDouble("Inhabitants"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(6500, resultingDataPerZone.get(zone).getDouble("Employee"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Construction"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(500, resultingDataPerZone.get(zone).getDouble("Employee Retail"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1500, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(2000, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), + MatsimTestUtils.EPSILON); + } + case "area3" -> { + Assertions.assertEquals(800, resultingDataPerZone.get(zone).getDouble("Inhabitants"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(1000, resultingDataPerZone.get(zone).getDouble("Employee"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(50, resultingDataPerZone.get(zone).getDouble("Employee Primary Sector"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Construction"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(100, resultingDataPerZone.get(zone).getDouble("Employee Secondary Sector Rest"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(150, resultingDataPerZone.get(zone).getDouble("Employee Retail"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(200, resultingDataPerZone.get(zone).getDouble("Employee Traffic/Parcels"), + MatsimTestUtils.EPSILON); + Assertions.assertEquals(300, resultingDataPerZone.get(zone).getDouble("Employee Tertiary Sector Rest"), + MatsimTestUtils.EPSILON); + } + default -> Assertions.fail("Zone not found"); + } } } } diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java index d88d2318fd1..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 @@ -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,19 @@ 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 org.matsim.utils.eventsfilecomparison.ComparisonResult; +import java.io.BufferedReader; import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; /** @@ -50,30 +61,44 @@ 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"; String creationOption = "createNewCarrierFile"; String landuseConfiguration = "useExistingDataDistribution"; String smallScaleCommercialTrafficType = "commercialPersonTraffic"; + String regionsShapeFileName = utils.getPackageInputDirectory() + "/shp/testRegions.shp"; + String regionsShapeRegionColumn = "region"; String zoneShapeFileName = utils.getPackageInputDirectory() + "/shp/testZones.shp"; + String zoneShapeFileNameColumn = "name"; String buildingsShapeFileName = utils.getPackageInputDirectory() + "/shp/testBuildings.shp"; + String shapeFileBuildingTypeColumn = "type"; String landuseShapeFileName = utils.getPackageInputDirectory() + "/shp/testLanduse.shp"; + String shapeFileLanduseTypeColumn = "fclass"; String shapeCRS = "EPSG:4326"; String resultPopulation = "testPopulation.xml.gz"; new GenerateSmallScaleCommercialTrafficDemand().execute( - inputDataDirectory, + pathToConfig, + "--pathToInvestigationAreaData", pathToInvestigationAreaData.toString(), + "--pathToExistingDataDistributionToZones", pathToExistingDataDistributionToZones.toString(), "--sample", sample, "--jspritIterations", jspritIterations, "--creationOption", creationOption, "--landuseConfiguration", landuseConfiguration, "--smallScaleCommercialTrafficType", smallScaleCommercialTrafficType, "--includeExistingModels", + "--regionsShapeFileName", regionsShapeFileName, + "--regionsShapeRegionColumn", regionsShapeRegionColumn, "--zoneShapeFileName", zoneShapeFileName, + "--zoneShapeFileNameColumn", zoneShapeFileNameColumn, "--buildingsShapeFileName", buildingsShapeFileName, + "--shapeFileBuildingTypeColumn", shapeFileBuildingTypeColumn, "--landuseShapeFileName", landuseShapeFileName, + "--shapeFileLanduseTypeColumn", shapeFileLanduseTypeColumn, "--shapeCRS", shapeCRS, "--nameOutputPopulation", resultPopulation, "--pathOutput", output); @@ -109,17 +134,65 @@ 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()); + 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 ); + ComparisonResult result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( ComparisonResult.FILES_ARE_EQUAL, result ); + } + + /** + * Reads a CSV file and creates a map with the first column as key and the rest as a map with the header as key and the value as value + * + * @param calculatedFile the file to read + * @return + */ + private static Map> readCSVInputAndCreateMap(String calculatedFile) { + Map> dataDistribution = new HashMap<>(); + try (BufferedReader reader = IOUtils.getBufferedReader(calculatedFile)) { + CSVParser parse = CSVFormat.Builder.create(CSVFormat.DEFAULT).setDelimiter('\t').setHeader() + .setSkipHeaderRecord(true).build().parse(reader); + for (CSVRecord record : parse) { + System.out.println(record); + dataDistribution.computeIfAbsent(record.get(0), k -> new Object2DoubleOpenHashMap<>()); + for (int i = 1; i < record.size(); i++) { + if (i == 1 && (calculatedFile.contains("dataDistributionPerZone") || calculatedFile.contains("TrafficVolume_"))) + continue; + dataDistribution.get(record.get(0)).put(parse.getHeaderNames().get(i), Double.parseDouble(record.get(i))); + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return dataDistribution; + } + + /** + * Compares the data distribution of two files + * + * @param calculatedFile the file to compare + * @param existingDataDistribution the existing data distribution + * @param simulatedDataDistribution the simulated data distribution + */ + private void compareDataDistribution(String calculatedFile, Map> existingDataDistribution, + Map> simulatedDataDistribution) { + Assertions.assertEquals(existingDataDistribution.size(), simulatedDataDistribution.size()); + for (String key : existingDataDistribution.keySet()) { + Object2DoubleMap existingMap = existingDataDistribution.get(key); + Object2DoubleMap simulatedMap = simulatedDataDistribution.get(key); + for (String subKey : existingMap.keySet()) { + Assertions.assertEquals(existingMap.getDouble(subKey), simulatedMap.getDouble(subKey), + "File: " + calculatedFile + "; Expected: " + existingMap.getDouble(subKey) + " but was: " + simulatedMap.getDouble( + subKey) + " for key: " + key + " and subKey: " + subKey); + } + } } } diff --git a/contribs/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..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 @@ -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()), - buildingsPerZone); + .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem(), + shapeFileZoneNameColumn), + buildingsPerZone, shapeFileZoneNameColumn); 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..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 @@ -60,11 +60,15 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { assert(new File(output.resolve("calculatedData").toString()).mkdir()); Path inputDataDirectory = Path.of(utils.getPackageInputDirectory()); String usedLanduseConfiguration = "useExistingDataDistribution"; + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "commercialPersonTraffic"; @@ -86,7 +90,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertTrue(trafficVolumePerTypeAndZone_start.containsKey(trafficVolumeKey)); Assertions.assertTrue(trafficVolumePerTypeAndZone_stop.containsKey(trafficVolumeKey)); } - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area1", modesORvehTypes.get(0)); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area1", modesORvehTypes.get(0)); Assertions.assertEquals(30, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(124, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(277, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -99,7 +103,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertEquals(121, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(65, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area2", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area2", modesORvehTypes.get(0)); Assertions.assertEquals(30, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(211, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(514, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -112,7 +116,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertEquals(246, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(102, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea2_area3", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area3", modesORvehTypes.get(0)); Assertions.assertEquals(6, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(34, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(79, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -136,7 +140,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertEquals(3, trafficVolumePerTypeAndZone_start.size()); Assertions.assertEquals(3, trafficVolumePerTypeAndZone_stop.size()); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area1", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area1", modesORvehTypes.get(0)); Assertions.assertEquals(7, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(31, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(69, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -149,7 +153,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertEquals(30, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(16, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area2", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area2", modesORvehTypes.get(0)); Assertions.assertEquals(7, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(53, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(129, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -162,7 +166,7 @@ void testTrafficVolumeGenerationCommercialPersonTraffic() throws IOException { Assertions.assertEquals(61, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(25, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea2_area3", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area3", modesORvehTypes.get(0)); Assertions.assertEquals(1, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(8, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); Assertions.assertEquals(20, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -186,11 +190,15 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { assert(new File(output.resolve("calculatedData").toString()).mkdir()); Path inputDataDirectory = Path.of(utils.getPackageInputDirectory()); String usedLanduseConfiguration = "useExistingDataDistribution"; + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "goodsTraffic"; double sample = 1.; @@ -214,7 +222,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { } } - // test for "testArea1_area1" + // test for "area1" HashMap estimatesStart = new HashMap<>(); estimatesStart.put(1, 12.); estimatesStart.put(2, 30.); @@ -234,7 +242,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area1", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area1", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); if (modeORvehType.equals("vehTyp1")) { @@ -317,7 +325,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { Assertions.assertEquals(estimatesStop.get(i), sumStop, MatsimTestUtils.EPSILON); } - // test for "testArea1_area2" + // test for "area2" estimatesStart = new HashMap<>(); estimatesStart.put(1, 12.); estimatesStart.put(2, 37.); @@ -337,7 +345,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area2", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area2", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); } @@ -345,7 +353,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { Assertions.assertEquals(estimatesStop.get(i), sumStop, MatsimTestUtils.EPSILON); } - // test for "testArea2_area3" + // test for "area3" estimatesStart = new HashMap<>(); estimatesStart.put(1, 2.); estimatesStart.put(2, 7.); @@ -365,7 +373,7 @@ void testTrafficVolumeGenerationGoodsTraffic() throws IOException { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea2_area3", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area3", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); } @@ -388,10 +396,12 @@ 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()), - buildingsPerZone); + .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem(), + shapeFileZoneNameColumn), + buildingsPerZone, shapeFileZoneNameColumn); SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); @@ -414,7 +424,7 @@ void testAddingExistingScenarios() throws Exception { Assertions.assertEquals("exampleServiceCarrier", addedCarrier1.getAttributes().getAttribute("existingModel")); Assertions.assertEquals("car", addedCarrier1.getAttributes().getAttribute("networkMode")); Assertions.assertNull(addedCarrier1.getAttributes().getAttribute("vehicleType")); - Assertions.assertEquals("testArea2_area3", addedCarrier1.getAttributes().getAttribute("tourStartArea")); + Assertions.assertEquals("area3", addedCarrier1.getAttributes().getAttribute("tourStartArea")); Carrier addedCarrier2 = CarriersUtils.getCarriers(scenario).getCarriers().get(Id.create("exampleServiceCarrier_carrier2", Carrier.class)); Assertions.assertNotNull(addedCarrier2.getSelectedPlan()); @@ -428,7 +438,7 @@ void testAddingExistingScenarios() throws Exception { Assertions.assertEquals("exampleServiceCarrier", addedCarrier2.getAttributes().getAttribute("existingModel")); Assertions.assertEquals("car", addedCarrier2.getAttributes().getAttribute("networkMode")); Assertions.assertNull(addedCarrier2.getAttributes().getAttribute("vehicleType")); - Assertions.assertEquals("testArea2_area3", addedCarrier2.getAttributes().getAttribute("tourStartArea")); + Assertions.assertEquals("area3", addedCarrier2.getAttributes().getAttribute("tourStartArea")); Carrier addedCarrier3 = CarriersUtils.getCarriers(scenario).getCarriers().get(Id.create("exampleShipmentCarrier_carrier1", Carrier.class)); Assertions.assertNull(addedCarrier3.getSelectedPlan()); @@ -447,6 +457,8 @@ void testAddingExistingScenariosWithSample() throws Exception { Path shapeFileZonePath = inputDataDirectory.resolve("shp/testZones.shp"); String networkPath = "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"; double sample = 0.2; + String shapeFileZoneNameColumn = "name"; + Config config = ConfigUtils.createConfig(); config.global().setCoordinateSystem("EPSG:4326"); config.network().setInputFile(networkPath); @@ -455,8 +467,9 @@ 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()), - buildingsPerZone); + .filterLinksForZones(scenario, SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, config.global().getCoordinateSystem(), + shapeFileZoneNameColumn), + buildingsPerZone, shapeFileZoneNameColumn); SmallScaleCommercialTrafficUtils.readExistingModels(scenario, sample, regionLinksMap); @@ -478,7 +491,7 @@ void testAddingExistingScenariosWithSample() throws Exception { Assertions.assertEquals("exampleServiceCarrier", addedCarrier1.getAttributes().getAttribute("existingModel")); Assertions.assertEquals("car", addedCarrier1.getAttributes().getAttribute("networkMode")); Assertions.assertNull(addedCarrier1.getAttributes().getAttribute("vehicleType")); - Assertions.assertEquals("testArea2_area3", addedCarrier1.getAttributes().getAttribute("tourStartArea")); + Assertions.assertEquals("area3", addedCarrier1.getAttributes().getAttribute("tourStartArea")); Carrier addedCarrier3 = CarriersUtils.getCarriers(scenario).getCarriers().get(Id.create("exampleShipmentCarrier_carrier1", Carrier.class)); Assertions.assertNull(addedCarrier3.getSelectedPlan()); @@ -502,6 +515,10 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { String networkPath = "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"; String usedTrafficType = "goodsTraffic"; double sample = 1.; + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); + ArrayList modesORvehTypes = new ArrayList<>( Arrays.asList("vehTyp1", "vehTyp2", "vehTyp3", "vehTyp4", "vehTyp5")); Config config = ConfigUtils.createConfig(); @@ -514,8 +531,9 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); Map> trafficVolumePerTypeAndZone_start = TrafficVolumeGeneration .createTrafficVolume_start(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); @@ -523,14 +541,14 @@ 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); 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 +568,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area1", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area1", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); if (modeORvehType.equals("vehTyp3")) { @@ -573,7 +591,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { Assertions.assertEquals(estimatesStop.get(i), sumStop, MatsimTestUtils.EPSILON); } - // test for "testArea1_area2" + // test for "area2" estimatesStart = new HashMap<>(); estimatesStart.put(1, 12.); estimatesStart.put(2, 37.); @@ -593,7 +611,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area2", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area2", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); } @@ -601,7 +619,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { Assertions.assertEquals(estimatesStop.get(i), sumStop, MatsimTestUtils.EPSILON); } - // test for "testArea2_area3" + // test for "area3" estimatesStart = new HashMap<>(); estimatesStart.put(1, 2.); estimatesStart.put(2, 7.); @@ -621,7 +639,7 @@ void testReducingDemandAfterAddingExistingScenarios_goods() throws Exception { double sumStart = 0; double sumStop = 0; for (String modeORvehType : modesORvehTypes) { - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea2_area3", modeORvehType); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area3", modeORvehType); sumStart += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(i); sumStop += trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(i); if (modeORvehType.equals("vehTyp3")) { @@ -657,6 +675,10 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th String networkPath = "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"; String usedTrafficType = "commercialPersonTraffic"; double sample = 1.; + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); + ArrayList modesORvehTypes = new ArrayList<>( List.of("total")); Config config = ConfigUtils.createConfig(); @@ -669,8 +691,9 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + SCTUtils.getIndexLanduse(inputDataDirectory), SCTUtils.getZoneIndex(inputDataDirectory), SCTUtils.getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); Map> trafficVolumePerTypeAndZone_start = TrafficVolumeGeneration .createTrafficVolume_start(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); @@ -678,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); @@ -688,7 +711,7 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th //because the reduction of the start volume in zone3 (purpose 2) is higher than the value, a start reduction will be distributed over other zones double sumOfStartOtherAreas = 0; - TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area1", modesORvehTypes.get(0)); + TrafficVolumeKey trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area1", modesORvehTypes.get(0)); Assertions.assertEquals(30, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); sumOfStartOtherAreas += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2); Assertions.assertEquals(277, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -701,7 +724,7 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th Assertions.assertEquals(121, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(65, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea1_area2", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area2", modesORvehTypes.get(0)); Assertions.assertEquals(30, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); sumOfStartOtherAreas += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2); Assertions.assertEquals(514, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(3), MatsimTestUtils.EPSILON); @@ -714,7 +737,7 @@ void testReducingDemandAfterAddingExistingScenarios_commercialPersonTraffic() th Assertions.assertEquals(246, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(4), MatsimTestUtils.EPSILON); Assertions.assertEquals(102, trafficVolumePerTypeAndZone_stop.get(trafficVolumeKey).getDouble(5), MatsimTestUtils.EPSILON); - trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("testArea2_area3", modesORvehTypes.get(0)); + trafficVolumeKey = TrafficVolumeGeneration.makeTrafficVolumeKey("area3", modesORvehTypes.get(0)); Assertions.assertEquals(6, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(1), MatsimTestUtils.EPSILON); Assertions.assertEquals(0, trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2), MatsimTestUtils.EPSILON); sumOfStartOtherAreas += trafficVolumePerTypeAndZone_start.get(trafficVolumeKey).getDouble(2); diff --git a/contribs/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 0cf215c836c..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 @@ -59,10 +59,15 @@ void testTripDistributionCommercialPersonTrafficTraffic() throws IOException { String usedLanduseConfiguration = "useExistingDataDistribution"; String networkLocation = "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"; Network network = NetworkUtils.readNetwork(networkLocation); + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); + Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "commercialPersonTraffic"; double sample = 1.; @@ -75,18 +80,18 @@ void testTripDistributionCommercialPersonTrafficTraffic() throws IOException { .createTrafficVolume_start(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); Map> trafficVolumePerTypeAndZone_stop = TrafficVolumeGeneration .createTrafficVolume_stop(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); - ArrayList listOfZones = new ArrayList<>( List.of("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(); 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()) { @@ -94,7 +99,7 @@ void testTripDistributionCommercialPersonTrafficTraffic() throws IOException { for (Integer purpose : trafficVolumePerTypeAndZone_start .get(TrafficVolumeGeneration.makeTrafficVolumeKey(startZone, modeORvehType)).keySet()) { odMatrix.setTripDistributionValue(startZone, stopZone, modeORvehType, purpose, usedTrafficType, - network, regionLinksMap, resistanceFactor); + network, regionLinksMap, resistanceFactor, shapeFileZoneNameColumn); } } } @@ -146,10 +151,14 @@ void testTripDistributionGoodsTraffic() throws IOException { String usedLanduseConfiguration = "useExistingDataDistribution"; String networkLocation = "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"; Network network = NetworkUtils.readNetwork(networkLocation); + String shapeFileZoneNameColumn = "name"; + Path pathToInvestigationAreaData = Path.of(utils.getPackageInputDirectory()).resolve("investigationAreaData.csv"); + Path pathToExistingDataDistributionToZones = Path.of(utils.getPackageInputDirectory()).resolve("dataDistributionPerZone.csv"); Map> resultingDataPerZone = LanduseBuildingAnalysis .createInputDataDistribution(output, landuseCategoriesAndDataConnection, - inputDataDirectory, usedLanduseConfiguration, - getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), buildingsPerZone); + usedLanduseConfiguration, + getIndexLanduse(inputDataDirectory), getZoneIndex(inputDataDirectory), getIndexBuildings(inputDataDirectory), + SCTUtils.getIndexRegions(inputDataDirectory), shapeFileZoneNameColumn, buildingsPerZone, pathToInvestigationAreaData, pathToExistingDataDistributionToZones); String usedTrafficType = "goodsTraffic"; double sample = 1.; @@ -157,7 +166,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); @@ -170,12 +179,12 @@ void testTripDistributionGoodsTraffic() throws IOException { listOfZones).build(); Map, Link>> regionLinksMap = new HashMap<>(); - regionLinksMap.put("testArea1_area1", new HashMap<>()); - regionLinksMap.get("testArea1_area1").put(Id.createLinkId("i(8,6)"), network.getLinks().get(Id.createLinkId("i(8,6)"))); - regionLinksMap.put("testArea1_area2", new HashMap<>()); - regionLinksMap.get("testArea1_area2").put(Id.createLinkId("i(2,7)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); - regionLinksMap.put("testArea2_area3", new HashMap<>()); - regionLinksMap.get("testArea2_area3").put(Id.createLinkId("i(2,1)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); + regionLinksMap.put("area1", new HashMap<>()); + regionLinksMap.get("area1").put(Id.createLinkId("i(8,6)"), network.getLinks().get(Id.createLinkId("i(8,6)"))); + regionLinksMap.put("area2", new HashMap<>()); + regionLinksMap.get("area2").put(Id.createLinkId("i(2,7)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); + regionLinksMap.put("area3", new HashMap<>()); + regionLinksMap.get("area3").put(Id.createLinkId("i(2,1)R"), network.getLinks().get(Id.createLinkId("i(2,7)R"))); for (String startZone : resultingDataPerZone.keySet()) { for (String stopZone : resultingDataPerZone.keySet()) { @@ -183,7 +192,7 @@ void testTripDistributionGoodsTraffic() throws IOException { for (Integer purpose : trafficVolumePerTypeAndZone_start .get(TrafficVolumeGeneration.makeTrafficVolumeKey(startZone, modeORvehType)).keySet()) { odMatrix.setTripDistributionValue(startZone, stopZone, modeORvehType, purpose, usedTrafficType, - network, regionLinksMap, resistanceFactor); + network, regionLinksMap, resistanceFactor, shapeFileZoneNameColumn); } } } diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_startPerZone_10pt.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_startPerZone_10pt.csv index bfdf8e63f8c..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 @@ -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 +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 0c53286d73b..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 @@ -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 +area2 total 1 20 86 25 10 +area1 total 1 10 43 12 6 +area3 total 0 3 13 4 2 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/dataDistributionPerZone.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/dataDistributionPerZone.csv 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..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 @@ - testArea2_area3 testArea1_area2 testArea1_area1 -testArea2_area3 0 0 0 -testArea1_area2 0 1 0 -testArea1_area1 0 0 1 +O/D area2 area1 area3 +area2 1 0 0 +area1 0 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose2.csv index 30cf57e5fc3..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 @@ - testArea2_area3 testArea1_area2 testArea1_area1 -testArea2_area3 0 0 0 -testArea1_area2 0 8 7 -testArea1_area1 1 5 3 +O/D area2 area1 area3 +area2 8 6 0 +area1 5 4 1 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose3.csv index 44108374c44..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 @@ - testArea2_area3 testArea1_area2 testArea1_area1 -testArea2_area3 2 7 3 -testArea1_area2 7 52 25 -testArea1_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 6cebadd2f70..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 @@ - testArea2_area3 testArea1_area2 testArea1_area1 -testArea2_area3 0 2 2 -testArea1_area2 2 17 7 -testArea1_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 5d7cb865fbf..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 @@ - testArea2_area3 testArea1_area2 testArea1_area1 -testArea2_area3 0 0 0 -testArea1_area2 1 7 4 -testArea1_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/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 00000000000..c97184381a4 Binary files /dev/null and b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.dbf differ 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 00000000000..50121591ca3 Binary files /dev/null and b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.shp differ diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.shx b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.shx new file mode 100644 index 00000000000..7bf75055f1c Binary files /dev/null and b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/shp/testRegions.shx differ 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 a3f7231747b..cedefa5d9a5 100644 Binary files a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz and b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz differ 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..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 @@ -9,18 +9,20 @@ 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.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; @@ -34,8 +36,6 @@ import java.util.concurrent.Callable; import java.util.stream.Collectors; -import static org.matsim.lanes.LanesUtils.calculateAndSetCapacity; - /** * Converter for sumo networks * @@ -43,394 +43,387 @@ */ public class SumoNetworkConverter implements Callable { - private static final Logger log = LogManager.getLogger(SumoNetworkConverter.class); + private static final Logger log = LogManager.getLogger(SumoNetworkConverter.class); - @CommandLine.Parameters(arity = "1..*", paramLabel = "INPUT", description = "Input file(s)") - private List input; + @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 = "--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 = "--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 = "--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; - @CommandLine.Option(names = "--free-speed-factor", description = "Free-speed reduction for urban links", defaultValue = "0.9") - private double freeSpeedFactor = LinkProperties.DEFAULT_FREESPEED_FACTOR; + @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, 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(List input, Path output, String fromCRS, String toCRS, double freeSpeedFactor, + LaneRestriction laneRestriction) { + this.input = input; + this.output = output; + this.fromCRS = fromCRS; + this.toCRS = toCRS; + this.freeSpeedFactor = freeSpeedFactor; + this.laneRestriction = laneRestriction; } - private SumoNetworkConverter() { - } + 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, fromCRS, toCRS, LinkProperties.DEFAULT_FREESPEED_FACTOR, LaneRestriction.IGNORE); + } + + + /** + * Creates a new instance. + * + * @see #newInstance(List, Path, String, String, double) + */ + 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, String, String, double) + */ + 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); + } + + /** + * 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). + */ + @Override + public Integer call() throws Exception { + + Network network = NetworkUtils.createNetwork(); + + SumoNetworkHandler handler = convert(network); - /** - * 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); - } + if (toCRS != null) + ProjectionUtils.putCRS(network, toCRS); - /** - * 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); - } + NetworkUtils.writeNetwork(network, output.toAbsolutePath().toString()); - /** - * 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); - } + writeGeometry(handler, output.toAbsolutePath().toString().replace(".xml", "-linkGeometries.csv")); - /** - * Reads network from input file. - */ - public static SumoNetworkHandler readNetwork(File input) throws IOException, SAXException, ParserConfigurationException { - return SumoNetworkHandler.read(input); - } + writeFeatures(handler, output.toAbsolutePath().toString().replace(".xml", "-ft.csv")); - public static void main(String[] args) { - System.exit(new CommandLine(new SumoNetworkConverter()).execute(args)); - } + return 0; + } - /** - * 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()); - } + /** + * Write csv with link properties. + */ + public void writeFeatures(SumoNetworkHandler handler, String output) { - /** - * Execute the converter, which includes conversion and writing the files - * - * @see #convert(Network, Lanes) . - */ - @Override - public Integer call() throws Exception { + SumoNetworkFeatureExtractor props = new SumoNetworkFeatureExtractor(handler); - Network network = NetworkUtils.createNetwork(); - Lanes lanes = LanesUtils.createLanesContainer(); + try (CSVPrinter out = new CSVPrinter(IOUtils.getBufferedWriter(output), CSVFormat.DEFAULT)) { + out.printRecord(props.getHeader()); + props.print(out); - SumoNetworkHandler handler = convert(network, lanes); + } catch (IOException e) { + log.warn("Could not write property file.", e); + } + } - calculateLaneCapacities(network, lanes); + /** + * 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")); - // 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); - }); + for (Map.Entry e : handler.getEdges().entrySet()) { - if (toCRS != null) - ProjectionUtils.putCRS(network, toCRS); + SumoNetworkHandler.Edge edge = e.getValue(); - NetworkUtils.writeNetwork(network, output.toAbsolutePath().toString()); + // Create straight line for edges without shape + if (edge.shape.isEmpty()) { - new LanesWriter(lanes).write(output.toAbsolutePath().toString().replace(".xml", "-lanes.xml")); + SumoNetworkHandler.Junction f = handler.getJunctions().get(edge.from); + SumoNetworkHandler.Junction t = handler.getJunctions().get(edge.to); + if (f == null || t == null) + continue; - writeGeometry(handler, output.toAbsolutePath().toString().replace(".xml", "-linkGeometries.csv")); + edge.shape.add(f.coord); + edge.shape.add(t.coord); + } - return 0; - } + 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(",")) + ); - /** - * 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")); + } - for (Map.Entry e : handler.getEdges().entrySet()) { + } catch (IOException e) { + log.error("Could not write link geometries", e); + } + } - SumoNetworkHandler.Edge edge = e.getValue(); + /** + * Perform the actual conversion on given input data. + * + * @param network results will be added into this network. + * @return internal handler used for conversion + */ + public SumoNetworkHandler convert(Network network) throws ParserConfigurationException, SAXException, IOException { - // Create straight line for edges without shape - if (edge.shape.isEmpty()) { + log.info("Parsing SUMO network"); - SumoNetworkHandler.Junction f = handler.getJunctions().get(edge.from); - SumoNetworkHandler.Junction t = handler.getJunctions().get(edge.to); - if (f == null || t == null) - continue; + SumoNetworkHandler sumoHandler = SumoNetworkHandler.read(input.get(0).toFile()); + log.info("Parsed {} edges with {} junctions", sumoHandler.edges.size(), sumoHandler.junctions.size()); - edge.shape.add(f.coord); - edge.shape.add(t.coord); - } + for (int i = 1; i < input.size(); i++) { - 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(",")) - ); + CoordinateTransformation ct = TransformationFactory.getCoordinateTransformation(fromCRS, toCRS); + File file = input.get(i).toFile(); + SumoNetworkHandler other = SumoNetworkHandler.read(file); - } + writeInductionLoops(file, other); - } catch (IOException e) { - log.error("Could not write link geometries", e); - } - } + log.info("Merging {} edges with {} junctions from {} into base network", other.edges.size(), other.junctions.size(), file); + sumoHandler.merge(other, ct); + } - /** - * 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 { + NetworkFactory f = network.getFactory(); - log.info("Parsing SUMO network"); + Map linkProperties = LinkProperties.createLinkProperties(); - SumoNetworkHandler sumoHandler = SumoNetworkHandler.read(input.get(0).toFile()); - log.info("Parsed {} edges with {} junctions", sumoHandler.edges.size(), sumoHandler.junctions.size()); + // add additional service tag + linkProperties.put(OsmTags.SERVICE, new LinkProperties(LinkProperties.LEVEL_LIVING_STREET, 1, 15 / 3.6, 450, false)); - for (int i = 1; i < input.size(); i++) { + for (SumoNetworkHandler.Edge edge : sumoHandler.edges.values()) { - CoordinateTransformation ct = TransformationFactory.getCoordinateTransformation(fromCRS, toCRS); + // skip railways and unknowns + if (edge.type == null || !edge.type.startsWith("highway")) + continue; - File file = input.get(i).toFile(); - SumoNetworkHandler other = SumoNetworkHandler.read(file); + Link link = f.createLink(Id.createLinkId(edge.id), + createNode(network, sumoHandler, edge.from), + createNode(network, sumoHandler, edge.to) + ); - writeInductionLoops(file, other); + if (edge.name != null) + link.getAttributes().putAttribute("name", edge.name); - log.info("Merging {} edges with {} junctions from {} into base network", other.edges.size(), other.junctions.size(), file); - sumoHandler.merge(other, ct); - } + link.getAttributes().putAttribute(NetworkUtils.TYPE, edge.type); - NetworkFactory f = network.getFactory(); - LanesFactory lf = lanes.getFactory(); + Set modes = Sets.newHashSet(TransportMode.car, TransportMode.ride); - Map linkProperties = LinkProperties.createLinkProperties(); + SumoNetworkHandler.Type type = sumoHandler.types.get(edge.type); - // add additional service tag - linkProperties.put(OsmTags.SERVICE, new LinkProperties(LinkProperties.LEVEL_LIVING_STREET, 1,15 / 3.6, 450, false)); + // Determine allowed modes + if (!isModeAllowed("passenger", edge, type)) { + modes.remove(TransportMode.car); + modes.remove(TransportMode.ride); + } - for (SumoNetworkHandler.Edge edge : sumoHandler.edges.values()) { + if (isModeAllowed("bicycle", edge, type)) + modes.add(TransportMode.bike); - // skip railways and unknowns - if (edge.type == null || !edge.type.startsWith("highway")) - continue; + if (isModeAllowed("truck", edge, type)) + modes.add(TransportMode.truck); - Link link = f.createLink(Id.createLinkId(edge.id), - createNode(network, sumoHandler, edge.from), - createNode(network, sumoHandler, edge.to) - ); + link.setAllowedModes(modes); + link.setLength(edge.getLength()); - if (edge.name != null) - link.getAttributes().putAttribute("name", edge.name); + if (laneRestriction == LaneRestriction.REDUCE_CAR_LANES) { - link.getAttributes().putAttribute(NetworkUtils.TYPE, edge.type); + int size = edge.lanes.size(); - link.setNumberOfLanes(edge.lanes.size()); - Set modes = Sets.newHashSet(TransportMode.car, TransportMode.ride); + SumoNetworkHandler.Lane lane = edge.lanes.get(0); + edge.lanes.removeIf(l -> l.allow != null && !l.allow.contains("passenger")); - SumoNetworkHandler.Type type = sumoHandler.types.get(edge.type); + // Keep at least one lane + if (edge.lanes.isEmpty()) + edge.lanes.add(lane); - if (type.allow.contains("bicycle") || (type.allow.isEmpty() && !type.disallow.contains("bicycle"))) - modes.add(TransportMode.bike); + int restricted = size - edge.lanes.size(); + if (restricted > 0) { + link.getAttributes().putAttribute("restricted_lanes", restricted); + } + } - link.setAllowedModes(modes); - link.setLength(edge.getLength()); - LanesToLinkAssignment l2l = lf.createLanesToLinkAssignment(link.getId()); + link.setNumberOfLanes(edge.lanes.size()); - 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); - } + // set link prop based on MATSim defaults + LinkProperties prop = linkProperties.get(type.highway); + double speed = type.speed; - // 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.isEmpty()) { + 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; + } + } - // 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); + link.getAttributes().putAttribute(NetworkUtils.ALLOWED_SPEED, speed); - 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 (prop == null) { + log.warn("Skipping unknown link type: {}", type.highway); + continue; + } - link.getAttributes().putAttribute(NetworkUtils.ALLOWED_SPEED, speed); + link.setFreespeed(LinkProperties.calculateSpeedIfSpeedTag(speed, freeSpeedFactor)); + link.setCapacity(LinkProperties.getLaneCapacity(link.getLength(), prop) * link.getNumberOfLanes()); - if (prop == null) { - log.warn("Skipping unknown link type: {}", type.highway); - continue; - } + network.addLink(link); + } - link.setFreespeed(LinkProperties.calculateSpeedIfSpeedTag(speed, freeSpeedFactor)); - link.setCapacity(LinkProperties.getLaneCapacity(link.getLength(), prop) * link.getNumberOfLanes()); + // clean up network + new NetworkCleaner().run(network); - lanes.addLanesToLinkAssignment(l2l); - network.addLink(link); - } + Set> ignored = new HashSet<>(); - if (shapeFile != null) { - Geometry shp = calculateNetworkArea(shapeFile); + for (Map.Entry> kv : sumoHandler.connections.entrySet()) { - // 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)); - } - } - } + Link link = network.getLinks().get(Id.createLinkId(kv.getKey())); - // clean up network - new NetworkCleaner().run(network); + if (link != null) { + Set> outLinks = link.getToNode().getOutLinks().keySet(); + Set> allowed = kv.getValue().stream().map(c -> Id.createLinkId(c.to)).collect(Collectors.toSet()); - // also clean lanes - lanes.getLanesToLinkAssignments().keySet().removeIf(l2l -> !network.getLinks().containsKey(l2l)); + Sets.SetView> diff = Sets.difference(outLinks, allowed); - for (List connections : sumoHandler.connections.values()) { - for (SumoNetworkHandler.Connection conn : connections) { + if (outLinks.size() == diff.size()) { + ignored.add(link.getId()); + continue; + } - Id fromLink = Id.createLinkId(conn.from); - Id toLink = Id.createLinkId(conn.to); + if (!diff.isEmpty()) { + DisallowedNextLinks disallowed = new DisallowedNextLinks(); + for (Id id : diff) { + disallowed.addDisallowedLinkSequence(TransportMode.car, List.of(id)); + } - LanesToLinkAssignment l2l = lanes.getLanesToLinkAssignments().get(fromLink); + NetworkUtils.setDisallowedNextLinks(link, disallowed); + } + } + } - // link was removed - if (l2l == null) - continue; + if (!ignored.isEmpty()) { + log.warn("Ignored turn restrictions for {} links with no connections: {}", ignored.size(), ignored); + } - 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())); - - 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; - } + 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); + private void writeInductionLoops(File file, SumoNetworkHandler other) throws IOException { + Path loops = Path.of(file.getAbsolutePath().replace(".xml", "_loops.xml")); + BufferedWriter writer = Files.newBufferedWriter(loops); - log.info("Writing induction loop definition {}", loops); - writer.write("\n"); + log.info("Writing induction loop definition {}", loops); + writer.write("\n"); - // ignore duplicated - Set written = new HashSet<>(); + // ignore duplicated + Set written = new HashSet<>(); - 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); - } + 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.write(""); - writer.close(); - } + writer.close(); + } - private Node createNode(Network network, SumoNetworkHandler sumoHandler, String nodeId) { + 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; + 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); + 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); + Coord coord = sumoHandler.createCoord(junction.coord); + node = network.getFactory().createNode(id, coord); + node.getAttributes().putAttribute("type", junction.type); - network.addNode(node); - return node; - } + network.addNode(node); + return node; + } + + /** + * How restricted lanes should be handled. + */ + public enum LaneRestriction { + IGNORE, REDUCE_CAR_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..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 @@ -20,438 +20,510 @@ */ 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; + } + + /** + * 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; + } + + 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 used afterward. + * + * @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)); + + 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())) { + + // remove connections that point to edges that are also in the other network + connections.get(e.getKey()).removeIf(c -> other.edges.containsKey(c.to)); + + // 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]); + } - /** - * 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; - } + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - /** - * 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))); - } - } - } + switch (qName) { - edges.keySet().removeAll(other.edges.keySet()); - lanes.keySet().removeAll(other.lanes.keySet()); + case "location": + String[] netOffsets = attributes.getValue("netOffset").split(","); + netOffset[0] = Double.parseDouble(netOffsets[0]); + netOffset[1] = Double.parseDouble(netOffsets[1]); - junctions.keySet().removeAll(notDeadEnd); + break; - // 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)); + case "type": - edges.putAll(other.edges); - lanes.putAll(other.lanes); + String typeId = attributes.getValue("id"); - other.junctions.forEach((k, v) -> { - if (notDeadEnd.contains(k)) - junctions.put(k, v); - else - junctions.putIfAbsent(k, v); - }); + types.put(typeId, new Type(typeId, attributes.getValue("allow"), attributes.getValue("disallow"), + Double.parseDouble(attributes.getValue("speed")))); - // connections are merged individually - for (Map.Entry> e : other.connections.entrySet()) { + break; - if (connections.containsKey(e.getKey())) { + case "edge": - // remove connections that point to edges that are also in the other network - connections.get(e.getKey()).removeIf(c -> other.edges.containsKey(c.to)); + // Internal edges are not needed + if ("internal".equals(attributes.getValue("function"))) + break; - // add all other connections - connections.get(e.getKey()).addAll(e.getValue()); + 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(" ") + ); - } else - connections.put(e.getKey(), e.getValue()); + break; - } + case "lane": - connections.putAll(other.connections); - } + // lane of internal edge + if (tmpEdge == null) + break; - Coord createCoord(double[] xy) { - return new Coord(xy[0] - netOffset[0], xy[1] - netOffset[1]); - } + Lane lane = new Lane( + attributes.getValue("id"), + Integer.parseInt(attributes.getValue("index")), + Double.parseDouble(attributes.getValue("length")), + Double.parseDouble(attributes.getValue("speed")), + parseModes(attributes.getValue("allow")), + parseModes(attributes.getValue("disallow")) + ); - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + tmpEdge.lanes.add(lane); + lanes.put(lane.id, tmpEdge); + break; - switch (qName) { + case "param": - case "location": - String[] netOffsets = attributes.getValue("netOffset").split(","); - netOffset[0] = Double.parseDouble(netOffsets[0]); - netOffset[1] = Double.parseDouble(netOffsets[1]); + if (tmpEdge == null) + break; - break; + String value = attributes.getValue("value"); - case "type": + switch (attributes.getValue("key")) { + case "origId": + tmpEdge.origId = value; + break; + case "origFrom": + tmpEdge.origFrom = value; + break; + case "origTo": + tmpEdge.origTo = value; + break; + } - String typeId = attributes.getValue("id"); + break; - types.put(typeId, new Type(typeId, attributes.getValue("allow"), attributes.getValue("disallow"), - Double.parseDouble(attributes.getValue("speed")))); + case "junction": - break; + String inc = attributes.getValue("incLanes"); - case "edge": + 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"))} + ); - // Internal edges are not needed - if ("internal".equals(attributes.getValue("function"))) - break; + junctions.put(id, tmpJunction); - 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(" ") - ); + break; - break; + case "request": - case "lane": + if (this.tmpJunction != null) + this.tmpJunction.requests.add( + new Req( + parseBitSet(attributes.getValue("response")), + parseBitSet(attributes.getValue("foes")) + ) + ); - // 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")) - ); - - tmpEdge.lanes.add(lane); - lanes.put(lane.id, tmpEdge); - - break; - - case "param": - - 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; - - } - } + case "connection": + + // 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; + + /** + * 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, allow, disallow); + } + } + + 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..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 { @@ -25,37 +19,32 @@ 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")); + Link link = network.getLinks().get(Id.createLinkId("-461905066#1")); - Config config = ConfigUtils.createConfig(); - Scenario scenario = ScenarioUtils.createScenario(config); + List>> disallowed = NetworkUtils.getDisallowedNextLinks(link).getDisallowedLinkSequences(TransportMode.car); + assert disallowed.contains(List.of(Id.createLinkId("461905066#0"))) : "Must contain disallowed link sequence"; - LanesReader reader = new LanesReader(scenario); - reader.readFile(lanes.toString()); + Path geometry = Path.of(output.toString().replace(".xml", "-linkGeometries.csv")); - SortedMap, LanesToLinkAssignment> l2l = scenario.getLanes().getLanesToLinkAssignments(); + assert Files.exists(geometry) : "Geometries must exist"; - System.out.println(l2l); + Path fts = Path.of(output.toString().replace(".xml", "-ft.csv")); - assert l2l.containsKey(Id.createLinkId("-160346478#3")) : "Must contain link id"; + assert Files.exists(fts) : "Features must exists"; - Path geometry = Path.of(output.toString().replace(".xml", "-linkGeometries.csv")); - - assert Files.exists(geometry) : "Geometries must exist"; - - } -} \ No newline at end of file + } +} diff --git a/contribs/taxi/src/test/java/org/matsim/contrib/etaxi/run/RunETaxiScenarioIT.java b/contribs/taxi/src/test/java/org/matsim/contrib/etaxi/run/RunETaxiScenarioIT.java index c086adedc50..5e029c8a29e 100644 --- a/contribs/taxi/src/test/java/org/matsim/contrib/etaxi/run/RunETaxiScenarioIT.java +++ b/contribs/taxi/src/test/java/org/matsim/contrib/etaxi/run/RunETaxiScenarioIT.java @@ -29,7 +29,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; /** * @author michalm @@ -73,8 +73,8 @@ private void runScenario(String configPath) { { String expected = utils.getInputDirectory() + "/output_events.xml.gz"; String actual = utils.getOutputDirectory() + "/output_events.xml.gz"; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles(expected, actual); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles(expected, actual); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } } diff --git a/contribs/taxi/src/test/java/org/matsim/contrib/taxi/optimizer/TaxiOptimizerTests.java b/contribs/taxi/src/test/java/org/matsim/contrib/taxi/optimizer/TaxiOptimizerTests.java index ca985585f82..3a3800467af 100644 --- a/contribs/taxi/src/test/java/org/matsim/contrib/taxi/optimizer/TaxiOptimizerTests.java +++ b/contribs/taxi/src/test/java/org/matsim/contrib/taxi/optimizer/TaxiOptimizerTests.java @@ -35,7 +35,7 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; public class TaxiOptimizerTests { public static void runBenchmark(boolean vehicleDiversion, AbstractTaxiOptimizerParams taxiOptimizerParams, MatsimTestUtils utils) { @@ -70,8 +70,8 @@ public static void runBenchmark(boolean vehicleDiversion, AbstractTaxiOptimizerP { String expected = utils.getInputDirectory() + "/output_events.xml.gz"; String actual = utils.getOutputDirectory() + "/output_events.xml.gz"; - EventsFileComparator.Result result = EventsUtils.compareEventsFiles(expected, actual); - Assertions.assertEquals(EventsFileComparator.Result.FILES_ARE_EQUAL, result); + ComparisonResult result = EventsUtils.compareEventsFiles(expected, actual); + Assertions.assertEquals(ComparisonResult.FILES_ARE_EQUAL, result); } } } diff --git a/contribs/vsp/pom.xml b/contribs/vsp/pom.xml index 701d3de1b86..c871cf3ebd9 100644 --- a/contribs/vsp/pom.xml +++ b/contribs/vsp/pom.xml @@ -184,7 +184,7 @@ org.openjfx javafx-graphics - 21.0.2 + 22 com.graphhopper diff --git a/contribs/vsp/src/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/pom.xml b/matsim/pom.xml index ba989fc0dff..5b5d4f34017 100644 --- a/matsim/pom.xml +++ b/matsim/pom.xml @@ -222,7 +222,7 @@ com.github.luben zstd-jni - 1.5.5-11 + 1.5.6-2 jakarta.validation @@ -344,7 +344,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.7.0 + 3.7.1 src/main/assembly/assembly-release.xml diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java index ba79214ff73..3aa0443b9e0 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java @@ -65,6 +65,8 @@ public class RaptorParameters { private double transferPenaltyPerTravelTimeHour = 0.0; private double transferPenaltyMinimum = Double.NEGATIVE_INFINITY; private double transferPenaltyMaximum = Double.POSITIVE_INFINITY; + + private boolean useTransportModeUtilities = false; private final SwissRailRaptorConfigGroup config; @@ -159,5 +161,13 @@ public double getTransferPenaltyMaximum() { public void setTransferPenaltyMaximum(double transferPenaltyMaximum) { this.transferPenaltyMaximum = transferPenaltyMaximum; } + + public boolean isUseTransportModeUtilities() { + return useTransportModeUtilities; + } + + public void setUseTransportModeUtilities(boolean useTransportModeUtilities) { + this.useTransportModeUtilities = useTransportModeUtilities; + } } diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java index 09cef257e09..0242f5e91ab 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java @@ -588,6 +588,7 @@ private void exploreRoutes(RaptorParameters parameters, Person person) { CachingTransferProvider transferProvider = this.data.new CachingTransferProvider(); double marginalUtilityOfWaitingPt_utl_s = parameters.getMarginalUtilityOfWaitingPt_utl_s(); + boolean useTransportModeUtilities = parameters.isUseTransportModeUtilities(); int routeIndex = -1; for (int firstRouteStopIndex = this.improvedRouteStopIndices.nextSetBit(0); firstRouteStopIndex >= 0; firstRouteStopIndex = this.improvedRouteStopIndices.nextSetBit(firstRouteStopIndex+1)) { @@ -627,7 +628,8 @@ private void exploreRoutes(RaptorParameters parameters, Person person) { routeIndex = tmpRouteIndex; int firstDepartureTime = (boardingPE.firstDepartureTime == TIME_UNDEFINED) ? currentAgentBoardingTime : boardingPE.firstDepartureTime; - double marginalUtilityOfTravelTime_utl_s = parameters.getMarginalUtilityOfTravelTime_utl_s(boardingPE.toRouteStop.mode); + double marginalUtilityOfTravelTime_utl_s = parameters.getMarginalUtilityOfTravelTime_utl_s( + !useTransportModeUtilities ? boardingPE.toRouteStop.mode : boardingPE.toRouteStop.route.getTransportMode()); transferProvider.reset(boardingPE.transfer); for (int toRouteStopIndex = firstRouteStopIndex + 1; toRouteStopIndex < route.indexFirstRouteStop + route.countRouteStops; toRouteStopIndex++) { diff --git a/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java b/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java index e19d7bbea3a..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 @@ -23,8 +23,17 @@ public interface BasicPlan { - public abstract void setScore(Double score); + String UNDEFINED_PLAN_TYPE = "undefined"; - public abstract Double getScore(); - -} \ No newline at end of file + void setScore(Double score ); + + Double getScore(); + + /** + * Plan type, which may be used to ensure there is at least one plan of a certain type. + */ + default String getType() { + return UNDEFINED_PLAN_TYPE; + } + +} 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/events/EventsUtils.java b/matsim/src/main/java/org/matsim/core/events/EventsUtils.java index 1f2ba7e3d33..7601a9091ad 100644 --- a/matsim/src/main/java/org/matsim/core/events/EventsUtils.java +++ b/matsim/src/main/java/org/matsim/core/events/EventsUtils.java @@ -21,19 +21,26 @@ package org.matsim.core.events; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.controler.Injector; -import org.matsim.utils.eventsfilecomparison.EventsFileComparator; +import org.matsim.utils.eventsfilecomparison.*; + +import java.io.File; public final class EventsUtils { + private static final Logger log = LogManager.getLogger(EventsUtils.class); + + /** * Create a events manager instance that guarantees causality of processed events across all handlers. */ - public static EventsManager createEventsManager() { + public static EventsManager createEventsManager() { return new EventsManagerImpl(); - } + } /** * Creates a parallel events manager, with no guarantees for the order of processed events between multiple handlers. @@ -43,11 +50,16 @@ public static EventsManager createParallelEventsManager() { } public static EventsManager createEventsManager(Config config) { - final EventsManager events = Injector.createInjector( config, new EventsManagerModule() ).getInstance( EventsManager.class ); + final EventsManager events = Injector.createInjector(config, new EventsManagerModule()).getInstance(EventsManager.class); // events.initProcessing(); return events; } + public static void readEvents(EventsManager events, String filename) { + new MatsimEventsReader(events).readFile(filename); + } + + /** * The SimStepParallelEventsManagerImpl can handle events from multiple threads. * The (Parallel)EventsMangerImpl cannot, therefore it has to be wrapped into a @@ -58,21 +70,68 @@ public static EventsManager getParallelFeedableInstance(EventsManager events) { return events; } else if (events instanceof ParallelEventsManager) { return events; - } - else if (events instanceof SynchronizedEventsManagerImpl) { + } else if (events instanceof SynchronizedEventsManagerImpl) { return events; } else { return new SynchronizedEventsManagerImpl(events); } } - public static void readEvents( EventsManager events, String filename ) { - new MatsimEventsReader(events).readFile(filename) ; + /** + * Create and write fingerprint file for events. + */ + public static FingerprintEventHandler createEventsFingerprint(String eventFile, String outputFingerprintFile) { + + FingerprintEventHandler handler = EventsFileFingerprintComparator.createFingerprintHandler(eventFile, null); + + EventFingerprint.write(outputFingerprintFile, handler.getEventFingerprint()); + + return handler; + } + + + /** + * Compares existing event file against fingerprint file. This will also create new fingerprint file along the input events. + * + * @param eventFile local events file + * @param compareFingerprintFile path or uri to fingerprint file + * + * @return comparison results + */ + public static ComparisonResult createAndCompareEventsFingerprint(File eventFile, String compareFingerprintFile) { + + String path = eventFile.getPath().replaceFirst("\\.xml[.a-zA-z0-9]*$", ""); + + FingerprintEventHandler handler = EventsFileFingerprintComparator.createFingerprintHandler(eventFile.toString(), compareFingerprintFile); + EventFingerprint.write(path + ".fp.zst", handler.getEventFingerprint()); + + if (handler.getComparisonMessage() != null) + log.warn(handler.getComparisonMessage()); + + return handler.getComparisonResult(); + } + + /** + * Compares existing event file against fingerprint file. This will also create new fingerprint file along the input events. + * + * @throws AssertionError if comparison fails + * @see #createAndCompareEventsFingerprint(File, String) + */ + public static void assertEqualEventsFingerprint(File eventFile, String compareFingerprintFile) { + + String path = eventFile.getPath().replaceFirst("\\.xml[.a-zA-z0-9]*$", ""); + + FingerprintEventHandler handler = EventsFileFingerprintComparator.createFingerprintHandler(eventFile.toString(), compareFingerprintFile); + EventFingerprint.write(path + ".fp.zst", handler.getEventFingerprint()); + + + if (handler.getComparisonResult() != ComparisonResult.FILES_ARE_EQUAL) + throw new AssertionError(handler.getComparisonMessage()); + } - public static EventsFileComparator.Result compareEventsFiles( String filename1, String filename2 ) { - EventsFileComparator.Result result = EventsFileComparator.compare( filename1, filename2 ); - return result ; + public static ComparisonResult compareEventsFiles(String filename1, String filename2) { + return EventsFileComparator.compare(filename1, filename2); } } diff --git a/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealer.java b/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealer.java index b576833d9fd..2522bd2a96e 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealer.java +++ b/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealer.java @@ -57,7 +57,7 @@ public class ReplanningAnnealer implements IterationStartsListener, StartupListe private final ReplanningAnnealerConfigGroup saConfig; private final int innovationStop; private final String sep; - private final EnumMap currentValues; + private final EnumMap> currentValuesPerSubpopulation; private int currentIter; private List header; @Inject @@ -67,7 +67,7 @@ public class ReplanningAnnealer implements IterationStartsListener, StartupListe public ReplanningAnnealer(Config config) { this.config = config; this.saConfig = ConfigUtils.addOrGetModule(config, ReplanningAnnealerConfigGroup.class); - this.currentValues = new EnumMap<>(AnnealParameterOption.class); + this.currentValuesPerSubpopulation = new EnumMap<>(AnnealParameterOption.class); this.innovationStop = getInnovationStop(config); this.sep = config.global().getDefaultDelimiter(); } @@ -83,17 +83,19 @@ private static boolean isInnovationStrategy(String strategyName) { @Override public void notifyStartup(StartupEvent event) { header = new ArrayList<>(); - for (AnnealingVariable av : this.saConfig.getAnnealingVariables().values()) { + for (AnnealingVariable av : this.saConfig.getAllAnnealingVariables()) { if (!av.getAnnealType().equals(AnnealOption.disabled)) { // check and fix initial value if needed checkAndFixStartValue(av, event); - this.currentValues.put(av.getAnnealParameter(), av.getStartValue()); - header.add(av.getAnnealParameter().name()); + var mapPerSubpopulation = this.currentValuesPerSubpopulation.computeIfAbsent(av.getAnnealParameter(),a-> new HashMap<>()); + mapPerSubpopulation.put(av.getSubpopulation(),av.getStartValue()); + String subpopulationString = av.getSubpopulation()!=null? "_"+av.getSubpopulation() :""; + header.add(av.getAnnealParameter().name()+subpopulationString); if (av.getAnnealParameter().equals(AnnealParameterOption.globalInnovationRate)) { header.addAll(this.config.replanning().getStrategySettings().stream() - .filter(s -> Objects.equals(av.getDefaultSubpopulation(), s.getSubpopulation())) - .map(ReplanningConfigGroup.StrategySettings::getStrategyName) + .filter(s -> Objects.equals(av.getSubpopulation(), s.getSubpopulation())) + .map(strategySettings -> strategySettings.getStrategyName()+subpopulationString) .collect(Collectors.toList())); } } else { // if disabled, better remove it @@ -114,34 +116,35 @@ public void notifyStartup(StartupEvent event) { public void notifyIterationStarts(IterationStartsEvent event) { this.currentIter = event.getIteration() - this.config.controller().getFirstIteration(); Map annealStats = new HashMap<>(); - for (AnnealingVariable av : this.saConfig.getAnnealingVariables().values()) { + List allVariables = this.saConfig.getAllAnnealingVariables(); + for (AnnealingVariable av : allVariables) { if (this.currentIter > 0) { switch (av.getAnnealType()) { case geometric: - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> v * av.getShapeFactor()); break; case exponential: int halfLifeIter = av.getHalfLife() <= 1.0 ? (int) (av.getHalfLife() * this.innovationStop) : (int) av.getHalfLife(); - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> av.getStartValue() / Math.exp((double) this.currentIter / halfLifeIter)); break; case msa: - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> av.getStartValue() / Math.pow(this.currentIter, av.getShapeFactor())); break; case sigmoid: halfLifeIter = av.getHalfLife() <= 1.0 ? (int) (av.getHalfLife() * this.innovationStop) : (int) av.getHalfLife(); - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> av.getEndValue() + (av.getStartValue() - av.getEndValue()) / (1 + Math.exp(av.getShapeFactor() * (this.currentIter - halfLifeIter)))); break; case linear: double slope = (av.getStartValue() - av.getEndValue()) / (this.config.controller().getFirstIteration() - this.innovationStop); - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> this.currentIter * slope + av.getStartValue()); break; case disabled: @@ -150,14 +153,16 @@ public void notifyIterationStarts(IterationStartsEvent event) { throw new IllegalArgumentException(); } - log.info("Annealling will be performed on parameter " + av.getAnnealParameter() + - ". Value: " + this.currentValues.get(av.getAnnealParameter())); + log.info("Annealling will be performed on parameter " + av.getAnnealParameter() +". Subpopulation: "+av.getSubpopulation()+ + ". Value: " +this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).get(av.getSubpopulation())); - this.currentValues.compute(av.getAnnealParameter(), (k, v) -> + this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) -> Math.max(v, av.getEndValue())); } - double annealValue = this.currentValues.get(av.getAnnealParameter()); - annealStats.put(av.getAnnealParameter().name(), String.format(Locale.US, "%.4f", annealValue)); + double annealValue = this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).get(av.getSubpopulation()); + String subpopulationString = av.getSubpopulation()!=null? "_"+av.getSubpopulation() :""; + + annealStats.put(av.getAnnealParameter().name()+subpopulationString, String.format(Locale.US, "%.4f", annealValue)); anneal(event, av, annealValue, annealStats); } @@ -178,6 +183,8 @@ private void writeIterationstats(int currentIter, Map annealStat } private void anneal(IterationStartsEvent event, AnnealingVariable av, double annealValue, Map annealStats) { + String subpopulationString = av.getSubpopulation()!=null? "_"+av.getSubpopulation() :""; + switch (av.getAnnealParameter()) { case BrainExpBeta: this.config.scoring().setBrainExpBeta(annealValue); @@ -193,16 +200,17 @@ private void anneal(IterationStartsEvent event, AnnealingVariable av, double ann annealValue = 0.0; } List annealValues = annealReplanning(annealValue, - event.getServices().getStrategyManager(), av.getDefaultSubpopulation()); + event.getServices().getStrategyManager(), av.getSubpopulation()); int i = 0; for (ReplanningConfigGroup.StrategySettings ss : this.config.replanning().getStrategySettings()) { - if (Objects.equals(ss.getSubpopulation(), av.getDefaultSubpopulation())) { - annealStats.put(ss.getStrategyName(), String.format(Locale.US, "%.4f", annealValues.get(i))); + if (Objects.equals(ss.getSubpopulation(), av.getSubpopulation())) { + annealStats.put(ss.getStrategyName()+subpopulationString, String.format(Locale.US, "%.4f", annealValues.get(i))); i++; } } - annealStats.put(av.getAnnealParameter().name(), String.format(Locale.US, "%.4f", // update value in case of switchoff - getStrategyWeights(event.getServices().getStrategyManager(), av.getDefaultSubpopulation(), StratType.allInnovation))); + + annealStats.put(av.getAnnealParameter().name()+subpopulationString, String.format(Locale.US, "%.4f", // update value in case of switchoff + getStrategyWeights(event.getServices().getStrategyManager(), av.getSubpopulation(), StratType.allInnovation))); break; default: throw new IllegalArgumentException(); @@ -328,14 +336,14 @@ private void checkAndFixStartValue(ReplanningAnnealerConfigGroup.AnnealingVariab configValue = this.config.scoring().getLearningRate(); break; case globalInnovationRate: - double innovationWeights = getStrategyWeights(this.config, av.getDefaultSubpopulation(), StratType.allInnovation); - double selectorWeights = getStrategyWeights(this.config, av.getDefaultSubpopulation(), StratType.allSelectors); + double innovationWeights = getStrategyWeights(this.config, av.getSubpopulation(), StratType.allInnovation); + double selectorWeights = getStrategyWeights(this.config, av.getSubpopulation(), StratType.allSelectors); if (innovationWeights + selectorWeights != 1.0) { log.warn("Initial sum of strategy weights different from 1.0. Rescaling."); double innovationStartValue = av.getStartValue() == null ? innovationWeights : av.getStartValue(); - rescaleStartupWeights(innovationStartValue, this.config, event.getServices().getStrategyManager(), av.getDefaultSubpopulation()); + rescaleStartupWeights(innovationStartValue, this.config, event.getServices().getStrategyManager(), av.getSubpopulation()); } - configValue = getStrategyWeights(this.config, av.getDefaultSubpopulation(), StratType.allInnovation); + configValue = getStrategyWeights(this.config, av.getSubpopulation(), StratType.allInnovation); break; default: throw new IllegalArgumentException(); diff --git a/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealerConfigGroup.java b/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealerConfigGroup.java index c3a9421862f..3c13879d7ca 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealerConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/replanning/annealing/ReplanningAnnealerConfigGroup.java @@ -20,7 +20,11 @@ package org.matsim.core.replanning.annealing; import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; + import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ReflectiveConfigGroup; @@ -81,27 +85,35 @@ public void addParameterSet(final ConfigGroup set) { addAnnealingVariable((AnnealingVariable) set); } - public Map getAnnealingVariables() { - final EnumMap map = - new EnumMap<>(AnnealParameterOption.class); - for (ConfigGroup pars : getParameterSets(AnnealingVariable.GROUP_NAME)) { - final AnnealParameterOption name = ((AnnealingVariable) pars).getAnnealParameter(); - final AnnealingVariable old = map.put(name, (AnnealingVariable) pars); - if (old != null) { - throw new IllegalStateException("several parameter sets for variable " + name); - } - } - return map; - } + public List getAllAnnealingVariables(){ + return getAnnealingVariablesPerSubpopulation().values().stream().flatMap(a->a.values().stream()).collect(Collectors.toList()); + } + public Map> getAnnealingVariablesPerSubpopulation() { + final EnumMap> map = + new EnumMap<>(AnnealParameterOption.class); + for (ConfigGroup pars : getParameterSets(AnnealingVariable.GROUP_NAME)) { + AnnealParameterOption name = ((AnnealingVariable) pars).getAnnealParameter(); + String subpopulation = ((AnnealingVariable) pars).getSubpopulation(); + var paramsPerSubpopulation = map.computeIfAbsent(name,a->new HashMap<>()); + final AnnealingVariable old = paramsPerSubpopulation.put(subpopulation, (AnnealingVariable) pars); + if (old != null) { + throw new IllegalStateException("several parameter sets for variable " + name + " and subpopulation "+subpopulation); + } + } + return map; + } public void addAnnealingVariable(final AnnealingVariable params) { - final AnnealingVariable previous = this.getAnnealingVariables().get(params.getAnnealParameter()); + var previousMap = this.getAnnealingVariablesPerSubpopulation().get(params.getAnnealParameter()); + if (previousMap!=null){ + AnnealingVariable previous = previousMap.get(params.getSubpopulation()); if (previous != null) { final boolean removed = removeParameterSet(previous); if (!removed) { throw new RuntimeException("problem replacing annealing variable"); } } + } super.addParameterSet(params); } @@ -117,11 +129,11 @@ public static class AnnealingVariable extends ReflectiveConfigGroup { private static final String START_VALUE = "startValue"; private static final String END_VALUE = "endValue"; private static final String ANNEAL_TYPE = "annealType"; - private static final String DEFAULT_SUBPOP = "defaultSubpopulation"; + private static final String SUBPOPULATION = "subpopulation"; private static final String ANNEAL_PARAM = "annealParameter"; private static final String HALFLIFE = "halfLife"; private static final String SHAPE_FACTOR = "shapeFactor"; - private String defaultSubpop = null; + private String subpopulation = null; private Double startValue = null; private double endValue = 0.0001; private double shapeFactor = 0.9; @@ -167,14 +179,14 @@ public void setAnnealType(AnnealOption annealType) { this.annealType = annealType; } - @StringGetter(DEFAULT_SUBPOP) - public String getDefaultSubpopulation() { - return this.defaultSubpop; + @StringGetter(SUBPOPULATION) + public String getSubpopulation() { + return this.subpopulation; } - @StringSetter(DEFAULT_SUBPOP) + @StringSetter(SUBPOPULATION) public void setDefaultSubpopulation(String defaultSubpop) { - this.defaultSubpop = defaultSubpop; + this.subpopulation = defaultSubpop; } @StringGetter(ANNEAL_PARAM) @@ -220,7 +232,7 @@ public Map getComments() { map.put(ANNEAL_TYPE, "options: linear, exponential, geometric, msa, sigmoid and disabled (no annealing)."); map.put(ANNEAL_PARAM, "list of config parameters that shall be annealed. Currently supported: globalInnovationRate, BrainExpBeta, PathSizeLogitBeta, learningRate. Default is globalInnovationRate"); - map.put(DEFAULT_SUBPOP, "subpopulation to have the global innovation rate adjusted. Not applicable when annealing with other parameters."); + map.put(SUBPOPULATION, "subpopulation to have the global innovation rate adjusted. Not applicable when annealing with other parameters."); map.put(START_VALUE, "start value for annealing."); map.put(END_VALUE, "final annealing value. When the annealing function reaches this value, further results remain constant."); return map; diff --git a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java index 116cd309427..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 @@ -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; + +import static org.matsim.api.core.v01.population.BasicPlan.UNDEFINED_PLAN_TYPE; + /** - *

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; - } + @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_PLAN_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_PLAN_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; + } } 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/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java index 98431e35cc7..567c6ace568 100644 --- a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java +++ b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java @@ -33,6 +33,7 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.PlanElement; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; @@ -337,7 +338,7 @@ void testLineChange() { assertEquals(Math.ceil(expectedTravelTime), actualTravelTime, MatsimTestUtils.EPSILON); } @Test - void testLineChangeWithDifferentUtils() { + void testLineChangeWithDifferentModeChangeUtils() { Fixture f = new Fixture(); f.init(); f.blueLine.getRoutes().values().forEach(transitRoute -> transitRoute.setTransportMode(TransportMode.ship)); @@ -355,6 +356,48 @@ void testLineChangeWithDifferentUtils() { //changing from train to ship is so expensive that direct walk is cheaper assertNull(legs); } + + @Test + void testLineChangeWithDifferentTravelTimeUtils() { + Fixture f = new Fixture(); + f.init(); + f.blueLine.getRoutes().values().forEach(transitRoute -> transitRoute.setTransportMode("bus")); + SwissRailRaptorConfigGroup swissRailRaptorConfigGroup = ConfigUtils.addOrGetModule(f.config, SwissRailRaptorConfigGroup.class); + swissRailRaptorConfigGroup.setTransferWalkMargin(0); + RaptorParameters raptorParams = RaptorUtils.createParameters(f.config); + SwissRailRaptorData data = SwissRailRaptorData.create(f.schedule, null, RaptorUtils.createStaticConfig(f.config), f.network, null); + TransitRouter router = new SwissRailRaptor.Builder(data, f.config).with(new RaptorParametersForPerson() { + @Override + public RaptorParameters getRaptorParameters(Person person) { + return raptorParams; + } + }).build(); + + // from C to G (see Fixture), competing between red line (express) and blue line (regular) + Coord fromCoord = new Coord(12000, 5000); + Coord toCoord = new Coord(28000, 5000); + + // default case + List legs = router.calcRoute(DefaultRoutingRequest.withoutAttributes(new FakeFacility(fromCoord), new FakeFacility(toCoord), 6.0*3600 - 60.0, null)); + assertEquals(3, legs.size()); + assertEquals("red", ((TransitPassengerRoute) ((Leg) legs.get(1)).getRoute()).getLineId().toString()); + + // routing by transport mode, same costs, choose red (train) again + raptorParams.setUseTransportModeUtilities(true); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("train", -1e-3); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("bus", -1e-3); + legs = router.calcRoute(DefaultRoutingRequest.withoutAttributes(new FakeFacility(fromCoord), new FakeFacility(toCoord), 6.0*3600 - 60.0, null)); + assertEquals(3, legs.size()); + assertEquals("red", ((TransitPassengerRoute) ((Leg) legs.get(1)).getRoute()).getLineId().toString()); + + // routing by transport mode, train is quicker, but more costly now, so choose blue (bus) + raptorParams.setUseTransportModeUtilities(true); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("train", -1e-2); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("bus", -1e-3); + legs = router.calcRoute(DefaultRoutingRequest.withoutAttributes(new FakeFacility(fromCoord), new FakeFacility(toCoord), 6.0*3600 - 60.0, null)); + assertEquals(3, legs.size()); + assertEquals("blue", ((TransitPassengerRoute) ((Leg) legs.get(1)).getRoute()).getLineId().toString()); + } @Test void testFasterAlternative() { diff --git a/matsim/src/test/java/org/matsim/core/replanning/annealing/ReplanningAnnealerTest.java b/matsim/src/test/java/org/matsim/core/replanning/annealing/ReplanningAnnealerTest.java index d16b44098a6..760d3e430e2 100644 --- a/matsim/src/test/java/org/matsim/core/replanning/annealing/ReplanningAnnealerTest.java +++ b/matsim/src/test/java/org/matsim/core/replanning/annealing/ReplanningAnnealerTest.java @@ -39,6 +39,19 @@ public class ReplanningAnnealerTest { "8;0.1000;0.0500;0.0500;0.9000\n" + "9;0.0500;0.0250;0.0250;0.9500\n" + "10;0.0000;0.0000;0.0000;1.0000\n"; + + private String expectedLinearAnnealMultipleSubpopulations = "it;globalInnovationRate_otherAnnealer;ChangeExpBeta_otherAnnealer;TimeAllocationMutator_otherAnnealer;globalInnovationRate_subpop;ReRoute_subpop;SubtourModeChoice_subpop;ChangeExpBeta_subpop\n" + + "0;0.8000;0.2000;0.8000;0.5000;0.2500;0.2500;0.5000\n" + + "1;0.7200;0.2800;0.7200;0.4500;0.2250;0.2250;0.5500\n" + + "2;0.6400;0.3600;0.6400;0.4000;0.2000;0.2000;0.6000\n" + + "3;0.5600;0.4400;0.5600;0.3500;0.1750;0.1750;0.6500\n" + + "4;0.4800;0.5200;0.4800;0.3000;0.1500;0.1500;0.7000\n" + + "5;0.4000;0.6000;0.4000;0.2500;0.1250;0.1250;0.7500\n" + + "6;0.3200;0.6800;0.3200;0.2000;0.1000;0.1000;0.8000\n" + + "7;0.2400;0.7600;0.2400;0.1500;0.0750;0.0750;0.8500\n" + + "8;0.1600;0.8400;0.1600;0.1000;0.0500;0.0500;0.9000\n" + + "9;0.0800;0.9200;0.0800;0.0500;0.0250;0.0250;0.9500\n" + + "10;0.0000;1.0000;0.0000;0.0000;0.0000;0.0000;1.0000\n"; private String expectedMsaAnneal = "it;globalInnovationRate;ReRoute;SubtourModeChoice;ChangeExpBeta\n" + "0;0.5000;0.2500;0.2500;0.5000\n" + @@ -360,21 +373,65 @@ void testSubpopulationAnneal() throws IOException { this.saConfigVar.setStartValue(0.5); this.saConfigVar.setDefaultSubpopulation(targetSubpop); this.config.replanning().getStrategySettings().forEach(s -> s.setSubpopulation(targetSubpop)); - ReplanningConfigGroup.StrategySettings s = new ReplanningConfigGroup.StrategySettings(); - s.setStrategyName("TimeAllocationMutator"); - s.setWeight(0.25); - s.setSubpopulation("noAnneal"); - this.config.replanning().addStrategySettings(s); + + String otherAnnealerSubpopulation = "otherAnnealer"; + String othertargetSubpop = otherAnnealerSubpopulation; + ReplanningAnnealerConfigGroup.AnnealingVariable saConfigVar2 = new ReplanningAnnealerConfigGroup.AnnealingVariable(); + saConfigVar2.setAnnealType("linear"); + saConfigVar2.setEndValue(0.0); + saConfigVar2.setStartValue(0.8); + saConfigVar2.setDefaultSubpopulation(othertargetSubpop); + this.config.replanningAnnealer().addParameterSet(saConfigVar2); + + ReplanningConfigGroup.StrategySettings s = new ReplanningConfigGroup.StrategySettings(); + s.setStrategyName("TimeAllocationMutator"); + s.setWeight(0.25); + s.setSubpopulation(otherAnnealerSubpopulation); + ReplanningConfigGroup.StrategySettings s2 = new ReplanningConfigGroup.StrategySettings(); + s2.setStrategyName("ChangeExpBeta"); // shouldn't be affected + s2.setWeight(0.5); + s2.setSubpopulation(otherAnnealerSubpopulation); + this.config.replanning().addStrategySettings(s2); + this.config.replanning().addStrategySettings(s); + + + ReplanningConfigGroup.StrategySettings noAnnealSettings = new ReplanningConfigGroup.StrategySettings(); + noAnnealSettings.setStrategyName("TimeAllocationMutator"); + noAnnealSettings.setWeight(0.25); + noAnnealSettings.setSubpopulation("noAnneal"); + this.config.replanning().addStrategySettings(noAnnealSettings); Controler controler = new Controler(this.scenario); controler.run(); - Assertions.assertEquals(expectedLinearAnneal, readResult(controler.getControlerIO().getOutputFilename(FILENAME_ANNEAL))); + Assertions.assertEquals(expectedLinearAnnealMultipleSubpopulations, readResult(controler.getControlerIO().getOutputFilename(FILENAME_ANNEAL))); StrategyManager sm = controler.getInjector().getInstance(StrategyManager.class); List weights = sm.getWeights(targetSubpop); + List weights2 = sm.getWeights(otherAnnealerSubpopulation); Assertions.assertEquals(1.0, weights.stream().mapToDouble(Double::doubleValue).sum(), 1e-4); + Assertions.assertEquals(1.0, weights2.stream().mapToDouble(Double::doubleValue).sum(), 1e-4); } + @Test + void testNullSubpopulationAnneal() throws IOException { + String targetSubpop = null; + this.saConfigVar.setAnnealType("linear"); + this.saConfigVar.setEndValue(0.0); + this.saConfigVar.setStartValue(0.5); + this.saConfigVar.setDefaultSubpopulation(targetSubpop); + this.config.replanning().getStrategySettings().forEach(s -> s.setSubpopulation(targetSubpop)); + + Controler controler = new Controler(this.scenario); + controler.run(); + + Assertions.assertEquals(expectedLinearAnneal, readResult(controler.getControlerIO().getOutputFilename(FILENAME_ANNEAL))); + + StrategyManager sm = controler.getInjector().getInstance(StrategyManager.class); + List weights = sm.getWeights(targetSubpop); + + Assertions.assertEquals(1.0, weights.stream().mapToDouble(Double::doubleValue).sum(), 1e-4); + } + } diff --git a/matsim/src/test/java/org/matsim/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 00000000000..7bf62ca48e2 Binary files /dev/null and b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/correct.fp.zst differ 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 00000000000..6437b813ac0 Binary files /dev/null and b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-type-count.fp.zst differ diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-type-count.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-type-count.xml new file mode 100644 index 00000000000..31662fae9c0 --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.diff-type-count.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order-wrong_logic.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order-wrong_logic.xml new file mode 100644 index 00000000000..1112364be0c --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order-wrong_logic.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order.xml new file mode 100644 index 00000000000..c4b9bbf33de --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.event-order.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.one-more-event.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.one-more-event.xml new file mode 100644 index 00000000000..663754db63f --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events.one-more-event.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events_correct.xml b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events_correct.xml new file mode 100644 index 00000000000..4b2bbbd1b92 --- /dev/null +++ b/matsim/test/input/org/matsim/utils/eventsfilecomparison/EventsFileFingerprintComparatorTest/events_correct.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8ab3815ad40..7ae87ef3a92 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 @@ -138,7 +138,7 @@ commons-io commons-io - 2.15.1 + 2.16.0 com.opencsv @@ -212,7 +212,7 @@ com.fasterxml.woodstox woodstox-core - 6.6.1 + 6.6.2 @@ -344,10 +344,16 @@ 0.43.1 + + com.google.j2objc + j2objc-annotations + 3.0.0 + + net.bytebuddy byte-buddy - 1.14.12 + 1.14.13 test @@ -359,7 +365,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.12.1 + 3.13.0 org.apache.maven.plugins @@ -420,7 +426,7 @@ org.apache.maven.plugins maven-source-plugin - 3.3.0 + 3.3.1 org.apache.maven.plugins @@ -492,7 +498,7 @@ org.jacoco jacoco-maven-plugin - 0.8.11 + 0.8.12 default-prepare-agent