This how-to guide assumes you already completed the steps described in the 5-minute getting started experience. To test that the Nextmv CLI is correctly configured, you can optionally run the following command on your terminal. It will get some files that are necessary to work with the Nextmv Platform. You can see the expected output as well.
The Nextmv Software Development Kit (SDK) lets you automate any operational decision in a way that looks and feels like writing other code. It provides the guardrails to turn your data into automated decisions and test and deploy them into production environments.
Introduction
This guide will walk you through our new-app
template which is acts as a skeleton to help you build your own custom model from scratch.
The template contains all the key elements a decision app built with the Nextmv platform must contain as placeholders but does not implement any real functionality.
If you do not feel comfortable building your own app from scratch, our other how-to guides for knapsack and shift scheduling will help you get there. In those guides we walk you through a working decision app, step by step.
To get the template, simply run the following command.
You can check that all files are available in the newly created new-app
folder. Running the tree
command, you should see the file structure.
LICENSE
contains the Apache License 2.0 under which we distribute this template.README.md
gives a short introduction to the new-app template and shows you how to run it.go.mod
andgo.sum
define a Go module and are used to manage dependencies, including the Nextmv SDK.input.json
describes the input data for a new-app template.main.go
contains the actual code of the new-app template.- The
new-app.code-workspace
file should be used to open the template in Visual Studio Code. It is pre-configured for you so that you can run and debug the template without any further steps.
Now you can run the template with the Nextmv CLI, reading from the input.json
file and writing to an output.json
file. The following command shows you how to specify solver limits as well. You should obtain an output similar to the one shown.
Note that transient fields like timestamps, duration, versions, etc. are represented with dummy values due to their dynamic nature. I.e., every time the input is run or the version is bumped, these fields will have a different value.
Now we will show you, step by step, what the code inside the main.go
achieves.
Dissecting the template
The first part of the main.go
defines a package name, imports packages that are needed by the code below and a main
function which is the starting point for the app. In the main
function the Run
function from the Nextmv run
package is being called. This function executes a solver which is passed in the form of the solver
function further down in the file.
The solver
function is where you actually build our model.
It takes two parameters input
and store.Options
. Whilst store.Options
is part of the Nextmv framework, the data struct input
serves as a custom data input when running the app. For the purpose of this skeleton, input simply contains a single field, Number
. We also added a json tag to automatically parse a json input data.
The central point of every decision app built with Nextmv's framework is the store
which holds all of the decision variables which are created as follows:
The last pieces that need to be implemented are a few functions: Value
, Validate
, Format
and Generate
.
The Generate
function is used to branch on the search tree and traverse the search space. In this template the Lazy
function with a helper variable i
is used to achieve this.
The Lazy
function returns a new Generator
of stores. It does this lazily, meaning on demand, and does this until there are no new stores to be created based on the current store. To achieve this, the Lazy
function takes two functions as arguments. The first function controls if we want to generate new child stores given the current store. We use a helper variable that contains the value of aVariable
of the store that the Generate
function is called upon and check whether it is still greater 0.
The second function takes a store and generates new child stores. Upon this child store the Generate
function will be called to create new stores. We do this by creating a set of changes to be made to the store the Generate
function is called on and applying the changes. By applying the changes a new store is created on which the Generate
function is called upon again.
In the Value
function the total value of a specific store is calculated. This value is used to evaluate which solution among all solutions is best. It takes a function as an input which gives us access to the store and all underlying decision variables and data. E.g., for TSP the travel time in seconds could be returned.
The Validate
function is used to check whether the solution is feasible and satisfies the operational requirements. E.g., for a knapsack, its weight must not be exceeded.
It is also recommended to implement the Format
function to achieve a user-friendly output that can also be used for post-processing.
The function itself is defined as such:
Last, in the template we return a solver using the Minimizer
function.