Salome HOME
Addition of redundant CF links tool for evalyfx.
[modules/yacs.git] / src / engine / Bloc.cxx
index 422e3947099d20254774fec16953c5ee051f032c..c91c7617295b77577717288021043a6942ba4824 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2006-2014  CEA/DEN, EDF R&D
+// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 #include "OutputDataStreamPort.hxx"
 #include "ElementaryNode.hxx"
 #include "Visitor.hxx"
+#include "SetOfPoints.hxx"
 
+#include <queue>
 #include <iostream>
+#include <numeric>
 
 //#define _DEVDEBUG_
 #include "YacsTrace.hxx"
@@ -58,7 +61,10 @@ Bloc::Bloc(const Bloc& other, ComposedNode *father, bool editionOnly):StaticDefi
     {
       OutPort* pout = iter2->first;
       InPort* pin = iter2->second;
-      edAddLink(getOutPort(other.getPortName(pout)),getInPort(other.getPortName(pin)));
+      if(&other == getLowestCommonAncestor(pout->getNode(), pin->getNode()))
+      {
+        edAddLink(getOutPort(other.getPortName(pout)),getInPort(other.getPortName(pin)));
+      }
     }
 }
 
@@ -220,6 +226,54 @@ void Bloc::edRemoveChild(Node *node) throw(YACS::Exception)
     }
 }
 
+std::vector< std::list<Node *> > Bloc::splitIntoIndependantGraph() const
+{
+  std::size_t sz(_setOfNode.size());
+  list<Node *>::const_iterator it=_setOfNode.begin();
+  for(;it!=_setOfNode.end();it++)
+    (*it)->_colour=White;
+  it=_setOfNode.begin();
+  std::vector< list<Node *> > ret;
+  while(it!=_setOfNode.end())
+    {
+      Node *start(*it); start->_colour=Grey;
+      ret.push_back(list<Node *>());
+      list<Node *>& ll(ret.back());
+      std::queue<Node *> fifo; fifo.push(start);
+      while(!fifo.empty())
+        {
+          Node *cur(fifo.front()); fifo.pop();
+          ll.push_back(cur);
+          //
+          OutGate *og(cur->getOutGate());
+          list<InGate *> og2(og->edSetInGate());
+          for(list<InGate *>::const_iterator it2=og2.begin();it2!=og2.end();it2++)
+            {
+              Node *cur2((*it2)->getNode());
+              if(cur2->_colour==White)
+                {
+                  cur2->_colour=Grey;
+                  fifo.push(cur2);
+                }
+            }
+          //
+          InGate *ig(cur->getInGate());
+          list<OutGate *> bl(ig->getBackLinks());
+          for(list<OutGate *>::const_iterator it3=bl.begin();it3!=bl.end();it3++)
+            {
+              Node *cur3((*it3)->getNode());
+              if(cur3->_colour==White)
+                {
+                  cur3->_colour=Grey;
+                  fifo.push(cur3);
+                }
+            }
+        }
+      for(it=_setOfNode.begin();it!=_setOfNode.end() && (*it)->_colour!=White;it++);
+    }
+  return ret;
+}
+
 Node *Bloc::getChildByShortName(const std::string& name) const throw(YACS::Exception)
 {
   for (list<Node *>::const_iterator iter = _setOfNode.begin(); iter != _setOfNode.end(); iter++)
@@ -229,10 +283,6 @@ Node *Bloc::getChildByShortName(const std::string& name) const throw(YACS::Excep
   throw Exception(what);
 }
 
-void Bloc::selectRunnableTasks(std::vector<Task *>& tasks)
-{
-}
-
 bool Bloc::areAllSubNodesDone() const
 {
   for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
@@ -269,8 +319,8 @@ bool Bloc::isNameAlreadyUsed(const std::string& name) const
 bool insertNodeChildrenInSet(Node *node, std::set<Node *>& nodeSet)
 {
   bool verdict=true;
-  set<Node *> outNodes=node->getOutNodes();
-  for (set<Node *>::iterator iter=outNodes.begin();iter!=outNodes.end(); iter++)
+  list<Node *> outNodes=node->getOutNodes();
+  for (list<Node *>::iterator iter=outNodes.begin();iter!=outNodes.end(); iter++)
     {
       verdict=(nodeSet.insert(*iter)).second;
       if (verdict) verdict = insertNodeChildrenInSet((*iter),nodeSet);
@@ -300,8 +350,8 @@ std::vector< std::pair<OutGate *, InGate *> > Bloc::getSetOfInternalCFLinks() co
   vector< pair<OutGate *, InGate *> > ret;
   for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
     {
-      set<InGate *> outCFLinksOfCurNode=(*iter)->_outGate.edSetInGate();
-      for(set<InGate *>::iterator iter2=outCFLinksOfCurNode.begin();iter2!=outCFLinksOfCurNode.end();iter2++)
+      list<InGate *> outCFLinksOfCurNode=(*iter)->_outGate.edSetInGate();
+      for(list<InGate *>::iterator iter2=outCFLinksOfCurNode.begin();iter2!=outCFLinksOfCurNode.end();iter2++)
         ret.push_back(pair<OutGate *, InGate *>(&(*iter)->_outGate,*iter2));
     }
   return ret;
@@ -353,7 +403,7 @@ YACS::Event Bloc::updateStateOnFinishedEventFrom(Node *node)
  * \param node : node that has emitted the event
  * \return the event to notify to bloc's father
  */
-YACS::Event Bloc::updateStateOnFailedEventFrom(Node *node)
+YACS::Event Bloc::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
 {
   node->exForwardFailed();
   if(areAllSubNodesFinished())
@@ -370,26 +420,26 @@ YACS::Event Bloc::updateStateOnFailedEventFrom(Node *node)
 
 void Bloc::writeDot(std::ostream &os) const
 {
-    os << "  subgraph cluster_" << getId() << "  {\n" ;
-    list<Node *>nodes=getChildren();
-    for(list<Node *>::const_iterator iter=nodes.begin();iter!=nodes.end();iter++)
+  os << "  subgraph cluster_" << getId() << "  {\n" ;
+  list<Node *>nodes=getChildren();
+  for(list<Node *>::const_iterator iter=nodes.begin();iter!=nodes.end();iter++)
     {
-        (*iter)->writeDot(os);
-        string p=(*iter)->getId();
-        //not connected node
-        if((*iter)->_inGate._backLinks.size() == 0) os << getId() << " -> " << p << ";\n";
-        set<Node *>outnodes = (*iter)->getOutNodes();
-        for(set<Node *>::const_iterator itout=outnodes.begin();itout!=outnodes.end();itout++)
+      (*iter)->writeDot(os);
+      string p=(*iter)->getId();
+      //not connected node
+      if((*iter)->_inGate._backLinks.size() == 0) os << getId() << " -> " << p << ";\n";
+      list<Node *>outnodes = (*iter)->getOutNodes();
+      for(list<Node *>::const_iterator itout=outnodes.begin();itout!=outnodes.end();itout++)
         {
-            os << p << " -> " << (*itout)->getId() << ";\n";
+          os << p << " -> " << (*itout)->getId() << ";\n";
         }
     }
-    os << "}\n" ;
-    os << getId() << "[fillcolor=\"" ;
-    YACS::StatesForNode state=getEffectiveState();
-    os << getColorState(state);
-    os << "\" label=\"" << "Bloc:" ;
-    os << getQualifiedName() <<"\"];\n";
+  os << "}\n" ;
+  os << getId() << "[fillcolor=\"" ;
+  YACS::StatesForNode state=getEffectiveState();
+  os << getColorState(state);
+  os << "\" label=\"" << "Bloc:" ;
+  os << getQualifiedName() <<"\"];\n";
 }
 
 void Bloc::accept(Visitor* visitor)
@@ -398,20 +448,36 @@ void Bloc::accept(Visitor* visitor)
 }
 
 /*!
- * Updates mutable structures _fwLinks and _bwLinks with the result of computation (CPU consuming method).
- * _fwLinks is a map with a Node* as key and a set<Node*> as value. The set gives
- * all nodes that are forwardly connected to the key node 
- * _bwLinks is a map for backward dependencies
- * The method is : for all CF link (n1->n2) 
- * add n2 and _fwLinks[n2] in forward dependencies of n1 and _bwLinks[n1]
- * add n1 and _bwLinks[n1] in backward dependencies of n2 and _fwLinks[n2]
- * For useless links
- * If a node is already in a forward dependency when adding and the direct link
- * already exists so it's a useless link (see the code !)
+ * Returns the max level of parallelism is this. The max of parallelism is equal to the sum of the max parallelism level
+ * for all concurrent branches in \a this.
  */
-void Bloc::performCFComputations(LinkInfo& info) const
+int Bloc::getMaxLevelOfParallelism() const
+{
+  std::vector< std::list<Node *> > r(splitIntoIndependantGraph());
+  int ret(0);
+  for(std::vector< std::list<Node *> >::const_iterator it=r.begin();it!=r.end();it++)
+    {
+      SetOfPoints sop(*it);
+      sop.simplify();
+      ret+=sop.getMaxLevelOfParallelism();
+    }
+  return ret;
+}
+
+void Bloc::removeRecursivelyRedundantCL()
+{
+  StaticDefinedComposedNode::removeRecursivelyRedundantCL();
+  LinkInfo info(I_CF_USELESS);
+  initComputation();
+  performCFComputationsOnlyOneLevel(info);
+  std::set< std::pair<Node *, Node *> > linksToKill(info.getInfoUselessLinks());
+  for(std::set< std::pair<Node *, Node *> >::const_iterator it=linksToKill.begin();it!=linksToKill.end();it++)
+    edRemoveCFLink((*it).first,(*it).second);
+  destructCFComputations(info);
+}
+
+void Bloc::performCFComputationsOnlyOneLevel(LinkInfo& info) const
 {
-  StaticDefinedComposedNode::performCFComputations(info);
   delete _fwLinks;//Normally useless
   delete _bwLinks;//Normally useless
   _fwLinks=new map<Node *,set<Node *> >;
@@ -423,8 +489,8 @@ void Bloc::performCFComputations(LinkInfo& info) const
   for(list<Node *>::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++)
     {
       Node* n1=*iter;
-      std::set<InGate *> ingates=n1->getOutGate()->edSetInGate();
-      for(std::set<InGate *>::const_iterator it2=ingates.begin();it2!=ingates.end();it2++)
+      std::list<InGate *> ingates=n1->getOutGate()->edSetInGate();
+      for(std::list<InGate *>::const_iterator it2=ingates.begin();it2!=ingates.end();it2++)
         {
           //CF link : n1 -> (*it2)->getNode()
           Node* n2=(*it2)->getNode();
@@ -482,6 +548,24 @@ void Bloc::performCFComputations(LinkInfo& info) const
     }
 }
 
+/*!
+ * Updates mutable structures _fwLinks and _bwLinks with the result of computation (CPU consuming method).
+ * _fwLinks is a map with a Node* as key and a set<Node*> as value. The set gives
+ * all nodes that are forwardly connected to the key node 
+ * _bwLinks is a map for backward dependencies
+ * The method is : for all CF link (n1->n2) 
+ * add n2 and _fwLinks[n2] in forward dependencies of n1 and _bwLinks[n1]
+ * add n1 and _bwLinks[n1] in backward dependencies of n2 and _fwLinks[n2]
+ * For useless links
+ * If a node is already in a forward dependency when adding and the direct link
+ * already exists so it's a useless link (see the code !)
+ */
+void Bloc::performCFComputations(LinkInfo& info) const
+{
+  StaticDefinedComposedNode::performCFComputations(info);
+  performCFComputationsOnlyOneLevel(info);
+}
+
 void Bloc::destructCFComputations(LinkInfo& info) const
 {
   StaticDefinedComposedNode::destructCFComputations(info);
@@ -789,9 +873,8 @@ void Bloc::findUselessLinksIn(const std::list< std::vector<Node *> >& res , Link
       set<Node *> searcher(iter2+1,(*whereToPeerAt).end());//to boost research
       for(;iter2!=((*whereToPeerAt).end()-2);iter2++)
         {
-          map<InGate *,bool>::iterator iter4;
-          map<InGate *,bool>& nexts=(*iter2)->getOutGate()->edMapInGate();
-          for(iter4=nexts.begin();iter4!=nexts.end();iter4++)
+          list< pair<InGate *,bool> >& nexts=(*iter2)->getOutGate()->edMapInGate();
+          for(list< pair<InGate *,bool> >::iterator iter4=nexts.begin();iter4!=nexts.end();iter4++)
             if((*iter4).first->getNode()!=*(iter2+1))
               if(searcher.find((*iter4).first->getNode())!=searcher.end())
                 info.pushUselessCFLink(*iter2,(*iter4).first->getNode());