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

Move LS route cost evaluation to CostEvaluator #417

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

wouterkool
Copy link
Collaborator

@wouterkool wouterkool commented Dec 12, 2023

This PR:

This is an exploratory implementation that moves the logic to compute the costs for a route inside the Exchange operator from the operator to the CostEvaluator. The idea is that the same logic can then be used for other operators (in a follow up PR).

By moving the cost evaluation logic to a central place, it is easier to implement different objectives and (soft) constraints such as duration in the objective, max duration, other vehicle cost structure, max distance etc. Additionally, this makes it easier to implement 'early prechecks' based on bounds on the route costs in a consistent way, also when changing objectives (this PR also has a stronger bounding mechanism than current main).

The downside is that the evaluation logic becomes more general and thereby less efficient. For example, we can no longer just compute delta distance (and delta cost from that) but we need to compute the new route distance and compare against the old route distance. Also, additional function calls introduce extra overhead.

In theory, the compiler could inline the calls and then deduce some logic that some computations kan be skipped, however this seems not to be happening as this code is significantly slower than the original. Despite the stronger bounding mechanism, the code is slower overall (TODO run some benchmarks).

@N-Wouda I remember we had a discussion and maybe you had some thoughts on how we can further optimize this?

  • Closes #xxxx.
  • Adds and passes relevant tests.
  • Has well-formatted code and documentation.

Notes:

  • It is essential that you add a test when making code changes.
    This keeps the code coverage level up, and helps ensure the changes work as intended.
  • When fixing a bug, you must add a test that would produce the bug in the master branch, and then show that it is fixed with the new code.
  • New code additions must be well formatted. Changes should pass the pre-commit workflow, which you can set up locally using pre-commit.
  • Docstring additions must render correctly, including escapes and LaTeX.

@wouterkool wouterkool marked this pull request as draft December 12, 2023 10:02
@wouterkool wouterkool changed the title Ls route cost eval props Move LS route cost evaluation to CostEvaluator Dec 12, 2023
* timeWarp
* Time warp for the route.
*/
struct RouteData
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: RouteData doesn't implement CostEvaluatable concept as it does not have uncollectedPrizes, fixedVehicleCost, loadExcess. While we could change that (or change the concept) I think it is cleaner this way: the concept is about the cost structure for a solution whereas this object is for a route. We could consider moving away from the concept (as we use it only once now) and also implement computing the 'solution level cost' based on a similar SolutionData (or properties or better name) that tracks KPI's of a solution.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like pyvrp.search.Route now does, I think this new object could also implement the member functions related to the concept. Then no further specialisation is necessary.

* timeWarp
* Time warp for the route.
*/
struct RouteData
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like pyvrp.search.Route now does, I think this new object could also implement the member functions related to the concept. Then no further specialisation is necessary.

Comment on lines +27 to +32
* RouteData(
* size: int,
* distance: Distance,
* load: Load,
* timeWarp: Duration
* )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about the name.

We use this exclusively in pyvrp.search, so putting this in CostEvaluator feels like the wrong place. Perhaps a new file in pyvrp/cpp/search?

Since this "route data" object essentially just holds the properties related to cost that a route will have after a proposed move is applied, a name like MoveProperties seems clearer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing to check remains performance. The previous attempt at decoupling delta cost computations from changes in route properties was not all that fast. This might be better, but I have no real feeling for where we lost those 20-30% iterations when going in this direction previously.

@N-Wouda
Copy link
Member

N-Wouda commented Feb 12, 2024

I think it'll be important to do something like this to also support e.g. duration in the objective, but I am not sure how to get there without the performance regression we identified in a previous PR. I also have some comments about the naming/interface and stuff, but those are not as much of a show-stopper as "make this work about as fast as what we currently do".

@N-Wouda
Copy link
Member

N-Wouda commented Mar 22, 2024

@wouterkool now that we have moved (almost all) cost evaluations to the CostEvaluator and reduced a lot of duplication along the way, I think we have done most of what this PR set out to do. Could you have a look and compare?

@wouterkool
Copy link
Collaborator Author

Sorry, I have not been able to catch up lately but it looks like a lot of nice work which indeed replaces this PR. I will find some time beginning of april to review things and see if everything is there or if there are still some remaining ideas to consider. Thanks!

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

Successfully merging this pull request may close these issues.

None yet

2 participants