-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add support for via-location visits in Raptor access and egress paths #7101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev-2.x
Are you sure you want to change the base?
Add support for via-location visits in Raptor access and egress paths #7101
Conversation
b80158a to
9d53204
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## dev-2.x #7101 +/- ##
=============================================
+ Coverage 72.09% 72.13% +0.04%
- Complexity 20706 20757 +51
=============================================
Files 2241 2242 +1
Lines 83725 83874 +149
Branches 8355 8380 +25
=============================================
+ Hits 60362 60503 +141
- Misses 20433 20437 +4
- Partials 2930 2934 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
9d53204 to
8dc0804
Compare
…tions visited in Raptor
The McStopArrivals is a critical class, building the listeners is just noice and can be done in a mapper and injected. This also remove StopArrivalParetoSet - witch only existed to take part of the listeners construction. A tiny business rule is no enforced by the the mapper, not ideal, but overall much better than it was. The mapper is responsible for the order the listeners are added.
…s from all workers.
26bc2e9 to
3469c83
Compare
| .max() | ||
| .orElse(0); | ||
|
|
||
| if (maxAccessViaVisits + maxEgressViaVisits > numberOfViaVisits) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic needs to be updates since the same via can be visited both in access and egress.
| "Stop Arrival - w/egress", | ||
| StopArrivalParetoSet.of(comparator).withEgressListener(List.of(), null).build() | ||
| ) | ||
| Arguments.of("Stop Arrival - regular", ParetoSet.of(comparator)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
they are both the same test case just under a different name
| null | ||
| accessPaths.filterOnSegment(i), | ||
| viaConnection, | ||
| egressPaths.filterOnSegment(nConnections - i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since you don't set the egress paths to null anymore, they shouldn't be nullable in the SearchContextViaSegments either
| ); | ||
| } | ||
|
|
||
| static TIntObjectMap<List<RaptorAccessEgress>> filter( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since this is used by both AccessPaths and EgressPaths I think this method might be better located in AccessEgressFunctions.
| } | ||
|
|
||
| /** | ||
| * Sets the next leg state. This is used to connect the state created by this config with the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some java doc still refers to segments as legs
|
|
||
| public static <T extends RaptorTripSchedule> TIntObjectMap< | ||
| ParetoSetEventListener<ArrivalView<T>> | ||
| > of( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's nice to separate this logic out, but I am not sure I like the naming here. When I call xxx.of(...) I'd expect to get a new instance of type xxx
| } | ||
|
|
||
| @Override | ||
| public boolean remove(Object o) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why could this be deleted?
|
|
||
| if (firstVectorAfterMarker == null) { | ||
| set.forEach(it -> buf.add(it.toString())); | ||
| set.stream().forEach(it -> buf.add(it.toString())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why did you add .stream() here and in the else block? Using a stream before forEach is just overhead, isn't it?
| * while using this iterator. | ||
| */ | ||
| private Iterator<T> tailIterator(final int startInclusive) { | ||
| private final Iterator<T> tailIterator(final int startInclusive) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private methods can't be overridden, so the final indicator is redundant
| } | ||
|
|
||
| @Override | ||
| protected final void notifyElementAccepted(T newElement) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the class is final, so the methods don't need to be
|
|
||
| @Override | ||
| protected final void notifyElementDropped(T element, T droppedByElement) { | ||
| if (eventListener != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the if clause is not necessary anymore. I'm not sure how much is actually won by putting the listener stuff into a child class. It's basically just dropping this if clause and having the very basic logic of calling the eventListener in another place. Not sure.
| /** | ||
| * In a via-search (both pass-through and visit-via) the access/egress may contain one | ||
| * ore more via-locations. If so Raptor needs to know how many via-locations are included | ||
| * ore more via-locations. If so, Raptor needs to know how many via-locations are included |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * ore more via-locations. If so, Raptor needs to know how many via-locations are included | |
| * or more via-locations. If so, Raptor needs to know how many via-locations are included |
| default void validateAccessEgressVisitVia(int numberOfViaLocations) { | ||
| int viaVisits = numberOfViaLocationsVisited(); | ||
|
|
||
| if (viaVisits < 0) { | ||
| throw new IllegalArgumentException( | ||
| "Access/Egress cannot have negative via visits: " + viaVisits | ||
| ); | ||
| } | ||
|
|
||
| if (viaVisits > numberOfViaLocations) { | ||
| throw new IllegalArgumentException( | ||
| "Access/Egress visits " + | ||
| viaVisits + | ||
| " via locations, but only " + | ||
| numberOfViaLocations + | ||
| " are defined" | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this kind of validation should be when you set the number of via locations instead of when you try to use them?
| * the "glue" make sure new destination arrivals are added to the destination arrivals. | ||
| */ | ||
| private TIntObjectMap<ParetoSetEventListener<ArrivalView<T>>> map() { | ||
| // debugListener, nextSearchListener, egressListener |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
| public class RouterResultPathAggregator<T extends RaptorTripSchedule> | ||
| implements RaptorRouterResult<T> { | ||
|
|
||
| private final RaptorRouterResult<T> master; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does master mean in this context?
| set.clear(); | ||
| set.addAll(list); | ||
| result.addAll(set); | ||
| result.addAll(set.stream().toList()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are repeating this stream.ToList() on at least a couple of places. Should ParetoSet itself have asList method?
| assertEquals( | ||
| """ | ||
| Walk 1m ~ A ~ BUS R1 0:05 0:15 ~ C ~ BUS R2 0:18 0:20 ~ D ~ Walk 1m [0:04 0:21 17m Tₙ1 C₁2_340] | ||
| Walk 1m ~ A ~ BUS R1 0:05 0:10 ~ B ~ Walk 15m Vₙ1 [0:04 0:25 21m Tₙ0 C₁2_820]""", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The formatting is a bit odd with """ at the end being on the same line. Is this something that prettier forces or something you can affect? There are other instances of this formatting in this class.
Summary
Build on top of #7095 and #7093.
Add support for via-location visits in access and egress paths in Raptor. This enables via points to be reached as part of access or egress. Currently we do not support flex, but the Raptor code do.
This PR extends Raptor's via-location search capability to handle via points that are visited in access or egress paths, not just during transit routing.
How the code works
See the Raptor desing doc
The implementation tracks the number of via locations visited in access/egress paths and uses a chain of Raptor workers+state. When a via-location is reached the state for that stop is coped over the the next segment. Driving this is a composit-worker and stop-arrival-events at the via-stops.
Key classes:
RangeRaptorWorkerComposite- chains Raptor searches togetherRouterResultPathAggregator- aggregates results from multiple segmentsViaConnectionStopArrivalEventListener- copies stop arrivals between segmentsArrivalsEventListenerMapper- builds and orders arrival listenersAccessEgressFunctions- filters access/egress by via countIssue
Part of #4887
Unit tests
J04_ViaVisitWithAccessTest- tests via locations visited in access pathsJ05_ViaVisitWithEgressTest- tests via locations visited in egress pathsDocumentation
✅ Design doc
✅ JavaDoc
Changelog
✅ Should be part of support for via