Skip to content

Commit

Permalink
backport & simplifications
Browse files Browse the repository at this point in the history
  • Loading branch information
sebhoerl committed Nov 10, 2023
1 parent 05ff372 commit 3155f24
Show file tree
Hide file tree
Showing 25 changed files with 273 additions and 212 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.matsim.contrib.drt.scheduler.DrtScheduleInquiry;
import org.matsim.contrib.drt.scheduler.EmptyVehicleRelocator;
import org.matsim.contrib.drt.scheduler.RequestInsertionScheduler;
import org.matsim.contrib.drt.stops.PassengerStopDurationProvider;
import org.matsim.contrib.drt.stops.StopTimeCalculator;
import org.matsim.contrib.dvrp.fleet.Fleet;
import org.matsim.contrib.dvrp.optimizer.VrpOptimizer;
Expand Down Expand Up @@ -136,7 +137,8 @@ public EmptyVehicleChargingScheduler get() {
getter.getModal(RequestInsertionScheduler.class),
getter.getModal(VehicleEntry.EntryFactory.class), getter.getModal(DrtInsertionSearch.class),
getter.getModal(DrtRequestInsertionRetryQueue.class), getter.getModal(DrtOfferAcceptor.class),
getter.getModal(QSimScopeForkJoinPoolHolder.class).getPool()))).asEagerSingleton();
getter.getModal(QSimScopeForkJoinPoolHolder.class).getPool(),
getter.getModal(PassengerStopDurationProvider.class)))).asEagerSingleton();

bindModal(InsertionCostCalculator.class).toProvider(modalProvider(
getter -> new DefaultInsertionCostCalculator(getter.getModal(CostCalculationStrategy.class))));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.IdMap;
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.PassengerEnteringVehicleEventHandler;
import org.matsim.contrib.drt.extension.prebooking.events.PassengerRequestBookedEvent;
import org.matsim.contrib.drt.extension.prebooking.events.PassengerRequestBookedEventHandler;
import org.matsim.contrib.dvrp.optimizer.Request;
Expand All @@ -17,10 +15,12 @@
import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEventHandler;
import org.matsim.contrib.dvrp.passenger.PassengerRequestSubmittedEvent;
import org.matsim.contrib.dvrp.passenger.PassengerRequestSubmittedEventHandler;
import org.matsim.contrib.dvrp.passenger.PassengerWaitingEvent;
import org.matsim.contrib.dvrp.passenger.PassengerWaitingEventHandler;

public class PrebookingAnalysisHandler implements PassengerRequestBookedEventHandler,
PassengerRequestSubmittedEventHandler, PassengerRequestScheduledEventHandler,
PassengerRequestRejectedEventHandler, PassengerEnteringVehicleEventHandler {
PassengerRequestRejectedEventHandler, PassengerWaitingEventHandler {
private final String mode;
private final IdMap<Request, Sequence> sequences = new IdMap<>(Request.class);

Expand Down Expand Up @@ -73,15 +73,15 @@ public void handleEvent(PassengerRequestScheduledEvent event) {
}

@Override
public void handleEvent(PassengerEnteringVehicleEvent event) {
public void handleEvent(PassengerWaitingEvent event) {
if (!event.getMode().equals(mode)) {
return;
}

Sequence sequence = sequences.get(event.getRequestId());

if (sequence != null) {
sequence.entering = event;
sequence.waiting = event;
}
}

Expand All @@ -93,7 +93,7 @@ public List<RequestRecord> getRecords() {
sequence.submitted != null ? sequence.submitted.getTime() : null,
sequence.scheduled != null ? sequence.scheduled.getTime() : null,
sequence.rejected != null ? sequence.rejected.getTime() : null,
sequence.entering != null ? sequence.entering.getTime() : null));
sequence.waiting != null ? sequence.waiting.getTime() : null));
}

return records;
Expand All @@ -106,7 +106,7 @@ public record RequestRecord(Id<Request> requestId, Id<Person> personId, Double s
private class Sequence {
final PassengerRequestBookedEvent booked;
PassengerRequestSubmittedEvent submitted;
PassengerEnteringVehicleEvent entering;
PassengerWaitingEvent waiting;
PassengerRequestScheduledEvent scheduled;
PassengerRequestRejectedEvent rejected;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ public class PrebookingActionCreator implements VrpAgentLogic.DynActionCreator {
private final VrpAgentLogic.DynActionCreator delegate;
private final PrebookingPassengerEngine passengerEngine;
private final PassengerStopDurationProvider stopDurationProvider;
private final PrebookingManager prebookingManager;

public PrebookingActionCreator(PrebookingPassengerEngine passengerEngine, VrpAgentLogic.DynActionCreator delegate,
PassengerStopDurationProvider stopDurationProvider, PrebookingManager prebookingManager) {
PassengerStopDurationProvider stopDurationProvider) {
this.delegate = delegate;
this.passengerEngine = passengerEngine;
this.stopDurationProvider = stopDurationProvider;
this.prebookingManager = prebookingManager;
}

@Override
Expand All @@ -43,8 +41,7 @@ public DynAction createAction(DynAgent dynAgent, DvrpVehicle vehicle, double now
if (getBaseTypeOrElseThrow(task).equals(DrtTaskBaseType.STOP)) {
DrtStopTask stopTask = (DrtStopTask) task;
return new PrebookingStopActivity(passengerEngine, dynAgent, stopTask, stopTask.getDropoffRequests(),
stopTask.getPickupRequests(), DrtActionCreator.DRT_STOP_NAME, stopDurationProvider, vehicle,
prebookingManager);
stopTask.getPickupRequests(), DrtActionCreator.DRT_STOP_NAME, () -> stopTask.getEndTime(), stopDurationProvider, vehicle);
}

return delegate.createAction(dynAgent, vehicle, now);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.matsim.contrib.drt.extension.prebooking.dvrp;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
Expand All @@ -10,10 +11,8 @@
import org.matsim.api.core.v01.network.Link;
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.api.core.v01.population.Plan;
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;
Expand All @@ -22,7 +21,9 @@
import org.matsim.contrib.dvrp.passenger.PassengerRequestValidator;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.mobsim.framework.MobsimAgent;
import org.matsim.core.mobsim.framework.MobsimAgent.State;
import org.matsim.core.mobsim.qsim.InternalInterface;
import org.matsim.core.mobsim.qsim.agents.WithinDayAgentUtils;
import org.matsim.core.mobsim.qsim.interfaces.MobsimEngine;

import com.google.common.base.Preconditions;
Expand All @@ -46,24 +47,13 @@
* @author Sebastian Hörl (sebhoerl), IRT SystemX
*/
public class PrebookingManager implements MobsimEngine {
private static final String PREBOOKED_REQUEST_PREFIX = "prebookedRequestId";

private final String mode;

private final Network network;
private final EventsManager eventsManager;

private final PassengerRequestCreator requestCreator;
private final PassengerRequestValidator requestValidator;
private final VrpOptimizer optimizer;

private final AtomicInteger currentRequestIndex = new AtomicInteger(-1);

private final String requestAttribute;

private final List<PrebookingQueueItem> prebookingQueue = new LinkedList<>();
private final IdMap<Request, PassengerRequest> prebookedRequests = new IdMap<>(Request.class);

public PrebookingManager(String mode, Network network, PassengerRequestCreator requestCreator,
VrpOptimizer optimizer, PassengerRequestValidator requestValidator, EventsManager eventsManager) {
this.network = network;
Expand All @@ -75,17 +65,11 @@ public PrebookingManager(String mode, Network network, PassengerRequestCreator r
this.eventsManager = eventsManager;
}

PassengerRequest consumePrebookedRequest(MobsimAgent agent, Leg leg) {
Verify.verify(leg.getMode().equals(mode), "Invalid mode for this prebooking manager");
// Functionality for ID management

String rawRequestId = (String) leg.getAttributes().getAttribute(requestAttribute);

if (rawRequestId == null) {
return null;
}

return prebookedRequests.remove(Id.create(rawRequestId, Request.class));
}
private static final String PREBOOKED_REQUEST_PREFIX = "prebookedRequestId";
private final AtomicInteger currentRequestIndex = new AtomicInteger(-1);
private final String requestAttribute;

private Id<Request> createRequestId() {
return Id.create(mode + "_prebooked_" + currentRequestIndex.incrementAndGet(), Request.class);
Expand All @@ -95,32 +79,34 @@ public boolean isPrebookedRequest(Id<Request> requestId) {
return requestId.toString().startsWith(mode + "_prebooked_");
}

public void prebook(Person person, Leg leg, double earliestDepartureTime) {
Verify.verify(leg.getMode().equals(mode), "Invalid mode for this prebooking manager");
public Id<Request> getRequestId(Leg leg) {
String rawRequestId = (String) leg.getAttributes().getAttribute(requestAttribute);

synchronized (prebookingQueue) {
this.prebookingQueue.add(new PrebookingQueueItem(person, leg, earliestDepartureTime));
if (rawRequestId == null) {
return null;
}
}

private Link getLink(Id<Link> linkId) {
return Preconditions.checkNotNull(network.getLinks().get(linkId),
"Link id=%s does not exist in network for mode %s. Agent departs from a link that does not belong to that network?",
linkId, mode);
return Id.create(rawRequestId, Request.class);
}

private record PrebookingQueueItem(Person person, Leg leg, double earliestDepartureTime) {
}
// Booking functionality

@Override
public void onPrepareSim() {
private final PassengerRequestCreator requestCreator;
private final PassengerRequestValidator requestValidator;
private final List<QueueItem> queue = new LinkedList<>();

public void prebook(MobsimAgent person, Leg leg, double earliestDepartureTime) {
Verify.verify(leg.getMode().equals(mode), "Invalid mode for this prebooking manager");

synchronized (queue) {
queue.add(new QueueItem(person, leg, earliestDepartureTime));
}
}

@Override
public void doSimStep(double now) {
synchronized (prebookingQueue) {
for (PrebookingQueueItem item : prebookingQueue) {
Verify.verify(item.leg.getMode().equals(mode), "Invalid mode for this prebooking manager");
private void processQueue(double now) {
synchronized (queue) {
for (QueueItem item : queue) {
Verify.verify(!item.person.getState().equals(State.ABORT), "Cannot prebook aborted agent");

Id<Request> requestId = createRequestId();

Expand All @@ -131,6 +117,16 @@ public void doSimStep(double now) {
getLink(item.leg.getRoute().getEndLinkId()), item.earliestDepartureTime, now);

Set<String> violations = requestValidator.validateRequest(request);

Plan plan = WithinDayAgentUtils.getModifiablePlan(item.person);
int currentLegIndex = WithinDayAgentUtils.getCurrentPlanElementIndex(item.person);
int prebookingLegIndex = plan.getPlanElements().indexOf(item.leg);

if (prebookingLegIndex <= currentLegIndex) {
violations = new HashSet<>(violations);
violations.add("past leg");
}

if (!violations.isEmpty()) {
String cause = String.join(", ", violations);
eventsManager.processEvent(new PassengerRequestRejectedEvent(now, mode, request.getId(),
Expand All @@ -141,17 +137,70 @@ public void doSimStep(double now) {
}

item.leg.getAttributes().putAttribute(requestAttribute, request.getId().toString());
prebookedRequests.put(request.getId(), request);
requests.put(requestId, new RequestItem(request));
}
}

prebookingQueue.clear();
queue.clear();
}
}

private Link getLink(Id<Link> linkId) {
return Preconditions.checkNotNull(network.getLinks().get(linkId),
"Link id=%s does not exist in network for mode %s. Agent departs from a link that does not belong to that network?",
linkId, mode);
}

private record QueueItem(MobsimAgent person, Leg leg, double earliestDepartureTime) {
}

// Interface with PassengerEngine

PassengerRequest consumePrebookedRequest(MobsimAgent agent, Leg leg) {
Verify.verify(leg.getMode().equals(mode), "Invalid mode for this prebooking manager");

Id<Request> requestId = getRequestId(leg);

if (requestId == null) {
return null;
}

RequestItem item = requests.get(requestId);

if (item == null) {
return null;
}

return item.request;
}

void notifyEntering(double now, AcceptedDrtRequest request) {
eventsManager
.processEvent(new PassengerEnteringVehicleEvent(now, mode, request.getId(), request.getPassengerId()));

// Housekeeping of requests

private IdMap<Request, RequestItem> requests = new IdMap<>(Request.class);

private class RequestItem {
// this class looks minimal for now, but will be extended with canceling
// functionality
final PassengerRequest request;

RequestItem(PassengerRequest request) {
this.request = request;
}
}

void notifyDropoff(Id<Request> requestId) {
requests.remove(requestId);
}

// Engine code

@Override
public void doSimStep(double now) {
processQueue(now);
}

@Override
public void onPrepareSim() {
}

@Override
Expand All @@ -160,5 +209,5 @@ public void afterSim() {

@Override
public void setInternalInterface(InternalInterface internalInterface) {
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ protected void configureQSim() {
DrtActionCreator delegate = getter.getModal(DrtActionCreator.class);
PassengerStopDurationProvider stopDurationProvider = getter
.getModal(PassengerStopDurationProvider.class);
PrebookingManager prebookingManager = getter.getModal(PrebookingManager.class);

return new PrebookingActionCreator(passengerEngine, delegate, stopDurationProvider, prebookingManager);
return new PrebookingActionCreator(passengerEngine, delegate, stopDurationProvider);
})).in(Singleton.class);
bindModal(VrpAgentLogic.DynActionCreator.class).to(modalKey(PrebookingActionCreator.class));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEvent;
import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEventHandler;
import org.matsim.contrib.dvrp.passenger.PassengerRequestValidator;
import org.matsim.contrib.dvrp.passenger.PassengerWaitingEvent;
import org.matsim.contrib.dvrp.run.DvrpModes;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.mobsim.framework.MobsimAgent;
Expand All @@ -46,6 +47,7 @@ public final class PrebookingPassengerEngine implements PassengerEngine, Passeng

private final String mode;
private final MobsimTimer mobsimTimer;
private final EventsManager eventsManager;

private final PassengerRequestCreator requestCreator;
private final VrpOptimizer optimizer;
Expand Down Expand Up @@ -77,6 +79,7 @@ public final class PrebookingPassengerEngine implements PassengerEngine, Passeng
this.optimizer = optimizer;
this.network = network;
this.requestValidator = requestValidator;
this.eventsManager = eventsManager;
this.prebookingManager = prebookingManager;

internalPassengerHandling = new InternalPassengerHandling(mode, eventsManager);
Expand Down Expand Up @@ -150,6 +153,8 @@ public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> fromLinkI
}
}

eventsManager.processEvent(new PassengerWaitingEvent(now, mode, request.getId(), request.getPassengerId()));

return true;
}

Expand Down
Loading

0 comments on commit 3155f24

Please sign in to comment.