2 .. _optimizationplugin:
4 Definition of an algorithm for the OptimizerLoop
5 ==========================================================================
6 The definition of the optimization algorithm is done by way of plugin.
7 The plugin can be a C++ plugin implemented in a dynamic library (.so file) or a Python plugin implemented in a Python module (.py).
8 It is possible to implement two kinds of algorithm : synchronous or asynchronous.
10 The algorithm uses a pool of samples to be evaluated.
11 When all the samples of the pool are evaluated, the algorithm stops.
14 --------------------------------------------------
15 In synchronous mode, the OptimizerLoop calls the algorithm to know what are the types of the input port (sample sent to the internal node),
16 and of the output port (data returned by the internal node). Then it calls the algorithm to initialize
17 it. At each iteration, it calls the algorithm to produce new sample or to stop the iteration. Finally, it calls the algorithm
18 to finalize the optimization process.
20 A synchronous algorithm is implemented in a class derived from the base class OptimizerAlgSync with several methods that
21 must be implemented and some optional methods (in C++ and in Python):
23 - **getTCForIn**, this method must return the YACS type of the input port of the internal node
24 - **getTCForOut**, this method must return the YACS type of the output port of the internal node
25 - **getTCForAlgoInit** (optional), this method returns the type of the "algoInit" port, string if undefined
26 - **getTCForAlgoResult** (optional), this method returns the type of the "algoResult" port, string if undefined
27 - **initialize** (optional), this method is called during the algorithm initialization
28 - **start**, this method is called at the beginning of iterations
29 - **takeDecision**, this method is called at each iteration
30 - **finish** (optional), this method is called to finish the algorithm at the end of the iteration process
31 - **getAlgoResult** (optional), this method returns the value of the "algoResult" port, "NULL" if undefined
33 In Python you need to implement another method:
35 - **setPool**, this method is used to set the data pool that is used to exchange data
39 Here is a small example of a C++ synchronous algorithm:
41 .. literalinclude:: ../src/yacsloader/Test/OptimizerAlgSyncExample.cxx
44 Here, the entry point in the dynamic library is the name of the factory function : createOptimizerAlgSyncExample
45 that returns an instance of the OptimizerAlgSyncExample class that implements the algorithm.
48 ''''''''''''''''''''''
49 Here, the same example of a synchronous algorithm in Python:
51 .. literalinclude:: ../src/yacsloader/Test/algosyncexample.py
53 Here, the entry point in the Python module is directly the name of the class that implements the algorithm : myalgosync.
56 Asynchronous algorithm
57 --------------------------------------------------
58 In asynchronous mode, all is the same except that after the initialization phase, the OptimizerLoop calls the algorithm only one time
59 to start it in a separate thread.
61 An asynchronous algorithm is implemented in a class derived from the base class OptimizerAlgASync with several methods that
62 must be implemented and some optional methods (in C++ and in Python):
64 - **getTCForIn**, this method must return the YACS type of the input port of the internal node
65 - **getTCForOut**, this method must return the YACS type of the output port of the internal node
66 - **getTCForAlgoInit** (optional), this method returns the type of the "algoInit" port, string if undefined
67 - **getTCForAlgoResult** (optional), this method returns the type of the "algoResult" port, string if undefined
68 - **initialize** (optional), this method is called during the algorithm initialization
69 - **startToTakeDecision**, this method is called to start the iteration process in a separate thread. It is the body of the algorithm.
70 - **finish** (optional), this method is called to finish the algorithm at the end of the iteration process
71 - **getAlgoResult** (optional), this method returns the value of the "algoResult" port, "NULL" if undefined
73 In Python you need to implement another method:
75 - **setPool**, this method is used to set the data pool that is used to exchange data
79 Here is a small example of a C++ asynchronous algorithm:
81 .. literalinclude:: ../src/yacsloader/Test/OptimizerAlgASyncExample.cxx
85 Here, the entry point in the dynamic library is the name of the factory function : createOptimizerAlgASyncExample
86 that returns an instance of the OptimizerAlgASyncExample class that implements the algorithm.
89 ''''''''''''''''''''''''
90 Here is an example of an asynchronous algorithm implemented in Python:
92 .. literalinclude:: ../src/yacsloader/Test/algoasyncexample.py
94 Here, the entry point in the Python module is directly the name of the class that implements the algorithm : myalgoasync.
96 Managing the pool of samples
97 ---------------------------------
99 Samples can be added to the pool at the initialization of the algorithm or
100 every time a sample is evaluated (while "taking decision").
101 The algorithm stops to take decisions when every sample is evaluated.
105 - an identifier - *Id*
106 - a priority - it is used to choose the order of evaluation
108 - an evaluated or computed value - *Out*
110 The current sample is the sample used by the latest terminated evaluation.
112 These are the methods needed to manage the pool of samples:
121 int getCurrentId() const ;
122 Any *getCurrentInSample() const ;
123 Any *getCurrentOutSample() const ;
124 Any *getOutSample(int id);
125 void pushInSample(int id, Any *inSample, unsigned char priority = 0);
130 In C++, the samples are of type ``YACS::ENGINE::Any``, in order to support any
131 type supported by YACS. For conversion to standard types, use:
138 It is possible to create a pointer to a new object with:
140 - ``YACS::ENGINE::AtomAny::New``
142 For further information, see `include/salome/Any.hxx <file:../../../../../include/salome/Any.hxx>`_.
144 C++ algorithm calling Python code
145 --------------------------------------------------
147 In some cases, it can be necessary to implement the algorithm as a C++ class but
148 nevertheless to call some Python code from this class. This is also possible with the
149 OptimizerLoop and even quite simple. To achieve this, your C++ class should inherit from
150 PyOptimizerAlgSync for a synchronous algorithm or from PyOptimizerAlgASync for an
151 asynchronous algorithm. The guidelines for developing the algorithm are the same as in
152 the C++ case, but you can also call any method from the Python C API. You don't need to
153 take care of the Python global interpreter lock or of thread states because this is
154 already done in the PyOptimizerAlg classes. An example of this kind of algorithm is the
155 class OpenTURNSScriptLauncher that can be found in the module OPENTURNS_SRC.