This page is for an old version of Hexaly Optimizer.
We recommend that you update your version and read the documentation for the
latest stable release .
Hexaly
Hexaly Modeler
Object-oriented C++ APIs are provided for the virtual machine powering the LSP
language. With only a few classes, you can load modules, interact with their
variables and execute them. If you are not familiar with the LSP language,
please have a look at the language reference for
more information.
Create a module
First, you have to create a LSPModeler
environment. It is the
main class of the Modeler library and allows you to create a module in one
of two ways:
Both of these methods return an instance of LSPModule
which
will enable you to interact with the module’s variables and functions.
Launch a module
There are two launch modes for a module:
Optimization mode: This is the classic and default mode for the modeler.
At the very least, you must implement a model
method in your LSP
module that will build an LSModel. You can then call
LSPModule::run()
to start the execution of the module. This function
takes as first argument a LocalSolver instance that you have to create
beforehand using the LSPModeler::createSolver()
method.
After the LocalSolver model has been built, the resolution process will be
started automatically.
Note that the run method also accepts as a parameter a list of arguments
that will be passed as global variables to your module:
LSPModeler modeler ;
LocalSolver ls = modeler . createSolver ();
LSPModule module = modeler . loadModule ( "my_lsp_file.lsp" );
module . run ( ls , { "lsIterationLimit=100" , "lsTimeLimit=10" });
Main mode: In this mode, the modeler behaves like a classical programming
language. To use this mode, you have to implement a function named
main
in which you are free to do anything you want without being
limited by the formalism of the functions input
, model
, param
,
display
and output
. You can then call LSPModule::runMain()
to start the execution of the module.
Note that unlike the optimization mode, it is your responsibility to
manually create the solver instances, close your models and launch the
resolutions. In return, you are free to run several successive resolutions
or none at all if you just want to use LSP for its pure programming
features.
For more details on the differences between the optimization and the main
mode, read Main mode .
Interacting with variables
You can interact with the variables inside a module thanks to getters and
setters on the LSPModule
class. Values can be obtained in their
native type or retrieved as LSPValue
which is a container
that can hold any type of value inside a module. For more information
on value types available in the modeler you can look at LSPType
.
You can create maps from the modeler instance with
LSPModeler::createMap()
. A Map is a data structure holding
(key, value) pairs that can also be used as an array. For more information
on maps you can look at the
map module .
Using external functions
You can use your own C++ functions as
LSP functions in the modeler thanks to the
method LSPModeler::createFunction()
. First you have to extend the
LSPFunctor
class and implement the call()
function:
class MyLspFunction : public LSPFunctor {
LSPValue call ( LSPModeler & modeler , const std :: vector < LSPValue >& arguments ) {
lsdouble result = arguments [ 0 ]. asDouble () + arguments [ 1 ]. asDouble ();
return modeler . createDouble ( result );
}
}
MyLspFunction myFunc ;
LSPFunction lspFunc = modeler . createFunction ( & myFunc );
LSPValue args [ 2 ] = { modeler . createDouble ( 1.5 ), modeler . createDouble ( 2.3 )};
LSPvalue result = lspFunc . call ( args , 2 );
std :: cout << "result = " << result . asDouble () << std :: endl ; // prints "result = 3.8"
In the snippet above we declare an LSP function that takes two LSP doubles as
input, adds them together and returns the result. We can then call the
function with LSPFunction::call()
to execute the function and
retrieve the result.
You can also assign the function to a variable in a module with
LSPModule::setFunction()
. After doing so, the function will be
callable within any function of the module.