From e7a6c23ba9b068f7d69298e14a81439c8e84277c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 4 Jan 2024 14:12:19 +0100 Subject: [PATCH] remove code replicating DrtOfferAcceptor --- .../alonso_mora/AlonsoMoraConfigGroup.java | 14 ---- .../alonso_mora/AlonsoMoraModeQSimModule.java | 7 +- .../alonso_mora/AlonsoMoraOfferAcceptor.java | 19 +++++ .../algorithm/AlonsoMoraAlgorithm.java | 70 ++++++++++--------- .../algorithm/AlonsoMoraRequest.java | 4 +- .../algorithm/DefaultAlonsoMoraRequest.java | 28 ++++---- .../function/DefaultAlonsoMoraFunction.java | 6 +- .../graphs/DefaultRequestGraphTest.java | 6 ++ .../graphs/DefaultVehicleGraphTest.java | 6 ++ .../alonso_mora/glpk/GlpkExamplesIT.java | 6 +- 10 files changed, 97 insertions(+), 69 deletions(-) create mode 100644 core/src/main/java/org/matsim/alonso_mora/AlonsoMoraOfferAcceptor.java diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigGroup.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigGroup.java index cb5e561..b547dda 100644 --- a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigGroup.java +++ b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigGroup.java @@ -59,15 +59,6 @@ public AlonsoMoraConfigGroup() { @PositiveOrZero public double maximumQueueTime = 0.0; - @Parameter - @Comment("By default, the algorithm updates the latest pickup time for a request to the planned pickup time that has been calculated at the first assignment. Subsequent dispatching steps must adhere to that value. Using this flag, this functionality may be turned off.") - public boolean usePlannedPickupTime = true; - - @Parameter - @Comment("See usePlannedPickupTime. When updating the required pickup time, the operator may add a little slack to provide a more pessimistic estimate. The value specified here is added to the planned pickup time on first assignment if usePlannedPickupTime is enabled.") - @PositiveOrZero - public double plannedPickupTimeSlack = 0; - @Parameter @Comment("Under ideal and correctly configured freeflow conditions, the algorithm will predict exactly what the vehicles will do in simulation. If this flag is enabled, the algorithm will perform self-checks to verify that this is the case. Use to verify your freeflow condiditons.") public boolean checkDeterminsticTravelTimes = false; @@ -444,11 +435,6 @@ protected void checkConsistency(Config config) { Verify.verify(loggingInterval % assignmentInterval == 0, "Logging interval must be multiple of the assignment interval"); - if (plannedPickupTimeSlack > 0.0) { - Verify.verify(!usePlannedPickupTime, - "Non-zero value for plannedPickupTimeSlack has no effect if usePlannedPickupTime is false"); - } - Verify.verifyNotNull(assignmentSolver); Verify.verifyNotNull(travelTimeEstimator); Verify.verifyNotNull(congestionMitigation); diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeQSimModule.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeQSimModule.java index 632d42c..f7f3519 100644 --- a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeQSimModule.java +++ b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeQSimModule.java @@ -57,6 +57,7 @@ import org.matsim.contrib.drt.optimizer.DrtOptimizer; import org.matsim.contrib.drt.optimizer.QSimScopeForkJoinPoolHolder; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; +import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.schedule.DrtStayTaskEndTimeCalculator; import org.matsim.contrib.drt.schedule.DrtTaskFactory; @@ -391,7 +392,8 @@ protected void configureQSim() { getter.getModal(QSimScopeForkJoinPoolHolder.class).getPool(), // getter.getModal(TravelTimeEstimator.class), // drtConfig.stopDuration, // - new AlgorithmSettings(amConfig)); + new AlgorithmSettings(amConfig), // + getter.getModal(DrtOfferAcceptor.class)); })); bindModal(AlonsoMoraVehicleFactory.class).toInstance(vehicle -> new DefaultAlonsoMoraVehicle(vehicle)); @@ -415,5 +417,8 @@ protected void configureQSim() { bindModal(AlonsoMoraConfigGroup.class).toInstance(amConfig); addModalComponent(DrtOptimizer.class, modalKey(AlonsoMoraOptimizer.class)); + + bindModal(AlonsoMoraOfferAcceptor.class).toInstance(new AlonsoMoraOfferAcceptor()); + bindModal(DrtOfferAcceptor.class).to(modalKey(AlonsoMoraOfferAcceptor.class)); } } diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraOfferAcceptor.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraOfferAcceptor.java new file mode 100644 index 0000000..6ffc658 --- /dev/null +++ b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraOfferAcceptor.java @@ -0,0 +1,19 @@ +package org.matsim.alonso_mora; + +import java.util.Optional; + +import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; +import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; +import org.matsim.contrib.drt.passenger.DrtRequest; + +public class AlonsoMoraOfferAcceptor implements DrtOfferAcceptor { + @Override + public Optional acceptDrtOffer(DrtRequest request, double departureTime, double arrivalTime) { + return Optional.of(AcceptedDrtRequest.newBuilder() // + .request(request) // + .earliestStartTime(request.getEarliestStartTime()) // + .latestArrivalTime(request.getLatestArrivalTime()) // + .latestStartTime(departureTime) // + .build()); + } +} diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraAlgorithm.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraAlgorithm.java index b7c9618..a9c2f34 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraAlgorithm.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraAlgorithm.java @@ -37,6 +37,7 @@ import org.matsim.alonso_mora.travel_time.TravelTimeEstimator; import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; +import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; import org.matsim.contrib.drt.passenger.DrtRequest; import org.matsim.contrib.drt.schedule.DefaultDrtStopTask; import org.matsim.contrib.drt.scheduler.EmptyVehicleRelocator; @@ -74,6 +75,7 @@ public class AlonsoMoraAlgorithm { private final AlonsoMoraScheduler scheduler; private final AlonsoMoraFunction function; private final ForkJoinPool forkJoinPool; + private final DrtOfferAcceptor offerAcceptor; private final EventsManager eventsManager; private final String mode; @@ -99,7 +101,7 @@ public class AlonsoMoraAlgorithm { public AlonsoMoraAlgorithm(Fleet fleet, AssignmentSolver assignmentSolver, RelocationSolver rebalancingSolver, AlonsoMoraFunction function, AlonsoMoraScheduler scheduler, EventsManager eventsManager, String mode, AlonsoMoraVehicleFactory vehicleFactory, ForkJoinPool forkJoinPool, TravelTimeEstimator travelTimeEstimator, - double stopDuration, AlgorithmSettings settings) { + double stopDuration, AlgorithmSettings settings, DrtOfferAcceptor offerAcceptor) { this.assignmentSolver = assignmentSolver; this.rebalancingSolver = rebalancingSolver; this.scheduler = scheduler; @@ -110,6 +112,7 @@ public AlonsoMoraAlgorithm(Fleet fleet, AssignmentSolver assignmentSolver, Reloc this.travelTimeEstimator = travelTimeEstimator; this.stopDuration = stopDuration; this.settings = settings; + this.offerAcceptor = offerAcceptor; // Create vehicle wrappers vehicles = new ArrayList<>(fleet.getVehicles().size()); @@ -430,9 +433,7 @@ private void processAssignedRequests(Solution solution, double now, Information for (AlonsoMoraRequest request : trip.getRequests()) { Verify.verify(newAssignedRequests.add(request), "Request is assigned twice!"); - // Set the vehicle - request.setVehicle(trip.getVehicle()); - + // obtain times double expectedPickupTime = Double.NaN; double expectedDropoffTime = Double.NaN; @@ -444,26 +445,7 @@ private void processAssignedRequests(Solution solution, double now, Information if (stop.getType().equals(StopType.Pickup)) { // We're looking at the pickup stop - expectedPickupTime = stop.getTime(); - - if (settings.usePlannedPickupTime) { - // We have a waiting time slack, i.e. we move the pickup constraint to the - // promised value from the assignment plus a small slack, which, by default, is - // zero. So in the usual case, we require that the request be picked up at the - // time that we promise at the first assignment. - - // ... but adding the slack cannot exceed the initial pickup requirement - double plannedPickupTime = expectedPickupTime + settings.plannedPickupTimeSlack; - plannedPickupTime = Math.min(plannedPickupTime, request.getLatestPickupTime()); - - request.setPlannedPickupTime(plannedPickupTime); - } - - if (request.isAssigned() && !request.getVehicle().equals(trip.getVehicle())) { - // Just for statistics: We track whether a request is assigned to a new vehicle - information.numberOfReassignments++; - } } else if (stop.getType().equals(StopType.Dropoff)) { // We're looking at the dropoff stop expectedDropoffTime = stop.getTime(); @@ -471,11 +453,39 @@ private void processAssignedRequests(Solution solution, double now, Information } } - /* For each DRT request, we create a scheduling event */ - AcceptedDrtRequest drtRequest = request.getAcceptedDrtRequest(); - eventsManager.processEvent( - new PassengerRequestScheduledEvent(now, mode, drtRequest.getId(), drtRequest.getPassengerIds(), - trip.getVehicle().getVehicle().getId(), expectedPickupTime, expectedDropoffTime)); + Verify.verify(Double.isFinite(expectedPickupTime)); + Verify.verify(Double.isFinite(expectedDropoffTime)); + + // check if request has already been accepted + Optional acceptedRequest = Optional.ofNullable(request.getAcceptedDrtRequest()); + + if (acceptedRequest.isEmpty()) { + // first need to check if user accepts the offer + + acceptedRequest = offerAcceptor.acceptDrtOffer(request.getDrtRequest(), + expectedPickupTime, expectedDropoffTime); + + if (acceptedRequest.isPresent()) { + request.accept(acceptedRequest.get()); + } + } + + // now proceed with the request, otherwise it is rejected + if (acceptedRequest.isPresent()) { + // Set the vehicle + request.setVehicle(trip.getVehicle()); + + // publish scheduling event + eventsManager.processEvent(new PassengerRequestScheduledEvent(now, mode, + request.getDrtRequest().getId(), request.getDrtRequest().getPassengerIds(), + trip.getVehicle().getVehicle().getId(), expectedPickupTime, expectedDropoffTime)); + + // statistics + if (request.isAssigned() && !request.getVehicle().equals(trip.getVehicle())) { + // Just for statistics: We track whether a request is assigned to a new vehicle + information.numberOfReassignments++; + } + } } } @@ -733,8 +743,6 @@ static public class AlgorithmSettings { final boolean useBindingRelocations; final boolean useStepwiseRelocation; final boolean preserveVehicleAssignments; - final boolean usePlannedPickupTime; - final double plannedPickupTimeSlack; final double relocationInterval; final boolean allowBareReassignment; final double loggingInterval; @@ -746,8 +754,6 @@ public AlgorithmSettings(AlonsoMoraConfigGroup config) { this.useBindingRelocations = config.useBindingRelocations; this.useStepwiseRelocation = config.useStepwiseRelocation; this.preserveVehicleAssignments = config.congestionMitigation.preserveVehicleAssignments; - this.usePlannedPickupTime = config.usePlannedPickupTime; - this.plannedPickupTimeSlack = config.plannedPickupTimeSlack; this.relocationInterval = config.relocationInterval; this.allowBareReassignment = config.congestionMitigation.allowBareReassignment; this.loggingInterval = config.loggingInterval; diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequest.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequest.java index a4394b2..f1cd8bb 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequest.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequest.java @@ -33,7 +33,7 @@ public interface AlonsoMoraRequest extends Comparable { double getLatestAssignmentTime(); DrtRequest getDrtRequest(); - + AcceptedDrtRequest getAcceptedDrtRequest(); public int getSize(); @@ -57,4 +57,6 @@ public interface AlonsoMoraRequest extends Comparable { public double getDirectRideDistance(); public double getEarliestPickupTime(); + + public void accept(AcceptedDrtRequest acceptedRequest); } diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequest.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequest.java index 9ddbf09..9e5a0d9 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequest.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequest.java @@ -6,6 +6,7 @@ import org.matsim.contrib.drt.schedule.DrtStopTask; import org.matsim.contrib.dvrp.schedule.Task.TaskStatus; +import com.google.common.base.Preconditions; import com.google.common.base.Verify; /** @@ -137,10 +138,6 @@ public DrtRequest getDrtRequest() { } public AcceptedDrtRequest getAcceptedDrtRequest() { - if (acceptedDrtRequest == null) { - acceptedDrtRequest = AcceptedDrtRequest.createFromOriginalRequest(drtRequest); - } - return acceptedDrtRequest; } @@ -208,17 +205,6 @@ public double getPlannedPickupTime() { } } - /** - * Sets the planned pickup time. This only happens once on the first assignment, - * afterwards the pickup time has been promised and can not be changed again. - */ - @Override - public void setPlannedPickupTime(double plannedPickupTime) { - if (Double.isNaN(this.plannedPickupTime)) { - this.plannedPickupTime = plannedPickupTime; - } - } - @Override public double getDirectRideDistance() { return directRideDistance; @@ -233,4 +219,16 @@ public double getEarliestPickupTime() { public String toString() { return drtRequest.toString(); } + + @Override + public void accept(AcceptedDrtRequest acceptedRequest) { + Preconditions.checkArgument(this.acceptedDrtRequest == null); + this.acceptedDrtRequest = acceptedRequest; + this.plannedPickupTime = acceptedRequest.getLatestStartTime(); + } + + @Override + public void setPlannedPickupTime(double plannedPickupTime) { + throw new IllegalStateException(); + } } diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/function/DefaultAlonsoMoraFunction.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/function/DefaultAlonsoMoraFunction.java index 689674c..370f464 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/function/DefaultAlonsoMoraFunction.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/function/DefaultAlonsoMoraFunction.java @@ -82,8 +82,8 @@ public boolean checkShareability(AlonsoMoraRequest firstRequest, AlonsoMoraReque Map requiredPickupTimes = new HashMap<>(); Map requiredDropoffTimes = new HashMap<>(); - requiredPickupTimes.put(firstRequest, firstRequest.getLatestPickupTime()); - requiredPickupTimes.put(secondRequest, secondRequest.getLatestPickupTime()); + requiredPickupTimes.put(firstRequest, firstRequest.getPlannedPickupTime()); + requiredPickupTimes.put(secondRequest, secondRequest.getPlannedPickupTime()); requiredDropoffTimes.put(firstRequest, firstRequest.getLatestDropoffTime()); requiredDropoffTimes.put(secondRequest, secondRequest.getLatestDropoffTime()); @@ -101,7 +101,7 @@ public boolean checkShareability(AlonsoMoraRequest firstRequest, AlonsoMoraReque switch (stop.getType()) { case Pickup: - double maximumPickupTime = stop.getRequest().getLatestPickupTime(); + double maximumPickupTime = stop.getRequest().getPlannedPickupTime(); double calculatedPickupTime = stop.getTime(); if (calculatedPickupTime > maximumPickupTime) { diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultRequestGraphTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultRequestGraphTest.java index 5afd1fb..001c894 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultRequestGraphTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultRequestGraphTest.java @@ -226,6 +226,12 @@ public double getEarliestPickupTime() { // TODO Auto-generated method stub return 0; } + + @Override + public void accept(AcceptedDrtRequest acceptedRequest) { + // TODO Auto-generated method stub + + } } private static class MockFunction implements AlonsoMoraFunction { diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultVehicleGraphTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultVehicleGraphTest.java index 3e2cfde..2c3f1f1 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultVehicleGraphTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultVehicleGraphTest.java @@ -463,6 +463,12 @@ public double getEarliestPickupTime() { // TODO Auto-generated method stub return 0; } + + @Override + public void accept(AcceptedDrtRequest acceptedRequest) { + // TODO Auto-generated method stub + + } } private AlonsoMoraVehicle mockVehicle() { diff --git a/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkExamplesIT.java b/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkExamplesIT.java index c2bf1a6..3e89a9e 100644 --- a/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkExamplesIT.java +++ b/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkExamplesIT.java @@ -132,9 +132,9 @@ public void testRunAlonsoMoraWithGlpk() { var expectedStats = Stats.newBuilder() // .rejectionRate(0.04) // .rejections(14) // - .waitAverage(269.76) // - .inVehicleTravelTimeMean(376.47) // - .totalTravelTimeMean(646.23) // + .waitAverage(268.97) // + .inVehicleTravelTimeMean(370.26) // + .totalTravelTimeMean(639.24) // .build(); verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats);