Capacities
You will learn how to use the Capacity option with a practical example.
Adding capacities to vehicles is a common task in vehicle routing problems (VRPs). This is known as the capacitated vehicle routing problem (CVRP). Stops have quantities associated to them that decrease or increase a vehicle's capacity. For example, a fuel-delivery truck can only hold a certain volume of fuel or a meal-delivery courier can only deliver three orders simultaneously, to keep them from losing freshness. In the case of sourcing, stops increase the vehicle's capacity since the vehicle is only performing pickups.
The router engine provides the Capacity option to configure a capacity constraint for the routing problem. This is done by specifying the stops' quantities and the vehicles' capacities. A stop's quantity:
  • decreases a vehicle's capacity if it is negative;
  • increases a vehicle's capacity if it is positive.
The Capacity option may be used multiple times if various dimensions need to be limited (for example, limiting weight and volume).

Example

The aim of this example is to add a quantity demanded to stops and a limited capacity to vehicles. The introductory router example is used as a base, where routes are created to visit seven landmarks in Kyoto using two vehicles.
capacity-input
Save the following information in an input.json file (see input and output for more information on working with input files).
JSON
1
{
2
"stops": [
3
{
4
"id": "Fushimi Inari Taisha",
5
"position": { "lon": 135.772695, "lat": 34.967146 }
6
},
7
{
8
"id": "Kiyomizu-dera",
9
"position": { "lon": 135.78506, "lat": 34.994857 }
10
},
11
{
12
"id": "Nijō Castle",
13
"position": { "lon": 135.748134, "lat": 35.014239 }
14
},
15
{
16
"id": "Kyoto Imperial Palace",
17
"position": { "lon": 135.762057, "lat": 35.025431 }
18
},
19
{
20
"id": "Gionmachi",
21
"position": { "lon": 135.775682, "lat": 35.002457 }
22
},
23
{
24
"id": "Kinkaku-ji",
25
"position": { "lon": 135.728898, "lat": 35.039705 }
26
},
27
{
28
"id": "Arashiyama Bamboo Forest",
29
"position": { "lon": 135.672009, "lat": 35.017209 }
30
}
31
],
32
"vehicles": ["v1", "v2"],
33
"quantities": [-1, -1, -1, -1, -1, -1, -1],
34
"capacities": [3, 4]
35
}
Copied!

Code

The following program uses the CLI Runner to obtain a solution and requires access to the Nextmv code repository on GitHub. To request access, please contact [email protected].
To proceed with running the example, create a main.go file and use the code snippet below.
Go
1
package main
2
3
import (
4
"github.com/nextmv-io/code/engines/route"
5
"github.com/nextmv-io/code/hop/run/cli"
6
"github.com/nextmv-io/code/hop/solve"
7
)
8
9
// Struct to read from JSON in.
10
type input struct {
11
Stops []route.Stop `json:"stops,omitempty"`
12
Vehicles []string `json:"vehicles,omitempty"`
13
Quantities []int `json:"quantities,omitempty"`
14
Capacities []int `json:"capacities,omitempty"`
15
}
16
17
// Use the CLI runner to solve a Vehicle Routing Problem.
18
func main() {
19
f := func(i input, opt solve.Options) (solve.Solver, error) {
20
router, err := route.NewRouter(
21
i.Stops,
22
i.Vehicles,
23
route.Capacity(i.Quantities, i.Capacities),
24
)
25
if err != nil {
26
return nil, err
27
}
28
29
return router.Solver(opt)
30
}
31
32
cli.Run(f)
33
}
Copied!
To execute the example, specify the path to the input.json file using command-line flags and use jq to extract the solution state (see runners for more information on building and running programs).
Bash
1
go run main.go -hop.runner.input.path input.json | jq .state
Copied!

Solution

The solution should look similar to this one:
JSON
1
{
2
"unassigned": [],
3
"vehicles": [
4
{
5
"id": "v1",
6
"route": [
7
{
8
"id": "Fushimi Inari Taisha",
9
"position": {
10
"lon": 135.772695,
11
"lat": 34.967146
12
}
13
},
14
{
15
"id": "Kiyomizu-dera",
16
"position": {
17
"lon": 135.78506,
18
"lat": 34.994857
19
}
20
},
21
{
22
"id": "Gionmachi",
23
"position": {
24
"lon": 135.775682,
25
"lat": 35.002457
26
}
27
}
28
],
29
"route_duration": 448
30
},
31
{
32
"id": "v2",
33
"route": [
34
{
35
"id": "Arashiyama Bamboo Forest",
36
"position": {
37
"lon": 135.672009,
38
"lat": 35.017209
39
}
40
},
41
{
42
"id": "Kinkaku-ji",
43
"position": {
44
"lon": 135.728898,
45
"lat": 35.039705
46
}
47
},
48
{
49
"id": "Nijō Castle",
50
"position": {
51
"lon": 135.748134,
52
"lat": 35.014239
53
}
54
},
55
{
56
"id": "Kyoto Imperial Palace",
57
"position": {
58
"lon": 135.762057,
59
"lat": 35.025431
60
}
61
}
62
],
63
"route_duration": 1085
64
}
65
]
66
}
Copied!
You can see that the capacity of each vehicle is not exceeded and the stops are assigned in a fashion that minimizes the route distance.
capacity-output
Export as PDF
Copy link