diff --git a/.github/workflows/deploy-dtds.yaml b/.github/workflows/deploy-dtds.yaml
index bb48f61d27b..09d94069d76 100644
--- a/.github/workflows/deploy-dtds.yaml
+++ b/.github/workflows/deploy-dtds.yaml
@@ -1,18 +1,20 @@
name: deploy-dtds-on-website
on:
- push:
- branches:
- - master
+ pull_request:
+ types:
+ - closed
paths:
- - matsim/src/main/resources/dtd
+ - 'matsim/src/main/resources/dtd/**'
jobs:
rsync-dtds:
+ if: github.event.pull_request.merged == true # only if PR closed by merging
name: sync DTDs to website
runs-on: ubuntu-latest
steps:
+ - uses: actions/checkout@v4
- name: rsync dtds
uses: burnett01/rsync-deployments@7.0.1
with:
diff --git a/.github/workflows/full-integration.yaml b/.github/workflows/full-integration.yaml
index a75ea5767da..2c20cb48d31 100644
--- a/.github/workflows/full-integration.yaml
+++ b/.github/workflows/full-integration.yaml
@@ -14,7 +14,8 @@ jobs:
strategy:
fail-fast: false
matrix:
- os: [ubuntu-latest, windows-latest, macos-latest]
+ os: [ubuntu-latest, windows-latest]
+ #os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Prepare git
diff --git a/contribs/accessibility/pom.xml b/contribs/accessibility/pom.xml
index c4ead8bf378..f08160490b9 100644
--- a/contribs/accessibility/pom.xml
+++ b/contribs/accessibility/pom.xml
@@ -37,12 +37,12 @@
org.matsim.contribmatrixbasedptrouter
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribroadpricing
- 2025.0-SNAPSHOT
+ ${project.parent.version}net.sf.trove4j
@@ -70,7 +70,7 @@
org.matsim.contribanalysis
- 2025.0-SNAPSHOT
+ ${project.parent.version}
diff --git a/contribs/analysis/pom.xml b/contribs/analysis/pom.xml
index 74a32b64c03..eea01c79ffb 100644
--- a/contribs/analysis/pom.xml
+++ b/contribs/analysis/pom.xml
@@ -13,7 +13,7 @@
org.matsim.contribroadpricing
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.osgeo
diff --git a/contribs/application/pom.xml b/contribs/application/pom.xml
index e8ec00d4800..b427dfbfcf9 100644
--- a/contribs/application/pom.xml
+++ b/contribs/application/pom.xml
@@ -40,37 +40,37 @@
org.matsim.contribotfvis
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribosm
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribsumo
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribanalysis
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribemissions
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribnoise
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribfreight
- 2025.0-SNAPSHOT
+ ${project.parent.version}
@@ -87,7 +87,7 @@
com.github.matsim-orggtfs2matsim
- 47b0802a29
+ 19f1676fc6
@@ -151,7 +151,7 @@
org.matsim.contribdvrp
- 2025.0-SNAPSHOT
+ ${project.parent.version}compile
diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java
index 120f9711ba6..8d8e341154d 100644
--- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java
+++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java
@@ -53,7 +53,8 @@ public class ApplyNetworkParams implements MATSimAppCommand {
@CommandLine.Option(names = "--model", description = "Reference to the network model class", required = true)
private Class extends NetworkModel> modelClazz;
- @CommandLine.Option(names = "--factor-bounds", split = ",", description = "Speed factor limits (lower,upper bound)", defaultValue = NetworkParamsOpt.DEFAULT_FACTOR_BOUNDS)
+ @CommandLine.Option(names = "--factor-bounds", split = ",", description = "Speed factor limits (lower, upper bound). " +
+ "Can be negative to indicate absolute speed bounds (in km/h)", defaultValue = NetworkParamsOpt.DEFAULT_FACTOR_BOUNDS)
private double[] speedFactorBounds;
@CommandLine.Option(names = "--capacity-bounds", split = ",", defaultValue = "0.4,0.6,0.8",
@@ -234,23 +235,40 @@ private boolean applyFreeSpeed(Link link, Feature ft) {
return false;
}
+ double allowedSpeed = (double) link.getAttributes().getAttribute("allowed_speed");
+ double freeSpeed = allowedSpeed * speedFactor;
+
boolean modified = false;
- if (speedFactor > speedFactorBounds[1]) {
+ if (speedFactor > speedFactorBounds[1] && speedFactorBounds[1] >= 0) {
log.warn("Reducing speed factor on {} from {} to {}", link.getId(), speedFactor, speedFactorBounds[1]);
speedFactor = speedFactorBounds[1];
modified = true;
}
+ // Use absolute bound for speed
+ if (freeSpeed > -speedFactorBounds[1]/3.6 && speedFactorBounds[1] < 0) {
+ log.warn("Reducing speed on {} from {} to {}", link.getId(), freeSpeed, -speedFactorBounds[1]/3.6);
+ speedFactor = (-speedFactorBounds[1] / 3.6) / allowedSpeed;
+ modified = true;
+ }
+
// Threshold for very low speed factors
- if (speedFactor < speedFactorBounds[0]) {
+ if (speedFactor < speedFactorBounds[0] && speedFactorBounds[0] >= 0) {
log.warn("Increasing speed factor on {} from {} to {}", link, speedFactor, speedFactorBounds[0]);
speedFactor = speedFactorBounds[0];
modified = true;
}
- double freeSpeed = (double) link.getAttributes().getAttribute("allowed_speed") * speedFactor;
+ // Absolute negative speed factor
+ if (freeSpeed < -speedFactorBounds[0]/3.6 && speedFactorBounds[0] < 0) {
+ log.warn("Increasing speed on {} from {} to {}", link, freeSpeed, -speedFactorBounds[0]/3.6);
+ speedFactor = (-speedFactorBounds[0] / 3.6) / allowedSpeed;
+ modified = true;
+ }
+ // Recalculate with updated speed factor
+ freeSpeed = allowedSpeed * speedFactor;
freeSpeed = BigDecimal.valueOf(freeSpeed).setScale(3, RoundingMode.HALF_EVEN).doubleValue();
if (decrease && freeSpeed > link.getFreespeed())
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
index cd2ba4e016a..68cd6099058 100644
--- 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
@@ -121,12 +121,27 @@ static Result applyAndEvaluateParams(
speedFactor = speedModel.predict(ft.features(), ft.categories());
// apply lower and upper bound
- speedFactor = Math.max(speedFactorBounds[0], speedFactor);
- speedFactor = Math.min(speedFactorBounds[1], speedFactor);
+ if (speedFactorBounds[0] >= 0)
+ speedFactor = Math.max(speedFactorBounds[0], speedFactor);
+
+ if (speedFactorBounds[1] >= 0)
+ speedFactor = Math.min(speedFactorBounds[1], speedFactor);
attributes.put(link.getId(), speedModel.getData(ft.features(), ft.categories()));
- link.setFreespeed(allowedSpeed * speedFactor);
+ double freespeed = allowedSpeed * speedFactor;
+
+ // Check absolute bounds on the freespeed
+ if (speedFactorBounds[0] < 0 && freespeed < -speedFactorBounds[0]/3.6) {
+ freespeed = -speedFactorBounds[0]/3.6;
+ speedFactor = freespeed / allowedSpeed;
+ }
+ if (speedFactorBounds[1] < 0 && freespeed > -speedFactorBounds[1]/3.6) {
+ freespeed = -speedFactorBounds[1]/3.6;
+ speedFactor = freespeed / allowedSpeed;
+ }
+
+ link.setFreespeed(freespeed);
link.getAttributes().putAttribute("speed_factor", speedFactor);
} else
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
index fef19850305..c17189b3a95 100644
--- 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
@@ -57,7 +57,8 @@ public class FreespeedOptServer implements MATSimAppCommand {
@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)
+ @CommandLine.Option(names = "--factor-bounds", split = ",", description = "Speed factor limits (lower, upper bound). " +
+ "Can be negative to indicate absolute speed bounds (in km/h)", defaultValue = NetworkParamsOpt.DEFAULT_FACTOR_BOUNDS)
private double[] speedFactorBounds;
@CommandLine.Option(names = "--ref-hours", description = "Reference hours", defaultValue = "3,21", split = ",")
diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/pt/CreateTransitScheduleFromGtfs.java b/contribs/application/src/main/java/org/matsim/application/prepare/pt/CreateTransitScheduleFromGtfs.java
index ddbe0e7868a..5483167fcdf 100644
--- a/contribs/application/src/main/java/org/matsim/application/prepare/pt/CreateTransitScheduleFromGtfs.java
+++ b/contribs/application/src/main/java/org/matsim/application/prepare/pt/CreateTransitScheduleFromGtfs.java
@@ -25,6 +25,7 @@
import org.matsim.core.utils.io.IOUtils;
import org.matsim.pt.transitSchedule.api.*;
import org.matsim.pt.utils.CreatePseudoNetwork;
+import org.matsim.pt.utils.CreatePseudoNetworkWithLoopLinks;
import org.matsim.pt.utils.TransitScheduleValidator;
import org.matsim.vehicles.*;
import picocli.CommandLine;
@@ -85,8 +86,8 @@ public class CreateTransitScheduleFromGtfs implements MATSimAppCommand {
@CommandLine.Option(names = "--transform-schedule", description = "Fully qualified class name to a Consumer to be executed after the schedule was created", arity = "0..*", split = ",")
private List> transformSchedule;
- @CommandLine.Option(names = "--merge-stops", description = "Whether stops should be merged by coordinate")
- private boolean mergeStops;
+ @CommandLine.Option(names = "--merge-stops", description = "Whether stops should be merged by coordinate", defaultValue = "doNotMerge")
+ private GtfsConverter.MergeGtfsStops mergeStops;
@CommandLine.Option(names = "--prefix", description = "Prefixes to add to the gtfs ids. Required if multiple inputs are used and ids are not unique.", split = ",")
private List prefixes = new ArrayList<>();
@@ -100,10 +101,29 @@ public class CreateTransitScheduleFromGtfs implements MATSimAppCommand {
@CommandLine.Option(names = "--shp-crs", description = "Overwrite coordinate system of the shape file")
private String shpCrs;
+ @CommandLine.Option(names = "--pseudo-network", description = "Define how the pseudo network should be created", defaultValue = "singleLinkBetweenStops")
+ private PseudoNetwork pseudoNetwork;
+
+
public static void main(String[] args) {
System.exit(new CommandLine(new CreateTransitScheduleFromGtfs()).execute(args));
}
+ private static void addHbefaMapping(VehicleType vehicleType, HbefaVehicleCategory category) {
+ EngineInformation carEngineInformation = vehicleType.getEngineInformation();
+ VehicleUtils.setHbefaVehicleCategory(carEngineInformation, String.valueOf(category));
+ VehicleUtils.setHbefaTechnology(carEngineInformation, "average");
+ VehicleUtils.setHbefaSizeClass(carEngineInformation, "average");
+ VehicleUtils.setHbefaEmissionsConcept(carEngineInformation, "average");
+ vehicleType.setNetworkMode(TransportMode.pt);
+ }
+
+ private static void increaseLinkFreespeedIfLower(Link link, double newFreespeed) {
+ if (link.getFreespeed() < newFreespeed) {
+ link.setFreespeed(newFreespeed);
+ }
+ }
+
@Override
public Integer call() throws Exception {
@@ -183,6 +203,13 @@ public Integer call() throws Exception {
Scenario ptScenario = getScenarioWithPseudoPtNetworkAndTransitVehicles(network, scenario.getTransitSchedule(), "pt_");
+ for (TransitLine line : new ArrayList<>(scenario.getTransitSchedule().getTransitLines().values())) {
+ if (line.getRoutes().isEmpty()) {
+ log.warn("Line {} with no routes removed.", line.getId());
+ scenario.getTransitSchedule().removeTransitLine(line);
+ }
+ }
+
if (validate) {
//Check schedule and network
TransitScheduleValidator.ValidationResult checkResult = TransitScheduleValidator.validateAll(ptScenario.getTransitSchedule(), ptScenario.getNetwork());
@@ -237,14 +264,19 @@ private Predicate createFilter(int i) throws Exception {
/**
* Creates the pt scenario and network.
*/
- private static Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network network, TransitSchedule schedule, String ptNetworkIdentifier) {
+ private Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network network, TransitSchedule schedule, String ptNetworkIdentifier) {
ScenarioUtils.ScenarioBuilder builder = new ScenarioUtils.ScenarioBuilder(ConfigUtils.createConfig());
builder.setNetwork(network);
builder.setTransitSchedule(schedule);
Scenario scenario = builder.build();
// add pseudo network for pt
- new CreatePseudoNetwork(scenario.getTransitSchedule(), scenario.getNetwork(), ptNetworkIdentifier, 0.1, 100000.0).createNetwork();
+ switch (pseudoNetwork) {
+ case singleLinkBetweenStops ->
+ new CreatePseudoNetwork(scenario.getTransitSchedule(), scenario.getNetwork(), ptNetworkIdentifier, 0.1, 100000.0).createNetwork();
+ case withLoopLinks ->
+ new CreatePseudoNetworkWithLoopLinks(scenario.getTransitSchedule(), scenario.getNetwork(), ptNetworkIdentifier, 0.1, 100000.0).createNetwork();
+ }
// create TransitVehicle types
// see https://svn.vsp.tu-berlin.de/repos/public-svn/publications/vspwp/2014/14-24/ for veh capacities
@@ -449,8 +481,12 @@ private static Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network
// so we need to add time for passengers to board and alight
double minStopTime = 30.0;
+ List> routeIds = new LinkedList<>();
+ routeIds.add(route.getRoute().getStartLinkId());
+ routeIds.addAll(route.getRoute().getLinkIds());
+ routeIds.add(route.getRoute().getEndLinkId());
+
for (int i = 1; i < routeStops.size(); i++) {
- // TODO cater for loop link at first stop? Seems to just work without.
TransitRouteStop routeStop = routeStops.get(i);
// if there is no departure offset set (or infinity), it is the last stop of the line,
// so we don't need to care about the stop duration
@@ -462,8 +498,23 @@ private static Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network
// Math.max to avoid negative values of travelTime
double travelTime = Math.max(1, routeStop.getArrivalOffset().seconds() - lastDepartureOffset - 1.0 -
(stopDuration >= minStopTime ? 0 : (minStopTime - stopDuration)));
- Link link = network.getLinks().get(routeStop.getStopFacility().getLinkId());
- increaseLinkFreespeedIfLower(link, link.getLength() / travelTime);
+
+
+ Id stopLink = routeStop.getStopFacility().getLinkId();
+ List> subRoute = new LinkedList<>();
+ do {
+ Id linkId = routeIds.removeFirst();
+ subRoute.add(linkId);
+ } while (!subRoute.contains(stopLink));
+
+ List extends Link> links = subRoute.stream().map(scenario.getNetwork().getLinks()::get)
+ .toList();
+
+ double length = links.stream().mapToDouble(Link::getLength).sum();
+
+ for (Link link : links) {
+ increaseLinkFreespeedIfLower(link, length / travelTime);
+ }
lastDepartureOffset = routeStop.getDepartureOffset().seconds();
}
@@ -481,20 +532,15 @@ private static Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network
return scenario;
}
- private static void addHbefaMapping(VehicleType vehicleType, HbefaVehicleCategory category) {
- EngineInformation carEngineInformation = vehicleType.getEngineInformation();
- VehicleUtils.setHbefaVehicleCategory(carEngineInformation, String.valueOf(category));
- VehicleUtils.setHbefaTechnology(carEngineInformation, "average");
- VehicleUtils.setHbefaSizeClass(carEngineInformation, "average");
- VehicleUtils.setHbefaEmissionsConcept(carEngineInformation, "average");
- vehicleType.setNetworkMode(TransportMode.pt);
- }
-
- private static void increaseLinkFreespeedIfLower(Link link, double newFreespeed) {
- if (link.getFreespeed() < newFreespeed) {
- link.setFreespeed(newFreespeed);
- }
+ public enum PseudoNetwork {
+ /**
+ * Create links between all stops and possibly duplicate stops.
+ */
+ singleLinkBetweenStops,
+ /**
+ * Create a pseudo network with loop links at each stop.
+ */
+ withLoopLinks,
}
-
}
diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/scenario/CreateScenarioCutOut.java b/contribs/application/src/main/java/org/matsim/application/prepare/scenario/CreateScenarioCutOut.java
index 4dcd8a6bf5a..909d311d64f 100644
--- a/contribs/application/src/main/java/org/matsim/application/prepare/scenario/CreateScenarioCutOut.java
+++ b/contribs/application/src/main/java/org/matsim/application/prepare/scenario/CreateScenarioCutOut.java
@@ -590,9 +590,12 @@ public void run(Person person) {
}
// Remove all unselected plans because these are not handled
- person.getPlans().stream()
- .filter(p -> p != person.getSelectedPlan())
- .forEach(person::removePlan);
+ List plans = new ArrayList<>(person.getPlans());
+ for(Plan p : plans){
+ if (p != person.getSelectedPlan()){
+ person.removePlan(p);
+ }
+ }
}
diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DefaultJobDurationCalculator.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DefaultJobDurationCalculator.java
new file mode 100644
index 00000000000..42ddbc4068a
--- /dev/null
+++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DefaultJobDurationCalculator.java
@@ -0,0 +1,37 @@
+package org.matsim.freightDemandGeneration;
+
+import org.matsim.api.core.v01.Scenario;
+
+public class DefaultJobDurationCalculator implements JobDurationCalculator {
+ @Override
+ public double calculateServiceDuration(Integer serviceTimePerUnit, int demandForThisService) {
+ return getDefaultCalculation(serviceTimePerUnit, demandForThisService);
+ }
+
+ @Override
+ public double calculatePickupDuration(Integer pickupDurationPerUnit, int demandForThisShipment) {
+ return getDefaultCalculation(pickupDurationPerUnit, demandForThisShipment);
+ }
+
+ @Override
+ public double calculateDeliveryDuration(Integer deliveryDurationPerUnit, int demandForThisShipment) {
+ return getDefaultCalculation(deliveryDurationPerUnit, demandForThisShipment);
+ }
+
+ @Override
+ public void recalculateJobDurations(Scenario scenario) {
+ // do nothing
+ }
+
+ /**
+ * @param timePerUnit time per unit
+ * @param demandForThisService demand for this service
+ * @return default calculation
+ */
+ private int getDefaultCalculation(int timePerUnit, int demandForThisService) {
+ if (demandForThisService == 0)
+ return timePerUnit;
+ else
+ return timePerUnit * demandForThisService;
+ }
+}
diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java
index e39eedd9ad4..63179128cc4 100644
--- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java
+++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java
@@ -324,16 +324,18 @@ public String getTypeOfDemand() {
* @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file
* @param population Population
* @param shapeCategory Column name in the shape file for the data connection in the csv files
- * @throws IOException if the csv file cannot be read
+ * @param jobDurationCalculator Calculator for the job duration
+ * @throws IOException if the csv file cannot be read
*/
static void readAndCreateDemand(Scenario scenario, Path csvLocationDemand,
ShpOptions.Index indexShape, boolean combineSimilarJobs,
- CoordinateTransformation crsTransformationNetworkAndShape, Population population, String shapeCategory) throws IOException {
+ CoordinateTransformation crsTransformationNetworkAndShape, Population population, String shapeCategory,
+ JobDurationCalculator jobDurationCalculator) throws IOException {
Set demandInformation = readDemandInformation(csvLocationDemand);
checkNewDemand(scenario, demandInformation, indexShape, shapeCategory);
createDemandForCarriers(scenario, indexShape, demandInformation, population, combineSimilarJobs,
- crsTransformationNetworkAndShape);
+ crsTransformationNetworkAndShape, jobDurationCalculator);
}
/**
@@ -538,42 +540,45 @@ static void checkNewDemand(Scenario scenario, Set dema
/**
* Creates for every demand information the services/shipments for the carriers
*
- * @param scenario Scenario
- * @param indexShape ShpOptions.Index for the shape file
- * @param demandInformation Set with the demand information
- * @param population Population
- * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined
- * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file
+ * @param scenario Scenario
+ * @param indexShape ShpOptions.Index for the shape file
+ * @param demandInformation Set with the demand information
+ * @param population Population
+ * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined
+ * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file
+ * @param jobDurationCalculator Calculator for the job duration
*/
static void createDemandForCarriers(Scenario scenario, ShpOptions.Index indexShape,
- Set demandInformation, Population population, boolean combineSimilarJobs,
- CoordinateTransformation crsTransformationNetworkAndShape) {
+ Set demandInformation, Population population, boolean combineSimilarJobs,
+ CoordinateTransformation crsTransformationNetworkAndShape, JobDurationCalculator jobDurationCalculator) {
for (DemandInformationElement newDemandInformationElement : demandInformation) {
log.info("Create demand for carrier {}", newDemandInformationElement.getCarrierName());
if (newDemandInformationElement.getTypeOfDemand().equals("service"))
- createServices(scenario, newDemandInformationElement, indexShape, population, combineSimilarJobs,
- crsTransformationNetworkAndShape);
+ createServices(scenario, newDemandInformationElement, indexShape, population,
+ crsTransformationNetworkAndShape, jobDurationCalculator);
else if (newDemandInformationElement.getTypeOfDemand().equals("shipment"))
- createShipments(scenario, newDemandInformationElement, indexShape, population, combineSimilarJobs,
- crsTransformationNetworkAndShape);
+ createShipments(scenario, newDemandInformationElement, indexShape, population,
+ crsTransformationNetworkAndShape, jobDurationCalculator);
}
-
+ if (combineSimilarJobs)
+ combineSimilarJobs(scenario);
+ jobDurationCalculator.recalculateJobDurations(scenario);
}
/**
* Creates the services.
*
- * @param scenario Scenario
- * @param newDemandInformationElement single DemandInformationElement
- * @param indexShape ShpOptions.Index
- * @param population Population
- * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined
- * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file
+ * @param scenario Scenario
+ * @param newDemandInformationElement single DemandInformationElement
+ * @param indexShape ShpOptions.Index
+ * @param population Population
+ * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file
+ * @param jobDurationCalculator Calculator for the job duration
*/
private static void createServices(Scenario scenario, DemandInformationElement newDemandInformationElement,
- ShpOptions.Index indexShape, Population population, boolean combineSimilarJobs,
- CoordinateTransformation crsTransformationNetworkAndShape) {
+ ShpOptions.Index indexShape, Population population,
+ CoordinateTransformation crsTransformationNetworkAndShape, JobDurationCalculator jobDurationCalculator) {
int countOfLinks = 1;
int distributedDemand = 0;
@@ -643,8 +648,8 @@ else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) {
Link link = findNextUsedLink(scenario, indexShape, possibleLinksForService, numberOfJobs,
areasForServiceLocations, locationsOfServices, usedServiceLocations,
possiblePersonsForService, nearestLinkPerPerson, crsTransformationNetworkAndShape, i);
- double serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit();
int demandForThisLink = 1;
+ double serviceTime = jobDurationCalculator.calculateServiceDuration(newDemandInformationElement.getFirstJobElementTimePerUnit(), demandForThisLink);
usedServiceLocations.add(link.getId().toString());
Id idNewService = Id.create(
createJobId(scenario, newDemandInformationElement, link.getId(), null),
@@ -673,13 +678,19 @@ else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) {
countOfLinks++;
Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers()
.get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class));
- int numberOfJobsForDemand = calculateNumberOfJobsForDemand(thisCarrier, demandForThisLink);
- for (int i = 0; i < numberOfJobsForDemand; i++) {
- int singleDemandForThisLink = demandForThisLink / numberOfJobsForDemand;
- if (i == numberOfJobsForDemand - 1)
- singleDemandForThisLink = demandForThisLink - (numberOfJobsForDemand - 1) * singleDemandForThisLink;
- double serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit()
- * singleDemandForThisLink;
+ int handledDemand = 0;
+ //the number of jobs on this link is calculated based on the available vehicles
+ double largestPossibleDemandSize = getLargestVehicleCapacity(thisCarrier);
+ while (handledDemand < demandForThisLink) {
+ int singleDemandForThisLink;
+ if (demandForThisLink - handledDemand < largestPossibleDemandSize)
+ singleDemandForThisLink = demandForThisLink - handledDemand;
+ else
+ singleDemandForThisLink = (int)largestPossibleDemandSize;
+ handledDemand = handledDemand + singleDemandForThisLink;
+ double serviceTime = jobDurationCalculator.calculateServiceDuration(
+ newDemandInformationElement.getFirstJobElementTimePerUnit(), singleDemandForThisLink);
+
Id idNewService = Id.create(
createJobId(scenario, newDemandInformationElement, link.getId(), null),
CarrierService.class);
@@ -718,16 +729,18 @@ else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) {
int demandForThisLink = calculateDemandForThisLink(demandToDistribute, numberOfJobs, distributedDemand, i);
Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers()
.get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class));
- int numberOfJobsForDemand = calculateNumberOfJobsForDemand(thisCarrier, demandForThisLink);
- for (int j = 0; j < numberOfJobsForDemand; j++) {
- int singleDemandForThisLink = demandForThisLink / numberOfJobsForDemand;
- if (j == numberOfJobsForDemand - 1)
- singleDemandForThisLink = demandForThisLink - (numberOfJobsForDemand - 1) * singleDemandForThisLink;
- double serviceTime;
- if (singleDemandForThisLink == 0)
- serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit();
+ int handledDemand = 0;
+ //the number of jobs on this link is calculated based on the available vehicles
+ double largestPossibleDemandSize = getLargestVehicleCapacity(thisCarrier);
+ while (handledDemand < demandForThisLink || demandToDistribute == 0) {
+ int singleDemandForThisLink;
+ if (demandForThisLink - handledDemand < largestPossibleDemandSize)
+ singleDemandForThisLink = demandForThisLink - handledDemand;
else
- serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit() * demandForThisLink;
+ singleDemandForThisLink = (int)largestPossibleDemandSize;
+ handledDemand = handledDemand + singleDemandForThisLink;
+ double serviceTime = jobDurationCalculator.calculateServiceDuration(
+ newDemandInformationElement.getFirstJobElementTimePerUnit(), singleDemandForThisLink);
usedServiceLocations.add(link.getId().toString());
Id idNewService = Id.create(
@@ -740,28 +753,28 @@ else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) {
CarriersUtils.getCarriers(scenario).getCarriers()
.get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)).getServices()
.put(thisService.getId(), thisService);
+ if (demandToDistribute == 0)
+ break;
}
}
distributedDemand = distributedDemand + demandForThisLink;
}
}
- if (combineSimilarJobs)
- reduceNumberOfJobsIfSameCharacteristics(scenario, newDemandInformationElement);
}
/**
* Creates the shipments of a carrier.
*
- * @param scenario Scenario
- * @param newDemandInformationElement single DemandInformationElement
- * @param indexShape ShpOptions.Index for the shape file
- * @param population Population
- * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined
- * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file
+ * @param scenario Scenario
+ * @param newDemandInformationElement single DemandInformationElement
+ * @param indexShape ShpOptions.Index for the shape file
+ * @param population Population
+ * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file
+ * @param jobDurationCalculator Calculator for the job duration
*/
private static void createShipments(Scenario scenario, DemandInformationElement newDemandInformationElement,
- ShpOptions.Index indexShape, Population population, boolean combineSimilarJobs,
- CoordinateTransformation crsTransformationNetworkAndShape) {
+ ShpOptions.Index indexShape, Population population,
+ CoordinateTransformation crsTransformationNetworkAndShape, JobDurationCalculator jobDurationCalculator) {
int countOfLinks = 1;
int distributedDemand = 0;
@@ -900,7 +913,7 @@ else if (population == null)
if (!usedDeliveryLocations.contains(linkDelivery.getId().toString()))
usedDeliveryLocations.add(linkDelivery.getId().toString());
- createSingleShipment(scenario, newDemandInformationElement, linkPickup, linkDelivery, demandForThisLink);
+ createSingleShipment(scenario, newDemandInformationElement, linkPickup, linkDelivery, demandForThisLink, jobDurationCalculator);
}
} else
// creates a demand on each link, demand depends on the length of the link
@@ -968,7 +981,7 @@ else if (numberOfPickupLocations != null) {
if (demandForThisLink > 0) {
createSingleShipment(scenario, newDemandInformationElement, linkPickup, linkDelivery,
- demandForThisLink);
+ demandForThisLink, jobDurationCalculator);
}
distributedDemand = distributedDemand + demandForThisLink;
}
@@ -998,52 +1011,52 @@ else if (numberOfPickupLocations != null) {
usedDeliveryLocations.add(linkDelivery.getId().toString());
createSingleShipment(scenario, newDemandInformationElement, linkPickup, linkDelivery,
- demandForThisLink);
+ demandForThisLink, jobDurationCalculator);
distributedDemand = distributedDemand + demandForThisLink;
}
}
- if (combineSimilarJobs)
- reduceNumberOfJobsIfSameCharacteristics(scenario, newDemandInformationElement);
}
- /** Creates a single shipment.
+ /**
+ * Creates a single shipment.
+ *
* @param scenario Scenario
* @param newDemandInformationElement single DemandInformationElement
* @param linkPickup Link for the pickup
* @param linkDelivery Link for the delivery
* @param demandForThisLink Demand for this link
+ * @param jobDurationCalculator Calculator for the job duration
*/
private static void createSingleShipment(Scenario scenario, DemandInformationElement newDemandInformationElement,
- Link linkPickup, Link linkDelivery, int demandForThisLink) {
+ Link linkPickup, Link linkDelivery, int demandForThisLink, JobDurationCalculator jobDurationCalculator) {
Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers()
.get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class));
- int numberOfJobsForDemand = calculateNumberOfJobsForDemand(thisCarrier, demandForThisLink);
-
+ double largestPossibleDemandSize = getLargestVehicleCapacity(thisCarrier);
+ int handledDemand = 0;
TimeWindow timeWindowPickup = newDemandInformationElement.getFirstJobElementTimeWindow();
TimeWindow timeWindowDelivery = newDemandInformationElement.getSecondJobElementTimeWindow();
- for (int i = 0; i < numberOfJobsForDemand; i++) {
+ while (handledDemand < demandForThisLink || demandForThisLink == 0) {
Id idNewShipment = Id.create(createJobId(scenario, newDemandInformationElement,
linkPickup.getId(), linkDelivery.getId()), CarrierShipment.class);
- double serviceTimePickup;
- double serviceTimeDelivery;
- int singleDemandForThisLink = Math.round ((float) demandForThisLink / numberOfJobsForDemand);
- if (i == numberOfJobsForDemand - 1)
- singleDemandForThisLink = demandForThisLink - (numberOfJobsForDemand - 1) * singleDemandForThisLink;
- if (singleDemandForThisLink == 0) {
- serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit();
- serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit();
- } else {
- serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit() * singleDemandForThisLink;
- serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit() * singleDemandForThisLink;
- }
+ int singleDemandForThisLink;
+ if (demandForThisLink - handledDemand < largestPossibleDemandSize)
+ singleDemandForThisLink = demandForThisLink - handledDemand;
+ else
+ singleDemandForThisLink = (int)largestPossibleDemandSize;
+ handledDemand = handledDemand + singleDemandForThisLink;
+ double serviceTimePickup = jobDurationCalculator.calculatePickupDuration(newDemandInformationElement.getFirstJobElementTimePerUnit(), singleDemandForThisLink);
+ double serviceTimeDelivery = jobDurationCalculator.calculateDeliveryDuration(newDemandInformationElement.getSecondJobElementTimePerUnit(), singleDemandForThisLink);
+
CarrierShipment thisShipment = CarrierShipment.Builder
.newInstance(idNewShipment, linkPickup.getId(), linkDelivery.getId(), singleDemandForThisLink)
.setPickupServiceTime(serviceTimePickup).setPickupTimeWindow(timeWindowPickup)
.setDeliveryServiceTime(serviceTimeDelivery).setDeliveryTimeWindow(timeWindowDelivery)
.build();
thisCarrier.getShipments().put(thisShipment.getId(), thisShipment);
+ if (demandForThisLink == 0)
+ break;
}
}
@@ -1051,21 +1064,16 @@ private static void createSingleShipment(Scenario scenario, DemandInformationEle
* Method calculates the number of jobs for a demand on one link based on the largest vehicle capacity of the carrier.
*
* @param thisCarrier the carrier of a job
- * @param demandForThisLink Demand for this link
* @return Number of jobs for this demand
*/
- private static int calculateNumberOfJobsForDemand(Carrier thisCarrier, int demandForThisLink) {
+ private static double getLargestVehicleCapacity(Carrier thisCarrier) {
double largestVehicleCapacity = 0;
for (CarrierVehicle vehicle : thisCarrier.getCarrierCapabilities().getCarrierVehicles().values()) {
if (vehicle.getType().getCapacity().getOther() > largestVehicleCapacity) {
largestVehicleCapacity = vehicle.getType().getCapacity().getOther();
}
}
- if (demandForThisLink > largestVehicleCapacity) {
- log.info("Demand {} is larger than the largest vehicle capacity ({}). Splitting demand into multiple jobs.", demandForThisLink, largestVehicleCapacity);
- return (int) Math.ceil((double) demandForThisLink / largestVehicleCapacity);
- }
- return 1;
+ return largestVehicleCapacity;
}
/**
@@ -1160,109 +1168,102 @@ private static int calculateDemandBasedOnLinkLength(int countOfLinks, int distri
* If jobs of a carrier have the same characteristics (time window, location),
* they will be combined to one job.
*
- * @param scenario Scenario
- * @param newDemandInformationElement single DemandInformationElement
+ * @param scenario Scenario
*/
- private static void reduceNumberOfJobsIfSameCharacteristics(Scenario scenario,
- DemandInformationElement newDemandInformationElement) {
+ private static void combineSimilarJobs(Scenario scenario) {
log.warn(
"The number of Jobs will be reduced if jobs have the same characteristics (e.g. time, location, carrier)");
- int connectedJobs = 0;
- if (newDemandInformationElement.getTypeOfDemand().equals("shipment")) {
- HashMap, CarrierShipment> shipmentsToRemove = new HashMap<>();
- ArrayList shipmentsToAdd = new ArrayList<>();
- Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers()
- .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class));
- for (Id baseShipmentId : thisCarrier.getShipments().keySet()) {
- if (!shipmentsToRemove.containsKey(baseShipmentId)) {
- CarrierShipment baseShipment = thisCarrier.getShipments().get(baseShipmentId);
- HashMap, CarrierShipment> shipmentsToConnect = new HashMap<>();
- shipmentsToConnect.put(baseShipmentId, baseShipment);
- for (Id thisShipmentId : thisCarrier.getShipments().keySet()) {
- if (!shipmentsToRemove.containsKey(thisShipmentId)) {
- CarrierShipment thisShipment = thisCarrier.getShipments().get(thisShipmentId);
- if (baseShipment.getId() != thisShipment.getId()
+ for (Carrier thisCarrier : CarriersUtils.getCarriers(scenario).getCarriers().values()) {
+ if (!thisCarrier.getShipments().isEmpty()) {
+ int shipmentsBeforeConnection = thisCarrier.getShipments().size();
+ HashMap, CarrierShipment> shipmentsToRemove = new HashMap<>();
+ ArrayList shipmentsToAdd = new ArrayList<>();
+ for (Id baseShipmentId : thisCarrier.getShipments().keySet()) {
+ if (!shipmentsToRemove.containsKey(baseShipmentId)) {
+ CarrierShipment baseShipment = thisCarrier.getShipments().get(baseShipmentId);
+ HashMap, CarrierShipment> shipmentsToConnect = new HashMap<>();
+ shipmentsToConnect.put(baseShipmentId, baseShipment);
+ for (Id thisShipmentId : thisCarrier.getShipments().keySet()) {
+ if (!shipmentsToRemove.containsKey(thisShipmentId)) {
+ CarrierShipment thisShipment = thisCarrier.getShipments().get(thisShipmentId);
+ if (baseShipment.getId() != thisShipment.getId()
&& baseShipment.getFrom() == thisShipment.getFrom()
&& baseShipment.getTo() == thisShipment.getTo()
&& baseShipment.getPickupTimeWindow() == thisShipment.getPickupTimeWindow()
&& baseShipment.getDeliveryTimeWindow() == thisShipment.getDeliveryTimeWindow())
- shipmentsToConnect.put(thisShipmentId, thisShipment);
+ shipmentsToConnect.put(thisShipmentId, thisShipment);
+ }
}
- }
- Id idNewShipment = baseShipment.getId();
- int demandForThisLink = 0;
- double serviceTimePickup = 0;
- double serviceTimeDelivery = 0;
- for (CarrierShipment carrierShipment : shipmentsToConnect.values()) {
- demandForThisLink = demandForThisLink + carrierShipment.getSize();
- serviceTimePickup = serviceTimePickup + carrierShipment.getPickupServiceTime();
- serviceTimeDelivery = serviceTimeDelivery + carrierShipment.getDeliveryServiceTime();
- shipmentsToRemove.put(carrierShipment.getId(), carrierShipment);
- connectedJobs++;
- }
- CarrierShipment newShipment = CarrierShipment.Builder
+ Id idNewShipment = baseShipment.getId();
+ int demandForThisLink = 0;
+ double serviceTimePickup = 0;
+ double serviceTimeDelivery = 0;
+ for (CarrierShipment carrierShipment : shipmentsToConnect.values()) {
+ demandForThisLink = demandForThisLink + carrierShipment.getSize();
+ serviceTimePickup = serviceTimePickup + carrierShipment.getPickupServiceTime();
+ serviceTimeDelivery = serviceTimeDelivery + carrierShipment.getDeliveryServiceTime();
+ shipmentsToRemove.put(carrierShipment.getId(), carrierShipment);
+ }
+ CarrierShipment newShipment = CarrierShipment.Builder
.newInstance(idNewShipment, baseShipment.getFrom(), baseShipment.getTo(), demandForThisLink)
.setPickupServiceTime(serviceTimePickup)
.setPickupTimeWindow(baseShipment.getPickupTimeWindow())
.setDeliveryServiceTime(serviceTimeDelivery)
.setDeliveryTimeWindow(baseShipment.getDeliveryTimeWindow()).build();
+ shipmentsToAdd.add(newShipment);
+ }
+ }
+ for (CarrierShipment id : shipmentsToRemove.values())
+ thisCarrier.getShipments().remove(id.getId(), id);
- shipmentsToAdd.add(newShipment);
- connectedJobs++;
+ for (CarrierShipment carrierShipment : shipmentsToAdd) {
+ thisCarrier.getShipments().put(carrierShipment.getId(), carrierShipment);
}
- }
- for (CarrierShipment id : shipmentsToRemove.values())
- thisCarrier.getShipments().remove(id.getId(), id);
- for (CarrierShipment carrierShipment : shipmentsToAdd) {
- thisCarrier.getShipments().put(carrierShipment.getId(), carrierShipment);
+ log.warn("Number of reduced shipments for carrier {}: {}", thisCarrier.getId().toString(), shipmentsBeforeConnection - thisCarrier.getShipments().size());
}
- log.warn("Number of reduced shipments: {}", connectedJobs);
- }
- if (newDemandInformationElement.getTypeOfDemand().equals("service")) {
- HashMap, CarrierService> servicesToRemove = new HashMap<>();
- ArrayList servicesToAdd = new ArrayList<>();
- Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers()
- .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class));
- for (Id baseServiceId : thisCarrier.getServices().keySet()) {
- if (!servicesToRemove.containsKey(baseServiceId)) {
- CarrierService baseService = thisCarrier.getServices().get(baseServiceId);
- HashMap, CarrierService> servicesToConnect = new HashMap<>();
- servicesToConnect.put(baseServiceId, baseService);
- for (Id thisServiceId : thisCarrier.getServices().keySet()) {
- if (!servicesToRemove.containsKey(thisServiceId)) {
- CarrierService thisService = thisCarrier.getServices().get(thisServiceId);
- if (baseService.getId() != thisService.getId()
+ if (!thisCarrier.getServices().isEmpty()) {
+ int servicesBeforeConnection = thisCarrier.getServices().size();
+ HashMap, CarrierService> servicesToRemove = new HashMap<>();
+ ArrayList servicesToAdd = new ArrayList<>();
+ for (Id baseServiceId : thisCarrier.getServices().keySet()) {
+ if (!servicesToRemove.containsKey(baseServiceId)) {
+ CarrierService baseService = thisCarrier.getServices().get(baseServiceId);
+ HashMap, CarrierService> servicesToConnect = new HashMap<>();
+ servicesToConnect.put(baseServiceId, baseService);
+ for (Id thisServiceId : thisCarrier.getServices().keySet()) {
+ if (!servicesToRemove.containsKey(thisServiceId)) {
+ CarrierService thisService = thisCarrier.getServices().get(thisServiceId);
+ if (baseService.getId() != thisService.getId()
&& baseService.getLocationLinkId() == thisService.getLocationLinkId() && baseService
- .getServiceStartTimeWindow() == thisService.getServiceStartTimeWindow())
- servicesToConnect.put(thisServiceId, thisService);
+ .getServiceStartTimeWindow() == thisService.getServiceStartTimeWindow())
+ servicesToConnect.put(thisServiceId, thisService);
+ }
}
- }
- Id idNewService = baseService.getId();
- int demandForThisLink = 0;
- double serviceTimeService = 0;
- for (CarrierService carrierService : servicesToConnect.values()) {
- demandForThisLink = demandForThisLink + carrierService.getCapacityDemand();
- serviceTimeService = serviceTimeService + carrierService.getServiceDuration();
- servicesToRemove.put(carrierService.getId(), carrierService);
- connectedJobs++;
- }
- CarrierService newService = CarrierService.Builder
+ Id idNewService = baseService.getId();
+ int demandForThisLink = 0;
+ double serviceTimeService = 0;
+ for (CarrierService carrierService : servicesToConnect.values()) {
+ demandForThisLink = demandForThisLink + carrierService.getCapacityDemand();
+ serviceTimeService = serviceTimeService + carrierService.getServiceDuration();
+ servicesToRemove.put(carrierService.getId(), carrierService);
+ }
+ CarrierService newService = CarrierService.Builder
.newInstance(idNewService, baseService.getLocationLinkId())
.setServiceDuration(serviceTimeService)
.setServiceStartTimeWindow(baseService.getServiceStartTimeWindow())
.setCapacityDemand(demandForThisLink).build();
- servicesToAdd.add(newService);
- connectedJobs++;
+ servicesToAdd.add(newService);
+ }
}
+ for (CarrierService id : servicesToRemove.values())
+ thisCarrier.getServices().remove(id.getId(), id);
+ for (CarrierService carrierService : servicesToAdd) {
+ thisCarrier.getServices().put(carrierService.getId(), carrierService);
+ }
+ log.warn("Number of reduced services for carrier {}: {}", thisCarrier.getId().toString(), servicesBeforeConnection - thisCarrier.getServices().size());
}
- for (CarrierService id : servicesToRemove.values())
- thisCarrier.getServices().remove(id.getId(), id);
- for (CarrierService carrierService : servicesToAdd) {
- thisCarrier.getServices().put(carrierService.getId(), carrierService);
- }
- log.warn("Number of reduced shipments: {}", connectedJobs);
}
}
diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java
index 368dddaad69..d01a6226691 100644
--- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java
+++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java
@@ -37,8 +37,8 @@
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.core.utils.geometry.CoordinateTransformation;
import org.matsim.freight.carriers.*;
-import org.matsim.freight.carriers.controler.CarrierModule;
-import org.matsim.freight.carriers.controler.CarrierScoringFunctionFactory;
+import org.matsim.freight.carriers.controller.CarrierModule;
+import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory;
import org.matsim.freight.carriers.usecases.chessboard.CarrierScoringFunctionFactoryImpl;
import picocli.CommandLine;
@@ -62,6 +62,8 @@
+ " * these files are given in the example project. See: TODO", showDefaultValues = true)
public class FreightDemandGeneration implements MATSimAppCommand {
+ private final JobDurationCalculator jobDurationCalculator;
+
private enum CarrierInputOptions {
readCarrierFile, createCarriersFromCSV, addCSVDataToExistingCarrierFileData
}
@@ -154,6 +156,16 @@ private enum OptionsOfVRPSolutions {
@CommandLine.Option(names = "--defaultJspritIterations", description = "Set the default number of jsprit iterations.")
private int defaultJspritIterations;
+ public FreightDemandGeneration() {
+ this.jobDurationCalculator = new DefaultJobDurationCalculator();
+ log.info("Using default {} for job duration calculation", jobDurationCalculator.getClass().getSimpleName());
+ }
+
+ public FreightDemandGeneration(JobDurationCalculator jobDurationCalculator) {
+ this.jobDurationCalculator = jobDurationCalculator;
+ log.info("Using {} for job duration calculation", jobDurationCalculator.getClass().getSimpleName());
+ }
+
public static void main(String[] args) {
System.exit(new CommandLine(new FreightDemandGeneration()).execute(args));
}
@@ -353,7 +365,7 @@ private void createDemand(DemandGenerationOptions selectedDemandGenerationOption
case createDemandFromCSV ->
// creates the demand by using the information given in the read csv file
DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, indexShape, combineSimilarJobs,
- crsTransformationNetworkAndShape, null, shapeCategory);
+ crsTransformationNetworkAndShape, null, shapeCategory, jobDurationCalculator);
case createDemandFromCSVAndUsePopulation -> {
/*
* Option creates the demand by using the information given in the read csv file
@@ -399,14 +411,14 @@ private void createDemand(DemandGenerationOptions selectedDemandGenerationOption
case useHolePopulation:
// uses the hole population as possible demand locations
DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, indexShape,
- combineSimilarJobs, crsTransformationNetworkAndShape, population, shapeCategory);
+ combineSimilarJobs, crsTransformationNetworkAndShape, population, shapeCategory, jobDurationCalculator);
break;
case usePopulationInShape:
// uses only the population with home location in the given shape file
FreightDemandGenerationUtils.reducePopulationToShapeArea(population,
shp.createIndex(populationCRS, "_"));
DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, indexShape,
- combineSimilarJobs, crsTransformationNetworkAndShape, population, shapeCategory);
+ combineSimilarJobs, crsTransformationNetworkAndShape, population, shapeCategory, jobDurationCalculator);
break;
default:
throw new RuntimeException("No valid population option selected!");
diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java
index c60a8a39390..ede28ace76d 100644
--- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java
+++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java
@@ -152,7 +152,7 @@ static void createDemandLocationsFile(Controler controler) {
writer.flush();
} catch (IOException e) {
- e.printStackTrace();
+ log.error("Could not write job locations file under " + "/outputLocationFile.xml.gz");
}
log.info("Wrote job locations file under " + "/outputLocationFile.xml.gz");
}
diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/JobDurationCalculator.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/JobDurationCalculator.java
new file mode 100644
index 00000000000..85d30908fa0
--- /dev/null
+++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/JobDurationCalculator.java
@@ -0,0 +1,39 @@
+package org.matsim.freightDemandGeneration;
+
+import org.matsim.api.core.v01.Scenario;
+
+public interface JobDurationCalculator {
+ /**
+ * Calculates the duration of a service in seconds.
+ *
+ * @param serviceDurationPerUnit in seconds
+ * @param demandForThisService amount of demand for this service
+ * @return duration in seconds
+ */
+ double calculateServiceDuration(Integer serviceDurationPerUnit, int demandForThisService);
+
+ /**
+ * Calculates the duration of a pickup in seconds.
+ *
+ * @param pickupDurationPerUnit in seconds
+ * @param demandForThisShipment amount of demand for this shipment
+ * @return duration in seconds
+ */
+ double calculatePickupDuration(Integer pickupDurationPerUnit, int demandForThisShipment);
+
+ /**
+ * Calculates the duration of a delivery in seconds.
+ *
+ * @param deliveryDurationPerUnit in seconds
+ * @param demandForThisShipment amount of demand for this shipment
+ * @return duration in seconds
+ */
+ double calculateDeliveryDuration(Integer deliveryDurationPerUnit, int demandForThisShipment);
+
+ /**
+ * Recalculates the job durations for all jobs in the scenario. The devault implementation does nothing.
+ *
+ * @param scenario scenario
+ */
+ void recalculateJobDurations(Scenario scenario);
+}
diff --git a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java
index c27b251afc4..9cd21c16d9d 100644
--- a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java
+++ b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java
@@ -79,10 +79,10 @@ void demandCreationWithSampleWithChangeNumberOfLocations() throws IOException {
String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml";
Population population = PopulationUtils.readPopulation(populationLocation);
FreightDemandGenerationUtils.preparePopulation(population, 0.5, 1.0, "changeNumberOfLocationsWithDemand");
-
+ Boolean combineSimilarJobs = false;
// run methods
createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory,
- population);
+ population, combineSimilarJobs);
Network network = scenario.getNetwork();
@@ -147,10 +147,11 @@ void demandCreationWithSampleWithDemandOnLocation() throws IOException {
String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml";
Population population = PopulationUtils.readPopulation(populationLocation);
FreightDemandGenerationUtils.preparePopulation(population, 0.5, 1.0, "changeDemandOnLocation");
+ Boolean combineSimilarJobs = false;
- createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory, population);
+ createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory,
+ population, combineSimilarJobs);
- // check carrier 1
Network network = scenario.getNetwork();
checkCarrier1and2(scenario, network, indexShape);
@@ -194,6 +195,74 @@ void demandCreationWithSampleWithDemandOnLocation() throws IOException {
}
}
+ @Test
+ void demandCreationWithSampleWithDemandOnLocationWithCombiningJobs() throws IOException {
+ // read inputs
+ Config config = ConfigUtils.createConfig();
+ config.network().setInputFile(
+ "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml");
+ Scenario scenario = ScenarioUtils.loadScenario(config);
+ FreightCarriersConfigGroup freightCarriersConfigGroup = ConfigUtils.addOrGetModule(scenario.getConfig(),
+ FreightCarriersConfigGroup.class);
+ freightCarriersConfigGroup.setCarriersVehicleTypesFile(utils.getPackageInputDirectory() + "testVehicleTypes.xml");
+ Path carrierCSVLocation = Path.of(utils.getPackageInputDirectory() + "testCarrierCSV.csv");
+ Path demandCSVLocation = Path.of(utils.getPackageInputDirectory() + "testDemandCSV.csv");
+ Path shapeFilePath = Path.of(utils.getPackageInputDirectory() + "testShape/testShape.shp");
+ ShpOptions shp = new ShpOptions(shapeFilePath, "WGS84", null);
+ String shapeCategory = "Ortsteil";
+ ShpOptions.Index indexShape = shp.createIndex("Ortsteil");
+ String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml";
+ Population population = PopulationUtils.readPopulation(populationLocation);
+ FreightDemandGenerationUtils.preparePopulation(population, 0.5, 1.0, "changeDemandOnLocation");
+ Boolean combineSimilarJobs = true;
+
+ createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory,
+ population, combineSimilarJobs);
+
+ Network network = scenario.getNetwork();
+
+ checkCarrier1and2WithCombiningJobs(scenario, network, indexShape);
+ int countDemand;
+ Object2IntMap countShipmentsWithCertainDemand;
+ Map> locationsPerShipmentElement;
+
+ // check carrier 3
+ Carrier testCarrier3 = CarriersUtils.getCarriers(scenario).getCarriers()
+ .get(Id.create("testCarrier3", Carrier.class));
+ Assertions.assertEquals(0, testCarrier3.getServices().size());
+ Assertions.assertEquals(2, testCarrier3.getShipments().size());
+ countShipmentsWithCertainDemand = new Object2IntOpenHashMap<>();
+ locationsPerShipmentElement = new HashMap<>();
+ countDemand = 0;
+ for (CarrierShipment shipment : testCarrier3.getShipments().values()) {
+ countShipmentsWithCertainDemand.merge((Integer) shipment.getSize(), 1, Integer::sum);
+ countDemand = countDemand + shipment.getSize();
+ Assertions.assertEquals(10, shipment.getSize());
+ Assertions.assertEquals(4000, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON);
+ Assertions.assertEquals(2500, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON);
+ Assertions.assertEquals(TimeWindow.newInstance(8000, 50000), shipment.getPickupTimeWindow());
+ Assertions.assertEquals(TimeWindow.newInstance(10000, 60000), shipment.getDeliveryTimeWindow());
+ locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_pickup", (k) -> new HashSet<>())
+ .add(shipment.getFrom().toString());
+ locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_delivery", (k) -> new HashSet<>())
+ .add(shipment.getTo().toString());
+ }
+ Assertions.assertEquals(20, countDemand);
+ Assertions.assertEquals(2, countShipmentsWithCertainDemand.getInt(10));
+ Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement1_pickup").size());
+ Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmentElement1_delivery").size());
+ for (String locationsOfShipmentElement : locationsPerShipmentElement.get("ShipmentElement1_delivery")) {
+ Link link = network.getLinks().get(Id.createLinkId(locationsOfShipmentElement));
+ Assertions.assertTrue(
+ FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null));
+ Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape,
+ new String[] { "area1" }, null));
+ Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape,
+ new String[] { "area2" }, null));
+ }
+ }
+
+
@Test
void demandCreationNoSampling() throws IOException {
// read inputs
@@ -213,10 +282,11 @@ void demandCreationNoSampling() throws IOException {
String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml";
Population population = PopulationUtils.readPopulation(populationLocation);
FreightDemandGenerationUtils.preparePopulation(population, 0.5, 0.5, "changeDemandOnLocation");
+ Boolean combineSimilarJobs = false;
// run methods
createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory,
- population);
+ population, combineSimilarJobs);
// check carrier 1
Network network = scenario.getNetwork();
@@ -367,7 +437,8 @@ void csvDemandReader() throws IOException {
private static void createDemandAndCheckCarrier(Path carrierCSVLocation, Scenario scenario, FreightCarriersConfigGroup freightCarriersConfigGroup,
ShpOptions.Index indexShape, Path demandCSVLocation, String shapeCategory,
- Population population) throws IOException {
+ Population population, Boolean combineSimilarJobs) throws IOException {
+ JobDurationCalculator jobDurationCalculator = new DefaultJobDurationCalculator();
// run methods
Set allNewCarrierInformation = CarrierReaderFromCSV
.readCarrierInformation(carrierCSVLocation);
@@ -375,8 +446,8 @@ private static void createDemandAndCheckCarrier(Path carrierCSVLocation, Scenari
indexShape, 1, null);
Set demandInformation = DemandReaderFromCSV.readDemandInformation(demandCSVLocation);
DemandReaderFromCSV.checkNewDemand(scenario, demandInformation, indexShape, shapeCategory);
- DemandReaderFromCSV.createDemandForCarriers(scenario, indexShape, demandInformation, population, false,
- null);
+ DemandReaderFromCSV.createDemandForCarriers(scenario, indexShape, demandInformation, population, combineSimilarJobs,
+ null, jobDurationCalculator);
Assertions.assertEquals(3, CarriersUtils.getCarriers(scenario).getCarriers().size());
Assertions.assertTrue(
CarriersUtils.getCarriers(scenario).getCarriers().containsKey(Id.create("testCarrier1", Carrier.class)));
@@ -491,4 +562,89 @@ private static void checkCarrier1and2(Scenario scenario, Network network, ShpOpt
Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement2_pickup").size());
Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmentElement2_delivery").size());
}
+
+ /**
+ * Results after combing jobs.
+ *
+ * @param scenario the scenario
+ * @param network the network
+ * @param indexShape the index of the shape
+ */
+ private static void checkCarrier1and2WithCombiningJobs(Scenario scenario, Network network, ShpOptions.Index indexShape) {
+ Carrier testCarrier1 = CarriersUtils.getCarriers(scenario).getCarriers()
+ .get(Id.create("testCarrier1", Carrier.class));
+ Assertions.assertEquals(8, testCarrier1.getServices().size());
+ Assertions.assertEquals(0, testCarrier1.getShipments().size());
+ Object2IntMap countServicesWithCertainDemand = new Object2IntOpenHashMap<>();
+ Map> locationsPerServiceElement = new HashMap<>();
+ int countDemand = 0;
+ for (CarrierService service : testCarrier1.getServices().values()) {
+ countServicesWithCertainDemand.merge((Integer) service.getCapacityDemand(), 1, Integer::sum);
+ countDemand = countDemand + service.getCapacityDemand();
+ if (service.getCapacityDemand() == 0) {
+ Assertions.assertEquals(180, service.getServiceDuration(), MatsimTestUtils.EPSILON);
+ Assertions.assertEquals(TimeWindow.newInstance(3000, 13000), service.getServiceStartTimeWindow());
+ locationsPerServiceElement.computeIfAbsent("serviceElement1", (k) -> new HashSet<>())
+ .add(service.getLocationLinkId().toString());
+ } else {
+ Assertions.assertEquals(service.getCapacityDemand() * 100, service.getServiceDuration(), MatsimTestUtils.EPSILON);
+ Assertions.assertEquals(TimeWindow.newInstance(5000, 20000), service.getServiceStartTimeWindow());
+ locationsPerServiceElement.computeIfAbsent("serviceElement2", (k) -> new HashSet<>())
+ .add(service.getLocationLinkId().toString());
+ }
+ }
+ Assertions.assertEquals(12, countDemand);
+ Assertions.assertEquals(4, countServicesWithCertainDemand.getInt(0));
+ Assertions.assertEquals(4, locationsPerServiceElement.get("serviceElement1").size());
+ for (String locationsOfServiceElement : locationsPerServiceElement.get("serviceElement1")) {
+ Link link = network.getLinks().get(Id.createLinkId(locationsOfServiceElement));
+ Assertions.assertTrue(
+ FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null));
+ Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape,
+ new String[] { "area1" }, null));
+ Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape,
+ new String[] { "area2" }, null));
+ }
+ Assertions.assertEquals(4, locationsPerServiceElement.get("serviceElement2").size());
+ Assertions.assertTrue(locationsPerServiceElement.get("serviceElement2").contains("i(2,0)"));
+
+ // check carrier 2
+ Carrier testCarrier2 = CarriersUtils.getCarriers(scenario).getCarriers()
+ .get(Id.create("testCarrier2", Carrier.class));
+ Assertions.assertEquals(0, testCarrier2.getServices().size());
+ Assertions.assertEquals(6, testCarrier2.getShipments().size());
+ Object2IntMap countShipmentsWithCertainDemand = new Object2IntOpenHashMap<>();
+ Map> locationsPerShipmentElement = new HashMap<>();
+ countDemand = 0;
+ for (CarrierShipment shipment : testCarrier2.getShipments().values()) {
+ countShipmentsWithCertainDemand.merge((Integer) shipment.getSize(), 1, Integer::sum);
+ countDemand = countDemand + shipment.getSize();
+ if (shipment.getSize() == 0) {
+ Assertions.assertEquals(300, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON);
+ Assertions.assertEquals(350, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON);
+ Assertions.assertEquals(TimeWindow.newInstance(10000, 45000), shipment.getPickupTimeWindow());
+ Assertions.assertEquals(TimeWindow.newInstance(11000, 44000), shipment.getDeliveryTimeWindow());
+ locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_pickup", (k) -> new HashSet<>())
+ .add(shipment.getFrom().toString());
+ locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_delivery", (k) -> new HashSet<>())
+ .add(shipment.getTo().toString());
+ } else {
+ Assertions.assertEquals(shipment.getSize() * 200, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON);
+ Assertions.assertEquals(shipment.getSize() * 200, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON);
+ Assertions.assertEquals(TimeWindow.newInstance(11000, 44000), shipment.getPickupTimeWindow());
+ Assertions.assertEquals(TimeWindow.newInstance(20000, 40000), shipment.getDeliveryTimeWindow());
+ locationsPerShipmentElement.computeIfAbsent("ShipmentElement2_pickup", (k) -> new HashSet<>())
+ .add(shipment.getFrom().toString());
+ locationsPerShipmentElement.computeIfAbsent("ShipmentElement2_delivery", (k) -> new HashSet<>())
+ .add(shipment.getTo().toString());
+ }
+ }
+ Assertions.assertEquals(15, countDemand);
+ Assertions.assertEquals(4, countShipmentsWithCertainDemand.getInt(0));
+ Assertions.assertEquals(4, locationsPerShipmentElement.get("ShipmentElement1_pickup").size());
+ Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement1_delivery").size());
+ Assertions.assertTrue(locationsPerShipmentElement.get("ShipmentElement1_delivery").contains("i(2,0)"));
+ Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement2_pickup").size());
+ Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmentElement2_delivery").size());
+ }
}
diff --git a/contribs/av/pom.xml b/contribs/av/pom.xml
index 1536e9e78ef..590c8f7e7a1 100644
--- a/contribs/av/pom.xml
+++ b/contribs/av/pom.xml
@@ -16,19 +16,19 @@
org.matsim.contribdvrp
- 2025.0-SNAPSHOT
+ ${project.parent.version}compileorg.matsim.contribtaxi
- 2025.0-SNAPSHOT
+ ${project.parent.version}compileorg.matsim.contribdrt
- 2025.0-SNAPSHOT
+ ${project.parent.version}compile
diff --git a/contribs/bicycle/pom.xml b/contribs/bicycle/pom.xml
index f3ffdc96601..9bd3a41df5e 100644
--- a/contribs/bicycle/pom.xml
+++ b/contribs/bicycle/pom.xml
@@ -23,7 +23,7 @@
org.matsim.contribosm
- 2025.0-SNAPSHOT
+ ${project.parent.version}compile
diff --git a/contribs/cadytsIntegration/pom.xml b/contribs/cadytsIntegration/pom.xml
index 2d4b716db7e..5fba4fc8e57 100644
--- a/contribs/cadytsIntegration/pom.xml
+++ b/contribs/cadytsIntegration/pom.xml
@@ -17,7 +17,7 @@
org.matsim.contribanalysis
- 2025.0-SNAPSHOT
+ ${project.parent.version}2012
diff --git a/contribs/carsharing/pom.xml b/contribs/carsharing/pom.xml
index 2580047b892..54eb37ac992 100644
--- a/contribs/carsharing/pom.xml
+++ b/contribs/carsharing/pom.xml
@@ -12,7 +12,7 @@
org.matsim.contribdvrp
- 2025.0-SNAPSHOT
+ ${project.parent.version}
diff --git a/contribs/commercialTrafficApplications/pom.xml b/contribs/commercialTrafficApplications/pom.xml
index 2d6f1061274..4804f34b6d9 100644
--- a/contribs/commercialTrafficApplications/pom.xml
+++ b/contribs/commercialTrafficApplications/pom.xml
@@ -14,13 +14,13 @@
org.matsim.contribfreight
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribdrt
- 2025.0-SNAPSHOT
+ ${project.parent.version}
diff --git a/contribs/commercialTrafficApplications/src/test/java/org/matsim/contrib/commercialTrafficApplications/jointDemand/TestScenarioGeneration.java b/contribs/commercialTrafficApplications/src/test/java/org/matsim/contrib/commercialTrafficApplications/jointDemand/TestScenarioGeneration.java
index 1d6b845a665..601038f2f73 100644
--- a/contribs/commercialTrafficApplications/src/test/java/org/matsim/contrib/commercialTrafficApplications/jointDemand/TestScenarioGeneration.java
+++ b/contribs/commercialTrafficApplications/src/test/java/org/matsim/contrib/commercialTrafficApplications/jointDemand/TestScenarioGeneration.java
@@ -126,8 +126,6 @@ private static CarrierVehicle getLightVehicle(Id> id, VehicleType type, Id zones = new IdMap<>(Zone.class);
- private final IdMap> zoneToLinksMap = new IdMap<>(Zone.class);
+ private final Map> index2Links;
private final Network network;
@@ -76,6 +77,7 @@ public SquareGridZoneSystem(Network network, double cellSize, boolean filterByNe
this.rows = Math.max(1, (int) Math.ceil((maxY - minY) / cellSize));
this.cols = Math.max(1, (int)Math.ceil((maxX - minX) / cellSize));
this.internalZones = new Zone[rows * cols +1];
+ this.index2Links = getIndexToLink(network);
if(filterByNetwork) {
network.getLinks().values().forEach(l -> getOrCreateZone(l.getToNode().getCoord()));
@@ -111,7 +113,7 @@ public Optional getZoneForCoord(Coord coord) {
@Override
public List getLinksForZoneId(Id zone) {
- return zoneToLinksMap.get(zone);
+ return this.index2Links.get(Integer.parseInt(zone.toString()));
}
private Optional getOrCreateZone(Coord coord) {
@@ -126,13 +128,6 @@ private Optional getOrCreateZone(Coord coord) {
if(zoneFilter.test(zone)) {
internalZones[index] = zone;
zones.put(zone.getId(), zone);
-
- for (Link link : network.getLinks().values()) {
- if (getIndex(link.getToNode().getCoord()) == index) {
- List links = zoneToLinksMap.computeIfAbsent(zone.getId(), zoneId -> new ArrayList<>());
- links.add(link);
- }
- }
} else {
return Optional.empty();
}
@@ -140,6 +135,11 @@ private Optional getOrCreateZone(Coord coord) {
return Optional.of(zone);
}
+ private Map> getIndexToLink(Network network) {
+ return network.getLinks().values().stream()
+ .collect(Collectors.groupingBy(link -> getIndex(link.getToNode().getCoord())));
+ }
+
private PreparedPolygon getGeometry(int r, int c) {
List coords = new ArrayList<>();
coords.add(new Coord(minX + c * cellSize, minY + r * cellSize));
diff --git a/contribs/decongestion/pom.xml b/contribs/decongestion/pom.xml
index 62d2f912040..992bd7c6a12 100644
--- a/contribs/decongestion/pom.xml
+++ b/contribs/decongestion/pom.xml
@@ -8,7 +8,7 @@
org.matsim.contribotfvis
- ${parent.version}
+ ${project.parent.version}test
diff --git a/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/DeterminismTest.java b/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/DeterminismTest.java
new file mode 100644
index 00000000000..bebc456de8f
--- /dev/null
+++ b/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/DeterminismTest.java
@@ -0,0 +1,55 @@
+package org.matsim.contrib.discrete_mode_choice;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.jupiter.api.Test;
+import org.matsim.api.core.v01.Scenario;
+import org.matsim.contribs.discrete_mode_choice.modules.DiscreteModeChoiceModule;
+import org.matsim.contribs.discrete_mode_choice.modules.ModeAvailabilityModule;
+import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup;
+import org.matsim.core.config.Config;
+import org.matsim.core.config.ConfigUtils;
+import org.matsim.core.controler.Controler;
+import org.matsim.core.controler.OutputDirectoryHierarchy;
+import org.matsim.core.gbl.MatsimRandom;
+import org.matsim.core.scenario.ScenarioUtils;
+import org.matsim.core.utils.io.IOUtils;
+import org.matsim.core.utils.misc.CRCChecksum;
+import org.matsim.examples.ExamplesUtils;
+
+import java.net.URL;
+
+public class DeterminismTest {
+ private static void runConfig(URL configUrl, String outputDirectory) {
+ Config config = ConfigUtils.loadConfig(configUrl, new DiscreteModeChoiceConfigGroup());
+ config.controller().setLastIteration(2);
+ config.controller().setOutputDirectory(outputDirectory);
+ config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists);
+ Scenario scenario = ScenarioUtils.createScenario(config);
+ ScenarioUtils.loadScenario(scenario);
+ Controler controler = new Controler(scenario);
+ controler.addOverridingModule(new DiscreteModeChoiceModule());
+ controler.addOverridingModule(new ModeAvailabilityModule());
+ controler.run();
+ }
+
+
+ @Test
+ public void testSimulationDeterminism() {
+ Logger logger = LogManager.getLogger(DeterminismTest.class);
+ logger.info("Testing simulation determinism");
+ URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("siouxfalls-2014"), "config_default.xml");
+ int samples = 10;
+ for(int i=0; iorg.matsim.contribdrt
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribev
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribinformed-mode-choice
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribsimwrapper
- 2025.0-SNAPSHOT
+ ${project.parent.version}
@@ -45,7 +45,7 @@
org.matsim.contribvsp
- 2025.0-SNAPSHOT
+ ${project.parent.version}test
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 00dabefc585..90773153294 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
@@ -59,6 +59,7 @@
import org.matsim.contrib.dvrp.schedule.ScheduleTimingUpdater;
import org.matsim.contrib.dvrp.vrpagent.VrpAgentLogic;
import org.matsim.contrib.dvrp.vrpagent.VrpLegFactory;
+import org.matsim.contrib.ev.charging.ChargingStrategy;
import org.matsim.contrib.ev.infrastructure.ChargingInfrastructure;
import org.matsim.contrib.ev.infrastructure.ChargingInfrastructureUtils;
import org.matsim.core.api.experimental.events.EventsManager;
@@ -116,7 +117,8 @@ protected void configureQSim() {
public EmptyVehicleChargingScheduler get() {
var taskFactory = getModalInstance(DrtTaskFactory.class);
var chargingInfrastructure = getModalInstance(ChargingInfrastructure.class);
- return new EmptyVehicleChargingScheduler(timer, taskFactory, chargingInfrastructure);
+ ChargingStrategy.Factory chargingStrategyFactory = getModalInstance(ChargingStrategy.Factory.class);
+ return new EmptyVehicleChargingScheduler(timer, taskFactory, chargingInfrastructure, chargingStrategyFactory);
}
}).asEagerSingleton();
diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenario.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenario.java
index 741c4047786..915c5efa220 100644
--- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenario.java
+++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenario.java
@@ -22,15 +22,17 @@
import java.net.URL;
+import org.matsim.contrib.drt.extension.edrt.optimizer.EDrtVehicleDataEntryFactory.EDrtVehicleDataEntryFactoryProvider;
import org.matsim.contrib.drt.run.DrtConfigGroup;
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule;
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
-import org.matsim.contrib.drt.extension.edrt.optimizer.EDrtVehicleDataEntryFactory.EDrtVehicleDataEntryFactoryProvider;
+import org.matsim.contrib.dvrp.run.DvrpModes;
import org.matsim.contrib.ev.EvConfigGroup;
import org.matsim.contrib.ev.charging.ChargeUpToMaxSocStrategy;
import org.matsim.contrib.ev.charging.ChargingLogic;
import org.matsim.contrib.ev.charging.ChargingPower;
+import org.matsim.contrib.ev.charging.ChargingStrategy;
import org.matsim.contrib.ev.charging.ChargingWithQueueingAndAssignmentLogic;
import org.matsim.contrib.ev.charging.FixedSpeedCharging;
import org.matsim.contrib.ev.temperature.TemperatureService;
@@ -40,6 +42,8 @@
import org.matsim.core.controler.Controler;
import org.matsim.vis.otfvis.OTFVisConfigGroup;
+import com.google.inject.Key;
+
/**
* @author Michal Maciejewski (michalm)
*/
@@ -69,10 +73,13 @@ public void install() {
controler.addOverridingModule(new AbstractModule() {
@Override
public void install() {
- bind(ChargingLogic.Factory.class).toProvider(new ChargingWithQueueingAndAssignmentLogic.FactoryProvider(
- charger -> new ChargeUpToMaxSocStrategy(charger, MAX_RELATIVE_SOC)));
+ bind(ChargingLogic.Factory.class).to(ChargingWithQueueingAndAssignmentLogic.Factory.class);
bind(ChargingPower.Factory.class).toInstance(ev -> new FixedSpeedCharging(ev, CHARGING_SPEED_FACTOR));
bind(TemperatureService.class).toInstance(linkId -> TEMPERATURE);
+
+ for (DrtConfigGroup drtCfg : MultiModeDrtConfigGroup.get(config).getModalElements()) {
+ bind(Key.get(ChargingStrategy.Factory.class, DvrpModes.mode(drtCfg.mode))).toInstance(new ChargeUpToMaxSocStrategy.Factory(MAX_RELATIVE_SOC));
+ }
}
});
diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtChargingTask.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtChargingTask.java
index e2dcfdba751..95b36f65889 100644
--- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtChargingTask.java
+++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtChargingTask.java
@@ -20,6 +20,7 @@
package org.matsim.contrib.drt.extension.edrt.schedule;
import org.matsim.contrib.drt.schedule.DrtTaskType;
+import org.matsim.contrib.ev.charging.ChargingStrategy;
import org.matsim.contrib.ev.fleet.ElectricVehicle;
import org.matsim.contrib.ev.infrastructure.Charger;
import org.matsim.contrib.evrp.ChargingTaskImpl;
@@ -27,7 +28,7 @@
public class EDrtChargingTask extends ChargingTaskImpl {
public static final DrtTaskType TYPE = new DrtTaskType("CHARGING");
- public EDrtChargingTask(double beginTime, double endTime, Charger charger, ElectricVehicle ev, double totalEnergy) {
- super(TYPE, beginTime, endTime, charger, ev, totalEnergy);
+ public EDrtChargingTask(double beginTime, double endTime, Charger charger, ElectricVehicle ev, double totalEnergy, ChargingStrategy chargingStrategy) {
+ super(TYPE, beginTime, endTime, charger, ev, totalEnergy, chargingStrategy);
}
}
diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtTaskFactoryImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtTaskFactoryImpl.java
index 4ec83dc7a15..d99fdc6fbfe 100644
--- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtTaskFactoryImpl.java
+++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtTaskFactoryImpl.java
@@ -26,6 +26,7 @@
import org.matsim.contrib.dvrp.schedule.DefaultStayTask;
import org.matsim.contrib.evrp.EvDvrpVehicle;
import org.matsim.contrib.evrp.VrpPathEnergyConsumptions;
+import org.matsim.contrib.ev.charging.ChargingStrategy;
import org.matsim.contrib.ev.fleet.ElectricVehicle;
import org.matsim.contrib.ev.infrastructure.Charger;
@@ -59,8 +60,8 @@ public DefaultStayTask createInitialTask(DvrpVehicle vehicle, double beginTime,
}
public EDrtChargingTask createChargingTask(DvrpVehicle vehicle, double beginTime, double endTime, Charger charger,
- double totalEnergy) {
+ double totalEnergy, ChargingStrategy chargingStrategy) {
return new EDrtChargingTask(beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(),
- totalEnergy);
+ totalEnergy, chargingStrategy);
}
}
diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/scheduler/EmptyVehicleChargingScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/scheduler/EmptyVehicleChargingScheduler.java
index eea29745e80..2df2ed57028 100644
--- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/scheduler/EmptyVehicleChargingScheduler.java
+++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/scheduler/EmptyVehicleChargingScheduler.java
@@ -47,10 +47,12 @@ public class EmptyVehicleChargingScheduler {
private final MobsimTimer timer;
private final EDrtTaskFactoryImpl taskFactory;
private final Map, List> linkToChargersMap;
+ private final ChargingStrategy.Factory chargingStrategyFactory;
public EmptyVehicleChargingScheduler(MobsimTimer timer, DrtTaskFactory taskFactory,
- ChargingInfrastructure chargingInfrastructure) {
+ ChargingInfrastructure chargingInfrastructure, ChargingStrategy.Factory chargingStrategyFactory) {
this.timer = timer;
+ this.chargingStrategyFactory = chargingStrategyFactory;
this.taskFactory = (EDrtTaskFactoryImpl)taskFactory;
linkToChargersMap = chargingInfrastructure.getChargers()
.values()
@@ -68,15 +70,16 @@ public void chargeVehicle(DvrpVehicle vehicle) {
// Empty charger or at least smallest queue charger
Charger charger = freeCharger.orElseGet(() -> chargers.stream().min(Comparator.comparingInt(e -> e.getLogic().getQueuedVehicles().size())).orElseThrow());
ElectricVehicle ev = ((EvDvrpVehicle)vehicle).getElectricVehicle();
- if (!charger.getLogic().getChargingStrategy().isChargingCompleted(ev)) {
- chargeVehicleImpl(vehicle, charger);
+ ChargingStrategy strategy = chargingStrategyFactory.createStrategy(charger.getSpecification(), ev);
+ if (!strategy.isChargingCompleted()) {
+ chargeVehicleImpl(vehicle, ev, charger, strategy);
}
}
}
- private void chargeVehicleImpl(DvrpVehicle vehicle, Charger charger) {
+ private void chargeVehicleImpl(DvrpVehicle vehicle, ElectricVehicle ev, Charger charger, ChargingStrategy strategy) {
Schedule schedule = vehicle.getSchedule();
DrtStayTask stayTask = (DrtStayTask)schedule.getCurrentTask();
if (stayTask.getTaskIdx() != schedule.getTaskCount() - 1) {
@@ -86,19 +89,17 @@ private void chargeVehicleImpl(DvrpVehicle vehicle, Charger charger) {
// add CHARGING TASK
double beginTime = stayTask.getEndTime();
- ChargingStrategy strategy = charger.getLogic().getChargingStrategy();
- ElectricVehicle ev = ((EvDvrpVehicle)vehicle).getElectricVehicle();
- double totalEnergy = -strategy.calcRemainingEnergyToCharge(ev);
+ double totalEnergy = -strategy.calcRemainingEnergyToCharge();
- double chargingDuration = Math.min(strategy.calcRemainingTimeToCharge(ev),
+ double chargingDuration = Math.min(strategy.calcRemainingTimeToCharge(),
vehicle.getServiceEndTime() - beginTime);
if (chargingDuration <= 0) {
return;// no charging
}
double endTime = beginTime + chargingDuration;
- schedule.addTask(taskFactory.createChargingTask(vehicle, beginTime, endTime, charger, totalEnergy));
- ((ChargingWithAssignmentLogic)charger.getLogic()).assignVehicle(ev);
+ schedule.addTask(taskFactory.createChargingTask(vehicle, beginTime, endTime, charger, totalEnergy, strategy));
+ ((ChargingWithAssignmentLogic)charger.getLogic()).assignVehicle(ev, strategy);
// append STAY
schedule.addTask(taskFactory.createStayTask(vehicle, endTime, vehicle.getServiceEndTime(), charger.getLink()));
diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftDispatcherImpl.java
index ace6e8d66e0..b3469edbc2e 100644
--- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftDispatcherImpl.java
+++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftDispatcherImpl.java
@@ -42,15 +42,18 @@ public class EDrtShiftDispatcherImpl implements DrtShiftDispatcher {
private final Fleet fleet;
+ private final ChargingStrategy.Factory chargingStrategyFactory;
+
public EDrtShiftDispatcherImpl(EShiftTaskScheduler shiftTaskScheduler, ChargingInfrastructure chargingInfrastructure,
ShiftsParams drtShiftParams, OperationFacilities operationFacilities,
- DrtShiftDispatcher delegate, Fleet fleet) {
+ DrtShiftDispatcher delegate, Fleet fleet, ChargingStrategy.Factory chargingStrategyFactory) {
this.shiftTaskScheduler = shiftTaskScheduler;
this.chargingInfrastructure = chargingInfrastructure;
this.drtShiftParams = drtShiftParams;
this.operationFacilities = operationFacilities;
this.delegate = delegate;
this.fleet = fleet;
+ this.chargingStrategyFactory = chargingStrategyFactory;
}
@Override
@@ -112,18 +115,18 @@ private void checkChargingAtHub(double timeStep) {
if (selectedCharger.isPresent()) {
Charger selectedChargerImpl = selectedCharger.get();
- ChargingStrategy chargingStrategy = selectedChargerImpl.getLogic().getChargingStrategy();
- if (!chargingStrategy.isChargingCompleted(electricVehicle)) {
+ ChargingStrategy chargingStrategy = chargingStrategyFactory.createStrategy(selectedChargerImpl.getSpecification(), electricVehicle);
+ if (!chargingStrategy.isChargingCompleted()) {
final double waitTime = ChargingEstimations
.estimateMaxWaitTimeForNextVehicle(selectedChargerImpl);
final double chargingTime = chargingStrategy
- .calcRemainingTimeToCharge(electricVehicle);
+ .calcRemainingTimeToCharge();
double energy = -chargingStrategy
- .calcRemainingEnergyToCharge(electricVehicle);
+ .calcRemainingEnergyToCharge();
final double endTime = timeStep + waitTime + chargingTime;
if (endTime < currentTask.getEndTime()) {
shiftTaskScheduler.chargeAtHub((WaitForShiftTask) currentTask, eShiftVehicle,
- electricVehicle, selectedChargerImpl, timeStep, endTime, energy);
+ electricVehicle, selectedChargerImpl, timeStep, endTime, energy, chargingStrategy);
}
}
}
diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java
index 32bf96909bf..95b6feb85e3 100644
--- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java
+++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java
@@ -34,6 +34,7 @@
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
import org.matsim.contrib.dvrp.vrpagent.VrpAgentLogic;
import org.matsim.contrib.dvrp.vrpagent.VrpLegFactory;
+import org.matsim.contrib.ev.charging.ChargingStrategy;
import org.matsim.contrib.ev.infrastructure.ChargingInfrastructure;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.mobsim.framework.MobsimTimer;
@@ -72,7 +73,7 @@ protected void configureQSim() {
drtShiftParams, new EDrtShiftStartLogic(new DefaultShiftStartLogic()),
new EDrtAssignShiftToVehicleLogic(new DefaultAssignShiftToVehicleLogic(drtShiftParams), drtShiftParams),
getter.getModal(ShiftScheduler.class)),
- getter.getModal(Fleet.class)))
+ getter.getModal(Fleet.class), getter.getModal(ChargingStrategy.Factory.class)))
).asEagerSingleton();
bindModal(VehicleEntry.EntryFactory.class).toProvider(modalProvider(getter ->
@@ -87,7 +88,8 @@ drtShiftParams, new EDrtShiftStartLogic(new DefaultShiftStartLogic()),
getter -> new EShiftTaskScheduler(getter.getModal(Network.class), getter.getModal(TravelTime.class),
getter.getModal(TravelDisutilityFactory.class).createTravelDisutility(getter.getModal(TravelTime.class)),
getter.get(MobsimTimer.class), getter.getModal(ShiftDrtTaskFactory.class), drtShiftParams, getter.getModal(ChargingInfrastructure.class),
- getter.getModal(OperationFacilities.class), getter.getModal(Fleet.class))
+ getter.getModal(OperationFacilities.class), getter.getModal(Fleet.class),
+ getter.getModal(ChargingStrategy.Factory.class))
)).asEagerSingleton();
// See EDrtModeOptimizerQSimModule
diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtTaskFactoryImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtTaskFactoryImpl.java
index b7c2657f1bf..c74713d9f73 100644
--- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtTaskFactoryImpl.java
+++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtTaskFactoryImpl.java
@@ -19,6 +19,7 @@
import org.matsim.contrib.dvrp.fleet.DvrpVehicle;
import org.matsim.contrib.dvrp.path.VrpPathWithTravelData;
import org.matsim.contrib.dvrp.schedule.DefaultStayTask;
+import org.matsim.contrib.ev.charging.ChargingStrategy;
import org.matsim.contrib.ev.infrastructure.Charger;
import org.matsim.contrib.evrp.ChargingTask;
import org.matsim.contrib.evrp.ChargingTaskImpl;
@@ -99,21 +100,21 @@ public WaitForShiftTask createWaitForShiftStayTask(DvrpVehicle vehicle, double b
public WaitForShiftTask createChargingWaitForShiftStayTask(DvrpVehicle vehicle, double beginTime,
double endTime, Link link, OperationFacility facility,
- double totalEnergy, Charger charger) {
- ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy);
+ double totalEnergy, Charger charger, ChargingStrategy strategy) {
+ ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy, strategy);
return new EDrtWaitForShiftTask(beginTime, endTime, link, totalEnergy, facility, chargingTask);
}
public EDrtShiftBreakTaskImpl createChargingShiftBreakTask(DvrpVehicle vehicle, double beginTime, double endTime, Link link,
- DrtShiftBreak shiftBreak, Charger charger, double totalEnergy, OperationFacility facility) {
- ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy);
+ DrtShiftBreak shiftBreak, Charger charger, double totalEnergy, OperationFacility facility, ChargingStrategy strategy) {
+ ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy, strategy);
return new EDrtShiftBreakTaskImpl(beginTime, endTime, link, shiftBreak, totalEnergy, chargingTask, facility);
}
public ShiftChangeOverTask createChargingShiftChangeoverTask(DvrpVehicle vehicle, double beginTime, double endTime,
Link link, Charger charger, double totalEnergy,
- DrtShift shift, OperationFacility facility) {
- ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy);
+ DrtShift shift, OperationFacility facility, ChargingStrategy strategy) {
+ ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy, strategy);
return new EDrtShiftChangeoverTaskImpl(beginTime, endTime, link, shift, totalEnergy, chargingTask, facility);
}
}
diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java
index 9c5a7172282..2bc42cc1925 100644
--- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java
+++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java
@@ -1,5 +1,11 @@
package org.matsim.contrib.drt.extension.operations.eshifts.scheduler;
+import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.DRIVE;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -12,7 +18,11 @@
import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility;
import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams;
import org.matsim.contrib.drt.extension.operations.shifts.fleet.ShiftDvrpVehicle;
-import org.matsim.contrib.drt.extension.operations.shifts.schedule.*;
+import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftBreakTask;
+import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftChangeOverTask;
+import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftDrtTaskFactory;
+import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftSchedules;
+import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftTask;
import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftTaskScheduler;
import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift;
import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftBreak;
@@ -23,11 +33,16 @@
import org.matsim.contrib.dvrp.fleet.Fleet;
import org.matsim.contrib.dvrp.path.VrpPathWithTravelData;
import org.matsim.contrib.dvrp.path.VrpPaths;
-import org.matsim.contrib.dvrp.schedule.*;
+import org.matsim.contrib.dvrp.schedule.DriveTask;
+import org.matsim.contrib.dvrp.schedule.Schedule;
+import org.matsim.contrib.dvrp.schedule.Schedules;
+import org.matsim.contrib.dvrp.schedule.StayTask;
+import org.matsim.contrib.dvrp.schedule.Task;
import org.matsim.contrib.dvrp.tracker.OnlineDriveTaskTracker;
import org.matsim.contrib.dvrp.util.LinkTimePair;
import org.matsim.contrib.ev.charging.BatteryCharging;
import org.matsim.contrib.ev.charging.ChargingEstimations;
+import org.matsim.contrib.ev.charging.ChargingStrategy;
import org.matsim.contrib.ev.charging.ChargingWithAssignmentLogic;
import org.matsim.contrib.ev.fleet.ElectricVehicle;
import org.matsim.contrib.ev.infrastructure.Charger;
@@ -38,12 +53,7 @@
import org.matsim.core.router.util.LeastCostPathCalculator;
import org.matsim.core.router.util.TravelDisutility;
import org.matsim.core.router.util.TravelTime;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-
-import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.DRIVE;
+import org.matsim.core.utils.collections.Tuple;
/**
* @author nkuehnel / MOIA
@@ -61,10 +71,12 @@ public class EShiftTaskScheduler implements ShiftTaskScheduler {
private final Network network;
private final ChargingInfrastructure chargingInfrastructure;
+ private final ChargingStrategy.Factory chargingStrategyFactory;
public EShiftTaskScheduler(Network network, TravelTime travelTime, TravelDisutility travelDisutility,
MobsimTimer timer, ShiftDrtTaskFactory taskFactory, ShiftsParams shiftsParams,
- ChargingInfrastructure chargingInfrastructure, OperationFacilities operationFacilities, Fleet fleet) {
+ ChargingInfrastructure chargingInfrastructure, OperationFacilities operationFacilities, Fleet fleet,
+ ChargingStrategy.Factory chargingStrategyFactory) {
this.travelTime = travelTime;
this.timer = timer;
this.taskFactory = taskFactory;
@@ -72,6 +84,7 @@ public EShiftTaskScheduler(Network network, TravelTime travelTime, TravelDisutil
this.shiftsParams = shiftsParams;
this.router = new SpeedyALTFactory().createPathCalculator(network, travelDisutility, travelTime);
this.chargingInfrastructure = chargingInfrastructure;
+ this.chargingStrategyFactory = chargingStrategyFactory;
}
public void relocateForBreak(ShiftDvrpVehicle vehicle, OperationFacility breakFacility, DrtShift shift) {
@@ -169,23 +182,25 @@ private void relocateForBreakImpl(ShiftDvrpVehicle vehicle, double startTime, do
ShiftBreakTask dropoffStopTask;
ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle();
- Optional charger = charge(breakFacility, ev);
+ Optional charger = charge(breakFacility, ev);
if (charger.isPresent()) {
- final Charger chargerImpl = charger.get();
+ final ChargerWithStrategy chargerImpl = charger.get();
final double waitTime = ChargingEstimations
- .estimateMaxWaitTimeForNextVehicle(chargerImpl);
+ .estimateMaxWaitTimeForNextVehicle(chargerImpl.charger);
if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() > shiftsParams.chargeDuringBreakThreshold ||
waitTime > 0) {
dropoffStopTask = taskFactory.createShiftBreakTask(vehicle, startTime,
endTime, link, shiftBreak, breakFacility);
} else {
- double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargerImpl.getSpecification(), endTime - startTime);
+ ChargingStrategy strategy = chargingStrategyFactory.createStrategy(chargerImpl.charger.getSpecification(), ev);
+
+ double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargerImpl.charger.getSpecification(), endTime - startTime);
double totalEnergy = -energyCharge;
- ((ChargingWithAssignmentLogic) chargerImpl.getLogic()).assignVehicle(ev);
+ ((ChargingWithAssignmentLogic) chargerImpl.charger.getLogic()).assignVehicle(ev, strategy);
dropoffStopTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingShiftBreakTask(vehicle,
- startTime, endTime, link, shiftBreak, chargerImpl, totalEnergy, breakFacility);
+ startTime, endTime, link, shiftBreak, chargerImpl.charger, totalEnergy, breakFacility, chargerImpl.strategy);
}
} else {
dropoffStopTask = taskFactory.createShiftBreakTask(vehicle, startTime,
@@ -202,7 +217,7 @@ private void relocateForBreakImpl(ShiftDvrpVehicle vehicle, double startTime, do
shiftBreak.schedule(Math.min(latestDetourArrival, latestTimeConstraintArrival));
}
- private Optional charge(OperationFacility breakFacility, ElectricVehicle electricVehicle) {
+ private Optional charge(OperationFacility breakFacility, ElectricVehicle electricVehicle) {
if (chargingInfrastructure != null) {
List> chargerIds = breakFacility.getChargers();
if (!chargerIds.isEmpty()) {
@@ -218,16 +233,19 @@ private Optional charge(OperationFacility breakFacility, ElectricVehicl
return Double.compare(waitTime, waitTime2);
});
if (selectedCharger.isPresent()) {
- if (selectedCharger.get().getLogic().getChargingStrategy().isChargingCompleted(electricVehicle)) {
+ ChargingStrategy strategy = chargingStrategyFactory.createStrategy(selectedCharger.get().getSpecification(), electricVehicle);
+ if (strategy.isChargingCompleted()) {
return Optional.empty();
}
+ return Optional.of(new ChargerWithStrategy(selectedCharger.get(), strategy));
}
- return selectedCharger;
}
}
return Optional.empty();
}
+ private record ChargerWithStrategy(Charger charger, ChargingStrategy strategy) {}
+
public void relocateForShiftChange(DvrpVehicle vehicle, Link link, DrtShift shift, OperationFacility breakFacility) {
final Schedule schedule = vehicle.getSchedule();
@@ -318,24 +336,24 @@ private void appendShiftChange(DvrpVehicle vehicle, DrtShift shift, OperationFac
// append SHIFT_CHANGEOVER task
ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle();
- Optional charger = charge(breakFacility, ev);
+ Optional charger = charge(breakFacility, ev);
if (charger.isPresent()) {
- Charger chargingImpl = charger.get();
-
+ ChargerWithStrategy chargingImpl = charger.get();
+
final double waitTime = ChargingEstimations
- .estimateMaxWaitTimeForNextVehicle(chargingImpl);
+ .estimateMaxWaitTimeForNextVehicle(chargingImpl.charger);
if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() < shiftsParams.chargeDuringBreakThreshold
- || ((ChargingWithAssignmentLogic) chargingImpl.getLogic()).getAssignedVehicles().contains(ev)
+ || ((ChargingWithAssignmentLogic) chargingImpl.charger.getLogic()).isAssigned(ev)
|| waitTime > 0) {
dropoffStopTask = taskFactory.createShiftChangeoverTask(vehicle, startTime,
endTime, link, shift, breakFacility);
} else {
- double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargingImpl.getSpecification(), endTime - startTime);
+ double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargingImpl.charger.getSpecification(), endTime - startTime);
double totalEnergy = -energyCharge;
- ((ChargingWithAssignmentLogic) chargingImpl.getLogic()).assignVehicle(ev);
+ ((ChargingWithAssignmentLogic) chargingImpl.charger.getLogic()).assignVehicle(ev, chargingImpl.strategy);
dropoffStopTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingShiftChangeoverTask(vehicle,
- startTime, endTime, link, chargingImpl, totalEnergy, shift, breakFacility);
+ startTime, endTime, link, chargingImpl.charger, totalEnergy, shift, breakFacility, chargingImpl.strategy);
}
} else {
dropoffStopTask = taskFactory.createShiftChangeoverTask(vehicle, startTime,
@@ -470,12 +488,12 @@ private void updateShiftChangeImpl(DvrpVehicle vehicle, VrpPathWithTravelData vr
public void chargeAtHub(WaitForShiftTask currentTask, ShiftDvrpVehicle vehicle,
ElectricVehicle electricVehicle, Charger charger, double beginTime,
- double endTime, double energy) {
+ double endTime, double energy, ChargingStrategy strategy) {
final double initialEndTime = currentTask.getEndTime();
currentTask.setEndTime(beginTime);
- ((ChargingWithAssignmentLogic) charger.getLogic()).assignVehicle(electricVehicle);
+ ((ChargingWithAssignmentLogic) charger.getLogic()).assignVehicle(electricVehicle, strategy);
final WaitForShiftTask chargingWaitForShiftTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingWaitForShiftStayTask(vehicle,
- beginTime, endTime, currentTask.getLink(), currentTask.getFacility(), energy, charger);
+ beginTime, endTime, currentTask.getLink(), currentTask.getFacility(), energy, charger, strategy);
final WaitForShiftTask waitForShiftTask = taskFactory.createWaitForShiftStayTask(vehicle, endTime,
initialEndTime, currentTask.getLink(), currentTask.getFacility());
diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/eshifts/run/RunEShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/eshifts/run/RunEShiftDrtScenarioIT.java
index a137d932fe5..a65091c6102 100644
--- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/eshifts/run/RunEShiftDrtScenarioIT.java
+++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/eshifts/run/RunEShiftDrtScenarioIT.java
@@ -17,6 +17,7 @@
import org.matsim.contrib.drt.run.DrtConfigGroup;
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
+import org.matsim.contrib.dvrp.run.DvrpModes;
import org.matsim.contrib.ev.EvConfigGroup;
import org.matsim.contrib.ev.charging.*;
import org.matsim.contrib.ev.temperature.TemperatureService;
@@ -32,6 +33,8 @@
import org.matsim.core.controler.OutputDirectoryHierarchy;
import org.matsim.examples.ExamplesUtils;
+import com.google.inject.Key;
+
import java.util.HashSet;
import java.util.Set;
@@ -177,8 +180,8 @@ void test() {
controler.addOverridingModule(new AbstractModule() {
@Override
public void install() {
- bind(ChargingLogic.Factory.class).toProvider(new ChargingWithQueueingAndAssignmentLogic.FactoryProvider(
- charger -> new ChargeUpToMaxSocStrategy(charger, MAX_RELATIVE_SOC)));
+ bind(ChargingLogic.Factory.class).to(ChargingWithQueueingAndAssignmentLogic.Factory.class);
+ bind(Key.get(ChargingStrategy.Factory.class, DvrpModes.mode(drtConfigGroup.mode))).toInstance(new ChargeUpToMaxSocStrategy.Factory(MAX_RELATIVE_SOC));
bind(ChargingPower.Factory.class).toInstance(FastThenSlowCharging::new);
bind(TemperatureService.class).toInstance(linkId -> TEMPERATURE);
}
diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java
index 61e3a64a97a..e4286bed31c 100644
--- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java
+++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java
@@ -280,8 +280,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(5000);
- start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 1800.);
- start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5000.);
+ AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 1800.0);
+ AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 5000.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
@@ -295,8 +295,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(5000);
- start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 900.);
- start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5005.);
+ AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 900.0);
+ AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 5005.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
@@ -310,8 +310,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(5000);
- start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.);
- start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5000.);
+ AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 4000.0);
+ AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 5000.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
@@ -325,8 +325,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(8000);
- start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.);
- start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 11000.);
+ AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 4000.0);
+ AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 11000.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
@@ -340,8 +340,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(6000.);
- start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.);
- start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 6000.);
+ AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 4000.0);
+ AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 6000.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
@@ -355,8 +355,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(6500.);
- start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.);
- start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 6500.);
+ AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 4000.0);
+ AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 6500.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/services/RunEDrtWithServicesScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/services/RunEDrtWithServicesScenarioIT.java
index b16dca56807..da8b28c6c82 100644
--- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/services/RunEDrtWithServicesScenarioIT.java
+++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/services/RunEDrtWithServicesScenarioIT.java
@@ -14,6 +14,7 @@
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
import org.matsim.contrib.dvrp.fleet.DvrpVehicle;
import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule;
+import org.matsim.contrib.dvrp.run.DvrpModes;
import org.matsim.contrib.ev.charging.*;
import org.matsim.contrib.ev.temperature.TemperatureService;
import org.matsim.core.config.Config;
@@ -22,6 +23,8 @@
import org.matsim.core.controler.Controler;
import org.matsim.testcases.MatsimTestUtils;
+import com.google.inject.Key;
+
public class RunEDrtWithServicesScenarioIT {
public static final double MINIMUM_RELATIVE_SOC = 0.2;
public static final double MAX_SOC = 1.0;
@@ -77,7 +80,8 @@ public void install() {
controler.addOverridingModule(new AbstractModule() {
@Override
public void install() {
- bind(ChargingLogic.Factory.class).toProvider(new ChargingWithQueueingAndAssignmentLogic.FactoryProvider(charger -> new ChargeUpToMaxSocStrategy(charger, MAX_SOC)));
+ bind(ChargingLogic.Factory.class).to(ChargingWithQueueingAndAssignmentLogic.Factory.class);
+ bind(Key.get(ChargingStrategy.Factory.class, DvrpModes.mode(drtConfigGroup.mode))).toInstance(new ChargeUpToMaxSocStrategy.Factory(MAX_SOC));
bind(ChargingPower.Factory.class).toInstance(ev -> new FixedSpeedCharging(ev, RELATIVE_SPEED));
bind(TemperatureService.class).toInstance(linkId -> TEMPERATURE);
}
diff --git a/contribs/drt/pom.xml b/contribs/drt/pom.xml
index 7790f252b3c..99fd9d77ec7 100644
--- a/contribs/drt/pom.xml
+++ b/contribs/drt/pom.xml
@@ -15,19 +15,19 @@
org.matsim.contribdvrp
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribotfvis
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribcommon
- 2025.0-SNAPSHOT
+ ${project.parent.version}
diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java
index 90836e785cc..cee1304544d 100644
--- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java
+++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java
@@ -159,7 +159,10 @@ public List getDrtFares() {
}
public boolean isCompleted() {
- return submitted.getPersonIds().stream().allMatch(personId -> personEvents.get(personId).droppedOff != null);
+ return submitted.getPersonIds().stream().allMatch(personId -> {
+ var events = personEvents.get(personId);
+ return events != null && personEvents.get(personId).droppedOff != null;
+ });
}
}
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 ce140ce1772..610511c61e2 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
@@ -37,6 +37,7 @@
import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector;
import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector.EventSequence;
import org.matsim.contrib.drt.run.DrtConfigGroup;
+import org.matsim.contrib.dvrp.optimizer.Request;
import org.matsim.core.controler.events.IterationEndsEvent;
import org.matsim.core.controler.events.ShutdownEvent;
import org.matsim.core.controler.listener.IterationEndsListener;
@@ -79,7 +80,7 @@ public void notifyIterationEnds(IterationEndsEvent event) {
}
public void write(String fileName) {
- Map, DescriptiveStatistics> zoneStats = createZonalStats();
+ Map, ZonalStatistics> zoneStats = createZonalStats();
BufferedWriter bw = IOUtils.getBufferedWriter(fileName);
try {
DecimalFormat format = new DecimalFormat();
@@ -90,7 +91,8 @@ public void write(String fileName) {
String header = new StringJoiner(delimiter)
.add("zone").add("centerX").add("centerY").add("nRequests")
.add("sumWaitTime").add("meanWaitTime").add("min").add("max")
- .add("p95").add("p90").add("p80").add("p75").add("p50").toString();
+ .add("p95").add("p90").add("p80").add("p75").add("p50")
+ .add("rejections").add("rejectionRate").toString();
bw.append(header);
// sorted output
SortedSet> zoneIdsAndOutside = new TreeSet<>(zones.getZones().keySet());
@@ -100,7 +102,8 @@ public void write(String fileName) {
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);
+ DescriptiveStatistics stats = zoneStats.get(zoneId).waitStats;
+ Set> rejections = zoneStats.get(zoneId).rejections;
bw.newLine();
bw.append(
new StringJoiner(delimiter)
@@ -116,7 +119,10 @@ public void write(String fileName) {
.add(String.valueOf(stats.getPercentile(90)))
.add(String.valueOf(stats.getPercentile(80)))
.add(String.valueOf(stats.getPercentile(75)))
- .add(String.valueOf(stats.getPercentile(50))).toString()
+ .add(String.valueOf(stats.getPercentile(50)))
+ .add(String.valueOf(rejections.size()))
+ .add(String.valueOf(rejections.size() / (double) (rejections.size() + stats.getN())))
+ .toString()
);
}
bw.flush();
@@ -126,13 +132,15 @@ public void write(String fileName) {
}
}
- private Map, DescriptiveStatistics> createZonalStats() {
- Map, DescriptiveStatistics> zoneStats = new IdMap<>(Zone.class);
+ record ZonalStatistics(DescriptiveStatistics waitStats, Set> rejections){}
+
+ private Map, ZonalStatistics> createZonalStats() {
+ Map, ZonalStatistics> zoneStats = new IdMap<>(Zone.class);
// prepare stats for all zones
for (Id zoneId : zones.getZones().keySet()) {
- zoneStats.put(zoneId, new DescriptiveStatistics());
+ zoneStats.put(zoneId, new ZonalStatistics(new DescriptiveStatistics(), new HashSet<>()));
}
- zoneStats.put(zoneIdForOutsideOfZonalSystem, new DescriptiveStatistics());
+ zoneStats.put(zoneIdForOutsideOfZonalSystem, new ZonalStatistics(new DescriptiveStatistics(), new HashSet<>()));
for (EventSequence seq : requestAnalyzer.getPerformedRequestSequences().values()) {
for (Map.Entry, EventSequence.PersonEvents> entry : seq.getPersonEvents().entrySet()) {
@@ -140,10 +148,17 @@ private Map, DescriptiveStatistics> createZonalStats() {
Id zone = zones.getZoneForLinkId(seq.getSubmitted().getFromLinkId())
.map(Identifiable::getId).orElse(zoneIdForOutsideOfZonalSystem);
double waitTime = entry.getValue().getPickedUp().get() .getTime() - seq.getSubmitted().getTime();
- zoneStats.get(zone).addValue(waitTime);
+ zoneStats.get(zone).waitStats.addValue(waitTime);
}
}
}
+
+ for (EventSequence seq : requestAnalyzer.getRejectedRequestSequences().values()) {
+ Id zone = zones.getZoneForLinkId(seq.getSubmitted().getFromLinkId())
+ .map(Identifiable::getId).orElse(zoneIdForOutsideOfZonalSystem);
+ zoneStats.get(zone).rejections.add(seq.getSubmitted().getRequestId());
+ }
+
return zoneStats;
}
@@ -191,16 +206,19 @@ private Collection convertGeometriesToSimpleFeatures(String targe
simpleFeatureBuilder.add("p80", Double.class);
simpleFeatureBuilder.add("p75", Double.class);
simpleFeatureBuilder.add("p50", Double.class);
+ simpleFeatureBuilder.add("rejections", Double.class);
+ simpleFeatureBuilder.add("rejectRate", Double.class);
SimpleFeatureBuilder builder = new SimpleFeatureBuilder(simpleFeatureBuilder.buildFeatureType());
Collection features = new ArrayList<>();
- Map, DescriptiveStatistics> zoneStats = createZonalStats();
+ Map, ZonalStatistics> zoneStats = createZonalStats();
for (Zone zone : zones.getZones().values()) {
- Object[] routeFeatureAttributes = new Object[14];
+ Object[] routeFeatureAttributes = new Object[16];
Geometry geometry = zone.getPreparedGeometry() != null ? zone.getPreparedGeometry().getGeometry() : null;
- DescriptiveStatistics stats = zoneStats.get(zone.getId());
+ DescriptiveStatistics stats = zoneStats.get(zone.getId()).waitStats;
+ Set> rejections = zoneStats.get(zone.getId()).rejections;
routeFeatureAttributes[0] = geometry;
routeFeatureAttributes[1] = zone.getId();
routeFeatureAttributes[2] = zone.getCentroid().getX();
@@ -215,6 +233,8 @@ private Collection convertGeometriesToSimpleFeatures(String targe
routeFeatureAttributes[11] = stats.getPercentile(80);
routeFeatureAttributes[12] = stats.getPercentile(75);
routeFeatureAttributes[13] = stats.getPercentile(50);
+ routeFeatureAttributes[14] = rejections.size();
+ routeFeatureAttributes[15] = rejections.size() / (double) (rejections.size() + stats.getN());
try {
features.add(builder.buildFeature(zone.getId().toString(), routeFeatureAttributes));
diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/constraints/DefaultDrtOptimizationConstraintsSet.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/constraints/DefaultDrtOptimizationConstraintsSet.java
index 3ba0a7ce169..fd26a90256a 100644
--- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/constraints/DefaultDrtOptimizationConstraintsSet.java
+++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/constraints/DefaultDrtOptimizationConstraintsSet.java
@@ -23,34 +23,35 @@ public class DefaultDrtOptimizationConstraintsSet extends DrtOptimizationConstra
@Parameter
@Comment(
- "Defines the maximum allowed absolute detour in seconds. Note that the detour is computed from the latest promised pickup time. " +
- "To enable the max detour constraint, maxAllowedPickupDelay has to be specified. maxAbsoluteDetour should not be smaller than 0, "
+ "Defines the maximum allowed absolute detour in seconds. maxAbsoluteDetour should not be smaller than 0, "
+ "and should be higher than the offset maxDetourBeta. By default, this limit is disabled (i.e. set to Inf)")
@PositiveOrZero
public double maxAbsoluteDetour = Double.POSITIVE_INFINITY;// [s]
@Parameter
@Comment(
- "Defines the maximum allowed absolute detour based on the unsharedRideTime. Note that the detour is computed from the latest promised "
- + "pickup time. To enable the max detour constraint, maxAllowedPickupDelay has to be specified. A linear combination similar to travel "
+ "Defines the maximum allowed absolute detour based on the unsharedRideTime. A linear combination similar to travel "
+ "time constrain is used. This is the ratio part. By default, this limit is disabled (i.e. set to Inf, together with maxDetourBeta).")
@DecimalMin("1.0")
public double maxDetourAlpha = Double.POSITIVE_INFINITY;
@Parameter
@Comment(
- "Defines the maximum allowed absolute detour based on the unsharedRideTime. Note that the detour is computed from the latest promised "
- + "pickup time. To enable the max detour constraint, maxAllowedPickupDelay has to be specified. A linear combination similar to travel "
+ "Defines the maximum allowed absolute detour based on the unsharedRideTime. A linear combination similar to travel "
+ "time constrain is used. This is the constant part. By default, this limit is disabled (i.e. set to Inf, together with maxDetourAlpha).")
@PositiveOrZero
public double maxDetourBeta = Double.POSITIVE_INFINITY;// [s]
+ @Parameter
+ @Comment(
+ "Defines the minimum allowed absolute detour in seconds. By default, this bound is disabled (i.e. set to 0.)")
+ @PositiveOrZero
+ public double minimumAllowedDetour = 0;
+
@Override
protected void checkConsistency(Config config) {
super.checkConsistency(config);
- 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.");
- }
+ Verify.verify(maxAbsoluteDetour > minimumAllowedDetour, "The minimum allowed detour must" +
+ "be lower than the maximum allowed detour.");
}
}
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 4e06666ed05..f3892019345 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
@@ -40,6 +40,9 @@
*/
public class MinCostFlowRebalancingStrategy implements RebalancingStrategy {
+ public static final String REBALANCING_ZONAL_TARGET_ALPHA = "rebalalpha";
+ public static final String REBALANCING_ZONAL_TARGET_BETA = "rebalbeta";
+
private final RebalancingTargetCalculator rebalancingTargetCalculator;
private final ZoneSystem zonalSystem;
private final Fleet fleet;
@@ -68,18 +71,37 @@ public List calcRelocations(Stream extends DvrpVehicle> rebalancab
return calculateMinCostRelocations(time, rebalancableVehiclesPerZone, soonIdleVehiclesPerZone);
}
- private List calculateMinCostRelocations(double time,
+ List calculateMinCostRelocations(double time,
Map> rebalancableVehiclesPerZone,
Map> soonIdleVehiclesPerZone) {
ToDoubleFunction targetFunction = rebalancingTargetCalculator.calculate(time,
rebalancableVehiclesPerZone);
var minCostFlowRebalancingStrategyParams = (MinCostFlowRebalancingStrategyParams)params.getRebalancingStrategyParams();
- double alpha = minCostFlowRebalancingStrategyParams.targetAlpha;
- double beta = minCostFlowRebalancingStrategyParams.targetBeta;
- List vehicleSurpluses = zonalSystem.getZones().values().stream().map(z -> {
+ List vehicleSurpluses = zonalSystem.getZones().values().stream().map(z -> {
+ double alpha;
+ double beta;
int rebalancable = rebalancableVehiclesPerZone.getOrDefault(z, List.of()).size();
int soonIdle = soonIdleVehiclesPerZone.getOrDefault(z, List.of()).size();
+
+ switch (minCostFlowRebalancingStrategyParams.targetCoefficientSource) {
+ case Static -> {
+ alpha = minCostFlowRebalancingStrategyParams.targetAlpha;
+ beta = minCostFlowRebalancingStrategyParams.targetBeta;
+ }
+ case FromZoneAttribute -> {
+ alpha = (Double) z.getAttributes().getAttribute(REBALANCING_ZONAL_TARGET_ALPHA);
+ beta = (Double) z.getAttributes().getAttribute(REBALANCING_ZONAL_TARGET_BETA);
+ }
+ case FromZoneAttributeOrStatic -> {
+ Object alphaAttribute = z.getAttributes().getAttribute(REBALANCING_ZONAL_TARGET_ALPHA);
+ alpha = alphaAttribute == null ? minCostFlowRebalancingStrategyParams.targetAlpha : (Double) alphaAttribute;
+ Object betaAttribute = z.getAttributes().getAttribute(REBALANCING_ZONAL_TARGET_BETA);
+ beta = betaAttribute == null ? minCostFlowRebalancingStrategyParams.targetBeta : (Double) betaAttribute;
+ }
+ default -> throw new IllegalStateException("Unknown target coefficient source " + minCostFlowRebalancingStrategyParams.targetCoefficientSource);
+ }
+
int target = (int)Math.floor(alpha * targetFunction.applyAsDouble(z) + beta);
int surplus = Math.min(rebalancable + soonIdle - target, rebalancable);
return new DrtZoneVehicleSurplus(z, surplus);
diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategyParams.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategyParams.java
index 7c0a72e3a07..a09867d4785 100644
--- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategyParams.java
+++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategyParams.java
@@ -56,6 +56,19 @@ public enum RebalancingTargetCalculatorType {
@NotNull
public RebalancingTargetCalculatorType rebalancingTargetCalculatorType = RebalancingTargetCalculatorType.EstimatedDemand;
+
+ public enum TargetCoefficientSource {
+ Static, FromZoneAttribute, FromZoneAttributeOrStatic
+ }
+
+ @Parameter
+ @Comment("Defines whether the alpha and beta of the target function should be"
+ + " [Static] or [FromZoneAttribute] in which case alpha and beta can be provided per zone as an attribute."
+ + " [FromZoneAttributeOrStatic] will fall back to the static coefficients if no attribute is found for a given zone."
+ + " Use " + MinCostFlowRebalancingStrategy.REBALANCING_ZONAL_TARGET_ALPHA + " and " + MinCostFlowRebalancingStrategy.REBALANCING_ZONAL_TARGET_BETA
+ + " to set values accordingly.")
+ public TargetCoefficientSource targetCoefficientSource = TargetCoefficientSource.Static;
+
public enum ZonalDemandEstimatorType {PreviousIterationDemand, None}
@Parameter
diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java
index a5dad2f114b..69aef1db822 100644
--- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java
+++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java
@@ -399,22 +399,31 @@ private void processRejections(double now) {
int index = WithinDayAgentUtils.getCurrentPlanElementIndex(agent);
Plan plan = WithinDayAgentUtils.getModifiablePlan(agent);
PlanElement planElement = plan.getPlanElements().get(index);
- Activity activity;
- if(planElement instanceof Activity currentActivity) {
- activity = currentActivity;
+
+ if (planElement instanceof Activity currentActivity) {
+ Activity activity = currentActivity;
+ activity.setEndTime(Double.POSITIVE_INFINITY);
+ activity.setMaximumDurationUndefined();
+
+ ((HasModifiablePlan) agent).resetCaches();
+ internalInterface.getMobsim().rescheduleActivityEnd(agent);
+ eventsManager.processEvent(new PersonStuckEvent(now, agent.getId(), agent.getCurrentLinkId(),
+ this.mode));
+
+ internalInterface.getMobsim().getAgentCounter().incLost();
+ internalInterface.getMobsim().getAgentCounter().decLiving();
} else {
// If the current element is a leg, the agent is walking towards the pickup location
// We make the agent stuck at the interaction activity
- activity = (Activity) plan.getPlanElements().get(index+1);
+ while (index < plan.getPlanElements().size()) {
+ if (plan.getPlanElements().get(index) instanceof Activity activity) {
+ activity.setEndTime(Double.POSITIVE_INFINITY);
+ activity.setMaximumDurationUndefined();
+ }
+
+ index++;
+ }
}
- activity.setEndTime(Double.POSITIVE_INFINITY);
- activity.setMaximumDurationUndefined();
-
- ((HasModifiablePlan) agent).resetCaches();
- internalInterface.getMobsim().rescheduleActivityEnd(agent);
- eventsManager.processEvent(new PersonStuckEvent(now, agent.getId(), agent.getCurrentLinkId(),
- this.mode));
- internalInterface.getMobsim().getAgentCounter().incLost();
}
}
}
diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/logic/AttributeBasedPrebookingLogic.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/logic/AttributeBasedPrebookingLogic.java
index a48cbe50e46..7908ca1378c 100644
--- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/logic/AttributeBasedPrebookingLogic.java
+++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/logic/AttributeBasedPrebookingLogic.java
@@ -2,6 +2,7 @@
import java.util.Optional;
+import org.matsim.api.core.v01.population.Activity;
import org.matsim.api.core.v01.population.Leg;
import org.matsim.api.core.v01.population.PlanElement;
import org.matsim.contrib.drt.prebooking.logic.helpers.PopulationIterator;
@@ -35,23 +36,40 @@
* @author Sebastian Hörl (sebhoerl), IRT SystemX
*/
public class AttributeBasedPrebookingLogic implements PrebookingLogic, MobsimInitializedListener {
- static private final String SUBMISSION_TIME_ATTRIBUTE_PREFIX = "prebooking:submissionTime";
- static private final String PLANNED_DEPARTURE_ATTRIBUTE_PREFIX = "prebooking:plannedDepartureTime";
+ static private final String SUBMISSION_TIME_ATTRIBUTE_PREFIX = "prebooking:submissionTime:";
+ static private final String PLANNED_DEPARTURE_ATTRIBUTE_PREFIX = "prebooking:plannedDepartureTime:";
- static public String getSubmissionAttribute(String mode) {
+ static public String getSubmissionTimeAttribute(String mode) {
return SUBMISSION_TIME_ATTRIBUTE_PREFIX + mode;
}
- static public String getPlannedDepartureAttribute(String mode) {
+ static public String getPlannedDepartureTimeAttribute(String mode) {
return PLANNED_DEPARTURE_ATTRIBUTE_PREFIX + mode;
}
static public Optional getSubmissionTime(String mode, Trip trip) {
- return Optional.ofNullable((Double) trip.getTripAttributes().getAttribute(getSubmissionAttribute(mode)));
+ return Optional.ofNullable((Double) trip.getTripAttributes().getAttribute(getSubmissionTimeAttribute(mode)));
}
static public Optional getPlannedDepartureTime(String mode, Trip trip) {
- return Optional.ofNullable((Double) trip.getTripAttributes().getAttribute(getPlannedDepartureAttribute(mode)));
+ return Optional
+ .ofNullable((Double) trip.getTripAttributes().getAttribute(getPlannedDepartureTimeAttribute(mode)));
+ }
+
+ static public void setSubmissionTime(String mode, Trip trip, double submissionTime) {
+ trip.getTripAttributes().putAttribute(getSubmissionTimeAttribute(mode), submissionTime);
+ }
+
+ static public void setPlannedDepartureTime(String mode, Trip trip, double plannedDepartureTime) {
+ trip.getTripAttributes().putAttribute(getPlannedDepartureTimeAttribute(mode), plannedDepartureTime);
+ }
+
+ static public void setSubmissionTime(String mode, Activity originActivity, double submissionTime) {
+ originActivity.getAttributes().putAttribute(getSubmissionTimeAttribute(mode), submissionTime);
+ }
+
+ static public void setPlannedDepartureTime(String mode, Activity originActivity, double plannedDepartureTime) {
+ originActivity.getAttributes().putAttribute(getPlannedDepartureTimeAttribute(mode), plannedDepartureTime);
}
private final PrebookingQueue prebookingQueue;
diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/routing/DefaultDrtRouteConstraintsCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/routing/DefaultDrtRouteConstraintsCalculator.java
index f8e1f9b36eb..cfcaaa3e5c8 100644
--- a/contribs/drt/src/main/java/org/matsim/contrib/drt/routing/DefaultDrtRouteConstraintsCalculator.java
+++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/routing/DefaultDrtRouteConstraintsCalculator.java
@@ -25,9 +25,12 @@ public DefaultDrtRouteConstraintsCalculator(DrtConfigGroup drtCfg, ConstraintSet
/**
* Calculates the maximum travel time defined as: drtCfg.getMaxTravelTimeAlpha()
* unsharedRideTime + drtCfg.getMaxTravelTimeBeta()
- *
- * Calculates the maximum ride time defined as: drtCfg.maxDetourAlpha *
- * unsharedRideTime + drtCfg.maxDetourBeta
+ *
+ * Calculates the maximum ride time defined as:
+ * unsharedRideTime + min(
+ * maxAbsoluteDetour,
+ * max(minimumAllowedDetour, unsharedRideTime * (1-drtCfg.maxDetourAlpha) + drtCfg.maxDetourBeta)
+ * )
*
* @return DrtRouteConstraints constraints
*/
@@ -40,8 +43,8 @@ public DrtRouteConstraints calculateRouteConstraints(double departureTime, Link
if (constraintsSet instanceof DefaultDrtOptimizationConstraintsSet defaultSet) {
double maxTravelTime = defaultSet.maxTravelTimeAlpha * unsharedRideTime + defaultSet.maxTravelTimeBeta;
- double maxRideTime = Math.min(unsharedRideTime + defaultSet.maxAbsoluteDetour,
- defaultSet.maxDetourAlpha * unsharedRideTime + defaultSet.maxDetourBeta);
+ double maxDetour = Math.max(defaultSet.minimumAllowedDetour, unsharedRideTime * (defaultSet.maxDetourAlpha -1) + defaultSet.maxDetourBeta);
+ double maxRideTime = unsharedRideTime + Math.min(defaultSet.maxAbsoluteDetour, maxDetour);
double maxWaitTime = constraintsSet.maxWaitTime;
return new DrtRouteConstraints(maxTravelTime, maxRideTime, maxWaitTime);
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 7f43fd42d8b..cca630fcf0c 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
@@ -199,9 +199,9 @@ static Network createNetwork() {
network.addNode(b);
Link ab = network.getFactory().createLink(Id.createLinkId("link_1"), a, b);
- Link bc = network.getFactory().createLink(Id.createLinkId("link_2"), b, a);
+ Link ba = network.getFactory().createLink(Id.createLinkId("link_2"), b, a);
network.addLink(ab);
- network.addLink(bc);
+ network.addLink(ba);
return network;
}
}
diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategyTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategyTest.java
new file mode 100644
index 00000000000..8aba7eefc00
--- /dev/null
+++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/optimizer/rebalancing/mincostflow/MinCostFlowRebalancingStrategyTest.java
@@ -0,0 +1,279 @@
+package org.matsim.contrib.drt.optimizer.rebalancing.mincostflow;
+
+import com.google.common.collect.ImmutableMap;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.locationtech.jts.geom.prep.PreparedPolygon;
+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.events.PersonDepartureEvent;
+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.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.analysis.zonal.MostCentralDrtZoneTargetLinkSelector;
+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.targetcalculator.DemandEstimatorAsTargetCalculator;
+import org.matsim.contrib.drt.run.DrtConfigGroup;
+import org.matsim.contrib.dvrp.fleet.*;
+import org.matsim.core.network.NetworkUtils;
+import org.matsim.core.utils.geometry.GeometryUtils;
+
+import java.util.*;
+
+public class MinCostFlowRebalancingStrategyTest {
+
+ private static final int ESTIMATION_PERIOD = 1800;
+
+ private final Network network = createNetwork();
+
+ private final Link link1 = network.getLinks().get(Id.createLinkId("link_1"));
+ private final Link link2 = network.getLinks().get(Id.createLinkId("link_2"));
+
+ private final Zone zone1 = new ZoneImpl(
+ Id.create("zone_1", Zone.class),
+ new PreparedPolygon(GeometryUtils.createGeotoolsPolygon(
+ List.of(
+ new Coord(0, 0),
+ new Coord(0, 500),
+ new Coord(500, 500),
+ new Coord(500, 0),
+ new Coord(0, 0)
+ ))), "dummy");
+
+ private final Zone zone2 = new ZoneImpl(
+ Id.create("zone_2", Zone.class),
+ new PreparedPolygon(GeometryUtils.createGeotoolsPolygon(
+ List.of(
+ new Coord(500, 0),
+ new Coord(500, 500),
+ new Coord(1000, 500),
+ new Coord(1000, 0),
+ new Coord(500, 0)
+ ))), "dummy");
+
+ private final ZoneSystem zonalSystem = new ZoneSystemImpl(List.of(zone1, zone2), coord -> {
+ if (coord == link1.getToNode().getCoord()) {
+ return Optional.of(zone1);
+ } else if (coord == link2.getToNode().getCoord()) {
+ return Optional.of(zone2);
+ } else {
+ throw new RuntimeException();
+ }
+ }, network);
+
+
+ @Test
+ void testEmptyDemandAndTarget() {
+ PreviousIterationDrtDemandEstimator estimator = createEstimator();
+ DemandEstimatorAsTargetCalculator targetCalculator = new DemandEstimatorAsTargetCalculator(estimator, ESTIMATION_PERIOD);
+
+ RebalancingParams rebalancingParams = new RebalancingParams();
+ MinCostFlowRebalancingStrategyParams minCostFlowRebalancingStrategyParams = new MinCostFlowRebalancingStrategyParams();
+ minCostFlowRebalancingStrategyParams.targetAlpha = 1.;
+ minCostFlowRebalancingStrategyParams.targetBeta = 0.;
+ rebalancingParams.addParameterSet(minCostFlowRebalancingStrategyParams);
+
+ AggregatedMinCostRelocationCalculator relocationCalculator = new AggregatedMinCostRelocationCalculator(new MostCentralDrtZoneTargetLinkSelector(zonalSystem));
+ MinCostFlowRebalancingStrategy strategy = new MinCostFlowRebalancingStrategy(targetCalculator,
+ zonalSystem, createEmptyFleet(), relocationCalculator, rebalancingParams);
+
+ Map> rebalanceableVehicles = new HashMap<>();
+ List relocations = strategy.calculateMinCostRelocations(0, rebalanceableVehicles, Collections.emptyMap());
+ Assertions.assertThat(relocations.isEmpty());
+ }
+
+ @Test
+ void testDemandWithoutSurplus() {
+ PreviousIterationDrtDemandEstimator estimator = createEstimator();
+ DemandEstimatorAsTargetCalculator targetCalculator = new DemandEstimatorAsTargetCalculator(estimator, ESTIMATION_PERIOD);
+
+ RebalancingParams rebalancingParams = new RebalancingParams();
+ MinCostFlowRebalancingStrategyParams minCostFlowRebalancingStrategyParams = new MinCostFlowRebalancingStrategyParams();
+ minCostFlowRebalancingStrategyParams.targetAlpha = 1.;
+ minCostFlowRebalancingStrategyParams.targetBeta = 0.;
+ rebalancingParams.addParameterSet(minCostFlowRebalancingStrategyParams);
+
+ AggregatedMinCostRelocationCalculator relocationCalculator = new AggregatedMinCostRelocationCalculator(new MostCentralDrtZoneTargetLinkSelector(zonalSystem));
+ MinCostFlowRebalancingStrategy strategy = new MinCostFlowRebalancingStrategy(targetCalculator,
+ zonalSystem, createEmptyFleet(), relocationCalculator, rebalancingParams);
+
+ //time bin 0-1800
+ estimator.handleEvent(departureEvent(100, link1, TransportMode.drt));
+ estimator.handleEvent(departureEvent(200, link1, TransportMode.drt));
+ estimator.handleEvent(departureEvent(500, link2, TransportMode.drt));
+ estimator.handleEvent(departureEvent(1500, link1, TransportMode.drt));
+ estimator.reset(1);
+
+ Map> rebalanceableVehicles = new HashMap<>();
+ List relocations = strategy.calculateMinCostRelocations(0, rebalanceableVehicles, Collections.emptyMap());
+ Assertions.assertThat(relocations.isEmpty());
+ }
+
+ @Test
+ void testDemandWithSurplus() {
+ PreviousIterationDrtDemandEstimator estimator = createEstimator();
+ DemandEstimatorAsTargetCalculator targetCalculator = new DemandEstimatorAsTargetCalculator(estimator, ESTIMATION_PERIOD);
+
+ RebalancingParams rebalancingParams = new RebalancingParams();
+ MinCostFlowRebalancingStrategyParams minCostFlowRebalancingStrategyParams = new MinCostFlowRebalancingStrategyParams();
+ minCostFlowRebalancingStrategyParams.targetAlpha = 1.;
+ minCostFlowRebalancingStrategyParams.targetBeta = 0.;
+ rebalancingParams.addParameterSet(minCostFlowRebalancingStrategyParams);
+
+ AggregatedMinCostRelocationCalculator relocationCalculator = new AggregatedMinCostRelocationCalculator(new MostCentralDrtZoneTargetLinkSelector(zonalSystem));
+ MinCostFlowRebalancingStrategy strategy = new MinCostFlowRebalancingStrategy(targetCalculator,
+ zonalSystem, createEmptyFleet(), relocationCalculator, rebalancingParams);
+
+ // 3 expected trips in zone 1
+ estimator.handleEvent(departureEvent(100, link1, TransportMode.drt));
+ estimator.handleEvent(departureEvent(200, link1, TransportMode.drt));
+ estimator.handleEvent(departureEvent(300, link1, TransportMode.drt));
+ // 1 expected trip in zone 2
+ estimator.handleEvent(departureEvent(100, link2, TransportMode.drt));
+ estimator.reset(1);
+
+ Map> rebalanceableVehicles = new HashMap<>();
+
+ // 4 vehicles in zone 1 (surplus = 1)
+ List rebalanceableVehiclesZone1 = new ArrayList<>();
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a1", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a2", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a3", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a4", DvrpVehicle.class), link1));
+ rebalanceableVehicles.put(zone1, rebalanceableVehiclesZone1);
+
+ List relocations = strategy.calculateMinCostRelocations(0, rebalanceableVehicles, Collections.emptyMap());
+ Assertions.assertThat(relocations.size()).isEqualTo(1);
+ Assertions.assertThat(relocations.getFirst().link.getId()).isEqualTo(link2.getId());
+
+ rebalanceableVehicles.clear();
+
+ // 5 vehicles in zone 1 (surplus = 2)
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a1", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a2", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a3", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a4", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a5", DvrpVehicle.class), link1));
+ rebalanceableVehicles.put(zone1, rebalanceableVehiclesZone1);
+
+ //set alpha to 2 -> send two vehicles to zone 2
+ minCostFlowRebalancingStrategyParams.targetAlpha = 2.;
+ List relocations2 = strategy.calculateMinCostRelocations(0, rebalanceableVehicles, Collections.emptyMap());
+ Assertions.assertThat(relocations2.size()).isEqualTo(2);
+ Assertions.assertThat(relocations2.getFirst().link.getId()).isEqualTo(link2.getId());
+ Assertions.assertThat(relocations2.getLast().link.getId()).isEqualTo(link2.getId());
+ }
+
+ @Test
+ void testDemandWithSurplusZoneBasedTargetRates() {
+
+ // set attributes
+ zone1.getAttributes().putAttribute(MinCostFlowRebalancingStrategy.REBALANCING_ZONAL_TARGET_ALPHA, 0.);
+ zone1.getAttributes().putAttribute(MinCostFlowRebalancingStrategy.REBALANCING_ZONAL_TARGET_BETA, 0.);
+ zone2.getAttributes().putAttribute(MinCostFlowRebalancingStrategy.REBALANCING_ZONAL_TARGET_ALPHA, 1.);
+ zone2.getAttributes().putAttribute(MinCostFlowRebalancingStrategy.REBALANCING_ZONAL_TARGET_BETA, 0.);
+
+
+ PreviousIterationDrtDemandEstimator estimator = createEstimator();
+ DemandEstimatorAsTargetCalculator targetCalculator = new DemandEstimatorAsTargetCalculator(estimator, ESTIMATION_PERIOD);
+
+ RebalancingParams rebalancingParams = new RebalancingParams();
+ MinCostFlowRebalancingStrategyParams minCostFlowRebalancingStrategyParams = new MinCostFlowRebalancingStrategyParams();
+ minCostFlowRebalancingStrategyParams.targetCoefficientSource = MinCostFlowRebalancingStrategyParams.TargetCoefficientSource.FromZoneAttribute;
+ rebalancingParams.addParameterSet(minCostFlowRebalancingStrategyParams);
+
+ AggregatedMinCostRelocationCalculator relocationCalculator = new AggregatedMinCostRelocationCalculator(new MostCentralDrtZoneTargetLinkSelector(zonalSystem));
+ MinCostFlowRebalancingStrategy strategy = new MinCostFlowRebalancingStrategy(targetCalculator,
+ zonalSystem, createEmptyFleet(), relocationCalculator, rebalancingParams);
+
+ // 3 expected trips in zone 1
+ estimator.handleEvent(departureEvent(100, link1, TransportMode.drt));
+ estimator.handleEvent(departureEvent(200, link1, TransportMode.drt));
+ estimator.handleEvent(departureEvent(300, link1, TransportMode.drt));
+ // 1 expected trip in zone 2
+ estimator.handleEvent(departureEvent(100, link2, TransportMode.drt));
+ estimator.reset(1);
+
+ Map> rebalanceableVehicles = new HashMap<>();
+
+ // 4 vehicles in zone 1 (surplus = 1)
+ List rebalanceableVehiclesZone1 = new ArrayList<>();
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a1", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a2", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a3", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a4", DvrpVehicle.class), link1));
+ rebalanceableVehicles.put(zone1, rebalanceableVehiclesZone1);
+
+ List relocations = strategy.calculateMinCostRelocations(0, rebalanceableVehicles, Collections.emptyMap());
+ Assertions.assertThat(relocations.size()).isEqualTo(1);
+ Assertions.assertThat(relocations.getFirst().link.getId()).isEqualTo(link2.getId());
+
+ rebalanceableVehicles.clear();
+
+ // 5 vehicles in zone 1 (surplus = 2)
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a1", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a2", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a3", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a4", DvrpVehicle.class), link1));
+ rebalanceableVehiclesZone1.add(getDvrpVehicle(Id.create("a5", DvrpVehicle.class), link1));
+ rebalanceableVehicles.put(zone1, rebalanceableVehiclesZone1);
+
+ //set alpha to 2 -> send two vehicles to zone 2
+ zone2.getAttributes().putAttribute(MinCostFlowRebalancingStrategy.REBALANCING_ZONAL_TARGET_ALPHA, 2.);
+ List relocations2 = strategy.calculateMinCostRelocations(0, rebalanceableVehicles, Collections.emptyMap());
+ Assertions.assertThat(relocations2.size()).isEqualTo(2);
+ Assertions.assertThat(relocations2.getFirst().link.getId()).isEqualTo(link2.getId());
+ Assertions.assertThat(relocations2.getLast().link.getId()).isEqualTo(link2.getId());
+ }
+
+ private DvrpVehicleImpl getDvrpVehicle(Id id, Link link) {
+ return new DvrpVehicleImpl(
+ ImmutableDvrpVehicleSpecification.newBuilder()
+ .id(id)
+ .capacity(0)
+ .serviceBeginTime(0)
+ .serviceEndTime(0)
+ .startLinkId(link.getId())
+ .build(), link);
+ }
+
+ private static Fleet createEmptyFleet() {
+ return () -> ImmutableMap., DvrpVehicle>builder().build();
+ }
+
+
+ private PreviousIterationDrtDemandEstimator createEstimator() {
+ RebalancingParams rebalancingParams = new RebalancingParams();
+ rebalancingParams.interval = ESTIMATION_PERIOD;
+
+ DrtConfigGroup drtConfigGroup = new DrtConfigGroup();
+ drtConfigGroup.addParameterSet(rebalancingParams);
+
+ return new PreviousIterationDrtDemandEstimator(zonalSystem, drtConfigGroup, ESTIMATION_PERIOD);
+ }
+
+ private PersonDepartureEvent departureEvent(double time, Link link, String mode) {
+ return new PersonDepartureEvent(time, null, link.getId(), mode, mode);
+ }
+
+ static Network createNetwork() {
+ Network network = NetworkUtils.createNetwork();
+ Node a = network.getFactory().createNode(Id.createNodeId("a"), new Coord(0,0));
+ Node b = network.getFactory().createNode(Id.createNodeId("b"), new Coord(500,0));
+ network.addNode(a);
+ network.addNode(b);
+
+ Link ab = network.getFactory().createLink(Id.createLinkId("link_1"), a, b);
+ Link ba = network.getFactory().createLink(Id.createLinkId("link_2"), b, a);
+ network.addLink(ab);
+ network.addLink(ba);
+ return network;
+ }
+}
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 4809a205c8a..22f9bef8d06 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,6 +4,11 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
+import org.matsim.api.core.v01.Coord;
+import org.matsim.api.core.v01.population.Activity;
+import org.matsim.api.core.v01.population.Leg;
+import org.matsim.api.core.v01.population.Person;
+import org.matsim.api.core.v01.population.Plan;
import org.matsim.contrib.drt.passenger.DrtRequest;
import org.matsim.contrib.drt.prebooking.PrebookingTestEnvironment.RequestInfo;
import org.matsim.contrib.drt.prebooking.logic.AttributeBasedPrebookingLogic;
@@ -13,6 +18,7 @@
import org.matsim.contrib.dvrp.fleet.DvrpVehicle;
import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule;
import org.matsim.core.controler.Controler;
+import org.matsim.core.population.PopulationUtils;
import org.matsim.testcases.MatsimTestUtils;
/**
@@ -67,7 +73,8 @@ static PrebookingParams installPrebooking(Controler controller, boolean installL
return installPrebooking(controller, installLogic, new PrebookingParams());
}
- static PrebookingParams installPrebooking(Controler controller, boolean installLogic, PrebookingParams prebookingParams) {
+ static PrebookingParams installPrebooking(Controler controller, boolean installLogic,
+ PrebookingParams prebookingParams) {
DrtConfigGroup drtConfig = DrtConfigGroup.getSingleModeDrtConfig(controller.getConfig());
drtConfig.addParameterSet(prebookingParams);
@@ -647,12 +654,12 @@ void intraStopTiming_pickupTooEarly() {
.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) //
+ .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() {
@@ -665,7 +672,7 @@ public double calcPickupDuration(DvrpVehicle vehicle, DrtRequest request) {
return 30.0; // shorter than the dropoff duration (see below)
}
}
-
+
@Override
public double calcDropoffDuration(DvrpVehicle vehicle, DrtRequest request) {
return 60.0;
@@ -673,7 +680,7 @@ public double calcDropoffDuration(DvrpVehicle vehicle, DrtRequest request) {
});
}
});
-
+
controller.run();
{
@@ -693,13 +700,14 @@ public double calcDropoffDuration(DvrpVehicle vehicle, DrtRequest request) {
{
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(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() {
/*-
@@ -715,12 +723,12 @@ void intraStopTiming_dropoffTooLate() {
.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) //
+ .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() {
@@ -729,7 +737,7 @@ public void install() {
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")) {
@@ -741,7 +749,7 @@ public double calcDropoffDuration(DvrpVehicle vehicle, DrtRequest request) {
});
}
});
-
+
controller.run();
{
@@ -755,9 +763,10 @@ public double calcDropoffDuration(DvrpVehicle vehicle, DrtRequest request) {
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
+ 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);
@@ -767,4 +776,62 @@ public double calcDropoffDuration(DvrpVehicle vehicle, DrtRequest request) {
assertEquals(3, environment.getTaskInfo().get("vehicleA").stream().filter(t -> t.type.equals("STOP")).count());
}
+
+ @Test
+ void abortAfterRejection_onActivity() {
+ PrebookingTestEnvironment environment = new PrebookingTestEnvironment(utils) //
+ .addVehicle("vehicleA", 1, 1) //
+ .setVehicleCapacity(1) //
+ .addRequest("requestA", 1, 1, 8, 8, 2000.0, 1800.0)
+ .configure(10.0, 1.0, 0.0, 5.0)
+ .endTime(12.0 * 3600.0);
+
+ Controler controller = environment.build();
+ installPrebooking(controller);
+
+ controller.run();
+
+ {
+ RequestInfo requestInfo = environment.getRequestInfo().get("requestA");
+ assertEquals(1800.0, requestInfo.submissionTime);
+ assertEquals(Double.NaN, requestInfo.pickupTime, 1e-3);
+ assertEquals(1, requestInfo.submissionTimes.size());
+ assertEquals(1, environment.getStuckInfo().size());
+ }
+ }
+
+ @Test
+ void abortAfterRejection_onLeg() {
+ PrebookingTestEnvironment environment = new PrebookingTestEnvironment(utils) //
+ .addVehicle("vehicleA", 1, 1) //
+ .setVehicleCapacity(1) //
+ .addRequest("requestA", 1, 1, 8, 8, 2000.0, 1800.0)
+ .configure(10.0, 1.0, 0.0, 5.0)
+ .endTime(12.0 * 3600.0);
+
+ Controler controller = environment.build();
+ installPrebooking(controller);
+
+ // make sure the agent will be on a leg
+ for (Person person : controller.getScenario().getPopulation().getPersons().values()) {
+ Plan plan = person.getSelectedPlan();
+
+ Activity activity = PopulationUtils.createActivityFromCoord("generic", new Coord(-50000.0, -50000.0));
+ activity.setEndTime(0.0);
+ Leg leg = PopulationUtils.createLeg("walk");
+
+ plan.getPlanElements().add(0, activity);
+ plan.getPlanElements().add(1, leg);
+ }
+
+ controller.run();
+
+ {
+ RequestInfo requestInfo = environment.getRequestInfo().get("requestA");
+ assertEquals(1800.0, requestInfo.submissionTime);
+ assertEquals(Double.NaN, requestInfo.pickupTime, 1e-3);
+ assertEquals(1, requestInfo.submissionTimes.size());
+ assertEquals(1, environment.getStuckInfo().size());
+ }
+ }
}
diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTestEnvironment.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTestEnvironment.java
index 60108070ab8..fcdb7ab7d7a 100644
--- a/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTestEnvironment.java
+++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTestEnvironment.java
@@ -1,14 +1,26 @@
package org.matsim.contrib.drt.prebooking;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
import org.apache.commons.lang3.tuple.Pair;
import org.matsim.api.core.v01.Coord;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
+import org.matsim.api.core.v01.events.PersonStuckEvent;
+import org.matsim.api.core.v01.events.handler.PersonStuckEventHandler;
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.api.core.v01.population.*;
+import org.matsim.api.core.v01.population.Activity;
+import org.matsim.api.core.v01.population.Leg;
+import org.matsim.api.core.v01.population.Person;
+import org.matsim.api.core.v01.population.Plan;
+import org.matsim.api.core.v01.population.Population;
+import org.matsim.api.core.v01.population.PopulationFactory;
import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystemParams;
import org.matsim.contrib.drt.optimizer.constraints.DefaultDrtOptimizationConstraintsSet;
import org.matsim.contrib.drt.optimizer.insertion.DrtInsertionSearchParams;
@@ -26,7 +38,12 @@
import org.matsim.contrib.dvrp.fleet.FleetSpecification;
import org.matsim.contrib.dvrp.fleet.FleetSpecificationImpl;
import org.matsim.contrib.dvrp.fleet.ImmutableDvrpVehicleSpecification;
-import org.matsim.contrib.dvrp.passenger.*;
+import org.matsim.contrib.dvrp.passenger.PassengerDroppedOffEvent;
+import org.matsim.contrib.dvrp.passenger.PassengerDroppedOffEventHandler;
+import org.matsim.contrib.dvrp.passenger.PassengerPickedUpEvent;
+import org.matsim.contrib.dvrp.passenger.PassengerPickedUpEventHandler;
+import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEvent;
+import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEventHandler;
import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule;
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
import org.matsim.contrib.dvrp.run.DvrpModule;
@@ -48,11 +65,6 @@
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.testcases.MatsimTestUtils;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
public class PrebookingTestEnvironment {
private final MatsimTestUtils utils;
@@ -164,6 +176,7 @@ public Controler build() {
configureRequestListener(controller);
configureVehicleListener(controller);
+ configureStuckListener(controller);
return controller;
}
@@ -227,9 +240,9 @@ private void buildConfig(Config config) {
DrtConfigGroup modeConfig = new DrtConfigGroup();
drtConfig.addParameterSet(modeConfig);
modeConfig.mode = "drt";
- DefaultDrtOptimizationConstraintsSet defaultConstraintsSet =
- (DefaultDrtOptimizationConstraintsSet) modeConfig.addOrGetDrtOptimizationConstraintsParams()
- .addOrGetDefaultDrtOptimizationConstraintsSet();
+ DefaultDrtOptimizationConstraintsSet defaultConstraintsSet = (DefaultDrtOptimizationConstraintsSet) modeConfig
+ .addOrGetDrtOptimizationConstraintsParams()
+ .addOrGetDefaultDrtOptimizationConstraintsSet();
defaultConstraintsSet.maxWaitTime = maximumWaitTime;
defaultConstraintsSet.maxTravelTimeAlpha = detourRelative;
defaultConstraintsSet.maxTravelTimeBeta = detourAbsolute;
@@ -270,13 +283,13 @@ private void buildPopulation(Scenario scenario) {
plan.addLeg(firstLeg);
if (!Double.isNaN(request.submissionTime)) {
- firstActivity.getAttributes().putAttribute(AttributeBasedPrebookingLogic.getSubmissionAttribute("drt"),
+ firstActivity.getAttributes().putAttribute(AttributeBasedPrebookingLogic.getSubmissionTimeAttribute("drt"),
request.submissionTime);
}
if (!Double.isNaN(request.plannedDepartureTime)) {
firstActivity.getAttributes().putAttribute(
- AttributeBasedPrebookingLogic.getPlannedDepartureAttribute("drt"),
+ AttributeBasedPrebookingLogic.getPlannedDepartureTimeAttribute("drt"),
request.plannedDepartureTime);
}
@@ -444,4 +457,26 @@ public void handleEvent(TaskEndedEvent event) {
taskInfo.get(event.getDvrpVehicleId().toString()).getLast().endTime = event.getTime();
}
}
+
+ private final List stuckEvents = new LinkedList<>();
+
+ public List getStuckInfo() {
+ return stuckEvents;
+ }
+
+ private void configureStuckListener(Controler controller) {
+ controller.addOverridingModule(new AbstractModule() {
+ @Override
+ public void install() {
+ addEventHandlerBinding().toInstance(new StuckListener());
+ }
+ });
+ }
+
+ private class StuckListener implements PersonStuckEventHandler {
+ @Override
+ public void handleEvent(PersonStuckEvent event) {
+ stuckEvents.add(event);
+ }
+ }
}
diff --git a/contribs/dvrp/pom.xml b/contribs/dvrp/pom.xml
index 716fab806f2..e6fc424004c 100644
--- a/contribs/dvrp/pom.xml
+++ b/contribs/dvrp/pom.xml
@@ -24,17 +24,17 @@
org.matsim.contribotfvis
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribcommon
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribev
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.apache.commons
diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpModeRoutingNetworkModule.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpModeRoutingNetworkModule.java
index 076ce4876ec..3b8463a1119 100644
--- a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpModeRoutingNetworkModule.java
+++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpModeRoutingNetworkModule.java
@@ -20,6 +20,7 @@
package org.matsim.contrib.dvrp.router;
+import java.io.File;
import java.util.Collections;
import java.util.Set;
@@ -32,6 +33,7 @@
import org.matsim.contrib.zone.skims.FreeSpeedTravelTimeMatrix;
import org.matsim.contrib.zone.skims.TravelTimeMatrix;
import org.matsim.core.config.Config;
+import org.matsim.core.config.ConfigGroup;
import org.matsim.core.config.groups.GlobalConfigGroup;
import org.matsim.core.config.groups.QSimConfigGroup;
import org.matsim.core.network.NetworkUtils;
@@ -86,9 +88,16 @@ public void install() {
DvrpTravelTimeMatrixParams matrixParams = dvrpConfigGroup.getTravelTimeMatrixParams();
ZoneSystem zoneSystem = ZoneSystemUtils.createZoneSystem(getConfig().getContext(), network,
matrixParams.getZoneSystemParams(), getConfig().global().getCoordinateSystem(), zone -> true);
- return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrix(network, zoneSystem,
- matrixParams, globalConfigGroup.getNumberOfThreads(),
- qSimConfigGroup.getTimeStepSize());
+
+
+ if (matrixParams.cachePath == null) {
+ return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrix(network, zoneSystem, matrixParams, globalConfigGroup.getNumberOfThreads(),
+ qSimConfigGroup.getTimeStepSize());
+ } else {
+ File cachePath = new File(ConfigGroup.getInputFileURL(getConfig().getContext(), matrixParams.cachePath).getPath());
+ return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrixFromCache(network, zoneSystem, matrixParams, globalConfigGroup.getNumberOfThreads(),
+ qSimConfigGroup.getTimeStepSize(), cachePath);
+ }
})).in(Singleton.class);
} else {
//use DVRP-routing (dvrp-global) network
diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/run/DvrpModule.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/run/DvrpModule.java
index d31fe11499d..769ea423515 100644
--- a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/run/DvrpModule.java
+++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/run/DvrpModule.java
@@ -19,7 +19,7 @@
package org.matsim.contrib.dvrp.run;
-import jakarta.inject.Provider;
+import java.io.File;
import org.matsim.api.core.v01.network.Network;
import org.matsim.contrib.common.zones.ZoneSystem;
@@ -33,6 +33,7 @@
import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams;
import org.matsim.contrib.zone.skims.FreeSpeedTravelTimeMatrix;
import org.matsim.contrib.zone.skims.TravelTimeMatrix;
+import org.matsim.core.config.ConfigGroup;
import org.matsim.core.config.groups.QSimConfigGroup;
import org.matsim.core.controler.AbstractModule;
import org.matsim.core.mobsim.framework.MobsimTimer;
@@ -44,6 +45,8 @@
import com.google.inject.name.Named;
import com.google.inject.name.Names;
+import jakarta.inject.Provider;
+
/**
* This module initialises generic (i.e. not taxi or drt-specific) AND global (not mode-specific) dvrp objects.
*
@@ -90,8 +93,15 @@ public TravelTimeMatrix get() {
DvrpTravelTimeMatrixParams matrixParams = dvrpConfigGroup.getTravelTimeMatrixParams();
ZoneSystem zoneSystem = ZoneSystemUtils.createZoneSystem(getConfig().getContext(), network,
matrixParams.getZoneSystemParams(), getConfig().global().getCoordinateSystem(), zone -> true);
- return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrix(network, zoneSystem, params, numberOfThreads,
+
+ if (params.cachePath == null) {
+ return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrix(network, zoneSystem, params, numberOfThreads,
qSimConfigGroup.getTimeStepSize());
+ } else {
+ File cachePath = new File(ConfigGroup.getInputFileURL(getConfig().getContext(), params.cachePath).getPath());
+ return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrixFromCache(network, zoneSystem, params, numberOfThreads,
+ qSimConfigGroup.getTimeStepSize(), cachePath);
+ }
}
}).in(Singleton.class);
diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dynagent/DynAgent.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dynagent/DynAgent.java
index 8915326d992..d7c15d7552f 100644
--- a/contribs/dvrp/src/main/java/org/matsim/contrib/dynagent/DynAgent.java
+++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dynagent/DynAgent.java
@@ -19,8 +19,6 @@
package org.matsim.contrib.dynagent;
-import java.util.List;
-
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.ActivityEndEvent;
import org.matsim.api.core.v01.events.ActivityStartEvent;
@@ -40,6 +38,8 @@
import org.matsim.pt.transitSchedule.api.TransitStopFacility;
import org.matsim.vehicles.Vehicle;
+import java.util.List;
+
public final class DynAgent implements MobsimDriverPassengerAgent {
private final DynAgentLogic agentLogic;
@@ -83,11 +83,11 @@ private void computeNextAction(DynAction oldDynAction, double now) {
DynAction nextDynAction = agentLogic.computeNextAction(oldDynAction, now);
if (nextDynAction instanceof DynActivity) {
- dynActivity = (DynActivity)nextDynAction;
+ dynActivity = (DynActivity) nextDynAction;
state = MobsimAgent.State.ACTIVITY;
events.processEvent(new ActivityStartEvent(now, id, currentLinkId, null, dynActivity.getActivityType()));
} else {
- dynLeg = (DynLeg)nextDynAction;
+ dynLeg = (DynLeg) nextDynAction;
state = MobsimAgent.State.LEG;
}
}
@@ -145,7 +145,7 @@ public String getMode() {
// VehicleUsingAgent
@Override
public final Id getPlannedVehicleId() {
- Id vehId = ((DriverDynLeg)dynLeg).getPlannedVehicleId();
+ Id vehId = ((DriverDynLeg) dynLeg).getPlannedVehicleId();
// according to BasicPlanAgentImpl
return vehId != null ? vehId : Id.create(id, Vehicle.class);
}
@@ -177,13 +177,13 @@ public Id getDestinationLinkId() {
// DriverAgent
@Override
public Id chooseNextLinkId() {
- return ((DriverDynLeg)dynLeg).getNextLinkId();
+ return ((DriverDynLeg) dynLeg).getNextLinkId();
}
// DriverAgent
@Override
public void notifyMoveOverNode(Id newLinkId) {
- ((DriverDynLeg)dynLeg).movedOverNode(newLinkId);
+ ((DriverDynLeg) dynLeg).movedOverNode(newLinkId);
currentLinkId = newLinkId;
}
@@ -226,26 +226,28 @@ public boolean isWantingToArriveOnCurrentLink() {
// PTPassengerAgent
@Override
public boolean getEnterTransitRoute(TransitLine line, TransitRoute transitRoute, List stopsToCome,
- TransitVehicle transitVehicle) {
- return ((PTPassengerDynLeg)dynLeg).getEnterTransitRoute(line, transitRoute, stopsToCome, transitVehicle);
+ TransitVehicle transitVehicle) {
+ return ((PTPassengerDynLeg) dynLeg).getEnterTransitRoute(line, transitRoute, stopsToCome, transitVehicle);
}
// PTPassengerAgent
+ // yyyy seems a bit odd, that this and the following methods are implemented for DynAgent as not every DynAgent is a PTPassengerAgent. paul,
+ // nov'24
@Override
public boolean getExitAtStop(TransitStopFacility stop) {
- return ((PTPassengerDynLeg)dynLeg).getExitAtStop(stop);
+ return ((PTPassengerDynLeg) dynLeg).getExitAtStop(stop);
}
// PTPassengerAgent
@Override
public Id getDesiredAccessStopId() {
- return ((PTPassengerDynLeg)dynLeg).getDesiredAccessStopId();
+ return ((PTPassengerDynLeg) dynLeg).getDesiredAccessStopId();
}
// PTPassengerAgent
@Override
public Id getDesiredDestinationStopId() {
- return ((PTPassengerDynLeg)dynLeg).getDesiredDestinationStopId();
+ return ((PTPassengerDynLeg) dynLeg).getDesiredDestinationStopId();
}
// PTPassengerAgent
diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingActivity.java b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingActivity.java
index 05217bf940e..8c1cb0adee3 100644
--- a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingActivity.java
+++ b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingActivity.java
@@ -21,6 +21,7 @@
package org.matsim.contrib.evrp;
import org.matsim.contrib.dynagent.DynActivity;
+import org.matsim.contrib.ev.charging.ChargingStrategy;
import org.matsim.contrib.ev.charging.ChargingWithAssignmentLogic;
import org.matsim.contrib.ev.fleet.ElectricVehicle;
@@ -64,7 +65,7 @@ private void initialize(double now) {
ChargingWithAssignmentLogic logic = chargingTask.getChargingLogic();
ElectricVehicle ev = chargingTask.getElectricVehicle();
logic.unassignVehicle(ev);
- logic.addVehicle(ev, new DvrpChargingListener(this), now);
+ logic.addVehicle(ev, chargingTask.getChargingStrategy(), new DvrpChargingListener(this), now);
state = State.added;
}
diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTask.java b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTask.java
index 21ad8303ae5..7326e1bedd9 100644
--- a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTask.java
+++ b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTask.java
@@ -20,6 +20,7 @@
package org.matsim.contrib.evrp;
+import org.matsim.contrib.ev.charging.ChargingStrategy;
import org.matsim.contrib.ev.charging.ChargingWithAssignmentLogic;
import org.matsim.contrib.ev.fleet.ElectricVehicle;
@@ -29,6 +30,8 @@
public interface ChargingTask extends ETask {
ChargingWithAssignmentLogic getChargingLogic();
+ ChargingStrategy getChargingStrategy();
+
ElectricVehicle getElectricVehicle();
double getChargingStartedTime();
diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTaskImpl.java b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTaskImpl.java
index 969fa50da00..8cbd525cbea 100644
--- a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTaskImpl.java
+++ b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTaskImpl.java
@@ -24,6 +24,7 @@
import com.google.common.base.Preconditions;
import org.matsim.contrib.dvrp.schedule.DefaultStayTask;
+import org.matsim.contrib.ev.charging.ChargingStrategy;
import org.matsim.contrib.ev.charging.ChargingWithAssignmentLogic;
import org.matsim.contrib.ev.fleet.ElectricVehicle;
import org.matsim.contrib.ev.infrastructure.Charger;
@@ -33,18 +34,20 @@
*/
public class ChargingTaskImpl extends DefaultStayTask implements ChargingTask {
private final ChargingWithAssignmentLogic chargingLogic;
+ private final ChargingStrategy chargingStrategy;
private final ElectricVehicle ev;
private Double chargingStartedTime;
private final double totalEnergy;
public ChargingTaskImpl(TaskType taskType, double beginTime, double endTime, Charger charger, ElectricVehicle ev,
- double totalEnergy) {
+ double totalEnergy, ChargingStrategy chargingStrategy) {
super(taskType, beginTime, endTime, charger.getLink());
Preconditions.checkArgument(totalEnergy < 0, "Total energy consumption is not negative: %s", totalEnergy);
this.chargingLogic = (ChargingWithAssignmentLogic)charger.getLogic();
this.ev = ev;
this.totalEnergy = totalEnergy;
+ this.chargingStrategy = chargingStrategy;
}
@Override
@@ -57,6 +60,11 @@ public ChargingWithAssignmentLogic getChargingLogic() {
return chargingLogic;
}
+ @Override
+ public ChargingStrategy getChargingStrategy() {
+ return chargingStrategy;
+ }
+
@Override
public ElectricVehicle getElectricVehicle() {
return ev;
@@ -76,6 +84,7 @@ public double getChargingStartedTime() {
public String toString() {
return MoreObjects.toStringHelper(this)
.add("chargingLogic", chargingLogic)
+ .add("chargingStrategy", chargingStrategy)
.add("ev", ev)
.add("chargingStartedTime", chargingStartedTime)
.add("totalEnergy", totalEnergy)
diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java
index 52c3c332f09..9b959a87ba2 100644
--- a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java
+++ b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java
@@ -28,6 +28,7 @@
import org.matsim.contrib.common.zones.systems.grid.GISFileZoneSystemParams;
import org.matsim.contrib.common.zones.systems.grid.h3.H3GridZoneSystemParams;
import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystemParams;
+import org.matsim.core.config.ReflectiveConfigGroup.Parameter;
/**
* @author Michal Maciejewski (michalm)
@@ -59,6 +60,9 @@ public class DvrpTravelTimeMatrixParams extends ReflectiveConfigGroupWithConfigu
@NotNull
private ZoneSystemParams zoneSystemParams;
+ @Parameter
+ @Comment("Caches the travel time matrix data into a binary file. If the file exists, the matrix will be read from the file, if not, the file will be created.")
+ public String cachePath = null;
public DvrpTravelTimeMatrixParams() {
super(SET_NAME);
diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrix.java b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrix.java
index 6351dd3bce8..356625f4295 100644
--- a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrix.java
+++ b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrix.java
@@ -20,14 +20,34 @@
package org.matsim.contrib.zone.skims;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+
+import org.matsim.api.core.v01.Id;
+import org.matsim.api.core.v01.IdSet;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.network.Node;
+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.dvrp.router.TimeAsTravelDisutility;
import org.matsim.contrib.dvrp.trafficmonitoring.QSimFreeSpeedTravelTime;
+import org.matsim.contrib.zone.skims.SparseMatrix.NodeAndTime;
+import org.matsim.contrib.zone.skims.SparseMatrix.SparseRow;
import org.matsim.core.router.util.TravelTime;
+import com.google.common.base.Verify;
+import com.google.common.collect.Sets;
+
/**
* @author Michal Maciejewski (michalm)
*/
@@ -68,4 +88,151 @@ public int getTravelTime(Node fromNode, Node toNode, double departureTime) {
public int getZonalTravelTime(Node fromNode, Node toNode, double departureTime) {
return freeSpeedTravelTimeMatrix.get(zoneSystem.getZoneForNodeId(fromNode.getId()).orElseThrow(), zoneSystem.getZoneForNodeId(toNode.getId()).orElseThrow());
}
+
+ public static FreeSpeedTravelTimeMatrix createFreeSpeedMatrixFromCache(Network dvrpNetwork, ZoneSystem zoneSystem, DvrpTravelTimeMatrixParams params, int numberOfThreads, double qSimTimeStepSize, File cachePath) {
+ boolean exists = cachePath.exists();
+
+ final FreeSpeedTravelTimeMatrix matrix;
+ if (exists) {
+ matrix = new FreeSpeedTravelTimeMatrix(dvrpNetwork, zoneSystem, cachePath);
+ } else {
+ matrix = createFreeSpeedMatrix(dvrpNetwork, zoneSystem, params, numberOfThreads, qSimTimeStepSize);
+ matrix.write(cachePath, dvrpNetwork);
+ }
+
+ return matrix;
+ }
+
+ public FreeSpeedTravelTimeMatrix(Network dvrpNetwork, ZoneSystem zoneSystem, File cachePath) {
+ this.zoneSystem = zoneSystem;
+
+ try (DataInputStream inputStream = new DataInputStream(new FileInputStream(cachePath))) {
+ // number of zones
+ int numberOfZones = inputStream.readInt();
+ Verify.verify(numberOfZones == zoneSystem.getZones().size());
+
+ // read zone list
+ List> zoneIds = new ArrayList<>(numberOfZones);
+ for (int i = 0; i < numberOfZones; i++) {
+ zoneIds.add(Id.create(inputStream.readUTF(), Zone.class));
+ }
+
+ IdSet systemZones = new IdSet<>(Zone.class);
+ systemZones.addAll(zoneSystem.getZones().keySet());
+
+ IdSet dataZones = new IdSet<>(Zone.class);
+ dataZones.addAll(zoneIds);
+
+ Verify.verify(Sets.difference(systemZones, dataZones).size() == 0);
+ Verify.verify(Sets.difference(dataZones, systemZones).size() == 0);
+
+ // fill matrix
+ freeSpeedTravelTimeMatrix = new Matrix(new HashSet<>(zoneSystem.getZones().values()));
+
+ for (var from : zoneIds) {
+ for (var to : zoneIds) {
+ Zone fromZone = zoneSystem.getZones().get(from);
+ Zone toZone = zoneSystem.getZones().get(to);
+ freeSpeedTravelTimeMatrix.set(fromZone, toZone, inputStream.readInt());
+ }
+ }
+
+ // sparse matrix available?
+ boolean hasSparseMatrix = inputStream.readBoolean();
+
+ if (!hasSparseMatrix) {
+ freeSpeedTravelTimeSparseMatrix = null;
+ } else {
+ freeSpeedTravelTimeSparseMatrix = new SparseMatrix();
+
+ // read nodes
+ int numberOfNodes = inputStream.readInt();
+ Verify.verify(numberOfNodes == dvrpNetwork.getNodes().size());
+
+ List nodes = new ArrayList<>(numberOfNodes);
+ for (int i = 0; i < numberOfNodes; i++) {
+ Id nodeId = Id.createNodeId(inputStream.readUTF());
+ nodes.add(Objects.requireNonNull(dvrpNetwork.getNodes().get(nodeId)));
+ }
+
+ // read rows
+ for (int i = 0; i < numberOfNodes; i++) {
+ Node from = nodes.get(i);
+ int numberOfElements = inputStream.readInt();
+
+ if (numberOfElements > 0) {
+ List nodeTimeList = new ArrayList<>(numberOfElements);
+
+ for (int j = 0; j < numberOfElements; j++) {
+ Node to = nodes.get(inputStream.readInt());
+ int value = inputStream.readInt();
+
+ nodeTimeList.add(new NodeAndTime(to.getId().index(), value));
+ }
+
+ SparseRow row = new SparseRow(nodeTimeList);
+ freeSpeedTravelTimeSparseMatrix.setRow(from, row);
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ public void write(File outputPath, Network dvrpNetwork) {
+ try (DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(outputPath))) {
+ // obtain fixed order of zones
+ List zones = new ArrayList<>(zoneSystem.getZones().values());
+ outputStream.writeInt(zones.size());
+ for (Zone zone : zones) {
+ outputStream.writeUTF(zone.getId().toString());
+ }
+
+ // write matrix
+ for (var from : zones) {
+ for (var to : zones) {
+ int value = freeSpeedTravelTimeMatrix.get(from, to);
+ outputStream.writeInt(value);
+ }
+ }
+
+ // write if sparse exists
+ outputStream.writeBoolean(freeSpeedTravelTimeSparseMatrix != null);
+
+ if (freeSpeedTravelTimeSparseMatrix != null) {
+ // obtain fixed order of nodes
+ List nodes = new ArrayList<>(dvrpNetwork.getNodes().values());
+ outputStream.writeInt(nodes.size());
+ for (Node node : nodes) {
+ outputStream.writeUTF(node.getId().toString());
+ }
+
+ for (Node from : nodes) {
+ // write size of the matrix row
+ int rowSize = 0;
+
+ for (Node to : nodes) {
+ int value = freeSpeedTravelTimeSparseMatrix.get(from, to);
+ if (value >= 0) {
+ rowSize++;
+ }
+ }
+
+ outputStream.writeInt(rowSize);
+
+ // write matrix row
+ for (Node to : nodes) {
+ int value = freeSpeedTravelTimeSparseMatrix.get(from, to);
+ if (value >= 0) {
+ outputStream.writeInt(nodes.indexOf(to));
+ outputStream.writeInt(value);
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
}
diff --git a/contribs/dvrp/src/test/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrixTest.java b/contribs/dvrp/src/test/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrixTest.java
index 8aaf6001258..2cf4cc30934 100644
--- a/contribs/dvrp/src/test/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrixTest.java
+++ b/contribs/dvrp/src/test/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrixTest.java
@@ -22,7 +22,10 @@
import static org.assertj.core.api.Assertions.assertThat;
+import java.io.File;
+
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
import org.matsim.api.core.v01.Coord;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Network;
@@ -30,12 +33,16 @@
import org.matsim.contrib.common.zones.ZoneSystem;
import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystem;
import org.matsim.core.network.NetworkUtils;
+import org.matsim.testcases.MatsimTestUtils;
/**
* @author Michal Maciejewski (michalm)
*/
public class FreeSpeedTravelTimeMatrixTest {
+ @RegisterExtension
+ MatsimTestUtils utils = new MatsimTestUtils();
+
private final Network network = NetworkUtils.createNetwork();
private final Node nodeA = NetworkUtils.createAndAddNode(network, Id.createNodeId("A"), new Coord(0, 0));
private final Node nodeB = NetworkUtils.createAndAddNode(network, Id.createNodeId("B"), new Coord(150, 150));
@@ -66,6 +73,23 @@ void matrix() {
assertThat(matrix.getTravelTime(nodeC, nodeA, 0)).isEqualTo(0);
assertThat(matrix.getTravelTime(nodeB, nodeC, 0)).isEqualTo(20 + 1); // 1 s for moving over nodes
assertThat(matrix.getTravelTime(nodeC, nodeB, 0)).isEqualTo(10 + 1); // 1 s for moving over nodes
+
+ // write and read cache
+ File cachePath = new File(utils.getOutputDirectory(), "cache.bin");
+ matrix.write(cachePath, network);
+ matrix = FreeSpeedTravelTimeMatrix.createFreeSpeedMatrixFromCache(network, zoneSystem, null, 1, 1, cachePath);
+
+ // distances between central nodes: A and B
+ assertThat(matrix.getTravelTime(nodeA, nodeA, 0)).isEqualTo(0);
+ assertThat(matrix.getTravelTime(nodeA, nodeB, 0)).isEqualTo(10 + 1); // 1 s for moving over nodes
+ assertThat(matrix.getTravelTime(nodeB, nodeA, 0)).isEqualTo(20 + 1); // 1 s for moving over nodes
+ assertThat(matrix.getTravelTime(nodeB, nodeB, 0)).isEqualTo(0);
+
+ // non-central node: C and A are in the same zone; A is the central node
+ assertThat(matrix.getTravelTime(nodeA, nodeC, 0)).isEqualTo(0);
+ assertThat(matrix.getTravelTime(nodeC, nodeA, 0)).isEqualTo(0);
+ assertThat(matrix.getTravelTime(nodeB, nodeC, 0)).isEqualTo(20 + 1); // 1 s for moving over nodes
+ assertThat(matrix.getTravelTime(nodeC, nodeB, 0)).isEqualTo(10 + 1); // 1 s for moving over nodes
}
@Test
@@ -87,5 +111,22 @@ void sparseMatrix() {
assertThat(matrix.getTravelTime(nodeC, nodeA, 0)).isEqualTo(9 + 1); // 1 s for moving over nodes
assertThat(matrix.getTravelTime(nodeB, nodeC, 0)).isEqualTo(20 + 11 + 2); // 2 s for moving over nodes
assertThat(matrix.getTravelTime(nodeC, nodeB, 0)).isEqualTo(10 + 9 + 2); // 2 s for moving over nodes
+
+ // write and read cache
+ File cachePath = new File(utils.getOutputDirectory(), "cache.bin");
+ matrix.write(cachePath, network);
+ matrix = FreeSpeedTravelTimeMatrix.createFreeSpeedMatrixFromCache(network, zoneSystem, null, 1, 1, cachePath);
+
+ // distances between central nodes: A and B
+ assertThat(matrix.getTravelTime(nodeA, nodeA, 0)).isEqualTo(0);
+ assertThat(matrix.getTravelTime(nodeA, nodeB, 0)).isEqualTo(10 + 1); // 1 s for moving over nodes
+ assertThat(matrix.getTravelTime(nodeB, nodeA, 0)).isEqualTo(20 + 1); // 1 s for moving over nodes
+ assertThat(matrix.getTravelTime(nodeB, nodeB, 0)).isEqualTo(0);
+
+ // non-central node: C and A are in the same zone; A is the central node
+ assertThat(matrix.getTravelTime(nodeA, nodeC, 0)).isEqualTo(11 + 1); // 1 s for moving over nodes
+ assertThat(matrix.getTravelTime(nodeC, nodeA, 0)).isEqualTo(9 + 1); // 1 s for moving over nodes
+ assertThat(matrix.getTravelTime(nodeB, nodeC, 0)).isEqualTo(20 + 11 + 2); // 2 s for moving over nodes
+ assertThat(matrix.getTravelTime(nodeC, nodeB, 0)).isEqualTo(10 + 9 + 2); // 2 s for moving over nodes
}
}
diff --git a/contribs/emissions/pom.xml b/contribs/emissions/pom.xml
index 16d87bc8cdb..98daccca22b 100644
--- a/contribs/emissions/pom.xml
+++ b/contribs/emissions/pom.xml
@@ -58,7 +58,7 @@
org.matsim.contribanalysis
- 2025.0-SNAPSHOT
+ ${project.parent.version}com.fasterxml.jackson.core
diff --git a/contribs/ev/pom.xml b/contribs/ev/pom.xml
index e1c5144d706..120d63dfbe3 100644
--- a/contribs/ev/pom.xml
+++ b/contribs/ev/pom.xml
@@ -14,7 +14,7 @@
org.matsim.contribcommon
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.apache.commons
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargeUpToMaxSocStrategy.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargeUpToMaxSocStrategy.java
index 85760aabefc..3703a7b0794 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargeUpToMaxSocStrategy.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargeUpToMaxSocStrategy.java
@@ -23,30 +23,65 @@
import org.matsim.contrib.ev.fleet.Battery;
import org.matsim.contrib.ev.fleet.ElectricVehicle;
import org.matsim.contrib.ev.infrastructure.ChargerSpecification;
+import org.matsim.vehicles.Vehicle;
/**
* @author Michal Maciejewski (michalm)
+ * @author Sebastian Hörl (sebhoerl), IRT SystemX
*/
public class ChargeUpToMaxSocStrategy implements ChargingStrategy {
+ static public final String MAXIMUM_SOC_VEHICLE_ATTRIBUTE = "maximumSoc";
+
+ private final ElectricVehicle ev;
private final ChargerSpecification charger;
private final double maxSoc;
- public ChargeUpToMaxSocStrategy(ChargerSpecification charger, double maxSoc) {
+ public ChargeUpToMaxSocStrategy(ChargerSpecification charger, ElectricVehicle ev, double maxSoc) {
if (maxSoc < 0 || maxSoc > 1) {
throw new IllegalArgumentException();
}
this.charger = charger;
this.maxSoc = maxSoc;
+ this.ev = ev;
}
@Override
- public double calcRemainingEnergyToCharge(ElectricVehicle ev) {
+ public double calcRemainingEnergyToCharge() {
Battery battery = ev.getBattery();
return maxSoc * battery.getCapacity() - battery.getCharge();
}
@Override
- public double calcRemainingTimeToCharge(ElectricVehicle ev) {
- return ((BatteryCharging)ev.getChargingPower()).calcChargingTime(charger, calcRemainingEnergyToCharge(ev));
+ public double calcRemainingTimeToCharge() {
+ return ((BatteryCharging)ev.getChargingPower()).calcChargingTime(charger, calcRemainingEnergyToCharge());
+ }
+
+ @Override
+ public boolean isChargingCompleted() {
+ return calcRemainingEnergyToCharge() <= 0;
+ }
+
+ static public class Factory implements ChargingStrategy.Factory {
+ private final double maxSoc;
+
+ public Factory(double maxSoc) {
+ this.maxSoc = maxSoc;
+ }
+
+ @Override
+ public ChargingStrategy createStrategy(ChargerSpecification charger, ElectricVehicle ev) {
+ double vehicleMaximumSoc = maxSoc;
+
+ Vehicle vehicle = ev.getVehicleSpecification().getMatsimVehicle();
+ if (vehicle != null) {
+ Double value = (Double) vehicle.getAttributes().getAttribute(MAXIMUM_SOC_VEHICLE_ATTRIBUTE);
+
+ if (value != null) {
+ vehicleMaximumSoc = value;
+ }
+ }
+
+ return new ChargeUpToMaxSocStrategy(charger, ev, vehicleMaximumSoc);
+ }
}
}
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEstimations.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEstimations.java
index 5c0499f3bbf..502573d8bb2 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEstimations.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEstimations.java
@@ -20,7 +20,7 @@
import java.util.stream.Stream;
-import org.matsim.contrib.ev.fleet.ElectricVehicle;
+import org.matsim.contrib.ev.charging.ChargingLogic.ChargingVehicle;
import org.matsim.contrib.ev.infrastructure.Charger;
/**
@@ -38,20 +38,18 @@ public static double estimateMaxWaitTimeForNextVehicle(Charger charger) {
}
public static double estimateTotalTimeToCharge(ChargingLogic logic) {
- return estimateTotalTimeToCharge(logic.getChargingStrategy(),
- Stream.concat(logic.getPluggedVehicles().stream(), logic.getQueuedVehicles().stream()));
+ return estimateTotalTimeToCharge(Stream.concat(logic.getPluggedVehicles().stream(), logic.getQueuedVehicles().stream()));
}
public static double estimateTotalEnergyToCharge(ChargingLogic logic) {
- return estimateTotalEnergyToCharge(logic.getChargingStrategy(),
- Stream.concat(logic.getPluggedVehicles().stream(), logic.getQueuedVehicles().stream()));
+ return estimateTotalEnergyToCharge(Stream.concat(logic.getPluggedVehicles().stream(), logic.getQueuedVehicles().stream()));
}
- public static double estimateTotalTimeToCharge(ChargingStrategy strategy, Stream vehicles) {
- return vehicles.mapToDouble(strategy::calcRemainingTimeToCharge).sum();
+ public static double estimateTotalTimeToCharge(Stream vehicles) {
+ return vehicles.map(ChargingVehicle::strategy).mapToDouble(ChargingStrategy::calcRemainingTimeToCharge).sum();
}
- public static double estimateTotalEnergyToCharge(ChargingStrategy strategy, Stream vehicles) {
- return vehicles.mapToDouble(strategy::calcRemainingEnergyToCharge).sum();
+ public static double estimateTotalEnergyToCharge(Stream vehicles) {
+ return vehicles.map(ChargingVehicle::strategy).mapToDouble(ChargingStrategy::calcRemainingEnergyToCharge).sum();
}
}
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingLogic.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingLogic.java
index 854947741e0..de274606326 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingLogic.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingLogic.java
@@ -29,17 +29,17 @@ interface Factory {
ChargingLogic create(ChargerSpecification charger);
}
- void addVehicle(ElectricVehicle ev, double now);
+ void addVehicle(ElectricVehicle ev, ChargingStrategy strategy, double now);
- void addVehicle(ElectricVehicle ev, ChargingListener chargingListener, double now);
+ void addVehicle(ElectricVehicle ev, ChargingStrategy strategy, ChargingListener chargingListener, double now);
void removeVehicle(ElectricVehicle ev, double now);
void chargeVehicles(double chargePeriod, double now);
- Collection getPluggedVehicles();
+ Collection getPluggedVehicles();
- Collection getQueuedVehicles();
+ Collection getQueuedVehicles();
- ChargingStrategy getChargingStrategy();
+ record ChargingVehicle(ElectricVehicle ev, ChargingStrategy strategy) {}
}
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingModule.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingModule.java
index 7b42877507d..1f81bac495c 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingModule.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingModule.java
@@ -20,14 +20,13 @@
package org.matsim.contrib.ev.charging;
-import com.google.inject.Singleton;
import org.matsim.contrib.ev.EvModule;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.controler.AbstractModule;
import org.matsim.core.mobsim.qsim.AbstractQSimModule;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
/**
* @author Michal Maciejewski (michalm)
@@ -35,13 +34,11 @@
public class ChargingModule extends AbstractModule {
@Override
public void install() {
- // The following returns a charging logic for a given charger specification. Needs to be a provider, since the eventsManager needs to be inserted.
- bind(ChargingLogic.Factory.class).toProvider(new Provider<>() {
- @Inject private EventsManager eventsManager;
- @Override public ChargingLogic.Factory get() {
- return charger -> new ChargingWithQueueingLogic(charger, new ChargeUpToMaxSocStrategy(charger, 1.), eventsManager);
- }
- });
+ // By default, charging logic with queue is used
+ bind(ChargingLogic.Factory.class).to(ChargingWithQueueingLogic.Factory.class);
+
+ // By default, charging strategy that chargers to 100% is used
+ bind(ChargingStrategy.Factory.class).toInstance(new ChargeUpToMaxSocStrategy.Factory(1.0));
// The following returns the charging power/speed for a vehicle:
bind(ChargingPower.Factory.class).toInstance(ev -> new FixedSpeedCharging(ev, 1));
@@ -57,5 +54,18 @@ public void install() {
// this.addMobsimListenerBinding().to( ChargingHandler.class ).in( Singleton.class );
// does not work since ChargingInfrastructure is not available.
+
+ // standard charging priority for all chargers
+ bind(ChargingPriority.Factory.class).toInstance(ChargingPriority.FIFO);
+ }
+
+ @Provides @Singleton
+ ChargingWithQueueingLogic.Factory provideChargingWithQueueingLogicFactory(EventsManager eventsManager, ChargingPriority.Factory chargingPriorityFactory) {
+ return new ChargingWithQueueingLogic.Factory(eventsManager, chargingPriorityFactory);
+ }
+
+ @Provides @Singleton
+ ChargingWithQueueingAndAssignmentLogic.Factory provideChargingWithQueueingAndAssignmentLogicFactory(EventsManager eventsManager, ChargingPriority.Factory chargingPriorityFactory) {
+ return new ChargingWithQueueingAndAssignmentLogic.Factory(eventsManager, chargingPriorityFactory);
}
}
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingPriority.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingPriority.java
new file mode 100644
index 00000000000..83087a37f79
--- /dev/null
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingPriority.java
@@ -0,0 +1,29 @@
+package org.matsim.contrib.ev.charging;
+
+import org.matsim.contrib.ev.charging.ChargingLogic.ChargingVehicle;
+import org.matsim.contrib.ev.infrastructure.ChargerSpecification;
+
+/**
+ * This interface is supposed to decide if a vehicle can be plugged right now or
+ * if it needs to go to / remain in the queue. While the condition whether
+ * enough of empty plugs are available is *always* checked, the presented method
+ * allows to define a more complex logic beyond that.
+ *
+ * @author Sebastian Hörl (sebhoerl), IRT SystemX
+ */
+public interface ChargingPriority {
+ /**
+ * The vehicle can start charging if the method returns true, otherwise it stays
+ * in the queue.
+ */
+ boolean requestPlugNext(ChargingVehicle cv, double now);
+
+ public interface Factory {
+ ChargingPriority create(ChargerSpecification charger);
+ }
+
+ /**
+ * The default charging priority: first-in first-out.
+ */
+ static public final Factory FIFO = charger -> (ev, now) -> true;
+}
\ No newline at end of file
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStrategy.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStrategy.java
index 87b76bf1303..bb5717b3cc2 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStrategy.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStrategy.java
@@ -19,17 +19,21 @@
package org.matsim.contrib.ev.charging;
import org.matsim.contrib.ev.fleet.ElectricVehicle;
+import org.matsim.contrib.ev.infrastructure.ChargerSpecification;
/**
* @author michalm
+ * @author Sebastian Hörl (sebhoerl), IRT SystemX
*/
public interface ChargingStrategy {
- default boolean isChargingCompleted(ElectricVehicle ev) {
- return calcRemainingEnergyToCharge(ev) <= 0;
- }
+ boolean isChargingCompleted();
- double calcRemainingEnergyToCharge(ElectricVehicle ev);
+ double calcRemainingEnergyToCharge();
//XXX should include potentially longer charging if AUX remains turned on
- double calcRemainingTimeToCharge(ElectricVehicle ev);
+ double calcRemainingTimeToCharge();
+
+ static public interface Factory {
+ ChargingStrategy createStrategy(ChargerSpecification charger, ElectricVehicle ev);
+ }
}
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithAssignmentLogic.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithAssignmentLogic.java
index ceaabad797e..cd7333d9411 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithAssignmentLogic.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithAssignmentLogic.java
@@ -5,9 +5,11 @@
import java.util.Collection;
public interface ChargingWithAssignmentLogic extends ChargingLogic {
- void assignVehicle(ElectricVehicle ev);
+ void assignVehicle(ElectricVehicle ev, ChargingStrategy strategy);
void unassignVehicle(ElectricVehicle ev);
- Collection getAssignedVehicles();
+ Collection getAssignedVehicles();
+
+ boolean isAssigned(ElectricVehicle ev);
}
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingAndAssignmentLogic.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingAndAssignmentLogic.java
index 5fb5cc0ae6d..1a0aa853af0 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingAndAssignmentLogic.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingAndAssignmentLogic.java
@@ -23,7 +23,6 @@
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.function.Function;
import org.matsim.api.core.v01.Id;
import org.matsim.contrib.ev.fleet.ElectricVehicle;
@@ -31,21 +30,18 @@
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.vehicles.Vehicle;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
public class ChargingWithQueueingAndAssignmentLogic extends ChargingWithQueueingLogic
implements ChargingWithAssignmentLogic {
- private final Map, ElectricVehicle> assignedVehicles = new LinkedHashMap<>();
+ private final Map, ChargingVehicle> assignedVehicles = new LinkedHashMap<>();
- public ChargingWithQueueingAndAssignmentLogic(ChargerSpecification charger, ChargingStrategy chargingStrategy,
- EventsManager eventsManager) {
- super(charger, chargingStrategy, eventsManager);
+ public ChargingWithQueueingAndAssignmentLogic(ChargerSpecification charger, EventsManager eventsManager, ChargingPriority priority) {
+ super(charger, eventsManager, priority);
}
@Override
- public void assignVehicle(ElectricVehicle ev) {
- if (assignedVehicles.put(ev.getId(), ev) != null) {
+ public void assignVehicle(ElectricVehicle ev, ChargingStrategy strategy) {
+ ChargingVehicle cv = new ChargingVehicle(ev, strategy);
+ if (assignedVehicles.put(ev.getId(), cv) != null) {
throw new IllegalArgumentException("Vehicle is already assigned: " + ev.getId());
}
}
@@ -57,28 +53,31 @@ public void unassignVehicle(ElectricVehicle ev) {
}
}
- private final Collection unmodifiableAssignedVehicles = Collections.unmodifiableCollection(
+ @Override
+ public boolean isAssigned(ElectricVehicle ev) {
+ return assignedVehicles.containsKey(ev.getId());
+ }
+
+ private final Collection unmodifiableAssignedVehicles = Collections.unmodifiableCollection(
assignedVehicles.values());
@Override
- public Collection getAssignedVehicles() {
+ public Collection getAssignedVehicles() {
return unmodifiableAssignedVehicles;
}
- public static class FactoryProvider implements Provider {
- @Inject
- private EventsManager eventsManager;
-
- private final Function chargingStrategyCreator;
+ static public class Factory implements ChargingLogic.Factory {
+ private final EventsManager eventsManager;
+ private final ChargingPriority.Factory priorityFactory;
- public FactoryProvider(Function chargingStrategyCreator) {
- this.chargingStrategyCreator = chargingStrategyCreator;
+ public Factory(EventsManager eventsManager, ChargingPriority.Factory priorityFactory) {
+ this.eventsManager = eventsManager;
+ this.priorityFactory = priorityFactory;
}
@Override
- public ChargingLogic.Factory get() {
- return charger -> new ChargingWithQueueingAndAssignmentLogic(charger,
- chargingStrategyCreator.apply(charger), eventsManager);
+ public ChargingLogic create(ChargerSpecification charger) {
+ return new ChargingWithQueueingAndAssignmentLogic(charger, eventsManager, priorityFactory.create(charger));
}
}
}
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingLogic.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingLogic.java
index 8cf57733532..0e0de973ffe 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingLogic.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingLogic.java
@@ -19,78 +19,87 @@
package org.matsim.contrib.ev.charging;
-import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Queue;
+import java.util.concurrent.LinkedBlockingQueue;
+
import org.matsim.api.core.v01.Id;
import org.matsim.contrib.ev.fleet.ElectricVehicle;
import org.matsim.contrib.ev.infrastructure.ChargerSpecification;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.vehicles.Vehicle;
-import java.util.*;
-import java.util.concurrent.LinkedBlockingQueue;
+import com.google.common.base.Preconditions;
public class ChargingWithQueueingLogic implements ChargingLogic {
protected final ChargerSpecification charger;
- private final ChargingStrategy chargingStrategy;
private final EventsManager eventsManager;
+ private final ChargingPriority priority;
- private final Map, ElectricVehicle> pluggedVehicles = new LinkedHashMap<>();
- private final Queue queuedVehicles = new LinkedList<>();
- private final Queue arrivingVehicles = new LinkedBlockingQueue<>();
+ private final Map, ChargingVehicle> pluggedVehicles = new LinkedHashMap<>();
+ private final Queue queuedVehicles = new LinkedList<>();
+ private final Queue arrivingVehicles = new LinkedBlockingQueue<>();
private final Map, ChargingListener> listeners = new LinkedHashMap<>();
- public ChargingWithQueueingLogic(ChargerSpecification charger, ChargingStrategy chargingStrategy, EventsManager eventsManager) {
- this.chargingStrategy = Objects.requireNonNull(chargingStrategy);
+ public ChargingWithQueueingLogic(ChargerSpecification charger, EventsManager eventsManager, ChargingPriority priority) {
this.charger = Objects.requireNonNull(charger);
this.eventsManager = Objects.requireNonNull(eventsManager);
+ this.priority = priority;
}
@Override
public void chargeVehicles(double chargePeriod, double now) {
- Iterator evIter = pluggedVehicles.values().iterator();
- while (evIter.hasNext()) {
- ElectricVehicle ev = evIter.next();
+ Iterator cvIter = pluggedVehicles.values().iterator();
+ while (cvIter.hasNext()) {
+ ChargingVehicle cv = cvIter.next();
// with fast charging, we charge around 4% of SOC per minute,
// so when updating SOC every 10 seconds, SOC increases by less then 1%
- double oldCharge = ev.getBattery().getCharge();
- double energy = ev.getChargingPower().calcChargingPower(charger) * chargePeriod;
- double newCharge = Math.min(oldCharge + energy, ev.getBattery().getCapacity());
- ev.getBattery().setCharge(newCharge);
- eventsManager.processEvent(new EnergyChargedEvent(now, charger.getId(), ev.getId(), newCharge - oldCharge, newCharge));
-
- if (chargingStrategy.isChargingCompleted(ev)) {
- evIter.remove();
- eventsManager.processEvent(new ChargingEndEvent(now, charger.getId(), ev.getId(), ev.getBattery().getCharge()));
- listeners.remove(ev.getId()).notifyChargingEnded(ev, now);
+ double oldCharge = cv.ev().getBattery().getCharge();
+ double energy = cv.ev().getChargingPower().calcChargingPower(charger) * chargePeriod;
+ double newCharge = Math.min(oldCharge + energy, cv.ev().getBattery().getCapacity());
+ cv.ev().getBattery().setCharge(newCharge);
+ eventsManager.processEvent(new EnergyChargedEvent(now, charger.getId(), cv.ev().getId(), newCharge - oldCharge, newCharge));
+
+ if (cv.strategy().isChargingCompleted()) {
+ cvIter.remove();
+ eventsManager.processEvent(new ChargingEndEvent(now, charger.getId(), cv.ev().getId(), cv.ev().getBattery().getCharge()));
+ listeners.remove(cv.ev().getId()).notifyChargingEnded(cv.ev(), now);
}
}
- int queuedToPluggedCount = Math.min(queuedVehicles.size(), charger.getPlugCount() - pluggedVehicles.size());
- for (int i = 0; i < queuedToPluggedCount; i++) {
- plugVehicle(queuedVehicles.poll(), now);
+ var queuedVehiclesIter = queuedVehicles.iterator();
+ while (queuedVehiclesIter.hasNext() && pluggedVehicles.size() < charger.getPlugCount()) {
+ var cv = queuedVehiclesIter.next();
+ if (plugVehicle(cv, now)) {
+ queuedVehiclesIter.remove();
+ }
}
var arrivingVehiclesIter = arrivingVehicles.iterator();
while (arrivingVehiclesIter.hasNext()) {
- var ev = arrivingVehiclesIter.next();
- if (pluggedVehicles.size() < charger.getPlugCount()) {
- plugVehicle(ev, now);
- } else {
- queueVehicle(ev, now);
+ var cv = arrivingVehiclesIter.next();
+ if (pluggedVehicles.size() >= charger.getPlugCount() || !plugVehicle(cv, now)) {
+ queueVehicle(cv, now);
}
- arrivingVehiclesIter.remove();
}
+ arrivingVehicles.clear();
}
@Override
- public void addVehicle(ElectricVehicle ev, double now) {
- addVehicle(ev, new ChargingListener() {
+ public void addVehicle(ElectricVehicle ev, ChargingStrategy strategy, double now) {
+ addVehicle(ev, strategy, new ChargingListener() {
}, now);
}
@Override
- public void addVehicle(ElectricVehicle ev, ChargingListener chargingListener, double now) {
- arrivingVehicles.add(ev);
+ public void addVehicle(ElectricVehicle ev, ChargingStrategy strategy, ChargingListener chargingListener, double now) {
+ arrivingVehicles.add(new ChargingVehicle(ev, strategy));
listeners.put(ev.getId(), chargingListener);
}
@@ -100,47 +109,79 @@ public void removeVehicle(ElectricVehicle ev, double now) {
eventsManager.processEvent(new ChargingEndEvent(now, charger.getId(), ev.getId(), ev.getBattery().getCharge()));
listeners.remove(ev.getId()).notifyChargingEnded(ev, now);
- if (!queuedVehicles.isEmpty()) {
- plugVehicle(queuedVehicles.poll(), now);
+ var queuedVehiclesIter = queuedVehicles.iterator();
+ while (queuedVehiclesIter.hasNext()) {
+ var queuedVehicle = queuedVehiclesIter.next();
+ if (plugVehicle(queuedVehicle, now)) {
+ queuedVehiclesIter.remove();
+ break;
+ }
}
} else {
- // make sure ev was in the queue
- Preconditions.checkState(queuedVehicles.remove(ev), "Vehicle (%s) is neither queued nor plugged at charger (%s)", ev.getId(),
- charger.getId());
- eventsManager.processEvent(new QuitQueueAtChargerEvent(now, charger.getId(), ev.getId()));
+ var queuedVehiclesIter = queuedVehicles.iterator();
+ while (queuedVehiclesIter.hasNext()) {
+ var queuedVehicle = queuedVehiclesIter.next();
+
+ if (queuedVehicle.ev() == ev) {
+ queuedVehiclesIter.remove();
+ eventsManager.processEvent(new QuitQueueAtChargerEvent(now, charger.getId(), ev.getId()));
+ return; // found the vehicle
+ }
+ }
+
+ throw new IllegalStateException(String.format("Vehicle (%s) is neither queued nor plugged at charger (%s)", ev.getId(),
+ charger.getId()));
}
}
- private void queueVehicle(ElectricVehicle ev, double now) {
- queuedVehicles.add(ev);
- eventsManager.processEvent(new QueuedAtChargerEvent(now, charger.getId(), ev.getId()));
- listeners.get(ev.getId()).notifyVehicleQueued(ev, now);
+ private void queueVehicle(ChargingVehicle cv, double now) {
+ queuedVehicles.add(cv);
+ eventsManager.processEvent(new QueuedAtChargerEvent(now, charger.getId(), cv.ev().getId()));
+ listeners.get(cv.ev().getId()).notifyVehicleQueued(cv.ev(), now);
}
- private void plugVehicle(ElectricVehicle ev, double now) {
- if (pluggedVehicles.put(ev.getId(), ev) != null) {
+ private boolean plugVehicle(ChargingVehicle cv, double now) {
+ assert pluggedVehicles.size() < charger.getPlugCount();
+
+ if (!priority.requestPlugNext(cv, now)) {
+ return false;
+ }
+
+ if (pluggedVehicles.put(cv.ev().getId(), cv) != null) {
throw new IllegalArgumentException();
}
- eventsManager.processEvent(new ChargingStartEvent(now, charger.getId(), ev.getId(), ev.getBattery().getCharge()));
- listeners.get(ev.getId()).notifyChargingStarted(ev, now);
+ eventsManager.processEvent(new ChargingStartEvent(now, charger.getId(), cv.ev().getId(), cv.ev().getBattery().getCharge()));
+ listeners.get(cv.ev().getId()).notifyChargingStarted(cv.ev(), now);
+
+ return true;
}
- private final Collection unmodifiablePluggedVehicles = Collections.unmodifiableCollection(pluggedVehicles.values());
+ private final Collection unmodifiablePluggedVehicles = Collections.unmodifiableCollection(pluggedVehicles.values());
@Override
- public Collection getPluggedVehicles() {
+ public Collection getPluggedVehicles() {
return unmodifiablePluggedVehicles;
}
- private final Collection unmodifiableQueuedVehicles = Collections.unmodifiableCollection(queuedVehicles);
+ private final Collection unmodifiableQueuedVehicles = Collections.unmodifiableCollection(queuedVehicles);
@Override
- public Collection getQueuedVehicles() {
+ public Collection getQueuedVehicles() {
return unmodifiableQueuedVehicles;
}
- @Override
- public ChargingStrategy getChargingStrategy() {
- return chargingStrategy;
+ static public class Factory implements ChargingLogic.Factory {
+ private final EventsManager eventsManager;
+ private final ChargingPriority.Factory chargingPriorityFactory;
+
+ public Factory(EventsManager eventsManager, ChargingPriority.Factory chargingPriorityFactory) {
+ this.eventsManager = eventsManager;
+ this.chargingPriorityFactory = chargingPriorityFactory;
+ }
+
+ @Override
+ public ChargingLogic create(ChargerSpecification charger) {
+ return new ChargingWithQueueingLogic(charger, eventsManager, chargingPriorityFactory.create(charger));
+ }
}
}
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java
index d206a50c875..15431cea1fe 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java
@@ -86,11 +86,14 @@ public class VehicleChargingHandler
private final ImmutableListMultimap, Charger> chargersAtLinks;
private final EvConfigGroup evCfg;
+ private final ChargingStrategy.Factory strategyFactory;
+
@Inject
- VehicleChargingHandler(ChargingInfrastructure chargingInfrastructure, ElectricFleet electricFleet, EvConfigGroup evConfigGroup) {
+ VehicleChargingHandler(ChargingInfrastructure chargingInfrastructure, ElectricFleet electricFleet, EvConfigGroup evConfigGroup, ChargingStrategy.Factory strategyFactory) {
this.chargingInfrastructure = chargingInfrastructure;
this.electricFleet = electricFleet;
this.evCfg = evConfigGroup;
+ this.strategyFactory = strategyFactory;
chargersAtLinks = ChargingInfrastructureUtils.getChargersAtLinks(chargingInfrastructure );
}
@@ -112,7 +115,7 @@ public void handleEvent(ActivityStartEvent event) {
.filter(ch -> ev.getChargerTypes().contains(ch.getChargerType()))
.findAny()
.get();
- c.getLogic().addVehicle(ev, event.getTime());
+ c.getLogic().addVehicle(ev, strategyFactory.createStrategy(c.getSpecification(), ev), event.getTime());
vehiclesAtChargers.put(evId, c.getId());
}
}
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetSpecificationDefaultImpl.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetSpecificationDefaultImpl.java
index b24583feb13..6b9b30e8cfd 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetSpecificationDefaultImpl.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetSpecificationDefaultImpl.java
@@ -30,7 +30,7 @@
/**
* @author Michal Maciejewski (michalm)
*/
-final class ElectricFleetSpecificationDefaultImpl implements ElectricFleetSpecification {
+public final class ElectricFleetSpecificationDefaultImpl implements ElectricFleetSpecification {
private final Map, ElectricVehicleSpecification> specifications = new LinkedHashMap<>();
@Override
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecificationDefaultImpl.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecificationDefaultImpl.java
index ef18ae6cce6..e3a4caca03e 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecificationDefaultImpl.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecificationDefaultImpl.java
@@ -33,7 +33,7 @@
/**
* @author Michal Maciejewski (michalm)
*/
-final class ElectricVehicleSpecificationDefaultImpl implements ElectricVehicleSpecification {
+public final class ElectricVehicleSpecificationDefaultImpl implements ElectricVehicleSpecification {
private final Vehicle matsimVehicle;
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureSpecificationDefaultImpl.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureSpecificationDefaultImpl.java
index 48a27563616..763a2cd70e1 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureSpecificationDefaultImpl.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureSpecificationDefaultImpl.java
@@ -28,7 +28,7 @@
/**
* @author Michal Maciejewski (michalm)
*/
-final class ChargingInfrastructureSpecificationDefaultImpl implements ChargingInfrastructureSpecification {
+public final class ChargingInfrastructureSpecificationDefaultImpl implements ChargingInfrastructureSpecification {
private final SpecificationContainer container = new SpecificationContainer<>();
@Override
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/reservation/ChargerReservationManager.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/reservation/ChargerReservationManager.java
new file mode 100644
index 00000000000..6e6fa1e77c9
--- /dev/null
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/reservation/ChargerReservationManager.java
@@ -0,0 +1,106 @@
+package org.matsim.contrib.ev.reservation;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.matsim.api.core.v01.IdMap;
+import org.matsim.contrib.ev.fleet.ElectricVehicle;
+import org.matsim.contrib.ev.infrastructure.Charger;
+import org.matsim.contrib.ev.infrastructure.ChargerSpecification;
+import org.matsim.core.controler.events.IterationStartsEvent;
+import org.matsim.core.controler.listener.IterationStartsListener;
+
+/**
+ * This class is a singleton service that keeps a list of reservations for
+ * chargers. It can be used in combination with the
+ * ReservationBasedChargingPriority to let vehicle pass on to charging only if
+ * they have a proper reservation.
+ *
+ * @author Sebastian Hörl (sebhoerl), IRT SystemX
+ */
+public class ChargerReservationManager implements IterationStartsListener {
+ private final IdMap> reservations = new IdMap<>(Charger.class);
+
+ public boolean isAvailable(ChargerSpecification charger, ElectricVehicle vehicle, double startTile,
+ double endTime) {
+ if (charger.getPlugCount() == 0) {
+ return false;
+ }
+
+ if (!reservations.containsKey(charger.getId())) {
+ return true;
+ }
+
+ int remaining = charger.getPlugCount();
+ for (Reservation reservation : reservations.get(charger.getId())) {
+ if (reservation.vehicle != vehicle && isOverlapping(reservation, startTile, endTime)) {
+ remaining--;
+ }
+ }
+
+ return remaining > 0;
+ }
+
+ private boolean isOverlapping(Reservation reservation, double startTime, double endTime) {
+ if (startTime >= reservation.startTime && startTime <= reservation.endTime) {
+ return true; // start time within existing range
+ } else if (endTime >= reservation.startTime && endTime <= reservation.endTime) {
+ return true; // end time within existing range
+ } else if (startTime <= reservation.startTime && endTime >= reservation.endTime) {
+ return true; // new range covers existing range
+ } else {
+ return false;
+ }
+ }
+
+ public Reservation addReservation(ChargerSpecification charger, ElectricVehicle vehicle, double startTime,
+ double endTime) {
+ if (isAvailable(charger, vehicle, startTime, endTime)) {
+ List chargerReservations = reservations.get(charger.getId());
+
+ if (chargerReservations == null) {
+ chargerReservations = new LinkedList<>();
+ reservations.put(charger.getId(), chargerReservations);
+ }
+
+ Reservation reservation = new Reservation(charger, vehicle, startTime, endTime);
+ chargerReservations.add(reservation);
+
+ return reservation;
+ }
+
+ return null;
+ }
+
+ public boolean removeReservation(Reservation reservation) {
+ List chargerReservations = reservations.get(reservation.charger.getId());
+
+ if (chargerReservations != null) {
+ return chargerReservations.remove(reservation);
+ }
+
+ return false;
+ }
+
+ public Reservation findReservation(ChargerSpecification charger, ElectricVehicle vehicle, double now) {
+ List chargerReservations = reservations.get(charger.getId());
+
+ if (chargerReservations != null) {
+ for (Reservation reservation : chargerReservations) {
+ if (reservation.vehicle == vehicle && now >= reservation.startTime && now <= reservation.endTime) {
+ return reservation;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public record Reservation(ChargerSpecification charger, ElectricVehicle vehicle, double startTime, double endTime) {
+ }
+
+ @Override
+ public void notifyIterationStarts(IterationStartsEvent event) {
+ reservations.clear();
+ }
+}
\ No newline at end of file
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/reservation/ChargerReservationModule.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/reservation/ChargerReservationModule.java
new file mode 100644
index 00000000000..9a17f208055
--- /dev/null
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/reservation/ChargerReservationModule.java
@@ -0,0 +1,35 @@
+package org.matsim.contrib.ev.reservation;
+
+import org.matsim.contrib.ev.charging.ChargingPriority;
+import org.matsim.core.controler.AbstractModule;
+
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+
+/**
+ * This module enables the reservation-based charging logic that requires
+ * vehicles to have or make a reservation when attempting to charge at a
+ * charger.
+ *
+ * @author Sebastian Hörl (sebhoerl), IRT SystemX
+ */
+public class ChargerReservationModule extends AbstractModule {
+ @Override
+ public void install() {
+ addControlerListenerBinding().to(ChargerReservationManager.class);
+ bind(ChargingPriority.Factory.class).to(ReservationBasedChargingPriority.Factory.class);
+ }
+
+ @Provides
+ @Singleton
+ ReservationBasedChargingPriority.Factory provideReservationBasedChargingPriorityFactory(
+ ChargerReservationManager reservationManager) {
+ return new ReservationBasedChargingPriority.Factory(reservationManager);
+ }
+
+ @Provides
+ @Singleton
+ ChargerReservationManager provideChargerReservationManager() {
+ return new ChargerReservationManager();
+ }
+}
\ No newline at end of file
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/reservation/ReservationBasedChargingPriority.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/reservation/ReservationBasedChargingPriority.java
new file mode 100644
index 00000000000..8ac5a79a8ad
--- /dev/null
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/reservation/ReservationBasedChargingPriority.java
@@ -0,0 +1,64 @@
+package org.matsim.contrib.ev.reservation;
+
+import org.matsim.contrib.ev.charging.ChargingLogic.ChargingVehicle;
+import org.matsim.contrib.ev.charging.ChargingPriority;
+import org.matsim.contrib.ev.infrastructure.ChargerSpecification;
+import org.matsim.contrib.ev.reservation.ChargerReservationManager.Reservation;
+
+/**
+ * This is an implementation of a charging priority which is backed by the
+ * ReservationManager: When a vehicle arrives, it is checked whether a
+ * reservation for this vehicle exists for the respective charger and the
+ * current time. In that case, the vehicle can be plugged if it is on top of the
+ * queue. If not, the ChargingPriority will try to make a reservation and if it
+ * is successful, the vehicle can start charging. In all other cases, the
+ * vehicle will stay in the queue until it is removed manually or a successful
+ * reservation can be made at a future time.
+ *
+ * @author Sebastian Hörl (sebhoerl), IRT SystemX
+ */
+public class ReservationBasedChargingPriority implements ChargingPriority {
+ private final ChargerReservationManager manager;
+ private final ChargerSpecification charger;
+
+ public ReservationBasedChargingPriority(ChargerReservationManager manager, ChargerSpecification charger) {
+ this.charger = charger;
+ this.manager = manager;
+ }
+
+ @Override
+ public boolean requestPlugNext(ChargingVehicle cv, double now) {
+ Reservation reservation = manager.findReservation(charger, cv.ev(), now);
+
+ if (reservation != null) {
+ // vehicle has a reservation, can be plugged right away, consume reservation
+ manager.removeReservation(reservation);
+ return true;
+ }
+
+ double endTime = cv.strategy().calcRemainingTimeToCharge() + now;
+ reservation = manager.addReservation(charger, cv.ev(), now, endTime);
+
+ if (reservation != null) {
+ // vehicle did not have a reservation, but managed to create one on the fly,
+ // consume it directly
+ manager.removeReservation(reservation);
+ return true;
+ }
+
+ return false;
+ }
+
+ static public class Factory implements ChargingPriority.Factory {
+ private final ChargerReservationManager reservationManager;
+
+ public Factory(ChargerReservationManager reservationManager) {
+ this.reservationManager = reservationManager;
+ }
+
+ @Override
+ public ChargingPriority create(ChargerSpecification charger) {
+ return new ReservationBasedChargingPriority(reservationManager, charger);
+ }
+ }
+}
\ No newline at end of file
diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargingProceduresCSVWriter.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargingProceduresCSVWriter.java
index ae1c9d0c013..4cef65da81b 100644
--- a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargingProceduresCSVWriter.java
+++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargingProceduresCSVWriter.java
@@ -83,8 +83,12 @@ private void proccessChargingEventSequences(CSVPrinter csvPrinter, Collection() {
- @Inject
- private ChargerPowerTimeProfileCalculator calculator;
- @Inject
- private MatsimServices matsimServices;
+ });
+ bind(ChargerPowerTimeProfileCalculator.class).asEagerSingleton();
+ addEventHandlerBinding().to(ChargerPowerTimeProfileCalculator.class);
+ addControlerListenerBinding().toProvider(new Provider<>() {
+ @Inject
+ private ChargerPowerTimeProfileCalculator calculator;
+ @Inject
+ private MatsimServices matsimServices;
- @Override
- public ControlerListener get() {
- var profileView = new ChargerPowerTimeProfileView(calculator);
- return new ProfileWriter(matsimServices,"ev",profileView,"charger_power_time_profiles");
+ @Override
+ public ControlerListener get() {
+ var profileView = new ChargerPowerTimeProfileView(calculator);
+ return new ProfileWriter(matsimServices, "ev", profileView, "charger_power_time_profiles");
- }
- });
+ }
+ });
+ }
}
}
diff --git a/contribs/freight/README.md b/contribs/freight/README.md
index afdcbcd4abc..746cdba1bc1 100644
--- a/contribs/freight/README.md
+++ b/contribs/freight/README.md
@@ -1,10 +1,25 @@
# Freight
-Package that plugs freight algorithms (programmed in external package jsprit) into matsim.
+This contrib contains the following packages:
+
+## Carriers
+(This is formally knows as 'freight contrib')
+
+Package that plugs vehicle routing problem algorithms (programmed in external package jsprit) into MATSim.
A good starting point for jsprit is [ https://github.com/graphhopper/jsprit](https://github.com/graphhopper/jsprit).
-For runnable code see, e.g., the packages org.matsim.contrib.freight.usecases.* above .
+For runnable code see, e.g., the packages org.matsim.contrib.freight.carriers.usecases.* above .
+
+## Logistics
+(This code comes from [https://github.com/matsim-vsp/logistics/](https://github.com/matsim-vsp/logistics/) )
+
+This code deals with creating logistics chains for freight transport.
+
+Here the decision agent is the logistics service provider (LSP) who decides on the logistics chain to be used for a given freight transport request.
+Therefore, it can use carriers (see above) and hubs.
+
+This package bases on work in the dfg-freight project.
\ No newline at end of file
diff --git a/contribs/freight/pom.xml b/contribs/freight/pom.xml
index d6dd0d20b65..c1df7ab953a 100644
--- a/contribs/freight/pom.xml
+++ b/contribs/freight/pom.xml
@@ -55,13 +55,13 @@
org.matsim.contribroadpricing
- 2025.0-SNAPSHOT
+ ${project.parent.version}org.matsim.contribotfvis
- 2025.0-SNAPSHOT
+ ${project.parent.version}
@@ -85,7 +85,7 @@
org.matsimmatsim-examples
- 2025.0-SNAPSHOT
+ ${project.parent.version}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/Carrier.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/Carrier.java
index 8ee9e1812e5..e80fbb6c9fa 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/Carrier.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/Carrier.java
@@ -21,13 +21,12 @@
package org.matsim.freight.carriers;
+import java.util.List;
+import java.util.Map;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.population.HasPlansAndId;
import org.matsim.utils.objectattributes.attributable.Attributable;
-import java.util.List;
-import java.util.Map;
-
/**
* A carrier.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierCapabilities.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierCapabilities.java
index fa14ddfd9bb..879017be0f4 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierCapabilities.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierCapabilities.java
@@ -21,12 +21,11 @@
package org.matsim.freight.carriers;
+import java.util.*;
import org.matsim.api.core.v01.Id;
import org.matsim.vehicles.Vehicle;
import org.matsim.vehicles.VehicleType;
-import java.util.*;
-
/**
* This contains the capabilities/resources a carrier has/can deploy.
*
@@ -65,7 +64,7 @@ public Builder setFleetSize(FleetSize fleetSize){
/**
* @deprecated Since the vehicle type is in the {@link CarrierVehicleTypes}
* container, it should not be duplicated here. It is also not written
- * to file when writing {@link CarrierPlanXmlWriterV2}.
+ * to file when writing.
*/
@Deprecated
public Builder addType( VehicleType type ){
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierImpl.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierImpl.java
index 8dcc53adc75..54bebb6b9d2 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierImpl.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierImpl.java
@@ -21,14 +21,13 @@
package org.matsim.freight.carriers;
-import org.matsim.api.core.v01.Id;
-import org.matsim.utils.objectattributes.attributable.Attributes;
-import org.matsim.utils.objectattributes.attributable.AttributesImpl;
-
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import org.matsim.api.core.v01.Id;
+import org.matsim.utils.objectattributes.attributable.Attributes;
+import org.matsim.utils.objectattributes.attributable.AttributesImpl;
/**
* This is a carrier that has capabilities and resources, jobs and plans to fulfill its obligations.
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierJob.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierJob.java
new file mode 100644
index 00000000000..1dc1cd32f8d
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierJob.java
@@ -0,0 +1,19 @@
+package org.matsim.freight.carriers;
+
+import org.matsim.utils.objectattributes.attributable.Attributable;
+
+/**
+ * A job that a {@link Carrier} can do.
+ *
+ * In a first step this is more or less a marker interface.
+ *
+ * In the next steps it will be extended, as follows
+ * 1) existing common methods of {@link CarrierShipment} and {@link
+ * CarrierService} where moved up here
+ * 2) some similar, but differently named methods of {@link
+ * CarrierShipment} and {@link CarrierService} were renamed to the same name and moved up here
+ * ...
+ * future) It maybe gets generalized in way, that we only have one job definition with 1 or 2
+ * location(s). This then defines, if jsprit takes the job as a service or as a shipment.
+ */
+public interface CarrierJob extends Attributable {}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlan.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlan.java
index 9c51aac159e..eed09f1b42b 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlan.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlan.java
@@ -21,13 +21,12 @@
package org.matsim.freight.carriers;
+import java.util.Collection;
import org.matsim.api.core.v01.population.BasicPlan;
import org.matsim.utils.objectattributes.attributable.Attributable;
import org.matsim.utils.objectattributes.attributable.Attributes;
import org.matsim.utils.objectattributes.attributable.AttributesImpl;
-import java.util.Collection;
-
/**
*
* A specific plan of a carrier, and its score.
@@ -70,7 +69,6 @@ public Double getScore() {
/**
* In future (starting in May'23) this is the score from the MATSim scoring function.
* The jsprit score is saved in attribute. Please use the method setJspritScore() to store it.
- * @return the (MATSim) score
*/
@Override
public void setScore(Double score) {
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanReaderV1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanReaderV1.java
index 4e13ad599b6..4bb90047d86 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanReaderV1.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanReaderV1.java
@@ -21,6 +21,7 @@
package org.matsim.freight.carriers;
+import java.util.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -34,8 +35,6 @@
import org.matsim.vehicles.VehicleType;
import org.xml.sax.Attributes;
-import java.util.*;
-
/**
* A reader that reads carriers and their plans.
*
@@ -82,7 +81,7 @@ class CarrierPlanReaderV1 extends MatsimXmlParser {
* Constructs a reader with an empty carriers-container for the carriers to be constructed.
*
* @param carriers which is a map that stores carriers
- * @param carrierVehicleTypes
+ * @param carrierVehicleTypes which is a map that stores carrierVehicleTypes
*/
public CarrierPlanReaderV1( Carriers carriers, CarrierVehicleTypes carrierVehicleTypes ) {
super(ValidationType.DTD_OR_XSD);
@@ -188,7 +187,7 @@ public void startTag(String name, Attributes attributes, Stack context)
{
String vehicleId = attributes.getValue("vehicleId");
currentVehicle = vehicles.get(vehicleId);
- currentTourBuilder = Tour.Builder.newInstance();
+ currentTourBuilder = Tour.Builder.newInstance(Id.create("unknown", Tour.class));
break ;
}
case "leg":
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanWriter.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanWriter.java
index 3d7922d9489..888bfcf5289 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanWriter.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanWriter.java
@@ -22,9 +22,8 @@
package org.matsim.freight.carriers;
import com.google.inject.Inject;
-import org.matsim.utils.objectattributes.AttributeConverter;
-
import java.util.Map;
+import org.matsim.utils.objectattributes.AttributeConverter;
/**
* @author mrieser / Simunto
@@ -47,31 +46,6 @@ public void write(String filename) {
this.writeV2_1(filename);
}
- /**
- * @deprecated The underlining {@Link{CarrierPlanXmlWriterV1} is deprecated since April21
- */
- @Deprecated
- public void writeV1(String filename) {
- new CarrierPlanXmlWriterV1(this.carriers.getCarriers().values()).write(filename);
- }
-
-
- /**
- * Writes out the Carriers file in version 2.
- * Please use the method {@link #write(String)} instead to always ensure writing out to the newest format.
- *
- * @deprecated The underlining {@Link{CarrierPlanXmlWriterV2} is deprecated since Sep'22
- *
- * @param filename Name of the file that should be written.
- */
- @Deprecated public void writeV2(String filename) {
- CarrierPlanXmlWriterV2 writer = new CarrierPlanXmlWriterV2(this.carriers);
- if (this.attributeConverters != null) {
- writer.putAttributeConverters(this.attributeConverters);
- }
- writer.write(filename);
- }
-
/**
* Writes out the Carriers file in version 2.1.
* Please use the method {@link #write(String)} to always ensure writing out to the newest format.
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2.java
index a63697cfab4..271871b0970 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2.java
@@ -21,7 +21,10 @@
package org.matsim.freight.carriers;
+import static org.matsim.freight.carriers.CarrierConstants.*;
+
import com.google.inject.Inject;
+import java.util.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -40,10 +43,6 @@
import org.matsim.vehicles.VehicleType;
import org.xml.sax.Attributes;
-import java.util.*;
-
-import static org.matsim.freight.carriers.CarrierConstants.*;
-
class CarrierPlanXmlParserV2 extends MatsimXmlParser {
public static final Logger logger = LogManager.getLogger(CarrierPlanXmlParserV2.class);
@@ -78,7 +77,7 @@ class CarrierPlanXmlParserV2 extends MatsimXmlParser {
* Constructs a reader with an empty carriers-container for the carriers to be constructed.
*
* @param carriers which is a map that stores carriers
- * @param carrierVehicleTypes
+ * @param carrierVehicleTypes which is a map that stores vehicle types
*/
CarrierPlanXmlParserV2( Carriers carriers, CarrierVehicleTypes carrierVehicleTypes ) {
super(ValidationType.XSD_ONLY);
@@ -234,7 +233,7 @@ public void startTag(String name, Attributes atts, Stack context) {
currentVehicle = vehicles.get(vehicleId);
if (currentVehicle == null)
throw new IllegalStateException("vehicle to vehicleId " + vehicleId + " is missing.");
- currentTourBuilder = Tour.Builder.newInstance();
+ currentTourBuilder = Tour.Builder.newInstance(Id.create("unknown", Tour.class));
break;
case "leg":
String depTime = atts.getValue("expected_dep_time");
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2_1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2_1.java
index 8503eb4acad..9c3f2b7a1e6 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2_1.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2_1.java
@@ -21,7 +21,10 @@
package org.matsim.freight.carriers;
+import static org.matsim.freight.carriers.CarrierConstants.*;
+
import com.google.inject.Inject;
+import java.util.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -40,10 +43,6 @@
import org.matsim.vehicles.VehicleType;
import org.xml.sax.Attributes;
-import java.util.*;
-
-import static org.matsim.freight.carriers.CarrierConstants.*;
-
class CarrierPlanXmlParserV2_1 extends MatsimXmlParser {
public static final Logger logger = LogManager.getLogger(CarrierPlanXmlParserV2_1.class);
@@ -77,7 +76,7 @@ class CarrierPlanXmlParserV2_1 extends MatsimXmlParser {
* Constructs a reader with an empty carriers-container for the carriers to be constructed.
*
* @param carriers which is a map that stores carriers
- * @param carrierVehicleTypes
+ * @param carrierVehicleTypes which is a map that stores vehicle types
*/
CarrierPlanXmlParserV2_1(Carriers carriers, CarrierVehicleTypes carrierVehicleTypes ) {
super(ValidationType.XSD_ONLY);
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlReader.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlReader.java
index 5155f5bdebc..4842ab434f9 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlReader.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlReader.java
@@ -21,6 +21,9 @@
package org.matsim.freight.carriers;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Stack;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.core.api.internal.MatsimReader;
@@ -28,10 +31,6 @@
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Stack;
-
/**
* A reader that reads carriers and their plans.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV1.java
deleted file mode 100644
index 510ea9b1ac3..00000000000
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV1.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * *********************************************************************** *
- * project: org.matsim.*
- * *********************************************************************** *
- * *
- * copyright : (C) 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.freight.carriers;
-
-import com.graphhopper.jsprit.core.problem.job.Shipment;
-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.population.routes.NetworkRoute;
-import org.matsim.core.utils.io.MatsimXmlWriter;
-import org.matsim.core.utils.misc.Time;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A writer that writes carriers and their plans in a xml-file.
- *
- * @author sschroeder
- *
- * @deprecated Use {@link CarrierPlanWriter} instead which writes the newest format
- */
-@Deprecated
-public class CarrierPlanXmlWriterV1 extends MatsimXmlWriter {
-
- @SuppressWarnings("unused")
- private static final Logger logger = LogManager.getLogger(CarrierPlanXmlWriterV1.class);
-
- private final Collection carriers;
- private int idCounter = 0;
- private final Map> registeredShipments = new HashMap<>();
-
- /**
- * Constructs the writer with the carriers to be written.
- *
- * @param carriers to be written
- */
- public CarrierPlanXmlWriterV1(Collection carriers) {
- super();
- this.carriers = carriers;
- }
-
- /**
- * Writes carriers and their plans into a xml-file.
- *
- * @param filename should be the target xml-file
- */
- public void write(String filename) {
- logger.info("write carrier plans");
- try {
- openFile(filename);
- writeXmlHead();
- startCarriers(this.writer);
- for (Carrier carrier : carriers) {
- startCarrier(carrier, this.writer);
- writeVehicles(carrier, this.writer);
- writeShipments(carrier, this.writer);
- writePlans(carrier, this.writer);
- endCarrier(this.writer);
- }
- endCarriers(this.writer);
- close();
- logger.info("done");
- } catch (IOException e) {
- e.printStackTrace();
- logger.error(e);
- System.exit(1);
- }
- }
-
- private void startCarriers(BufferedWriter writer) throws IOException {
- writer.write("\t\n");
- }
-
- private void startCarrier(Carrier carrier, BufferedWriter writer)
- throws IOException {
- writer.write("\t\t\n");
- }
-
- private void writeVehicles(Carrier carrier, BufferedWriter writer)
- throws IOException {
- writer.write("\t\t\t\n");
- for (CarrierVehicle v : carrier.getCarrierCapabilities().getCarrierVehicles().values()) {
- writer.write("\t\t\t\t\n");
- }
- writer.write("\t\t\t\n\n");
- }
-
- private void writeShipments(Carrier carrier, BufferedWriter writer)
- throws IOException {
- writer.write("\t\t\t\n");
- for (CarrierShipment s : carrier.getShipments().values()) {
- // CarrierShipment s = contract.getShipment();
- Id shipmentId = Id.create(++idCounter, Shipment.class);
- registeredShipments.put(s, shipmentId);
- writer.write("\t\t\t\t\n");
- }
- writer.write("\t\t\t\n\n");
- }
-
- private String getTime(double time) {
- return Time.writeTime(time);
- }
-
- private void writePlans(Carrier carrier, BufferedWriter writer)
- throws IOException {
- if (carrier.getSelectedPlan() == null) {
- return;
- }
-
- for(CarrierPlan plan : carrier.getPlans()){
- writer.write("\t\t\t\n");
-
- for (ScheduledTour tour : plan.getScheduledTours()) {
- writer.write("\t\t\t\t\n");
- writer.write("\t\t\t\t\t\n");
- for (Tour.TourElement tourElement : tour.getTour().getTourElements()) {
- if (tourElement instanceof Tour.Leg leg) {
- writer.write("\t\t\t\t\t");
- if (leg.getRoute() != null) {
- writer.write("\n");
- writer.write("\t\t\t\t\t\t");
- boolean firstLink = true;
- for (Id id : ((NetworkRoute) leg.getRoute()).getLinkIds()) {
- if (firstLink) {
- writer.write(id.toString());
- firstLink = false;
- } else {
- writer.write(" " + id.toString());
- }
- }
- writer.write("\n");
- writer.write("\t\t\t\t\t\n");
- } else {
- writer.write("\n");
- }
- }
- if (tourElement instanceof Tour.ShipmentBasedActivity act) {
- writer.write("\t\t\t\t\t\n");
- }
-
- }
- writer.write("\t\t\t\t\t\n");
- writer.write("\t\t\t\t\n");
- }
- writer.write("\t\t\t\n\n");
- }
-
- }
-
- private void endCarrier(BufferedWriter writer) throws IOException {
- writer.write("\t\t\n\n");
- registeredShipments.clear();
- }
-
- private void endCarriers(BufferedWriter writer) throws IOException {
- writer.write("\t\n");
-
- }
-}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2.java
deleted file mode 100644
index b78af8aa3e6..00000000000
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * *********************************************************************** *
- * project: org.matsim.*
- * *********************************************************************** *
- * *
- * copyright : (C) 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.freight.carriers;
-
-import com.google.inject.Inject;
-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.population.routes.NetworkRoute;
-import org.matsim.core.utils.collections.Tuple;
-import org.matsim.core.utils.io.MatsimXmlWriter;
-import org.matsim.core.utils.misc.Time;
-import org.matsim.freight.carriers.Tour.Leg;
-import org.matsim.freight.carriers.Tour.ServiceActivity;
-import org.matsim.freight.carriers.Tour.ShipmentBasedActivity;
-import org.matsim.freight.carriers.Tour.TourElement;
-import org.matsim.utils.objectattributes.AttributeConverter;
-import org.matsim.utils.objectattributes.attributable.AttributesXmlWriterDelegate;
-import org.matsim.vehicles.VehicleType;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.util.*;
-
-/**
- * A writer that writes carriers and their plans in a xml-file.
- *
- * @author sschroeder
- *
- * @deprecated Use {@link CarrierPlanWriter} instead which writes the newest format
- */
-@Deprecated
-public class CarrierPlanXmlWriterV2 extends MatsimXmlWriter {
-
- @SuppressWarnings("unused")
- private static final Logger logger = LogManager.getLogger(CarrierPlanXmlWriterV2.class);
-
- private final Collection carriers;
-
- private final Map> registeredShipments = new HashMap<>();
-
- private final Map> serviceMap = new HashMap<>();
-
- private final AttributesXmlWriterDelegate attributesWriter = new AttributesXmlWriterDelegate();
- private final List> atts = new ArrayList<>();
-
-
- /**
- * Constructs the writer with the carriers to be written.
- *
- * @param carriers to be written
- */
- public CarrierPlanXmlWriterV2(Carriers carriers) {
- super();
- this.carriers = carriers.getCarriers().values();
- }
-
- @Inject
- public void putAttributeConverters( final Map, AttributeConverter>> converters ) {
- attributesWriter.putAttributeConverters( converters );
- }
-
- /**
- * Writes carriers and their plans into a xml-file.
- *
- * @param filename should be the target xml-file
- */
- public void write(String filename) {
- logger.info("write carrier plans");
- try {
- openFile(filename);
- writeXmlHead();
-
- startCarriers(this.writer);
- for (Carrier carrier : carriers) {
- startCarrier(carrier, this.writer);
- writeVehiclesAndTheirTypes(carrier, this.writer);
- writeShipments(carrier, this.writer);
- writeServices(carrier,this.writer);
- writePlans(carrier, this.writer);
- endCarrier(this.writer);
- }
- endCarriers(this.writer);
- close();
- logger.info("done");
- } catch (IOException e) {
- e.printStackTrace();
- logger.error(e);
- System.exit(1);
- }
- }
-
- private void startCarriers(BufferedWriter writer) throws IOException {
- writer.write("\t\n");
- }
-
- private void startCarrier(Carrier carrier, BufferedWriter writer)
- throws IOException {
- writer.write("\t\t\n");
- attributesWriter.writeAttributes("\t\t\t", writer, carrier.getAttributes());
- }
-
- private void writeVehiclesAndTheirTypes(Carrier carrier, BufferedWriter writer)throws IOException {
- writer.write("\t\t\t\n");
- //vehicles
- writer.write("\t\t\t\t\n");
- for (CarrierVehicle v : carrier.getCarrierCapabilities().getCarrierVehicles().values()) {
- Id vehicleTypeId = v.getVehicleTypeId();
- if(vehicleTypeId == null) vehicleTypeId = v.getType() == null ? null : v.getType().getId();
- if(vehicleTypeId == null) throw new IllegalStateException("vehicleTypeId is missing.");
- writer.write("\t\t\t\t\t\n");
- }
- writer.write("\t\t\t\t\n\n");
- writer.write("\t\t\t\n\n");
- }
-
- private void writeShipments(Carrier carrier, BufferedWriter writer) throws IOException {
- if(carrier.getShipments().isEmpty()) return;
- writer.write("\t\t\t\n");
- for (CarrierShipment s : carrier.getShipments().values()) {
- // CarrierShipment s = contract.getShipment();
- Id shipmentId = s.getId();
- registeredShipments.put(s, shipmentId);
- writer.write("\t\t\t\t\n");
- } else {
- writer.write("\">\n");
- this.attributesWriter.writeAttributes("\t\t\t\t\t", writer, s.getAttributes());
- writer.write("\t\t\t\t\n");
- }
- }
- writer.write("\t\t\t\n\n");
- }
-
- private void writeServices(Carrier carrier, BufferedWriter writer) throws IOException {
- writer.write("\t\t\t\n");
- for (CarrierService s : carrier.getServices().values()) {
- serviceMap.put(s, s.getId());
- writer.write("\t\t\t\t\n");
- } else {
- writer.write("\">\n");
- this.attributesWriter.writeAttributes("\t\t\t\t\t", writer, s.getAttributes());
- writer.write("\t\t\t\t\n");
- }
-
- }
- writer.write("\t\t\t\n\n");
-
- }
-
- private String getTime(double time) {
- return Time.writeTime(time);
- }
-
- private void writePlans(Carrier carrier, BufferedWriter writer)
- throws IOException {
- if (carrier.getSelectedPlan() == null) {
- return;
- }
-
- for(CarrierPlan plan : carrier.getPlans()){
- writer.write("\t\t\t\n");
-
- for (ScheduledTour tour : plan.getScheduledTours()) {
- writer.write("\t\t\t\t\n");
- writer.write("\t\t\t\t\t\n");
- for (TourElement tourElement : tour.getTour().getTourElements()) {
- if (tourElement instanceof Leg leg) {
- writer.write("\t\t\t\t\t");
- if (leg.getRoute() != null) {
- writer.write("\n");
- writer.write("\t\t\t\t\t\t");
- boolean firstLink = true;
- for (Id id : ((NetworkRoute) leg.getRoute())
- .getLinkIds()) {
- if (firstLink) {
- writer.write(id.toString());
- firstLink = false;
- } else {
- writer.write(" " + id.toString());
- }
- }
- writer.write("\n");
- writer.write("\t\t\t\t\t\n");
- } else {
- writer.write("\n");
- }
- }
- else if (tourElement instanceof ShipmentBasedActivity act) {
- writer.write("\t\t\t\t\t\n");
- }
- else if (tourElement instanceof ServiceActivity act){
- writer.write("\t\t\t\t\t\n");
- }
-
- }
- writer.write("\t\t\t\t\t\n");
- writer.write("\t\t\t\t\n");
- }
- writer.write("\t\t\t\n\n");
- }
-
- }
-
- private void endCarrier(BufferedWriter writer) throws IOException {
- writer.write("\t\t\n\n");
- registeredShipments.clear();
- }
-
- private void endCarriers(BufferedWriter writer) throws IOException {
- writer.write("\t\n");
-
- }
-}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1.java
index 92699982378..6195fb3834f 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1.java
@@ -21,7 +21,16 @@
package org.matsim.freight.carriers;
+import static org.matsim.freight.carriers.CarrierConstants.*;
+
import com.google.inject.Inject;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -34,16 +43,6 @@
import org.matsim.utils.objectattributes.attributable.AttributesXmlWriterDelegate;
import org.matsim.vehicles.VehicleType;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import static org.matsim.freight.carriers.CarrierConstants.*;
-
/**
* A writer that writes carriers and their plans in a xml-file.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierService.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierService.java
index b7106fa6de9..69a5ce75e42 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierService.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierService.java
@@ -27,8 +27,7 @@
import org.matsim.utils.objectattributes.attributable.Attributes;
import org.matsim.utils.objectattributes.attributable.AttributesImpl;
-
-public final class CarrierService implements Attributable {
+public final class CarrierService implements CarrierJob {
public static class Builder {
@@ -56,10 +55,10 @@ public Builder setName(String name){
}
/**
- * By default it is [0.0,Integer.MaxValue].
+ * By default, it is [0.0,Integer.MaxValue].
*
- * @param serviceDuration
- * @return
+ * @param serviceDuration duration of the service
+ * @return the builder
*/
public Builder setServiceDuration(double serviceDuration){
this.serviceTime = serviceDuration;
@@ -72,8 +71,8 @@ public Builder setServiceDuration(double serviceDuration){
*
Note that the time-window restricts the start-time of the service (i.e. serviceActivity). If one works with hard time-windows (which means that
* time-windows must be met) than the service is allowed to start between startTimeWindow.getStart() and startTimeWindow.getEnd().
*
- * @param startTimeWindow
- * @return
+ * @param startTimeWindow time-window for the service
+ * @return the builder
*/
public Builder setServiceStartTimeWindow(TimeWindow startTimeWindow){
this.timeWindow = startTimeWindow;
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierShipment.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierShipment.java
index 9472ffaac91..01c8b873e70 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierShipment.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierShipment.java
@@ -36,7 +36,7 @@
* @author sschroeder
*
*/
-public final class CarrierShipment implements Attributable {
+public final class CarrierShipment implements CarrierJob {
/**
* A builder that builds shipments.
@@ -47,17 +47,17 @@ public final class CarrierShipment implements Attributable {
public static class Builder {
/**
- * @Deprecated Please use Builder newInstance(Id id, Id from, Id to, int size) instead.
+ * @deprecated Please use Builder newInstance(Id id, Id from, Id to, int size) instead.
*
* Returns a new shipment builder.
*
*
The builder is init with the shipment's origin (from), destination (to) and with the shipment's size.
* The default-value for serviceTime is 0.0. The default-value for a timeWindow is [start=0.0, end=Double.maxValue()].
*
- * @param from
- * @param to
- * @param size
- * @return the builder
+ * @param from the origin
+ * @param to the destination
+ * @param size size of the shipment
+ * @return the builder
*/
@Deprecated
public static Builder newInstance(Id from, Id to, int size){
@@ -70,11 +70,11 @@ public static Builder newInstance(Id from, Id to, int size){
*
The builder is init with the shipment's origin (from), destination (to) and with the shipment's size.
* The default-value for serviceTime is 0.0. The default-value for a timeWindow is [start=0.0, end=Double.maxValue()].
*
- * @param id
- * @param from
- * @param to
- * @param size
- * @return the builder
+ * @param id the id of the shipment
+ * @param from the origin
+ * @param to the destination
+ * @param size size of the shipment
+ * @return the builder
*/
public static Builder newInstance(Id id, Id from, Id to, int size){
return new Builder(id, from,to,size);
@@ -90,7 +90,7 @@ public static Builder newInstance(Id id, Id from, Id id, Id from, Id to, int size) instead.
+ * @deprecated Please use Builder (Id id, Id from, Id to, int size) instead.
*/
@Deprecated
public Builder(Id from, Id to, int size) {
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicle.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicle.java
index 917052a65fe..7d317af7d26 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicle.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicle.java
@@ -46,8 +46,8 @@ public final class CarrierVehicle implements Vehicle {
*
* The default values for other fields (being implicitly set) are [capacity=0][earliestStart=0.0][latestEnd=Integer.MaxValue()].
*
- * @param vehicleId
- * @param locationId
+ * @param vehicleId the vehicle id
+ * @param locationId the location id
* @return CarrierVehicle
* @see CarrierVehicle
*/
@@ -68,9 +68,9 @@ public static class Builder {
*
* The default values for other fields (being implicitly set) are [capacity=0][earliestStart=0.0][latestEnd=Integer.MaxValue()].
*
- * @param vehicleId
- * @param locationId
- * @param vehicleType
+ * @param vehicleId the vehicle id
+ * @param locationId the location id
+ * @param vehicleType the vehicle type
* @return a new vehicle builder
*/
public static Builder newInstance( Id vehicleId, Id locationId, VehicleType vehicleType ){
@@ -91,29 +91,6 @@ public Builder( Id vehicleId, Id locationId, VehicleType vehicleT
this.type = vehicleType;
}
- /**
- * @param type
- * @deprecated The vehicleType need now to be set in the constructor kai/kai jan'22
- */
- @Deprecated
- public Builder setType( VehicleType type ){
- log.warn(".setType has no functionality anymore and is deprecated");
-// this.type=type;
- return this;
- }
-
- /**
- * @param typeId
- * @deprecated The vehicleTypeId is no longer needed and was confusing -> Use getType().getId kai/kai jan'22
- */
- @Deprecated
- public Builder setTypeId(Id typeId ){
- log.warn(".setTypeId has no functionality anymore and is deprecated");
-// this.typeId = typeId;
- return this;
- }
-
-
public Builder setEarliestStart(double earliestStart){
this.earliestStart=earliestStart;
return this;
@@ -151,10 +128,7 @@ private CarrierVehicle(Builder builder){
public Id getLinkId() {
return locationId;
}
- /**
- * @deprecated -- please inline. kai, jul'22
- */
- @Deprecated public Id getLocation() { return getLinkId(); }
+
@Override
public Id getId() {
return vehicleId;
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleType.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleType.java
index 16b7e92a03d..2983b859043 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleType.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleType.java
@@ -28,7 +28,7 @@
/**
* The carrier vehicle type.
*
- * I decided to put vehicle cost information into the type (which is indeed not a physical attribute of the type). Thus physical and
+ * I decided to put vehicle cost information into the type (which is indeed not a physical attribute of the type). Thus, physical and
* non-physical attributes are used. This is likely to be changed in the future.
*
* @author sschroeder
@@ -57,30 +57,13 @@ public static class Builder {
*
* The defaults are [fix=0.0][perDistanceUnit=1.0][perTimeUnit=0.0].
*
- * @param typeId
+ * @param typeId the type id
* @return a type builder
*/
public static Builder newInstance(Id typeId){
return new Builder(typeId);
}
- /**
- * Returns a new instance of builder initialized with the typeId and the values the given from existing CarrierVehicleType.
- *
- * Can be used for create a new, modified CarrierVehicleType basing on an existing one.
- * Values can be changed within the builder afterwards.
- *
- * @param carrierVehicleType
- * @param typeId
- * @return a type builder
- *
- * @deprecated Use {@link #newInstance(Id)} instead
- */
- @Deprecated(since = "sep'19", forRemoval = true)
- public static Builder newInstance(Id typeId, CarrierVehicleType carrierVehicleType){
- throw new RuntimeException("not implemented") ;
- }
-
private Builder(Id typeId){
this.delegate = VehicleUtils.getFactory().createVehicleType( typeId ) ;
}
@@ -88,9 +71,9 @@ private Builder(Id typeId){
/**
* Sets fixed costs of vehicle.
*
- *
By default it is 0.
- * @param fix
- * @return
+ *
By default, it is 0.
+ * @param fix fixed costs
+ * @return this builder
*/
public Builder setFixCost(double fix){
this.delegate.getCostInformation().setFixedCost( fix ) ;
@@ -100,10 +83,10 @@ public Builder setFixCost(double fix){
/**
* Sets costs per distance-unit.
*
- *
By default it is 1.
+ *
By default, it is 1.
*
- * @param perDistanceUnit
- * @return
+ * @param perDistanceUnit costs per distance-unit
+ * @return this builder
*/
public Builder setCostPerDistanceUnit(double perDistanceUnit){
this.delegate.getCostInformation().setCostsPerMeter( perDistanceUnit ) ;
@@ -113,10 +96,10 @@ public Builder setCostPerDistanceUnit(double perDistanceUnit){
/**
* Sets costs per time-unit.
*
- *
By default it is 0.
+ *
By default, it is 0.
*
- * @param perTimeUnit
- * @return
+ * @param perTimeUnit costs per time-unit
+ * @return this builder
*/
public Builder setCostPerTimeUnit(double perTimeUnit){
this.delegate.getCostInformation().setCostsPerSecond( perTimeUnit ) ;
@@ -126,8 +109,8 @@ public Builder setCostPerTimeUnit(double perTimeUnit){
/**
* Sets description.
*
- * @param description
- * @return this builder
+ * @param description the description
+ * @return this builder
*/
public Builder setDescription(String description){
this.delegate.setDescription( description ) ;
@@ -139,8 +122,8 @@ public Builder setDescription(String description){
*
*
By default, the capacity is 0.
*
- * @param capacity
- * @return this builder
+ * @param capacity the capacity of the vehicle-type
+ * @return this builder
*/
public Builder setCapacity(int capacity){
this.delegate.getCapacity().setOther( capacity );
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReader.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReader.java
index f10e5fc9bd5..b96a224b20e 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReader.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReader.java
@@ -21,6 +21,10 @@
package org.matsim.freight.carriers;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Map;
+import java.util.Stack;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -33,11 +37,6 @@
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Map;
-import java.util.Stack;
-
/**
* Reader reading carrierVehicleTypes from a xml-file.
*
@@ -79,7 +78,7 @@ public void readURL( URL url ){
reader.readURL(url);
} catch (Exception e) {
log.warn("### Exception: Message={}", e.getMessage());
- log.warn("### Exception: Cause={}", e.getCause());
+ log.warn("### Exception: Cause={}", e.getCause().toString());
log.warn("### Exception: Class={}", e.getClass());
if (e.getCause().getMessage().contains("cvc-elt.1.a")) { // "Cannot find the declaration of element" -> exception comes most probably because no validation information was found
log.warn("read with validation = true failed. Try it again without validation... url: {}", url.toString());
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java
index 92e2bacc590..f1cb66dac45 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java
@@ -21,6 +21,7 @@
package org.matsim.freight.carriers;
+import java.util.Stack;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -33,8 +34,6 @@
import org.matsim.vehicles.VehicleUtils;
import org.xml.sax.Attributes;
-import java.util.Stack;
-
class CarrierVehicleTypeReaderV1 extends MatsimXmlParser {
private static final Logger log = LogManager.getLogger(CarrierVehicleTypeReaderV1.class) ;
@@ -73,9 +72,8 @@ public void startTag( String name, Attributes attributes, Stack context
}
if(name.equals("engineInformation")){
EngineInformation engineInfo = this.currentType.getEngineInformation() ;
- VehicleUtils.setFuelConsumption(this.currentType, Double.parseDouble(attributes.getValue( "gasConsumption" )));
- engineInfo.setFuelConsumption( Double.parseDouble( attributes.getValue( "gasConsumption" ) ) );
- engineInfo.setFuelType( EngineInformation.FuelType.valueOf( attributes.getValue( "fuelType" ) ) );
+ VehicleUtils.setHbefaTechnology(engineInfo, attributes.getValue( "fuelType"));
+ VehicleUtils.setFuelConsumptionLitersPerMeter(engineInfo, Double.parseDouble(attributes.getValue( "gasConsumption" )));
}
if(name.equals("costInformation")){
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriter.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriter.java
index 4fbd8d68bbb..573f8441cae 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriter.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriter.java
@@ -21,6 +21,7 @@
package org.matsim.freight.carriers;
+import java.util.Map;
import org.matsim.api.core.v01.Id;
import org.matsim.core.api.internal.MatsimWriter;
import org.matsim.vehicles.MatsimVehicleWriter;
@@ -28,8 +29,6 @@
import org.matsim.vehicles.VehicleUtils;
import org.matsim.vehicles.Vehicles;
-import java.util.Map;
-
/**
* A writer that writes carriers and their plans in a xml-file.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriterV1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriterV1.java
deleted file mode 100644
index 823123e916a..00000000000
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriterV1.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * *********************************************************************** *
- * project: org.matsim.*
- * *********************************************************************** *
- * *
- * copyright : (C) 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.freight.carriers;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.matsim.core.utils.io.MatsimXmlWriter;
-import org.matsim.vehicles.CostInformation;
-import org.matsim.vehicles.EngineInformation;
-import org.matsim.vehicles.VehicleType;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-
-@Deprecated // only there if someone insists on writing V1
-public final class CarrierVehicleTypeWriterV1 extends MatsimXmlWriter {
-
- @SuppressWarnings("unused")
- private static final Logger logger = LogManager.getLogger(CarrierVehicleTypeWriter.class );
-
- private final CarrierVehicleTypes vehicleTypes;
-
-
- public CarrierVehicleTypeWriterV1(CarrierVehicleTypes carrierVehicleTypes) {
- super();
- this.vehicleTypes = carrierVehicleTypes;
- }
-
-
- public void write(String filename) {
- logger.info("write vehicle-types");
- try {
- openFile(filename);
- writeXmlHead();
- writeTypes(this.writer);
- close();
- logger.info("done");
- } catch ( IOException e) {
- e.printStackTrace();
- logger.error(e);
- System.exit(1);
- }
- }
-
- private void writeTypes( BufferedWriter writer )throws IOException {
- writer.write("\t\n");
- for( VehicleType type : vehicleTypes.getVehicleTypes().values()){
- writer.write("\t\t\n");
- writer.write("\t\t\t" + type.getDescription() + "\n");
- EngineInformation engineInformation = type.getEngineInformation();
- if(engineInformation != null && !engineInformation.getAttributes().isEmpty()) {
- writer.write("\t\t\t\n");
- }
- writer.write("\t\t\t" + type.getCapacity().getWeightInTons() + "\n" );
- CostInformation vehicleCostInformation = type.getCostInformation();
- if(vehicleCostInformation == null) throw new IllegalStateException("vehicleCostInformation is missing.");
- writer.write("\t\t\t\n");
- writer.write("\t\t\n");
- }
- writer.write("\t\n\n");
- }
-
-
-
-}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypes.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypes.java
index e9900cdc6cb..0250412938a 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypes.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypes.java
@@ -21,11 +21,10 @@
package org.matsim.freight.carriers;
-import org.matsim.api.core.v01.Id;
-import org.matsim.vehicles.VehicleType;
-
import java.util.HashMap;
import java.util.Map;
+import org.matsim.api.core.v01.Id;
+import org.matsim.vehicles.VehicleType;
/**
* VehicleTypeContainer mapping all vehicleTypes.
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/Carriers.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/Carriers.java
index f13f0bc56ae..4512008b9e8 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/Carriers.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/Carriers.java
@@ -21,13 +21,12 @@
package org.matsim.freight.carriers;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.matsim.api.core.v01.Id;
-
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.matsim.api.core.v01.Id;
/**
* A container that maps carriers.
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java
index 7c8e7220e3e..1b6a270e65e 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java
@@ -28,6 +28,10 @@
import com.graphhopper.jsprit.core.problem.job.Shipment;
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import com.graphhopper.jsprit.core.util.Solutions;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.management.InvalidAttributeValueException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -44,11 +48,6 @@
import org.matsim.vehicles.Vehicle;
import org.matsim.vehicles.VehicleType;
-import javax.management.InvalidAttributeValueException;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicInteger;
-
public class CarriersUtils {
static final String CARRIER_VEHICLE = "carrierVehicle";
@@ -235,7 +234,7 @@ public static void runJsprit(Scenario scenario, CarrierSelectionForSolution carr
continue;
}
}
- case solveForAllCarriersAndAddPLans -> {carrier.setSelectedPlan(null);} // Keep existing plan(s), but make them not selected.
+ case solveForAllCarriersAndAddPLans -> carrier.setSelectedPlan(null); // Keep existing plan(s), but make them not selected.
default -> throw new IllegalStateException("Unexpected value: " + carriersSolutionType);
}
carrierActivityCounterMap.put(carrier.getId(), carrierActivityCounterMap.getOrDefault(carrier.getId(), 0) + carrier.getServices().size());
@@ -338,7 +337,7 @@ public static Carriers getOrCreateCarriers(Scenario scenario) {
public static Carriers addOrGetCarriers(Scenario scenario) {
// I have separated getOrCreateCarriers and getCarriers, since when the
- // controler is started, it is better to fail if the carriers are not found.
+ // controller is started, it is better to fail if the carriers are not found.
// kai, oct'19
Carriers carriers = (Carriers) scenario.getScenarioElement(CARRIERS);
if (carriers == null) {
@@ -382,8 +381,6 @@ public static void loadCarriersAccordingToFreightConfig(Scenario scenario) {
Carriers carriers = addOrGetCarriers(scenario); // also registers with scenario
new CarrierPlanXmlReader(carriers, vehTypes).readURL(
IOUtils.extendUrl(scenario.getConfig().getContext(), freightCarriersConfigGroup.getCarriersFile()));
-
-// new CarrierVehicleTypeLoader( carriers ).loadVehicleTypes( vehTypes );
}
/**
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/FreightCarriersConfigGroup.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/FreightCarriersConfigGroup.java
index 1aed1a936f2..2474df19550 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/FreightCarriersConfigGroup.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/FreightCarriersConfigGroup.java
@@ -22,11 +22,10 @@
package org.matsim.freight.carriers;
import jakarta.validation.constraints.Positive;
-import org.matsim.core.config.ConfigGroup;
-import org.matsim.core.config.ReflectiveConfigGroup;
-
import java.net.URL;
import java.util.Map;
+import org.matsim.core.config.ConfigGroup;
+import org.matsim.core.config.ReflectiveConfigGroup;
public class FreightCarriersConfigGroup extends ReflectiveConfigGroup {
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/ScheduledTour.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/ScheduledTour.java
index 6a133ebc71c..84eeb1907a1 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/ScheduledTour.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/ScheduledTour.java
@@ -37,9 +37,9 @@ public class ScheduledTour {
*
Look at the builder. It might be easier to build a scheduled tour.
* You get the builder this way: ScheduledTour.Builder.newInstance(carrierVehicle).
*
- * @param tour
- * @param vehicle
- * @param departureTime
+ * @param tour The scheduled tour.
+ * @param vehicle The vehicle for the tour.
+ * @param departureTime The time when the vehicle starts the tour.
* @return a scheduledTour
* @see ScheduledTour
*/
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/TimeWindow.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/TimeWindow.java
index 8c5e9fc0d25..1eadbe077c0 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/TimeWindow.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/TimeWindow.java
@@ -24,7 +24,6 @@
import org.matsim.core.utils.misc.Time;
-
/**
* Q: What happens/should happen if the time window is not sufficient to unload, or
* the vehicle arrives after the time window?
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/Tour.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/Tour.java
index cb522e857fb..55f72325237 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/Tour.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/Tour.java
@@ -21,6 +21,7 @@
package org.matsim.freight.carriers;
+import java.util.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -30,8 +31,6 @@
import org.matsim.core.population.routes.NetworkRoute;
import org.matsim.core.population.routes.RouteUtils;
-import java.util.*;
-
/**
* This is a tour of a carrier which is a sequence of activities and legs.
*
@@ -62,21 +61,6 @@ public static class Builder {
private End end;
- /**
- * Returns a new tour builder.
- *
- * @deprecated
- * Please use {@link #newInstance(Id)} instead. kmt sep'22
- *
- *
- *
- * @return the builder including "unknown" as tourId
- */
- @Deprecated
- public static Builder newInstance(){
- return new Builder(Id.create("unknown", Tour.class));
- }
-
/**
* Returns a new tour builder.
* This now also includes an Id for this tour.
@@ -98,8 +82,8 @@ private Builder(Id tourId) {
*
*
Tour start should correspond to the locationId of the vehicle that runs the tour.
*
- * @param startLinkId
- * @return the builder again
+ * @param startLinkId linkId of the start location
+ * @return the builder again
*/
public Builder scheduleStart(Id startLinkId) {
scheduleStart(startLinkId, TimeWindow.newInstance(0.0, Double.MAX_VALUE));
@@ -121,7 +105,7 @@ public void scheduleEnd(Id endLinkId, TimeWindow timeWindow){
/**
* Schedules the end of the tour (in terms of locationId).
*
- * @param endLinkId
+ * @param endLinkId linkId of the end location
*/
public void scheduleEnd(Id endLinkId) {
scheduleEnd(endLinkId, TimeWindow.newInstance(0.0, Double.MAX_VALUE));
@@ -132,8 +116,8 @@ public void scheduleEnd(Id endLinkId) {
*
*
Consider that a leg follows an activity. Otherwise, an exception occurs.
*
- * @param leg
- * @throws IllegalStateException if leg is null or if previous element is not an activity.
+ * @param leg the leg to be added
+ * @throws IllegalStateException if leg is null or if previous element is not an activity.
*/
public Builder addLeg(Leg leg) {
Gbl.assertNotNull(leg);
@@ -156,9 +140,9 @@ public Leg createLeg(Route route, double dep_time, double transportTime) {
/**
* Inserts leg at the beginning of a tour.
*
- * @param leg
- * @return the builder
- * @throws IllegalStateException if leg is null
+ * @param leg the leg to be inserted
+ * @return the builder
+ * @throws IllegalStateException if leg is null
*/
@Deprecated
public Builder insertLegAtBeginning(Leg leg) {
@@ -170,9 +154,9 @@ public Builder insertLegAtBeginning(Leg leg) {
/**
* Schedules a pickup of the shipment right at the beginning of the tour.
*
- * @param shipment
- * @return the builder
- * @throws IllegalStateException if shipment is null or shipment has already been picked up.
+ * @param shipment the shipment to be picked up
+ * @return the builder
+ * @throws IllegalStateException if shipment is null or shipment has already been picked up.
*/
@Deprecated
public Builder schedulePickupAtBeginning(CarrierShipment shipment) {
@@ -218,8 +202,8 @@ private void assertLastElementIsLeg() {
/**
* Schedules a delivery of a shipment, i.e. adds a delivery activity to current tour.
*
- * @param shipment
- * @throws IllegalStateException if shipment is null or if shipment has not been picked up yet or if last element is not a leg.
+ * @param shipment the shipment to be delivered
+ * @throws IllegalStateException if shipment is null or if shipment has not been picked up yet or if last element is not a leg.
*/
public void scheduleDelivery(CarrierShipment shipment) {
Gbl.assertNotNull(shipment);
@@ -272,10 +256,10 @@ public Leg createLeg() {
/**
* Creates and returns a network route.
*
- * @param startLinkId
- * @param linkIds
- * @param endLinkId
- * @return NetworkRoute
+ * @param startLinkId start link id
+ * @param linkIds list of link ids that form the route
+ * @param endLinkId end link id
+ * @return NetworkRoute
* @see NetworkRoute
*/
public NetworkRoute createRoute(Id startLinkId, List> linkIds, Id endLinkId) {
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierLoadAnalysis.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierLoadAnalysis.java
index 7de5125e51e..760ce513035 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierLoadAnalysis.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierLoadAnalysis.java
@@ -21,6 +21,16 @@
package org.matsim.freight.carriers.analysis;
+import static org.matsim.freight.carriers.events.CarrierEventAttributes.ATTRIBUTE_CAPACITYDEMAND;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -34,17 +44,6 @@
import org.matsim.vehicles.VehicleType;
import org.matsim.vehicles.VehicleUtils;
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Comparator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.Map;
-
-import static org.matsim.freight.carriers.events.CarrierEventAttributes.ATTRIBUTE_CAPACITYDEMAND;
-
/**
* @author Kai Martins-Turner (kturner)
*/
@@ -52,7 +51,7 @@ public class CarrierLoadAnalysis implements CarrierShipmentPickupStartEventHandl
private static final Logger log = LogManager.getLogger(CarrierLoadAnalysis.class);
private final String delimiter;
- Carriers carriers;
+ final Carriers carriers;
private final Map, LinkedList> vehicle2Load = new LinkedHashMap<>();
@@ -96,6 +95,7 @@ void writeLoadPerVehicle(String analysisOutputDirectory, Scenario scenario) thro
//Write headline:
bw1.write(String.join(delimiter,"vehicleId",
+ "vehicleTypeId",
"capacity",
"maxLoad",
"load state during tour"));
@@ -104,12 +104,13 @@ void writeLoadPerVehicle(String analysisOutputDirectory, Scenario scenario) thro
for (Id vehicleId : vehicle2Load.keySet()) {
final LinkedList load = vehicle2Load.get(vehicleId);
- final Integer maxLoad = load.stream().max(Comparator.naturalOrder()).get();
+ final Integer maxLoad = load.stream().max(Comparator.naturalOrder()).orElseThrow();
final VehicleType vehicleType = VehicleUtils.findVehicle(vehicleId, scenario).getType();
final Double capacity = vehicleType.getCapacity().getOther();
bw1.write(vehicleId.toString());
+ bw1.write(delimiter + vehicleType.getId().toString());
bw1.write(delimiter + capacity);
bw1.write(delimiter + maxLoad);
bw1.write(delimiter + load);
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierPlanAnalysis.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierPlanAnalysis.java
index aeec93fd605..362dfaf8793 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierPlanAnalysis.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierPlanAnalysis.java
@@ -21,17 +21,16 @@
package org.matsim.freight.carriers.analysis;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.matsim.api.core.v01.Id;
-import org.matsim.core.utils.misc.Time;
-import org.matsim.freight.carriers.*;
-
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Path;
import java.util.TreeMap;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.matsim.api.core.v01.Id;
+import org.matsim.core.utils.misc.Time;
+import org.matsim.freight.carriers.*;
/**
* Some basic analysis / data collection for {@link Carriers}(files)
@@ -55,7 +54,7 @@ public class CarrierPlanAnalysis {
private static final Logger log = LogManager.getLogger(CarrierPlanAnalysis.class);
public final String delimiter;
- Carriers carriers;
+ final Carriers carriers;
public CarrierPlanAnalysis(String delimiter, Carriers carriers) {
this.delimiter = delimiter;
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java
index c62863465d5..6302c0df803 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java
@@ -21,6 +21,13 @@
package org.matsim.freight.carriers.analysis;
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.TreeMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -44,14 +51,6 @@
import org.matsim.vehicles.VehicleType;
import org.matsim.vehicles.VehicleUtils;
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.TreeMap;
-
/**
* @author Kai Martins-Turner (kturner)
*/
@@ -227,7 +226,7 @@ void writeTravelTimeAndDistancePerVehicle(String analysisOutputDirectory, Scenar
void writeTravelTimeAndDistancePerVehicleType(String analysisOutputDirectory, Scenario scenario) throws IOException {
log.info("Writing out Time & Distance & Costs ... perVehicleType");
- //----- All VehicleTypes in CarriervehicleTypes container. Used so that even unused vehTypes appear in the output
+ //----- All VehicleTypes in CarrierVehicleTypes container. Used so that even unused vehTypes appear in the output
TreeMap, VehicleType> vehicleTypesMap = new TreeMap<>(CarriersUtils.getCarrierVehicleTypes(scenario).getVehicleTypes());
//For the case that there are additional vehicle types found in the events.
for (VehicleType vehicleType : vehicleId2VehicleType.values()) {
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java
index 7269a70ac7f..0502ae2e1c4 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java
@@ -21,6 +21,9 @@
package org.matsim.freight.carriers.analysis;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Scenario;
@@ -36,10 +39,6 @@
import org.matsim.freight.carriers.FreightCarriersConfigGroup;
import org.matsim.freight.carriers.events.CarrierEventsReaders;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Path;
-
//import static org.matsim.application.ApplicationUtils.globFile;
@@ -83,11 +82,12 @@ public RunFreightAnalysisEventBased(String simOutputPath, String analysisOutputP
// the better version with the globFile method is not available since there is a circular dependency between the modules application and freight
- this.EVENTS_PATH = Path.of(simOutputPath).resolve("output_events.xml.gz").toString();
- String vehiclesPath = Path.of(simOutputPath).resolve("output_allVehicles.xml.gz").toString();
- String networkPath = Path.of(simOutputPath).resolve("output_network.xml.gz").toString();
- String carriersPath = Path.of(simOutputPath).resolve("output_carriers.xml.gz").toString();
- String carriersVehicleTypesPath = Path.of(simOutputPath).resolve("output_carriersVehicleTypes.xml.gz").toString();
+ final Path path = Path.of(simOutputPath);
+ this.EVENTS_PATH = path.resolve("output_events.xml.gz").toString();
+ String vehiclesPath = path.resolve("output_allVehicles.xml.gz").toString();
+ String networkPath = path.resolve("output_network.xml.gz").toString();
+ String carriersPath = path.resolve("output_carriers.xml.gz").toString();
+ String carriersVehicleTypesPath = path.resolve("output_carriersVehicleTypes.xml.gz").toString();
createScenarioForFreightAnalysis(vehiclesPath, networkPath, carriersPath, carriersVehicleTypesPath, globalCrs);
}
@@ -136,7 +136,7 @@ private void createScenarioForFreightAnalysis(String vehiclesPath, String networ
//freight settings
FreightCarriersConfigGroup freightCarriersConfigGroup = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class);
freightCarriersConfigGroup.setCarriersFile(carriersPath);
- freightCarriersConfigGroup.setCarriersVehicleTypesFile(carriersVehicleTypesPath.toString());
+ freightCarriersConfigGroup.setCarriersVehicleTypesFile(carriersVehicleTypesPath);
scenario = ScenarioUtils.loadScenario(config);
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgent.java
similarity index 99%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgent.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgent.java
index da31ae5637d..1afe10da4d0 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgent.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgent.java
@@ -19,8 +19,9 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
+import java.util.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -38,8 +39,6 @@
import org.matsim.vehicles.Vehicle;
import org.matsim.vehicles.VehicleUtils;
-import java.util.*;
-
/**
* This keeps track of the carrier during simulation.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgentTracker.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgentTracker.java
similarity index 99%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgentTracker.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgentTracker.java
index 09c4036d92f..f2bd02a204e 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgentTracker.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgentTracker.java
@@ -19,9 +19,10 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
import com.google.inject.Inject;
+import java.util.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -35,8 +36,6 @@
import org.matsim.freight.carriers.events.CarrierEventCreator;
import org.matsim.freight.carriers.events.CarrierEventCreatorUtils;
-import java.util.*;
-
/**
* This keeps track of all carrierAgents during simulation.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerListener.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerListener.java
similarity index 92%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerListener.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerListener.java
index f8a103bcbe5..136fecf4725 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerListener.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerListener.java
@@ -19,9 +19,10 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
import jakarta.inject.Inject;
+import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Scenario;
@@ -31,8 +32,6 @@
import org.matsim.core.controler.listener.ScoringListener;
import org.matsim.freight.carriers.CarriersUtils;
-import javax.annotation.Nullable;
-
/**
* Controls the workflow of the simulation.
*
@@ -46,13 +45,13 @@
* // not sure if this _should_ be public, but current LSP design makes this necessary. kai, sep'20
*/
-public class CarrierControlerListener implements ScoringListener, ReplanningListener {
+public class CarrierControllerListener implements ScoringListener, ReplanningListener {
// not sure if this _should_ be public, but current LSP design makes this necessary.
// It is done analogue to CarrierAgentTracker. kmt oct'22
@SuppressWarnings("unused")
- private static final Logger log = LogManager.getLogger( CarrierControlerListener.class ) ;
+ private static final Logger log = LogManager.getLogger( CarrierControllerListener.class ) ;
private final CarrierStrategyManager strategyManager;
private final CarrierAgentTracker carrierAgentTracker;
@@ -62,7 +61,8 @@ public class CarrierControlerListener implements ScoringListener, ReplanningList
/**
* Constructs a controller with a set of carriers, re-planning capabilities and scoring-functions.
*/
- @Inject CarrierControlerListener( @Nullable CarrierStrategyManager strategyManager, CarrierAgentTracker carrierAgentTracker ) {
+ @Inject
+ CarrierControllerListener(@Nullable CarrierStrategyManager strategyManager, CarrierAgentTracker carrierAgentTracker ) {
// The current default is bind( CarrierStrategyManager.class ).toProvider( () -> null );
this.strategyManager = strategyManager;
this.carrierAgentTracker = carrierAgentTracker;
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerUtils.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerUtils.java
similarity index 94%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerUtils.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerUtils.java
index fe19207bfcc..5d15a6821f0 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerUtils.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerUtils.java
@@ -19,7 +19,7 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
/**
* Utils class for (package-private) content of freight.carriers.controler - package;
@@ -27,7 +27,7 @@
* @author kturner
*
*/
-public class CarrierControlerUtils {
+public class CarrierControllerUtils {
public static CarrierStrategyManager createDefaultCarrierStrategyManager() {
return new CarrierStrategyManagerImpl();
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierDriverAgent.java
similarity index 99%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierDriverAgent.java
index c7f030f3457..50474242a92 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierDriverAgent.java
@@ -19,8 +19,13 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -41,12 +46,6 @@
import org.matsim.freight.carriers.events.CarrierEventCreator;
import org.matsim.vehicles.Vehicle;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
/**
* This keeps track of a scheduledTour during simulation and can thus be seen as the driver of the vehicle that runs the tour.
*
@@ -265,7 +264,7 @@ else if( index < elementsSize ){
* Basic event handler that collects the relation between vehicles and drivers.
* Necessary since link enter and leave events do not contain the driver anymore.
*
- * This is the vice-versa implementation of {@link org.matsim.core.events.algorithms.Vehicle2DriverEventHandler}.
+ * This is the vice versa implementation of {@link org.matsim.core.events.algorithms.Vehicle2DriverEventHandler}.
*
* In a first step only used internally. When needed more often, I have nothing against putting it more central.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierModule.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierModule.java
similarity index 97%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierModule.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierModule.java
index e2b9e1d8354..d95e1e7ac18 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierModule.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierModule.java
@@ -19,11 +19,12 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
+import java.util.List;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.events.Event;
import org.matsim.api.core.v01.population.Activity;
@@ -38,8 +39,6 @@
import org.matsim.core.scoring.ScoringFunction;
import org.matsim.freight.carriers.*;
-import java.util.List;
-
public final class CarrierModule extends AbstractModule {
@@ -49,8 +48,8 @@ public final class CarrierModule extends AbstractModule {
bind(Carriers.class).toProvider( new CarrierProvider() ).asEagerSingleton(); // needs to be eager since it is still scenario construction. kai, oct'19
// this is probably ok
- bind(CarrierControlerListener.class).in( Singleton.class );
- addControlerListenerBinding().to(CarrierControlerListener.class);
+ bind(CarrierControllerListener.class).in( Singleton.class );
+ addControlerListenerBinding().to(CarrierControllerListener.class);
bind(CarrierAgentTracker.class).in( Singleton.class );
addEventHandlerBinding().to( CarrierAgentTracker.class );
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierReRouteVehicles.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierReRouteVehicles.java
similarity index 95%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierReRouteVehicles.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierReRouteVehicles.java
index f59ba81c930..a2e32470a88 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierReRouteVehicles.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierReRouteVehicles.java
@@ -19,7 +19,7 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -77,8 +77,8 @@ private CarrierReRouteVehicles( LeastCostPathCalculator router, Network network,
/**
* Routes the carrierPlan in time and space.
*
- * @param carrierPlan
- * @throws IllegalStateException if carrierPlan is null.
+ * @param carrierPlan the carrierPlan to be routed.
+ * @throws IllegalStateException if carrierPlan is null.
* @see CarrierTimeAndSpaceTourRouter
*/
@Override
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierScoringFunctionFactory.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierScoringFunctionFactory.java
similarity index 96%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierScoringFunctionFactory.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierScoringFunctionFactory.java
index c73a41b3008..79338a48884 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierScoringFunctionFactory.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierScoringFunctionFactory.java
@@ -19,7 +19,7 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
import org.matsim.core.scoring.ScoringFunction;
import org.matsim.freight.carriers.Carrier;
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManager.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManager.java
similarity index 98%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManager.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManager.java
index f1d6d06e84e..8a7a3cfa263 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManager.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManager.java
@@ -19,7 +19,7 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
import com.google.inject.Provider;
import org.matsim.core.replanning.GenericStrategyManager;
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManagerImpl.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManagerImpl.java
similarity index 98%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManagerImpl.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManagerImpl.java
index 5bcad45b183..8a673af527b 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManagerImpl.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManagerImpl.java
@@ -19,8 +19,9 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
+import java.util.List;
import org.matsim.api.core.v01.population.HasPlansAndId;
import org.matsim.core.replanning.GenericPlanStrategy;
import org.matsim.core.replanning.GenericStrategyManager;
@@ -30,8 +31,6 @@
import org.matsim.freight.carriers.Carrier;
import org.matsim.freight.carriers.CarrierPlan;
-import java.util.List;
-
class CarrierStrategyManagerImpl implements CarrierStrategyManager{
final GenericStrategyManager delegate = new GenericStrategyManagerImpl<>();
@Override public void addStrategy( GenericPlanStrategy strategy, String subpopulation, double weight ){
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAllocationMutator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAllocationMutator.java
similarity index 98%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAllocationMutator.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAllocationMutator.java
index 3b7fc83af01..b38a96a8fd2 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAllocationMutator.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAllocationMutator.java
@@ -18,17 +18,16 @@
* ***********************************************************************
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
+import java.util.ArrayList;
+import java.util.Collection;
import org.matsim.core.gbl.MatsimRandom;
import org.matsim.core.replanning.ReplanningContext;
import org.matsim.core.replanning.modules.GenericPlanStrategyModule;
import org.matsim.freight.carriers.CarrierPlan;
import org.matsim.freight.carriers.ScheduledTour;
-import java.util.ArrayList;
-import java.util.Collection;
-
/**
* @author nagel
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAndSpaceTourRouter.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAndSpaceTourRouter.java
similarity index 96%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAndSpaceTourRouter.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAndSpaceTourRouter.java
index 0a6a7399c9f..b02c5938e42 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAndSpaceTourRouter.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAndSpaceTourRouter.java
@@ -19,8 +19,10 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
+import java.util.ArrayList;
+import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -41,9 +43,6 @@
import org.matsim.vehicles.Vehicle;
import org.matsim.vehicles.VehicleType;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* Router routing scheduledTours.
*
@@ -94,9 +93,9 @@ public Attributes getAttributes() {
/**
* Constructs the timeAndSpaceRouter with a leastCostPathCalculator, network and travelTime.
- * @param router
- * @param network
- * @param travelTime
+ * @param router the leastCostPathCalculator
+ * @param network the network
+ * @param travelTime the travelTime
* @see LeastCostPathCalculator, Network, TravelTime
*/
public CarrierTimeAndSpaceTourRouter( LeastCostPathCalculator router, Network network, TravelTime travelTime ) {
@@ -111,7 +110,7 @@ public CarrierTimeAndSpaceTourRouter( LeastCostPathCalculator router, Network ne
*
*
Uses a leastCostPathCalculator to calculate a route/path from one activity to another. It starts at the departureTime of
* the scheduledTour and determines activity arrival and departure times considering activities time-windows.
- * @param tour
+ * @param tour the scheduledTour to be routed.
*/
public void route(ScheduledTour tour) {
MatsimVehicleAdapter matsimVehicle = new MatsimVehicleAdapter(tour.getVehicle());
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierVehicleReRouter.java
similarity index 98%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierVehicleReRouter.java
index cd03cb5fd94..1d9a02d74d0 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierVehicleReRouter.java
@@ -19,7 +19,7 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
@@ -35,6 +35,7 @@
import com.graphhopper.jsprit.io.algorithm.AlgorithmConfig;
import com.graphhopper.jsprit.io.algorithm.AlgorithmConfigXmlReader;
import com.graphhopper.jsprit.io.algorithm.VehicleRoutingAlgorithms;
+import java.util.Collection;
import org.matsim.api.core.v01.network.Network;
import org.matsim.contrib.roadpricing.RoadPricingScheme;
import org.matsim.core.replanning.ReplanningContext;
@@ -45,9 +46,6 @@
import org.matsim.freight.carriers.CarrierVehicleTypes;
import org.matsim.freight.carriers.jsprit.MatsimJspritFactory;
import org.matsim.freight.carriers.jsprit.NetworkBasedTransportCosts;
-import org.matsim.freight.carriers.jsprit.VehicleTypeDependentRoadPricingCalculator;
-
-import java.util.Collection;
class CarrierVehicleReRouter implements GenericPlanStrategyModule{
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightActivity.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightActivity.java
similarity index 98%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightActivity.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightActivity.java
index 42cd58ae587..ee3f0e65afc 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightActivity.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightActivity.java
@@ -19,7 +19,7 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
import org.matsim.api.core.v01.Coord;
import org.matsim.api.core.v01.Id;
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightAgentSource.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightAgentSource.java
similarity index 98%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightAgentSource.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightAgentSource.java
index f5613f1a961..c1550c49701 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightAgentSource.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightAgentSource.java
@@ -19,9 +19,11 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
import com.google.inject.Inject;
+import java.util.ArrayList;
+import java.util.Collection;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -35,8 +37,6 @@
import org.matsim.vehicles.Vehicle;
import org.matsim.vehicles.VehicleUtils;
-import java.util.ArrayList;
-import java.util.Collection;
/**
* Created by IntelliJ IDEA. User: zilske Date: 10/31/11 Time: 5:59 PM To change
* this template use File | Settings | File Templates.
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/WithinDayActivityReScheduling.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/WithinDayActivityReScheduling.java
similarity index 98%
rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/WithinDayActivityReScheduling.java
rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/WithinDayActivityReScheduling.java
index 285939a7174..0e4cbebfa6d 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/WithinDayActivityReScheduling.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/WithinDayActivityReScheduling.java
@@ -19,9 +19,12 @@
*
*/
-package org.matsim.freight.carriers.controler;
+package org.matsim.freight.carriers.controller;
import com.google.inject.Inject;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -38,10 +41,6 @@
import org.matsim.freight.carriers.Tour.Start;
import org.matsim.freight.carriers.Tour.TourActivity;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
/*
* Physically enforces beginnings of time windows for freight activities, i.e. freight agents
* wait before closed doors until they can deliver / pick up their goods.
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/AbstractCarrierEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/AbstractCarrierEvent.java
index 1380144b9b4..497bc3dca7e 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/AbstractCarrierEvent.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/AbstractCarrierEvent.java
@@ -21,6 +21,7 @@
package org.matsim.freight.carriers.events;
+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.HasLinkId;
@@ -29,8 +30,6 @@
import org.matsim.freight.carriers.Carrier;
import org.matsim.vehicles.Vehicle;
-import java.util.Map;
-
/**
* A general freight event contains the information (= {@link Id}) of the
* - {@link Carrier}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierEventsReaders.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierEventsReaders.java
index 23c9176a0ff..ee06d87ba6d 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierEventsReaders.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierEventsReaders.java
@@ -21,11 +21,10 @@
package org.matsim.freight.carriers.events;
+import java.util.Map;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.events.MatsimEventsReader;
-import java.util.Map;
-
/**
* Creates an {@link MatsimEventsReader} that also handles the carrier specific events.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceEndEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceEndEvent.java
index bfd8ad7d68c..f806248471c 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceEndEvent.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceEndEvent.java
@@ -21,6 +21,7 @@
package org.matsim.freight.carriers.events;
+import java.util.Map;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.GenericEvent;
import org.matsim.api.core.v01.network.Link;
@@ -28,8 +29,6 @@
import org.matsim.freight.carriers.CarrierService;
import org.matsim.vehicles.Vehicle;
-import java.util.Map;
-
/**
* An event, that informs that a Freight {@link CarrierService} activity has ended.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceStartEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceStartEvent.java
index 1b866d5ce5b..d1b4d816ace 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceStartEvent.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceStartEvent.java
@@ -21,6 +21,7 @@
package org.matsim.freight.carriers.events;
+import java.util.Map;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.GenericEvent;
import org.matsim.api.core.v01.network.Link;
@@ -28,8 +29,6 @@
import org.matsim.freight.carriers.CarrierService;
import org.matsim.vehicles.Vehicle;
-import java.util.Map;
-
/**
* An event, that informs that a Freight {@link CarrierService} activity has started.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java
index c02717031fa..8f60260a067 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java
@@ -21,6 +21,7 @@
package org.matsim.freight.carriers.events;
+import java.util.Map;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.GenericEvent;
import org.matsim.api.core.v01.network.Link;
@@ -28,8 +29,6 @@
import org.matsim.freight.carriers.CarrierShipment;
import org.matsim.vehicles.Vehicle;
-import java.util.Map;
-
/**
* An event, that informs that a Freight {@link CarrierShipment} delivery-activity has ended.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java
index 43cf21fc752..a30035968c0 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java
@@ -21,6 +21,9 @@
package org.matsim.freight.carriers.events;
+import static org.matsim.freight.carriers.events.CarrierEventAttributes.*;
+
+import java.util.Map;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.GenericEvent;
import org.matsim.api.core.v01.network.Link;
@@ -28,10 +31,6 @@
import org.matsim.freight.carriers.CarrierShipment;
import org.matsim.vehicles.Vehicle;
-import java.util.Map;
-
-import static org.matsim.freight.carriers.events.CarrierEventAttributes.*;
-
/**
* An event, that informs that a Freight {@link CarrierShipment} delivery-activity has started.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupEndEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupEndEvent.java
index 90e1fd137b7..4316e6f4dfe 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupEndEvent.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupEndEvent.java
@@ -21,6 +21,9 @@
package org.matsim.freight.carriers.events;
+import static org.matsim.freight.carriers.events.CarrierEventAttributes.*;
+
+import java.util.Map;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.GenericEvent;
import org.matsim.api.core.v01.network.Link;
@@ -28,10 +31,6 @@
import org.matsim.freight.carriers.CarrierShipment;
import org.matsim.vehicles.Vehicle;
-import java.util.Map;
-
-import static org.matsim.freight.carriers.events.CarrierEventAttributes.*;
-
/**
* An event, that informs that a Freight {@link CarrierShipment} pickup-activity has ended.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupStartEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupStartEvent.java
index ab36e627190..fe851a10138 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupStartEvent.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupStartEvent.java
@@ -21,6 +21,7 @@
package org.matsim.freight.carriers.events;
+import java.util.Map;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.GenericEvent;
import org.matsim.api.core.v01.network.Link;
@@ -28,8 +29,6 @@
import org.matsim.freight.carriers.CarrierShipment;
import org.matsim.vehicles.Vehicle;
-import java.util.Map;
-
/**
* An event, that informs that a Freight {@link CarrierShipment} pickup-activity has started.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourEndEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourEndEvent.java
index 82e133f2166..1c0e3579312 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourEndEvent.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourEndEvent.java
@@ -21,6 +21,7 @@
package org.matsim.freight.carriers.events;
+import java.util.Map;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.GenericEvent;
import org.matsim.api.core.v01.network.Link;
@@ -28,8 +29,6 @@
import org.matsim.freight.carriers.Tour;
import org.matsim.vehicles.Vehicle;
-import java.util.Map;
-
/**
* An event, that informs when a Freight {@link Tour} has ended.
* There are NO specific information of the tour given, because the {@link Tour} is determined by the {@link Vehicle} and its {@link Carrier}.
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEvent.java
index 9c64e8213b2..aa4ff9f1084 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEvent.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEvent.java
@@ -21,6 +21,9 @@
package org.matsim.freight.carriers.events;
+import static org.matsim.freight.carriers.events.CarrierEventAttributes.ATTRIBUTE_TOUR_ID;
+
+import java.util.Map;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.GenericEvent;
import org.matsim.api.core.v01.network.Link;
@@ -28,10 +31,6 @@
import org.matsim.freight.carriers.Tour;
import org.matsim.vehicles.Vehicle;
-import java.util.Map;
-
-import static org.matsim.freight.carriers.events.CarrierEventAttributes.ATTRIBUTE_TOUR_ID;
-
/**
* An event, that informs when a Freight {@link Tour} has started.
* There are NO specific information of the tour given, because the {@link Tour} is determined by the {@link Vehicle} and its {@link Carrier}.
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEventCreator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEventCreator.java
index aacf3e6ef12..6a29c022aae 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEventCreator.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEventCreator.java
@@ -21,6 +21,7 @@
package org.matsim.freight.carriers.events;
+import java.util.TreeMap;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.ActivityEndEvent;
import org.matsim.api.core.v01.events.Event;
@@ -32,8 +33,6 @@
import org.matsim.freight.carriers.ScheduledTour;
import org.matsim.vehicles.Vehicle;
-import java.util.TreeMap;
-
/*package-private*/ final class CarrierTourStartEventCreator implements CarrierEventCreator {
final TreeMap, ActivityEndEvent> endEventMap = new TreeMap<>();
@@ -69,9 +68,9 @@ public Event createEvent(Event event, Carrier carrier, Activity activity, Schedu
/**
* Creating the FreightTourStartsEvent
*
- * @param personId
- * @param carrier
- * @param scheduledTour
+ * @param personId id of the driver (person)
+ * @param carrier the carrier
+ * @param scheduledTour the scheduledTour
* @return CarrierTourStartEvent
*/
private CarrierTourStartEvent createFreightTourStartsEvent(Id personId, Carrier carrier, ScheduledTour scheduledTour) {
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceStartEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceStartEventHandler.java
index a8ea55c13e8..362974eae3f 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceStartEventHandler.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceStartEventHandler.java
@@ -24,7 +24,6 @@
import org.matsim.core.events.handler.EventHandler;
import org.matsim.freight.carriers.events.CarrierServiceStartEvent;
-
public interface CarrierServiceStartEventHandler extends EventHandler {
void handleEvent( CarrierServiceStartEvent event );
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourEndEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourEndEventHandler.java
index 2d30ce4d70c..d14a5d285cf 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourEndEventHandler.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourEndEventHandler.java
@@ -24,7 +24,6 @@
import org.matsim.core.events.handler.EventHandler;
import org.matsim.freight.carriers.events.CarrierTourEndEvent;
-
public interface CarrierTourEndEventHandler extends EventHandler {
void handleEvent( CarrierTourEndEvent event );
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourStartEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourStartEventHandler.java
index 5f4b26ce4bb..3a7997cc9ef 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourStartEventHandler.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourStartEventHandler.java
@@ -24,7 +24,6 @@
import org.matsim.core.events.handler.EventHandler;
import org.matsim.freight.carriers.events.CarrierTourStartEvent;
-
public interface CarrierTourStartEventHandler extends EventHandler {
void handleEvent( CarrierTourStartEvent event );
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java
index bc9236decbf..0d5b9902f57 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java
@@ -20,15 +20,14 @@
*/
package org.matsim.freight.carriers.events.eventhandler;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.matsim.api.core.v01.Id;
import org.matsim.freight.carriers.Carrier;
import org.matsim.freight.carriers.events.CarrierTourEndEvent;
import org.matsim.freight.carriers.events.CarrierTourStartEvent;
import org.matsim.vehicles.Vehicle;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
/**
* Basic event handler that collects the relation between vehicles and carrier.
* Necessary since link enter and leave events do not contain any information of the carrier.
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/DistanceConstraint.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/DistanceConstraint.java
index 068c70506cd..8615e0b3d75 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/DistanceConstraint.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/DistanceConstraint.java
@@ -94,7 +94,7 @@ public ConstraintsStatus fulfilled(JobInsertionContext context, TourActivity pre
consumptionPerMeter = VehicleUtils
.getEnergyConsumptionKWhPerMeter(vehicleTypeOfNewVehicle.getEngineInformation());
else
- consumptionPerMeter = VehicleUtils.getFuelConsumption(vehicleTypeOfNewVehicle);
+ consumptionPerMeter = VehicleUtils.getFuelConsumptionLitersPerMeter(vehicleTypeOfNewVehicle.getEngineInformation());
double routeDistance = calculateRouteDistance(context, newVehicle);
double routeConsumption = routeDistance * (consumptionPerMeter);
@@ -212,9 +212,9 @@ private double calculateRouteDistance(JobInsertionContext context, Vehicle newVe
* directly behind the new pickup. This method gives back the minimal distance
* of this three options.
*
- * @param context
- * @param newInvestigatedPickup
- * @param nextAct
+ * @param context the context of the job insertion
+ * @param newInvestigatedPickup the new pickup which should be added to the tour
+ * @param nextAct the next activity after the new pickup
* @return minimal distance of the associated delivery
*/
private double findMinimalAdditionalDistance(JobInsertionContext context, TourActivity newInvestigatedPickup,
@@ -283,8 +283,8 @@ private double findMinimalAdditionalDistance(JobInsertionContext context, TourAc
/**
* Checks if the find possible distance is the minimal one.
*
- * @param minimalAdditionalDistance
- * @param possibleAdditionalDistance
+ * @param minimalAdditionalDistance the minimal additional distance
+ * @param possibleAdditionalDistance the possible additional distance
* @return the minimal transport distance
*/
private double findMinimalDistance(double minimalAdditionalDistance, double possibleAdditionalDistance) {
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/MatsimJspritFactory.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/MatsimJspritFactory.java
index 8710e50c7ba..00cf9347716 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/MatsimJspritFactory.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/MatsimJspritFactory.java
@@ -45,6 +45,10 @@
import com.graphhopper.jsprit.io.algorithm.AlgorithmConfig;
import com.graphhopper.jsprit.io.algorithm.AlgorithmConfigXmlReader;
import com.graphhopper.jsprit.io.algorithm.VehicleRoutingAlgorithms;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Coord;
@@ -57,11 +61,6 @@
import org.matsim.vehicles.VehicleType;
import org.matsim.vehicles.VehicleUtils;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
/**
* A factory that creates matsim-object from jsprit
* (...) and vice versa.
@@ -686,9 +685,6 @@ public static Carrier createCarrier(String carrierId, VehicleRoutingProblem vrp)
capabilityBuilder.setFleetSize(CarrierCapabilities.FleetSize.FINITE);
} else
capabilityBuilder.setFleetSize(CarrierCapabilities.FleetSize.INFINITE);
- for (com.graphhopper.jsprit.core.problem.vehicle.VehicleType type : vrp.getTypes()) {
- capabilityBuilder.addType(createMatsimVehicleType(type));
- }
for (Vehicle vehicle : vrp.getVehicles()) {
capabilityBuilder.addVehicle(createCarrierVehicle(vehicle));
}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java
index e6d8e1a0e45..c97243d50fe 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java
@@ -26,6 +26,8 @@
import com.graphhopper.jsprit.core.problem.driver.Driver;
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
@@ -45,9 +47,6 @@
import org.matsim.vehicles.VehicleType;
import org.matsim.vehicles.VehicleUtils;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
/**
* This calculates transport-times, transport-costs and the distance to cover
* the distance from one location to another. It calculates these values based
@@ -57,7 +56,7 @@
*
*
* It can be used with multiple threads. Note that each thread gets its own
- * leastCostPathCalculator. It is created only once and cached afterwards. Thus,
+ * leastCostPathCalculator. It is created only once and cached afterward. Thus,
* it requires a threadSafe leastCostPathCalculatorFactory (the calculator
* itself does not need to be thread-safe).
*
@@ -85,8 +84,6 @@
*/
public class NetworkBasedTransportCosts implements VRPTransportCosts {
- private final RoadPricingScheme roadPricingScheme;
-
public interface InternalLeastCostPathCalculatorListener {
void startCalculation(long routerId);
@@ -497,7 +494,7 @@ public Builder setRoadPricingScheme( RoadPricingScheme roadPricingScheme) {
*
* Comments:
*
- *
By default this will take free speed travel times.
+ *
By default, this will take free speed travel times.
*
yyyy These free speed travel times do not take the time-dependent
* network into account. kai, jan'14
*
Either can be changed with builder.setTravelTime(...) or with
@@ -578,7 +575,6 @@ private NetworkBasedTransportCosts(Builder builder) {
this.travelTime = builder.travelTime;
this.network = builder.network;
this.leastCostPathCalculatorFactory = builder.leastCostPathCalculatorFactory;
- this.roadPricingScheme = builder.roadPricingScheme;
this.timeSliceWidth = builder.timeSliceWidth;
this.defaultTypeId = builder.defaultTypeId;
this.ttMemorizedCounter = new Counter("#TransportCostValues cached ");
@@ -658,12 +654,12 @@ private VehicleImpl getDefaultVehicle(Location fromId) {
private void informEndCalc() {
for (InternalLeastCostPathCalculatorListener l : listeners)
- l.endCalculation(Thread.currentThread().getId());
+ l.endCalculation(Thread.currentThread().threadId());
}
private void informStartCalc() {
for (InternalLeastCostPathCalculatorListener l : listeners)
- l.startCalculation(Thread.currentThread().getId());
+ l.startCalculation(Thread.currentThread().threadId());
}
/**
@@ -853,11 +849,11 @@ public LeastCostPathCalculator getRouter() {
}
private LeastCostPathCalculator createLeastCostPathCalculator() {
- LeastCostPathCalculator router = routerCache.get(Thread.currentThread().getId());
+ LeastCostPathCalculator router = routerCache.get(Thread.currentThread().threadId());
if (router == null) {
LeastCostPathCalculator newRouter = leastCostPathCalculatorFactory.createPathCalculator(network,
travelDisutility, travelTime);
- router = routerCache.putIfAbsent(Thread.currentThread().getId(), newRouter);
+ router = routerCache.putIfAbsent(Thread.currentThread().threadId(), newRouter);
if (router == null) {
router = newRouter;
}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsFactory.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsFactory.java
index 6a0be5414f0..558ec523a81 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsFactory.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsFactory.java
@@ -21,19 +21,18 @@
package org.matsim.freight.carriers.jsprit;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.router.util.TravelTime;
-import org.matsim.freight.carriers.FreightCarriersConfigGroup;
import org.matsim.freight.carriers.Carriers;
+import org.matsim.freight.carriers.FreightCarriersConfigGroup;
import org.matsim.vehicles.VehicleType;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
/**
* @author steffenaxer
*/
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkRouter.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkRouter.java
index 7dac94a1c8c..2388801503b 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkRouter.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkRouter.java
@@ -22,7 +22,7 @@
import org.matsim.freight.carriers.CarrierPlan;
import org.matsim.freight.carriers.ScheduledTour;
-import org.matsim.freight.carriers.controler.CarrierTimeAndSpaceTourRouter;
+import org.matsim.freight.carriers.controller.CarrierTimeAndSpaceTourRouter;
/**
* Router that routes {@link CarrierPlan}.
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VRPTransportCosts.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VRPTransportCosts.java
index d831d329fc9..240c16adf7c 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VRPTransportCosts.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VRPTransportCosts.java
@@ -27,7 +27,7 @@
import org.matsim.core.router.util.TravelTime;
/**
- * @author: Steffen Axer
+ * @author Steffen Axer
*/
public interface VRPTransportCosts extends VehicleRoutingTransportCosts {
LeastCostPathCalculator getRouter();
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java
index 6175780ab9a..7c9541f5777 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java
@@ -21,14 +21,12 @@
package org.matsim.freight.carriers.jsprit;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleType;
+import java.util.*;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.contrib.roadpricing.RoadPricingScheme;
import org.matsim.contrib.roadpricing.RoadPricingSchemeImpl.Cost;
-import java.util.*;
-
-
/**
* Calculator that manages and calculates vehicle type dependent road pricing schemas.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/CarrierScoreStats.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/CarrierScoreStats.java
index 84556de1a14..8578c0a91b9 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/CarrierScoreStats.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/CarrierScoreStats.java
@@ -21,6 +21,10 @@
package org.matsim.freight.carriers.usecases.analysis;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Locale;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.core.controler.events.IterationEndsEvent;
@@ -35,11 +39,6 @@
import org.matsim.freight.carriers.CarrierPlan;
import org.matsim.freight.carriers.Carriers;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.util.Locale;
-
/**
* As you can see, it is basically a copy of {@link org.matsim.analysis.ScoreStatsControlerListener}. However, it is modified to score {@link Carrier}s
* rather than Persons. (Oct'13, schroeder)
@@ -81,7 +80,6 @@ public class CarrierScoreStats implements StartupListener, IterationEndsListener
*
* @param filename including the path, excluding the file type extension
* @param createPNG true if in every iteration, the scorestats should be visualized in a graph and written to disk.
- * @throws UncheckedIOException
*/
public CarrierScoreStats(Carriers carriers, final String filename, final boolean createPNG) throws UncheckedIOException {
this.carriers = carriers;
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/LegHistogram.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/LegHistogram.java
index fff393eee93..2a1400a6564 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/LegHistogram.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/LegHistogram.java
@@ -22,6 +22,14 @@
package org.matsim.freight.carriers.usecases.analysis;
import jakarta.inject.Inject;
+import java.awt.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
@@ -42,15 +50,6 @@
import org.matsim.api.core.v01.population.Population;
import org.matsim.core.utils.misc.Time;
-import java.awt.*;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
/**
* It is a copy of {@link org.matsim.analysis.LegHistogram}. It is modified to include or exclude persons.
*
@@ -392,8 +391,7 @@ private int getBinIndex(final double time) {
private ModeData getDataForMode(final String legMode) {
// +1 for all times out of our range
- ModeData modeData = this.data.computeIfAbsent(legMode, k -> new ModeData(this.nofBins + 1));
- return modeData;
+ return this.data.computeIfAbsent(legMode, k -> new ModeData(this.nofBins + 1));
}
private static class ModeData {
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/CarrierScoringFunctionFactoryImpl.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/CarrierScoringFunctionFactoryImpl.java
index 759b3da5890..8b61af1efdc 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/CarrierScoringFunctionFactoryImpl.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/CarrierScoringFunctionFactoryImpl.java
@@ -22,6 +22,8 @@
package org.matsim.freight.carriers.usecases.chessboard;
import com.google.inject.Inject;
+import java.util.HashSet;
+import java.util.Set;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
@@ -36,14 +38,11 @@
import org.matsim.core.scoring.ScoringFunction;
import org.matsim.core.scoring.SumScoringFunction;
import org.matsim.freight.carriers.*;
-import org.matsim.freight.carriers.controler.CarrierScoringFunctionFactory;
-import org.matsim.freight.carriers.controler.FreightActivity;
+import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory;
+import org.matsim.freight.carriers.controller.FreightActivity;
import org.matsim.freight.carriers.jsprit.VehicleTypeDependentRoadPricingCalculator;
import org.matsim.vehicles.Vehicle;
-import java.util.HashSet;
-import java.util.Set;
-
/**
* Defines example carrier scoring function (factory).
*
@@ -187,9 +186,7 @@ public void handleLeg(Leg leg) {
Id vehicleId = nRoute.getVehicleId();
CarrierVehicle vehicle = CarriersUtils.getCarrierVehicle(carrier, vehicleId);
Gbl.assertNotNull(vehicle);
- if(!employedVehicles.contains(vehicle)){
- employedVehicles.add(vehicle);
- }
+ employedVehicles.add(vehicle);
double distance = 0.0;
if(leg.getRoute() instanceof NetworkRoute){
Link startLink = network.getLinks().get(leg.getRoute().getStartLinkId());
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/FreightScenarioCreator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/FreightScenarioCreator.java
index c258d01e703..3d291829b77 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/FreightScenarioCreator.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/FreightScenarioCreator.java
@@ -21,6 +21,9 @@
package org.matsim.freight.carriers.usecases.chessboard;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.network.Link;
@@ -34,10 +37,6 @@
import org.matsim.vehicles.VehicleType;
import org.matsim.vehicles.VehicleUtils;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
/**
* Creates chessboard freight scenario.
*
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InitialCarrierPlanCreator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InitialCarrierPlanCreator.java
index fb2979e4be1..72c6d90df96 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InitialCarrierPlanCreator.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InitialCarrierPlanCreator.java
@@ -34,6 +34,7 @@
import com.graphhopper.jsprit.io.algorithm.AlgorithmConfig;
import com.graphhopper.jsprit.io.algorithm.AlgorithmConfigXmlReader;
import com.graphhopper.jsprit.io.algorithm.VehicleRoutingAlgorithms;
+import java.util.Collection;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.network.Network;
import org.matsim.core.config.Config;
@@ -44,8 +45,6 @@
import org.matsim.freight.carriers.jsprit.NetworkBasedTransportCosts;
import org.matsim.freight.carriers.jsprit.NetworkRouter;
-import java.util.Collection;
-
final class InitialCarrierPlanCreator {
private final Network network;
@@ -166,8 +165,6 @@ public static void main(String[] args) {
Carriers carriers = new Carriers();
new CarrierPlanXmlReader(carriers, types ).readFile("input/usecases/chessboard/freight/carrierPlansWithoutRoutes_10minTW.xml" );
- new CarrierVehicleTypeLoader(carriers).loadVehicleTypes(types);
-
for(Carrier carrier : carriers.getCarriers().values()){
CarrierPlan plan = new InitialCarrierPlanCreator(scenario.getNetwork()).createPlan(carrier);
carrier.addPlan(plan);
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InnerOuterCityScenarioCreator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InnerOuterCityScenarioCreator.java
index d5b48f1df69..789a5681a46 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InnerOuterCityScenarioCreator.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InnerOuterCityScenarioCreator.java
@@ -21,12 +21,11 @@
package org.matsim.freight.carriers.usecases.chessboard;
-import org.matsim.api.core.v01.Id;
-import org.matsim.api.core.v01.network.Link;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import org.matsim.api.core.v01.Id;
+import org.matsim.api.core.v01.network.Link;
final class InnerOuterCityScenarioCreator {
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PassengerScenarioCreator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PassengerScenarioCreator.java
index 3a742ced5e6..1060931835e 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PassengerScenarioCreator.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PassengerScenarioCreator.java
@@ -21,6 +21,8 @@
package org.matsim.freight.carriers.usecases.chessboard;
+import java.util.ArrayList;
+import java.util.List;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.TransportMode;
@@ -36,9 +38,6 @@
import org.matsim.core.router.util.LeastCostPathCalculator.Path;
import org.matsim.core.scenario.ScenarioUtils;
-import java.util.ArrayList;
-import java.util.List;
-
final class PassengerScenarioCreator {
static int agentCounter = 1;
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PlotPlans.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PlotPlans.java
index 838ac5463ae..9e615dda9f4 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PlotPlans.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PlotPlans.java
@@ -47,8 +47,6 @@ public static void main(String[] args) {
// new CarrierPlanXmlReader(carriers).read("input/usecases/chessboard/freight/singleCarrierTwentyActivities.xml");
new CarrierPlanXmlReader(carriers, types ).readFile("output/ITERS/it.140/140.carrierPlans.xml" );
- new CarrierVehicleTypeLoader(carriers).loadVehicleTypes(types);
-
final Carrier carrier = carriers.getCarriers().get(Id.create("carrier1",Carrier.class));
VehicleRoutingProblem.Builder vrpBuilder = MatsimJspritFactory.createRoutingProblemBuilder(carrier, scenario.getNetwork());
VehicleRoutingProblem vrp = vrpBuilder.build();
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboard.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboard.java
index e8f7887cfea..ff62264a468 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboard.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboard.java
@@ -23,14 +23,13 @@
import com.google.inject.Provider;
import jakarta.inject.Inject;
+import java.util.Map;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.api.core.v01.network.Network;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
-import org.matsim.core.controler.AbstractModule;
-import org.matsim.core.controler.Controler;
-import org.matsim.core.controler.OutputDirectoryHierarchy;
+import org.matsim.core.controler.*;
import org.matsim.core.controler.events.IterationEndsEvent;
import org.matsim.core.controler.listener.IterationEndsListener;
import org.matsim.core.replanning.GenericPlanStrategyImpl;
@@ -46,12 +45,10 @@
import org.matsim.core.utils.io.IOUtils;
import org.matsim.examples.ExamplesUtils;
import org.matsim.freight.carriers.*;
-import org.matsim.freight.carriers.controler.*;
+import org.matsim.freight.carriers.controller.*;
import org.matsim.freight.carriers.usecases.analysis.CarrierScoreStats;
import org.matsim.freight.carriers.usecases.analysis.LegHistogram;
-import java.util.Map;
-
public final class RunChessboard {
public static void main(String[] args){
@@ -74,11 +71,11 @@ public static void main(String[] args){
Carriers carriers = CarriersUtils.addOrGetCarriers( scenario );
CarrierVehicleTypes types = CarriersUtils.getCarrierVehicleTypes( scenario );
- Controler controler = new Controler( scenario);
+ Controller controller = ControllerUtils.createController( scenario );
- controler.addOverridingModule(new CarrierModule() );
+ controller.addOverridingModule(new CarrierModule() );
- controler.addOverridingModule(new AbstractModule() {
+ controller.addOverridingModule(new AbstractModule() {
@Override
public void install() {
@@ -113,7 +110,7 @@ public void install() {
}
});
- controler.run();
+ controller.run();
}
@@ -139,7 +136,7 @@ private static class MyCarrierPlanStrategyManagerProvider implements Provider strategy = new GenericPlanStrategyImpl<>( new ExpBetaPlanChanger.Factory().build() );
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunPassengerAlongWithCarriers.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunPassengerAlongWithCarriers.java
index 40a49ecf40c..2561968e1f2 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunPassengerAlongWithCarriers.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunPassengerAlongWithCarriers.java
@@ -23,16 +23,15 @@
import com.google.inject.Provider;
import jakarta.inject.Inject;
+import java.net.URL;
+import java.util.Map;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.api.core.v01.network.Network;
import org.matsim.core.api.experimental.events.EventsManager;
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.core.controler.MatsimServices;
-import org.matsim.core.controler.OutputDirectoryHierarchy;
+import org.matsim.core.controler.*;
import org.matsim.core.controler.listener.IterationEndsListener;
import org.matsim.core.gbl.Gbl;
import org.matsim.core.replanning.GenericPlanStrategyImpl;
@@ -47,13 +46,10 @@
import org.matsim.core.utils.io.IOUtils;
import org.matsim.examples.ExamplesUtils;
import org.matsim.freight.carriers.*;
-import org.matsim.freight.carriers.controler.*;
+import org.matsim.freight.carriers.controller.*;
import org.matsim.freight.carriers.usecases.analysis.CarrierScoreStats;
import org.matsim.freight.carriers.usecases.analysis.LegHistogram;
-import java.net.URL;
-import java.util.Map;
-
final class RunPassengerAlongWithCarriers {
final static URL url = ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9");
@@ -67,7 +63,7 @@ public void run() {
Scenario scenario = prepareScenario(config);
- Controler controler = new Controler(scenario);
+ Controller controller = ControllerUtils.createController(scenario);
CarrierVehicleTypes types = new CarrierVehicleTypes();
new CarrierVehicleTypeReader(types).readURL( IOUtils.extendUrl(url, "vehicleTypes.xml" ) );
@@ -75,9 +71,9 @@ public void run() {
final Carriers carriers = new Carriers();
new CarrierPlanXmlReader(carriers, types ).readURL( IOUtils.extendUrl(url, "carrierPlans.xml" ) );
- controler.addOverridingModule( new CarrierModule() );
+ controller.addOverridingModule( new CarrierModule() );
- controler.addOverridingModule( new AbstractModule(){
+ controller.addOverridingModule( new AbstractModule(){
@Override public void install(){
this.bind( CarrierStrategyManager.class ).toProvider( new MyCarrierPlanStrategyManagerFactory(types) );
this.bind( CarrierScoringFunctionFactory.class ).toInstance(carrier -> {
@@ -91,9 +87,9 @@ public void run() {
} );
- prepareFreightOutputDataAndStats(scenario, controler.getEvents(), controler, carriers);
+ prepareFreightOutputDataAndStats(scenario, controller.getEvents(), controller, carriers);
- controler.run();
+ controller.run();
}
@@ -154,7 +150,7 @@ public MyCarrierPlanStrategyManagerFactory(CarrierVehicleTypes types) {
final TravelDisutility travelDisutility = CarrierTravelDisutilities.createBaseDisutility(types, modeTravelTimes.get(TransportMode.car ) );
final LeastCostPathCalculator router = leastCostPathCalculatorFactory.createPathCalculator(network, travelDisutility, modeTravelTimes.get(TransportMode.car));
- final CarrierStrategyManager carrierStrategyManager = CarrierControlerUtils.createDefaultCarrierStrategyManager();
+ final CarrierStrategyManager carrierStrategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager();
carrierStrategyManager.setMaxPlansPerAgent(5);
carrierStrategyManager.addStrategy(new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 0.95);
diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/SelectBestPlanAndOptimizeItsVehicleRouteFactory.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/SelectBestPlanAndOptimizeItsVehicleRouteFactory.java
index 0051af3de81..a043c85d958 100644
--- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/SelectBestPlanAndOptimizeItsVehicleRouteFactory.java
+++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/SelectBestPlanAndOptimizeItsVehicleRouteFactory.java
@@ -30,6 +30,8 @@
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import com.graphhopper.jsprit.core.util.Solutions;
import com.graphhopper.jsprit.io.algorithm.VehicleRoutingAlgorithms;
+import java.net.URL;
+import java.util.Collection;
import org.matsim.api.core.v01.network.Network;
import org.matsim.core.replanning.GenericPlanStrategy;
import org.matsim.core.replanning.GenericPlanStrategyImpl;
@@ -46,9 +48,6 @@
import org.matsim.freight.carriers.jsprit.NetworkBasedTransportCosts;
import org.matsim.freight.carriers.jsprit.NetworkRouter;
-import java.net.URL;
-import java.util.Collection;
-
final class SelectBestPlanAndOptimizeItsVehicleRouteFactory {
final URL url = ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9");
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/ForwardLogisticChainSchedulerImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/ForwardLogisticChainSchedulerImpl.java
new file mode 100644
index 00000000000..71d76c307ce
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/ForwardLogisticChainSchedulerImpl.java
@@ -0,0 +1,189 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import java.util.ArrayList;
+import org.matsim.api.core.v01.Id;
+import org.matsim.freight.logistics.shipment.LspShipment;
+
+/**
+ * .... Macht 3 Schritte: 1.) the LSPShipments are handed over to the first {@link
+ * LogisticChainElement} of their {@link LogisticChain} 2.) the neighbors, i.e. the predecessors and
+ * successors of all {@link LSPResource}s are determined 3.) the Resources are brought into the
+ * right sequence according to the algorithm.
+ *
+ *
When traversing this list of {@link LSPResource}s, the operations in each {@link LSPResource}
+ * are scheduled individually by calling their {@link LSPResourceScheduler}.
+ */
+/* package-private */ class ForwardLogisticChainSchedulerImpl implements LogisticChainScheduler {
+
+ /**
+ * The Resources are brought into the right sequence according to the algorithm. The result of
+ * this algorithm is a list of Resources that is later traversed from the front to the back, i.e.
+ * starting with the entry at index 0. In the algorithm, this list is called sortedResourceList.
+ */
+ private final ArrayList sortedResourceList;
+
+ /**
+ * The determination of the neighborhood structure among the Resources resulted in the
+ * neighborList.
+ */
+ private final ArrayList neighbourList;
+
+ private LSP lsp;
+ private int bufferTime;
+
+ ForwardLogisticChainSchedulerImpl() {
+ this.sortedResourceList = new ArrayList<>();
+ this.neighbourList = new ArrayList<>();
+ }
+
+ @Override
+ public void scheduleLogisticChain() {
+ insertShipmentsAtBeginning();
+ setResourceNeighbours();
+ sortResources();
+ for (LSPResource resource : sortedResourceList) {
+ resource.schedule(bufferTime, lsp.getSelectedPlan());
+ }
+ }
+
+ @Override
+ public void setEmbeddingContainer(LSP lsp) {
+ this.lsp = lsp;
+ }
+
+ private void setResourceNeighbours() {
+ // internal data structure, try to ignore when looking from outside. kai/kai, jan'22
+ neighbourList.clear();
+ for (LSPResource resource : lsp.getResources()) {
+ ResourceNeighbours neighbours = new ResourceNeighbours(resource);
+ for (LogisticChainElement element : resource.getClientElements()) {
+ LogisticChainElement predecessor = element.getPreviousElement();
+ LSPResource previousResource = predecessor.getResource();
+ neighbours.addPredecessor(previousResource);
+ LogisticChainElement successor = element.getNextElement();
+ LSPResource nextResource = successor.getResource();
+ neighbours.addSuccessor(nextResource);
+ }
+ neighbourList.add(neighbours);
+ }
+ }
+
+ private void sortResources() {
+ sortedResourceList.clear();
+ while (!neighbourList.isEmpty()) {
+ for (ResourceNeighbours neighbours : neighbourList) {
+ if (allPredecessorsAlreadyScheduled(neighbours)
+ && noSuccessorAlreadyScheduled(neighbours)) {
+ sortedResourceList.add(neighbours.resource);
+ neighbourList.remove(neighbours);
+ }
+ }
+ }
+ }
+
+ private boolean allPredecessorsAlreadyScheduled(ResourceNeighbours neighbours) {
+ if (neighbours.predecessors.isEmpty()) {
+ return true;
+ }
+
+ for (LSPResource predecessor : neighbours.predecessors) {
+ if (!sortedResourceList.contains(predecessor)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean noSuccessorAlreadyScheduled(ResourceNeighbours neighbours) {
+ if (neighbours.successors.isEmpty()) {
+ return true;
+ }
+
+ for (LSPResource successor : neighbours.successors) {
+ if (!sortedResourceList.contains(successor)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void insertShipmentsAtBeginning() {
+ for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) {
+ LogisticChainElement firstElement = getFirstElement(solution);
+ assert firstElement != null;
+ for (Id lspShipmentId : solution.getLspShipmentIds()) {
+ var shipment = LSPUtils.findLspShipment(lsp, lspShipmentId);
+ assert shipment != null;
+ firstElement
+ .getIncomingShipments()
+ .addShipment(shipment.getPickupTimeWindow().getStart(), shipment);
+ }
+ }
+ }
+
+ private LogisticChainElement getFirstElement(LogisticChain solution) {
+ for (LogisticChainElement element : solution.getLogisticChainElements()) {
+ if (element.getPreviousElement() == null) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void setBufferTime(int bufferTime) {
+ this.bufferTime = bufferTime;
+ }
+
+ /**
+ * The relationship between different {@link LSPResource}s allows to handle various supply
+ * structures that the {@link LSP} might decide to maintain. Thus, a {@link LSPResource} can have
+ * several successors or predecessors or can be used by several different {@link LogisticChain}s.
+ * The neighborhood structure among the {@link LSPResource}s is stored in instances of the class
+ * {@link ResourceNeighbours} which contain references on the considered {@link LSPResource} and
+ * on the set of immediate successors respective predecessors. As the result of this step, a
+ * collection of {@link ResourceNeighbours} called neighborList is created that contains the
+ * neighbors of all {@link LSPResource}s in the plan of the considered {@link LSP}.
+ */
+ private static class ResourceNeighbours {
+ // internal data structure, try to ignore when looking from outside. kai/kai, jan'22
+
+ private final ArrayList predecessors;
+ private final ArrayList successors;
+ private final LSPResource resource;
+
+ private ResourceNeighbours(LSPResource resource) {
+ this.resource = resource;
+ this.predecessors = new ArrayList<>();
+ this.successors = new ArrayList<>();
+ }
+
+ private void addPredecessor(LSPResource resource) {
+ this.predecessors.add(resource);
+ }
+
+ private void addSuccessor(LSPResource resource) {
+ this.successors.add(resource);
+ }
+ }
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/FreightLogisticsConfigGroup.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/FreightLogisticsConfigGroup.java
new file mode 100644
index 00000000000..ca222f462ab
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/FreightLogisticsConfigGroup.java
@@ -0,0 +1,142 @@
+/*
+ *********************************************************************** *
+ * project: org.matsim.*
+ * *
+ * *********************************************************************** *
+ * *
+ * copyright : (C) 2024 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.freight.logistics;
+
+import java.net.URL;
+import java.util.Map;
+import org.matsim.core.config.ConfigGroup;
+import org.matsim.core.config.ReflectiveConfigGroup;
+
+public class FreightLogisticsConfigGroup extends ReflectiveConfigGroup {
+
+ public static final String GROUPNAME="freightLogistics" ;
+
+ private String lspsFile;
+ static final String LSPS_FILE = "lspsFile";
+ private static final String LSPS_FILE_DESC = "Freight LogisticsServiceProviders (LSP)s File, according to MATSim logistics extension as part of MATSim's freight contrib.";
+
+ public FreightLogisticsConfigGroup() {
+ super(GROUPNAME);
+ }
+
+ //### CarriersFile ###
+ /**
+ * @return -- {@value #LSPS_FILE_DESC}
+ */
+ @StringGetter(LSPS_FILE)
+ public String getLspsFile() {
+ return lspsFile;
+ }
+
+ URL getLspsFileUrl(URL context) {
+ return ConfigGroup.getInputFileURL(context, this.lspsFile);
+ }
+
+ /**
+ * @param -- {@value #LSPS_FILE_DESC}
+ */
+ @StringSetter(LSPS_FILE)
+ public void setLspsFile(String lspsFile) {
+ this.lspsFile = lspsFile;
+ }
+
+
+
+ //---
+ // Commenting this out, because in a frist step I think it is better/ more straight forward to have the VRP logic in the carriers as an attribute.
+ // please see {@link CarrierSchedulerUtils#setVrpLogic(carrier, VRPLogic)} and {@link CarrierSchedulerUtils#getVrpLogic(carrier)}
+ //---
+
+// static final String VRP_LOGIC_OF_DISTRIBUTION_CARRIER = "vrpLogicOfDistributionCarrier";
+// private LSPUtils.LogicOfVrp vrpLogicOfDistributionCarrier = LSPUtils.LogicOfVrp.serviceBased;
+// private static final String VRP_LOGIC_OF_DISTRIBUTION_CARRIER_DESC = "Define, on which type of jobs the VRP of the **distribution** carrier will base on:" + Arrays.toString(LSPUtils.LogicOfVrp.values());
+//
+// static final String VRP_LOGIC_OF_MAINRUN_CARRIER = "vrpLogicOfMainRunCarrier";
+// private LSPUtils.LogicOfVrp vrpLogicOfMainRunCarrier = LSPUtils.LogicOfVrp.serviceBased;
+// private static final String VRP_LOGIC_OF_MAINRUN_CARRIER_DESC = "Define, on which type of jobs the VRP of the **MainRun** carrier will base on:" + Arrays.toString(LSPUtils.LogicOfVrp.values());
+//
+// static final String VRP_LOGIC_OF_COLLECTION_CARRIER = "vrpLogicOfCollectionCarrier";
+// private LSPUtils.LogicOfVrp vrpLogicOfCollectionCarrier = LSPUtils.LogicOfVrp.serviceBased;
+// private static final String VRP_LOGIC_OF_COLLECTION_CARRIER_DESC = "Define, on which type of jobs the VRP of the **Collection** carrier will base on:" + Arrays.toString(LSPUtils.LogicOfVrp.values());
+//
+// /**
+// *
+// * @return The internal type of jobs, on which the VRPs of the distribution carrier bases on.
+// */
+// @StringGetter(VRP_LOGIC_OF_DISTRIBUTION_CARRIER)
+// public LSPUtils.LogicOfVrp getVrpLogicOfDistributionCarrier() {
+// return vrpLogicOfDistributionCarrier;
+// }
+//
+// /**
+// * @param vrpLogicOfDistributionCarrier {@value #VRP_LOGIC_OF_DISTRIBUTION_CARRIER}
+// */
+// @StringSetter(VRP_LOGIC_OF_DISTRIBUTION_CARRIER)
+// public void setVrpLogicOfDistributionCarrier(LSPUtils.LogicOfVrp vrpLogicOfDistributionCarrier) {
+// this.vrpLogicOfDistributionCarrier = vrpLogicOfDistributionCarrier;
+// }
+//
+// /**
+// * @return The internal type of jobs, on which the VRPs of the main run carrier bases on.
+// */
+// @StringGetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_MAINRUN_CARRIER)
+// public LSPUtils.LogicOfVrp getVrpLogicOfMainRunCarrier() {
+// return vrpLogicOfMainRunCarrier;
+// }
+//
+// /**
+// * @param vrpLogicOfMainRunCarrier {@value #VRP_LOGIC_OF_MAINRUN_CARRIER}
+// */
+// @StringSetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_MAINRUN_CARRIER)
+// public void setVrpLogicOfMainRunCarrier(LSPUtils.LogicOfVrp vrpLogicOfMainRunCarrier) {
+// this.vrpLogicOfMainRunCarrier = vrpLogicOfMainRunCarrier;
+// }
+//
+// /**
+// * @return The internal type of jobs, on which the VRPs of the collection carrier bases on.
+// */
+// @StringGetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_COLLECTION_CARRIER)
+// public LSPUtils.LogicOfVrp getVrpLogicOfCollectionCarrier() {
+// return vrpLogicOfCollectionCarrier;
+// }
+//
+// /**
+// * @param vrpLogicOfCollectionCarrier {@value #VRP_LOGIC_OF_COLLECTION_CARRIER}
+// */
+// @StringSetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_COLLECTION_CARRIER)
+// public void setVrpLogicOfCollectionCarrier(LSPUtils.LogicOfVrp vrpLogicOfCollectionCarrier) {
+// this.vrpLogicOfCollectionCarrier = vrpLogicOfCollectionCarrier;
+// }
+
+ //---
+ //---
+ @Override
+ public Map getComments() {
+ Map map = super.getComments();
+ map.put(LSPS_FILE, LSPS_FILE_DESC);
+// map.put(VRP_LOGIC_OF_DISTRIBUTION_CARRIER, VRP_LOGIC_OF_DISTRIBUTION_CARRIER_DESC);
+// map.put(VRP_LOGIC_OF_MAINRUN_CARRIER, VRP_LOGIC_OF_MAINRUN_CARRIER_DESC);
+// map.put(VRP_LOGIC_OF_COLLECTION_CARRIER, VRP_LOGIC_OF_COLLECTION_CARRIER_DESC);
+ return map;
+ }
+
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/HasBackpointer.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasBackpointer.java
new file mode 100644
index 00000000000..73f97386951
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasBackpointer.java
@@ -0,0 +1,12 @@
+package org.matsim.freight.logistics;
+
+@SuppressWarnings("InterfaceMayBeAnnotatedFunctional")
+public interface HasBackpointer {
+ // In general, we set backpointers when we add to the container.
+
+ // yy maybe also have interface HasSettableBackpointer?
+ void setEmbeddingContainer(T pointer);
+
+ // T getEmbeddingContainer();
+
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/HasLspShipmentId.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasLspShipmentId.java
new file mode 100644
index 00000000000..e3ddd1fc2f5
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasLspShipmentId.java
@@ -0,0 +1,32 @@
+/* *********************************************************************** *
+ * project: org.matsim.* *
+ * *
+ * *********************************************************************** *
+ * *
+ * copyright : (C) 2008 by the members listed in the COPYING, *
+ * LICENSE and WARRANTY file. *
+ * email : info at matsim dot org *
+ * *
+ * *********************************************************************** *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * See also COPYING, LICENSE and WARRANTY file *
+ * *
+ * *********************************************************************** */
+package org.matsim.freight.logistics;
+
+import org.matsim.api.core.v01.Id;
+import org.matsim.freight.logistics.shipment.LspShipment;
+
+/**
+ * @author Kai Martins-Turner (kturner)
+ */
+public interface HasLspShipmentId {
+
+ String ATTRIBUTE_LSP_SHIPMENT_ID = "lspShipmentId";
+
+ Id getLspShipmentId();
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/HasSimulationTrackers.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasSimulationTrackers.java
new file mode 100644
index 00000000000..33ba50074ed
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasSimulationTrackers.java
@@ -0,0 +1,14 @@
+package org.matsim.freight.logistics;
+
+import java.util.Collection;
+
+// One could say that the simulation trackers are the decorators that convert the data objects into
+// behavioral objects. In core matsim, we instead
+// create behavioral objects, which contain the data objects. E.g. MobsimAgent, DriverAgent,
+// CarrierAgent, etc. kai, may'22
+public interface HasSimulationTrackers {
+
+ void addSimulationTracker(LSPSimulationTracker tracker);
+
+ Collection> getSimulationTrackers();
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/InitialShipmentAssigner.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/InitialShipmentAssigner.java
new file mode 100644
index 00000000000..9d856aaa6cb
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/InitialShipmentAssigner.java
@@ -0,0 +1,43 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import org.matsim.freight.logistics.shipment.LspShipment;
+
+/**
+ * Takes an {@link LspShipment} and normally assigns it to something that belongs to an {@link LSP}.
+ *
+ * After changes in fall 2023 (see master thesis of nrichter), the assignment is
+ * there to be done one time initially.
+ *
+ * If there are several {@link LogisticChain}s in a {@link LSPPlan}, the {@link LSP} has to assign each {@link
+ * LspShipment} to the suitable {@link LogisticChain}. For this purpose, each {@link LSPPlan}
+ * (or only the LSP? - kmt jan'24), contains a pluggable strategy
+ * that is contained in classes implementing the interface {@link InitialShipmentAssigner}.
+ *
+ * During iterations, it can happen that the {@link LspShipment} should be moved to another
+ * {@link LogisticChain} of the same {@link LSPPlan}. This is now (since fall 2023; see master
+ * thesis of nrichter) part of the (innovative) **Replanning** strategies.
+ */
+public interface InitialShipmentAssigner {
+
+ void assignToPlan(LSPPlan lspPlan, LspShipment lspShipment);
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/KnowsLSP.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/KnowsLSP.java
new file mode 100644
index 00000000000..60a9c8ea190
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/KnowsLSP.java
@@ -0,0 +1,7 @@
+package org.matsim.freight.logistics;
+
+interface KnowsLSP {
+ LSP getLSP();
+
+ void setLSP(LSP lsp);
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSP.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSP.java
new file mode 100644
index 00000000000..0486cd0f958
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSP.java
@@ -0,0 +1,53 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import java.util.Collection;
+import org.matsim.api.core.v01.population.HasPlansAndId;
+import org.matsim.freight.logistics.shipment.LspShipment;
+
+/**
+ * In the class library, the interface LSP has the following tasks: 1. Maintain one or several
+ * transport chains through which {@link LspShipment}s are routed. 2. Assign {@link LspShipment}s to
+ * the suitable transport chain. --> {@link InitialShipmentAssigner}. 3. Interact with the agents that
+ * embody the demand side of the freight transport market, if they are specified in the setting. 4.
+ * Coordinate carriers that are in charge of the physical transport.
+ */
+public interface LSP extends HasPlansAndId, HasSimulationTrackers {
+
+ /** yyyy does this have to be exposed? */
+ Collection getLspShipments();
+
+ /** ok (behavioral method) */
+ void scheduleLogisticChains();
+
+ /** yyyy does this have to be exposed? */
+ Collection getResources();
+
+ /** ok (behavioral method) */
+ void scoreSelectedPlan();
+
+ /**
+ * @param lspShipment ok (LSP needs to be told that it is responsible for lspShipment)
+ */
+ void assignShipmentToLSP(LspShipment lspShipment);
+
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPCarrierResource.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPCarrierResource.java
new file mode 100644
index 00000000000..1a26be79a61
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPCarrierResource.java
@@ -0,0 +1,28 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import org.matsim.freight.carriers.Carrier;
+
+public interface LSPCarrierResource extends LSPResource {
+
+ Carrier getCarrier();
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPConstants.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPConstants.java
new file mode 100644
index 00000000000..44df1603232
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPConstants.java
@@ -0,0 +1,29 @@
+package org.matsim.freight.logistics;
+
+import org.matsim.freight.carriers.CarrierConstants;
+
+public abstract class LSPConstants extends CarrierConstants {
+
+ public static final String CAPACITY_NEED_FIXED = "capacityNeedFixed";
+ public static final String CAPACITY_NEED_LINEAR = "capacityNeedLinear";
+ public static final String CHAIN_ID = "chainId";
+ public static final String ELEMENT = "element";
+ public static final String END_TIME = "endTime";
+ public static final String FIXED_COST = "fixedCost";
+ public static final String HUB = "hub";
+ public static final String LOCATION = "location";
+ public static final String LOGISTIC_CHAIN = "logisticChain";
+ public static final String LOGISTIC_CHAINS = "logisticChains";
+ public static final String LOGISTIC_CHAIN_ELEMENT = "logisticChainElement";
+ public static final String LSP = "lsp";
+ public static final String LSPS = "lsps";
+ public static final String LSP_PLAN = "LspPlan";
+ public static final String LSP_PLANS = "LspPlans";
+ public static final String RESOURCES = "resources";
+ public static final String RESOURCE_ID = "resourceId";
+ public static final String SCHEDULER = "scheduler";
+ public static final String SHIPMENT_PLAN = "shipmentPlan";
+ public static final String SHIPMENT_PLANS = "shipmentPlans";
+ public static final String START_TIME = "startTime";
+ public static final String TYPE = "type";
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPControllerListener.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPControllerListener.java
new file mode 100644
index 00000000000..0da2e144cbc
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPControllerListener.java
@@ -0,0 +1,253 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import jakarta.inject.Inject;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.Nullable;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.matsim.api.core.v01.Scenario;
+import org.matsim.core.api.experimental.events.EventsManager;
+import org.matsim.core.controler.MatsimServices;
+import org.matsim.core.controler.OutputDirectoryHierarchy;
+import org.matsim.core.controler.events.*;
+import org.matsim.core.controler.listener.*;
+import org.matsim.core.events.handler.EventHandler;
+import org.matsim.core.gbl.Gbl;
+import org.matsim.freight.carriers.Carrier;
+import org.matsim.freight.carriers.CarrierPlanWriter;
+import org.matsim.freight.carriers.Carriers;
+import org.matsim.freight.carriers.CarriersUtils;
+import org.matsim.freight.carriers.controller.CarrierAgentTracker;
+import org.matsim.freight.logistics.io.LSPPlanXmlWriter;
+import org.matsim.freight.logistics.shipment.LspShipment;
+
+class LSPControllerListener
+ implements StartupListener,
+ BeforeMobsimListener,
+ AfterMobsimListener,
+ ScoringListener,
+ ReplanningListener,
+ IterationStartsListener,
+ IterationEndsListener,
+ ShutdownListener {
+ private static final Logger log = LogManager.getLogger(LSPControllerListener.class);
+ private final Scenario scenario;
+ private final List registeredHandlers = new ArrayList<>();
+
+ private static int addListenerCnt = 0;
+ private static final int maxAddListenerCnt = 1;
+
+ @Inject private EventsManager eventsManager;
+ @Inject private MatsimServices matsimServices;
+ @Inject private LSPScorerFactory lspScoringFunctionFactory;
+ @Inject @Nullable private LSPStrategyManager strategyManager;
+ @Inject private OutputDirectoryHierarchy controlerIO;
+ @Inject private CarrierAgentTracker carrierAgentTracker;
+
+
+ @Inject
+ LSPControllerListener(Scenario scenario) {
+ this.scenario = scenario;
+ }
+
+ @Override
+ public void notifyStartup(StartupEvent event) {
+ //Ensure that all ressource Ids are only there once.
+
+ checkForUniqueResourceIds();
+
+ }
+
+/**
+* For later steps, e.g. scoring the Ids of the {@link LSPResource} ids must be unique.
+ * Otherwise, there are scored several times.
+ *
+ * For the future we may reduce it to unique {@link LSPResource} ids PER {@link LSP}.
+ * This means, that the events (also from the carriers) need to have an information obout the LSP it belongs to and that
+ * in scoring and analysis this must be taken into account. What itself is another source for errors...
+ * KMT jul'24
+*/
+ private void checkForUniqueResourceIds() {
+ List duplicates = new ArrayList<>();
+ Set set = new HashSet<>();
+
+ LSPs lsps = LSPUtils.getLSPs(scenario);
+ for (LSP lsp : lsps.getLSPs().values()) {
+ for (LSPResource lspResource : lsp.getResources()) {
+ String idString = lspResource.getId().toString();
+ if (set.contains(idString)) {
+ duplicates.add(idString);
+ } else {
+ set.add(idString);
+ }
+ }
+ }
+
+ if (!duplicates.isEmpty()) {
+ log.error("There are non-unique ressource Ids. This must not be! The duplicate ids are: {}.", duplicates.toString());
+ log.error("You may also use output_lsp.xml to check were the duplicates are located");
+ log.error("Aborting now ...");
+ throw new RuntimeException();
+ }
+ }
+
+ @Override
+ public void notifyBeforeMobsim(BeforeMobsimEvent event) {
+ LSPs lsps = LSPUtils.getLSPs(scenario);
+
+ // TODO: Why do we add all simTrackers in every iteration beforeMobsim starts?
+ // Doing so results in a lot of "not adding eventsHandler since already added" warnings.
+ // @KN: Would it be possible to do it in (simulation) startup and therefor only oce?
+ for (LSP lsp : lsps.getLSPs().values()) {
+ ((LSPImpl) lsp).setScorer(lspScoringFunctionFactory.createScoringFunction());
+
+ // simulation trackers of lsp:
+ registerSimulationTrackers(lsp);
+
+ // simulation trackers of resources:
+ for (LSPResource resource : lsp.getResources()) {
+ registerSimulationTrackers(resource);
+ }
+
+ // simulation trackers of shipments:
+ for (LspShipment lspShipment : lsp.getLspShipments()) {
+ registerSimulationTrackers(lspShipment);
+ }
+
+ // simulation trackers of solutions:
+ for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) {
+ registerSimulationTrackers(solution);
+
+ // simulation trackers of solution elements:
+ for (LogisticChainElement element : solution.getLogisticChainElements()) {
+ registerSimulationTrackers(element);
+
+ // simulation trackers of resources:
+ registerSimulationTrackers(element.getResource());
+ }
+ }
+ }
+ }
+
+ private void registerSimulationTrackers(HasSimulationTrackers> hasSimulationTrackers) {
+ // get all simulation trackers ...
+ for (LSPSimulationTracker> simulationTracker :
+ hasSimulationTrackers.getSimulationTrackers()) {
+ // ... register them ...
+ if (!registeredHandlers.contains(simulationTracker)) {
+ log.info("adding eventsHandler: {}", simulationTracker);
+ eventsManager.addHandler(simulationTracker);
+ registeredHandlers.add(simulationTracker);
+ matsimServices.addControlerListener(simulationTracker);
+ simulationTracker.setEventsManager(eventsManager);
+ } else if ( addListenerCnt < maxAddListenerCnt ){
+ log.warn("not adding eventsHandler since already added: {}", simulationTracker);
+ addListenerCnt++;
+ if (addListenerCnt == maxAddListenerCnt) {
+ log.warn(Gbl.FUTURE_SUPPRESSED);
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public void notifyReplanning(ReplanningEvent event) {
+ if (strategyManager == null) {
+ throw new RuntimeException(
+ "You need to set LSPStrategyManager to something meaningful to run iterations.");
+ }
+
+ LSPs lsps = LSPUtils.getLSPs(scenario);
+ strategyManager.run(
+ lsps.getLSPs().values(), event.getIteration(), event.getReplanningContext());
+
+ for (LSP lsp : lsps.getLSPs().values()) {
+ lsp.getSelectedPlan()
+ .getShipmentPlans()
+ .clear(); // clear ShipmentPlans to start with clear(n) state. Otherwise, some of the times were
+ // accumulating over the time. :(
+ lsp.scheduleLogisticChains();
+ }
+
+ // Update carriers in scenario and CarrierAgentTracker
+ carrierAgentTracker.getCarriers().getCarriers().clear();
+ for (Carrier carrier : getCarriersFromLSP().getCarriers().values()) {
+ CarriersUtils.getCarriers(scenario).addCarrier(carrier);
+ carrierAgentTracker.getCarriers().addCarrier(carrier);
+ }
+ }
+
+ @Override
+ public void notifyScoring(ScoringEvent scoringEvent) {
+ for (LSP lsp : LSPUtils.getLSPs(scenario).getLSPs().values()) {
+ lsp.scoreSelectedPlan();
+ }
+ // yyyyyy might make more sense to register the lsps directly as scoring controler listener (??)
+ }
+
+ @Override
+ public void notifyAfterMobsim(AfterMobsimEvent event) {}
+
+ Carriers getCarriersFromLSP() {
+ LSPs lsps = LSPUtils.getLSPs(scenario);
+ assert !lsps.getLSPs().isEmpty();
+
+ Carriers carriers = new Carriers();
+ for (LSP lsp : lsps.getLSPs().values()) {
+ LSPPlan selectedPlan = lsp.getSelectedPlan();
+ for (LogisticChain solution : selectedPlan.getLogisticChains()) {
+ for (LogisticChainElement element : solution.getLogisticChainElements()) {
+ if (element.getResource() instanceof LSPCarrierResource carrierResource) {
+ Carrier carrier = carrierResource.getCarrier();
+ if (!carriers.getCarriers().containsKey(carrier.getId())) {
+ carriers.addCarrier(carrier);
+ }
+ }
+ }
+ }
+ }
+ return carriers;
+ }
+
+ @Override
+ public void notifyIterationStarts(IterationStartsEvent event) {}
+
+ @Override
+ public void notifyIterationEnds(IterationEndsEvent event) {
+ new LSPPlanXmlWriter(LSPUtils.getLSPs(scenario))
+ .write(controlerIO.getIterationFilename(event.getIteration(), "lsps.xml"));
+ }
+
+ @Override
+ public void notifyShutdown(ShutdownEvent event) {
+ new LSPPlanXmlWriter(LSPUtils.getLSPs(scenario))
+ .write(controlerIO.getOutputPath() + "/output_lsps.xml.gz");
+ new CarrierPlanWriter(CarriersUtils.getCarriers(scenario))
+ .write(controlerIO.getOutputPath() + "/output_carriers.xml.gz");
+ }
+
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPDataObject.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPDataObject.java
new file mode 100644
index 00000000000..ff150a79d88
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPDataObject.java
@@ -0,0 +1,45 @@
+package org.matsim.freight.logistics;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import org.matsim.api.core.v01.Id;
+import org.matsim.api.core.v01.Identifiable;
+import org.matsim.utils.objectattributes.attributable.Attributable;
+import org.matsim.utils.objectattributes.attributable.Attributes;
+import org.matsim.utils.objectattributes.attributable.AttributesImpl;
+
+public class LSPDataObject implements HasSimulationTrackers, Attributable, Identifiable {
+
+ private final Collection> trackers = new LinkedList<>();
+ private final Attributes attributes = new AttributesImpl();
+ private final Id id;
+
+ public LSPDataObject(Id id) {
+ this.id = id;
+ }
+
+ @Override
+ public final void addSimulationTracker(LSPSimulationTracker tracker) {
+ this.trackers.add(tracker);
+ tracker.setEmbeddingContainer((T) this);
+ // It may not be possible to do this without this cast. Since "this" only knows that it is at
+ // least an LSPDataObject, and only we
+ // know that it is truly of type T. kai, jun'22
+ }
+
+ @Override
+ public final Collection> getSimulationTrackers() {
+ return Collections.unmodifiableCollection(this.trackers);
+ }
+
+ @Override
+ public final Attributes getAttributes() {
+ return attributes;
+ }
+
+ @Override
+ public final Id getId() {
+ return id;
+ }
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPImpl.java
new file mode 100644
index 00000000000..d25cbfb043a
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPImpl.java
@@ -0,0 +1,163 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.matsim.freight.logistics.shipment.LspShipment;
+
+/* package-private */ class LSPImpl extends LSPDataObject implements LSP {
+ private static final Logger log = LogManager.getLogger(LSPImpl.class);
+
+ private final Collection lspShipments;
+ private final ArrayList lspPlans;
+ private final LogisticChainScheduler logisticChainScheduler;
+ private final Collection resources;
+ private LSPPlan selectedPlan;
+ private LSPScorer scorer;
+
+ // private LSPReplanner replanner;
+
+ LSPImpl(LSPUtils.LSPBuilder builder) {
+ super(builder.id);
+ this.lspShipments = new ArrayList<>();
+ this.lspPlans = new ArrayList<>();
+ this.logisticChainScheduler = builder.logisticChainScheduler;
+ this.logisticChainScheduler.setEmbeddingContainer(this);
+ this.selectedPlan = builder.initialPlan;
+ this.selectedPlan.setLSP(this);
+ this.lspPlans.add(builder.initialPlan);
+ this.resources = builder.resources;
+ }
+
+ public static LSPPlan copyPlan(LSPPlan plan2copy) {
+ List newPlanChains = new ArrayList<>();
+ for (LogisticChain initialPlanChain : plan2copy.getLogisticChains()) {
+ LogisticChain newPlanChain =
+ LSPUtils.LogisticChainBuilder.newInstance(initialPlanChain.getId()).build();
+ newPlanChain.getLogisticChainElements().addAll(initialPlanChain.getLogisticChainElements());
+ newPlanChain.getLspShipmentIds().addAll(initialPlanChain.getLspShipmentIds());
+ newPlanChains.add(newPlanChain);
+ }
+
+ LSPPlan copiedPlan = LSPUtils.createLSPPlan();
+ copiedPlan.setInitialShipmentAssigner(plan2copy.getInitialShipmentAssigner());
+ copiedPlan.setLSP(plan2copy.getLSP());
+ copiedPlan.setScore(plan2copy.getScore());
+ copiedPlan.setType(plan2copy.getType());
+ copiedPlan.getLogisticChains().addAll(newPlanChains);
+ return copiedPlan;
+ }
+
+ /**
+ * This is used from {@link LSPControllerListener} and not meant to be used from user code. Users
+ * should bind {@link LSPScorerFactory}.
+ */
+ /* package-private */ void setScorer(LSPScorer scorer) {
+ this.scorer = scorer;
+ scorer.setEmbeddingContainer(this);
+ this.addSimulationTracker(scorer);
+ }
+
+ @Override
+ public void scheduleLogisticChains() {
+ logisticChainScheduler.scheduleLogisticChain();
+ }
+
+ @Override
+ public boolean addPlan(LSPPlan plan) {
+ for (LogisticChain solution : plan.getLogisticChains()) {
+ for (LogisticChainElement element : solution.getLogisticChainElements()) {
+ if (!resources.contains(element.getResource())) {
+ resources.add(element.getResource());
+ }
+ }
+ }
+ plan.setLSP(this);
+ return lspPlans.add(plan);
+ }
+
+ @Override
+ public LSPPlan createCopyOfSelectedPlanAndMakeSelected() {
+ LSPPlan newPlan = LSPImpl.copyPlan(this.selectedPlan);
+ this.setSelectedPlan(newPlan);
+ return newPlan;
+ }
+
+ @Override
+ public ArrayList getPlans() {
+ return lspPlans;
+ }
+
+ @Override
+ public LSPPlan getSelectedPlan() {
+ return selectedPlan;
+ }
+
+ @Override
+ public void setSelectedPlan(LSPPlan selectedPlan) {
+ if (!lspPlans.contains(selectedPlan)) {
+ lspPlans.add(selectedPlan);
+ }
+ this.selectedPlan = selectedPlan;
+ }
+
+ @Override
+ public boolean removePlan(LSPPlan lspPlan) {
+ if (lspPlans.contains(lspPlan)) {
+ lspPlans.remove(lspPlan);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Collection getResources() {
+ return resources;
+ }
+
+ public void scoreSelectedPlan() {
+ if (this.scorer != null) {
+ this.selectedPlan.setScore(scorer.getScoreForCurrentPlan());
+ } else {
+ throw new RuntimeException("trying to score the current LSP plan, but scorer is not set.");
+ }
+ }
+
+ @Override
+ public void assignShipmentToLSP(LspShipment lspShipment) {
+ // shipment.setLspId(this.getId()); // und rückweg dann auch darüber und dann
+ // lsp.getselectedPlan.getShipment...
+ lspShipments.add(lspShipment);
+ for (LSPPlan lspPlan : lspPlans) {
+ lspPlan.getInitialShipmentAssigner().assignToPlan(lspPlan, lspShipment);
+ }
+ }
+
+ @Override
+ public Collection getLspShipments() {
+ return this.lspShipments;
+ }
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPModule.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPModule.java
new file mode 100644
index 00000000000..520aead053b
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPModule.java
@@ -0,0 +1,184 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+import java.util.List;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.matsim.api.core.v01.Scenario;
+import org.matsim.api.core.v01.population.HasPlansAndId;
+import org.matsim.core.config.ConfigUtils;
+import org.matsim.core.controler.AbstractModule;
+import org.matsim.core.controler.events.BeforeMobsimEvent;
+import org.matsim.core.controler.listener.BeforeMobsimListener;
+import org.matsim.core.mobsim.qsim.AbstractQSimModule;
+import org.matsim.core.mobsim.qsim.components.QSimComponentsConfigGroup;
+import org.matsim.core.replanning.GenericPlanStrategy;
+import org.matsim.core.replanning.ReplanningContext;
+import org.matsim.core.replanning.selectors.PlanSelector;
+import org.matsim.freight.carriers.FreightCarriersConfigGroup;
+import org.matsim.freight.carriers.controller.*;
+import org.matsim.freight.logistics.analysis.LspScoreStatsModule;
+
+public class LSPModule extends AbstractModule {
+ private static final Logger log = LogManager.getLogger(LSPModule.class);
+
+ @Override
+ public void install() {
+ FreightCarriersConfigGroup freightConfig =
+ ConfigUtils.addOrGetModule(getConfig(), FreightCarriersConfigGroup.class);
+
+ bind(LSPControllerListener.class).in(Singleton.class);
+ addControlerListenerBinding().to(LSPControllerListener.class);
+
+ install(new CarrierModule());
+ install(new LspScoreStatsModule());
+
+ // this switches on certain qsim components:
+ QSimComponentsConfigGroup qsimComponents =
+ ConfigUtils.addOrGetModule(getConfig(), QSimComponentsConfigGroup.class);
+ List abc = qsimComponents.getActiveComponents();
+ abc.add(FreightAgentSource.COMPONENT_NAME);
+ switch (freightConfig.getTimeWindowHandling()) {
+ case ignore:
+ break;
+ case enforceBeginnings:
+ //// abc.add( WithinDayActivityReScheduling.COMPONENT_NAME );
+ log.warn(
+ "LSP has never hedged against time window openings; this is probably wrong; but I don't know what to do ...");
+ // break;
+ default:
+ throw new IllegalStateException(
+ "Unexpected value: " + freightConfig.getTimeWindowHandling());
+ }
+ qsimComponents.setActiveComponents(abc);
+
+ // this installs qsim components, which are switched on (or not) via the above syntax:
+ this.installQSimModule(
+ new AbstractQSimModule() {
+ @Override
+ protected void configureQSim() {
+ this.bind(FreightAgentSource.class).in(Singleton.class);
+ this.addQSimComponentBinding(FreightAgentSource.COMPONENT_NAME)
+ .to(FreightAgentSource.class);
+ switch (freightConfig.getTimeWindowHandling()) {
+ case ignore:
+ break;
+ case enforceBeginnings:
+ ////
+ // this.addQSimComponentBinding(WithinDayActivityReScheduling.COMPONENT_NAME).to(
+ // WithinDayActivityReScheduling.class );
+ log.warn(
+ "LSP has never hedged against time window openings; this is probably wrong; but I don't know what to do ...");
+ // break;
+ default:
+ throw new IllegalStateException(
+ "Unexpected value: " + freightConfig.getTimeWindowHandling());
+ }
+ }
+ });
+
+ // the scorers are necessary to run a zeroth iteration to the end:
+ bind(LSPScorerFactory.class).to(LSPScoringFunctionFactoryDummyImpl.class);
+
+ // for iterations, one needs to replace the following with something meaningful. If nothing
+ // else, there are "empty implementations" that do nothing. kai, jul'22
+ bind(LSPStrategyManager.class).toProvider(() -> null);
+
+ this.addControlerListenerBinding().to(DumpLSPPlans.class);
+ }
+
+ private static class LSPScoringFunctionFactoryDummyImpl implements LSPScorerFactory {
+ @Override
+ public LSPScorer createScoringFunction() {
+ return new LSPScorer() {
+ @Override
+ public double getScoreForCurrentPlan() {
+ return Double.NEGATIVE_INFINITY;
+ }
+
+ @Override
+ public void setEmbeddingContainer(LSP pointer) {}
+ };
+ }
+ }
+
+ public static final class LSPStrategyManagerEmptyImpl implements LSPStrategyManager {
+
+ @Override
+ public void addStrategy(
+ GenericPlanStrategy strategy, String subpopulation, double weight) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public void run(
+ Iterable extends HasPlansAndId> persons,
+ int iteration,
+ ReplanningContext replanningContext) {
+ log.warn("Running iterations without a strategy may lead to unclear results."); // "run" is
+ // possible, but will not do anything. kai, jul'22
+ }
+
+ @Override
+ public void setMaxPlansPerAgent(int maxPlansPerAgent) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public void addChangeRequest(int iteration, GenericPlanStrategy strategy, String subpopulation, double newWeight) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public void setPlanSelectorForRemoval(PlanSelector planSelector) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public List> getStrategies(String subpopulation) {
+ throw new RuntimeException("not implemented");
+ }
+
+ @Override
+ public List getWeights(String subpopulation) {
+ throw new RuntimeException("not implemented");
+ }
+ }
+
+ public static final class DumpLSPPlans implements BeforeMobsimListener {
+ @Inject Scenario scenario;
+
+ @Override
+ public void notifyBeforeMobsim(BeforeMobsimEvent event) {
+ LSPs lsps = LSPUtils.getLSPs(scenario);
+ for (LSP lsp : lsps.getLSPs().values()) {
+ log.info("Dumping plan(s) of [LSP={}] ; [No of plans={}]", lsp.getId(), lsp.getPlans().size());
+ for (LSPPlan plan : lsp.getPlans()) {
+ log.info("[LSPPlan: {}]", plan.toString());
+ }
+ log.info("Plan(s) of [LSP={}] dumped.", lsp.getId());
+ }
+ }
+ }
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlan.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlan.java
new file mode 100644
index 00000000000..7f7d3823866
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlan.java
@@ -0,0 +1,59 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import java.util.Collection;
+import org.matsim.api.core.v01.population.BasicPlan;
+import org.matsim.freight.logistics.shipment.LspShipment;
+import org.matsim.freight.logistics.shipment.LspShipmentPlan;
+
+/**
+ * This interface has the following properties:
+ *
+ *
+ *
As a {@link BasicPlan} it has a score, so it can be used for evolutionary learning. kai,
+ * may'22
+ *
An {@link LspShipment} is added via lspPlan#getAssigner().assignToSolution(shipment). The
+ * {@link InitialShipmentAssigner} assigns it deterministically to a {@link LogisticChain}.
+ *
+ */
+public interface LSPPlan extends BasicPlan, KnowsLSP {
+
+ LSPPlan addLogisticChain(LogisticChain solution);
+
+ Collection getLogisticChains();
+
+ /**
+ * yy My intuition would be to replace lspPlan#getAssigner().assignToSolution( shipment ) by
+ * lspPlan.addShipment( shipment ). kai, may'22
+ */
+ InitialShipmentAssigner getInitialShipmentAssigner();
+
+ LSPPlan setInitialShipmentAssigner(InitialShipmentAssigner assigner);
+
+ Collection getShipmentPlans();
+
+ void addShipmentPlan(LspShipmentPlan lspShipmentPlan);
+
+ String getType();
+
+ void setType(final String type);
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlanImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlanImpl.java
new file mode 100644
index 00000000000..84a698a5edd
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlanImpl.java
@@ -0,0 +1,126 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import org.matsim.freight.logistics.shipment.LspShipmentPlan;
+
+public class LSPPlanImpl implements LSPPlan {
+
+ private final Collection logisticChains;
+ private final Collection lspShipmentPlans;
+ private LSP lsp;
+ private Double score = null;
+ private InitialShipmentAssigner assigner;
+ private String type = null;
+
+ public LSPPlanImpl() {
+ this.logisticChains = new ArrayList<>();
+ this.lspShipmentPlans = new ArrayList<>();
+ }
+
+ @Override
+ public LSPPlan addLogisticChain(LogisticChain solution) {
+ this.logisticChains.add(solution);
+ solution.setLSP(this.lsp);
+ return this;
+ }
+
+ @Override
+ public Collection getLogisticChains() {
+ return logisticChains;
+ }
+
+ @Override
+ public InitialShipmentAssigner getInitialShipmentAssigner() {
+ return assigner;
+ }
+
+ @Override
+ public LSPPlan setInitialShipmentAssigner(InitialShipmentAssigner assigner) {
+ this.assigner = assigner;
+ return this;
+ }
+
+ @Override
+ public Collection getShipmentPlans() {
+ return this.lspShipmentPlans;
+ }
+
+ @Override
+ public void addShipmentPlan(LspShipmentPlan lspShipmentPlan) {
+ this.lspShipmentPlans.add(lspShipmentPlan);
+ }
+
+ @Override
+ public Double getScore() {
+ return score;
+ }
+
+ @Override
+ public void setScore(Double score) {
+ this.score = score;
+ }
+
+ @Override
+ public String getType() {
+ return this.type;
+ }
+
+ @Override
+ public void setType(final String type) {
+ this.type = type;
+ }
+
+ @Override
+ public LSP getLSP() {
+ return lsp;
+ }
+
+ @Override
+ public void setLSP(LSP lsp) {
+ this.lsp = lsp;
+ for (LogisticChain solution : logisticChains) {
+ solution.setLSP(lsp);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder strb = new StringBuilder();
+ strb.append("[score=").append(this.score).append("]");
+ strb.append(", [type=").append(this.type).append("]");
+ for (LogisticChain logisticChain : this.logisticChains) {
+ strb.append(", [LogisticChainId=")
+ .append(logisticChain.getId())
+ .append("], [No of LogisticChainElements=")
+ .append(logisticChain.getLogisticChainElements().size())
+ .append("] \n");
+ if (!logisticChain.getLogisticChainElements().isEmpty()) {
+ for (LogisticChainElement solutionElement : logisticChain.getLogisticChainElements()) {
+ strb.append("\t \t").append(solutionElement.toString()).append("\n");
+ }
+ }
+ }
+ return strb.toString();
+ }
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResource.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResource.java
new file mode 100644
index 00000000000..4f1e595ebe0
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResource.java
@@ -0,0 +1,40 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import java.util.Collection;
+import org.matsim.api.core.v01.Id;
+import org.matsim.api.core.v01.Identifiable;
+import org.matsim.api.core.v01.network.Link;
+import org.matsim.utils.objectattributes.attributable.Attributable;
+
+/** */
+public interface LSPResource
+ extends Identifiable, HasSimulationTrackers, Attributable {
+
+ Id getStartLinkId();
+
+ Id getEndLinkId();
+
+ Collection getClientElements();
+
+ void schedule(int bufferTime, LSPPlan lspPlan);
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResourceScheduler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResourceScheduler.java
new file mode 100644
index 00000000000..c63d9258742
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResourceScheduler.java
@@ -0,0 +1,106 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import org.matsim.freight.logistics.shipment.LspShipment;
+import org.matsim.freight.logistics.shipment.LspShipmentUtils;
+
+/**
+ * Resources are scheduled separately by calling their individual scheduling algorithm.
+ *
+ *
Within this algorithm, some methods are abstract, whereas others have a default implementation
+ * for forward scheduling. The former ones are specified in a suitable way by the corresponding
+ * Resource whereas the latter are only specified in the abstract parent class in order to
+ * coordinate the way in which the LSPShipments are handed over between subsequent Resources. The
+ * abstract methods deal with aspects that are specific to the Resource which contains the
+ * implementation of the ResourceScheduler.
+ *
+ *
Forwarding of LSPShipments is done by the two methods presortIncomingShipments() and
+ * switchHandledShipments(int bufferTime).
+ */
+public abstract class LSPResourceScheduler {
+
+ protected LSPResource resource;
+ protected ArrayList lspShipmentsToSchedule;
+
+ protected LSPPlan lspPlan;
+
+ public final void scheduleShipments(LSPPlan lspPlan, LSPResource resource, int bufferTime) {
+ this.lspPlan = lspPlan;
+ this.resource = resource;
+ this.lspShipmentsToSchedule = new ArrayList<>();
+ initializeValues(resource);
+ presortIncomingShipments();
+ scheduleResource();
+ updateShipments();
+ switchHandledShipments(bufferTime);
+ lspShipmentsToSchedule.clear();
+ }
+
+ /**
+ * Is in charge of the initialization of the actual scheduling process for the concerned Resource.
+ * Depending on the concrete shape of this process, there are mainly values to be deleted that are
+ * still stored from the previous iteration or the infrastructure for the used algorithm has to be
+ * set up.
+ *
+ * @param resource The LSPRessource
+ */
+ protected abstract void initializeValues(LSPResource resource);
+
+ /** Controls the actual scheduling process that depends on the shape and task of the Resource. */
+ protected abstract void scheduleResource();
+
+ /**
+ * Endows the involved {@link LspShipment}s with information that resulted from the scheduling in
+ * a narrow sense in scheduleResource(). The information can be divided into two main components.
+ * 1.) the schedule of the {@link LspShipment}s is updated if necessary 2.) the information for a
+ * later logging of the is added.
+ */
+ protected abstract void updateShipments();
+
+ private void presortIncomingShipments() {
+ this.lspShipmentsToSchedule = new ArrayList<>();
+ for (LogisticChainElement element : resource.getClientElements()) {
+ lspShipmentsToSchedule.addAll(element.getIncomingShipments().getLspShipmentsWTime());
+ }
+ lspShipmentsToSchedule.sort(Comparator.comparingDouble(LspShipmentUtils::getTimeOfLspShipment));
+ }
+
+ private void switchHandledShipments(int bufferTime) {
+ for (LspShipment lspShipmentWithTime : lspShipmentsToSchedule) {
+ var shipmentPlan = LspShipmentUtils.getOrCreateShipmentPlan(lspPlan, lspShipmentWithTime.getId());
+ double endOfTransportTime = shipmentPlan.getMostRecentEntry().getEndTime() + bufferTime;
+ LspShipmentUtils.setTimeOfLspShipment(lspShipmentWithTime, endOfTransportTime);
+ for (LogisticChainElement element : resource.getClientElements()) {
+ if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipmentWithTime)) {
+ element.getIncomingShipments().getLspShipmentsWTime().remove(lspShipmentWithTime);
+ element.getOutgoingShipments().getLspShipmentsWTime().add(lspShipmentWithTime);
+ if (element.getNextElement() != null) {
+ element.getNextElement().getIncomingShipments().getLspShipmentsWTime().add(lspShipmentWithTime);
+ element.getOutgoingShipments().getLspShipmentsWTime().remove(lspShipmentWithTime);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorer.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorer.java
new file mode 100644
index 00000000000..4f4916c0510
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorer.java
@@ -0,0 +1,43 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import org.matsim.api.core.v01.population.Activity;
+import org.matsim.core.controler.listener.ControlerListener;
+import org.matsim.core.events.handler.EventHandler;
+import org.matsim.core.scoring.ScoringFunction;
+import org.matsim.freight.carriers.Carrier;
+
+/**
+ * This is somewhat similar to the MATSim core {@link ScoringFunction}, which is also used for
+ * {@link Carrier}s. A difference, however, is that it does not implement the separate methods
+ * {@link ScoringFunction#handleActivity(Activity)} etc., but is just an {@link EventHandler} and a
+ * {@link ControlerListener}. (This is, in some sense, the old design for {@link ScoringFunction},
+ * and one, where I am still not sure if the new design is truly better.) In any case, here there is
+ * not a question: LSP scoring is not so much about activities and legs, since those are handled
+ * through the carrier scoring, and need to be pulled in by the lsp scoring if the company is
+ * vertically integrated (i.e. if the LSP owns its carriers).
+ *
+ *
also @see {@link LSPScorerFactory}
+ */
+public interface LSPScorer extends LSPSimulationTracker {
+ double getScoreForCurrentPlan();
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorerFactory.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorerFactory.java
new file mode 100644
index 00000000000..e5a5d7ea78f
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorerFactory.java
@@ -0,0 +1,7 @@
+package org.matsim.freight.logistics;
+
+import org.matsim.core.api.internal.MatsimFactory;
+
+public interface LSPScorerFactory extends MatsimFactory {
+ LSPScorer createScoringFunction();
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPSimulationTracker.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPSimulationTracker.java
new file mode 100644
index 00000000000..55d967c293b
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPSimulationTracker.java
@@ -0,0 +1,32 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import org.matsim.core.api.experimental.events.EventsManager;
+import org.matsim.core.controler.listener.ControlerListener;
+import org.matsim.core.events.handler.EventHandler;
+
+public interface LSPSimulationTracker
+ extends ControlerListener, EventHandler, HasBackpointer {
+ // In general, we set backpointers when we add to the container. So specifically, we set the
+ // backpointer to which the tracker points when the tracker is added.
+ default void setEventsManager(EventsManager eventsManager) {}
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManager.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManager.java
new file mode 100644
index 00000000000..79d7c5a64bc
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManager.java
@@ -0,0 +1,44 @@
+/*
+ * *********************************************************************** *
+ * project: org.matsim.*
+ * *********************************************************************** *
+ * *
+ * copyright : (C) 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.freight.logistics;
+
+import jakarta.inject.Provider;
+import org.matsim.core.replanning.GenericStrategyManager;
+
+/**
+ * The current (jul'22) logic of this is:
+ *
+ *
+ *
There is a null binding of this interface in {@link LSPModule}. If one wants to use
+ * strategies, this needs to be overwritten.
+ *
Normally, the strategy manager is fixed infrastructure, and should just be configured.
+ * However, since it is not yet there before injection, it also cannot be configured before
+ * injection. Core matsim solves that by writing the corresponding configuration into the
+ * config. We could, in principle, do the same here. Don't want to do this yet.
+ *
So way to configure this "in code" is to bind {@link LSPStrategyManager} to a {@link
+ * Provider } and then configure it in the provider.
+ *
+ */
+public interface LSPStrategyManager extends GenericStrategyManager {
+ // (this is mostly there so that it can be guice-bound. kai, jul'22)
+
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManagerImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManagerImpl.java
new file mode 100644
index 00000000000..f628d4f2ab4
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManagerImpl.java
@@ -0,0 +1,71 @@
+package org.matsim.freight.logistics;
+
+import java.util.List;
+import org.matsim.api.core.v01.population.HasPlansAndId;
+import org.matsim.core.replanning.GenericPlanStrategy;
+import org.matsim.core.replanning.GenericStrategyManager;
+import org.matsim.core.replanning.GenericStrategyManagerImpl;
+import org.matsim.core.replanning.ReplanningContext;
+import org.matsim.core.replanning.selectors.PlanSelector;
+
+/**
+ * Normally, this would be infrastructure that is configurable via the config. Since we ain't there
+ * yet, the way to configure this is something like:
+ *
+ *
+ */
+public class LSPStrategyManagerImpl implements LSPStrategyManager {
+ final GenericStrategyManager delegate = new GenericStrategyManagerImpl<>();
+
+ @Override
+ public void addStrategy(
+ GenericPlanStrategy strategy, String subpopulation, double weight) {
+ delegate.addStrategy(strategy, subpopulation, weight);
+ }
+
+ @Override
+ public void run(
+ Iterable extends HasPlansAndId> persons,
+ int iteration,
+ ReplanningContext replanningContext) {
+ delegate.run(persons, iteration, replanningContext);
+ }
+
+ @Override
+ public void setMaxPlansPerAgent(int maxPlansPerAgent) {
+ delegate.setMaxPlansPerAgent(maxPlansPerAgent);
+ }
+
+ @Override
+ public void addChangeRequest(
+ int iteration,
+ GenericPlanStrategy strategy,
+ String subpopulation,
+ double newWeight) {
+ delegate.addChangeRequest(iteration, strategy, subpopulation, newWeight);
+ }
+
+ @Override
+ public void setPlanSelectorForRemoval(PlanSelector planSelector) {
+ delegate.setPlanSelectorForRemoval(planSelector);
+ }
+
+ @Override
+ public List> getStrategies(String subpopulation) {
+ return delegate.getStrategies(subpopulation);
+ }
+
+ @Override
+ public List getWeights(String subpopulation) {
+ return delegate.getWeights(subpopulation);
+ }
+}
diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPUtils.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPUtils.java
new file mode 100644
index 00000000000..4f0ae7a718d
--- /dev/null
+++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPUtils.java
@@ -0,0 +1,271 @@
+/*
+ * *********************************************************************** *
+ * * project: org.matsim.*
+ * * *********************************************************************** *
+ * * *
+ * * copyright : (C) 2022 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.freight.logistics;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import org.matsim.api.core.v01.Id;
+import org.matsim.api.core.v01.Scenario;
+import org.matsim.freight.carriers.Carriers;
+import org.matsim.freight.carriers.CarriersUtils;
+import org.matsim.freight.logistics.shipment.LspShipment;
+import org.matsim.freight.logistics.shipment.LspShipmentPlan;
+import org.matsim.utils.objectattributes.attributable.Attributable;
+
+public final class LSPUtils {
+ private static final String lspsString = "lsps";
+
+ private LSPUtils() {} // do not instantiate
+
+ public static LSPPlan createLSPPlan() {
+ return new LSPPlanImpl();
+ }
+
+
+ /**
+ * Checks, is the plan the selcted plan.
+ * (This is adapted copy from PersonUtils.isSelected(plan) )
+ * @param lspPlan the plan to check
+ * @return true if the plan is the selected plan. false, if not.
+ */
+ public static boolean isPlanTheSelectedPlan(LSPPlan lspPlan) {
+ return lspPlan.getLSP().getSelectedPlan() == lspPlan;
+ }
+
+ public static LogisticChainScheduler createForwardLogisticChainScheduler() {
+ return new ForwardLogisticChainSchedulerImpl();
+ }
+
+ public static WaitingShipments createWaitingShipments() {
+ return new WaitingShipmentsImpl();
+ }
+
+ public static void addLSPs(Scenario scenario, LSPs lsps) {
+ Carriers carriers = CarriersUtils.addOrGetCarriers(scenario);
+ // Register carriers from all lsps
+ for (LSP lsp : lsps.getLSPs().values()) {
+ for (LSPResource lspResource : lsp.getResources()) {
+ if (lspResource instanceof LSPCarrierResource lspCarrierResource) {
+ carriers.addCarrier(lspCarrierResource.getCarrier());
+ }
+ }
+ }
+ scenario.addScenarioElement(lspsString, lsps);
+ }
+
+ public static LSPs getLSPs(Scenario scenario) {
+ Object result = scenario.getScenarioElement(lspsString);
+ if (result == null) {
+ throw new RuntimeException(
+ "there is no scenario element of type "
+ + lspsString
+ + ". You will need something like LSPUtils.addLSPs( scenario, lsps) somewhere.");
+ }
+ return (LSPs) result;
+ }
+
+ public static Double getVariableCost(Attributable attributable) {
+ return (Double) attributable.getAttributes().getAttribute("variableCost");
+ }
+
+ public static void setVariableCost(Attributable attributable, Double variableCost) {
+ attributable.getAttributes().putAttribute("variableCost", variableCost);
+ }
+
+ public static Double getFixedCost(Attributable attributable) {
+ return (Double) attributable.getAttributes().getAttribute("fixedCost");
+ }
+
+ // The following would be closer to how we have done it elsewhere (scenario containers are
+ // mutable). kai, may'22'
+ // public static LSPs createOrGetLPSs( Scenario scenario ){
+ // Object result = scenario.getScenarioElement( lspsString );
+ // LSPs lsps;
+ // if ( result != null ) {
+ // lsps = (LSPs) result;
+ // } else {
+ // lsps = new LSPs( );
+ // scenario.addScenarioElement( lspsString, lsps );
+ // }
+ // return lsps;
+ // }
+
+ public static void setFixedCost(Attributable attributable, Double fixedCost) {
+ attributable.getAttributes().putAttribute("fixedCost", fixedCost);
+ }
+
+ /**
+ * Gives back the {@link LspShipment} object of the {@link LSP}, which matches to the shipmentId
+ *
+ * @param lsp In this LSP this method tries to find the shipment.
+ * @param shipmentId Id of the shipment that should be found.
+ * @return the lspShipment object or null, if it is not found.
+ */
+ public static LspShipment findLspShipment(LSP lsp, Id shipmentId) {
+ for (LspShipment lspShipment : lsp.getLspShipments()) {
+ if (lspShipment.getId().equals(shipmentId)) {
+ return lspShipment;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the {@link LspShipmentPlan} of an {@link LspShipment}.
+ *
+ * @param lspPlan the lspPlan: It contains the information of its shipmentPlans
+ * @param shipmentId Id of the shipment that should be found.
+ * @return the shipmentPlan object or null, if it is not found.
+ */
+ public static LspShipmentPlan findLspShipmentPlan(LSPPlan lspPlan, Id shipmentId) {
+ for (LspShipmentPlan lspShipmentPlan : lspPlan.getShipmentPlans()) {
+ if (lspShipmentPlan.getLspShipmentId().equals(shipmentId)) {
+ return lspShipmentPlan;
+ }
+ }
+ return null;
+ }
+
+ public enum LogicOfVrp {serviceBased, shipmentBased}
+
+ public static final class LSPBuilder {
+ final Collection resources;
+ final Id id;
+ LogisticChainScheduler logisticChainScheduler;
+ LSPPlan initialPlan;
+
+ private LSPBuilder(Id id) {
+ this.id = id; // this line was not there until today. kai, may'22
+ this.resources = new ArrayList<>();
+ }
+
+ public static LSPBuilder getInstance(Id id) {
+ return new LSPBuilder(id);
+ }
+
+ public LSPBuilder setLogisticChainScheduler(LogisticChainScheduler logisticChainScheduler) {
+ this.logisticChainScheduler = logisticChainScheduler;
+ return this;
+ }
+
+ // /**
+ // * @deprecated -- It feels attractive to attach this to the "agent". A big disadvantage
+ // with this approach, however, is that
+ // * we cannot use injection ... since we cannot inject as many scorers as we have agents.
+ // (At least this is what I think.) Which means
+ // * that the approach in matsim core and in carriers to have XxxScoringFunctionFactory is
+ // better for what we are doing here. yyyyyy So
+ // * this needs to be changed. kai, jul'22
+ // */
+ // public LSPBuilder setSolutionScorer(LSPScorer scorer) {
+ // this.scorer = scorer;
+ // return this;
+ // }
+
+ // /**
+ // * @deprecated -- It feels attractive to attach this to the "agent". A big disadvantage
+ // with this approach, however, is that
+ // * we cannot use injection ... since we cannot inject as many replanners as we have
+ // agents. (At least this is what I think.) yyyyyy So
+ // * this needs to be changed. kai, jul'22
+ // */
+ // public LSPBuilder setReplanner(LSPReplanner replanner) {
+ // this.replanner = replanner;
+ // return this;
+ // }
+ // never used. Thus disabling it. kai, jul'22
+
+ public LSPBuilder setInitialPlan(LSPPlan plan) {
+ this.initialPlan = plan;
+ for (LogisticChain solution : plan.getLogisticChains()) {
+ for (LogisticChainElement element : solution.getLogisticChainElements()) {
+ if (!resources.contains(element.getResource())) {
+ resources.add(element.getResource());
+ }
+ }
+ }
+ return this;
+ }
+
+ public LSP build() {
+ return new LSPImpl(this);
+ }
+ }
+
+ public static final class LogisticChainBuilder {
+ final Id id;
+ final Collection