Salome HOME
Copyright update 2022
[modules/yacs.git] / src / runtime / SalomeOptimizerLoop.cxx
1 // Copyright (C) 2006-2022  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "SalomeOptimizerLoop.hxx"
21
22 // rnv: avoid compilation warning on Linux : "_POSIX_C_SOURCE" and "_XOPEN_SOURCE" are redefined
23 #ifdef _POSIX_C_SOURCE
24 #undef _POSIX_C_SOURCE
25 #endif
26
27 #ifdef _XOPEN_SOURCE
28 #undef _XOPEN_SOURCE
29 #endif
30 #include <Python.h>
31 #include "TypeCode.hxx"
32 #include "PyStdout.hxx"
33
34 //#define _DEVDEBUG_
35 #include "YacsTrace.hxx"
36
37 using namespace YACS::ENGINE;
38 using namespace std;
39
40
41 /*! \class YACS::ENGINE::SalomeOptimizerLoop
42  *  \brief class to build optimization loops
43  *
44  * \ingroup Nodes
45  */
46
47 SalomeOptimizerLoop::SalomeOptimizerLoop(const std::string& name, const std::string& algLibWthOutExt,
48                                          const std::string& symbolNameToOptimizerAlgBaseInstanceFactory,
49                                          bool algInitOnFile,bool initAlgo, Proc * procForTypes):
50                      OptimizerLoop(name,algLibWthOutExt,symbolNameToOptimizerAlgBaseInstanceFactory,algInitOnFile,false)
51 {
52   if(initAlgo)
53     {
54       //try
55       //  {
56           setAlgorithm(algLibWthOutExt, symbolNameToOptimizerAlgBaseInstanceFactory, true, procForTypes);
57       //  }
58       //catch(YACS::Exception& e)
59       //  {
60           //ignore it
61       //  }
62     }
63 }
64
65 SalomeOptimizerLoop::SalomeOptimizerLoop(const SalomeOptimizerLoop& other, ComposedNode *father, bool editionOnly): 
66                      OptimizerLoop(other,father,editionOnly)
67 {
68 }
69
70 SalomeOptimizerLoop::~SalomeOptimizerLoop()
71 {
72   Py_XDECREF(_pyAlgo);
73 }
74
75 Node *SalomeOptimizerLoop::simpleClone(ComposedNode *father, bool editionOnly) const
76 {
77   SalomeOptimizerLoop* sol=new SalomeOptimizerLoop(*this,father,editionOnly);
78   // TODO: Remove this const_cast (find a better design to get the type codes from the original node)
79   Proc * procForTypes = sol->getProc();
80   if (procForTypes == NULL) {
81     const Proc * origProc = getProc();
82     procForTypes = const_cast<Proc *>(origProc);
83   }
84   sol->setAlgorithm(_alglib, _symbol, false, procForTypes);
85   return sol;
86 }
87
88 //! Load the algorithm object from a Python module or a dynamic library
89 /*!
90  *  Member _alglib is the library name (shared library WITHOUT extension .so or python
91  *  module WITH extension .py). Member _symbol is a symbol name in the library to use as
92  *  an algorithm factory.
93  */
94 void SalomeOptimizerLoop::loadAlgorithm()
95 {
96   YASSERT(_alg == NULL)
97
98   if(_alglib.size() > 3 && _alglib.substr(_alglib.size()-3,3)==".py")
99     {
100       //if alglib extension is .py try to import the corresponding python module
101       PyGILState_STATE gstate=PyGILState_Ensure();
102
103       PyObject* mainmod = PyImport_AddModule("__main__");
104       PyObject* globals = PyModule_GetDict(mainmod);
105
106       std::string pyscript;
107       pyscript="import sys\n"
108                "import SALOMERuntime\n"
109                "filename='";
110       pyscript=pyscript+_alglib+"'\nentry='"+_symbol+"'\n";
111       pyscript=pyscript+"import os\n"
112                         "import pilot\n"
113                         "rep,mod=os.path.split(os.path.splitext(filename)[0])\n"
114                         "if rep != '':\n"
115                         "  sys.path.insert(0,rep)\n"
116                         "algomodule=__import__(mod)\n"
117                         "if rep != '':\n"
118                         "  del sys.path[0]\n"
119                         "algoclass= getattr(algomodule,entry)\n"
120                         "algo= algoclass()\n"
121                         "swigalgo= algo.this\n"
122                         "\n";
123
124       PyObject* res=PyRun_String(pyscript.c_str(), Py_file_input, globals, globals );
125
126       if(res == NULL)
127         {
128           //error during import
129           _errorDetails="";
130           PyObject* new_stderr = newPyStdOut(_errorDetails);
131           PySys_SetObject((char*)"stderr", new_stderr);
132           PyErr_Print();
133           PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
134           Py_DECREF(new_stderr);
135           modified();
136           PyGILState_Release(gstate);
137           throw YACS::Exception(_errorDetails);
138         }
139       else
140         {
141           Py_DECREF(res);
142
143           typedef struct {
144               PyObject_HEAD
145               void *ptr;
146               void *ty;
147               int own;
148               PyObject *next;
149           } SwigPyObject;
150
151           PyObject * _pyAlgo = PyDict_GetItemString(globals, "algo");
152           Py_XINCREF(_pyAlgo);
153           SwigPyObject* pyalgo = (SwigPyObject*)PyDict_GetItemString(globals, "swigalgo");
154           _alg=(OptimizerAlgBase*)pyalgo->ptr;
155           _alg->setPool(&_myPool);
156         }
157       PyGILState_Release(gstate);
158     }
159   else
160     {
161       //else try to load a dynamic library
162       OptimizerLoop::loadAlgorithm();
163     }
164 }