Skip to content

Commit

Permalink
Merge branch 'master' into disallowed-next-links
Browse files Browse the repository at this point in the history
  • Loading branch information
marecabo authored Nov 22, 2023
2 parents de1b094 + 9a83107 commit 9a8c81e
Show file tree
Hide file tree
Showing 104 changed files with 4,185 additions and 691 deletions.
5 changes: 5 additions & 0 deletions contribs/drt-extensions/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@
<version>16.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>

</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import org.apache.commons.math3.stat.regression.SimpleRegression;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.PersonMoneyEvent;
import org.matsim.api.core.v01.population.Person;
import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector;
import org.matsim.contrib.drt.extension.estimator.run.DrtEstimatorConfigGroup;
import org.matsim.contrib.drt.fare.DrtFareParams;
Expand All @@ -16,6 +18,7 @@
import org.matsim.core.controler.listener.IterationEndsListener;
import org.matsim.core.utils.misc.OptionalTime;

import java.util.Map;
import java.util.SplittableRandom;

/**
Expand Down Expand Up @@ -64,19 +67,21 @@ public void notifyIterationEnds(IterationEndsEvent event) {

for (DrtEventSequenceCollector.EventSequence seq : collector.getPerformedRequestSequences().values()) {

if (seq.getPickedUp().isPresent() && seq.getDroppedOff().isPresent()) {
Map<Id<Person>, DrtEventSequenceCollector.EventSequence.PersonEvents> personEvents = seq.getPersonEvents();
for (Map.Entry<Id<Person>, DrtEventSequenceCollector.EventSequence.PersonEvents> entry : personEvents.entrySet()) {
if (entry.getValue().getPickedUp().isPresent() && entry.getValue().getDroppedOff().isPresent()) {
double waitTime = entry.getValue().getPickedUp().get().getTime() - seq.getSubmitted().getTime();
est.waitTime.addValue(waitTime);

double waitTime = seq.getPickedUp().get().getTime() - seq.getSubmitted().getTime();
est.waitTime.addValue(waitTime);
double unsharedTime = seq.getSubmitted().getUnsharedRideTime();
double travelTime = entry.getValue().getDroppedOff().get().getTime() - entry.getValue().getPickedUp().get().getTime();

double unsharedTime = seq.getSubmitted().getUnsharedRideTime();
double travelTime = seq.getDroppedOff().get().getTime() - seq.getPickedUp().get().getTime();
est.detour.addValue(travelTime / unsharedTime);

est.detour.addValue(travelTime / unsharedTime);

double fare = seq.getDrtFares().stream().mapToDouble(PersonMoneyEvent::getAmount).sum();
est.fare.addData(seq.getSubmitted().getUnsharedRideDistance(), fare);
n++;
double fare = seq.getDrtFares().stream().mapToDouble(PersonMoneyEvent::getAmount).sum();
est.fare.addData(seq.getSubmitted().getUnsharedRideDistance(), fare);
n++;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.PersonMoneyEvent;
import org.matsim.api.core.v01.population.Person;
import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector;
import org.matsim.contrib.drt.extension.estimator.run.DrtEstimatorConfigGroup;
import org.matsim.contrib.drt.routing.DrtRoute;
Expand All @@ -23,6 +25,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;

/**
* Analyzes and outputs drt estimates errors metrics based on daily requests.
Expand Down Expand Up @@ -96,22 +99,25 @@ private Iterable<Number> calcMetrics(int iteration) {
DescriptiveStatistics fare = new DescriptiveStatistics();

for (DrtEventSequenceCollector.EventSequence seq : collector.getPerformedRequestSequences().values()) {
if (seq.getPickedUp().isPresent() && seq.getDroppedOff().isPresent()) {
Map<Id<Person>, DrtEventSequenceCollector.EventSequence.PersonEvents> personEvents = seq.getPersonEvents();
for (Map.Entry<Id<Person>, DrtEventSequenceCollector.EventSequence.PersonEvents> entry : personEvents.entrySet()) {
if (entry.getValue().getPickedUp().isPresent() && entry.getValue().getDroppedOff().isPresent()) {

// many attributes are not filled, when using the constructor
DrtRoute route = new DrtRoute(seq.getSubmitted().getFromLinkId(), seq.getSubmitted().getToLinkId());
route.setDirectRideTime(seq.getSubmitted().getUnsharedRideTime());
route.setDistance(seq.getSubmitted().getUnsharedRideDistance());
// many attributes are not filled, when using the constructor
DrtRoute route = new DrtRoute(seq.getSubmitted().getFromLinkId(), seq.getSubmitted().getToLinkId());
route.setDirectRideTime(seq.getSubmitted().getUnsharedRideTime());
route.setDistance(seq.getSubmitted().getUnsharedRideDistance());

double valWaitTime = seq.getPickedUp().get().getTime() - seq.getSubmitted().getTime();
double valTravelTime = seq.getDroppedOff().get().getTime() - seq.getPickedUp().get().getTime();
double valFare = seq.getDrtFares().stream().mapToDouble(PersonMoneyEvent::getAmount).sum();
double valWaitTime = entry.getValue().getPickedUp().get().getTime() - seq.getSubmitted().getTime();
double valTravelTime = entry.getValue().getDroppedOff().get().getTime() - entry.getValue().getPickedUp().get().getTime();
double valFare = seq.getDrtFares().stream().mapToDouble(PersonMoneyEvent::getAmount).sum();

DrtEstimator.Estimate estimate = estimator.estimate(route, OptionalTime.defined(seq.getSubmitted().getTime()));
DrtEstimator.Estimate estimate = estimator.estimate(route, OptionalTime.defined(seq.getSubmitted().getTime()));

waitTime.addValue(Math.abs(estimate.waitingTime() - valWaitTime));
travelTime.addValue(Math.abs(estimate.travelTime() - valTravelTime));
fare.addValue(Math.abs(estimate.fare() - valFare));
waitTime.addValue(Math.abs(estimate.waitingTime() - valWaitTime));
travelTime.addValue(Math.abs(estimate.travelTime() - valTravelTime));
fare.addValue(Math.abs(estimate.fare() - valFare));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.matsim.contrib.drt.extension.operations.eshifts.charging;

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Identifiable;
import org.matsim.api.core.v01.population.Person;
import org.matsim.contrib.drt.passenger.AcceptedDrtRequest;
import org.matsim.contrib.dvrp.optimizer.Request;
Expand All @@ -15,7 +16,10 @@
import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftBreakTask;
import org.matsim.core.mobsim.framework.MobsimPassengerAgent;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
* based on {@link DrtStopActivity} and {@link ChargingActivity}
Expand Down Expand Up @@ -50,7 +54,7 @@ public ChargingBreakActivity(ChargingTask chargingTask, PassengerHandler passeng
protected boolean isLastStep(double now) {
if(chargingDelegate.getEndTime() < now && now >= endTime) {
for (var request : pickupRequests.values()) {
if (passengerHandler.tryPickUpPassenger(this, driver, request.getId(), now)) {
if (passengerHandler.tryPickUpPassengers(this, driver, request.getId(), now)) {
passengersPickedUp++;
}
}
Expand All @@ -64,13 +68,13 @@ public void finalizeAction(double now) {
}

@Override
public void notifyPassengerIsReadyForDeparture(MobsimPassengerAgent passenger, double now) {
public void notifyPassengersAreReadyForDeparture(List<MobsimPassengerAgent> passengers, double now) {
if (!isLastStep(now)) {
return;// pick up only at the end of stop activity
}

var request = getRequestForPassenger(passenger.getId());
if (passengerHandler.tryPickUpPassenger(this, driver, request.getId(), now)) {
var request = getRequestForPassengers(passengers.stream().map(Identifiable::getId).toList());
if (passengerHandler.tryPickUpPassengers(this, driver, request.getId(), now)) {
passengersPickedUp++;
} else {
throw new IllegalStateException("The passenger is not on the link or not available for departure!");
Expand All @@ -81,7 +85,7 @@ public void notifyPassengerIsReadyForDeparture(MobsimPassengerAgent passenger, d
protected void beforeFirstStep(double now) {
// TODO probably we should simulate it more accurately (passenger by passenger, not all at once...)
for (var request : dropoffRequests.values()) {
passengerHandler.dropOffPassenger(driver, request.getId(), now);
passengerHandler.dropOffPassengers(driver, request.getId(), now);
}
}

Expand All @@ -95,9 +99,9 @@ protected void simStep(double now) {
chargingDelegate.doSimStep(now);
}

private AcceptedDrtRequest getRequestForPassenger(Id<Person> passengerId) {
private AcceptedDrtRequest getRequestForPassengers(List<Id<Person>> passengerIds) {
return pickupRequests.values().stream()
.filter(r -> passengerId.equals(r.getPassengerId()))
.filter(r -> r.getPassengerIds().size() == passengerIds.size() && r.getPassengerIds().containsAll(passengerIds))
.findAny()
.orElseThrow(() -> new IllegalArgumentException("I am waiting for different passengers!"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,14 @@ public void addDropoffRequest(AcceptedDrtRequest request) {
public void addPickupRequest(AcceptedDrtRequest request) {
delegate.addPickupRequest(request);
}

@Override
public void removePickupRequest(Id<Request> requestId) {
delegate.removePickupRequest(requestId);
}

@Override
public void removeDropoffRequest(Id<Request> requestId) {
delegate.removeDropoffRequest(requestId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,14 @@ public void addDropoffRequest(AcceptedDrtRequest request) {
public void addPickupRequest(AcceptedDrtRequest request) {
delegate.addPickupRequest(request);
}

@Override
public void removePickupRequest(Id<Request> requestId) {
delegate.removePickupRequest(requestId);
}

@Override
public void removeDropoffRequest(Id<Request> requestId) {
delegate.removeDropoffRequest(requestId);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package org.matsim.contrib.drt.extension.operations.shifts.schedule;

import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.STOP;

import java.util.Map;

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility;
Expand All @@ -11,10 +15,6 @@
import org.matsim.contrib.dvrp.optimizer.Request;
import org.matsim.contrib.dvrp.schedule.DefaultStayTask;

import java.util.Map;

import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.STOP;

/**
* A task representing stopping and waiting for a new shift.
* @author nkuehnel / MOIA
Expand Down Expand Up @@ -64,5 +64,15 @@ public void addDropoffRequest(AcceptedDrtRequest request) {
public void addPickupRequest(AcceptedDrtRequest request) {
delegate.addPickupRequest(request);
}

@Override
public void removePickupRequest(Id<Request> requestId) {
delegate.removePickupRequest(requestId);
}

@Override
public void removeDropoffRequest(Id<Request> requestId) {
delegate.removeDropoffRequest(requestId);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@

import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.STAY;

import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.*;

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
Expand Down Expand Up @@ -118,7 +116,7 @@ public void requestSubmitted(Request request) {
"Pre-planned request (%s) not assigned to any vehicle and not marked as unassigned.",
preplannedRequest);
eventsManager.processEvent(new PassengerRequestRejectedEvent(timer.getTimeOfDay(), mode, request.getId(),
drtRequest.getPassengerId(), "Marked as unassigned"));
drtRequest.getPassengerIds(), "Marked as unassigned"));
return;
}

Expand All @@ -130,7 +128,7 @@ public void requestSubmitted(Request request) {
//TODO in the current implementation we do not know the scheduled pickup and dropoff times
eventsManager.processEvent(
new PassengerRequestScheduledEvent(timer.getTimeOfDay(), drtRequest.getMode(), drtRequest.getId(),
drtRequest.getPassengerId(), vehicleId, Double.NaN, Double.NaN));
drtRequest.getPassengerIds(), vehicleId, Double.NaN, Double.NaN));
}

@Override
Expand Down Expand Up @@ -203,7 +201,7 @@ public record PreplannedSchedules(Map<PreplannedRequestKey, Id<DvrpVehicle>> pre
Map<PreplannedRequestKey, PreplannedRequest> unassignedRequests) {
}

public record PreplannedRequestKey(Id<Person> passengerId, Id<Link> fromLinkId, Id<Link> toLinkId) {
public record PreplannedRequestKey(Set<Id<Person>> passengerIds, Id<Link> fromLinkId, Id<Link> toLinkId) {
}

// also input to the external optimiser
Expand All @@ -212,7 +210,7 @@ public record PreplannedRequest(PreplannedRequestKey key, double earliestStartTi
}

static PreplannedRequest createFromRequest(DrtRequest request) {
return new PreplannedRequest(new PreplannedRequestKey(request.getPassengerId(), request.getFromLink().getId(),
return new PreplannedRequest(new PreplannedRequestKey(Set.copyOf(request.getPassengerIds()), request.getFromLink().getId(),
request.getToLink().getId()), request.getEarliestStartTime(), request.getLatestStartTime(),
request.getLatestArrivalTime());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,24 @@

package org.matsim.contrib.drt.extension.edrt.run;

import static org.junit.Assert.assertEquals;

import java.net.URL;

import org.junit.Test;
import org.matsim.contrib.drt.prebooking.PrebookingParams;
import org.matsim.contrib.drt.prebooking.logic.ProbabilityBasedPrebookingLogic;
import org.matsim.contrib.drt.run.DrtConfigGroup;
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEvent;
import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEventHandler;
import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEvent;
import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEventHandler;
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
import org.matsim.contrib.ev.EvConfigGroup;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.controler.AbstractModule;
import org.matsim.core.controler.Controler;
import org.matsim.core.utils.io.IOUtils;
import org.matsim.examples.ExamplesUtils;
Expand Down Expand Up @@ -57,6 +64,50 @@ public void testWithPrebooking() {
Controler controller = RunEDrtScenario.createControler(config, false);
ProbabilityBasedPrebookingLogic.install(controller, drtConfig, 0.5, 4.0 * 3600.0);

PrebookingTracker tracker = new PrebookingTracker();
tracker.install(controller);

controller.run();

assertEquals(74, tracker.immediateScheduled);
assertEquals(198, tracker.prebookedScheduled);
assertEquals(116, tracker.immediateRejected);
assertEquals(7, tracker.prebookedRejected);
}

static private class PrebookingTracker implements PassengerRequestRejectedEventHandler, PassengerRequestScheduledEventHandler {
int immediateScheduled = 0;
int prebookedScheduled = 0;
int immediateRejected = 0;
int prebookedRejected = 0;

@Override
public void handleEvent(PassengerRequestScheduledEvent event) {
if (event.getRequestId().toString().contains("prebooked")) {
prebookedScheduled++;
} else {
immediateScheduled++;
}
}

@Override
public void handleEvent(PassengerRequestRejectedEvent event) {
if (event.getRequestId().toString().contains("prebooked")) {
prebookedRejected++;
} else {
immediateRejected++;
}
}

void install(Controler controller) {
PrebookingTracker thisTracker = this;

controller.addOverridingModule(new AbstractModule() {
@Override
public void install() {
addEventHandlerBinding().toInstance(thisTracker);
}
});
}
}
}
Loading

0 comments on commit 9a8c81e

Please sign in to comment.