{
  "resources": [
    {
      "name": "delivery-truck",
      "capacity": [1000],
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T18:00:00Z"
      }]
    }
  ],
  "jobs": [
    {
      "name": "delivery-1",
      "location": {"latitude": 52.520, "longitude": 13.405},
      "load": [150],
      "duration": 600
    },
    {
      "name": "delivery-2", 
      "location": {"latitude": 52.523, "longitude": 13.401},
      "load": [200],
      "duration": 600
    }
  ]
}
{
  "routes": [
    {
      "resource": "delivery-van",
      "jobs": [
        {
          "job": "delivery-1",
          "arrival": "2024-03-15T09:15:00Z",
          "departure": "2024-03-15T09:25:00Z",
          "load": [150],  // Current load after this job
          "cumulativeLoad": [150]  // Total load at this point
        },
        {
          "job": "delivery-2",
          "arrival": "2024-03-15T09:45:00Z",
          "departure": "2024-03-15T09:55:00Z",
          "load": [200],
          "cumulativeLoad": [350]  // 150 + 200
        }
      ],
      "summary": {
        "maxLoad": [350],  // Peak load during route
        "capacityUtilization": 0.35  // 35% of 1000kg capacity
      }
    }
  ]
}

Capacity Management

The VRP solver provides comprehensive capacity management features to handle real-world loading constraints. From simple weight limits to complex multi-dimensional capacity tracking, this guide covers all capacity-related features.

Overview

Capacity management ensures that vehicles don’t exceed their loading limits while optimizing resource utilization. The solver supports:

  • Multi-dimensional capacity (weight, volume, pallets, etc.)
  • Dynamic capacity tracking for pickup/delivery operations
  • Capacity utilization optimization
  • Soft capacity constraints with violations

Basic Capacity Configuration

Single-Dimension Capacity

The simplest form uses a single capacity value:

{
  "resources": [
    {
      "name": "delivery-truck",
      "capacity": [1000],
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T18:00:00Z"
      }]
    }
  ],
  "jobs": [
    {
      "name": "delivery-1",
      "location": {"latitude": 52.520, "longitude": 13.405},
      "load": [150],
      "duration": 600
    },
    {
      "name": "delivery-2", 
      "location": {"latitude": 52.523, "longitude": 13.401},
      "load": [200],
      "duration": 600
    }
  ]
}

Always ensure that job loads and resource capacities have the same number of dimensions. If a resource has capacity: [1000, 50], all jobs must have loads like load: [weight, volume].

Multi-Dimensional Capacity

Handle multiple capacity constraints simultaneously:

{
  "resources": [
    {
      "name": "delivery-van",
      "capacity": [2000, 15, 24],  // [weight_kg, volume_m3, pallet_positions]
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T18:00:00Z"
      }]
    }
  ],
  "jobs": [
    {
      "name": "furniture-delivery",
      "location": {"latitude": 52.520, "longitude": 13.405},
      "load": [300, 4, 2],  // 300kg, 4m³, 2 pallet positions
      "duration": 1800
    },
    {
      "name": "appliance-delivery",
      "location": {"latitude": 52.523, "longitude": 13.401},
      "load": [150, 2, 1],  // 150kg, 2m³, 1 pallet position
      "duration": 900
    }
  ]
}

The solver tracks all capacity dimensions independently. A vehicle can only accept a job if ALL capacity dimensions have sufficient remaining space.

Pickup and Delivery Capacity

For pickup and delivery operations, capacity changes dynamically during the route:

{
  "resources": [
    {
      "name": "courier-1",
      "capacity": [500],
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T18:00:00Z",
        "start": {"latitude": 52.520, "longitude": 13.405},
        "end": {"latitude": 52.520, "longitude": 13.405}
      }]
    }
  ],
  "jobs": [
    {
      "name": "pickup-order-123",
      "location": {"latitude": 52.523, "longitude": 13.401},
      "load": [50],  // Positive load = pickup (adds to vehicle)
      "duration": 300,
      "activity": "PICKUP"
    },
    {
      "name": "delivery-order-123",
      "location": {"latitude": 52.517, "longitude": 13.388},
      "load": [50],  // Same load = delivery (removes from vehicle)
      "duration": 300,
      "activity": "DELIVERY"
    }
  ],
  "relations": [
    {
      "type": "PICKUP_AND_DELIVERY",
      "jobs": ["pickup-order-123", "delivery-order-123"]
    }
  ]
}

Capacity Flow Example

1

Initial State

Vehicle starts empty: 0 / 500 kg

2

After Pickup

Load increases: 50 / 500 kg

3

After Delivery

Load decreases: 0 / 500 kg

Active Capacity Coefficient

The activeCapacityCoefficient optimizes vehicle utilization by preferring fuller vehicles:

{
  "options": {
    "weights": {
      "activeCapacityCoefficient": 0.7,
      "capacityDiscountCoefficient": 0.1
    }
  }
}
activeCapacityCoefficient
number
default:"0.7"

Controls preference for using vehicle capacity efficiently. Higher values (0.8-1.0) strongly prefer fuller vehicles, while lower values (0.3-0.5) allow more distributed loading.

capacityDiscountCoefficient
number
default:"0.1"

Discount factor for capacity utilization scoring. Helps balance between filling vehicles completely vs. other objectives.

How Active Capacity Works

The solver calculates a capacity utilization score for each vehicle:

The active capacity coefficient encourages the solver to:

  1. Use fewer vehicles by filling them more completely
  2. Reduce partial loads and empty space
  3. Consolidate deliveries when possible

Score Impact Formula:

utilization_score = (used_capacity / total_capacity) * activeCapacityCoefficient

Dynamic Capacity Tracking for PDP

Pickup and Delivery Problems (PDP) require sophisticated capacity tracking as vehicle loads change throughout the route:

Real-Time Capacity Updates

1

Track Current Load

The solver maintains real-time load state for each vehicle:

{
  "vehicleState": {
    "currentLoad": [300, 5],  // [weight_kg, volume_m3]
    "remainingCapacity": [700, 10],  // Available space
    "maxCapacityReached": [450, 8]  // Peak during route
  }
}
2

Validate Each Stop

Before adding a job, the solver checks:

  • Can the vehicle handle the pickup load?
  • Will future deliveries free enough space?
  • Does the route respect capacity at all times?
3

Optimize Load Sequence

The solver may reorder stops to manage capacity:

  • Group pickups early when possible
  • Schedule deliveries to free space for later pickups
  • Balance load throughout the route

Complex PDP Example

Here’s a real-world scenario with multiple pickups and deliveries:

{
  "resources": [{
    "name": "courier-van",
    "capacity": [1000, 12],  // 1000kg, 12m³
    "shifts": [{
      "from": "2024-03-15T08:00:00Z",
      "to": "2024-03-15T18:00:00Z"
    }]
  }],
  "jobs": [
    // Morning pickups from suppliers
    {
      "name": "pickup-supplier-a",
      "location": {"latitude": 52.520, "longitude": 13.405},
      "load": [200, 3],
      "activity": "PICKUP",
      "duration": 900,
      "windows": [{"from": "2024-03-15T08:00:00Z", "to": "2024-03-15T10:00:00Z"}]
    },
    {
      "name": "pickup-supplier-b",
      "location": {"latitude": 52.525, "longitude": 13.410},
      "load": [300, 4],
      "activity": "PICKUP",
      "duration": 900,
      "windows": [{"from": "2024-03-15T08:00:00Z", "to": "2024-03-15T10:00:00Z"}]
    },
    
    // Midday deliveries to customers
    {
      "name": "deliver-customer-1",
      "location": {"latitude": 52.515, "longitude": 13.400},
      "load": [150, 2],
      "activity": "DELIVERY",
      "duration": 600,
      "windows": [{"from": "2024-03-15T11:00:00Z", "to": "2024-03-15T13:00:00Z"}]
    },
    
    // Afternoon mixed operations
    {
      "name": "pickup-return-1",
      "location": {"latitude": 52.510, "longitude": 13.395},
      "load": [100, 1],
      "activity": "PICKUP",
      "duration": 600,
      "windows": [{"from": "2024-03-15T14:00:00Z", "to": "2024-03-15T16:00:00Z"}]
    },
    {
      "name": "deliver-customer-2",
      "location": {"latitude": 52.530, "longitude": 13.415},
      "load": [250, 3],
      "activity": "DELIVERY",
      "duration": 600,
      "windows": [{"from": "2024-03-15T15:00:00Z", "to": "2024-03-15T17:00:00Z"}]
    }
  ]
}

Capacity Timeline Visualization

The solver tracks how capacity changes throughout the route:

Time     | Stop                 | Action   | Load Change | Current Load | Remaining
---------|---------------------|----------|-------------|--------------|------------
08:00    | Start               | -        | -           | [0, 0]       | [1000, 12]
08:30    | pickup-supplier-a   | PICKUP   | +[200, 3]   | [200, 3]     | [800, 9]
09:15    | pickup-supplier-b   | PICKUP   | +[300, 4]   | [500, 7]     | [500, 5]
11:30    | deliver-customer-1  | DELIVERY | -[150, 2]   | [350, 5]     | [650, 7]
14:30    | pickup-return-1     | PICKUP   | +[100, 1]   | [450, 6]     | [550, 6]
16:00    | deliver-customer-2  | DELIVERY | -[250, 3]   | [200, 3]     | [800, 9]

The solver ensures that at no point does the current load exceed the vehicle’s capacity in any dimension.

Common Use Cases

1. Last-Mile Delivery

Standard parcel delivery with weight and volume constraints:

{
  "resources": [{
    "name": "delivery-van",
    "capacity": [1000],  // 1000 kg
    "shifts": [{
      "from": "2024-03-15T08:00:00Z",
      "to": "2024-03-15T18:00:00Z"
    }]
  }],
  "jobs": [
    {"name": "parcel-1", "load": [5]},
    {"name": "parcel-2", "load": [3]},
    {"name": "parcel-3", "load": [8]}
  ]
}

2. Waste Collection

Vehicles that fill up and need to visit disposal sites:

{
  "resources": [{
    "name": "garbage-truck",
    "capacity": [10000],  // 10 tons
    "shifts": [{
      "from": "2024-03-15T06:00:00Z",
      "to": "2024-03-15T14:00:00Z"
    }]
  }],
  "jobs": [
    // Collection points (pickups)
    {"name": "bin-1", "load": [200], "activity": "PICKUP"},
    {"name": "bin-2", "load": [150], "activity": "PICKUP"},
    {"name": "bin-3", "load": [300], "activity": "PICKUP"},
    // Disposal site (delivery)
    {
      "name": "disposal-site",
      "load": [10000],  // Empties entire truck
      "activity": "DELIVERY",
      "duration": 1800
    }
  ]
}

3. Mixed Fleet Optimization

Different vehicle types with varying capacities:

{
  "resources": [
    {
      "name": "bike-courier",
      "capacity": [20, 0.5],  // 20kg, 0.5m³
      "category": "BIKE",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T18:00:00Z"
      }]
    },
    {
      "name": "cargo-van",
      "capacity": [1000, 8],  // 1000kg, 8m³
      "category": "CAR",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T18:00:00Z"
      }]
    },
    {
      "name": "truck",
      "capacity": [5000, 40],  // 5 tons, 40m³
      "category": "TRUCK",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T18:00:00Z"
      }]
    }
  ],
  "jobs": [
    {"name": "small-parcel", "load": [15, 0.3]},
    {"name": "large-parcel", "load": [500, 5]},
    {"name": "bulk-delivery", "load": [3000, 25]}
  ]
}

Best Practices

Capacity Planning Guidelines:

  1. Reserve Buffer: Keep 10-15% capacity buffer for unexpected additions
  2. Dimension Selection: Only use dimensions that actually constrain your operations
  3. Load Accuracy: Ensure load estimates include packaging and handling equipment
  4. Mixed Units: Keep units consistent (all kg or all lbs, not mixed)

Handling Overloading

When capacity constraints make problems infeasible:

1

Enable Partial Planning

{
  "options": {
    "partialPlanning": true
  }
}
2

Check Unassigned Jobs

Review the response for jobs that couldn’t be assigned due to capacity:

{
  "unassigned": ["heavy-delivery-5", "bulky-item-3"],
  "unassignedReasons": {
    "heavy-delivery-5": ["CAPACITY_EXCEEDED"],
    "bulky-item-3": ["NO_VEHICLE_WITH_SUFFICIENT_CAPACITY"]
  }
}
3

Add Resources or Adjust Loads

Either add more vehicles or review if load estimates are accurate.

Performance Considerations

Multi-dimensional capacity impact:

  • Each additional capacity dimension increases computation complexity
  • Use 1-3 dimensions for best performance
  • More than 5 dimensions may significantly slow solving

Optimization Tips

  1. Simplify When Possible: If volume rarely constrains, use weight only
  2. Round Values: Round loads to reasonable precision (1kg vs 1.234kg)
  3. Group Similar Items: Combine small items into single jobs when feasible

Capacity in Response

The solution includes capacity tracking information:

{
  "routes": [
    {
      "resource": "delivery-van",
      "jobs": [
        {
          "job": "delivery-1",
          "arrival": "2024-03-15T09:15:00Z",
          "departure": "2024-03-15T09:25:00Z",
          "load": [150],  // Current load after this job
          "cumulativeLoad": [150]  // Total load at this point
        },
        {
          "job": "delivery-2",
          "arrival": "2024-03-15T09:45:00Z",
          "departure": "2024-03-15T09:55:00Z",
          "load": [200],
          "cumulativeLoad": [350]  // 150 + 200
        }
      ],
      "summary": {
        "maxLoad": [350],  // Peak load during route
        "capacityUtilization": 0.35  // 35% of 1000kg capacity
      }
    }
  ]
}