Multi-Trip Routes (Reload)¶
A vehicle with limited capacity can serve more demand than it carries: allow it to return to its depot mid-route, reload, and continue. One vehicle then runs several trips within a single route.
How It Works¶
- Set
reloadon a vehicle type to allow mid-route reloads and to define the turnaround time spent at the depot per reload (0= instant). - The solver decides where and how often to reload — trips are priced and optimized together with the rest of the route.
- Reloading resets the carried load (both dimensions on two-dimensional instances; with pickup & delivery, peak-load tracking restarts per trip).
- The vehicle always reloads at its own
start_location. reloadrequires a capacity — reloading an uncapacitated vehicle is meaningless, and validation rejects it.
The turnaround time counts toward route duration exactly like a customer's
service_time: it delays all later arrivals and is included in
max_duration, shift_end, and time-window feasibility. The two extra travel
legs (to and from the depot) count toward route duration and distance.
Example¶
from tqrouting import TQRouter, VRPInstance, Customer, VehicleType, Location
router = TQRouter()
instance = VRPInstance(
customers=[
Customer(location=Location(matrix_id=1), delivery_load=6),
Customer(location=Location(matrix_id=2), delivery_load=6),
Customer(location=Location(matrix_id=3), delivery_load=6),
],
fleet=[
VehicleType(
start_location=Location(matrix_id=0),
end_location=Location(matrix_id=0),
capacity_load=12, # total demand is 18 -> a reload is needed
reload="00:05:00", # allowed, 5 min turnaround per reload
n_vehicles=1,
),
],
duration_matrix=[ # seconds
[0, 600, 600, 600],
[600, 0, 240, 240],
[600, 240, 0, 240],
[600, 240, 240, 0],
],
)
solution = router.solve(instance, time_limit=2)
Reading the Results¶
On multi-trip routes, route.customer_sequence contains ReloadStop entries
between customer visits, in stop order. A ReloadStop mirrors a visit's
timing fields:
eta— arrival time at the depotend_service_time—eta+ turnaround (when the vehicle is ready to leave)
Use the filtered views when you only need one kind of stop:
route = solution.routes[0]
route.visits # customer visits only
route.reload_stops # reload stops only
for stop in route.customer_sequence: # full stop order
print(stop)
# CustomerVisit(customer_id=0, eta=600, service=[600..600])
# ReloadStop(eta=1200, end_service_time=1500)
# CustomerVisit(customer_id=1, eta=2100, service=[2100..2100])
# CustomerVisit(customer_id=2, eta=2340, service=[2340..2340])
The vehicle delivers customer 0's six units first, returns to the depot (arriving at 1200, leaving after the 300 s turnaround at 1500), and serves the remaining twelve units in a second trip.
route.n_visits counts customers only — reload stops are not visits.
Note
compute_schedule arrival windows and set_departure_time are not yet
available on routes that contain reload stops.