Version: 9.15.0
OptimizerLoop.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2025 CEA, EDF
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 "OptimizerLoop.hxx"
21 #include "OutputPort.hxx"
22 #include "Visitor.hxx"
23 
24 #include <iostream>
25 
26 //#define _DEVDEBUG_
27 #include "YacsTrace.hxx"
28 
29 using namespace YACS::ENGINE;
30 using namespace std;
31 
32 const char FakeNodeForOptimizerLoop::NAME[]="thisIsAFakeNode";
33 
34 const int OptimizerLoop::NOT_RUNNING_BRANCH_ID=-1973012217;
36 
37 const char OptimizerLoop::NAME_OF_ALGO_INIT_PORT[] = "algoInit";
38 const char OptimizerLoop::NAME_OF_OUT_POOL_INPUT[] = "evalResults";
39 const char OptimizerLoop::NAME_OF_ALGO_RESULT_PORT[] = "algoResults";
40 
41 
42 FakeNodeForOptimizerLoop::FakeNodeForOptimizerLoop(OptimizerLoop *loop, bool normal, std::string message)
43  : ElementaryNode(NAME), _loop(loop), _normal(normal), _message(message)
44 {
47 }
48 
50  : ElementaryNode(other), _loop(0), _normal(other._normal), _message(other._message)
51 {
52 }
53 
54 Node *FakeNodeForOptimizerLoop::simpleClone(ComposedNode *father, bool editionOnly) const
55 {
56  return new FakeNodeForOptimizerLoop(*this);
57 }
58 
60 {
62 }
63 
65 {
67 }
68 
70 {
71  DEBTRACE("FakeNodeForOptimizerLoop::execute: " << _message)
72  if (!_normal) {
74  throw Exception(_message);
75  }
76  else
77  {
79  }
80 }
81 
83 {
85 }
86 
88 {
90 }
91 
98 OptimizerLoop::OptimizerLoop(const std::string& name, const std::string& algLibWthOutExt,
99  const std::string& symbolNameToOptimizerAlgBaseInstanceFactory,
100  bool algInitOnFile,bool initAlgo, Proc * procForTypes):
101  DynParaLoop(name,Runtime::_tc_string,std::unique_ptr<NbBranchesAbstract>(new NbBranches(this))),_algInitOnFile(algInitOnFile),_alglib(algLibWthOutExt),
102  _algoInitPort(NAME_OF_ALGO_INIT_PORT, this, Runtime::_tc_string, true),
103  _loader(NULL),_alg(0),_convergenceReachedWithOtherCalc(false),
104  _retPortForOutPool(NAME_OF_OUT_POOL_INPUT,this,Runtime::_tc_string),
105  _nodeForSpecialCases(0), _algoResultPort(NAME_OF_ALGO_RESULT_PORT, this, Runtime::_tc_string)
106 {
107  //We need this because calling a virtual method in a constructor does not call the most derived method but the method of the class
108  //A derived class must take care to manage that
109  if(initAlgo)
110  setAlgorithm(algLibWthOutExt,symbolNameToOptimizerAlgBaseInstanceFactory, procForTypes);
111 }
112 
113 OptimizerLoop::OptimizerLoop(const OptimizerLoop& other, ComposedNode *father, bool editionOnly):
114  DynParaLoop(other,father,editionOnly),_algInitOnFile(other._algInitOnFile),_alglib(other._alglib),
115  _convergenceReachedWithOtherCalc(false),_loader(NULL),_alg(0),_algoInitPort(other._algoInitPort,this),
116  _retPortForOutPool(other._retPortForOutPool,this),_nodeForSpecialCases(0),
117  _algoResultPort(other._algoResultPort, this)
118 {
119  //Don't call setAlgorithm here because it will be called several times if the class is derived. Call it in simpleClone for cloning
120 
121  // Create the links to evalResults port
122  set<OutPort *> fromPortsToReproduce=other._retPortForOutPool.edSetOutPort();
123  for(set<OutPort *>::iterator iter=fromPortsToReproduce.begin();iter!=fromPortsToReproduce.end();iter++)
125 }
126 
128 {
129  if(_alg)
130  _alg->decrRef();
131  cleanDynGraph();
133  delete _loader;
134  delete _nodeForSpecialCases;
135 }
136 
137 Node *OptimizerLoop::simpleClone(ComposedNode *father, bool editionOnly) const
138 {
139  OptimizerLoop* ol=new OptimizerLoop(*this,father,editionOnly);
140  // TODO: Remove this const_cast (find a better design to get the type codes from the original node)
141  Proc * procForTypes = ol->getProc();
142  if (procForTypes == NULL) {
143  const Proc * origProc = getProc();
144  procForTypes = const_cast<Proc *>(origProc);
145  }
146  ol->setAlgorithm(_alglib, _symbol, false, procForTypes);
147  return ol;
148 }
149 
150 void OptimizerLoop::init(bool start)
151 {
152  DynParaLoop::init(start);
153  _algoInitPort.exInit(start);
154  _retPortForOutPool.exInit(start);
157  cleanDynGraph();
159 }
160 
162 {
163  if(_state == YACS::DISABLED)
164  return;
165  delete _nodeForSpecialCases;
166  _nodeForSpecialCases = NULL;
167  try
168  {
169  if(_inGate.exIsReady())
170  {
172  // Force termination in case the previous algorithm did not finish properly (manual stop)
173  _alg->finishProxy();
175 
176  // Initialize and launch the algorithm
178  if (_alg->hasError()) {
179  string error = _alg->getError();
180  _alg->finishProxy();
181  throw Exception(error);
182  }
183 
184  //internal graph update
185  int i;
186  int nbOfBr=_nbOfBranches->getIntValue();
187  _alg->setNbOfBranches(nbOfBr);
188 
189  _alg->startProxy();
190  if (_alg->hasError()) {
191  string error = _alg->getError();
192  _alg->finishProxy();
193  throw Exception(error);
194  }
195 
196  if(nbOfBr==0)
197  {
198  // A number of branches of 0 is acceptable if there are no output ports
199  // leaving OptimizerLoop
200  bool normal = getAllOutPortsLeavingCurrentScope().empty();
202  "OptimizerLoop has no branch to run the internal node(s)");
203  return;
204  }
205  _execNodes.resize(nbOfBr);
206  _execIds.resize(nbOfBr);
207  if(_initNode)
208  {
209  _execInitNodes.resize(nbOfBr);
210  _initNodeUpdated.resize(nbOfBr);
211  for(i=0;i<nbOfBr;i++)
212  _initNodeUpdated[i]=false;
213  }
215  if (_finalizeNode)
216  _execFinalizeNodes.resize(nbOfBr);
217  vector<Node *> origNodes;
218  origNodes.push_back(_initNode);
219  origNodes.push_back(_node);
220  origNodes.push_back(_finalizeNode);
221  for(i=0;i<nbOfBr;i++)
222  {
224  vector<Node *> clonedNodes = cloneAndPlaceNodesCoherently(origNodes);
225  if(_initNode)
226  _execInitNodes[i] = clonedNodes[0];
227  _execNodes[i] = clonedNodes[1];
228  if(_finalizeNode)
229  _execFinalizeNodes[i] = clonedNodes[2];
231  }
232  initInterceptors(nbOfBr);
233  int id;
234  unsigned char priority;
235  Any *val=_myPool.getNextSampleWithHighestPriority(id,priority);
236  if(!val)
237  {
238  // It is acceptable to have no sample to launch if there are no output ports
239  // leaving OptimizerLoop
240  std::set<OutPort *> setOutPort = getAllOutPortsLeavingCurrentScope();
241  // Special in the special
242  // We do not check algoResult
243  setOutPort.erase(&_algoResultPort);
244  bool normal = setOutPort.empty();
246  string("The algorithm of OptimizerLoop with name ") + _name +
247  " returns no sample to launch");
248  _alg->finishProxy();
249  return;
250  }
251  launchMaxOfSamples(true);
252  }
253  }
254  catch (const exception & e)
255  {
257  string("An error happened in the control algorithm of OptimizerLoop \"") + _name +
258  "\": " + e.what());
259  }
260 }
261 
263 {
265 }
266 
267 InputPort *OptimizerLoop::getInputPort(const std::string& name) const
268 {
269  if (name == NAME_OF_ALGO_INIT_PORT)
270  return (InputPort *)&_algoInitPort;
271  else if (name == NAME_OF_OUT_POOL_INPUT)
272  return (InputPort *)&_retPortForOutPool;
273  else
274  return DynParaLoop::getInputPort(name);
275 }
276 
277 std::list<InputPort *> OptimizerLoop::getSetOfInputPort() const
278 {
279  list<InputPort *> ret=DynParaLoop::getSetOfInputPort();
280  ret.push_back((InputPort *)&_algoInitPort);
281  ret.push_back((InputPort *)&_retPortForOutPool);
282  return ret;
283 }
284 
285 std::list<InputPort *> OptimizerLoop::getLocalInputPorts() const
286 {
287  list<InputPort *> ret=DynParaLoop::getLocalInputPorts();
288  ret.push_back((InputPort *)&_algoInitPort);
289  ret.push_back((InputPort *)&_retPortForOutPool);
290  return ret;
291 }
292 
293 void OptimizerLoop::selectRunnableTasks(std::vector<Task *>& tasks)
294 {
295 }
296 
297 void OptimizerLoop::getReadyTasks(std::vector<Task *>& tasks)
298 {
299  if(!_node)
300  return;
302  {
304  {
306  return ;
307  }
308  vector<Node *>::iterator iter;
309  for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
310  (*iter)->getReadyTasks(tasks);
311  for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
312  (*iter)->getReadyTasks(tasks);
313  for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
314  (*iter)->getReadyTasks(tasks);
315  }
316 }
317 
319 {
320  if (getState() == YACS::FAILED)
321  {
322  // This happens when a valid computation on a branch finishes after an error on another branch.
323  // In this case we just ignore the new result because the algorithm has already been terminated.
324  return YACS::NOEVENT;
325  }
326  unsigned int id;
327  switch(getIdentityOfNotifyerNode(node,id))
328  {
329  case INIT_NODE:
330  {
331  _execNodes[id]->exUpdateState();
335  break;
336  }
337  case WORK_NODE:
338  {
340  { //This case happens when alg has reached its convergence whereas other calculations still compute
342  if(!isFullyLazy())
343  return YACS::NOEVENT;
344  else
345  return finalize();
346  }
350  if (_alg->hasError()) {
351  _errorDetails = string("An error happened in the control algorithm of optimizer loop: ") +
352  _alg->getError();
353  _alg->finishProxy();
355  return YACS::ABORT;
356  }
357 
359  if(_myPool.empty())
360  {
363  if(!isFullyLazy())
364  {// This case happens when the hand is returned to continue, whereas some other are working in parallel for nothing.
366  return YACS::NOEVENT;
367  }
368  return finalize();
369  }
371  int newId;
372  unsigned char priority;
373  Any *val=_myPool.getNextSampleWithHighestPriority(newId, priority);
374  if(!val)
375  {
376  bool isFinished=true;
377  for(int i=0;i<_execIds.size() && isFinished;i++)
379  if(isFinished)
380  {
381  std::cerr <<"OptimizerLoop::updateStateOnFinishedEventFrom: Alg has not inserted more cases whereas last element has been calculated !" << std::endl;
383  exForwardFailed();
384  _alg->finishProxy();
385  return YACS::FINISH;
386  }
387  return YACS::NOEVENT;
388  }
389  launchMaxOfSamples(false);
390  break;
391  }
392  case FINALIZE_NODE:
393  {
395  if (_unfinishedCounter == 0)
396  {
399  return YACS::FINISH;
400  }
401  else
402  return YACS::NOEVENT;
403  break;
404  }
405  default:
406  YASSERT(false);
407  }
408  return YACS::NOEVENT;
409 }
410 
412 {
413  //update internal node (definition node) state
414  if (_node)
415  {
417  ComposedNode* compNode = dynamic_cast<ComposedNode*>(_node);
418  if (compNode)
419  {
420  std::list<Node *> aChldn = compNode->getAllRecursiveConstituents();
421  std::list<Node *>::iterator iter=aChldn.begin();
422  for(;iter!=aChldn.end();iter++)
423  (*iter)->setState(YACS::DONE);
424  }
425  }
427  _alg->finishProxy();
428  if (_finalizeNode == NULL)
429  {
430  // No finalize node, we just finish OptimizerLoop at the end of exec nodes execution
432  return YACS::FINISH;
433  }
434  else
435  {
436  // Run the finalize nodes, the OptimizerLoop will be done only when they all finish
437  _unfinishedCounter = 0; // This counter indicates how many branches are not finished
438  for (int i=0 ; i<_nbOfBranches->getIntValue() ; i++)
440  {
441  DEBTRACE("Launching finalize node for branch " << i)
442  _execFinalizeNodes[i]->exUpdateState();
444  }
445  else
446  // There should not be any running branch at this point
448  return YACS::NOEVENT;
449  }
450 }
451 
453 
461 {
462  DEBTRACE("OptimizerLoop::updateStateOnFailedEventFrom " << node->getName());
463  _alg->setError(string("Error during the execution of YACS node ") + node->getName() +
464  ": " + node->getErrorReport());
465  _alg->finishProxy();
467  DEBTRACE("OptimizerLoop::updateStateOnFailedEventFrom: returned from error notification.");
468  return DynParaLoop::updateStateOnFailedEventFrom(node,execInst);
469 }
470 
472 {
473 }
474 
475 void OptimizerLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
476 {
477  DynParaLoop::buildDelegateOf(port,initialStart,pointsOfView);
478  if(port==&_retPortForOutPool)
479  {
480  std::string linkName("(");
481  linkName += initialStart->getName()+" to "+port->getName()+")";
482  throw Exception(std::string("Illegal OptimizerLoop link: \
483 The 'evalResults' port must be linked within the scope of the loop.")
484  + linkName);
485  }
486 }
487 
488 void OptimizerLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
489 {
490  DynParaLoop::buildDelegateOf(port,finalTarget,pointsOfView);
491  if(port.first != &_algoResultPort)
492  {
493  std::string linkName("(");
494  linkName += port.first->getName()+" to "+finalTarget->getName()+")";
495  throw Exception(std::string("Illegal OptimizerLoop link: \
496 Only the algorithm result port can be linked to a port outside the scope of the loop.")
497  + linkName);
498  }
499 
500  string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
501  if(typeOfPortInstance!=OutputPort::NAME)
502  throw Exception("OptimizerLoop::buildDelegateOf : not implemented for DS because not specified ");
503 }
504 
506  std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw,
507  std::vector<OutPort *>& fwCross,
508  std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
509  LinkInfo& info) const
510 {
511  if(end==&_retPortForOutPool)
512  fw[(ComposedNode *)this].push_back(start);
513  else
514  DynParaLoop::checkControlDependancy(start,end,cross,fw,fwCross,bw,info);
515 }
516 
517 void OptimizerLoop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
518 {
519  if(end==&_retPortForOutPool)
520  solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
521  else
522  DynParaLoop::checkCFLinks(starts,end,alreadyFed,direction,info);
523 }
524 
525 void OptimizerLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
526  InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd)
527 {
528  DynParaLoop::checkLinkPossibility(start, pointsOfViewStart, end, pointsOfViewEnd);
529  std::string linkName("(");
530  linkName += start->getName()+" to "+end->getName()+")";
531 
532  // Yes, it should be possible to link back the result port to any input port of the loop.
533  if(end == _nbOfBranches->getPort() || end == &_algoInitPort)
534  if(start != &_algoResultPort)
535  throw Exception(std::string("Illegal OptimizerLoop link.") + linkName);
536  else
537  return;
538 
539  if(start == &_algoResultPort)
540  throw Exception(std::string("Illegal OptimizerLoop link: \
541 The 'algoResult' port can't be linked within the scope of the loop.") + linkName);
542 
543  if(end == &_retPortForOutPool && isInMyDescendance(start->getNode())!=_node)
544  throw Exception(std::string("Illegal OptimizerLoop link: \
545 The 'evalResults' port can only be linked to the working node.") + linkName);
546 }
547 
549 {
550  // At this point all garanties taken let's clean all.
551  map<InputPort *,vector<InputPort *> >::iterator iter=_interceptors.begin();
552  for(;iter!=_interceptors.end();iter++)
553  for(vector<InputPort *>::iterator iter2=(*iter).second.begin();iter2!=(*iter).second.end();iter2++)
554  delete (*iter2);
555  _interceptors.clear();
556  for(vector<AnyInputPort *>::iterator iter3=_interceptorsForOutPool.begin();iter3!=_interceptorsForOutPool.end();iter3++)
557  delete (*iter3);
558  _interceptorsForOutPool.clear();
559 }
560 
562 {
563  int id;
564  unsigned char priority;
565  Any *val;
566  unsigned i;
567  for (val = _myPool.getNextSampleWithHighestPriority(id, priority);
568  !isFullyBusy(i) && val;
569  val = _myPool.getNextSampleWithHighestPriority(id, priority))
570  {
572  first=true; // node is not initialized (first pass)
573  else
574  first=false; // node is initialized (second pass)
575  _execIds[i]=id;
577  if(_initNode && !_initNodeUpdated[i])
578  {
579  putValueOnBranch(val,i,first);
580  _execInitNodes[i]->exUpdateState();
581  _initNodeUpdated[i]=true;
583  }
584  else
585  {
586  if(!first)
587  _execNodes[i]->init(first);
588  putValueOnBranch(val,i,first);
589  _execNodes[i]->exUpdateState();
591  }
592  }
593 }
594 
596 {
597  bool isLazy=true;
598  for(unsigned i=0;i<_execIds.size() && isLazy;i++)
600  return isLazy;
601 }
602 
607 bool OptimizerLoop::isFullyBusy(unsigned& branchId) const
608 {
609  bool isFinished=true;
610  unsigned i;
611  for(i=0;i<_execIds.size() && isFinished;i++)
613  if(!isFinished)
614  branchId=i-1;
615  return isFinished;
616 }
617 
621 void OptimizerLoop::initInterceptors(unsigned nbOfBr)
622 {
623  //For all classical outputports leaving 'this'
624  set<OutPort *> portsToIntercept=getAllOutPortsLeavingCurrentScope();
625  portsToIntercept.erase(&_algoResultPort);
626  for(set<OutPort *>::iterator iter=portsToIntercept.begin();iter!=portsToIntercept.end();iter++)
627  {
628  OutputPort *portC=(OutputPort *)(*iter);//Warrantied by OptimizerLoop::buildDelegateOf
629  const set<InputPort *>& links=portC->getSetOfPhyLinks();
630  for(set<InputPort *>::const_iterator iter2=links.begin();iter2!=links.end();iter2++)
631  {
632 #ifdef NOCOVARIANT
633  InputPort *reprCur=dynamic_cast<InputPort *>((*iter2)->getPublicRepresentant());
634 #else
635  InputPort *reprCur=(*iter2)->getPublicRepresentant();
636 #endif
637  if(!isInMyDescendance(reprCur->getNode()))
638  {//here we've got an out of scope link : Let's intercept it
639  if(_interceptors.find(reprCur)==_interceptors.end())
640  {
641  _interceptors[reprCur].resize(nbOfBr);
642  for(unsigned i=0;i<nbOfBr;i++)
643  {
645  InputPort *clone=reprCur->clone(0);
646  _interceptors[reprCur][i]=clone;
647  portExecC->edAddInputPort(clone);
648  }
649  }
650  else
651  {
652  for(unsigned i=0;i<nbOfBr;i++)
653  {
655  portExecC->edAddInputPort(_interceptors[reprCur][i]);
656  }
657  }
658  }
659  }
660  }
661  // For out pool
662  _interceptorsForOutPool.resize(nbOfBr);
663  set< OutPort * > links=_retPortForOutPool.edSetOutPort();
664  for(unsigned i=0;i<nbOfBr;i++)
666  for(set<OutPort *>::iterator iter2=links.begin();iter2!=links.end();iter2++)
667  for(unsigned j=0;j<nbOfBr;j++)
668  {
669  OutPort *portExec;
670  Node *whatType=isInMyDescendance((*iter2)->getNode());
671  if(whatType==_node)
672  {
673  portExec=_execNodes[j]->getOutPort(_node->getOutPortName(*iter2));
674  portExec->addInPort(_interceptorsForOutPool[j]);
675  }
676  else if(whatType==_initNode && whatType!=0)//This case should never happend. Useless !
677  {
678  portExec=_execInitNodes[j]->getOutPort(_node->getOutPortName(*iter2));
679  portExec->addInPort(_interceptorsForOutPool[j]);
680  }
681  }
682 }
683 
689 {
690  map<InputPort *, std::vector<InputPort *> >::iterator iter;
691  for(iter=_interceptors.begin();iter!=_interceptors.end();iter++)
692  (*iter).first->put((*iter).second[branchId]->get());
693 }
694 
696 {
697  visitor->visitOptimizerLoop(this);
698 }
699 
701 
704 void OptimizerLoop::setAlgorithm(const std::string& alglib, const std::string& symbol,
705  bool checkLinks, Proc * procForTypes)
706 {
707  if(checkLinks)
708  {
713  throw Exception("The OptimizerLoop node must be disconnected before setting the algorithm");
714  }
715 
716  _symbol = symbol;
717  _alglib = alglib;
718 
719  if (_alg) {
720  _alg->decrRef();
721  _alg = NULL;
722  }
723 
724  loadAlgorithm();
725 
726  if(_alg)
727  {
728  _alg->setProc((procForTypes == NULL) ? getProc() : procForTypes);
729 
730  // Delete the values in the input ports if they were initialized
731  _retPortForOutPool.put((Any *)NULL);
732  _algoInitPort.put((Any *)NULL);
733 
734  // Change the type of the ports
739  }
740 
741  modified();
742 }
743 
744 TypeCode * OptimizerLoop::checkTypeCode(TypeCode * tc, const char * portName)
745 {
746  if (tc == NULL) {
747  ostringstream errorMsg;
748  errorMsg << "The algorithm specified for OptimizerLoop node \"" << getName() <<
749  "\" provided an invalid type for port \"" << portName << "\"";
750  throw Exception(errorMsg.str());
751  }
752  return tc;
753 }
754 
756 
760 {
761  YASSERT(_alg == NULL)
762 
763  if (_loader != NULL) {
764  delete _loader;
765  _loader = NULL;
766  }
767  _loader = new YACS::BASES::DynLibLoader(_alglib);
768  OptimizerAlgBaseFactory algFactory = NULL;
769 
770  if (_alglib != "" && _symbol != "")
771  {
772  try
773  {
774  _errorDetails = "";
775  algFactory = (OptimizerAlgBaseFactory)_loader->getHandleOnSymbolWithName(_symbol);
776  }
777  catch (YACS::Exception& e)
778  {
779  _errorDetails = e.what();
780  modified();
781  throw;
782  }
783  }
784 
785  if (algFactory != NULL)
786  _alg = algFactory(&_myPool);
787 }
788 
790 
793 std::string OptimizerLoop::getAlgLib() const
794 {
795  return _alglib;
796 }
797 
799 
803 {
804  DEBTRACE("OptimizerLoop::checkBasicConsistency");
805  if (_alglib == "")
806  throw Exception("No library specified for the OptimizerLoop control algorithm");
807  if (_symbol == "")
808  throw Exception("No symbol specified for the OptimizerLoop control algorithm");
809  if(_alg == NULL)
810  throw YACS::Exception("Problem during library loading: "+_errorDetails);
811 
813 }
814 
816 {
818 }
819 
820 std::list<OutputPort *> OptimizerLoop::getSetOfOutputPort() const
821 {
822  list<OutputPort *> ret = DynParaLoop::getSetOfOutputPort();
823  ret.push_back((OutputPort *)&_algoResultPort);
824  return ret;
825 }
826 
827 std::list<OutputPort *> OptimizerLoop::getLocalOutputPorts() const
828 {
829  list<OutputPort *> ret = DynParaLoop::getLocalOutputPorts();
830  ret.push_front((OutputPort *)&_algoResultPort);
831  return ret;
832 }
833 
834 OutPort * OptimizerLoop::getOutPort(const std::string& name) const
835 {
836  return (name == NAME_OF_ALGO_RESULT_PORT) ? (OutPort *)&_algoResultPort :
838 }
839 
840 
841 OutputPort * OptimizerLoop::getOutputPort(const std::string& name) const
842 {
843  return (name == NAME_OF_ALGO_RESULT_PORT) ? (OutputPort *)&_algoResultPort :
845 }
#define YASSERT(val)
YASSERT macro is always defined, used like assert, but throw a YACS::Exception instead of abort.
Definition: YacsTrace.hxx:59
#define DEBTRACE(msg)
Definition: YacsTrace.hxx:31
InputPort * clone(Node *newHelder) const
virtual void put(const void *data)
: Interface for management of storage of data formated dynamically in its TypeCode....
Definition: Any.hxx:79
Base class for all composed nodes.
std::string getName() const
void solveObviousOrDelegateCFLinks(const std::list< OutPort * > &starts, InputPort *end, unsigned char &alreadyFed, bool direction, LinkInfo &info) const
virtual std::list< Node * > getAllRecursiveConstituents()
Idem getAllRecursiveNodes, but this node is NOT included.
std::set< OutPort * > getAllOutPortsLeavingCurrentScope() const
List all output ports of children nodes that are linked to out of scope input ports.
std::string getPortName(const PORT *port) const
bool edAddLink(OutPort *start, InPort *end)
Add a dataflow link between two data ports.
Node * isInMyDescendance(Node *nodeToTest) const
Returns the parent of a node that is the direct child of this node.
void edSetType(TypeCode *type)
Definition: DataPort.cxx:47
std::string getName() const
Definition: DataPort.hxx:55
Base class for dynamically (fully or semifully) built graphs.
Definition: DynParaLoop.hxx:41
InputPort * getInputPort(const std::string &name) const
Get an input port given its name.
std::list< OutputPort * > getLocalOutputPorts() const
redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
int getNumberOfInputPorts() const
virtual void checkLinkPossibility(OutPort *start, const std::list< ComposedNode * > &pointsOfViewStart, InPort *end, const std::list< ComposedNode * > &pointsOfViewEnd)
std::unique_ptr< NbBranchesAbstract > _nbOfBranches
Definition: DynParaLoop.hxx:56
std::list< OutputPort * > getSetOfOutputPort() const
std::vector< Node * > _execNodes
Definition: DynParaLoop.hxx:58
static const char NAME_OF_SPLITTED_SEQ_OUT[]
Definition: DynParaLoop.hxx:67
std::vector< Node * > cloneAndPlaceNodesCoherently(const std::vector< Node * > &origNodes)
Clone nodes and make their placement consistent with the placement of the original ones.
void buildDelegateOf(InPort *&port, OutPort *initialStart, const std::list< ComposedNode * > &pointsOfView)
OutputPort * getOutputPort(const std::string &name) const
Get an output port given its name.
OutPort * getOutPort(const std::string &name) const
std::vector< int > _execIds
Definition: DynParaLoop.hxx:54
void checkControlDependancy(OutPort *start, InPort *end, bool cross, std::map< ComposedNode *, std::list< OutPort * >, SortHierarc > &fw, std::vector< OutPort * > &fwCross, std::map< ComposedNode *, std::list< OutPort * >, SortHierarc > &bw, LinkInfo &info) const
virtual YACS::Event updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
Method used to notify the node that a child node has failed.
std::list< InputPort * > getLocalInputPorts() const
redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
void init(bool start=true)
std::vector< Node * > _execFinalizeNodes
Definition: DynParaLoop.hxx:60
int getNumberOfOutputPorts() const
void prepareInputsFromOutOfScope(int branchNb)
virtual void cleanDynGraph()
void checkCFLinks(const std::list< OutPort * > &starts, InputPort *end, unsigned char &alreadyFed, bool direction, LinkInfo &info) const
check control flow links
void putValueOnBranch(Any *val, unsigned branchId, bool first)
AnyOutputPort _splittedPort
Definition: DynParaLoop.hxx:57
std::vector< Node * > _execInitNodes
Definition: DynParaLoop.hxx:59
std::list< InputPort * > getSetOfInputPort() const
TypeOfNode getIdentityOfNotifyerNode(const Node *node, unsigned &id)
virtual void checkBasicConsistency() const
Base class for all calculation nodes.
void getReadyTasks(std::vector< Task * > &tasks)
Threaded Executor.
Definition: Executor.hxx:63
Node * simpleClone(ComposedNode *father, bool editionOnly) const
FakeNodeForOptimizerLoop(OptimizerLoop *loop, bool normal, std::string message)
bool exIsReady() const
Definition: InGate.cxx:126
virtual std::set< OutPort * > edSetOutPort() const
Returns physical backlinks NOT user backlinks.
Definition: InPort.cxx:65
virtual int edGetNumberOfLinks() const
Returns number of physical backlinks NOT number of user backlinks.
Definition: InPort.cxx:45
Base class for Input Ports.
Definition: InputPort.hxx:44
virtual void exInit(bool start)
Definition: InputPort.cxx:63
virtual InputPort * clone(Node *newHelder) const =0
virtual InputPort * getPublicRepresentant()
returns the final physical port behind 'this'.
Definition: InputPort.hxx:57
Class that deal with list of semantics links for high level analysis.
Definition: LinkInfo.hxx:83
Base class for all nodes.
Definition: Node.hxx:70
std::string _name
Definition: Node.hxx:89
virtual void exForwardFinished()
Definition: Node.cxx:386
ComposedNode * _father
Definition: Node.hxx:90
InGate _inGate
Definition: Node.hxx:86
virtual void modified()
Sets Node in modified state and its father if it exists.
Definition: Node.cxx:805
virtual std::string getOutPortName(const OutPort *) const =0
Node * clone(ComposedNode *father, bool editionOnly=true) const
This method MUST NEVER BE VIRTUAL
Definition: Node.cxx:131
ComposedNode * getFather() const
Definition: Node.hxx:127
void setState(YACS::StatesForNode theState)
Sets the given state for node.
Definition: Node.cxx:652
virtual std::string getErrorReport()
returns a string that contains an error report if the node is in error
Definition: Node.cxx:755
virtual YACS::StatesForNode getState() const
Definition: Node.hxx:118
const std::string & getName() const
Definition: Node.hxx:125
virtual void exForwardFailed()
Definition: Node.cxx:378
std::string _errorDetails
Definition: Node.hxx:93
YACS::StatesForNode _state
Definition: Node.hxx:91
virtual Proc * getProc()
Definition: Node.cxx:401
virtual TypeCode * getTCForInProxy() const
virtual TypeCode * getTCForAlgoInitProxy() const
virtual Any * getAlgoResultProxy()
virtual void setError(const std::string &message)
virtual void setProc(Proc *proc)
virtual void initializeProxy(const Any *input)
virtual TypeCode * getTCForAlgoResultProxy() const
virtual const std::string & getError() const
virtual bool hasError() const
void setNbOfBranches(int nbOfBranches)
virtual TypeCode * getTCForOutProxy() const
class to build optimization loops
void buildDelegateOf(InPort *&port, OutPort *initialStart, const std::list< ComposedNode * > &pointsOfView)
virtual std::string getAlgLib() const
Return the name of the algorithm library.
void exUpdateState()
Update the node state.
std::map< InputPort *, std::vector< InputPort * > > _interceptors
outputports interceptors leaving current scope.
InputPort * getInputPort(const std::string &name) const
Get an input port given its name.
friend class FakeNodeForOptimizerLoop
void initInterceptors(unsigned nbOfBr)
virtual void accept(Visitor *visitor)
static const char NAME_OF_OUT_POOL_INPUT[]
bool isFullyBusy(unsigned &branchId) const
OutputPort * getOutputPort(const std::string &name) const
Get an output port given its name.
std::list< OutputPort * > getLocalOutputPorts() const
redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
YACS::Event updateStateOnFinishedEventFrom(Node *node)
virtual void setAlgorithm(const std::string &alglib, const std::string &symbol, bool checkLinks=true, Proc *procForTypes=NULL)
Set the algorithm library name and factory name (symbol in library) to create the algorithm and chang...
std::list< OutputPort * > getSetOfOutputPort() const
static const int NOT_RUNNING_BRANCH_ID
void checkControlDependancy(OutPort *start, InPort *end, bool cross, std::map< ComposedNode *, std::list< OutPort * >, SortHierarc > &fw, std::vector< OutPort * > &fwCross, std::map< ComposedNode *, std::list< OutPort * >, SortHierarc > &bw, LinkInfo &info) const
FakeNodeForOptimizerLoop * _nodeForSpecialCases
static const char NAME_OF_ALGO_INIT_PORT[]
void pushValueOutOfScopeForCase(unsigned branchId)
void checkCFLinks(const std::list< OutPort * > &starts, InputPort *end, unsigned char &alreadyFed, bool direction, LinkInfo &info) const
check control flow links
Node * simpleClone(ComposedNode *father, bool editionOnly=true) const
void getReadyTasks(std::vector< Task * > &tasks)
void selectRunnableTasks(std::vector< Task * > &tasks)
static const int NOT_INITIALIZED_BRANCH_ID
OptimizerLoop(const std::string &name, const std::string &algLibWthOutExt, const std::string &symbolNameToOptimizerAlgBaseInstanceFactory, bool algInitOnFile, bool initAlgo=true, Proc *procForTypes=NULL)
std::list< InputPort * > getLocalInputPorts() const
redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
void init(bool start=true)
OutPort * getOutPort(const std::string &name) const
::YACS::BASES::DynLibLoader * _loader
static const char NAME_OF_ALGO_RESULT_PORT[]
TypeCode * checkTypeCode(TypeCode *tc, const char *portName)
virtual void loadAlgorithm()
Load the algorithm from the dynamic library.
std::vector< AnyInputPort * > _interceptorsForOutPool
void checkLinkPossibility(OutPort *start, const std::list< ComposedNode * > &pointsOfViewStart, InPort *end, const std::list< ComposedNode * > &pointsOfViewEnd)
void launchMaxOfSamples(bool first)
std::vector< bool > _initNodeUpdated
virtual YACS::Event updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
Method used to notify the node that a child node has failed.
void checkNoCyclePassingThrough(Node *node)
std::list< InputPort * > getSetOfInputPort() const
virtual void checkBasicConsistency() const
Check validity for the node.
virtual bool addInPort(InPort *inPort)=0
virtual int edGetNumberOfOutLinks() const
Definition: OutPort.cxx:50
virtual bool edAddInputPort(InputPort *phyPort)
Definition: OutputPort.cxx:75
const std::set< InputPort * > & getSetOfPhyLinks() const
Returns physical links linked to this. Contrary to edSetInPort that returns semantic links.
Definition: OutputPort.cxx:255
static const char NAME[]
Definition: OutputPort.hxx:79
virtual void exInit()
Definition: OutputPort.cxx:62
void destroyCurrentCase()
Definition: Pool.cxx:127
void destroyAll()
Definition: Pool.cxx:122
bool empty() const
Definition: Pool.cxx:246
void setCurrentId(int id)
Definition: Pool.cxx:159
void putOutSampleAt(int id, Any *outValue)
Definition: Pool.cxx:180
void markIdAsInUse(int id)
Definition: Pool.cxx:232
Any * getNextSampleWithHighestPriority(int &id, unsigned char &priority) const
Definition: Pool.cxx:204
Node * getNode() const
Definition: Port.hxx:46
Base class for all schema objects.
Definition: Proc.hxx:44
Base class for all type objects.
Definition: TypeCode.hxx:68
virtual void visitOptimizerLoop(OptimizerLoop *node)=0
const char * what(void) const noexcept
Definition: Exception.cxx:50
OptimizerAlgBase *(* OptimizerAlgBaseFactory)(Pool *pool)
Event
Definition: define.hxx:56
@ ABORT
Definition: define.hxx:60
@ NOEVENT
Definition: define.hxx:57
@ FINISH
Definition: define.hxx:59
@ FAILED
Definition: define.hxx:51
@ ACTIVATED
Definition: define.hxx:41
@ DONE
Definition: define.hxx:43
@ TOACTIVATE
Definition: define.hxx:40
@ DISABLED
Definition: define.hxx:50
@ ERROR
Definition: define.hxx:52