Salome HOME
Use pyobj type in optimizer loop.
authorOvidiu Mircescu <ovidiu.mircescu@edf.fr>
Mon, 13 Jan 2020 14:02:53 +0000 (15:02 +0100)
committerOvidiu Mircescu <ovidiu.mircescu@edf.fr>
Tue, 14 Jan 2020 10:24:01 +0000 (11:24 +0100)
src/engine/Any.cxx
src/engine/Any.hxx
src/engine/OptimizerLoop.cxx
src/engine/TypeCode.cxx
src/engine_swig/pilot.i
src/runtime/TypeConversions.cxx
src/runtime_swig/SALOMERuntime.i
src/yacsloader/Test/CMakeLists.txt
src/yacsloader/Test/YacsLoaderTest.cxx
src/yacsloader/Test/sync_plugin_pyobj.py [new file with mode: 0644]
src/yacsloader/samples/optimizer_pyobj.xml [new file with mode: 0644]

index c4a8e09fc87d88aee0a122127fe3a3617416981e..c796d9ffd796f5dde003a56ffaf95026eb7c9fee 100644 (file)
@@ -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);
 }
 
index 05a9ba54427cfe818185720c669999b6846927f4..f8d1e672fa6233d6b5b61e69aac1e5df0bae5ba2 100644 (file)
@@ -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<class T>
       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);
index bcad53a63cb8d3ff64192bb9ab1d281169a2cf12..1b9cb794b70cc09b895475d10c3863b8498dffef 100644 (file)
@@ -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
index 146f9a5b7243e2a65008b76020d7cd55a1a1d773..670115aeb241c1084482ecd8070b490b625a9b3d 100644 (file)
@@ -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)
index 9a4c6b805f63bc9b5dbdc1756abf9acf84db9320..4d5ef483353036d58b9def0905c138171aa2514b 100644 (file)
@@ -244,6 +244,7 @@ EXCEPTION(YACS::ENGINE::ExecutorSwig::waitPause)
 
 %include <RefCounter.hxx>
 
+%feature("unref") YACS::ENGINE::Any "$this->decrRef();"
 %include <Any.hxx>
 
 %ignore YACS::ENGINE::TypeCode::getOrBuildAnyFromZippedData;
index 2c76e0e7acbbef49b4f1a527193efe24df734a81..f75e20abf45c4bb71a8e53241a6e760b8cdf2510 100644 (file)
@@ -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<TypeCode *>(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<TypeCode *>(t));
         }
     };
 
index ad88619c8d57a56d2b424fe8880f9df96c3bf223..0b8091f6cf622f2decec4d7660898de7fec193a5 100644 (file)
@@ -66,6 +66,7 @@
 #include "PyStdout.hxx"
 #include "ExecutorSwig.hxx"
 #include <sstream>
+#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);
+  }
 }
index 80cafabe896a7dc02aabeec475a986f1c353a5b6..b6a1b61cc6435bdcd291dc9ac8060e3a7c657f22 100644 (file)
@@ -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.
index 8bc41779a484ef58900ac119db42e9285b8f105b..83a5413a5baa3c418e866f3928cf86157433b7c6 100644 (file)
@@ -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 (file)
index 0000000..bb2c31a
--- /dev/null
@@ -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 (file)
index 0000000..1123c54
--- /dev/null
@@ -0,0 +1,84 @@
+<?xml version='1.0' encoding='iso-8859-1' ?>
+<proc name="newSchema_1">
+   <type name="string" kind="string"/>
+   <struct name="Engines/dataref">
+      <member name="ref" type="string"/>
+   </struct>
+   <type name="bool" kind="bool"/>
+   <sequence name="boolvec" content="bool"/>
+   <type name="double" kind="double"/>
+   <sequence name="dblevec" content="double"/>
+   <objref name="file" id="file"/>
+   <type name="int" kind="int"/>
+   <sequence name="intvec" content="int"/>
+   <struct name="stringpair">
+      <member name="name" type="string"/>
+      <member name="value" type="string"/>
+   </struct>
+   <sequence name="propvec" content="stringpair"/>
+   <objref name="pyobj" id="python:obj:1.0"/>
+   <sequence name="seqboolvec" content="boolvec"/>
+   <sequence name="seqdblevec" content="dblevec"/>
+   <sequence name="seqintvec" content="intvec"/>
+   <sequence name="seqpyobj" content="pyobj"/>
+   <sequence name="stringvec" content="string"/>
+   <sequence name="seqstringvec" content="stringvec"/>
+   <container name="DefaultContainer">
+      <property name="container_kind" value="Salome"/>
+      <property name="attached_on_cloning" value="0"/>
+      <property name="container_name" value="FactoryServer"/>
+      <property name="name" value="localhost"/>
+   </container>
+   <container name="container0">
+      <property name="container_kind" value="Salome"/>
+      <property name="attached_on_cloning" value="0"/>
+   </container>
+   <optimizer name="OptimizerLoop0" nbranch="1" loopWeight="-1" lib="sync_plugin_pyobj.py" entry="myalgosync">
+      <remote name="PyScript1" elementaryWeight="-1">
+         <script><code><![CDATA[o3=list(range(len(i2)))
+]]></code></script>
+         <load container="container0"/>
+         <inport name="i2" type="pyobj"/>
+         <outport name="o3" type="pyobj"/>
+      </remote>
+   </optimizer>
+   <inline name="PyScript4">
+      <script><code><![CDATA[o5=range(10)
+]]></code></script>
+      <outport name="o5" type="pyobj"/>
+   </inline>
+   <inline name="PyScript1">
+      <script><code><![CDATA[r = i
+]]></code></script>
+      <load container="DefaultContainer"/>
+      <inport name="i" type="pyobj"/>
+      <outport name="r" type="int"/>
+   </inline>
+   <control> <fromnode>OptimizerLoop0</fromnode> <tonode>PyScript1</tonode> </control>
+   <control> <fromnode>PyScript4</fromnode> <tonode>OptimizerLoop0</tonode> </control>
+   <datalink control="false">
+      <fromnode>OptimizerLoop0</fromnode> <fromport>algoResults</fromport>
+      <tonode>PyScript1</tonode> <toport>i</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>OptimizerLoop0</fromnode> <fromport>evalSamples</fromport>
+      <tonode>OptimizerLoop0.PyScript1</tonode> <toport>i2</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>PyScript4</fromnode> <fromport>o5</fromport>
+      <tonode>OptimizerLoop0</tonode> <toport>algoInit</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>OptimizerLoop0.PyScript1</fromnode> <fromport>o3</fromport>
+      <tonode>OptimizerLoop0</tonode> <toport>evalResults</toport>
+   </datalink>
+   <parameter>
+      <tonode>OptimizerLoop0</tonode><toport>nbBranches</toport>
+      <value><int>1</int></value>
+   </parameter>
+   <presentation name="OptimizerLoop0" x="272.5" y="32" width="167" height="202" expanded="1" expx="272.5" expy="32" expWidth="167" expHeight="202" shownState="0"/>
+   <presentation name="PyScript1" x="472" y="32" width="158" height="63" expanded="1" expx="472" expy="32" expWidth="158" expHeight="63" shownState="0"/>
+   <presentation name="PyScript4" x="4" y="58" width="158" height="63" expanded="1" expx="4" expy="58" expWidth="158" expHeight="63" shownState="0"/>
+   <presentation name="OptimizerLoop0.PyScript1" x="5" y="135" width="158" height="63" expanded="1" expx="5" expy="135" expWidth="158" expHeight="63" shownState="0"/>
+   <presentation name="__ROOT__" x="0" y="0" width="634" height="238" expanded="1" expx="0" expy="0" expWidth="634" expHeight="238" shownState="0"/>
+</proc>