-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Implement issue #4266: alternative stretch-test based on detour #4639
Conversation
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.
Can you compare the following:
- number of found alternatives compared to master
- performance impact
// const auto scaled_at_most_longer_by = | ||
// scaledAtMostLongerByFactorBasedOnDuration(shortest_route_duration); | ||
// const auto stretch_duration_limit = (1. + scaled_at_most_longer_by) * | ||
// shortest_route_duration; |
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.
Can this be removed?
// const auto stretch_duration_limit = (1. + scaled_at_most_longer_by) * | ||
// shortest_route_duration; | ||
|
||
const auto over_duration_limit = [&](const InternalRouteResult &route) { |
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.
Could you add a high-level description comment of what the following check does and why we need it
} | ||
|
||
auto s_it_e = short_seg.rbegin(); | ||
auto a_it_e = alter_seg.rbegin(); |
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.
Here and above: could you either make the variable names more clear or add a comment with the route sketch from the issue
There's also https://github.com/Project-OSRM/osrm-backend/blob/master/features/testbot/alternative.feature failing now because we no longer find an alternative. Feel free to adapt. |
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 think we are close, but there are some structural questions / considerations. For a testcase, I would suggest you try to implement a cucumber test as follows:
The test should be in the scenarios twice. Once with the weights chosen so that that the stretch between X
and a e f h
is accepted, once so that it isn't. Weights need to be selected (max-speed) in a way that the shortest path is a b c
and all other roads are invalid (you could also use restricted access). The partition size needs to be specified to separate all the four cliques.
const auto scaled_at_most_longer_by = | ||
scaledAtMostLongerByFactorBasedOnDuration(shortest_route_duration); | ||
const auto stretch_duration_limit = (1. + scaled_at_most_longer_by) * shortest_route_duration; | ||
static constexpr double kStretchScale = 1.2f; |
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 are we using a different factor here, compared to https://github.com/Project-OSRM/osrm-backend/pull/4639/files#diff-11d58f5aa5de9239b03afbaf1ac02bd9R45? I would like to keep it consistent with other factors.
In case there is a good reason for a new one, it should probably be defined up next to the others.
// also that there are just on different sequence | ||
auto s_it_b = short_seg.begin(); | ||
auto a_it_b = alter_seg.begin(); | ||
while ((*s_it_b).turn_via_node == (*a_it_b).turn_via_node && |
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.
If I see it correctly, you are skipping one node too much. Especially on motorways, this can have a longer segment not being considered.
You want to find the last node, which is common. Instead you are finding the first uncommon one.
// shortest_route_duration; | ||
|
||
const auto over_duration_limit = [&](const InternalRouteResult &route) { | ||
bool passed = true; |
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 would prefer a negative name here. Passed has an acceptance criteria meaning to me. What about something like over_limit
?
auto s_it_e = short_seg.rbegin(); | ||
auto a_it_e = alter_seg.rbegin(); | ||
while ((*s_it_b).turn_via_node == (*a_it_b).turn_via_node && | ||
s_it_e != short_seg.rend() && a_it_e != alter_seg.rend()) |
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.
same as above, you skip over one node to much.
|
||
// now calculate duration of found parts | ||
const auto calcDuration = [](auto it_begin, auto it_end) { | ||
double duration = 0.0; |
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.
https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/internal_route_result.hpp#L32 This value should be an integer. Any reason you switch to double here?
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.
Doesn't need to cast it later, twicely. There are no any problems, that it's already double there
} | ||
|
||
// now calculate duration of found parts | ||
const auto calcDuration = [](auto it_begin, auto it_end) { |
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 entire loop can be skipped, if you sum the distances you see during the discovery of the bounds.
calcDuration = length(P) - length(s,v) - length(u,t)
with u
and v
the last common nodes seen from source/target.
The same holds for the alternative path.
if (short_duration * kStretchScale < alter_duration) | ||
{ | ||
passed = false; | ||
break; |
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'd prefer return short_duration * kStretScale < alter_duration
bool passed = true; | ||
BOOST_ASSERT(route.unpacked_path_segments.size() == | ||
shortest_route.unpacked_path_segments.size()); | ||
for (size_t i = 0; i < shortest_route.unpacked_path_segments.size(); ++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.
I am a bit confused by this loop. We should only ever have a single path-segment, or the deviation should consider all path segments.
The via-node approach we support only does support a single segment and a single deviation. The moment multiple nodes are selected for the route, we will not provide alternatives. What we do here is somewhat a mix.
The code seems to allow alternatives on a by-segment basis, but removes the entire route if a single segment doesn't offer a reasonable alternative.
I would like to either clarify that we only do single destination alternatives (-> segments.size() == 1) or replace invalid segments with the shortest path in between to allow alternatives on a per-segment basis.
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 algorithm works fine with [0; N) segments, why we need it to remove it, if it more common, and prevent some future errors
Next actions here:
|
@daniel-j-h it's very strange, because i've pushed test fix yesterday to my branch, but it doesn't appeared into PR Will add comments, but algorithm that i've implemented was provided to me by @MoKob. |
@daniel-j-h Have no idea how to use this script to get compare data. Is there any instruction or ready test that can be suitable? Because it seems, that it require a lot of hand made work to prepare input csv file. Maybe there are already done work? |
You run the script once and it will create random queries - save these in a txt file. Then you can run repeated tests re-using the same queries you saved. For example something like this should get you started:
It would be great to compare timings and number of found alternatives for |
@daniel-j-h There are some results. As you wrote, i've used script and run it first 50000 queries, on
After that i've made python script to analyze this two csv files. It read each in memory an compare
There is a strange issue, because i have more average routes in my branch, then in This metric works very strange. My opinion that this metric not work good. Proof: In that file, there are cases, where this PR provide 2 routes, but master provides 1. For example check: |
I think, that approach of alternative routes find should be changed. The main problem right now, that we use 2 directional dijkstra's algorithm, main problem, that candidates for alternative routes got from cache of main route finding. So I think, that implementing A* algorithm can solve this problem, because it can be implemented with heuristic function, that prioritize better class roads, ( The main problem to find a good heuristic function, that will include |
Yes you need to figure out why your branch seems to find more routes then master - this should never happen if all you do here is filter out more routes. Make sure to fix both the base map and the queries you send.
Please read #3905 and http://algo2.iti.kit.edu/documents/Dissertation_Kobitzsch_Moritz.pdf section 5.2 "The Via-Node Paradigm" pages 59--65. The approach we're doing here for MLD is fine - if we need more candidates we can make the search space larger and tune quality coefficients in the impl. to trade-off quality vs quantity. |
@daniel-j-h There are new resuts:
But there are still no good routes, but some of them good. For example: Was filtered out in master. Wasn't filtered, because diff duration < 25% There are a list of queries, where Was ~6000 cases, for now 412 cases update: Whit that criteria we lost 37941 of 50000 alternative routes, that was in master Another words, there are no alternatives for 45840 of 50000 with that criteria. The same value for a |
@daniel-j-h Also i've checked for example in case http://192.168.100.6:9966/?z=9&loc=40.76237765397561%2C-82.33968788244843&loc=40.09863185660194%2C-83.13247493222241&hl=en&alt=0 i got for filter just on alternative route. And it's already very bad. With uturn on way |
@daniel-j-h Why thats going on? |
with const constexpr auto kAtMostLongerBy = 0.5;
|
closing stale PR. Reopen if still relevant. |
Issue
#4266
Tasklist