-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Direct transit search #7145
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
Open
habrahamsson-skanetrafiken
wants to merge
32
commits into
dev-2.x
Choose a base branch
from
relaxed-limited-transfer-search
base: dev-2.x
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,425
−15
Open
Direct transit search #7145
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
bfe7155
feat: Implement RelaxedLimitedTransferSearch
habrahamsson-skanetrafiken 2207936
feat: Add configuration for RelaxedLimitedTransferSearch
habrahamsson-skanetrafiken 4588ff4
test: Tests for RelaxedLimitedTransferSearch
habrahamsson-skanetrafiken 6081246
feat: Implement direct transit search and refactor related components
t2gran 86a578e
feat: Add debug timers
habrahamsson-skanetrafiken b6a90f3
feat: Remove opening hour access/egress from direct transit search
habrahamsson-skanetrafiken bad1eed
Fix build
habrahamsson-skanetrafiken 1bd2aaa
Fix test
habrahamsson-skanetrafiken 14c38fd
Regen doc
habrahamsson-skanetrafiken 56f75f0
restore the enabled configuration flag
habrahamsson-skanetrafiken 9552764
fix: Fix for direct transit results not showing up
habrahamsson-skanetrafiken 8f2ecc2
change disableAcessEgress to maxAccessEgressDuration
habrahamsson-skanetrafiken 5bcfb71
Remove unused code
habrahamsson-skanetrafiken 57f1220
Add some documentation
habrahamsson-skanetrafiken 02ad356
Minor changes to RaptorDirectTransitRequest
habrahamsson-skanetrafiken bdc915c
Dont run search if access/egress is empty
habrahamsson-skanetrafiken 3e525f4
refactor: Remove unused RelaxedLimitedTransferRequest and rename test.
t2gran 4f21b2e
Address review comments
habrahamsson-skanetrafiken d500b70
Merge branch 'dev-2.x' into fix-direct
habrahamsson-skanetrafiken 1abe08a
Small fixes after merge
habrahamsson-skanetrafiken 30a9e4c
refactor: Skip trips in trip-search for direct transit search
t2gran 9527457
refactor: Separate mapping logic
habrahamsson-skanetrafiken 59f8755
Fix documentation
habrahamsson-skanetrafiken 8221011
refactor: Rename CostFactor to Reluctance
habrahamsson-skanetrafiken 75be5cf
Update preferences object
habrahamsson-skanetrafiken 2fef52c
Adress review comments
habrahamsson-skanetrafiken 4cb1c54
Update application/src/main/java/org/opentripplanner/routing/algorith…
habrahamsson-skanetrafiken bf33980
Add constructor non-null validation
habrahamsson-skanetrafiken 4c2df61
Fix nullable parameter
habrahamsson-skanetrafiken 46fe8ee
Don't log the enabled flag when default
habrahamsson-skanetrafiken 4fc568a
refactor: Only log DirectTransitPreferences when not default
t2gran 64cf3b4
Fix formatting
habrahamsson-skanetrafiken File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
...rg/opentripplanner/routing/algorithm/raptoradapter/transit/AccessEgressWithExtraCost.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package org.opentripplanner.routing.algorithm.raptoradapter.transit; | ||
|
|
||
| import org.opentripplanner.raptor.api.model.AbstractAccessEgressDecorator; | ||
| import org.opentripplanner.raptor.api.model.RaptorAccessEgress; | ||
|
|
||
| /** | ||
| * This decorator will add an extra cost factor to the c1 of the access/egress. | ||
| */ | ||
| public class AccessEgressWithExtraCost extends AbstractAccessEgressDecorator { | ||
|
|
||
| private final double costFactor; | ||
|
|
||
| public AccessEgressWithExtraCost(RaptorAccessEgress delegate, double costFactor) { | ||
| super(delegate); | ||
| this.costFactor = costFactor; | ||
| } | ||
|
|
||
| @Override | ||
| public int c1() { | ||
| return (int) (delegate().c1() * costFactor); | ||
| } | ||
| } |
83 changes: 83 additions & 0 deletions
83
...ipplanner/routing/algorithm/raptoradapter/transit/mappers/DirectTransitRequestMapper.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| package org.opentripplanner.routing.algorithm.raptoradapter.transit.mappers; | ||
|
|
||
| import java.time.Duration; | ||
| import java.util.Collection; | ||
| import java.util.List; | ||
| import java.util.Optional; | ||
| import org.opentripplanner.raptor.api.model.RaptorAccessEgress; | ||
| import org.opentripplanner.raptor.api.request.SearchParams; | ||
| import org.opentripplanner.raptor.direct.api.RaptorDirectTransitRequest; | ||
| import org.opentripplanner.routing.algorithm.raptoradapter.transit.AccessEgressWithExtraCost; | ||
| import org.opentripplanner.routing.api.request.RouteRequest; | ||
|
|
||
| public class DirectTransitRequestMapper { | ||
|
|
||
| /// Map the request into a request object for the direct transit search. Will return empty if | ||
| /// the direct transit search shouldn't be run. | ||
| public static Optional<RaptorDirectTransitRequest> map( | ||
| RouteRequest request, | ||
| SearchParams searchParamsUsed | ||
| ) { | ||
| var directTransitRequestOpt = request.preferences().transit().directTransit(); | ||
| if (directTransitRequestOpt.isEmpty()) { | ||
| return Optional.empty(); | ||
| } | ||
| var rel = directTransitRequestOpt.orElseThrow(); | ||
| Collection<? extends RaptorAccessEgress> access = searchParamsUsed.accessPaths(); | ||
| Collection<? extends RaptorAccessEgress> egress = searchParamsUsed.egressPaths(); | ||
|
|
||
| access = filterAccessEgressNoOpeningHours(access); | ||
| egress = filterAccessEgressNoOpeningHours(egress); | ||
|
|
||
| if (rel.maxAccessEgressDuration().isPresent()) { | ||
| var maxDuration = rel.maxAccessEgressDuration().get(); | ||
| access = filterAccessEgressByDuration(access, maxDuration); | ||
| egress = filterAccessEgressByDuration(egress, maxDuration); | ||
| } | ||
| if (rel.isExtraReluctanceAddedToAccessAndEgress()) { | ||
| double f = rel.extraAccessEgressReluctance(); | ||
| access = decorateAccessEgressWithExtraCost(access, f); | ||
| egress = decorateAccessEgressWithExtraCost(egress, f); | ||
| } | ||
| if (access.isEmpty() || egress.isEmpty()) { | ||
| return Optional.empty(); | ||
| } | ||
| var directRequest = RaptorDirectTransitRequest.of() | ||
| .addAccessPaths(access) | ||
| .addEgressPaths(egress) | ||
| .searchWindowInSeconds(searchParamsUsed.searchWindowInSeconds()) | ||
| .earliestDepartureTime(searchParamsUsed.earliestDepartureTime()) | ||
| .withRelaxC1(RaptorRequestMapper.mapRelaxCost(rel.costRelaxFunction())) | ||
| .build(); | ||
| return Optional.of(directRequest); | ||
| } | ||
|
|
||
| private static List<? extends RaptorAccessEgress> filterAccessEgressByDuration( | ||
| Collection<? extends RaptorAccessEgress> list, | ||
| Duration maxDuration | ||
| ) { | ||
| return list | ||
| .stream() | ||
| .filter(ae -> ae.durationInSeconds() <= maxDuration.toSeconds()) | ||
| .toList(); | ||
| } | ||
|
|
||
| private static List<? extends RaptorAccessEgress> filterAccessEgressNoOpeningHours( | ||
| Collection<? extends RaptorAccessEgress> list | ||
| ) { | ||
| return list | ||
| .stream() | ||
| .filter(it -> !it.hasOpeningHours()) | ||
| .toList(); | ||
| } | ||
|
|
||
| private static List<? extends RaptorAccessEgress> decorateAccessEgressWithExtraCost( | ||
| Collection<? extends RaptorAccessEgress> list, | ||
| double costFactor | ||
| ) { | ||
| return list | ||
| .stream() | ||
| .map(it -> new AccessEgressWithExtraCost(it, costFactor)) | ||
| .toList(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
173 changes: 173 additions & 0 deletions
173
...ain/java/org/opentripplanner/routing/api/request/preference/DirectTransitPreferences.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| package org.opentripplanner.routing.api.request.preference; | ||
|
|
||
| import java.time.Duration; | ||
| import java.util.Objects; | ||
| import java.util.Optional; | ||
| import javax.annotation.Nullable; | ||
| import org.opentripplanner.framework.model.Cost; | ||
| import org.opentripplanner.routing.api.request.framework.CostLinearFunction; | ||
| import org.opentripplanner.utils.tostring.ToStringBuilder; | ||
|
|
||
| /// All preferences related to the Direct Transit Search | ||
| public class DirectTransitPreferences { | ||
|
|
||
| // The next constants are package-local to be readable in the unit-test. | ||
| static final double DEFAULT_RELUCTANCE = 1.0; | ||
| static final CostLinearFunction DEFAULT_COST_RELAX_FUNCTION = CostLinearFunction.of( | ||
| Cost.costOfMinutes(15), | ||
| 1.5 | ||
| ); | ||
|
|
||
| public static final DirectTransitPreferences DEFAULT = new DirectTransitPreferences( | ||
| false, | ||
| DEFAULT_COST_RELAX_FUNCTION, | ||
| DEFAULT_RELUCTANCE, | ||
| null | ||
| ); | ||
|
|
||
| private final boolean enabled; | ||
| private final CostLinearFunction costRelaxFunction; | ||
| private final double extraAccessEgressReluctance; | ||
|
|
||
| @Nullable | ||
| private final Duration maxAccessEgressDuration; | ||
|
|
||
| private DirectTransitPreferences( | ||
| boolean enabled, | ||
| CostLinearFunction costRelaxFunction, | ||
| double extraAccessEgressReluctance, | ||
| @Nullable Duration maxAccessEgressDuration | ||
| ) { | ||
| this.enabled = enabled; | ||
| this.costRelaxFunction = Objects.requireNonNull(costRelaxFunction); | ||
| this.extraAccessEgressReluctance = extraAccessEgressReluctance; | ||
| this.maxAccessEgressDuration = maxAccessEgressDuration; | ||
| } | ||
|
|
||
| public static Builder of() { | ||
| return new Builder(DEFAULT); | ||
| } | ||
|
|
||
| public Builder copyOf() { | ||
| return new Builder(this); | ||
| } | ||
|
|
||
| /// Whether to enable direct transit search | ||
| public boolean enabled() { | ||
| return enabled; | ||
| } | ||
|
|
||
| /// This is used to limit the results from the search. Paths are compared with the cheapest path | ||
| /// in the search window and are included in the result if they fall within the limit given by the | ||
| /// costRelaxFunction. | ||
| public CostLinearFunction costRelaxFunction() { | ||
| return costRelaxFunction; | ||
| } | ||
|
|
||
| /// An extra cost that is used to increase the cost of the access/egress legs for this search. | ||
| public double extraAccessEgressReluctance() { | ||
| return extraAccessEgressReluctance; | ||
| } | ||
|
|
||
| /// Whether there is any extra access/egress reluctance | ||
| public boolean isExtraReluctanceAddedToAccessAndEgress() { | ||
| return extraAccessEgressReluctance != DEFAULT_RELUCTANCE; | ||
| } | ||
|
|
||
| /// A limit on the duration for access/egress for this search. Setting this to 0 will only include | ||
| /// results that require no access or egress. I.e. a stop-to-stop search. | ||
| public Optional<Duration> maxAccessEgressDuration() { | ||
| return Optional.ofNullable(maxAccessEgressDuration); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object o) { | ||
| if (o == null || getClass() != o.getClass()) { | ||
| return false; | ||
| } | ||
| DirectTransitPreferences that = (DirectTransitPreferences) o; | ||
| return ( | ||
| enabled == that.enabled && | ||
| Double.compare(extraAccessEgressReluctance, that.extraAccessEgressReluctance) == 0 && | ||
| Objects.equals(maxAccessEgressDuration, that.maxAccessEgressDuration) && | ||
| Objects.equals(costRelaxFunction, that.costRelaxFunction) | ||
| ); | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash( | ||
| enabled, | ||
| costRelaxFunction, | ||
| extraAccessEgressReluctance, | ||
| maxAccessEgressDuration | ||
| ); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| if (!enabled) { | ||
| return "DirectTransitPreferences{not enabled}"; | ||
| } | ||
| return ToStringBuilder.of(DirectTransitPreferences.class) | ||
| .addObj("costRelaxFunction", costRelaxFunction, DEFAULT.costRelaxFunction) | ||
| .addNum( | ||
| "extraAccessEgressReluctance", | ||
| extraAccessEgressReluctance, | ||
| DEFAULT.extraAccessEgressReluctance | ||
| ) | ||
| .addDuration( | ||
| "maxAccessEgressDuration", | ||
| maxAccessEgressDuration, | ||
| DEFAULT.maxAccessEgressDuration | ||
| ) | ||
| .toString(); | ||
| } | ||
|
|
||
| public static class Builder { | ||
|
|
||
| private boolean enabled; | ||
| private CostLinearFunction costRelaxFunction; | ||
| private double extraAccessEgressReluctance; | ||
| private Duration maxAccessEgressDuration; | ||
| public DirectTransitPreferences original; | ||
|
|
||
| public Builder(DirectTransitPreferences original) { | ||
| this.original = original; | ||
| this.enabled = original.enabled; | ||
| this.costRelaxFunction = original.costRelaxFunction; | ||
| this.extraAccessEgressReluctance = original.extraAccessEgressReluctance; | ||
| this.maxAccessEgressDuration = original.maxAccessEgressDuration; | ||
| } | ||
|
|
||
| public Builder withEnabled(boolean enabled) { | ||
| this.enabled = enabled; | ||
| return this; | ||
| } | ||
|
|
||
| public Builder withCostRelaxFunction(CostLinearFunction costRelaxFunction) { | ||
| this.costRelaxFunction = costRelaxFunction; | ||
| return this; | ||
| } | ||
|
|
||
| public Builder withExtraAccessEgressReluctance(double extraAccessEgressReluctance) { | ||
| this.extraAccessEgressReluctance = extraAccessEgressReluctance; | ||
| return this; | ||
| } | ||
|
|
||
| public Builder withMaxAccessEgressDuration(Duration maxAccessEgressDuration) { | ||
| this.maxAccessEgressDuration = maxAccessEgressDuration; | ||
| return this; | ||
| } | ||
|
|
||
| public DirectTransitPreferences build() { | ||
| var value = new DirectTransitPreferences( | ||
| enabled, | ||
| costRelaxFunction, | ||
| extraAccessEgressReluctance, | ||
| maxAccessEgressDuration | ||
| ); | ||
| return original.equals(value) ? original : value; | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.