Hexaly Modeler API¶
The modeler API allows you to interact with the virtual machine powering the LSP language: developers with prototypes written in LSP will now be able to integrate them in Python, Java, C#, and C++ environments fully. With these new bindings, you can, for example:
Load existing LSP files into modules and execute them.
Interact with functions and variables contained in modules.
Expose methods developed in your language of choice as LSP functions.
Thus, integrating the knapsack LSP program in a Python environment is now possible. First, we need to instantiate the API’s main class, the LSPModeler, which will enable us to interact with modules, maps, and functions. Given that the model above is available to us in a file named knapsack.lsp, we can load the module into the modeler with the following snippet:
from localsolver.modeler import *
with LSPModeler() as modeler:
knapsack_module = modeler.load_module("knapsack", "knapsack.lsp")
This makes all variables and functions contained in knapsack.lsp available to us
through the knapsack_module
object (see the
LSPModule reference). It also enables us to
execute this module, which means running the model function and starting the
resolution process. As we have seen before, we need to initialize a few
variables beforehand.
To set a value for integer variables like nbItems
and knapsackBound
, we
can do the following:
# Declares a variable named `nbItems` and sets its value to 5.
knapsack_module["nbItems"] = 5
Next, we need to input the weights and the prices. They are both collections of numbers, so they should be objects of type LSPMap:
# `weights_data` is the data we want to input.
weights_data = [5, 4, 6, 3, 1]
# `weights_map` is the LSPMap that will hold the values in the LSP program.
weights_map = modeler.create_map()
for value in weights_data:
weights_map.append(value)
knapsack_module["weights"] = weights_map
With all variables set, we can create a solver and execute the module by calling
either knapsack_module.run()
or knapsack_module.runMain()
depending on
the LSP mode (classic or main). This method replicates the behavior
we would get by executing the module from the command line, and we can pass
down arguments like lsTimeLimit
:
solver = modeler.create_solver()
knapsack_module.run(solver, "lsTimeLimit=10")
Once the resolution process is done, we can extract solution data:
# First we extract the LSExpression created within the LSP program.
obj_expression = knapsack_module["knapsackValue"]
# We can then extract the objective value using the regular LocalSolver Python API.
obj_value = obj_expression.value
Using the modeler API, you can thus benefit from the ease of modeling in LSP whilst still being able to integrate models in Python, Java, C#, and C++ applications.
Complete example¶
from localsolver.modeler import *
with LSPModeler() as modeler:
knapsack_module = modeler.load_module("knapsack", "knapsack.lsp")
# Declares a variable and sets its value.
knapsack_module["nbItems"] = 8
knapsack_module["knapsackBound"] = 102
# Data we want to input
weights_data = [10, 60, 30, 40, 30, 20, 20, 2]
prices_data = [1, 10, 15, 40, 60, 90, 100, 15]
# LSPMap that will hold the values in the LSP program
weights_map = modeler.create_map()
prices_map = modeler.create_map()
for value in weights_data:
weights_map.append(value)
for value in prices_data:
prices_map.append(value)
knapsack_module["weights"] = weights_map
knapsack_module["prices"] = prices_map
ls = modeler.create_solver()
knapsack_module.run(ls, "lsTimeLimit=10")
# First we extract the LSExpression created within the LSP program.
obj_expression = knapsack_module["knapsackValue"]
# We can then extract the objective value using the regular LocalSolver Python API.
obj_value = obj_expression.value
print("The final knapsack value is", obj_value)
#include "localsolver.h"
#include "modeler/lspmodeler.h"
#include <iostream>
using namespace localsolver;
using namespace modeler;
using namespace std;
int main(int argc, char** argv) {
LSPModeler modeler;
LSPModule knapsackModule = modeler.loadModule("knapsack", "knapsack.lsp");
// Declares a variable and sets its value.
knapsackModule.setInt("nbItems", 8);
knapsackModule.setInt("knapsackBound", 102);
// Data we want to input
vector<int> weights {10, 60, 30, 40, 30, 20, 20, 2};
vector<int> prices {1, 10, 15, 40, 60, 90, 100, 15};
// LSPMap that will hold the values in the LSP program
LSPMap weightsMap = modeler.createMap();
LSPMap pricesMap = modeler.createMap();
for (int value : weights)
weightsMap.addInt(value);
for (int value : prices)
pricesMap.addInt(value);
knapsackModule.setMap("weights", weightsMap);
knapsackModule.setMap("prices", pricesMap);
LocalSolver ls = modeler.createSolver();
vector<string> arguments {"lsTimeLimit=10"};
knapsackModule.run(ls, arguments);
// First we extract the LSExpression created within the LSP program.
LSExpression objExpression = knapsackModule.getExpression("knapsackValue");
// We can then extract the objective value using the regular LocalSolver C++ API.
int objValue = objExpression.getValue();
cout << "The final knapsack value is " << objValue << endl;
return 0;
}
using System;
using System.Collections.Generic;
using localsolver;
using localsolver.modeler;
public class ModelerTest : IDisposable
{
public void Dispose() {}
public static void Main(string[] args)
{
LSPModeler modeler = new LSPModeler();
LSPModule knapsackModule = modeler.LoadModule("knapsack", "knapsack.lsp");
// Declares a variable and sets its value.
knapsackModule.SetInt("nbItems", 8);
knapsackModule.SetInt("knapsackBound", 102);
// Data we want to input
List<int> weights = new List<int>() {10, 60, 30, 40, 30, 20, 20, 2};
List<int> prices = new List<int>() {1, 10, 15, 40, 60, 90, 100, 15};
// LSPMap that will hold the values in the LSP program
LSPMap weightsMap = modeler.CreateMap();
LSPMap pricesMap = modeler.CreateMap();
foreach (int value in weights)
weightsMap.AddInt(value);
foreach (int value in prices)
pricesMap.AddInt(value);
knapsackModule.SetMap("weights", weightsMap);
knapsackModule.SetMap("prices", pricesMap);
LocalSolver ls = modeler.CreateSolver();
List<string> arguments = new List<string>() {"lsTimeLimit=10"};
knapsackModule.Run(ls, arguments);
// First we extract the LSExpression created within the LSP program.
LSExpression objExpression = knapsackModule.GetExpression("knapsackValue");
// We can then extract the objective value using the regular LocalSolver C# API.
long objValue = objExpression.GetValue();
Console.WriteLine("The final knapsack value is " + objValue);
}
}
import java.util.Arrays;
import java.util.List;
import localsolver.*;
import localsolver.modeler.*;
public class ModelerTest {
public static void main(String[] args) {
try (LSPModeler modeler = new LSPModeler()) {
LSPModule knapsackModule = modeler.loadModule("knapsack", "knapsack.lsp");
// Declares a variable and sets its value.
knapsackModule.setInt("nbItems", 8);
knapsackModule.setInt("knapsackBound", 102);
// Data we want to input
List<Integer> weights = Arrays.asList(10, 60, 30, 40, 30, 20, 20, 2);
List<Integer> prices = Arrays.asList(1, 10, 15, 40, 60, 90, 100, 15);
// LSPMap that will hold the values in the LSP program
LSPMap weightsMap = modeler.createMap();
LSPMap pricesMap = modeler.createMap();
for (int value : weights)
weightsMap.addInt(value);
for (int value : prices)
pricesMap.addInt(value);
knapsackModule.setMap("weights", weightsMap);
knapsackModule.setMap("prices", pricesMap);
LocalSolver ls = modeler.createSolver();
List<String> arguments = Arrays.asList("lsTimeLimit=10");
knapsackModule.run(ls, arguments);
// First we extract the LSExpression created within the LSP program.
LSExpression objExpression = knapsackModule.getExpression("knapsackValue");
// We can then extract the objective value using the regular LocalSolver Java API.
long objValue = objExpression.getValue();
System.out.println("The final knapsack value is " + objValue);
} catch (Exception ex) {
System.err.println(ex);
ex.printStackTrace();
System.exit(1);
}
}
}