Skip to content

Commit 8400d12

Browse files
authored
fix(drt): Compute sharing metrics per DRT mode (#4844)
1 parent d7bd997 commit 8400d12

3 files changed

Lines changed: 82 additions & 5 deletions

File tree

contribs/drt/src/main/java/org/matsim/contrib/drt/sharingmetrics/SharingMetricsModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public SharingMetricsModule(DrtConfigGroup drtConfigGroup) {
1919
@Override
2020
public void install() {
2121
bindModal(SharingMetricsTracker.class).toProvider(modalProvider(getter ->
22-
new SharingMetricsTracker())).asEagerSingleton();
22+
new SharingMetricsTracker(getMode()))).asEagerSingleton();
2323
addEventHandlerBinding().to(modalKey(SharingMetricsTracker.class));
2424
bindModal(SharingMetricsControllerListener.class).toProvider(modalProvider(getter ->
2525
new SharingMetricsControllerListener(getConfig(), drtConfigGroup,

contribs/drt/src/main/java/org/matsim/contrib/drt/sharingmetrics/SharingMetricsTracker.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
import org.matsim.contrib.dvrp.passenger.PassengerPickedUpEvent;
1414
import org.matsim.contrib.dvrp.passenger.PassengerPickedUpEventHandler;
1515
import org.matsim.core.gbl.Gbl;
16-
import org.matsim.core.mobsim.framework.events.MobsimBeforeCleanupEvent;
17-
import org.matsim.core.mobsim.framework.listeners.MobsimBeforeCleanupListener;
1816

1917
import java.util.*;
2018

@@ -29,6 +27,8 @@ public class SharingMetricsTracker implements DrtRequestSubmittedEventHandler, P
2927
record Segment(double start, int occupancy) {
3028
}
3129

30+
private final String mode;
31+
3232
private final Map<Id<DvrpVehicle>, List<Id<Request>>> occupancyByVehicle = new HashMap<>();
3333

3434
private final Map<Id<Request>, List<Segment>> segments = new HashMap<>();
@@ -39,16 +39,23 @@ record Segment(double start, int occupancy) {
3939
private final Map<Id<Request>, Boolean> poolingRate = new HashMap<>();
4040

4141

42-
public SharingMetricsTracker() {
42+
public SharingMetricsTracker(String mode) {
43+
this.mode = mode;
4344
}
4445

4546
@Override
4647
public void handleEvent(DrtRequestSubmittedEvent event) {
48+
if (!event.getMode().equals(mode)) {
49+
return;
50+
}
4751
knownGroups.put(event.getRequestId(), new ArrayList<>(event.getPersonIds()));
4852
}
4953

5054
@Override
5155
public void handleEvent(PassengerDroppedOffEvent event) {
56+
if (!event.getMode().equals(mode)) {
57+
return;
58+
}
5259

5360
List<Id<Person>> passengers = knownGroups.get(event.getRequestId());
5461
Gbl.assertIf(passengers.contains(event.getPersonId()));
@@ -103,6 +110,9 @@ public void handleEvent(PassengerDroppedOffEvent event) {
103110

104111
@Override
105112
public void handleEvent(PassengerPickedUpEvent event) {
113+
if (!event.getMode().equals(mode)) {
114+
return;
115+
}
106116
List<Id<Request>> occupancy = occupancyByVehicle.computeIfAbsent(event.getVehicleId(), vehicleId -> new ArrayList<>());
107117
if (occupancy.contains(event.getRequestId())) {
108118
if (knownGroups.get(event.getRequestId()).size() > 1) {

contribs/drt/src/test/java/org/matsim/contrib/drt/sharingmetrics/SharingFactorTest.java

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public void testDrtSharingFactorHandler() {
3131

3232

3333
ParallelEventsManager events = new ParallelEventsManager(false);
34-
SharingMetricsTracker sharingFactorTracker = new SharingMetricsTracker();
34+
SharingMetricsTracker sharingFactorTracker = new SharingMetricsTracker(mode);
3535
events.addHandler(sharingFactorTracker);
3636

3737
events.initProcessing();
@@ -196,4 +196,71 @@ public void testDrtSharingFactorHandler() {
196196
Assertions.assertEquals(1., sharingFactorTracker.getSharingFactors().get(requestId1), MatsimTestUtils.EPSILON);
197197
}
198198
}
199+
200+
/**
201+
* Verifies that two trackers bound to different modes each process only their own
202+
* mode's events and produce independent, correct results.
203+
* <p>
204+
* mode_A has two pooled trips (sharing factor > 1); mode_B has a single solo trip
205+
* (sharing factor = 1). Before the fix both trackers would have seen all events and
206+
* produced identical, aggregated output.
207+
*/
208+
@Test
209+
public void testSharingMetricsAreComputedPerMode() {
210+
String modeA = "drt_A";
211+
String modeB = "drt_B";
212+
213+
var vehicleA = Id.create("vA", DvrpVehicle.class);
214+
var vehicleB = Id.create("vB", DvrpVehicle.class);
215+
216+
var person1 = Id.createPersonId("p1");
217+
var person2 = Id.createPersonId("p2");
218+
var person3 = Id.createPersonId("p3");
219+
220+
// Two requests in mode_A overlap completely -> both are pooled, sharing factor = 2
221+
var requestA1 = Id.create("rA1", Request.class);
222+
var requestA2 = Id.create("rA2", Request.class);
223+
224+
// One solo request in mode_B -> not pooled, sharing factor = 1
225+
var requestB1 = Id.create("rB1", Request.class);
226+
227+
ParallelEventsManager events = new ParallelEventsManager(false);
228+
229+
SharingMetricsTracker trackerA = new SharingMetricsTracker(modeA);
230+
SharingMetricsTracker trackerB = new SharingMetricsTracker(modeB);
231+
232+
events.addHandler(trackerA);
233+
events.addHandler(trackerB);
234+
events.initProcessing();
235+
236+
// mode_A: two requests picked up at the same time and dropped off at the same time
237+
events.processEvent(new DrtRequestSubmittedEvent(0.0, modeA, requestA1, List.of(person1), null, null, 0, 0, 0, 0, 0, 0, null, null));
238+
events.processEvent(new DrtRequestSubmittedEvent(0.0, modeA, requestA2, List.of(person2), null, null, 0, 0, 0, 0, 0, 0, null, null));
239+
events.processEvent(new PassengerPickedUpEvent(100.0, modeA, requestA1, person1, vehicleA));
240+
events.processEvent(new PassengerPickedUpEvent(100.0, modeA, requestA2, person2, vehicleA));
241+
events.processEvent(new PassengerDroppedOffEvent(200.0, modeA, requestA1, person1, vehicleA));
242+
events.processEvent(new PassengerDroppedOffEvent(200.0, modeA, requestA2, person2, vehicleA));
243+
244+
// mode_B: single solo trip
245+
events.processEvent(new DrtRequestSubmittedEvent(0.0, modeB, requestB1, List.of(person3), null, null, 0, 0, 0, 0, 0, 0, null, null));
246+
events.processEvent(new PassengerPickedUpEvent(100.0, modeB, requestB1, person3, vehicleB));
247+
events.processEvent(new PassengerDroppedOffEvent(300.0, modeB, requestB1, person3, vehicleB));
248+
249+
events.flush();
250+
251+
// --- trackerA: must contain exactly the two mode_A requests ---
252+
Assertions.assertEquals(2, trackerA.getSharingFactors().size(), "trackerA must track only mode_A requests");
253+
Assertions.assertNull(trackerA.getSharingFactors().get(requestB1), "trackerA must not contain mode_B request");
254+
Assertions.assertTrue(trackerA.getPoolingRates().get(requestA1), "requestA1 must be pooled");
255+
Assertions.assertTrue(trackerA.getPoolingRates().get(requestA2), "requestA2 must be pooled");
256+
Assertions.assertEquals(2., trackerA.getSharingFactors().get(requestA1), MatsimTestUtils.EPSILON);
257+
Assertions.assertEquals(2., trackerA.getSharingFactors().get(requestA2), MatsimTestUtils.EPSILON);
258+
259+
// --- trackerB: must contain exactly the one mode_B request ---
260+
Assertions.assertEquals(1, trackerB.getSharingFactors().size(), "trackerB must track only mode_B requests");
261+
Assertions.assertNull(trackerB.getSharingFactors().get(requestA1), "trackerB must not contain mode_A request rA1");
262+
Assertions.assertNull(trackerB.getSharingFactors().get(requestA2), "trackerB must not contain mode_A request rA2");
263+
Assertions.assertFalse(trackerB.getPoolingRates().get(requestB1), "requestB1 must not be pooled");
264+
Assertions.assertEquals(1., trackerB.getSharingFactors().get(requestB1), MatsimTestUtils.EPSILON);
265+
}
199266
}

0 commit comments

Comments
 (0)