Skip to content

Commit

Permalink
Merge pull request #2833 from moia-oss/drtGroupBookings
Browse files Browse the repository at this point in the history
Group Bookings DRT
  • Loading branch information
nkuehnel authored Nov 21, 2023
2 parents c6639f3 + db0cf2f commit 9a83107
Show file tree
Hide file tree
Showing 59 changed files with 1,029 additions and 421 deletions.
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 @@ -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 @@ -25,11 +25,7 @@
import static org.matsim.contrib.drt.extension.preplanned.optimizer.PreplannedDrtOptimizer.PreplannedStop;

import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand All @@ -53,34 +49,34 @@ public void testRun() {

// create preplanned requests (they will be mapped to drt requests created during simulation)
var preplannedRequest_0 = new PreplannedRequest(
new PreplannedRequestKey(Id.createPersonId("passenger_0"), Id.createLinkId("114"),
new PreplannedRequestKey(Set.of(Id.createPersonId("passenger_0")), Id.createLinkId("114"),
Id.createLinkId("349")), 0.0, 900.0, 844.4);
var preplannedRequest_1 = new PreplannedRequest(
new PreplannedRequestKey(Id.createPersonId("passenger_1"), Id.createLinkId("144"),
new PreplannedRequestKey(Set.of(Id.createPersonId("passenger_1")), Id.createLinkId("144"),
Id.createLinkId("437")), 300.0, 1200.0, 1011.8);
var preplannedRequest_2 = new PreplannedRequest(
new PreplannedRequestKey(Id.createPersonId("passenger_2"), Id.createLinkId("223"),
new PreplannedRequestKey(Set.of(Id.createPersonId("passenger_2")), Id.createLinkId("223"),
Id.createLinkId("347")), 600.0, 1500.0, 1393.7);
var preplannedRequest_3 = new PreplannedRequest(
new PreplannedRequestKey(Id.createPersonId("passenger_3"), Id.createLinkId("234"),
new PreplannedRequestKey(Set.of(Id.createPersonId("passenger_3")), Id.createLinkId("234"),
Id.createLinkId("119")), 900.0, 1800.0, 1825.0);
var preplannedRequest_4 = new PreplannedRequest(
new PreplannedRequestKey(Id.createPersonId("passenger_4"), Id.createLinkId("314"),
new PreplannedRequestKey(Set.of(Id.createPersonId("passenger_4")), Id.createLinkId("314"),
Id.createLinkId("260")), 1200.0, 2100.0, 1997.6);
var preplannedRequest_5 = new PreplannedRequest(
new PreplannedRequestKey(Id.createPersonId("passenger_5"), Id.createLinkId("333"),
new PreplannedRequestKey(Set.of(Id.createPersonId("passenger_5")), Id.createLinkId("333"),
Id.createLinkId("438")), 1500.0, 2400.0, 2349.6);
var preplannedRequest_6 = new PreplannedRequest(
new PreplannedRequestKey(Id.createPersonId("passenger_6"), Id.createLinkId("325"),
new PreplannedRequestKey(Set.of(Id.createPersonId("passenger_6")), Id.createLinkId("325"),
Id.createLinkId("111")), 1800.0, 2700.0, 2600.2);
var preplannedRequest_7 = new PreplannedRequest(
new PreplannedRequestKey(Id.createPersonId("passenger_7"), Id.createLinkId("412"),
new PreplannedRequestKey(Set.of(Id.createPersonId("passenger_7")), Id.createLinkId("412"),
Id.createLinkId("318")), 2100.0, 3000.0, 2989.9);
var preplannedRequest_8 = new PreplannedRequest(
new PreplannedRequestKey(Id.createPersonId("passenger_8"), Id.createLinkId("455"),
new PreplannedRequestKey(Set.of(Id.createPersonId("passenger_8")), Id.createLinkId("455"),
Id.createLinkId("236")), 2400.0, 3300.0, 3110.5);
var preplannedRequest_9 = new PreplannedRequest(
new PreplannedRequestKey(Id.createPersonId("passenger_9"), Id.createLinkId("139"),
new PreplannedRequestKey(Set.of(Id.createPersonId("passenger_9")), Id.createLinkId("139"),
Id.createLinkId("330")), 2700.0, 3600.0, 3410.5);
var preplannedRequests = List.of(preplannedRequest_0, preplannedRequest_1, preplannedRequest_2,
preplannedRequest_3, preplannedRequest_4, preplannedRequest_5, preplannedRequest_6);
Expand Down
Loading

0 comments on commit 9a83107

Please sign in to comment.