Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add router binding for complex request unscheduling #3340

Merged
merged 5 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@
import org.matsim.contrib.dvrp.fleet.DvrpVehicleLookup;
import org.matsim.contrib.dvrp.optimizer.VrpOptimizer;
import org.matsim.contrib.dvrp.passenger.*;
import org.matsim.contrib.dvrp.router.TimeAsTravelDisutility;
import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule;
import org.matsim.contrib.dvrp.schedule.ScheduleTimingUpdater;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.mobsim.framework.MobsimTimer;
import org.matsim.core.mobsim.qsim.QSim;
import org.matsim.core.router.speedy.SpeedyALTFactory;
import org.matsim.core.router.util.LeastCostPathCalculator;
import org.matsim.core.router.util.TravelDisutility;
import org.matsim.core.router.util.TravelTime;

public class PrebookingModeQSimModule extends AbstractDvrpModeQSimModule {
Expand Down Expand Up @@ -97,6 +100,10 @@ protected void configureQSim() {
bindModal(RequestUnscheduler.class).to(modalKey(SimpleRequestUnscheduler.class));
break;
case Routing:
bindModal(LeastCostPathCalculator.class).toProvider(modalProvider(getter ->
new SpeedyALTFactory().createPathCalculator(getter.getModal(Network.class),
new TimeAsTravelDisutility(getter.getModal(TravelTime.class)), getter.getModal(TravelTime.class)
)));
bindModal(RequestUnscheduler.class).to(modalKey(ComplexRequestUnscheduler.class));
break;
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void unscheduleRequest(double now, Id<DvrpVehicle> vehicleId, Id<Request>
DvrpVehicle vehicle = vehicleLookup.lookupVehicle(vehicleId);
VehicleEntry vEntry = vehicleEntryFactory.create(vehicle, now);

Waypoint.Stop pickupStop = null;
Waypoint pickupStop = null;
Waypoint.Stop dropoffStop = null;

DrtStopTask pickupStopTask = null;
Expand All @@ -89,6 +89,15 @@ public void unscheduleRequest(double now, Id<DvrpVehicle> vehicleId, Id<Request>
}
}

if(pickupStopTask == null) {
if(vEntry.start.task.orElseThrow() instanceof DrtStopTask stopTask) {
if(stopTask.getPickupRequests().containsKey(requestId)) {
pickupStopTask = stopTask;
pickupStop = vEntry.start;
}
}
}

Verify.verifyNotNull(pickupStopTask, "Could not find request that I'm supposed to unschedule");
Verify.verifyNotNull(dropoffStopTask, "Could not find request that I'm supposed to unschedule");
Verify.verifyNotNull(pickupStop);
Expand All @@ -103,12 +112,13 @@ public void unscheduleRequest(double now, Id<DvrpVehicle> vehicleId, Id<Request>
// removed the pickup and the StopAction will handle the situation
// - or we found a stop, then it is not started yet and we can remove it

boolean removePickup = pickupStopTask.getPickupRequests().size() == 0
&& pickupStopTask.getDropoffRequests().size() == 0;
boolean removeDropoff = dropoffStopTask.getPickupRequests().size() == 0
&& dropoffStopTask.getDropoffRequests().size() == 0;
boolean removePickup = pickupStopTask.getPickupRequests().isEmpty()
&& pickupStopTask.getDropoffRequests().isEmpty()
&& pickupStop instanceof Waypoint.Stop;
boolean removeDropoff = dropoffStopTask.getPickupRequests().isEmpty()
&& dropoffStopTask.getDropoffRequests().isEmpty();

Replacement pickupReplacement = removePickup ? findReplacement(vEntry, pickupStop) : null;
Replacement pickupReplacement = removePickup ? findReplacement(vEntry, (Waypoint.Stop) pickupStop) : null;
Replacement dropoffReplacement = removeDropoff ? findReplacement(vEntry, dropoffStop) : null;

if (pickupReplacement != null && dropoffReplacement != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,4 +265,69 @@ public void notifyMobsimBeforeSimStep(MobsimBeforeSimStepEvent e) {
assertTrue(requestInfo.rejected);
}
}

@Test
void cancelLateWithComplexUnschedulerTest() {
/*
* One person requests to depart at 2000 and also is there at 2000. Another
* person asks also to depart at 2000, but only arrives at 4000, i.e. the person
* has 1000s delay.
*
* In this test we manually cancel the second request at 3000.0 (so after
* departure of the first agent).
*/

PrebookingTestEnvironment environment = new PrebookingTestEnvironment(utils) //
.addVehicle("vehicle", 1, 1) //
.addRequest("personOk", 0, 0, 5, 5, 2000.0, 0.0, 2000.0) //
.addRequest("personLate", 0, 0, 5, 5, 4000.0, 0.0, 2000.0) //
.configure(600.0, 1.3, 600.0, 60.0) //
.endTime(10.0 * 3600.0);

Controler controller = environment.build();
PrebookingParams prebookingParams = new PrebookingParams();
prebookingParams.unschedulingMode = PrebookingParams.UnschedulingMode.Routing;
PrebookingTest.installPrebooking(controller, prebookingParams);

controller.addOverridingQSimModule(new AbstractDvrpModeQSimModule("drt") {
@Override
protected void configureQSim() {
addModalQSimComponentBinding().toProvider(modalProvider(getter -> {
PrebookingManager prebookingManager = getter.getModal(PrebookingManager.class);
QSim qsim = getter.get(QSim.class);

return new MobsimBeforeSimStepListener() {
@Override
public void notifyMobsimBeforeSimStep(MobsimBeforeSimStepEvent e) {
if (e.getSimulationTime() == 3000.0) {
PlanAgent planAgent = (PlanAgent) qsim.getAgents()
.get(Id.createPersonId("personLate"));

Leg leg = TripStructureUtils.getLegs(planAgent.getCurrentPlan()).get(1);

prebookingManager.cancel(leg);
}
}
};
}));
}
});

controller.run();

{
RequestInfo requestInfo = environment.getRequestInfo().get("personOk");
assertEquals(0.0, requestInfo.submissionTime, 1e-3);
assertEquals(2061.0, requestInfo.pickupTime, 1e-3);
assertEquals(3212.0, requestInfo.dropoffTime, 1e-3); // still waited quite a bit
}

{
RequestInfo requestInfo = environment.getRequestInfo().get("personLate");
assertEquals(0.0, requestInfo.submissionTimes.get(0), 1e-3);
// agent tries a non-prebooked request upon arrival
assertEquals(4000.0, requestInfo.submissionTimes.get(1), 1e-3);
assertTrue(requestInfo.rejected);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import org.matsim.contrib.drt.stops.StaticPassengerStopDurationProvider;
import org.matsim.contrib.dvrp.fleet.DvrpVehicle;
import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule;
import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule;
import org.matsim.core.controler.Controler;
import org.matsim.testcases.MatsimTestUtils;

Expand Down Expand Up @@ -57,12 +56,20 @@ void withoutPrebookedRequests() {
}

static PrebookingParams installPrebooking(Controler controller) {
return installPrebooking(controller, true);
return installPrebooking(controller, true, new PrebookingParams());
}

static PrebookingParams installPrebooking(Controler controller, PrebookingParams prebookingParams) {
return installPrebooking(controller, true, prebookingParams);
}

static PrebookingParams installPrebooking(Controler controller, boolean installLogic) {
return installPrebooking(controller, installLogic, new PrebookingParams());
}

static PrebookingParams installPrebooking(Controler controller, boolean installLogic, PrebookingParams prebookingParams) {
DrtConfigGroup drtConfig = DrtConfigGroup.getSingleModeDrtConfig(controller.getConfig());
drtConfig.addParameterSet(new PrebookingParams());
drtConfig.addParameterSet(prebookingParams);

if (installLogic) {
AttributeBasedPrebookingLogic.install(controller, drtConfig);
Expand Down
Loading