Version: 8.3.0
OptimizerLoop.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2016 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 "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),_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  return;
249  }
250  launchMaxOfSamples(true);
251  }
252  }
253  catch (const exception & e)
254  {
256  string("An error happened in the control algorithm of OptimizerLoop \"") + _name +
257  "\": " + e.what());
258  }
259 }
260 
262 {
264 }
265 
266 InputPort *OptimizerLoop::getInputPort(const std::string& name) const throw(YACS::Exception)
267 {
268  if (name == NAME_OF_ALGO_INIT_PORT)
269  return (InputPort *)&_algoInitPort;
270  else if (name == NAME_OF_OUT_POOL_INPUT)
271  return (InputPort *)&_retPortForOutPool;
272  else
273  return DynParaLoop::getInputPort(name);
274 }
275 
276 std::list<InputPort *> OptimizerLoop::getSetOfInputPort() const
277 {
278  list<InputPort *> ret=DynParaLoop::getSetOfInputPort();
279  ret.push_back((InputPort *)&_algoInitPort);
280  ret.push_back((InputPort *)&_retPortForOutPool);
281  return ret;
282 }
283 
284 std::list<InputPort *> OptimizerLoop::getLocalInputPorts() const
285 {
286  list<InputPort *> ret=DynParaLoop::getLocalInputPorts();
287  ret.push_back((InputPort *)&_algoInitPort);
288  ret.push_back((InputPort *)&_retPortForOutPool);
289  return ret;
290 }
291 
292 void OptimizerLoop::selectRunnableTasks(std::vector<Task *>& tasks)
293 {
294 }
295 
296 void OptimizerLoop::getReadyTasks(std::vector<Task *>& tasks)
297 {
298  if(!_node)
299  return;
301  {
303  {
305  return ;
306  }
307  vector<Node *>::iterator iter;
308  for (iter=_execNodes.begin() ; iter!=_execNodes.end() ; iter++)
309  (*iter)->getReadyTasks(tasks);
310  for (iter=_execInitNodes.begin() ; iter!=_execInitNodes.end() ; iter++)
311  (*iter)->getReadyTasks(tasks);
312  for (iter=_execFinalizeNodes.begin() ; iter!=_execFinalizeNodes.end() ; iter++)
313  (*iter)->getReadyTasks(tasks);
314  }
315 }
316 
318 {
319  if (getState() == YACS::FAILED)
320  {
321  // This happens when a valid computation on a branch finishes after an error on another branch.
322  // In this case we just ignore the new result because the algorithm has already been terminated.
323  return YACS::NOEVENT;
324  }
325  unsigned int id;
326  switch(getIdentityOfNotifyerNode(node,id))
327  {
328  case INIT_NODE:
329  {
330  _execNodes[id]->exUpdateState();
334  break;
335  }
336  case WORK_NODE:
337  {
339  { //This case happens when alg has reached its convergence whereas other calculations still compute
341  if(!isFullyLazy())
342  return YACS::NOEVENT;
343  else
344  return finalize();
345  }
349  if (_alg->hasError()) {
350  _errorDetails = string("An error happened in the control algorithm of optimizer loop: ") +
351  _alg->getError();
352  _alg->finishProxy();
354  return YACS::ABORT;
355  }
356 
358  if(_myPool.empty())
359  {
362  if(!isFullyLazy())
363  {// This case happens when the hand is returned to continue, whereas some other are working in parallel for nothing.
365  return YACS::NOEVENT;
366  }
367  return finalize();
368  }
370  int newId;
371  unsigned char priority;
372  Any *val=_myPool.getNextSampleWithHighestPriority(newId, priority);
373  if(!val)
374  {
375  bool isFinished=true;
376  for(int i=0;i<_execIds.size() && isFinished;i++)
378  if(isFinished)
379  {
380  std::cerr <<"OptimizerLoop::updateStateOnFinishedEventFrom: Alg has not inserted more cases whereas last element has been calculated !" << std::endl;
382  exForwardFailed();
383  _alg->finishProxy();
384  return YACS::FINISH;
385  }
386  return YACS::NOEVENT;
387  }
388  launchMaxOfSamples(false);
389  break;
390  }
391  case FINALIZE_NODE:
392  {
394  if (_unfinishedCounter == 0)
395  {
398  return YACS::FINISH;
399  }
400  else
401  return YACS::NOEVENT;
402  break;
403  }
404  default:
405  YASSERT(false);
406  }
407  return YACS::NOEVENT;
408 }
409 
411 {
412  //update internal node (definition node) state
413  if (_node)
414  {
416  ComposedNode* compNode = dynamic_cast<ComposedNode*>(_node);
417  if (compNode)
418  {
419  std::list<Node *> aChldn = compNode->getAllRecursiveConstituents();
420  std::list<Node *>::iterator iter=aChldn.begin();
421  for(;iter!=aChldn.end();iter++)
422  (*iter)->setState(YACS::DONE);
423  }
424  }
425  _alg->finishProxy();
427  if (_finalizeNode == NULL)
428  {
429  // No finalize node, we just finish OptimizerLoop at the end of exec nodes execution
431  return YACS::FINISH;
432  }
433  else
434  {
435  // Run the finalize nodes, the OptimizerLoop will be done only when they all finish
436  _unfinishedCounter = 0; // This counter indicates how many branches are not finished
437  for (int i=0 ; i<_nbOfBranches.getIntValue() ; i++)
439  {
440  DEBTRACE("Launching finalize node for branch " << i)
441  _execFinalizeNodes[i]->exUpdateState();
443  }
444  else
445  // There should not be any running branch at this point
447  return YACS::NOEVENT;
448  }
449 }
450 
452 
460 {
461  DEBTRACE("OptimizerLoop::updateStateOnFailedEventFrom " << node->getName());
462  _alg->setError(string("Error during the execution of YACS node ") + node->getName() +
463  ": " + node->getErrorReport());
464  _alg->finishProxy();
466  DEBTRACE("OptimizerLoop::updateStateOnFailedEventFrom: returned from error notification.");
467  return DynParaLoop::updateStateOnFailedEventFrom(node,execInst);
468 }
469 
471 {
472 }
473 
474 void OptimizerLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
475 {
476  DynParaLoop::buildDelegateOf(port,initialStart,pointsOfView);
477  if(port==&_retPortForOutPool)
478  {
479  std::string linkName("(");
480  linkName += initialStart->getName()+" to "+port->getName()+")";
481  throw Exception(std::string("Illegal OptimizerLoop link: \
482 The 'evalResults' port must be linked within the scope of the loop.")
483  + linkName);
484  }
485 }
486 
487 void OptimizerLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
488 {
489  DynParaLoop::buildDelegateOf(port,finalTarget,pointsOfView);
490  if(port.first != &_algoResultPort)
491  {
492  std::string linkName("(");
493  linkName += port.first->getName()+" to "+finalTarget->getName()+")";
494  throw Exception(std::string("Illegal OptimizerLoop link: \
495 Only the algorithm result port can be linked to a port outside the scope of the loop.")
496  + linkName);
497  }
498 
499  string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
500  if(typeOfPortInstance!=OutputPort::NAME)
501  throw Exception("OptimizerLoop::buildDelegateOf : not implemented for DS because not specified ");
502 }
503 
505  std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw,
506  std::vector<OutPort *>& fwCross,
507  std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
508  LinkInfo& info) const
509 {
510  if(end==&_retPortForOutPool)
511  fw[(ComposedNode *)this].push_back(start);
512  else
513  DynParaLoop::checkControlDependancy(start,end,cross,fw,fwCross,bw,info);
514 }
515 
516 void OptimizerLoop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
517 {
518  if(end==&_retPortForOutPool)
519  solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
520  else
521  DynParaLoop::checkCFLinks(starts,end,alreadyFed,direction,info);
522 }
523 
524 void OptimizerLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
525  InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
526 {
527  DynParaLoop::checkLinkPossibility(start, pointsOfViewStart, end, pointsOfViewEnd);
528  std::string linkName("(");
529  linkName += start->getName()+" to "+end->getName()+")";
530 
531  // Yes, it should be possible to link back the result port to any input port of the loop.
532  if(end == &_nbOfBranches || end == &_algoInitPort)
533  if(start != &_algoResultPort)
534  throw Exception(std::string("Illegal OptimizerLoop link.") + linkName);
535  else
536  return;
537 
538  if(start == &_algoResultPort)
539  throw Exception(std::string("Illegal OptimizerLoop link: \
540 The 'algoResult' port can't be linked within the scope of the loop.") + linkName);
541 
542  if(end == &_retPortForOutPool && isInMyDescendance(start->getNode())!=_node)
543  throw Exception(std::string("Illegal OptimizerLoop link: \
544 The 'evalResults' port can only be linked to the working node.") + linkName);
545 }
546 
548 {
549  // At this point all garanties taken let's clean all.
550  map<InputPort *,vector<InputPort *> >::iterator iter=_interceptors.begin();
551  for(;iter!=_interceptors.end();iter++)
552  for(vector<InputPort *>::iterator iter2=(*iter).second.begin();iter2!=(*iter).second.end();iter2++)
553  delete (*iter2);
554  _interceptors.clear();
555  for(vector<AnyInputPort *>::iterator iter3=_interceptorsForOutPool.begin();iter3!=_interceptorsForOutPool.end();iter3++)
556  delete (*iter3);
557  _interceptorsForOutPool.clear();
558 }
559 
561 {
562  int id;
563  unsigned char priority;
564  Any *val;
565  unsigned i;
566  for (val = _myPool.getNextSampleWithHighestPriority(id, priority);
567  !isFullyBusy(i) && val;
568  val = _myPool.getNextSampleWithHighestPriority(id, priority))
569  {
571  first=true; // node is not initialized (first pass)
572  else
573  first=false; // node is initialized (second pass)
574  _execIds[i]=id;
576  if(_initNode && !_initNodeUpdated[i])
577  {
578  putValueOnBranch(val,i,first);
579  _execInitNodes[i]->exUpdateState();
580  _initNodeUpdated[i]=true;
582  }
583  else
584  {
585  if(!first)
586  _execNodes[i]->init(first);
587  putValueOnBranch(val,i,first);
588  _execNodes[i]->exUpdateState();
590  }
591  }
592 }
593 
595 {
596  bool isLazy=true;
597  for(unsigned i=0;i<_execIds.size() && isLazy;i++)
599  return isLazy;
600 }
601 
606 bool OptimizerLoop::isFullyBusy(unsigned& branchId) const
607 {
608  bool isFinished=true;
609  unsigned i;
610  for(i=0;i<_execIds.size() && isFinished;i++)
612  if(!isFinished)
613  branchId=i-1;
614  return isFinished;
615 }
616 
620 void OptimizerLoop::initInterceptors(unsigned nbOfBr)
621 {
622  //For all classical outputports leaving 'this'
623  set<OutPort *> portsToIntercept=getAllOutPortsLeavingCurrentScope();
624  portsToIntercept.erase(&_algoResultPort);
625  for(set<OutPort *>::iterator iter=portsToIntercept.begin();iter!=portsToIntercept.end();iter++)
626  {
627  OutputPort *portC=(OutputPort *)(*iter);//Warrantied by OptimizerLoop::buildDelegateOf
628  const set<InputPort *>& links=portC->getSetOfPhyLinks();
629  for(set<InputPort *>::const_iterator iter2=links.begin();iter2!=links.end();iter2++)
630  {
631 #ifdef NOCOVARIANT
632  InputPort *reprCur=dynamic_cast<InputPort *>((*iter2)->getPublicRepresentant());
633 #else
634  InputPort *reprCur=(*iter2)->getPublicRepresentant();
635 #endif
636  if(!isInMyDescendance(reprCur->getNode()))
637  {//here we've got an out of scope link : Let's intercept it
638  if(_interceptors.find(reprCur)==_interceptors.end())
639  {
640  _interceptors[reprCur].resize(nbOfBr);
641  for(unsigned i=0;i<nbOfBr;i++)
642  {
644  InputPort *clone=reprCur->clone(0);
645  _interceptors[reprCur][i]=clone;
646  portExecC->edAddInputPort(clone);
647  }
648  }
649  else
650  {
651  for(unsigned i=0;i<nbOfBr;i++)
652  {
654  portExecC->edAddInputPort(_interceptors[reprCur][i]);
655  }
656  }
657  }
658  }
659  }
660  // For out pool
661  _interceptorsForOutPool.resize(nbOfBr);
662  set< OutPort * > links=_retPortForOutPool.edSetOutPort();
663  for(unsigned i=0;i<nbOfBr;i++)
665  for(set<OutPort *>::iterator iter2=links.begin();iter2!=links.end();iter2++)
666  for(unsigned j=0;j<nbOfBr;j++)
667  {
668  OutPort *portExec;
669  Node *whatType=isInMyDescendance((*iter2)->getNode());
670  if(whatType==_node)
671  {
672  portExec=_execNodes[j]->getOutPort(_node->getOutPortName(*iter2));
673  portExec->addInPort(_interceptorsForOutPool[j]);
674  }
675  else if(whatType==_initNode && whatType!=0)//This case should never happend. Useless !
676  {
677  portExec=_execInitNodes[j]->getOutPort(_node->getOutPortName(*iter2));
678  portExec->addInPort(_interceptorsForOutPool[j]);
679  }
680  }
681 }
682 
688 {
689  map<InputPort *, std::vector<InputPort *> >::iterator iter;
690  for(iter=_interceptors.begin();iter!=_interceptors.end();iter++)
691  (*iter).first->put((*iter).second[branchId]->get());
692 }
693 
695 {
696  visitor->visitOptimizerLoop(this);
697 }
698 
700 
703 void OptimizerLoop::setAlgorithm(const std::string& alglib, const std::string& symbol,
704  bool checkLinks, Proc * procForTypes)
705 {
706  if(checkLinks)
707  {
712  throw Exception("The OptimizerLoop node must be disconnected before setting the algorithm");
713  }
714 
715  _symbol = symbol;
716  _alglib = alglib;
717 
718  if (_alg) {
719  _alg->decrRef();
720  _alg = NULL;
721  }
722 
723  loadAlgorithm();
724 
725  if(_alg)
726  {
727  _alg->setProc((procForTypes == NULL) ? getProc() : procForTypes);
728 
729  // Delete the values in the input ports if they were initialized
730  _retPortForOutPool.put((Any *)NULL);
731  _algoInitPort.put((Any *)NULL);
732 
733  // Change the type of the ports
738  }
739 
740  modified();
741 }
742 
743 TypeCode * OptimizerLoop::checkTypeCode(TypeCode * tc, const char * portName)
744 {
745  if (tc == NULL) {
746  ostringstream errorMsg;
747  errorMsg << "The algorithm specified for OptimizerLoop node \"" << getName() <<
748  "\" provided an invalid type for port \"" << portName << "\"";
749  throw Exception(errorMsg.str());
750  }
751  return tc;
752 }
753 
755 
759 {
760  YASSERT(_alg == NULL)
761 
762  if (_loader != NULL) {
763  delete _loader;
764  _loader = NULL;
765  }
766  _loader = new YACS::BASES::DynLibLoader(_alglib);
767  OptimizerAlgBaseFactory algFactory = NULL;
768 
769  if (_alglib != "" && _symbol != "")
770  {
771  try
772  {
773  _errorDetails = "";
774  algFactory = (OptimizerAlgBaseFactory)_loader->getHandleOnSymbolWithName(_symbol);
775  }
776  catch (YACS::Exception& e)
777  {
778  _errorDetails = e.what();
779  modified();
780  throw;
781  }
782  }
783 
784  if (algFactory != NULL)
785  _alg = algFactory(&_myPool);
786 }
787 
789 
792 std::string OptimizerLoop::getAlgLib() const
793 {
794  return _alglib;
795 }
796 
798 
802 {
803  DEBTRACE("OptimizerLoop::checkBasicConsistency");
804  if (_alglib == "")
805  throw Exception("No library specified for the OptimizerLoop control algorithm");
806  if (_symbol == "")
807  throw Exception("No symbol specified for the OptimizerLoop control algorithm");
808  if(_alg == NULL)
809  throw YACS::Exception("Problem during library loading: "+_errorDetails);
810 
812 }
813 
815 {
817 }
818 
819 std::list<OutputPort *> OptimizerLoop::getSetOfOutputPort() const
820 {
821  list<OutputPort *> ret = DynParaLoop::getSetOfOutputPort();
822  ret.push_back((OutputPort *)&_algoResultPort);
823  return ret;
824 }
825 
826 std::list<OutputPort *> OptimizerLoop::getLocalOutputPorts() const
827 {
828  list<OutputPort *> ret = DynParaLoop::getLocalOutputPorts();
829  ret.push_front((OutputPort *)&_algoResultPort);
830  return ret;
831 }
832 
833 OutPort * OptimizerLoop::getOutPort(const std::string& name) const throw(YACS::Exception)
834 {
835  return (name == NAME_OF_ALGO_RESULT_PORT) ? (OutPort *)&_algoResultPort :
837 }
838 
839 
840 OutputPort * OptimizerLoop::getOutputPort(const std::string& name) const throw(YACS::Exception)
841 {
842  return (name == NAME_OF_ALGO_RESULT_PORT) ? (OutputPort *)&_algoResultPort :
844 }