From 2c083fcba53b4e91d8e2da645904d7f7904b151e Mon Sep 17 00:00:00 2001 From: Ovidiu Mircescu Date: Mon, 13 Jan 2020 15:02:53 +0100 Subject: [PATCH] Use pyobj type in optimizer loop. --- src/engine/Any.cxx | 40 +++++------ src/engine/Any.hxx | 3 + src/engine/OptimizerLoop.cxx | 2 +- src/engine/TypeCode.cxx | 8 +-- src/engine_swig/pilot.i | 1 + src/runtime/TypeConversions.cxx | 6 +- src/runtime_swig/SALOMERuntime.i | 10 +++ src/yacsloader/Test/CMakeLists.txt | 4 +- src/yacsloader/Test/YacsLoaderTest.cxx | 6 ++ src/yacsloader/Test/sync_plugin_pyobj.py | 76 ++++++++++++++++++++ src/yacsloader/samples/optimizer_pyobj.xml | 84 ++++++++++++++++++++++ 11 files changed, 208 insertions(+), 32 deletions(-) create mode 100644 src/yacsloader/Test/sync_plugin_pyobj.py create mode 100644 src/yacsloader/samples/optimizer_pyobj.xml diff --git a/src/engine/Any.cxx b/src/engine/Any.cxx index c4a8e09fc..c796d9ffd 100644 --- a/src/engine/Any.cxx +++ b/src/engine/Any.cxx @@ -280,9 +280,14 @@ AtomAny::AtomAny(const std::string& val):Any(Runtime::_tc_string) _value._s=new StringOnHeap(val); } +AtomAny::AtomAny(const std::string& val, TypeCode* type):Any(type) +{ + _value._s=new StringOnHeap(val); +} + AtomAny::AtomAny(const AtomAny& other):Any(other) { - if(_type->isA(Runtime::_tc_string)) + if(_type->isA(Runtime::_tc_string) || _type->kind()==YACS::ENGINE::Objref) { StringOnHeap *cpy=(other._value._s)->deepCopy(); memcpy(&_value._s,&cpy,_type->getSizeInByteOfAnyReprInSeq()); @@ -302,7 +307,7 @@ AtomAny::AtomAny(char *val, Deallocator deAlloc):Any(Runtime::_tc_string) AtomAny::AtomAny(char *data, TypeCode* type):Any(type) { - if(type->isA(Runtime::_tc_string)) + if(type->isA(Runtime::_tc_string) || _type->kind()==YACS::ENGINE::Objref) { void **tmp=(void **)data; StringOnHeap *cpy=((StringOnHeap *)(*tmp))->deepCopy(); @@ -326,6 +331,11 @@ AtomAny *AtomAny::New(char *val,Deallocator dealloc) return new AtomAny(val,dealloc); } +AtomAny *AtomAny::New(const std::string& val, TypeCode *type) +{ + return new AtomAny(val,type); +} + AnyPtr AtomAny::operator[](int i) const throw(YACS::Exception) { throw InvalidExtractionException(_type->kind(),Sequence); @@ -347,7 +357,7 @@ bool AtomAny::operator ==(const Any& other) const return _value._i==otherC._value._i; else if(_type->isA(Runtime::_tc_bool)) return _value._b==otherC._value._b; - else if(_type->isA(Runtime::_tc_string)) + else if(_type->isA(Runtime::_tc_string) || _type->kind()==Objref) return (*_value._s)==*(otherC._value._s); else return false; @@ -379,7 +389,7 @@ double AtomAny::getDoubleValue() const throw(YACS::Exception) std::string AtomAny::getStringValue() const throw(YACS::Exception) { - if(_type->isA(Runtime::_tc_string)) + if(_type->isA(Runtime::_tc_string) || _type->kind()==YACS::ENGINE::Objref) { std::size_t sz(_value._s->size()); if(sz==0) @@ -393,7 +403,7 @@ std::string AtomAny::getStringValue() const throw(YACS::Exception) const char *AtomAny::getBytesValue(std::size_t& len) const { - if(_type->isA(Runtime::_tc_string)) + if(_type->isA(Runtime::_tc_string) || _type->kind()==YACS::ENGINE::Objref) { len=_value._s->size(); return _value._s->cStr(); @@ -411,7 +421,7 @@ const char *AtomAny::getBytesValue(std::size_t& len) const */ void AtomAny::putMyReprAtPlace(char *data) const { - if(_type->isA(Runtime::_tc_string)) + if(_type->isA(Runtime::_tc_string) || _type->kind()==YACS::ENGINE::Objref) { StringOnHeap *tmp=_value._s->deepCopy(); memcpy(data,&tmp,_type->getSizeInByteOfAnyReprInSeq()); @@ -437,7 +447,7 @@ void AtomAny::putMyReprAtPlace(char *data) const */ void AtomAny::putReprAtPlace(char *data, const char *src, const TypeCode *type, bool deepCpy) { - if(type->isA(Runtime::_tc_string)) + if(type->isA(Runtime::_tc_string) || type->kind()==YACS::ENGINE::Objref) { void **tmp1=(void **)src; StringOnHeap *tmp=((const StringOnHeap *)(*tmp1))->deepCopy(); @@ -458,7 +468,7 @@ void AtomAny::putReprAtPlace(char *data, const char *src, const TypeCode *type, void AtomAny::destroyReprAtPlace(char *data, const TypeCode *type) { DynType typ=type->kind(); - if(typ==String) + if(typ==String || typ==Objref) { if(!Any::IsNull(data)) { @@ -483,7 +493,7 @@ bool AtomAny::takeInChargeStorageOf(TypeCode *type) AtomAny::~AtomAny() { - if(_type->kind() == String) + if(_type->kind() == String || _type->kind()==Objref) delete _value._s; } @@ -759,23 +769,11 @@ SequenceAny *SequenceAny::removeUnsetItemsFromThis() const SequenceAny *SequenceAny::New(const TypeCode *typeOfContent) { - if(typeOfContent->kind() == Objref) - { - //In case of Objref, use a sequence of string - return new SequenceAny(Runtime::_tc_string); - } - else return new SequenceAny(typeOfContent); } SequenceAny *SequenceAny::New(const TypeCode *typeOfContent, unsigned lgth) { - if(typeOfContent->kind() == Objref) - { - //In case of Objref, use a sequence of string - return new SequenceAny(Runtime::_tc_string,lgth); - } - else return new SequenceAny(typeOfContent,lgth); } diff --git a/src/engine/Any.hxx b/src/engine/Any.hxx index 05a9ba544..f8d1e672f 100644 --- a/src/engine/Any.hxx +++ b/src/engine/Any.hxx @@ -111,6 +111,7 @@ namespace YACS class YACSLIBENGINE_EXPORT AtomAny : public Any { friend class TypeCode; + friend class TypeCodeObjref; union ValueContainer { @@ -124,6 +125,7 @@ namespace YACS template static AtomAny *New(T val) { return new AtomAny(val); } static AtomAny *New(char *val, Deallocator dealloc); + static AtomAny *New(const std::string& val, TypeCode *type); AnyPtr operator[](int i) const throw(Exception); AnyPtr operator[](const char *key) const throw(Exception); bool operator ==(const Any& other) const; @@ -145,6 +147,7 @@ namespace YACS AtomAny(double val); AtomAny(const char *val); AtomAny(const std::string& val); + AtomAny(const std::string& val, TypeCode* type); AtomAny(const AtomAny& other); AtomAny(char *data, TypeCode* type); AtomAny(char *val, Deallocator deAlloc); diff --git a/src/engine/OptimizerLoop.cxx b/src/engine/OptimizerLoop.cxx index bcad53a63..1b9cb794b 100644 --- a/src/engine/OptimizerLoop.cxx +++ b/src/engine/OptimizerLoop.cxx @@ -422,8 +422,8 @@ YACS::Event OptimizerLoop::finalize() (*iter)->setState(YACS::DONE); } } - _alg->finishProxy(); _algoResultPort.put(_alg->getAlgoResultProxy()); + _alg->finishProxy(); if (_finalizeNode == NULL) { // No finalize node, we just finish OptimizerLoop at the end of exec nodes execution diff --git a/src/engine/TypeCode.cxx b/src/engine/TypeCode.cxx index 146f9a5b7..670115aeb 100644 --- a/src/engine/TypeCode.cxx +++ b/src/engine/TypeCode.cxx @@ -71,13 +71,11 @@ AnyPtr TypeCode::getOrBuildAnyFromZippedData(char *data) const const char * TypeCode::name() const throw(YACS::Exception) { - //throw Exception("No name"); return id(); } const char * TypeCode::shortName() const { - //throw Exception("No shortName"); return id(); } @@ -313,17 +311,17 @@ TypeCode *TypeCodeObjref::clone() const void TypeCodeObjref::putReprAtPlace(char *pt, const char *val, bool deepCpy) const { - throw Exception("Not implemented yet : YACS::Any for objs ref"); + AtomAny::putReprAtPlace(pt,val,this,deepCpy); } void TypeCodeObjref::destroyZippedAny(char *data) const { - throw Exception("Not implemented yet : YACS::Any for objs ref"); + AtomAny::destroyReprAtPlace(data,this); } AnyPtr TypeCodeObjref::getOrBuildAnyFromZippedData(char *data) const { - throw Exception("Not implemented yet : YACS::Any for objs ref"); + return AtomAny::getOrBuildFromData(data,this); } const char * TypeCodeObjref::id() const throw(YACS::Exception) diff --git a/src/engine_swig/pilot.i b/src/engine_swig/pilot.i index 9a4c6b805..4d5ef4833 100644 --- a/src/engine_swig/pilot.i +++ b/src/engine_swig/pilot.i @@ -244,6 +244,7 @@ EXCEPTION(YACS::ENGINE::ExecutorSwig::waitPause) %include +%feature("unref") YACS::ENGINE::Any "$this->decrRef();" %include %ignore YACS::ENGINE::TypeCode::getOrBuildAnyFromZippedData; diff --git a/src/runtime/TypeConversions.cxx b/src/runtime/TypeConversions.cxx index 2c76e0e7a..f75e20abf 100644 --- a/src/runtime/TypeConversions.cxx +++ b/src/runtime/TypeConversions.cxx @@ -1616,7 +1616,7 @@ namespace YACS { static inline std::string convert(const TypeCode *t,YACS::ENGINE::Any* o,void*,int protocol) { - if(o->getType()->kind()==String) + if(o->getType()->kind()==String || o->getType()->kind()==Objref) return o->getStringValue(); stringstream msg; msg << "Problem in conversion: a objref(string) is expected " ; @@ -1702,7 +1702,7 @@ namespace YACS { //Check if objref is a GenericObj and register it if it is the case (workaround for bad management of GenericObj) if(o=="" || (t->isA(Runtime::_tc_file)) || (strncmp(t->id(),"python",6)==0) || (strncmp(t->id(),"json",4)==0)) - return YACS::ENGINE::AtomAny::New(o); + return YACS::ENGINE::AtomAny::New(o, const_cast(t)); //Objref CORBA. prefix=IOR,corbaname,corbaloc CORBA::Object_var obref; @@ -1736,7 +1736,7 @@ namespace YACS else DEBTRACE("It's a CORBA::Object but not a SALOME::GenericObj"); - return YACS::ENGINE::AtomAny::New(o); + return YACS::ENGINE::AtomAny::New(o, const_cast(t)); } }; diff --git a/src/runtime_swig/SALOMERuntime.i b/src/runtime_swig/SALOMERuntime.i index ad88619c8..0b8091f6c 100644 --- a/src/runtime_swig/SALOMERuntime.i +++ b/src/runtime_swig/SALOMERuntime.i @@ -66,6 +66,7 @@ #include "PyStdout.hxx" #include "ExecutorSwig.hxx" #include +#include "Catalog.hxx" %} // ---------------------------------------------------------------------------- @@ -227,8 +228,11 @@ namespace YACS // becomes a real derived class, this will have to be changed. %rename(OptimizerAlgSync) YACS::ENGINE::PyOptimizerAlgBase; %rename(OptimizerAlgASync) YACS::ENGINE::PyOptimizerAlgASync; + %include "PyOptimizerAlg.hxx" +%newobject YACS::ENGINE::RuntimeSALOME::createAnyPyObject; + %extend YACS::ENGINE::RuntimeSALOME { PyObject *createContainer(const std::string& kind="") @@ -236,4 +240,10 @@ namespace YACS YACS::ENGINE::Container *ret(self->createContainer(kind)); return convertContainer2(ret,SWIG_POINTER_OWN | 0); } + + Any* createAnyPyObject(PyObject * pyobj) + { + return convertPyObjectNeutral(self->getBuiltinCatalog()->_typeMap["pyobj"], + pyobj); + } } diff --git a/src/yacsloader/Test/CMakeLists.txt b/src/yacsloader/Test/CMakeLists.txt index 80cafabe8..b6a1b61cc 100644 --- a/src/yacsloader/Test/CMakeLists.txt +++ b/src/yacsloader/Test/CMakeLists.txt @@ -120,6 +120,8 @@ IF(NOT WIN32) SET(LOCAL_TEST_FILES algoasyncexample.py algosyncexample.py + sync_plugin_pyobj.py + optim_plugin.py genPascal.py genTriangle.py echoclt.py) @@ -132,8 +134,6 @@ IF(NOT WIN32) INSTALL(FILES CTestTestfileInstall.cmake DESTINATION ${LOCAL_TEST_DIR} RENAME CTestTestfile.cmake) - INSTALL(FILES optim_plugin.py - DESTINATION ${LOCAL_TEST_DIR}) INSTALL(PROGRAMS runYacsLoaderTest.sh ${CMAKE_CURRENT_BINARY_DIR}/xmlrun.sh DESTINATION ${LOCAL_TEST_DIR}) # Use relative path for symbolic links in order to allow the copy of the directory. diff --git a/src/yacsloader/Test/YacsLoaderTest.cxx b/src/yacsloader/Test/YacsLoaderTest.cxx index 8bc41779a..83a5413a5 100644 --- a/src/yacsloader/Test/YacsLoaderTest.cxx +++ b/src/yacsloader/Test/YacsLoaderTest.cxx @@ -847,6 +847,12 @@ void YacsLoaderTest::optimizers() CPPUNIT_ASSERT(ret == 0); CPPUNIT_ASSERT(p->getEffectiveState() == YACS::DONE ); delete p; + + ret = driverTest(p, "samples/optimizer_pyobj.xml"); + CPPUNIT_ASSERT(ret == 0); + CPPUNIT_ASSERT(p->getEffectiveState() == YACS::DONE ); + delete p; + } void YacsLoaderTest::pyremotes() diff --git a/src/yacsloader/Test/sync_plugin_pyobj.py b/src/yacsloader/Test/sync_plugin_pyobj.py new file mode 100644 index 000000000..bb2c31a9e --- /dev/null +++ b/src/yacsloader/Test/sync_plugin_pyobj.py @@ -0,0 +1,76 @@ +import SALOMERuntime +import pickle + +class myalgosync(SALOMERuntime.OptimizerAlgSync): + def __init__(self): + SALOMERuntime.OptimizerAlgSync.__init__(self, None) + r=SALOMERuntime.getSALOMERuntime() + self.tin=r.getTypeCode("pyobj") + self.tout=r.getTypeCode("pyobj") + self.tAlgoInit=r.getTypeCode("pyobj") + self.tAlgoResult=r.getTypeCode("pyobj") + + def setPool(self,pool): + """Must be implemented to set the pool""" + self.pool=pool + + def getTCForIn(self): + """return typecode of type expected as Input of the internal node """ + return self.tin + + def getTCForOut(self): + """return typecode of type expected as Output of the internal node""" + return self.tout + + def getTCForAlgoInit(self): + """return typecode of type expected as input for initialize """ + return self.tAlgoInit + + def getTCForAlgoResult(self): + """return typecode of type expected as output of the algorithm """ + return self.tAlgoResult + + def initialize(self,input): + """Optional method called on initialization. + The type of "input" is returned by "getTCForAlgoInit" + """ + self.data=input.getPyObj() + self.result = 0 + + def start(self): + """Start to fill the pool with samples to evaluate.""" + r=SALOMERuntime.getSALOMERuntime() + self.iter=0 + for i in self.data: + # "range" is for a python object which is not of basic type + self.pool.pushInSample(self.iter, r.createAnyPyObject(range(i))) + self.iter=self.iter+1 + + def takeDecision(self): + """ This method is called each time a sample has been evaluated. It can + either add new samples to evaluate in the pool, do nothing (wait for + more samples), or empty the pool to finish the evaluation. + """ + currentId=self.pool.getCurrentId() + in_value = self.pool.getCurrentInSample().getPyObj() + result = self.pool.getCurrentOutSample().getPyObj() + self.result = self.result + len(result) + + def finish(self): + """Optional method called when the algorithm has finished, successfully + or not, to perform any necessary clean up.""" + self.pool.destroyAll() + self.result = 0 # the result object is destroyed + + def getAlgoResult(self): + """return the result of the algorithm. + The object returned is of type indicated by getTCForAlgoResult. + """ + r=SALOMERuntime.getSALOMERuntime() + # Force the creation of a python object into the result port. + # If a basic python type is used, it will be converted to a basic c++ type + # (int, double, std::string) and this is not what the result port expects as + # it is declared of type pyobj. + self.result = r.createAnyPyObject(self.result) + # do not return a local variable created with "createAnyPyObject" (crash) + return self.result diff --git a/src/yacsloader/samples/optimizer_pyobj.xml b/src/yacsloader/samples/optimizer_pyobj.xml new file mode 100644 index 000000000..1123c546e --- /dev/null +++ b/src/yacsloader/samples/optimizer_pyobj.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OptimizerLoop0 PyScript1 + PyScript4 OptimizerLoop0 + + OptimizerLoop0 algoResults + PyScript1 i + + + OptimizerLoop0 evalSamples + OptimizerLoop0.PyScript1 i2 + + + PyScript4 o5 + OptimizerLoop0 algoInit + + + OptimizerLoop0.PyScript1 o3 + OptimizerLoop0 evalResults + + + OptimizerLoop0nbBranches + 1 + + + + + + + -- 2.30.2