Salome HOME
[EDF26936] : End of the 2GB limit.
[modules/yacs.git] / doc / optimizer.rst
1
2 .. _optimizationplugin:
3
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.
9
10 The algorithm uses a pool of samples to be evaluated.
11 When all the samples of the pool are evaluated, the algorithm stops.
12
13 Synchronous algorithm
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.
19
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):
22
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
32
33 In Python you need to implement another method:
34
35 - **setPool**, this method is used to set the data pool that is used to exchange data
36
37 C++ plugin example
38 ''''''''''''''''''''
39 Here is a small example of a C++ synchronous algorithm:
40
41 .. literalinclude:: ../src/yacsloader/Test/OptimizerAlgSyncExample.cxx
42     :language: cpp
43
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.
46
47 Python plugin example
48 ''''''''''''''''''''''
49 Here, the same example of a synchronous algorithm in Python:
50
51 .. literalinclude:: ../src/yacsloader/Test/algosyncexample.py
52
53 Here, the entry point in the Python module is directly the name of the class that implements the algorithm : myalgosync.
54
55
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.
60
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):
63
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
72
73 In Python you need to implement another method:
74
75 - **setPool**, this method is used to set the data pool that is used to exchange data
76
77 C++ plugin example
78 ''''''''''''''''''''
79 Here is a small example of a C++ asynchronous algorithm:
80
81 .. literalinclude:: ../src/yacsloader/Test/OptimizerAlgASyncExample.cxx
82     :language: cpp
83
84
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.
87
88 Python plugin example
89 ''''''''''''''''''''''''
90 Here is an example of an asynchronous algorithm implemented in Python:
91
92 .. literalinclude:: ../src/yacsloader/Test/algoasyncexample.py
93
94 Here, the entry point in the Python module is directly the name of the class that implements the algorithm : myalgoasync.
95
96 Managing the pool of samples
97 ---------------------------------
98
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.
102
103 A sample has:
104
105 - an identifier - *Id*
106 - a priority - it is used to choose the order of evaluation
107 - a value - *In*
108 - an evaluated or computed value - *Out*
109
110 The current sample is the sample used by the latest terminated evaluation.
111
112 These are the methods needed to manage the pool of samples:
113
114 .. code-block:: cpp
115
116   class Pool
117   {
118       //...
119     public:
120       //For algorithm use
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);
126       void destroyAll();
127       //...
128   }
129
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:
132
133 - ``getIntValue``
134 - ``getBoolValue``
135 - ``getDoubleValue``
136 - ``getStringValue``
137
138 It is possible to create a pointer to a new object with:
139
140 - ``YACS::ENGINE::AtomAny::New``
141
142 For further information, see `include/salome/Any.hxx <file:../../../../../include/salome/Any.hxx>`_.
143
144 C++ algorithm calling Python code
145 --------------------------------------------------
146
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.