Skip to content

docs: update vehicle routing use case guide - #2691

Open
TomCools wants to merge 9 commits into
TimefoldAI:mainfrom
TomCools:docs/update-vehicle-routing
Open

TomCools wants to merge 9 commits into
TimefoldAI:mainfrom
TomCools:docs/update-vehicle-routing

Conversation

@TomCools

Copy link
Copy Markdown
Contributor

Updated the vehicle routing use case guide to use the new service module. We don't describe everything in detail yet, but at least it mentions the maps service and the updated structure (to better lean into incremental) which I'm also fixing in TimefoldAI/timefold-quickstarts#1218.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity · 1 Low severity

Open (2)
What changed in this PR

Updates the vehicle-routing guide to use the service module, maps enrichment, asynchronous REST APIs, and incremental shadow variables.

Changes:

  • Reworks the domain model and constraints for medium-score unassigned visits.
  • Adds DTOs, model conversion, REST configuration, and service testing guidance.
  • Updates the quickstart source link and service-module Maven setup.
File Description
docs/​src/​modules/​ROOT/​pages/​quickstart/​quarkus-vehicle-routing/​vehicle-routing-solution.adoc Updated as part of this pull request.
docs/​src/​modules/​ROOT/​pages/​quickstart/​quarkus-vehicle-routing/​vehicle-routing-model.adoc Updated as part of this pull request.
docs/​src/​modules/​ROOT/​pages/​quickstart/​quarkus-vehicle-routing/​vehicle-routing-constraints.adoc Updated as part of this pull request.
docs/​src/​modules/​ROOT/​pages/​quickstart/​quarkus-vehicle-routing/​vehicle-routing-api.adoc Updated as part of this pull request.
docs/​src/​modules/​ROOT/​pages/​quickstart/​quarkus-vehicle-routing/​quarkus-vehicle-routing-quickstart.adoc Updated as part of this pull request.
docs/​src/​modules/​ROOT/​pages/​_attributes.adoc Updated as part of this pull request.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@triceo triceo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I am adding a few comments, but mostly this PR is for @rsynek to review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Review effort: Lite
Findings: 1 Low severity

Open (1)
Resolved since last review (2)

Copilot AI review requested due to automatic review settings September 29, 2026 08:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Review effort: Lite
Findings: 1 High severity · 1 Low severity

Open (2)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (2)

Copilot AI lite review requested due to automatic review settings October 4, 2026 13:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

One or more issues must be addressed before approval.

0 open findings

🧠 Review effort: Lite

TomCools and others added 6 commits October 26, 2026 08:47
Change handling of duplicate visit IDs in visitMap collection.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Clarified the description of the 'enable-fallback' option to specify that it applies when the remote service is unavailable.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@TomCools

Copy link
Copy Markdown
Contributor Author

@rsynek, update this so it fixes all merge issues.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved critical conversion and map-handling issues, plus moderate constraint and testing issues, remain.

2 open issues

Review effort: Lite

Copilot AI lite review requested due to automatic review settings October 30, 2026 11:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

A moderate active finding remains because the match weight optimizes assigned service duration rather than the documented goal of maximizing the number of assigned visits.

No open issues 🎉

2 resolved since last review

Review effort: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Active critical and moderate issues remain, including crashes on unreachable routes, inefficient duplicate location handling, and an incorrect visit-count constraint definition.

4 open issues

Review effort: Lite

Comment on lines +627 to +628
public double getNearbyDistance(Visit origin, LocationAware destination) {
return origin.getLocation().getTravelTimeTo(destination.getLocation()).seconds();
return 0;
}
return cumulativeDrivingTime + lastVisit.getLocation().getDrivingTimeTo(homeLocation);
return cumulativeDrivingTime + lastVisit.getLocation().getTravelTimeTo(homeLocation).seconds();
@@ -149,22 +111,26 @@ Specifically, these classes are the input of the problem:
* The `vehicles` field with all vehicles
** This is a list of planning entities, because they change during solving.
}

private static Location toLocation(LocationInputDTO dto) {
return new Location(dto.latitude(), dto.longitude());

@rsynek rsynek left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nicely written! Please see my question and comments inline; some parts may need a bit of polishing.


@QuarkusTest
class VehicleRoutingConstraintProviderTest {
class VehicleRoutePlanConstraintProviderTest {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The test content looks very different from what we have in the qs/use-cases/vehicle-routing. It's it a bit confusing for the reader?

.body(vehicleRoutePlan)
.expect().contentType(ContentType.TEXT)
.when().post("/route-plans")
.body(mapper.writeValueAsString(Map.of("modelInput", input)))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No need to go for random object serialized to JSON. We have the ModelRequest in the solver-service that acts as the top-level DTO and contains the modelInput field.

=== Generate the initial OpenAPI specification

This test verifies that after solving that it found a feasible solution (no hard constraints broken).
Before running a full build with `mvn install`, generate the initial OpenAPI specification file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This has been already improved and if the file is missing, the maven build generates it. Just checked that with the QS. Feel free to try for yourself.

return 0;
}

Visit lastVisit = visits.get(visits.size() - 1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Strictly speaking, this is a dangerous pattern to teach our users. If the related constraint starts from a vehicle shift and does not join the last visit, there is a risk of a score corruption, since Bavet won't propagate the last visit's change to this constraint.

Not introduced to this PR, so not in scope to fix it here. Also, we have it in the QS for a while already.

}

protected Constraint vehicleCapacity(ConstraintFactory factory) {
public Constraint vehicleCapacity(ConstraintFactory factory) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nitpick: the way the constraint is written allows temporary inconsistencies:
vehicle capacity = 10, visit A demands 12, the next visit B demands -4, which leads to no penalty.

constructor()
// Every solve builds its own one-off matrix rather than reusing a named, pre-built one.
@Override
public Optional<String> getLocationSetName() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

import org.acme.vehiclerouting.domain.Location;
* `getLocations()` returns every location the matrix needs to cover:
every vehicle's home location plus every visit's location.
* `getLocationSetName()` returns empty, so each solve builds its own one-off matrix

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

See my above comment; perhaps not worth even mentioning the method here.

----
--
==== No newline at end of file
Running locally, you use the local computation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we at least mention that locally we use the Haversine with a fixed speed factor?

----
package org.acme.vehiclerouting.dto.input;

public record LocationInputDTO(Double latitude, Double longitude) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Any particular reason to duplicate the original Location? It's JSON-serializable and used across our models.

This branch was successfully deployed

1 active and 1 inactive deployments
documentation (preview) — 632efcfe Deployed Oct 30, 2026 by TomCools via Build Documentation #839
internal — 632efcfe Deployed Oct 30, 2026 by TomCools via approval_required #839
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.

4 participants