Single vehicle routing
Last updatedAugust 12, 2021
The following is an example for how to use the Nextmv vehicle engine to route a single driver from Mvrs-N-Shkrs Coffee Distributor to a set of coffee shops that ordered beans while minimizing distance traveled.
Our input for the model is pretty straightforward, with a set of locations and a single vehicle with a starting location.
{
"vehicles":
{
"vehicle_id": "Mvrs-N-Shkrs-1",
"start": [33.122746, -96.659222],
"end": [33.122746, -96.659222]
},
"requests": [
{
"location_id": "Coffee Labs Cafe",
"position": [33.004745, -96.827094]
},
{
"location_id": "The Caffeinated Cat",
"position": [33.005741, -96.86074]
},
{
"location_id": "Barks and Brew",
"position": [32.969456, -96.820915]
},
{
"location_id": "Study Loft",
"position": [32.921629, -96.695259]
},
{
"location_id": "Java the Hutt",
"position": [32.875507, -96.673973]
}
]
}
Since the value we are minimizing is the same as the vehicle engine, but the
input schema is different, we are going to use the DefaultModel to customize
for our data.
package route
import (
"github.com/nextmv-io/code/hop/model"
"github.com/nextmv-io/code/hop/solve"
"github.com/nextmv-io/code/engines/route/vehicle"
"github.com/mooney-corp/coffee-router/schema"
"github.com/nextmv-io/code/engines/measure"
vehicleschema "github.com/nextmv-io/code/engines/route/vehicle/schema"
)
// Solver constructs root state from inputs and options and returns a Minimizer.
func Solver(input schema.Input, opt solve.Options) (solve.Solver, error) {
// Extract geo points from requests to use in vehicle.
// i.e. [location 1, location 2, ...., location n]
points := []measure.Point{}
for _, request := range input.Requests {
points = append(points, request.Position)
}
// Create an intDomain for efficient indexing points.
requests := model.Domain(model.Range(0, len(points)-1))
// Add the vehicle start and end to points
input.Vehicle.StartIndex = len(points)
points = append(points, input.Vehicle.Start)
input.Vehicle.EndIndex = input.Vehicle.StartIndex
// measure the cost between location in haversine meters
measure := measure.HaversineByIndex(points)
// Build the vehicle model input
vehicleInput := vehicleschema.Vehicle{
VehicleID: input.Vehicle.ID,
Locations: requests,
Start: input.Vehicle.StartIndex,
End: input.Vehicle.EndIndex,
}
// Use the default model
root, err := vehicle.DefaultModel(vehicleInput, measure)
if err != nil {
return nil, err
}
opt.Tags["measure"] = measure
return solve.Minimizer(root, opt), nil
}
This is all we need to do! go build and we now have a vehicle router for our
coffee business.
Was this helpful?