Skip to content

Commit

Permalink
Merge branch 'master' into mode-restriction
Browse files Browse the repository at this point in the history
  • Loading branch information
paulheinr authored Jul 24, 2024
2 parents 3c72fcb + 2a40907 commit a09c238
Show file tree
Hide file tree
Showing 92 changed files with 1,250 additions and 703 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -667,18 +667,25 @@ else if (samplingOption.equals("changeDemandOnLocation")) {
int demandForThisLink = calculateDemandBasedOnLinkLength(countOfLinks, distributedDemand, demandToDistribute, possibleLinksForService.size(),
sumOfPossibleLinkLength, link);
countOfLinks++;
double serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit()
* demandForThisLink;
Id<CarrierService> idNewService = Id.create(
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;
Id<CarrierService> idNewService = Id.create(
createJobId(scenario, newDemandInformationElement, link.getId(), null),
CarrierService.class);
if (demandToDistribute > 0 && demandForThisLink > 0) {
CarrierService thisService = CarrierService.Builder.newInstance(idNewService, link.getId())
.setCapacityDemand(demandForThisLink).setServiceDuration(serviceTime)
if (demandToDistribute > 0 && singleDemandForThisLink > 0) {
CarrierService thisService = CarrierService.Builder.newInstance(idNewService, link.getId())
.setCapacityDemand(singleDemandForThisLink).setServiceDuration(serviceTime)
.setServiceStartTimeWindow(newDemandInformationElement.getFirstJobElementTimeWindow())
.build();
CarriersUtils.getCarriers(scenario).getCarriers().values().iterator().next().getServices()
.put(thisService.getId(), thisService);
thisCarrier.getServices().put(thisService.getId(), thisService);
}
}
distributedDemand = distributedDemand + demandForThisLink;
}
Expand All @@ -705,24 +712,31 @@ else if (samplingOption.equals("changeDemandOnLocation")) {
.skip(rand.nextInt(usedServiceLocations.size() - 1)).findFirst().get()));
}
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();
else
serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit() * demandForThisLink;
usedServiceLocations.add(link.getId().toString());

double serviceTime;
if (demandToDistribute == 0)
serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit();
else
serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit() * demandForThisLink;
usedServiceLocations.add(link.getId().toString());

Id<CarrierService> idNewService = Id.create(
Id<CarrierService> idNewService = Id.create(
createJobId(scenario, newDemandInformationElement, link.getId(), null), CarrierService.class);
if ((demandToDistribute > 0 && demandForThisLink > 0) || demandToDistribute == 0) {
CarrierService thisService = CarrierService.Builder.newInstance(idNewService, link.getId())
.setCapacityDemand(demandForThisLink).setServiceDuration(serviceTime)
if ((demandToDistribute > 0 && singleDemandForThisLink > 0) || demandToDistribute == 0) {
CarrierService thisService = CarrierService.Builder.newInstance(idNewService, link.getId())
.setCapacityDemand(singleDemandForThisLink).setServiceDuration(serviceTime)
.setServiceStartTimeWindow(newDemandInformationElement.getFirstJobElementTimeWindow())
.build();
CarriersUtils.getCarriers(scenario).getCarriers()
CarriersUtils.getCarriers(scenario).getCarriers()
.get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)).getServices()
.put(thisService.getId(), thisService);
}
}
distributedDemand = distributedDemand + demandForThisLink;
}
Expand Down Expand Up @@ -1007,29 +1021,56 @@ else if (numberOfPickupLocations != null) {
private static void createSingleShipment(Scenario scenario, DemandInformationElement newDemandInformationElement,
Link linkPickup, Link linkDelivery, int demandForThisLink) {

Id<CarrierShipment> idNewShipment = Id.create(createJobId(scenario, newDemandInformationElement,
linkPickup.getId(), linkDelivery.getId()), CarrierShipment.class);
Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers()
.get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class));
int numberOfJobsForDemand = calculateNumberOfJobsForDemand(thisCarrier, demandForThisLink);

TimeWindow timeWindowPickup = newDemandInformationElement.getFirstJobElementTimeWindow();
TimeWindow timeWindowDelivery = newDemandInformationElement.getSecondJobElementTimeWindow();

double serviceTimePickup;
double serviceTimeDelivery;
if (demandForThisLink == 0) {
serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit();
serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit();
} else {
serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit() * demandForThisLink;
serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit() * demandForThisLink;
for (int i = 0; i < numberOfJobsForDemand; i++) {
Id<CarrierShipment> 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;
}
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);
}
}

/**
* 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) {
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);
}
CarrierShipment thisShipment = CarrierShipment.Builder
.newInstance(idNewShipment, linkPickup.getId(), linkDelivery.getId(), demandForThisLink)
.setPickupServiceTime(serviceTimePickup).setPickupTimeWindow(timeWindowPickup)
.setDeliveryServiceTime(serviceTimeDelivery).setDeliveryTimeWindow(timeWindowDelivery)
.build();
CarriersUtils.getCarriers(scenario).getCarriers()
.get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)).getShipments()
.put(thisShipment.getId(), thisShipment);
return 1;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,13 @@ private void createDemand(DemandGenerationOptions selectedDemandGenerationOption
*/
FreightDemandGenerationUtils.preparePopulation(population, sampleSizeInputPopulation,
upSamplePopulationTo, "changeDemandOnLocation");
case noPopulationSampling ->
/*
* If the demand sample is equal to the population sample, the demand is created
* based on the given population and the set input population sampleSize
*/
FreightDemandGenerationUtils.preparePopulation(population, sampleSizeInputPopulation,
sampleSizeInputPopulation, "noPopulationSampling");
default -> throw new RuntimeException("No valid sampling option selected!");
}
switch (selectedPopulationOption) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@
public class EDrtControlerCreator {

public static Controler createControler(Config config, boolean otfvis) {
MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config);
DrtConfigs.adjustMultiModeDrtConfig(multiModeDrtConfig, config.scoring(), config.routing());

Scenario scenario = DrtControlerCreator.createScenarioWithDrtRouteFactory(config);
ScenarioUtils.loadScenario(scenario);
return createControler(config, scenario, otfvis);
}
public static Controler createControler(Config config, Scenario scenario, boolean otfvis) {
MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config);
DrtConfigs.adjustMultiModeDrtConfig(multiModeDrtConfig, config.scoring(), config.routing());

Controler controler = new Controler(scenario);
controler.addOverridingModule(new MultiModeEDrtModule());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.matsim.contrib.drt.extension.operations;

import org.matsim.api.core.v01.Scenario;
import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup;
import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesModeModule;
import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesQSimModule;
Expand Down Expand Up @@ -27,10 +28,25 @@ public class DrtOperationsControlerCreator {
* @return
*/
public static Controler createControler(Config config, boolean otfvis) {
MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config);

Controler controler = DrtControlerCreator.createControler(config, otfvis);
return prepareController(config, controler);
}

/**
* Creates a controller in one step.
*
* @param config
* @param scenario
* @param otfvis
* @return
*/
public static Controler createControler(Config config, Scenario scenario, boolean otfvis) {
Controler controler = DrtControlerCreator.createControler(config, scenario, otfvis);
return prepareController(config, controler);
}

private static Controler prepareController(Config config, Controler controler) {
MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config);
for (DrtConfigGroup drtCfg : multiModeDrtConfig.getModalElements()) {
controler.addOverridingModule(new ShiftDrtModeModule(drtCfg));
controler.addOverridingQSimModule(new DrtModeQSimModule(drtCfg, new ShiftDrtModeOptimizerQSimModule(drtCfg)));
Expand All @@ -40,7 +56,6 @@ public static Controler createControler(Config config, boolean otfvis) {
}

controler.configureQSimComponents(DvrpQSimComponents.activateAllModes(multiModeDrtConfig));

return controler;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.matsim.contrib.drt.extension.operations;

import org.matsim.api.core.v01.Scenario;
import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup;
import org.matsim.contrib.drt.extension.edrt.run.EDrtControlerCreator;
import org.matsim.contrib.drt.extension.operations.eshifts.charging.ShiftOperatingVehicleProvider;
Expand All @@ -24,11 +25,19 @@
public class EDrtOperationsControlerCreator {

public static Controler createControler(Config config, boolean otfvis) {

MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config);

Controler controler = EDrtControlerCreator.createControler(config, otfvis);
prepareController(config, controler);
return controler;
}

public static Controler createControler(Config config, Scenario scenario, boolean otfvis) {
Controler controler = EDrtControlerCreator.createControler(config, scenario, otfvis);
prepareController(config, controler);
return controler;
}

private static void prepareController(Config config, Controler controler) {
MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config);
for (DrtConfigGroup drtCfg : multiModeDrtConfig.getModalElements()) {
controler.addOverridingModule(new ShiftDrtModeModule(drtCfg));
controler.addOverridingQSimModule(new DrtModeQSimModule(drtCfg, new ShiftDrtModeOptimizerQSimModule(drtCfg)));
Expand All @@ -39,14 +48,11 @@ public static Controler createControler(Config config, boolean otfvis) {
controler.addOverridingModule(new DrtShiftEfficiencyModeModule(drtCfg));
}


controler.addOverridingQSimModule(new AbstractQSimModule() {
@Override
protected void configureQSim() {
this.bind(IdleDischargingHandler.VehicleProvider.class).to(ShiftOperatingVehicleProvider.class);
}
});

return controler;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# DRT Operations

Provides functionality to realistically simulate operational aspects,
designed for, bot not limited to, non-autonomous services.

Initially developed for MOIA GmbH

If used, please cite:

Felix Zwick, Nico Kuehnel, Sebastian Hörl.
Shifts in perspective: Operational aspects in (non-)autonomous
ride-pooling simulations.
Transportation Research Part A: Policy and Practice,
Volume 165, 2022, Pages 300-320.
https://doi.org/10.1016/j.tra.2022.09.001.


## Core features:

- Operation facilities
- (Driver) shifts


The entry point for setting up a simulation are the specific control(l)er creators:
- DrtOperationsControlerCreator
- or
- EDrtOperationsControlerCreator
- in the electric vehicles case

## Operation Facilities
Operation facilities are meant to represent hubs and in-field break locations.
The facilities have a capacity that cannot be exceeded and may be linked to
existing chargers via the id.

(Driver) shifts may only start or end at operation facilities in the default setup.
Vehicles will route to operation facilities to end a shift or for scheduling a break.

Operational facilities may be described with an xml file like this:
```
<facilities>
<facility id="1" linkId="274110" x="4478595" y="5304631" chargerId="1" capacity="20" type="hub">
<chargers>
<charger id="1"/>
<charger id="2"/>
</chargers>
</facility>
</facilities>
```

## Shifts
Shifts define periods in which vehicles may be active serving passengers.
Shifts are dynamically assigned to vehicles.

In autonomous settings, shifts may be used to model up- and down-time and/or cleaning
cycles.

Shifts have a start and end time and can optionally have a break which is defined
by earliest start and latest end as well as a duration. Optionally, as operation
facility id may be defined to control the location of the start/end of the shift.

Shifts may be described in an xml file likes this:
```
<shifts>
<shift id="0" start="14400" end="45000" operationFacilityId="1">
<break earliestStart="28800.0" latestEnd="32400.0" duration="1800.0"/>
</shift>
<shift id="1" start="14400" end="45000" operationFacilityId="1">
<break earliestStart="28800.0" latestEnd="32400.0" duration="1800.0"/>
</shift>
</shifts>
```

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
package org.matsim.contrib.drt.extension.operations.eshifts.dispatcher;

import org.matsim.contrib.drt.extension.operations.eshifts.fleet.EvShiftDvrpVehicle;
import org.matsim.contrib.drt.extension.operations.eshifts.schedule.EDrtWaitForShiftStayTask;
import org.matsim.contrib.drt.extension.operations.eshifts.schedule.EDrtWaitForShiftTask;
import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams;
import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.AssignShiftToVehicleLogic;
import org.matsim.contrib.drt.extension.operations.shifts.fleet.ShiftDvrpVehicle;
Expand Down Expand Up @@ -37,8 +37,8 @@ public boolean canAssignVehicleToShift(ShiftDvrpVehicle vehicle, DrtShift shift)
// no, if charging
if(vehicle.getSchedule().getStatus() == Schedule.ScheduleStatus.STARTED) {
final Task currentTask = vehicle.getSchedule().getCurrentTask();
if (currentTask instanceof EDrtWaitForShiftStayTask) {
if (((EDrtWaitForShiftStayTask) currentTask).getChargingTask() != null) {
if (currentTask instanceof EDrtWaitForShiftTask) {
if (((EDrtWaitForShiftTask) currentTask).getChargingTask() != null) {
if (currentTask.getEndTime() > shift.getStartTime()) {
return false;
}
Expand Down
Loading

0 comments on commit a09c238

Please sign in to comment.