.. _optimizationplugin: Definition of an algorithm for the OptimizerLoop ========================================================================== The definition of the optimization algorithm is done by way of plugin. The plugin can be a C++ plugin implemented in a dynamic library (.so file) or a Python plugin implemented in a Python module (.py). It is possible to implement two kinds of algorithm : synchronous or asynchronous. The algorithm uses a pool of samples to be evaluated. When all the samples of the pool are evaluated, the algorithm stops. Synchronous algorithm -------------------------------------------------- In synchronous mode, the OptimizerLoop calls the algorithm to know what are the types of the input port (sample sent to the internal node), and of the output port (data returned by the internal node). Then it calls the algorithm to initialize it. At each iteration, it calls the algorithm to produce new sample or to stop the iteration. Finally, it calls the algorithm to finalize the optimization process. A synchronous algorithm is implemented in a class derived from the base class OptimizerAlgSync with several methods that must be implemented and some optional methods (in C++ and in Python): - **getTCForIn**, this method must return the YACS type of the input port of the internal node - **getTCForOut**, this method must return the YACS type of the output port of the internal node - **getTCForAlgoInit** (optional), this method returns the type of the "algoInit" port, string if undefined - **getTCForAlgoResult** (optional), this method returns the type of the "algoResult" port, string if undefined - **initialize** (optional), this method is called during the algorithm initialization - **start**, this method is called at the beginning of iterations - **takeDecision**, this method is called at each iteration - **finish** (optional), this method is called to finish the algorithm at the end of the iteration process - **getAlgoResult** (optional), this method returns the value of the "algoResult" port, "NULL" if undefined In Python you need to implement another method: - **setPool**, this method is used to set the data pool that is used to exchange data C++ plugin example '''''''''''''''''''' Here is a small example of a C++ synchronous algorithm: .. literalinclude:: ../src/yacsloader/Test/OptimizerAlgSyncExample.cxx :language: cpp Here, the entry point in the dynamic library is the name of the factory function : createOptimizerAlgSyncExample that returns an instance of the OptimizerAlgSyncExample class that implements the algorithm. Python plugin example '''''''''''''''''''''' Here, the same example of a synchronous algorithm in Python: .. literalinclude:: ../src/yacsloader/Test/algosyncexample.py Here, the entry point in the Python module is directly the name of the class that implements the algorithm : myalgosync. Asynchronous algorithm -------------------------------------------------- In asynchronous mode, all is the same except that after the initialization phase, the OptimizerLoop calls the algorithm only one time to start it in a separate thread. An asynchronous algorithm is implemented in a class derived from the base class OptimizerAlgASync with several methods that must be implemented and some optional methods (in C++ and in Python): - **getTCForIn**, this method must return the YACS type of the input port of the internal node - **getTCForOut**, this method must return the YACS type of the output port of the internal node - **getTCForAlgoInit** (optional), this method returns the type of the "algoInit" port, string if undefined - **getTCForAlgoResult** (optional), this method returns the type of the "algoResult" port, string if undefined - **initialize** (optional), this method is called during the algorithm initialization - **startToTakeDecision**, this method is called to start the iteration process in a separate thread. It is the body of the algorithm. - **finish** (optional), this method is called to finish the algorithm at the end of the iteration process - **getAlgoResult** (optional), this method returns the value of the "algoResult" port, "NULL" if undefined In Python you need to implement another method: - **setPool**, this method is used to set the data pool that is used to exchange data C++ plugin example '''''''''''''''''''' Here is a small example of a C++ asynchronous algorithm: .. literalinclude:: ../src/yacsloader/Test/OptimizerAlgASyncExample.cxx :language: cpp Here, the entry point in the dynamic library is the name of the factory function : createOptimizerAlgASyncExample that returns an instance of the OptimizerAlgASyncExample class that implements the algorithm. Python plugin example '''''''''''''''''''''''' Here is an example of an asynchronous algorithm implemented in Python: .. literalinclude:: ../src/yacsloader/Test/algoasyncexample.py Here, the entry point in the Python module is directly the name of the class that implements the algorithm : myalgoasync. Managing the pool of samples --------------------------------- Samples can be added to the pool at the initialization of the algorithm or every time a sample is evaluated (while "taking decision"). The algorithm stops to take decisions when every sample is evaluated. A sample has: - an identifier - *Id* - a priority - it is used to choose the order of evaluation - a value - *In* - an evaluated or computed value - *Out* The current sample is the sample used by the latest terminated evaluation. These are the methods needed to manage the pool of samples: .. code-block:: cpp class Pool { //... public: //For algorithm use int getCurrentId() const ; Any *getCurrentInSample() const ; Any *getCurrentOutSample() const ; Any *getOutSample(int id); void pushInSample(int id, Any *inSample, unsigned char priority = 0); void destroyAll(); //... } In C++, the samples are of type ``YACS::ENGINE::Any``, in order to support any type supported by YACS. For conversion to standard types, use: - ``getIntValue`` - ``getBoolValue`` - ``getDoubleValue`` - ``getStringValue`` It is possible to create a pointer to a new object with: - ``YACS::ENGINE::AtomAny::New`` For further information, see `include/salome/Any.hxx `_. C++ algorithm calling Python code -------------------------------------------------- In some cases, it can be necessary to implement the algorithm as a C++ class but nevertheless to call some Python code from this class. This is also possible with the OptimizerLoop and even quite simple. To achieve this, your C++ class should inherit from PyOptimizerAlgSync for a synchronous algorithm or from PyOptimizerAlgASync for an asynchronous algorithm. The guidelines for developing the algorithm are the same as in the C++ case, but you can also call any method from the Python C API. You don't need to take care of the Python global interpreter lock or of thread states because this is already done in the PyOptimizerAlg classes. An example of this kind of algorithm is the class OpenTURNSScriptLauncher that can be found in the module OPENTURNS_SRC.