Hexaly Modeler
Object-oriented C#/.NET APIs are provided for the virtual machine powering the
Hexaly modeling language. With only a few classes, you can load modules,
interact with their variables and execute them. If you are not familiar with the
modeling language, please have a look at the
language reference for more information.
Create a module
First, you have to create a HexalyModeler
environment. As with
Hexaly Optimizer, we recommend using a “using” statement that will ensure
the native memory allocated for the modeler is correctly released when the
environment is discarded. HexalyModeler
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 HxmModule
which
will enable you to interact with the module 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
module that will build an HxModel. You can then call HxmModule.Run
to start the execution of the module. This function takes as first
argument a Hexaly Optimizer instance that you have to create beforehand
using the HexalyModeler.CreateOptimizer
method. After the
Hexaly Optimizer 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:
using ( HexalyModeler modeler = new HexalyModeler ())
{
HexalyOptimizer optimizer = modeler . CreateOptimizer ();
HxmModule module = modeler . LoadModule ( "module_name" , "my_file.hxm" );
module . Run ( optimizer , "hxIterationLimit=100" , "hxTimeLimit=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 HxmModule.RunMain
to start the execution of the module.
Note that unlike the optimization mode, it is your responsibility to
manually create the optimizer 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 the modeler 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 HxmModule
class. Values can be obtained in their
native C# type or retrieved as HxmValue
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 HxmType
.
You can create maps from the modeler instance with
HexalyModeler.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 expose your own C# functions to Hexaly Modeler and turns them into
Hexaly functions thanks to the method
HexalyModeler.CreateFunction
. The signature of the external function
must conform to the delegate HxmFunctor
:
HxmValue MyHxmFunction ( HexalyModeler modeler , IList < HxmValue > arguments ) {
double result = arguments [ 0 ] . AsDouble () + arguments [ 1 ] . AsDouble ();
return modeler . CreateDouble ( result );
}
void Main () {
HxmFunction hxmFunc = modeler . CreateFunction ( MyHxmFunction );
List < HxmValue > arguments = new List < HxmValue > ();
arguments . Add ( modeler . CreateDouble ( 1.5 ));
arguments . Add ( modeler . CreateDouble ( 2.3 ));
HxmValue result = hxmFunc . Call ( arguments );
Console . WriteLine ( "result = " + result . AsDouble ()); // prints "result = 3.8"
}
In the snippet above we declare a function that takes two doubles as input,
add them together and returns the result. We can then call the function
with HxmFunction.Call
to execute the function and retrieve the
result.
You can also assign the function to a variable in a module with
HxmModule.SetFunction
. After doing so, the function will be callable
within any function of the module.
Memory management
When you access a modeler object from the C# API, your C# program takes a
new reference to that modeler object (HxmMap
, HxmModule
,
HxmValue
or HxmFunction
are examples of references to
modeler objects).
A modeler object can only be destroyed if no more C# reference points to it.
In other words, a C# reference on a modeler object prevents the object from
being freed even if it is no longer used in the modeler. If you have
to create, access and destroy many objects in your Hexaly Modeler programs,
you may keep in memory objects that have become inaccessible within your
code. You have 3 ways to limit this phenomenon:
Wait for the destruction of your HexalyModeler object. All references
are automatically freed when the modeler is released by using the
HexalyModeler.Dispose
method on the HexalyModeler instance. This
is the simplest solution and the recommended solution if the
interactions between your C# code and Hexaly Modeler are limited to a
few exchanges at the beginning/end of the resolution.
Release specific references at any time by calling
HxmMap.Dispose
, HxmModule.Dispose
,
HxmFunction.Dispose
, HxmValue.Dispose
or
Hexaly.HexalyOptimizer.Dispose
.
Release all references attached to a HxmReferenceScope
.
When you instantiate a new reference scope object by doing
new HxmReferenceScope(modeler)
, all references created from that
point anywhere in the API will be automatically associated with that
scope. Finally, a call to HxmReferenceScope.Dispose
will release
all references registered in the scope and will restore the previous
scope as the current one.
Note that invoking any method on a released reference will throw an
exception. It is therefore important not to release your references too
early and to keep them alive as long as you need them.
Also note that several references can point to the same object if you
call methods like HxmMap.GetMap
or HxmModule.GetFunction
several times. At each call, a new reference is created. This is not a
problem in itself, but try to minimize the number of calls to functions that
return objects of type HxmMap
, HxmModule
,
HxmValue
or HxmFunction
to reduce the number of
references.