Cost optimisation¶
If all tasks can be planned, FastVRP minimises the total operational cost across all planned routes. Vehicles incur costs in three ways:
- Fixed cost: a one-time cost incurred when a vehicle is assigned to a route. This can be helpful to encourage the solver to use fewer vehicles, or when differentiating between in-house and third-party vehicles.
- Cost per kilometre: cost based on travel distance. Setting only a cost per kilometre optimises for shortest routes, for example to reduce fuel consumption.
- Cost per hour: hourly operating cost for the total route duration, and an additional cost per hour overtime for time exceeding the nominal shift duration.
By default, only the cost per hour is set (to 1.00), optimising for routes with minimal duration.
Tip
Keep fixed costs proportional to expected distance and duration costs for the best results.
Example¶
Three tasks in Rotterdam, Amsterdam, and Eindhoven each require 1 hour of service within the same morning window (8:00-10:00), so each task needs its own vehicle. All vehicles start and return to a depot in Utrecht. There are two fleets: an in-house primary fleet of one vehicle (100 fixed, 10/hour, 0.10/km) and a third-party (outsourced) fleet with many vehicles at twice the cost.
{
"locations": [
{
"id": "loc-Rotterdam",
"latitude": 51.9255,
"longitude": 4.4786
},
{
"id": "loc-Amsterdam",
"latitude": 52.3676,
"longitude": 4.9041
},
{
"id": "loc-Eindhoven",
"latitude": 51.4416,
"longitude": 5.4697
},
{
"id": "loc-Utrecht",
"latitude": 52.0907,
"longitude": 5.1214
}
],
"tasks": [
{
"id": "task-Rotterdam",
"location": "loc-Rotterdam",
"service_duration": "PT3600S",
"time_windows": [
{
"start": "2025-01-01T08:00:00",
"end": "2025-01-01T10:00:00"
}
]
},
{
"id": "task-Amsterdam",
"location": "loc-Amsterdam",
"service_duration": "PT3600S",
"time_windows": [
{
"start": "2025-01-01T08:00:00",
"end": "2025-01-01T10:00:00"
}
]
},
{
"id": "task-Eindhoven",
"location": "loc-Eindhoven",
"service_duration": "PT3600S",
"time_windows": [
{
"start": "2025-01-01T08:00:00",
"end": "2025-01-01T10:00:00"
}
]
}
],
"depots": [
{
"id": "depot-Utrecht",
"location": "loc-Utrecht"
}
],
"vehicle_types": [
{
"id": "in-house",
"start_depot": "depot-Utrecht",
"end_depot": "depot-Utrecht",
"num_available": 1,
"costs": {
"fixed": "100.00",
"per_hour": "10.00",
"per_km": "0.10"
},
"shift": {
"earliest_start": "2025-01-01T08:00:00",
"latest_end": "2025-01-01T18:00:00"
}
},
{
"id": "outsourced",
"start_depot": "depot-Utrecht",
"end_depot": "depot-Utrecht",
"num_available": 3,
"costs": {
"fixed": "200.00",
"per_hour": "20.00",
"per_km": "0.20"
},
"shift": {
"earliest_start": "2025-01-01T08:00:00",
"latest_end": "2025-01-01T18:00:00"
}
}
],
"options": {
"stop": {
"seconds": 1,
"type": "max_runtime"
}
}
}
Since only one in-house vehicle is available, two tasks must be served by the third-party fleet. FastVRP assigns the in-house vehicle to the Eindhoven route, as it has the highest distance and duration costs, making it the most cost-effective choice for the in-house vehicle.
The outsourced routes are roughly twice as costly due to the higher rates.
{
"summary": {
"total_cost": "152.82",
"distance_cost": "17.71",
"duration_cost": "35.11",
"fixed_vehicle_cost": "100.00",
"distance": 177052,
"duration": "PT12641S",
"travel_duration": "PT9041S",
"service_duration": "PT3600S",
"wait_duration": "P0D",
"start_time": "2025-01-01T08:00:00",
"end_time": "2025-01-01T11:30:41",
"num_tasks": 1,
"num_activities": 3,
"slack_duration": "PT2694S",
"load_duration": "P0D",
"overtime": "P0D"
},
"vehicle_type_id": "in-house",
"profile": "car",
"activities": [
{
"id": "depot-Utrecht",
"location": {
"id": "loc-Utrecht",
"latitude": 52.0907,
"longitude": 5.1214
},
"type": "depot",
"start_time": "2025-01-01T08:00:00",
"end_time": "2025-01-01T08:00:00",
"duration": "P0D",
"wait_duration": "P0D",
"travel_duration": "P0D",
"distance": 0
},
{
"id": "task-Eindhoven",
"location": {
"id": "loc-Eindhoven",
"latitude": 51.4416,
"longitude": 5.4697
},
"type": "task",
"start_time": "2025-01-01T09:15:06",
"end_time": "2025-01-01T10:15:06",
"duration": "PT3600S",
"wait_duration": "P0D",
"travel_duration": "PT4506S",
"distance": 88052
},
{
"id": "depot-Utrecht",
"location": {
"id": "loc-Utrecht",
"latitude": 52.0907,
"longitude": 5.1214
},
"type": "depot",
"start_time": "2025-01-01T11:30:41",
"end_time": "2025-01-01T11:30:41",
"duration": "P0D",
"wait_duration": "P0D",
"travel_duration": "PT4535S",
"distance": 89000
}
]
}
{
"summary": {
"total_cost": "267.14",
"distance_cost": "17.71",
"duration_cost": "49.43",
"fixed_vehicle_cost": "200.00",
"distance": 88538,
"duration": "PT8897S",
"travel_duration": "PT5297S",
"service_duration": "PT3600S",
"wait_duration": "P0D",
"start_time": "2025-01-01T08:00:00",
"end_time": "2025-01-01T10:28:17",
"num_tasks": 1,
"num_activities": 3,
"slack_duration": "PT4569S",
"load_duration": "P0D",
"overtime": "P0D"
},
"vehicle_type_id": "outsourced",
"profile": "car",
"activities": [
{
"id": "depot-Utrecht",
"location": {
"id": "loc-Utrecht",
"latitude": 52.0907,
"longitude": 5.1214
},
"type": "depot",
"start_time": "2025-01-01T08:00:00",
"end_time": "2025-01-01T08:00:00",
"duration": "P0D",
"wait_duration": "P0D",
"travel_duration": "P0D",
"distance": 0
},
{
"id": "task-Amsterdam",
"location": {
"id": "loc-Amsterdam",
"latitude": 52.3676,
"longitude": 4.9041
},
"type": "task",
"start_time": "2025-01-01T08:43:51",
"end_time": "2025-01-01T09:43:51",
"duration": "PT3600S",
"wait_duration": "P0D",
"travel_duration": "PT2631S",
"distance": 44198
},
{
"id": "depot-Utrecht",
"location": {
"id": "loc-Utrecht",
"latitude": 52.0907,
"longitude": 5.1214
},
"type": "depot",
"start_time": "2025-01-01T10:28:17",
"end_time": "2025-01-01T10:28:17",
"duration": "P0D",
"wait_duration": "P0D",
"travel_duration": "PT2666S",
"distance": 44340
}
]
}
{
"summary": {
"total_cost": "280.85",
"distance_cost": "24.46",
"duration_cost": "56.39",
"fixed_vehicle_cost": "200.00",
"distance": 122286,
"duration": "PT10150S",
"travel_duration": "PT6550S",
"service_duration": "PT3600S",
"wait_duration": "P0D",
"start_time": "2025-01-01T08:00:00",
"end_time": "2025-01-01T10:49:10",
"num_tasks": 1,
"num_activities": 3,
"slack_duration": "PT3973S",
"load_duration": "P0D",
"overtime": "P0D"
},
"vehicle_type_id": "outsourced",
"profile": "car",
"activities": [
{
"id": "depot-Utrecht",
"location": {
"id": "loc-Utrecht",
"latitude": 52.0907,
"longitude": 5.1214
},
"type": "depot",
"start_time": "2025-01-01T08:00:00",
"end_time": "2025-01-01T08:00:00",
"duration": "P0D",
"wait_duration": "P0D",
"travel_duration": "P0D",
"distance": 0
},
{
"id": "task-Rotterdam",
"location": {
"id": "loc-Rotterdam",
"latitude": 51.9255,
"longitude": 4.4786
},
"type": "task",
"start_time": "2025-01-01T08:53:47",
"end_time": "2025-01-01T09:53:47",
"duration": "PT3600S",
"wait_duration": "P0D",
"travel_duration": "PT3227S",
"distance": 60252
},
{
"id": "depot-Utrecht",
"location": {
"id": "loc-Utrecht",
"latitude": 52.0907,
"longitude": 5.1214
},
"type": "depot",
"start_time": "2025-01-01T10:49:10",
"end_time": "2025-01-01T10:49:10",
"duration": "P0D",
"wait_duration": "P0D",
"travel_duration": "PT3323S",
"distance": 62034
}
]
}
Conclusion¶
In this tutorial you learned how cost components influence routing decisions. This can be useful for managing fleet preferences, such as prioritising cheaper vehicles or balancing distance and duration trade-offs.