Skip to content
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

Scaling logic of speed_factor is flawed for high values #591

Closed
krashish8 opened this issue Oct 12, 2021 · 7 comments · Fixed by #592
Closed

Scaling logic of speed_factor is flawed for high values #591

krashish8 opened this issue Oct 12, 2021 · 7 comments · Fixed by #592
Milestone

Comments

@krashish8
Copy link
Contributor

Problem
The speed_factor in the vehicle does not scale vehicle travel times properly for higher values.
Specifically, the output produced is same for the same values of std::round(100/speed_factor). So,

  • with speed_factor > 200, all durations are 0 and random routes are computed
  • the scaling logic is flawed if 100 <= speed_factor <= 200, i.e., the result is same for any speed factor in this range.
  • the results are "almost" fine if 0 < speed_factor <= 100, but the time values in the output may not be exact. e.g. speed_factor = 70 and speed_factor = 100 produce the same result, because 100/70 ~ 100/100 ~ 1.

For small values of speed_factor, everything is fine.

Also,

  • speed_factor = 0 sounds like an undefined behaviour.
  • speed_factor < 0 is also possible, leading to random outputs.

To Reproduce
Change the speed_factor values in the input json and compare the result.

Expectation
Only positive values of speed_factor must be allowed, and the vehicle travel times shall scale properly for any values of the speed_factor.

@jcoupey
Copy link
Collaborator

jcoupey commented Oct 13, 2021

@krashish8 thanks for summing up the situation! The speed_factor parameter has been initially introduced as a way to marginally scale speeds/travel times in a situation where the routing profile need some adjustment to a certain extent. So most of the values are expected to be around 1. in the first place.

The discrete_duration_factor = std::round(1 / speed_factor * DIVISOR)) logic does introduce some biases for high speed_factor values but we badly need this to move computing to the integer world for performance so we can't simply revert the changes in #491.

I think we should simply enforce (and document) reasonable values of speed_factor in input, e.g. throw an error if not 0 < speed_factor <= 50.

I can't really think of use-cases with the need of higher values, but if need be they could (should?) be treated differently: either by adjusting the routing layer, or by scaling the matrix manually prior to solving the problem.

@krashish8
Copy link
Contributor Author

Yes, I understand that speed_factor was introduced considering the values are closer to 1. Enforcing the limit 0 < speed_factor <= 50 and properly documenting it would be the best way so that users are aware of it.

Normally, the speed_factor will lie in that range. But, one can think of some use-cases, such as:

  • If someone is using a custom cost matrix, where the cost is the euclidean distance between the points.
  • The speed_factor in the set to the avg. speed of the vehicle.
  • Distances are measured in km, and the speed is measured in km/hr, because it's a long route VRP problem, and everything is measured in km or hours (And VROOM allows using any unit of measurement).

In such cases, speed_factor may go high up to 100 km/hr or even more. This seems more like an imaginary situation, but something similar can occur.

These cases can be easily tackled by scaling the matrix manually or using some other units of measurement (such as meter and m/sec, since 50m/sec is sufficiently large). It is good to have this documented, just to make the users aware of it.

@krashish8
Copy link
Contributor Author

I think because of similar reasons, for the values of speed_factor NOT closer to 1, the "duration" (i.e. travel_time) per step is approximate in the output. Say, the distance is 4000, and speed_factor = any value in [23,28], then the duration that we get in the output for the step is always 160. (i.e. the duration when the speed factor is 25).

This is fine, considering nothing is "exact" in the real world, the service time or speed are all approximate. Still, can you think of some way of tackling this issue? I think the only best way would be to do some manual preprocessing i.e. scaling the matrix cost such that all the speed_factors become closer to 1. Anyone using a custom matrix and relying "only" on the speed_factor for scaling would think of this as an error.

@jcoupey
Copy link
Collaborator

jcoupey commented Oct 13, 2021

And VROOM allows using any unit of measurement

That's technically true but the introduction in the API docs states that "all timings are in seconds" and "all distances are in meters" (in order to be consistent with calls to routing engines). So users tweaking expected values/units should not really complain when getting inconsistent results. ;-)

The need for higher speed_factor values would only occur for users providing their own matrices (not using a routing engine). In that case I think that if the allowed values are too limiting, it means they're asking too much of the vroom scaling possibility, and should rather keep their own scaling logic outside vroom: compute relevant matrices in the first place and forget about speed_factor.

This is fine, considering nothing is "exact" in the real world, the service time or speed are all approximate. Still, can you think of some way of tackling this issue?

The rounding effect you point out is bigger (and less and less acceptable) as the speed_factor grows so the best way I see to tackle the problem is to further reduce the allowed values, e.g. to 0 < speed_factor <= 5.

@krashish8
Copy link
Contributor Author

Thanks, @jcoupey, got it! :)

I agree that reducing the speed factor to the range (0, 5] would be better. This way, anyone using a custom matrix would be aware of it, and have their own scaling logic. Simultaneously, this range is good enough, considering that for one problem, the speed of any vehicle would be "at most" 5 times the speed of some other vehicle.

Anyway, the speed factor is a double value, so it can accommodate any such range of speeds by custom scaling.

@jcoupey
Copy link
Collaborator

jcoupey commented Oct 13, 2021

So all in all it boils down to:

  • adding a check in the CostWrapper constructor to raise an error if the speed_factor is outside the range
  • document the restriction of speed_factor values

I'd like to have this straightened up in the next release, @krashish8 would you consider submitting a PR for this by any chance? ;-)

@jcoupey jcoupey added this to the v1.11.0 milestone Oct 13, 2021
@krashish8
Copy link
Contributor Author

Thanks, I'd love to submit a PR! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants