From 05ff372cbbc24406c3d3071a96b23738b4bf5247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 16 Oct 2023 07:59:38 +0200 Subject: [PATCH] some further cleanup --- .../prebooking/dvrp/EnteringHandler.java | 24 ---------- .../dvrp/PrebookingActionCreator.java | 8 ++-- .../prebooking/dvrp/PrebookingManager.java | 19 ++++---- .../prebooking/dvrp/PrebookingModeModule.java | 2 +- .../dvrp/PrebookingModeQSimModule.java | 32 +++++++++---- .../dvrp/PrebookingRequestQueue.java | 15 ++---- .../dvrp/PrebookingStopActivity.java | 9 ++-- .../ElectricPrebookingActionCreator.java | 10 ++-- .../logic/AttributePrebookingLogic.java | 25 ++++++---- .../logic/FixedSharePrebookingLogic.java | 45 +++++++++--------- .../prebooking/logic/PopulationIterator.java | 47 +++++++++++++++++++ .../logic/TimedPrebookingLogic.java | 14 ++++-- 12 files changed, 145 insertions(+), 105 deletions(-) delete mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/EnteringHandler.java create mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/PopulationIterator.java diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/EnteringHandler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/EnteringHandler.java deleted file mode 100644 index 62887c75e27..00000000000 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/EnteringHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.matsim.contrib.drt.extension.prebooking.dvrp; - -import org.matsim.contrib.drt.extension.prebooking.events.PassengerEnteringVehicleEvent; -import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; -import org.matsim.core.api.experimental.events.EventsManager; - -/** - * Helper class to decouple event processing from PrebookingStopActivity. - * - * @author Sebastian Hörl (sebhoerl), IRT SystemX - */ -public class EnteringHandler { - private final EventsManager eventsManager; - private final String mode; - - public EnteringHandler(EventsManager eventsManager, String mode) { - this.mode = mode; - this.eventsManager = eventsManager; - } - - public void sendEnteringEvent(double now, AcceptedDrtRequest request) { - eventsManager.processEvent(new PassengerEnteringVehicleEvent(now, mode, request.getId(), request.getPassengerId())); - } -} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingActionCreator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingActionCreator.java index 303cd7e23f3..e56679f716a 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingActionCreator.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingActionCreator.java @@ -26,14 +26,14 @@ public class PrebookingActionCreator implements VrpAgentLogic.DynActionCreator { private final VrpAgentLogic.DynActionCreator delegate; private final PrebookingPassengerEngine passengerEngine; private final PassengerStopDurationProvider stopDurationProvider; - private final EnteringHandler enteringHandler; + private final PrebookingManager prebookingManager; public PrebookingActionCreator(PrebookingPassengerEngine passengerEngine, VrpAgentLogic.DynActionCreator delegate, - PassengerStopDurationProvider stopDurationProvider, EnteringHandler enteringHandler) { + PassengerStopDurationProvider stopDurationProvider, PrebookingManager prebookingManager) { this.delegate = delegate; this.passengerEngine = passengerEngine; this.stopDurationProvider = stopDurationProvider; - this.enteringHandler = enteringHandler; + this.prebookingManager = prebookingManager; } @Override @@ -44,7 +44,7 @@ public DynAction createAction(DynAgent dynAgent, DvrpVehicle vehicle, double now DrtStopTask stopTask = (DrtStopTask) task; return new PrebookingStopActivity(passengerEngine, dynAgent, stopTask, stopTask.getDropoffRequests(), stopTask.getPickupRequests(), DrtActionCreator.DRT_STOP_NAME, stopDurationProvider, vehicle, - enteringHandler); + prebookingManager); } return delegate.createAction(dynAgent, vehicle, now); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingManager.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingManager.java index 8bc142b64c4..49e93234a72 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingManager.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingManager.java @@ -11,7 +11,9 @@ import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.Person; +import org.matsim.contrib.drt.extension.prebooking.events.PassengerEnteringVehicleEvent; import org.matsim.contrib.drt.extension.prebooking.events.PassengerRequestBookedEvent; +import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; import org.matsim.contrib.dvrp.optimizer.Request; import org.matsim.contrib.dvrp.optimizer.VrpOptimizer; import org.matsim.contrib.dvrp.passenger.PassengerRequest; @@ -62,9 +64,6 @@ public class PrebookingManager implements MobsimEngine { private final List prebookingQueue = new LinkedList<>(); private final IdMap prebookedRequests = new IdMap<>(Request.class); - private final List prebookedLegs = new LinkedList<>(); - private boolean cleanupFinished = false; - public PrebookingManager(String mode, Network network, PassengerRequestCreator requestCreator, VrpOptimizer optimizer, PassengerRequestValidator requestValidator, EventsManager eventsManager) { this.network = network; @@ -97,7 +96,7 @@ public boolean isPrebookedRequest(Id requestId) { } public void prebook(Person person, Leg leg, double earliestDepartureTime) { - Verify.verify(!cleanupFinished, "Attempting to prebook a request after Mobsim has finished"); + Verify.verify(leg.getMode().equals(mode), "Invalid mode for this prebooking manager"); synchronized (prebookingQueue) { this.prebookingQueue.add(new PrebookingQueueItem(person, leg, earliestDepartureTime)); @@ -143,22 +142,20 @@ public void doSimStep(double now) { item.leg.getAttributes().putAttribute(requestAttribute, request.getId().toString()); prebookedRequests.put(request.getId(), request); - prebookedLegs.add(item.leg); } } prebookingQueue.clear(); } } + + void notifyEntering(double now, AcceptedDrtRequest request) { + eventsManager + .processEvent(new PassengerEnteringVehicleEvent(now, mode, request.getId(), request.getPassengerId())); + } @Override public void afterSim() { - // reset leg attributes for next iteration - cleanupFinished = true; - - for (Leg leg : prebookedLegs) { - leg.getAttributes().removeAttribute(requestAttribute); - } } @Override diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingModeModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingModeModule.java index 76f2110b73f..6fcdc161876 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingModeModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingModeModule.java @@ -46,7 +46,7 @@ public void install() { })); // install QSim bindings / overrides - installOverridingQSimModule(new PrebookingModeQSimModule(getMode(), isElectric)); + installOverridingQSimModule(new PrebookingModeQSimModule(getMode(), drtConfig, isElectric)); // analysis install(new PrebookingModeAnalysisModule(getMode())); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingModeQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingModeQSimModule.java index c4a34d49050..9bfe632359e 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingModeQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingModeQSimModule.java @@ -3,27 +3,34 @@ import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.extension.edrt.EDrtActionCreator; import org.matsim.contrib.drt.extension.prebooking.electric.ElectricPrebookingActionCreator; +import org.matsim.contrib.drt.passenger.DrtRequest; +import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; import org.matsim.contrib.drt.vrpagent.DrtActionCreator; import org.matsim.contrib.dvrp.optimizer.VrpOptimizer; +import org.matsim.contrib.dvrp.passenger.DefaultRequestQueue; import org.matsim.contrib.dvrp.passenger.PassengerEngine; import org.matsim.contrib.dvrp.passenger.PassengerHandler; import org.matsim.contrib.dvrp.passenger.PassengerRequestCreator; import org.matsim.contrib.dvrp.passenger.PassengerRequestValidator; +import org.matsim.contrib.dvrp.passenger.RequestQueue; import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; import org.matsim.contrib.dvrp.vrpagent.VrpAgentLogic; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.mobsim.framework.MobsimTimer; import com.google.inject.Singleton; +import com.google.inject.TypeLiteral; class PrebookingModeQSimModule extends AbstractDvrpModeQSimModule { private final boolean isElectric; + private final DrtConfigGroup drtConfig; - PrebookingModeQSimModule(String mode, boolean isElectric) { + PrebookingModeQSimModule(String mode, DrtConfigGroup drtConfig, boolean isElectric) { super(mode); this.isElectric = isElectric; + this.drtConfig = drtConfig; } @Override @@ -36,9 +43,9 @@ protected void configureQSim() { DrtActionCreator delegate = getter.getModal(DrtActionCreator.class); PassengerStopDurationProvider stopDurationProvider = getter .getModal(PassengerStopDurationProvider.class); - EnteringHandler enteringHandler = getter.getModal(EnteringHandler.class); + PrebookingManager prebookingManager = getter.getModal(PrebookingManager.class); - return new PrebookingActionCreator(passengerEngine, delegate, stopDurationProvider, enteringHandler); + return new PrebookingActionCreator(passengerEngine, delegate, stopDurationProvider, prebookingManager); })).in(Singleton.class); bindModal(VrpAgentLogic.DynActionCreator.class).to(modalKey(PrebookingActionCreator.class)); } else { @@ -51,19 +58,14 @@ protected void configureQSim() { PassengerStopDurationProvider stopDurationProvider = getter .getModal(PassengerStopDurationProvider.class); MobsimTimer timer = getter.get(MobsimTimer.class); - EnteringHandler enteringHandler = getter.getModal(EnteringHandler.class); + PrebookingManager prebookingManager = getter.getModal(PrebookingManager.class); return new ElectricPrebookingActionCreator(passengerEngine, delegate, stopDurationProvider, timer, - enteringHandler); + prebookingManager); })).in(Singleton.class); bindModal(VrpAgentLogic.DynActionCreator.class).to(modalKey(ElectricPrebookingActionCreator.class)); } - bindModal(EnteringHandler.class).toProvider(modalProvider(getter -> { - EventsManager eventsManager = getter.get(EventsManager.class); - return new EnteringHandler(eventsManager, getMode()); - })).in(Singleton.class); - // override the PassengerEngine bindModal(PrebookingPassengerEngine.class).toProvider(modalProvider(getter -> { EventsManager eventsManager = getter.get(EventsManager.class); @@ -92,5 +94,15 @@ protected void configureQSim() { eventsManager); })).in(Singleton.class); addModalQSimComponentBinding().to(modalKey(PrebookingManager.class)); + + bindModal(new TypeLiteral>() { + }).toProvider(modalProvider(getter -> { + PrebookingManager prebookingManager = getter.getModal(PrebookingManager.class); + RequestQueue delegate = DefaultRequestQueue + .withLimitedAdvanceRequestPlanningHorizon(drtConfig.advanceRequestPlanningHorizon); + + return new PrebookingRequestQueue<>(prebookingManager, delegate); + })).in(Singleton.class); + } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingRequestQueue.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingRequestQueue.java index 12d9e398c2e..d1af9223859 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingRequestQueue.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingRequestQueue.java @@ -15,7 +15,7 @@ public final class PrebookingRequestQueue implements private final PrebookingManager prebookingManager; private final RequestQueue delegate; - private final List queue = new LinkedList<>(); + private final List schedulableRequests = new LinkedList<>(); public PrebookingRequestQueue(PrebookingManager prebookingManager, RequestQueue delegate) { this.prebookingManager = prebookingManager; @@ -31,7 +31,7 @@ public void updateQueuesOnNextTimeSteps(double currentTime) { public void addRequest(R request) { if (prebookingManager.isPrebookedRequest(request.getId())) { // add to queue in the order of submission - queue.add(request); + schedulableRequests.add(request); } else { delegate.addRequest(request); } @@ -39,13 +39,8 @@ public void addRequest(R request) { @Override public Collection getSchedulableRequests() { - // prebooked requests, they are treated when and in the order they are submitted - List requests = new LinkedList<>(queue); - queue.clear(); - - // other requests treated according to sorting default logic - requests.addAll(delegate.getSchedulableRequests()); - - return requests; + schedulableRequests.addAll(delegate.getSchedulableRequests()); + delegate.getSchedulableRequests().clear(); + return schedulableRequests; } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingStopActivity.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingStopActivity.java index 31dee7fce0d..fcd4b0eac68 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingStopActivity.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/dvrp/PrebookingStopActivity.java @@ -36,16 +36,15 @@ public class PrebookingStopActivity extends FirstLastSimStepDynActivity implemen private final IdMap leaveTimes = new IdMap<>(Request.class); private final Set> enteredRequests = new HashSet<>(); + private final PrebookingManager prebookingManager; private final PrebookingPassengerEngine passengerEngine; private final PassengerStopDurationProvider stopDurationProvider; - private final EnteringHandler enteringHandler; - public PrebookingStopActivity(PrebookingPassengerEngine passengerEngine, DynAgent driver, StayTask task, Map, ? extends AcceptedDrtRequest> dropoffRequests, Map, ? extends AcceptedDrtRequest> pickupRequests, String activityType, PassengerStopDurationProvider stopDurationProvider, DvrpVehicle vehicle, - EnteringHandler enteringHandler) { + PrebookingManager prebookingManager) { super(activityType); this.passengerEngine = passengerEngine; this.driver = driver; @@ -53,7 +52,7 @@ public PrebookingStopActivity(PrebookingPassengerEngine passengerEngine, DynAgen this.pickupRequests = pickupRequests; this.stopDurationProvider = stopDurationProvider; this.vehicle = vehicle; - this.enteringHandler = enteringHandler; + this.prebookingManager = prebookingManager; } @Override @@ -119,7 +118,7 @@ private boolean updatePickupRequests(double now) { } private void queuePickup(AcceptedDrtRequest request, double now) { - enteringHandler.sendEnteringEvent(now, request); + prebookingManager.notifyEntering(now, request); double enterTime = now + stopDurationProvider.calcPickupDuration(vehicle, request.getRequest()); enterTimes.put(request.getId(), enterTime); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/electric/ElectricPrebookingActionCreator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/electric/ElectricPrebookingActionCreator.java index b9a85dabd8d..ab7d089c458 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/electric/ElectricPrebookingActionCreator.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/electric/ElectricPrebookingActionCreator.java @@ -1,6 +1,6 @@ package org.matsim.contrib.drt.extension.prebooking.electric; -import org.matsim.contrib.drt.extension.prebooking.dvrp.EnteringHandler; +import org.matsim.contrib.drt.extension.prebooking.dvrp.PrebookingManager; import org.matsim.contrib.drt.extension.prebooking.dvrp.PrebookingPassengerEngine; import org.matsim.contrib.drt.extension.prebooking.dvrp.PrebookingStopActivity; import org.matsim.contrib.drt.schedule.DrtStopTask; @@ -27,16 +27,16 @@ public class ElectricPrebookingActionCreator implements VrpAgentLogic.DynActionC private final PrebookingPassengerEngine passengerEngine; private final PassengerStopDurationProvider stopDurationProvider; private final MobsimTimer timer; - private final EnteringHandler enteringHandler; + private final PrebookingManager prebookingManager; public ElectricPrebookingActionCreator(PrebookingPassengerEngine passengerEngine, VrpAgentLogic.DynActionCreator delegate, PassengerStopDurationProvider stopDurationProvider, - MobsimTimer timer, EnteringHandler enteringHandler) { + MobsimTimer timer, PrebookingManager prebookingManager) { this.delegate = delegate; this.passengerEngine = passengerEngine; this.stopDurationProvider = stopDurationProvider; this.timer = timer; - this.enteringHandler = enteringHandler; + this.prebookingManager = prebookingManager; } @Override @@ -51,7 +51,7 @@ public DynAction createAction(DynAgent dynAgent, DvrpVehicle vehicle, double now return new PrebookingStopActivity(passengerEngine, dynAgent, stopTask, stopTask.getDropoffRequests(), stopTask.getPickupRequests(), DrtActionCreator.DRT_STOP_NAME, stopDurationProvider, vehicle, - enteringHandler); + prebookingManager); } return delegate.createAction(dynAgent, vehicle, now); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/AttributePrebookingLogic.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/AttributePrebookingLogic.java index 1bbf69cf3bb..e7b85ac0720 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/AttributePrebookingLogic.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/AttributePrebookingLogic.java @@ -2,13 +2,12 @@ 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.PlanElement; import org.matsim.api.core.v01.population.Population; import org.matsim.contrib.drt.extension.prebooking.dvrp.PrebookingManager; import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; import org.matsim.core.controler.Controler; +import org.matsim.core.mobsim.qsim.QSim; import org.matsim.core.router.TripStructureUtils; import org.matsim.core.utils.timing.TimeInterpretation; import org.matsim.core.utils.timing.TimeTracker; @@ -43,20 +42,24 @@ public class AttributePrebookingLogic extends TimedPrebookingLogic { private final Population population; private final TimeInterpretation timeInterpretation; + private final QSim qsim; public AttributePrebookingLogic(String mode, PrebookingManager prebookingManager, Population population, - TimeInterpretation timeInterpretation) { + TimeInterpretation timeInterpretation, QSim qsim) { super(prebookingManager); this.mode = mode; this.population = population; this.timeInterpretation = timeInterpretation; + this.qsim = qsim; } @Override protected void scheduleRequests() { - for (Person person : population.getPersons().values()) { - Plan plan = person.getSelectedPlan(); + PopulationIterator iterator = PopulationIterator.create(population, qsim); + + while (iterator.hasNext()) { + var item = iterator.next(); TimeTracker timeTracker = new TimeTracker(timeInterpretation); @@ -64,11 +67,12 @@ protected void scheduleRequests() { Double plannedDepartureTime = null; boolean foundLeg = false; - for (PlanElement element : plan.getPlanElements()) { + for (PlanElement element : item.plan().getPlanElements()) { if (element instanceof Activity) { Activity activity = (Activity) element; if (!TripStructureUtils.isStageActivityType(activity.getType())) { + foundLeg = false; submissionTime = (Double) activity.getAttributes().getAttribute(SUBMISSION_TIME_ATTRIBUTE); plannedDepartureTime = (Double) activity.getAttributes() .getAttribute(PLANNED_DEPARTURE_ATTRIBUTE); @@ -79,8 +83,8 @@ protected void scheduleRequests() { Leg leg = (Leg) element; if (leg.getMode().equals(mode)) { - Verify.verify(!foundLeg, "Person " + person.getId().toString() - + " has at least two drt legs. Please make use of a different PrebookingLogic."); + Verify.verify(!foundLeg, "Person " + item.person().getId().toString() + + " has at least two drt legs in one trip."); foundLeg = true; if (plannedDepartureTime == null) { @@ -88,7 +92,7 @@ protected void scheduleRequests() { } if (submissionTime != null) { - queue.schedule(submissionTime, person, leg, plannedDepartureTime); + queue.schedule(submissionTime, item.person(), leg, plannedDepartureTime); } } } @@ -106,8 +110,9 @@ protected void configureQSim() { PrebookingManager prebookingManager = getter.getModal(PrebookingManager.class); Population population = getter.get(Population.class); TimeInterpretation timeInterpretation = TimeInterpretation.create(getConfig()); + QSim qsim = getter.get(QSim.class); - return new AttributePrebookingLogic(mode, prebookingManager, population, timeInterpretation); + return new AttributePrebookingLogic(mode, prebookingManager, population, timeInterpretation, qsim); })); } }); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/FixedSharePrebookingLogic.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/FixedSharePrebookingLogic.java index 031ae30094f..02bb26cd16a 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/FixedSharePrebookingLogic.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/FixedSharePrebookingLogic.java @@ -3,18 +3,15 @@ import java.util.Random; 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.PlanElement; import org.matsim.api.core.v01.population.Population; import org.matsim.contrib.drt.extension.prebooking.dvrp.PrebookingManager; import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; import org.matsim.core.controler.Controler; +import org.matsim.core.mobsim.qsim.QSim; import org.matsim.core.utils.timing.TimeInterpretation; import org.matsim.core.utils.timing.TimeTracker; -import com.google.common.base.Verify; - /** * This class represents a prebooking logic that searches for DRT legs in the * population and decides based on a predefiend probability if each trip is @@ -31,49 +28,51 @@ public class FixedSharePrebookingLogic extends TimedPrebookingLogic { private final String mode; - private final Population population; + private final QSim qsim; private final TimeInterpretation timeInterpretation; + private final Population population; - private final double prbookingProbability; + private final double prebookingProbability; private final double submissionSlack; private final long randomSeed; - public FixedSharePrebookingLogic(String mode, double prbookingProbability, double submissionSlack, + public FixedSharePrebookingLogic(String mode, double prebookingProbability, double submissionSlack, PrebookingManager prebookingManager, Population population, TimeInterpretation timeInterpretation, - long randomSeed) { + long randomSeed, QSim qsim) { super(prebookingManager); this.mode = mode; - this.prbookingProbability = prbookingProbability; + this.prebookingProbability = prebookingProbability; this.submissionSlack = submissionSlack; - this.population = population; this.timeInterpretation = timeInterpretation; this.randomSeed = randomSeed; + this.qsim = qsim; + this.population = population; + } @Override protected void scheduleRequests() { Random random = new Random(randomSeed); - for (Person person : population.getPersons().values()) { - Plan plan = person.getSelectedPlan(); + PopulationIterator iterator = PopulationIterator.create(population, qsim); + + while (iterator.hasNext()) { + var item = iterator.next(); TimeTracker timeTracker = new TimeTracker(timeInterpretation); - boolean foundLeg = false; - for (PlanElement element : plan.getPlanElements()) { + for (PlanElement element : item.plan().getPlanElements()) { if (element instanceof Leg) { Leg leg = (Leg) element; - if (leg.getMode().equals(mode) && random.nextDouble() < prbookingProbability) { - Verify.verify(!foundLeg, "Person " + person.getId().toString() - + " has at least two drt legs. Please make use of a different PrebookingLogic."); - foundLeg = true; - + if (leg.getMode().equals(mode) && random.nextDouble() < prebookingProbability) { double earliestDepartureTime = leg.getDepartureTime().seconds(); - double submissionTime = leg.getDepartureTime().seconds() - submissionSlack; - queue.schedule(submissionTime, person, leg, earliestDepartureTime); + double submissionTime = Double.isFinite(submissionSlack) + ? leg.getDepartureTime().seconds() - submissionSlack + : timeInterpretation.getSimulationStartTime(); + queue.schedule(submissionTime, item.person(), leg, earliestDepartureTime); } } @@ -91,9 +90,11 @@ protected void configureQSim() { PrebookingManager prebookingManager = getter.getModal(PrebookingManager.class); Population population = getter.get(Population.class); TimeInterpretation timeInterpretation = TimeInterpretation.create(getConfig()); + QSim qsim = getter.get(QSim.class); return new FixedSharePrebookingLogic(mode, prebookingProbability, submissionSlack, - prebookingManager, population, timeInterpretation, getConfig().global().getRandomSeed()); + prebookingManager, population, timeInterpretation, getConfig().global().getRandomSeed(), + qsim); })); } }); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/PopulationIterator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/PopulationIterator.java new file mode 100644 index 00000000000..8735934790e --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/PopulationIterator.java @@ -0,0 +1,47 @@ +package org.matsim.contrib.drt.extension.prebooking.logic; + +import java.util.Iterator; + +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.contrib.drt.extension.prebooking.logic.PopulationIterator.PersonItem; +import org.matsim.core.mobsim.framework.MobsimAgent; +import org.matsim.core.mobsim.qsim.QSim; +import org.matsim.core.mobsim.qsim.agents.HasModifiablePlan; + +/** + * This is a helper class that allows to loop through all persons that are + * active in a QSim. It is used to prebook drt legs for specific legs. + * + * @author Sebastian Hörl (sebhoerl), IRT SystemX + */ +public class PopulationIterator implements Iterator { + private final QSim qsim; + private final Iterator internalIterator; + + private PopulationIterator(Population population, QSim qsim) { + this.qsim = qsim; + this.internalIterator = population.getPersons().values().iterator(); + } + + @Override + public boolean hasNext() { + return internalIterator.hasNext(); + } + + @Override + public PersonItem next() { + Person person = internalIterator.next(); + MobsimAgent agent = qsim.getAgents().get(person.getId()); + Plan plan = ((HasModifiablePlan) agent).getModifiablePlan(); + return new PersonItem(person, plan); + } + + public record PersonItem(Person person, Plan plan) { + } + + static public PopulationIterator create(Population population, QSim qsim) { + return new PopulationIterator(population, qsim); + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/TimedPrebookingLogic.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/TimedPrebookingLogic.java index 3ee629f86d4..30da7592701 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/TimedPrebookingLogic.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/prebooking/logic/TimedPrebookingLogic.java @@ -47,9 +47,10 @@ public void notifyMobsimBeforeSimStep(@SuppressWarnings("rawtypes") MobsimBefore protected class PrebookingQueue { private PriorityQueue queue = new PriorityQueue<>(); + private int sequence = 0; public void schedule(double submissionTime, Person person, Leg leg, double departureTime) { - queue.add(new ScheduledItem(submissionTime, person, leg, departureTime)); + queue.add(new ScheduledItem(submissionTime, person, leg, departureTime, sequence++)); } public Collection getScheduledItems(double time) { @@ -64,16 +65,23 @@ public Collection getScheduledItems(double time) { public void clear() { queue.clear(); + sequence = 0; } } - private record ScheduledItem(double submissionTime, Person person, Leg leg, double departuretime) + private record ScheduledItem(double submissionTime, Person person, Leg leg, double departuretime, int sequence) implements Comparable { @Override public int compareTo(ScheduledItem o) { // sort by submissionTime, but otherwise keep the order of submission - return Double.compare(submissionTime, o.submissionTime); + int comparison = Double.compare(submissionTime, o.submissionTime); + + if (comparison != 0) { + return comparison; + } + + return Integer.compare(sequence, o.sequence); } } }