The second release of 2024 adds support for several new VRP variants, includes a few much needed refactorings, and overall makes PyVRP easier to use.
Highlights
- PyVRP now also supports return shipments, from clients back to the depot (in 471). This means PyVRP can now also solve the VRP with **backhaul**, and the VRP with **simultaneous pickup and delivery**. Examples have been added to the documentation (in 513).
- PyVRP now supports a **maximum distance** constraint (in 500), in addition to the maximum duration constraint that was added in v0.7.0.
- PyVRP now supports mutually exclusive client groups (in 514). Exactly one client in such a group must be visited. This can be used to model **generalised VRP**, but also for example the VRP with **multiple time windows**.
- `Model.solve` now takes solver configuration options, and can be toggled to display solver progress.
Breaking changes
The following breaking changes have been made to PyVRP's `Model` interface:
- The default values for `tw_late` and `max_duration` has changed to `INT_MAX` in all cases. Additionally, `VehicleType.tw_early = 0`, `VehicleType.tw_late = INT_MAX`, and `VehicleType.max_duration = INT_MAX` now no longer take `None` as an argument (in 463).
- The `VehicleType` now also has a `max_distance = INT_MAX` argument.
- The `Client.demand` attribute has been renamed to `delivery`, and a `Client.pickup` attribute has been added. The `pickup` attribute can be used to indicate the amount of goods flowing from a client back to the depot. The `Client.__init__` method has been updated to reflect these changes (in 471). More generally, `demand` has been renamed to `delivery`, and a `pickup` value has been added where appropriate.
- We have separated the underlying data structures for clients and depots (in 481). Before, a depot also used the same data structure as a client, which resulted in many attributes that a depot does not have (and should not have been set to values other than zero). This change rectifies the situation by making those attributes unavailable for depots. The consequences to user code should be limited if one uses the `pyvrp.Model` interface.
- The `Client` object now also takes an optional `group` argument to indicate membership in a client group.
- All getters have been renamed to drop the use of `get_`. E.g., `solution.get_routes()` is now simply `solution.routes()`.
- All `name` arguments (available for depots, clients, and vehicle types) must now be passed as keywords, rather than by position.
Additional changes have been made to PyVRP's internals, but should not impact users of PyVRP's modelling interface.
Additional
- We have added OR-Tools as a reference solver to our [benchmarks page](https://pyvrp.org/setup/benchmarks.html) (in #469). The gaps to the BKS are 5-13% across different instances.
- PyVRP now uses 64-bit integer values internally (in 490). This significantly increases the range of acceptable input values.
What's Changed
* Update pybind11 to v2.11.1 by N-Wouda in https://github.com/PyVRP/PyVRP/pull/447
* Update pyvrp.repair operator interface to use lists of routes, not solutions by N-Wouda in https://github.com/PyVRP/PyVRP/pull/448
* Add Solution::Route::depot() member by N-Wouda in https://github.com/PyVRP/PyVRP/pull/449
* Consistency checks by N-Wouda in https://github.com/PyVRP/PyVRP/pull/450
* Add another TWS test checking duration and time warp values by N-Wouda in https://github.com/PyVRP/PyVRP/pull/457
* Add asserts that check for overflow by N-Wouda in https://github.com/PyVRP/PyVRP/pull/462
* Test Client::required field is correctly set, add Client attributes documentation by N-Wouda in https://github.com/PyVRP/PyVRP/pull/466
* Move tests out of the source tree by N-Wouda in https://github.com/PyVRP/PyVRP/pull/467
* Make [0, INT_MAX] the default time windows by N-Wouda in https://github.com/PyVRP/PyVRP/pull/463
* OR-Tools benchmark by leonlan in https://github.com/PyVRP/PyVRP/pull/469
* Print solver progress by leonlan in https://github.com/PyVRP/PyVRP/pull/460
* Proxy for segments of route statistics by N-Wouda in https://github.com/PyVRP/PyVRP/pull/473
* New README badges by leonlan in https://github.com/PyVRP/PyVRP/pull/477
* Simultaneous pickup and delivery by N-Wouda in https://github.com/PyVRP/PyVRP/pull/471
* Separate client and depot structs by N-Wouda in https://github.com/PyVRP/PyVRP/pull/481
* Rename TimeWindowSegment to DurationSegment by N-Wouda in https://github.com/PyVRP/PyVRP/pull/483
* Remove NodeStats struct, use vectors instead by N-Wouda in https://github.com/PyVRP/PyVRP/pull/484
* Support VRPLIB backhaul instances by leonlan in https://github.com/PyVRP/PyVRP/pull/485
* Update read and tests to properly round load and capacity values by N-Wouda in https://github.com/PyVRP/PyVRP/pull/493
* Switch over to int64_t by N-Wouda in https://github.com/PyVRP/PyVRP/pull/490
* VRPB benchmarking instructions by leonlan in https://github.com/PyVRP/PyVRP/pull/494
* Add DistanceSegment by N-Wouda in https://github.com/PyVRP/PyVRP/pull/487
* Per client argument in CLI by leonlan in https://github.com/PyVRP/PyVRP/pull/497
* Remove "get" prefix from data accessors by N-Wouda in https://github.com/PyVRP/PyVRP/pull/499
* Split 2-OPT into ReverseSegment and SwapTails by N-Wouda in https://github.com/PyVRP/PyVRP/pull/510
* Update quick tutorial with new problem variants by N-Wouda in https://github.com/PyVRP/PyVRP/pull/513
* Remove unnecessary local search operators by leonlan in https://github.com/PyVRP/PyVRP/pull/511
* Exact round function by leonlan in https://github.com/PyVRP/PyVRP/pull/517
* Add support for a maximum distance constraint by N-Wouda in https://github.com/PyVRP/PyVRP/pull/500
* Remove double precision support by N-Wouda in https://github.com/PyVRP/PyVRP/pull/518
* Update tests to use assert_equal where possible by N-Wouda in https://github.com/PyVRP/PyVRP/pull/519
* Make name argument keyword only by N-Wouda in https://github.com/PyVRP/PyVRP/pull/526
* Add ClientGroup by N-Wouda in https://github.com/PyVRP/PyVRP/pull/528
* Generalised VRP by N-Wouda in https://github.com/PyVRP/PyVRP/pull/514
* Make collecting statistics optional by N-Wouda in https://github.com/PyVRP/PyVRP/pull/531
* Add SolveParams configuration and separate solve function by leonlan in https://github.com/PyVRP/PyVRP/pull/523
* Make PopulationParams fields readonly by N-Wouda in https://github.com/PyVRP/PyVRP/pull/536
* Clip the penalty parameters to [1, 100K] by N-Wouda in https://github.com/PyVRP/PyVRP/pull/535
* Add a link to the paper's preprint to README and docs by N-Wouda in https://github.com/PyVRP/PyVRP/pull/540
* Simplify operators by N-Wouda in https://github.com/PyVRP/PyVRP/pull/534
**Zenodo**: https://doi.org/10.5281/zenodo.11409573
**Full Changelog**: https://github.com/PyVRP/PyVRP/compare/v0.7.0...v0.8.0