Upgrade guide
Upgrade guides for working with the Nextmv decision stack.

Nextmv v0.16.0

  • Set your go.mod requirements to match the new version.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.16.0
3
github.com/nextmv-io/code/hop v0.16.0
4
)
Copied!
The Expander.Expand() method now returns an additional bool value which indicates whether the expander can be queried for additional states. As a result you have to add this bool to your implementations of the Expander interface, for example, when you are passing a function to expand.Lazy(). Before this change you would return nil as the sentinel value to inform hop to not expand a state any further. Now you can return false when you want to stop expansion.
Before (Go)
After (Go)
1
return expand.Lazy(func() model.State {
2
return myState{}
3
})
Copied!
1
return expand.Lazy(func() (model.State, ok) {
2
// this signals that the expander can always be queried for a next state
3
// to signal that an expander is exhausted, return false as the second value
4
return myState{}, true
5
})
Copied!
The signatures of Assigner.Assign and VehicleSorter received and additional rand.Rand parameter that can be used to add randomization to their respective implementations. Importantly this ensures deterministic behavior (as long as only one thread is used) when re-running the same input with randomization.
Before (Go)
After (Go)
1
type Assigner interface {
2
// Assign determines the next assignment based on the current state.
3
Assign(State) Assignment
4
...
5
}
6
7
func DefaultVehicleSorter(s State, locations, vehicles model.IntDomain) []int {
8
}
Copied!
1
type Assigner interface {
2
// Assign determines the next assignment based on the current state.
3
Assign(State, *rand.Rand) Assignment
4
...
5
}
6
7
func DefaultVehicleSorter(s State, locations, vehicles model.IntDomain, random *rand.Rand) []int {
8
// use random to introduce randomness
9
}
Copied!

Nextmv v0.15.1

  • Set your go.mod requirements to match the new version.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.15.1
3
github.com/nextmv-io/code/hop v0.15.1
4
)
Copied!
In this release we removed the Hash() function from the Constraint interface. Thus, custom constraints no longer need to implement this function. In consequence, Hash() functions for existing custom constraints are now obsolete and can be removed from the code base.

Nextmv v0.15.0

Note, this release includes breaking changes and you now must have Go version >= 1.18 installed.
  • Set your go.mod requirements to match the new version.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.15.0
3
github.com/nextmv-io/code/hop v0.15.0
4
)
Copied!
If you did not set the solver's limits for duration, nodes, or solutions before, the new default values of 10s and model.MaxInt will be used respectively. The options can be set via environmental variables or directly in code.
Go
1
opt := solve.DefaultOptions()
2
opt.Limits.Duration = time.Duration(30 * time.Second)
3
opt.Limits.Nodes = 10
4
opt.Limits.Solutions = 10
Copied!

Nextmv v0.14.0

Note, this release includes breaking changes for fleet engine users only.
  • Set your go.mod requirements to match the new version.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.14.0
3
github.com/nextmv-io/code/hop v0.14.0
4
)
Copied!
The DefaultTimeTracker now takes two additional parameters, the indices of the vehicle's start/end location.
Before (Go)
After (Go)
1
timeTracker := vehicleEngine.DefaultTracker(
2
shiftStart,
3
windowDomains,
4
travelTimeMeasures,
5
serviceTimes,
6
durationGroups,
7
maxWaitTimes,
8
)
Copied!
1
timeTracker, err := vehicleEngine.DefaultTracker(
2
shiftStart,
3
windowDomains,
4
travelTimeMeasures,
5
serviceTimes,
6
durationGroups,
7
maxWaitTimes,
8
vehicleStartIndex,
9
vehicleEndIndex,
10
)
11
if err != nil {
12
return nil, err
13
}
Copied!
See the release notes for more information on what's included in v0.14.0.

Nextmv v0.13.0

Note, this release includes breaking changes for fleet engine users only.
  • Set your go.mod requirements to match the new version.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.13.0
3
github.com/nextmv-io/code/hop v0.13.0
4
)
Copied!
The here client received some updates. The WithAsyncTimeOut and WithAsyncPollingInterval have been removed and replaced by a cancellation context that is applied to the matrix functions.
Before (Go)
After (Go)
1
cli := here.NewClient("<API_KEY>", here.WithAsyncTimeout(300), here.WithAsyncPollingInterval(600))
2
matrix, err := cli.DistanceMatrix(points)
Copied!
1
cli := here.NewClient("<API_KEY>")
2
matrix, err := cli.DistanceMatrix(
3
context.Background(), // Used for cancellation instead of "WithAsyncTimeout" option
4
points,
5
)
6
if err != nil {
7
return nil, err
8
}
Copied!
The location measure - which handles service times - now also takes a new parameter, durationGroups, to apply an additional service time every time a group of stops is approached.
Before (Go)
After (Go)
1
m := measure.Location(measure, serviceTimes)
Copied!
1
m, err := measure.Location(measure, serviceTimes, make(measure.DurationGroups, 0))
2
if err != nil {
3
return nil, err
4
}
Copied!
The route.Operators option for router now has 2 parameters. The second parameter lets the user either replace or append the ALNS operators.
Before (Go)
After (Go)
1
router, err := route.NewRouter(
2
i.Stops,
3
i.Vehicles,
4
route.Operators(operators),
5
)
6
if err != nil {
7
return nil, err
8
}
Copied!
1
router, err := route.NewRouter(
2
i.Stops,
3
i.Vehicles,
4
route.Operators(operators, true),
5
)
6
if err != nil {
7
return nil, err
8
}
Copied!
The VehicleSorter sets the vehicle sorting function that determines the order in which the solver tries to assign locations.
Before (Go)
After (Go)
1
assigner := fleetEngine.CustomAssigner(
2
input,
3
selector,
4
groupers,
5
filters,
6
)
Copied!
1
import fleetEngine "github.com/nextmv-io/code/engines/route/fleet"
2
3
...
4
5
assigner := fleetEngine.CustomAssigner(
6
input,
7
selector,
8
groupers,
9
filters,
10
fleetEngine.DefaultVehicleSorter,
11
)
Copied!
See the release notes for more information on what's included in v0.13.0.

Nextmv v0.12.1

Set your go.mod requirements to match the new version. No additional steps are needed to upgrade to v0.12.1.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.12.1
3
github.com/nextmv-io/code/hop v0.12.1
4
)
Copied!
See the release notes for more information on what's included in v0.12.1.

Nextmv v0.12.0

  • Set your go.mod requirements to match the new version.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.12.0
3
github.com/nextmv-io/code/hop v0.12.0
4
)
Copied!
With this release the OSRM measure is extended to improve performance making parallel calls to the OSRM server. The faster request-response times are possible by splitting the distance/duration matrix and executing the resulting sub-requests in parallel. The scalability of this technique depends on the resources available to the OSRM server. For this reason a new argument is introduced when creating a new OSRM client that defines how many parallel calls should be made. There are three different options:
  • If a value smaller than 1 is given, the number of parallel calls will be chosen automatically.
  • If 1 is given, one call is made to the server.
  • If a value greater than 1 is given, that number of calls is made to the server.
Before (Go)
After (Go)
1
cli := osrm.DefaultClient("<your-host>", true)
2
osrm.DistanceDurationMatrices(cli, points)
Copied!
1
// Make 4 parallel calls to the OSRM server
2
cli := osrm.DefaultClient("<your-host>", true)
3
osrm.DistanceDurationMatrices(cli, points, 4)
Copied!

Nextmv v0.11.0

  • Set your go.mod requirements to match the new version.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.11.0
3
github.com/nextmv-io/code/hop v0.11.0
4
)
Copied!
  • With this release the following router options were renamed:
    • Measures option to ValueFunctionMeasures
    • TimeMeasures option to TravelTimeMeasures
    • Limit option was renamed to Limits
  • Before, the Limits option was only limiting the value function. Since this release, the options signature has changed to support full custom limitations of routes. To limit the route's distance or duration the new options LimitDistances and LimitDurations should be used.
Before (Go)
After (Go)
1
maxValues := []float64{1000.0, 2000.0}
2
3
router, err := route.NewRouter(
4
stops,
5
vehicles,
6
route.Measures(measures),
7
route.TimeMeasures(measures),
8
route.Limit(maxValues, true),
9
)
Copied!
1
// Create a Limit slice
2
limits := make([]route.Limit, len(i.Vehicles))
3
measures := measures(i)
4
for i, m := range measures {
5
limits[i] = route.Limit{
6
Measure: m,
7
Value: 9000,
8
}
9
}
10
11
router, err := route.NewRouter(
12
stops,
13
vehicles,
14
route.ValueFunctionMeasures(measures),
15
route.TravelTimeMeasures(measures),
16
route.Limits(limits, true),
17
)
18
19
// measures returns an array of Haversine measures based on stops.
20
func measures(i input) []measure.ByIndex {
21
count := len(i.Stops)
22
points := make([]measure.Point, count+2*len(i.Vehicles))
23
for s, stop := range i.Stops {
24
points[s] = measure.Point{stop.Position.Lon, stop.Position.Lat}
25
}
26
// Haversine measure.
27
measures := make([]measure.ByIndex, len(i.Vehicles))
28
m := measure.Indexed(measure.HaversineByPoint(), points)
29
for v := range i.Vehicles {
30
measures[v] = m
31
}
32
return measures
33
}
Copied!

Nextmv v0.10.0

  • Set your go.mod requirements to match the new version.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.10.0
3
github.com/nextmv-io/code/hop v0.10.0
4
)
Copied!
  • Profiles in the routingkit measure constructors have changed. We support the following standard profiles: Car, Truck, Bike and Pedestrian. We also provide support for custom profiles. Learn more about routingkit measures and (custom) profiles here.
Before (Go)
After (Go)
1
snapDistance := 1000
2
cacheSize := 1<<30
3
fallbackMeasure := measure.ScaleByPoint(measure.HaversineByPoint(), 1.3)
4
byPointDistance, err := routingkit.ByPoint(
5
osmFile,
6
snapDistance,
7
cacheSize,
8
routingkit.CarTravelProfile,
9
fallbackMeasure,
10
)
11
byPointDuration, err := routingkit.DurationByPoint(
12
osmFile,
13
snapDistance,
14
cacheSize,
15
fallbackMeasure,
16
)
Copied!
1
snapDistance := 1000
2
cacheSize := 1<<30
3
carProfile := routingkit.Car()
4
pedestrianProfile := routingkit.Pedestrian()
5
fallbackMeasure := measure.ScaleByPoint(measure.HaversineByPoint(), 1.3)
6
byPointDistance, err := routingkit.ByPoint(
7
osmFile,
8
snapDistance,
9
cacheSize,
10
carProfile,
11
fallbackMeasure,
12
)
13
byPointDuration, err := routingkit.DurationByPoint(
14
osmFile,
15
snapDistance,
16
cacheSize,
17
pedestrianProfile,
18
fallbackMeasure,
19
)
Copied!

Nextmv v0.9.1

  • Set your go.mod requirements to match the new version.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.9.1
3
github.com/nextmv-io/code/hop v0.9.1
4
)
Copied!
  • If using the Windows option in the router, now the service times (optional) and shifts (mandatory) are passed in with the Services and Shifts options.
Before (Go)
After (Go)
1
router, err := route.NewRouter(
2
stops,
3
vehicles,
4
route.Windows(windows, shifts),
5
)
Copied!
1
router, err := route.NewRouter(
2
stops,
3
vehicles,
4
route.Shifts(shifts),
5
route.Windows(windows),
6
route.Services(services),
7
)
Copied!

Nextmv v0.9.0

To upgrade to this version a few steps are necessary. To make your upgrade as smooth as possible, we give a step by step introduction which covers the minimum steps required to upgrade from version 0.8.0 or 0.8.1 to 0.9.0.
  • Set your go.mod requirements to match the new version.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.9.0
3
github.com/nextmv-io/code/hop v0.9.0
4
)
Copied!
  • The model.Domains function was renamed to model.Repeat to better reflect the purpose of this function. All you need to do is rename the function in case you used it. The signature did not change.
  • The signature of the alns.Destroyer and alns.Repairer interfaces changed. If you have implemented your own Destroyers or Repairers, you will have to add a parameter of type *rand.Rand as outlined below to still implement the respective interface.
Before (Go)
After (Go)
1
type Destroyer interface {
2
Destroy(ctx context.Context, m model.Valuer) model.Valuer
3
}
4
5
type Repairer interface {
6
Repair(ctx context.Context, m model.Valuer) model.Valuer
7
}
Copied!
1
type Destroyer interface {
2
Destroy(ctx context.Context, random *rand.Rand, m model.Valuer) model.Valuer
3
}
4
5
type Repairer interface {
6
Repair(ctx context.Context, random *rand.Rand, m model.Valuer) model.Valuer
7
}
Copied!
  • The signature of the MaxRouteLengthFilter changed as outlined below. Note that the first parameter changed from a single measure.ByIndex to []measure.ByIndex. For each vehicle you need to pass in one measure.ByIndex. In the simplest case, you can create a []measure.ByIndex with the length of the number of vehicles and set the same measure.ByIndex for all of the vehicles.
Before (Go)
After (Go)
1
func MaxRouteLengthFilter(m measure.ByIndex, routeLengths []float64, ignoreTriangular bool) (VehicleFilter, error)
Copied!
1
func MaxRouteLengthFilter(m []measure.ByIndex, routeLengths []float64, ignoreTriangular bool) (VehicleFilter, error)
Copied!

Nextmv v0.8.1

Set your go.mod requirements to match the new version. No additional steps are needed to upgrade to v0.8.1.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.8.1
3
github.com/nextmv-io/code/hop v0.8.1
4
)
Copied!
See the release notes or go package docs for more information on what's included in v0.8.1.

Nextmv v0.8.0

To upgrade to this version a few steps are necessary. To make your upgrade as smooth as possible, we give a step by step introduction which covers the minimum steps required to upgrade from version 0.7.3 to 0.8.0. Please keep in mind that, depending on your own code customizations, additional steps might be necessary.
  • Set your go.mod requirements to match the new version.
Go
1
require (
2
github.com/nextmv-io/code/engines v0.8.0
3
github.com/nextmv-io/code/hop v0.8.0
4
)
Copied!
  • Search for hopm and replace all occurrences in the import statements for engines (i.e., github.com/nextmv-io/code/hopm is now github.com/nextmv-io/code/engines).
  • To configure a window constraint, you now have to pass five instead of three arguments. If you used a stop_duration or maxWait_time in your measure, remove it there and pass them to the window method. Note that the length of the slice must match the length of your window constraint's slice. If you do not use them, you can simply pass nil.
Go
1
routeVehicle.Window(
2
int(vehicle.ShiftStart.Unix()),
3
windows,
4
measurer,
5
nil,
6
nil,
7
)
Copied!
  • Note that default UnassignedPenalties behavior has changed.
    • If no unassigned penalties are provided, assignment will be enforced (note, this could result in no feasible solutions being returned).
    • If unassigned penalties are provided, assignment will not be enforced. Unassignment will be discouraged (more or less, based on the penalty value).
    • If you are using a custom penalty in your value function to penalize unassigned locations, please remove it from there.
    If you solve a VRP, use UnassignedPenaltyfor all stops in your input.json and read it in your input.go.
    • Extend stop struct with new field UnassignedPenalty, read your json input.
    • Double check that your input data has values set for UnassignedPenalty. If you don't set this data, they will be set to zero and, thus, will not be assigned to your routes.
    • Make a slice of your UnassignedPenalty indexed by stop and pass it to your fleet schema.
Go
1
return fleetSchema.Fleet{
2
Locations: locations,
3
Vehicles: vehicles,
4
UnassignedPenalties: unassignedPenalties,
5
}
Copied!
  • Change deprecated Haversine methods, if necessary. The following code snipped should help you when applying the new method.
Before (Go)
After (Go)
1
measure.HaversineByIndex(point)
Copied!
1
measure.Indexed(measure.HaversineByPoint(), point)
Copied!
  • The Next() method now takes an argument and has changed to Next(ctx context.Context). If you are calling it, the argument to pass is context.Background().

Nextmv v0.7.1

See the release notes for details on upgrading to Nextmv v0.7.1.

Nextmv v0.7.0

See the release notes for details on upgrading to Nextmv v0.7.0.