Stop groups
You will learn how to use the Grouper option with a practical example.
In vehicle routing problems (VRPs) stops often have to be serviced in the same route together. In many cases this is a simple pickup/dropoff problem which you can easily address with our precedence option in the router engine. However, in some cases you may need to address more specific requirements that involve setting up groups that are served by the same vehicle.
The router engine provides the Grouper option to set up groups of stops. This is done by adding a stop matrix that defines the groups.

Example

The aim of this example is to create two groups of stops by ID that must be served together. The introductory router example is used as a base, where routes are created to visit seven landmarks in Kyoto using two vehicles.
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
"groups": [
34
["Fushimi Inari Taisha", "Kiyomizu-dera", "Nijō Castle"],
35
["Gionmachi", "Kinkaku-ji", "Arashiyama Bamboo Forest"]
36
]
37
}
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. We create 2 groups which we then pass into the Grouper option.
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
Groups [][]string `json:"groups,omitempty"`
14
}
15
16
// Use the CLI runner to solve a Vehicle Routing Problem.
17
func main() {
18
f := func(i input, opt solve.Options) (solve.Solver, error) {
19
router, err := route.NewRouter(
20
i.Stops,
21
i.Vehicles,
22
route.Grouper(i.Groups),
23
)
24
if err != nil {
25
return nil, err
26
}
27
28
return router.Solver(opt)
29
}
30
31
cli.Run(f)
32
}
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": "Kyoto Imperial Palace",
9
"position": {
10
"lon": 135.762057,
11
"lat": 35.025431
12
}
13
}
14
],
15
"route_duration": 0
16
},
17
{
18
"id": "v2",
19
"route": [
20
{
21
"id": "Arashiyama Bamboo Forest",
22
"position": {
23
"lon": 135.672009,
24
"lat": 35.017209
25
}
26
},
27
{
28
"id": "Kinkaku-ji",
29
"position": {
30
"lon": 135.728898,
31
"lat": 35.039705
32
}
33
},
34
{
35
"id": "Nijō Castle",
36
"position": {
37
"lon": 135.748134,
38
"lat": 35.014239
39
}
40
},
41
{
42
"id": "Gionmachi",
43
"position": {
44
"lon": 135.775682,
45
"lat": 35.002457
46
}
47
},
48
{
49
"id": "Kiyomizu-dera",
50
"position": {
51
"lon": 135.78506,
52
"lat": 34.994857
53
}
54
},
55
{
56
"id": "Fushimi Inari Taisha",
57
"position": {
58
"lon": 135.772695,
59
"lat": 34.967146
60
}
61
}
62
],
63
"route_duration": 1639
64
}
65
]
66
}
Copied!
You can see that stops which are grouped together are assigned to the same route. In this case both groups are assigned to the same vehicle for optimality reasons.
Export as PDF
Copy link