Skip to main content

Vehicle cost

Vehicle costs tell the optimization engine how much each vehicle costs to run, so it can decide which vehicles to deploy and how far to route them. The solver always searches for the solution with the lowest total cost, so the numbers you set here directly shape the fleet plan.

SWAT models three complementary kinds of cost:

  • Fixed cost (vehicle_cost) — a one-time "activation fee" charged the moment a vehicle is used at all, regardless of how far or how long it drives.
  • Variable costs (cost_per_km, cost_per_hour) — charged in proportion to the distance driven and the time spent on the route, with an optional higher overtime rate once a shift runs long.
  • Per-stop cost (cost_per_stop) — charged once for every stop the vehicle serves, however short or close together those stops are.
Units

All monetary values use the currency's minor unit (cents for USD/SGD, or the base unit for JPY/THB — whatever your deployment's currency uses). overtime_threshold_duration is expressed in seconds (e.g. an 8.5-hour shift is 30600).

How the solver uses cost

In the Vehicle Routing Problem (VRP), vehicle_cost is added once to the total solution cost for every vehicle used to serve at least one order. Its purpose is to give the engine a way to decide whether it is more economical to add a new vehicle to the plan or to extend the route of a vehicle already in use. The solver picks the cheaper of:

  • Add a new vehicle — pay the fixed vehicle_cost.
  • Extend an existing route — pay the extra travel time and distance of adding more stops to a vehicle that is already in use.

The remaining rates then scale with whichever route it builds:

  • cost_per_km is multiplied by the total distance of the route. Use it to represent fuel and per-distance wear, or to bias the solver toward assigning distant work to whichever vehicle is cheapest per kilometre.
  • cost_per_hour is multiplied by the total duration of the route — measured from the start of the first stop to the end of the last, including travel, service, and any waiting time. Use it to represent driver wages or per-hour running costs.
  • Overtime bills route time up to overtime_threshold_duration at the regular cost_per_hour, and time beyond it at overtime_cost_per_hour. Overtime billing is only active if you set overtime_threshold_duration and overtime_cost_per_hour; set just one of them and the whole route is billed at the regular cost_per_hour.
  • cost_per_stop is multiplied by the number of stops the vehicle serves. Use it for costs that scale with the count of drops rather than with distance or time — per-parcel handling and paperwork, or a subcontractor who bills a flat fee per delivery.
What counts as a stop

Every pickup and dropoff node on the route counts as one stop, so a delivery-only order counts as one stop and a pickup-and-delivery order counts as two. Depot visits and waypoints are not charged.

Tuning vehicle_cost shifts the deploy-or-extend trade-off:

  • High vehicle_cost — the solver strongly prefers to fit more orders onto vehicles already in use, creating longer, more complex routes to avoid deploying another vehicle.
  • Low vehicle_cost — the solver is more willing to deploy additional vehicles when doing so produces more efficient individual routes (e.g. shorter travel times).

Set the value relative to your other operational costs, primarily travel costs:

  • Guideline: vehicle_cost should represent how much extra travel you are willing to accept to avoid deploying another vehicle. For example, at vehicle_cost = 10000 the solver will accept up to roughly 10000 seconds (~2.78 hours) of extra driving time on an existing route rather than use a new vehicle.
  • Typical range: 0 to 50,000 is a common starting point, though it can be much higher when travel costs are significant due to long distances or times.

Use case: prioritizing your own fleet

A common use case is a mixed fleet of owned vehicles and more expensive subcontracted vehicles:

  • Your fleet: assign a low vehicle_cost (e.g. 1000).
  • Subcontractor fleet: assign a high vehicle_cost (e.g. 50000).

The optimizer then always prioritizes your own vehicles, only "activating" a subcontractor's vehicle once it has exhausted all feasible options with your internal fleet — correctly modeling the real-world cost difference.

Use case: vehicles that bill per drop

Not every carrier charges by distance or by hour. A courier paid per parcel, or a 3PL that invoices a flat handling fee per delivery, is modeled with cost_per_stop instead:

  • Your fleet: leave cost_per_stop unset (or low) — your drivers cost the same whether a route has 10 stops or 20.
  • Per-drop carrier: set cost_per_stop to the fee that carrier charges for one delivery.

The solver then pushes stops toward whichever vehicle handles them most cheaply: the per-drop carrier picks up the deliveries that would be expensive for your own fleet to reach, and your own vehicles absorb the dense clusters where an extra stop is nearly free.

Keep order penalties above cost_per_stop

A stop is only worth serving if it costs less than dropping the order. If cost_per_stop exceeds an order's rejection penalty, the solver leaves that order unassigned rather than pay to visit it. Keep cost_per_stop well below the penalties of the orders you expect to be served.

Setting costs (Integration API)

Every cost field exists on both the Vehicle Type and the individual Vehicle:

  • Set a value on the Vehicle Type to define a fleet-wide default that applies to every vehicle of that type.
  • Set a value on an individual Vehicle to override the type default for that one vehicle.

Any field a vehicle does not specify inherits the value from its vehicle type. This lets you configure a sensible default once per type (e.g. all vans cost 150 per km) while still tuning an exceptional vehicle (e.g. a subcontracted van that costs more).

Vehicle Type — fleet-wide defaults:

POST /api/v2/vehicletype
{
"name": "Delivery Van",
"vehicle_cost": 10000,
"cost_per_km": 150,
"cost_per_hour": 2500,
"cost_per_stop": 300,
"overtime_cost_per_hour": 3750,
"overtime_threshold_duration": 30600
}

Vehicle — override the type default for a single vehicle:

PATCH /api/v2/vehicle/{vehicle_id}
{
"cost_per_hour": 3000
}

Parameters

ParameterTypeDefaultUnitWhat it charges
vehicle_costintegernullcurrency minor unitFixed amount added once per vehicle used.
cost_per_kmintegernullcurrency minor unit per kmMultiplied by the total distance of the route.
cost_per_hourintegernullcurrency minor unit per hourMultiplied by the total duration of the route.
cost_per_stopintegernullcurrency minor unit per stopMultiplied by the number of stops the vehicle serves.
overtime_cost_per_hourintegernullcurrency minor unit per hourRate applied to route time beyond the overtime threshold. Requires overtime_threshold_duration.
overtime_threshold_durationintegernullsecondsLength of a regular shift; time past this point is billed at the overtime rate. Requires overtime_cost_per_hour.
Stateless API

The same fields are set directly on each vehicle in the Stateless API request. cost_per_stop also accepts a fleet-wide default in model_parameters, which applies to every vehicle that does not set its own value.

Example: costing a mixed 2W / 4W / 10W fleet

A common setup has several vehicle sizes — a 2-wheeler (2W) for light loads, a 4-wheeler (4W) van for medium loads, and a 10-wheeler (10W) truck for the heaviest. Larger vehicles carry far more, but cost more to deploy and to run. By setting both the fixed vehicle_cost and the variable rates on each vehicle type, you let the solver choose the most economical mix for any order volume.

Two-wheeler delivery motorbike with a rear cargo box, the cheapest vehicle.

2-wheeler — light loads

$

Four-wheeler box truck, mid-priced.

4-wheeler — medium loads

$$

Ten-wheeler large truck with a long trailer, the most expensive vehicle.

10-wheeler — heavy loads

$$$

A cost ladder for these three types — cheapest to deploy at the top, most expensive at the bottom:

Vehicle typeTypical loadvehicle_costcost_per_kmcost_per_hour
2-wheeler (2W)light500301200
4-wheeler (4W)medium50001002000
10-wheeler (10W)heavy80001302600

Set each row once on its vehicle type (POST /api/v2/vehicletype).

When volume is high, bigger is often cheaper

Because vehicle_cost is charged once per vehicle used, splitting a large batch of orders across several small vehicles means paying that activation fee — and duplicating travel — multiple times. Consolidating onto one larger vehicle pays it once.

Suppose a dense batch of orders needs either two 4-wheelers or one 10-wheeler (which has the capacity to carry it all):

2 × 4-wheeler37,0001 × 10-wheeler29,450 — cheaper
For a high-volume batch, one 10-wheeler undercuts two 4-wheelers despite its higher variable rates.

Even though the 10-wheeler has higher per-km and per-hour rates, it wins by ~7,550 (about 20%): it pays the fixed cost once and avoids the duplicated depot trips two vans would make. The solver weighs trade-offs like this automatically and picks the cheaper option.

How those totals are calculated
Two 4-wheelers — each drives ~45 km over ~4.5 h
per van: 5000 + 100×45 + 2000×4.5 = 18,500
two vans: 18,500 × 2 = 37,000

One 10-wheeler — one consolidated loop of ~55 km over ~5.5 h
8000 + 130×55 + 2600×5.5 = 29,450
Right tool for the job

The same cost ladder also keeps small jobs cheap. For a handful of nearby orders, a 10-wheeler would waste its high fixed cost, so the solver falls back to the 2-wheeler. Set the costs to reflect real operating economics and the optimizer scales the vehicle choice to the demand.

Special considerations

CVRPTW mode

When using prebook_cvrptw mode, use vehicle_cost with caution. In this mode vehicles are often pre-configured with a partial_route to a depot for loading, which can cause the solver to assume all vehicles are already "in use," making vehicle_cost ineffective for minimizing fleet size.

To solve this, set the vehicle property zero_cost_if_only_partial_routes to true:

PATCH /api/v2/vehicle/{vehicle_id}
{
"vehicle_cost": 10000,
"zero_cost_if_only_partial_routes": true,
"partial_route": ["depot_node_uid"]
}

This flag tells the solver not to apply vehicle_cost if the vehicle only serves its pre-assigned partial route and is not assigned any new orders.

PDP mode

In prebook (PDP) mode, vehicle_cost can also have side effects if not configured carefully. Since vehicle starting positions are defined as nodes in a partial_route, the solver might incorrectly apply the cost. If the solver is not correctly minimizing the number of vehicles used, adjust the vehicle_cost value or review your partial_route setup to ensure it accurately reflects which vehicles are truly "inactive" at the start of the optimization.

Playground

You can try out the Vehicle Cost concept using the playground below. The example defines two vehicles: one "Cheap" (cost 100) and one "Expensive" (cost 10000). Observe how the solver prioritizes the cheaper vehicle for the assigned jobs.

Loading...