]> SALOME platform Git repositories - modules/yacs.git/blob - src/engine/Bloc.cxx
Salome HOME
mergefrom branch BR_V511_PR tag mergeto_trunk_03feb09
[modules/yacs.git] / src / engine / Bloc.cxx
1 //  Copyright (C) 2006-2008  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.
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 #include "Bloc.hxx"
20 #include "LinkInfo.hxx"
21 #include "InputPort.hxx"
22 #include "OutputPort.hxx"
23 #include "ElementaryNode.hxx"
24 #include "Visitor.hxx"
25
26 #include <iostream>
27
28 //#define _DEVDEBUG_
29 #include "YacsTrace.hxx"
30
31 using namespace YACS::ENGINE;
32 using namespace std;
33
34 Bloc::Bloc(const Bloc& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_fwLinks(0),_bwLinks(0)
35 {
36   for(list<Node *>::const_iterator iter=other._setOfNode.begin();iter!=other._setOfNode.end();iter++)
37     _setOfNode.push_back((*iter)->simpleClone(this,editionOnly));
38   //CF Linking
39   vector< pair<OutGate *, InGate *> > cfLinksToReproduce=other.getSetOfInternalCFLinks();
40   vector< pair<OutGate *, InGate *> >::iterator iter1=cfLinksToReproduce.begin();
41   for(;iter1!=cfLinksToReproduce.end();iter1++)
42     edAddCFLink(getChildByName(other.getChildName((*iter1).first->getNode())),getChildByName(other.getChildName((*iter1).second->getNode())));
43   //Data + DataStream linking
44   vector< pair<OutPort *, InPort *> > linksToReproduce=other.getSetOfInternalLinks();
45   vector< pair<OutPort *, InPort *> >::iterator iter2=linksToReproduce.begin();
46   for(;iter2!=linksToReproduce.end();iter2++)
47     edAddLink(getOutPort(other.getPortName((*iter2).first)),getInPort(other.getPortName((*iter2).second)));
48 }
49
50 //! Create a Bloc node with a given name
51 /*!
52  *   \param name : the given name
53  */
54 Bloc::Bloc(const std::string& name):StaticDefinedComposedNode(name),_fwLinks(0),_bwLinks(0)
55 {
56 }
57
58 Bloc::~Bloc()
59 {
60   for(list<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
61     delete *iter;
62   delete _fwLinks;
63   delete _bwLinks;
64 }
65
66 //! Initialize the bloc
67 /*!
68  * \param start : a boolean flag indicating the kind of initialization
69  * If start is true, it's a complete initialization with reinitialization of port values
70  * If start is false, there is no initialization of port values
71  */
72 void Bloc::init(bool start)
73 {
74   Node::init(start);
75   for(list<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
76     (*iter)->init(start);
77 }
78
79 //! Indicate if the bloc execution is finished
80 /*!
81  * The execution bloc is finished if all its child nodes
82  * are finished with or without error or if it is disabled (not to execute)
83  */
84 bool Bloc::isFinished()
85 {
86     if(_state==YACS::DONE)return true;
87     if(_state==YACS::ERROR)return true;
88     if(_state==YACS::FAILED)return true;
89     if(_state==YACS::DISABLED)return true;
90     return false;
91 }
92
93 int Bloc::getNumberOfCFLinks() const
94 {
95   int ret=0;
96   for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
97     ret+=(*iter)->getOutGate()->getNbOfInGatesConnected();
98   return ret;
99 }
100
101 Node *Bloc::simpleClone(ComposedNode *father, bool editionOnly) const
102 {
103   return new Bloc(*this,father,editionOnly);
104 }
105
106 //! Collect all nodes that are ready to execute
107 /*!
108  * \param tasks : vector of tasks to collect ready nodes
109  */
110 void Bloc::getReadyTasks(std::vector<Task *>& tasks)
111 {
112   /*
113    * ComposedNode state goes to ACTIVATED when one of its child has been ACTIVATED
114    * To change this uncomment the following line
115    * Then the father node will go to ACTIVATED state before its child node
116    */
117   if(_state==YACS::TOACTIVATE ) setState(YACS::ACTIVATED);
118   if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
119     for(list<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
120       (*iter)->getReadyTasks(tasks);
121 }
122
123 //! Update the bloc state
124 /*!
125  * Update the '_state' attribute.
126  * Typically called by 'this->_inGate' when 'this->_inGate' is ready. 
127  * Contrary to Node::exUpdateState no check done on inputs
128  * because internal linked DF inputports are not valid yet.
129  */
130 void Bloc::exUpdateState()
131 {
132   if(_state == YACS::DISABLED)return;
133   if(_inGate.exIsReady())
134     {
135       setState(YACS::TOACTIVATE);
136       for(list<Node *>::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
137         if((*iter)->exIsControlReady())
138           (*iter)->exUpdateState();
139     }
140 }
141
142 //! Add a child node to the bloc
143 /*!
144  * \param node: the node to add to the bloc
145  * \return a boolean flag indicating if the node has been added
146  *
147  * If node is already a direct child of current bloc, do nothing.
148  * If node is a child of another bloc, throw exception.
149  * If node name already used in bloc, throw exception.
150  * Publish inputPorts in current bloc and ancestors.
151  */
152 bool Bloc::edAddChild(Node *node) throw(Exception)
153 {
154   if(isNodeAlreadyAggregated(node))
155     {
156       if(node->_father==this)
157         return false;
158       else
159         {
160           string what = "Bloc::edAddChild : node "; what += node->getName();
161           what += " is already grand children of node";
162           throw Exception(what);
163         }
164     }
165
166   if(node->_father)
167     {
168       string what = "Bloc::edAddChild: node is not orphan: "; what += node->getName();
169       throw Exception(what);
170     }
171   
172   checkNoCrossHierachyWith(node);
173
174   if(isNameAlreadyUsed(node->getName()))
175     {
176       string what("Bloc::edAddChild : name "); what+=node->getName(); 
177       what+=" already exists in the scope of "; what+=_name;
178       throw Exception(what);
179     }
180   
181   node->_father=this;
182   _setOfNode.push_back(node);
183   //should we also set _modified flag for node ??
184   ComposedNode *iter=node->_father;
185   //set the _modified flag so that latter on edUpdateState (eventually called by isValid) refresh state
186   //better call it at end
187   modified();
188   return true;
189 }
190
191 /**
192  * Remove 'node' from the set of direct children.
193  * @exception If 'node' is NOT the son of 'this'.
194  */
195
196 void Bloc::edRemoveChild(Node *node) throw(Exception)
197 {
198   StaticDefinedComposedNode::edRemoveChild(node);
199   list<Node *>::iterator iter=find(_setOfNode.begin(),_setOfNode.end(),node);
200   if(iter!=_setOfNode.end())
201     {
202       _setOfNode.erase(iter);
203       modified();
204     }
205 }
206
207 Node *Bloc::getChildByShortName(const std::string& name) const throw(Exception)
208 {
209   for (list<Node *>::const_iterator iter = _setOfNode.begin(); iter != _setOfNode.end(); iter++)
210     if ((*iter)->getName() == name)
211       return (*iter);
212   string what("node "); what+= name ; what+=" is not a child of Bloc "; what += getName();
213   throw Exception(what);
214 }
215
216 void Bloc::selectRunnableTasks(std::vector<Task *>& tasks)
217 {
218 }
219
220 bool Bloc::areAllSubNodesDone() const
221 {
222   for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
223     {
224       if((*iter)->_state == YACS::DONE)continue;
225       if((*iter)->_state == YACS::DISABLED)continue;
226       return false;
227     }
228   return true;
229 }
230
231 bool Bloc::areAllSubNodesFinished() const
232 {
233   for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
234     {
235       if((*iter)->_state == YACS::DONE)continue;
236       if((*iter)->_state == YACS::FAILED)continue;
237       if((*iter)->_state == YACS::DISABLED)continue;
238       if((*iter)->_state == YACS::ERROR)continue;
239       if((*iter)->_state == YACS::INTERNALERR)continue;
240       return false;
241     }
242   return true;
243 }
244
245 bool Bloc::isNameAlreadyUsed(const std::string& name) const
246 {
247   for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
248     if((*iter)->getName()==name)
249       return true;
250   return false;
251 }
252
253 bool insertNodeChildrenInSet(Node *node, std::set<Node *>& nodeSet)
254 {
255   bool verdict=true;
256   set<Node *> outNodes=node->getOutNodes();
257   for (set<Node *>::iterator iter=outNodes.begin();iter!=outNodes.end(); iter++)
258     {
259       verdict=(nodeSet.insert(*iter)).second;
260       if (verdict) verdict = insertNodeChildrenInSet((*iter),nodeSet);
261     }
262   return verdict;
263 }
264
265 /*!
266  * \note  Checks that in the forest from 'node' there are NO back-edges.
267  *        \b WARNING : When using this method 'node' has to be checked in order to be part of direct children of 'this'. 
268  *
269  */
270 void Bloc::checkNoCyclePassingThrough(Node *node) throw(Exception)
271 {
272   set<Node *> currentNodesToTest;
273   //don't insert node to test in set. 
274   //If it is present after insertion of connected nodes we have a loop
275   //collect all connected nodes
276   insertNodeChildrenInSet(node,currentNodesToTest);
277   //try to insert node
278   if(!(currentNodesToTest.insert(node)).second)
279     throw Exception("Cycle has been detected");
280 }
281
282 std::vector< std::pair<OutGate *, InGate *> > Bloc::getSetOfInternalCFLinks() const
283 {
284   vector< pair<OutGate *, InGate *> > ret;
285   for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
286     {
287       set<InGate *> outCFLinksOfCurNode=(*iter)->_outGate.edSetInGate();
288       for(set<InGate *>::iterator iter2=outCFLinksOfCurNode.begin();iter2!=outCFLinksOfCurNode.end();iter2++)
289         ret.push_back(pair<OutGate *, InGate *>(&(*iter)->_outGate,*iter2));
290     }
291   return ret;
292 }
293
294 /*!
295  *
296  * @note : Runtime called method. Indirectly called by StaticDefinedComposedNode::updateStateFrom which has dispatch to this method
297  *          'when event == FINISH'.
298  *          WARNING Precondition : '_state == Running' and 'node->_father==this'(garanteed by StaticDefinedComposedNode::notifyFrom)
299  *
300  * Calls the node's outgate OutGate::exNotifyDone if all nodes are not finished
301  */
302 YACS::Event Bloc::updateStateOnFinishedEventFrom(Node *node)
303 {
304   DEBTRACE("Bloc::updateStateOnFinishedEventFrom: " << node->getName());
305   //ASSERT(node->_father==this)
306   if(areAllSubNodesFinished())
307     {
308       setState(YACS::DONE);
309       if(!areAllSubNodesDone())
310         {
311           setState(YACS::FAILED);
312           return YACS::ABORT;
313         }
314       return YACS::FINISH;//notify to father node that 'this' has becomed finished.
315     }
316   //more job to do in 'this' bloc
317   //Conversion exceptions can be thrown so catch them to control errors
318   try
319     {
320       //notify the finished node to propagate to its following nodes
321       node->exForwardFinished();
322     }
323   catch(YACS::Exception& ex)
324     {
325       //The node has failed to propagate. It must be put in error
326       DEBTRACE("Bloc::updateStateOnFinishedEventFrom: " << ex.what());
327       // notify the node it has failed
328       node->exForwardFailed();
329       setState(YACS::FAILED);
330       return YACS::ABORT;
331     }
332   return YACS::NOEVENT;//no notification to father needed because from father point of view nothing happened.
333 }
334
335 //! Notify this bloc that a node has failed
336 /*!
337  * \param node : node that has emitted the event
338  * \return the event to notify to bloc's father
339  */
340 YACS::Event Bloc::updateStateOnFailedEventFrom(Node *node)
341 {
342   node->exForwardFailed();
343   if(areAllSubNodesFinished())
344     {
345       setState(YACS::DONE);
346       if(!areAllSubNodesDone()){
347           setState(YACS::FAILED);
348           return YACS::ABORT;
349       }
350       return YACS::FINISH;//notify to father node that 'this' has becomed finished.
351     }
352   return YACS::NOEVENT;
353 }
354
355 void Bloc::writeDot(std::ostream &os) const
356 {
357     os << "  subgraph cluster_" << getId() << "  {\n" ;
358     list<Node *>nodes=getChildren();
359     for(list<Node *>::const_iterator iter=nodes.begin();iter!=nodes.end();iter++)
360     {
361         (*iter)->writeDot(os);
362         string p=(*iter)->getId();
363         //not connected node
364         if((*iter)->_inGate._backLinks.size() == 0) os << getId() << " -> " << p << ";\n";
365         set<Node *>outnodes = (*iter)->getOutNodes();
366         for(set<Node *>::const_iterator itout=outnodes.begin();itout!=outnodes.end();itout++)
367         {
368             os << p << " -> " << (*itout)->getId() << ";\n";
369         }
370     }
371     os << "}\n" ;
372     os << getId() << "[fillcolor=\"" ;
373     YACS::StatesForNode state=getEffectiveState();
374     os << getColorState(state);
375     os << "\" label=\"" << "Bloc:" ;
376     os << getQualifiedName() <<"\"];\n";
377 }
378
379 void Bloc::accept(Visitor* visitor)
380 {
381   visitor->visitBloc(this);
382 }
383
384 /*!
385  * Updates mutable structures _fwLinks and _bwLinks with the result of computation (CPU consuming method).
386  * _fwLinks is a map with a Node* as key and a set<Node*> as value. The set gives
387  * all nodes that are forwardly connected to the key node 
388  * _bwLinks is a map for backward dependencies
389  * The method is : for all CF link (n1->n2) 
390  * add n2 and _fwLinks[n2] in forward dependencies of n1 and _bwLinks[n1]
391  * add n1 and _bwLinks[n1] in backward dependencies of n2 and _fwLinks[n2]
392  * For useless links
393  * If a node is already in a forward dependency when adding and the direct link
394  * already exists so it's a useless link (see the code !)
395  */
396 void Bloc::performCFComputations(LinkInfo& info) const
397 {
398   StaticDefinedComposedNode::performCFComputations(info);
399   delete _fwLinks;//Normally useless
400   delete _bwLinks;//Normally useless
401   _fwLinks=new map<Node *,set<Node *> >;
402   _bwLinks=new map<Node *,set<Node *> >;
403
404   //a set to store all CF links : used to find fastly if two nodes are connected
405   std::set< std::pair< Node*, Node* > > links;
406
407   for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
408     {
409       Node* n1=*iter;
410       std::set<InGate *> ingates=n1->getOutGate()->edSetInGate();
411       for(std::set<InGate *>::const_iterator it2=ingates.begin();it2!=ingates.end();it2++)
412         {
413           //CF link : n1 -> (*it2)->getNode()
414           Node* n2=(*it2)->getNode();
415           links.insert(std::pair< Node*, Node* >(n1,n2));
416           std::set<Node *> bwn1=(*_bwLinks)[n1];
417           std::set<Node *> fwn1=(*_fwLinks)[n1];
418           std::set<Node *> fwn2=(*_fwLinks)[n2];
419           std::set<Node *> bwn2=(*_bwLinks)[n2];
420           std::pair<std::set<Node*>::iterator,bool> ret;
421           for(std::set<Node *>::const_iterator iter2=bwn1.begin();iter2!=bwn1.end();iter2++)
422             {
423               for(std::set<Node *>::const_iterator it3=fwn2.begin();it3!=fwn2.end();it3++)
424                 {
425                   ret=(*_fwLinks)[*iter2].insert(*it3);
426                   if(ret.second==false)
427                     {
428                       //dependency already exists (*iter2) -> (*it3) : if a direct link exists it's a useless one
429                       if(links.find(std::pair< Node*, Node* >(*iter2,*it3)) != links.end())
430                         info.pushUselessCFLink(*iter2,*it3);
431                     }
432                 }
433               ret=(*_fwLinks)[*iter2].insert(n2);
434               if(ret.second==false)
435                 {
436                   //dependency already exists (*iter2) -> n2 : if a direct link exists it's a useless one
437                   if(links.find(std::pair< Node*, Node* >(*iter2,n2)) != links.end())
438                     info.pushUselessCFLink(*iter2,n2);
439                 }
440             }
441           for(std::set<Node *>::const_iterator it3=fwn2.begin();it3!=fwn2.end();it3++)
442             {
443               ret=(*_fwLinks)[n1].insert(*it3);
444               if(ret.second==false)
445                 {
446                   //dependency already exists n1 -> *it3 : if a direct link exists it's a useless one
447                   if(links.find(std::pair< Node*, Node* >(n1,*it3)) != links.end())
448                     info.pushUselessCFLink(n1,*it3);
449                 }
450             }
451           ret=(*_fwLinks)[n1].insert(n2);
452           if(ret.second==false)
453             {
454               //dependency already exists n1 -> n2 : it's a useless link
455               info.pushUselessCFLink(n1,n2);
456             }
457
458           for(std::set<Node *>::const_iterator iter2=fwn2.begin();iter2!=fwn2.end();iter2++)
459             {
460               (*_bwLinks)[*iter2].insert(bwn1.begin(),bwn1.end());
461               (*_bwLinks)[*iter2].insert(n1);
462             }
463           (*_bwLinks)[n2].insert(bwn1.begin(),bwn1.end());
464           (*_bwLinks)[n2].insert(n1);
465         }
466     }
467 }
468
469 void Bloc::destructCFComputations(LinkInfo& info) const
470 {
471   StaticDefinedComposedNode::destructCFComputations(info);
472   delete _fwLinks; _fwLinks=0;
473   delete _bwLinks; _bwLinks=0;
474 }
475
476 /*!
477  * \b WARNING \b Needs call of performCFComputations before beeing called.
478  *  Perform updates of containers regarding attributes of link 'start' -> 'end' and check the correct linking.
479  *  The output is in info struct.
480  *
481  * \param fw out parameter beeing append if start -> end link is a forward link \b without cross type DF/DS.
482  * \param fwCross out parameter beeing append if start -> end link is a forward link \b with cross type DF/DS.
483  * \param bw out parameter beeing append if start -> end link is a backward link.
484  * \param info out parameter beeing informed about eventual errors.
485  */
486 void Bloc::checkControlDependancy(OutPort *start, InPort *end, bool cross,
487                                   std::map < ComposedNode *,  std::list < OutPort * >, SortHierarc >& fw,
488                                   std::vector<OutPort *>& fwCross,
489                                   std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
490                                   LinkInfo& info) const
491 {
492   if(!cross)
493     {
494       Node *startN=isInMyDescendance(start->getNode());
495       Node *endN=isInMyDescendance(end->getNode());
496       if(startN==endN)
497         bw[(ComposedNode *)this].push_back(start);
498       else if(areLinked(startN,endN,true))
499         fw[(ComposedNode *)this].push_back(start);
500       else
501         if(areLinked(startN,endN,false))
502           bw[(ComposedNode *)this].push_back(start);
503         else
504           info.pushErrLink(start,end,E_UNPREDICTABLE_FED);
505     }
506   else//DFDS detected
507     if(arePossiblyRunnableAtSameTime(isInMyDescendance(start->getNode()),isInMyDescendance(end->getNode())))
508       fwCross.push_back(start);
509     else
510       info.pushErrLink(start,end,E_DS_LINK_UNESTABLISHABLE);
511 }
512
513 /*!
514  * 'start' and 'end' \b must be direct son of 'this'.
515  * Typically used for data link.
516  * \param fw indicates if it is a forward link searched (true : default value) or a backward link serach.
517  */
518 bool Bloc::areLinked(Node *start, Node *end, bool fw) const
519 {
520   set<Node *>& nexts=fw ? (*_fwLinks)[start] : (*_bwLinks)[start];
521   return nexts.find(end)!=nexts.end();
522 }
523
524 /*!
525  * Typically used for stream link.
526  * 'start' and 'end' \b must be direct son of 'this'.
527  */
528 bool Bloc::arePossiblyRunnableAtSameTime(Node *start, Node *end) const
529 {
530   set<Node *>& nexts=(*_fwLinks)[start];
531   set<Node *>& preds=(*_bwLinks)[start];
532   return nexts.find(end)==nexts.end() && preds.find(end)==preds.end();
533 }
534
535 /*!
536  * \param starts If different of 0, must aggregate at leat \b 1 element.
537  * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
538  * \param direction If true : forward direction else backward direction.
539  */
540 void Bloc::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
541 {
542   if(alreadyFed==FREE_ST || alreadyFed==FED_ST)
543     {
544       map<Node *,list <OutPort *> > classPerNodes;
545       for(list< OutPort *>::const_iterator iter1=starts.begin();iter1!=starts.end();iter1++)
546         classPerNodes[isInMyDescendance((*iter1)->getNode())].push_back(*iter1);
547       set<Node *> allNodes;
548       for(map<Node *,list <OutPort *> >::iterator iter2=classPerNodes.begin();iter2!=classPerNodes.end();iter2++)
549         allNodes.insert((*iter2).first);
550       vector<Node *> okAndUseless1,useless2;
551       seekOkAndUseless1(okAndUseless1,allNodes);
552       seekUseless2(useless2,allNodes);//after this point allNodes contains collapses
553       verdictForOkAndUseless1(classPerNodes,end,okAndUseless1,alreadyFed,direction,info);
554       verdictForCollapses(classPerNodes,end,allNodes,alreadyFed,direction,info);
555       verdictForOkAndUseless1(classPerNodes,end,useless2,alreadyFed,direction,info);
556     }
557   else if(alreadyFed==FED_DS_ST)
558     for(list< OutPort *>::const_iterator iter1=starts.begin();iter1!=starts.end();iter1++)
559       info.pushErrLink(*iter1,end,E_COLLAPSE_DFDS);
560 }
561
562 void Bloc::initComputation() const
563 {
564   for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
565     {
566       (*iter)->_colour=White;
567       (*iter)->getInGate()->exReset();
568       (*iter)->getOutGate()->exReset();
569     }
570 }
571
572 /*!
573  * Part of final step for CF graph anylizing. This is the part of non collapse nodes. 
574  * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
575  */
576 void Bloc::verdictForOkAndUseless1(const std::map<Node *,std::list <OutPort *> >& pool, InputPort *end, const std::vector<Node *>& candidates, unsigned char& alreadyFed, 
577                                    bool direction, LinkInfo& info)
578 {
579   for(vector<Node *>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
580     {
581       const list<OutPort *>& mySet=(*pool.find(*iter)).second;
582       if(mySet.size()==1)
583         {
584           if(alreadyFed==FREE_ST)
585             {
586               alreadyFed=FED_ST;//This the final choice. General case !
587               if(!direction)
588                 info.pushInfoLink(*(mySet.begin()),end,I_BACK);
589             }
590           else if(alreadyFed==FED_ST)
591               info.pushInfoLink(*(mySet.begin()),end,direction ? I_USELESS : I_BACK_USELESS);//Second or more turn in case of alreadyFed==FREE_ST before call of this method
592         }
593       else
594         {
595           if(dynamic_cast<ElementaryNode *>(*iter))
596             {
597               WarnReason reason;
598               if(alreadyFed==FREE_ST)
599                 reason=direction ? W_COLLAPSE_EL : W_BACK_COLLAPSE_EL;
600               else if(alreadyFed==FED_ST)
601                 reason=direction ? W_COLLAPSE_EL_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS;
602               for(list<OutPort *>::const_iterator iter2=mySet.begin();iter2!=mySet.end();iter2++)    
603                 info.pushWarnLink(*iter2,end,reason);
604             }
605           else
606             ((ComposedNode *)(*iter))->checkCFLinks(mySet,end,alreadyFed,direction,info);//Thanks to recursive model!
607         }
608     }
609 }
610
611 /*!
612  * Part of final step for CF graph anylizing. This is the part of collapses nodes. 
613  * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
614  */
615 void Bloc::verdictForCollapses(const std::map<Node *,std::list <OutPort *> >& pool, InputPort *end, const std::set<Node *>& candidates, unsigned char& alreadyFed, 
616                                bool direction, LinkInfo& info)
617 {
618   info.startCollapseTransac();
619   for(set<Node *>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
620     {
621       const list<OutPort *>& mySet=(*pool.find(*iter)).second;
622       if(mySet.size()==1)
623         {
624           if(alreadyFed==FREE_ST)
625             info.pushWarnLink(*(mySet.begin()),end,direction ? W_COLLAPSE : W_BACK_COLLAPSE);
626           else if(alreadyFed==FED_ST)
627             info.pushWarnLink(*(mySet.begin()),end,direction ? W_COLLAPSE_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS);
628         }
629       else
630         {
631           if(dynamic_cast<ElementaryNode *>(*iter))
632             {
633               WarnReason reason;
634               if(alreadyFed==FREE_ST)
635                 reason=direction ? W_COLLAPSE_EL : W_BACK_COLLAPSE_EL;
636               else if(alreadyFed==FED_ST)
637                 reason=direction ? W_COLLAPSE_EL_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS;
638               for(list<OutPort *>::const_iterator iter2=mySet.begin();iter2!=mySet.end();iter2++)    
639                 info.pushWarnLink(*iter2,end,reason);
640             }
641           else
642             {
643               ((ComposedNode *)(*iter))->checkCFLinks(mySet,end,alreadyFed,direction,info);//Thanks to recursive model!
644               WarnReason reason;
645               if(alreadyFed==FREE_ST)
646                 reason=direction ? W_COLLAPSE : W_BACK_COLLAPSE;
647               else if(alreadyFed==FED_ST)
648                 reason=direction ? W_COLLAPSE_AND_USELESS : W_BACK_COLLAPSE_AND_USELESS;
649               for(list<OutPort *>::const_iterator iter2=mySet.begin();iter2!=mySet.end();iter2++)    
650                 info.pushWarnLink(*iter2,end,reason);
651             }
652         }
653     }
654   if(!candidates.empty())
655     if(alreadyFed==FREE_ST)
656       alreadyFed=FED_ST;
657   info.endCollapseTransac();
658 }
659
660 /*!
661  * \b WARNING use this method only after having called Bloc::performCFComputations method.
662  * \param okAndUseless1 out param contains at the end, the nodes without any collapse.
663  * \param allNodes in/out param. At the end, all the nodes in 'okAndUseless1' are deleted from 'allNodes'.
664  */
665 void Bloc::seekOkAndUseless1(std::vector<Node *>& okAndUseless1, std::set<Node *>& allNodes) const
666 {
667   set<Node *>::iterator iter=allNodes.begin();
668   while(iter!=allNodes.end())
669     {
670       set<Node *>& whereToFind=(*_bwLinks)[*iter];
671       std::set<Node *>::iterator iter2;
672       for(iter2=allNodes.begin();iter2!=allNodes.end();iter2++)
673         if((*iter)!=(*iter2))
674           if(whereToFind.find(*iter2)==whereToFind.end())
675             break;
676       if(iter2!=allNodes.end())
677         iter++;
678       else
679         {
680           okAndUseless1.push_back((*iter));
681           allNodes.erase(iter);
682           iter=allNodes.begin();
683         }
684     }
685 }
686
687 /*!
688  * \b WARNING use this method only after having called Bloc::performCFComputations method.
689  * For params see Bloc::seekOkAndUseless1.
690  */
691 void Bloc::seekUseless2(std::vector<Node *>& useless2, std::set<Node *>& allNodes) const
692 {
693   set<Node *>::iterator iter=allNodes.begin();
694   while(iter!=allNodes.end())
695     {
696       set<Node *>& whereToFind=(*_fwLinks)[*iter];
697       std::set<Node *>::iterator iter2;
698       for(iter2=allNodes.begin();iter2!=allNodes.end();iter2++)
699         if((*iter)!=(*iter2))
700           if(whereToFind.find(*iter2)==whereToFind.end())
701             break;
702       if(iter2!=allNodes.end())
703         {
704           iter++;
705         }
706       else
707         {
708           useless2.push_back((*iter));
709           allNodes.erase(iter);
710           iter=allNodes.begin();
711         }
712     }
713 }
714
715 /*! 
716  * Internal method : Given a succeful path : updates 'fastFinder'
717  */
718 void Bloc::updateWithNewFind(const std::vector<Node *>& path, map<Node *, std::set<Node *> >& fastFinder)
719 {
720   if(path.size()>=3)
721     {
722       vector<Node *>::const_iterator iter=path.begin(); iter++;
723       vector<Node *>::const_iterator iter2=path.end(); iter2-=1;
724       for(;iter!=iter2;iter++)
725         fastFinder[*iter].insert(*(iter+1));
726     }
727 }
728
729 /*! 
730  * Internal method : After all paths have been found, useless CF links are searched
731  */
732 void Bloc::findUselessLinksIn(const std::list< std::vector<Node *> >& res , LinkInfo& info)
733 {
734   unsigned maxSize=0;
735   list< vector<Node *> >::const_iterator whereToPeerAt;
736   for(list< vector<Node *> >::const_iterator iter=res.begin();iter!=res.end();iter++)
737     if((*iter).size()>maxSize)
738       {
739         maxSize=(*iter).size();
740         whereToPeerAt=iter;
741       }
742   //
743   if(maxSize>1)
744     {
745       vector<Node *>::const_iterator iter2=(*whereToPeerAt).begin();
746       map<Node *,bool>::iterator iter4;
747       set<Node *> searcher(iter2+1,(*whereToPeerAt).end());//to boost research
748       for(;iter2!=((*whereToPeerAt).end()-2);iter2++)
749         {
750           map<InGate *,bool>::iterator iter4;
751           map<InGate *,bool>& nexts=(*iter2)->getOutGate()->edMapInGate();
752           for(iter4=nexts.begin();iter4!=nexts.end();iter4++)
753             if((*iter4).first->getNode()!=*(iter2+1))
754               if(searcher.find((*iter4).first->getNode())!=searcher.end())
755                 info.pushUselessCFLink(*iter2,(*iter4).first->getNode());
756           searcher.erase(*iter2);
757         }
758     }
759 }