Salome HOME
[EDF20032] : Algorithm is less strict to support new configuration
[modules/yacs.git] / src / engine / BagPoint.cxx
index 64e0c71cf73234d4d2aef5402e99adfd56e60c92..89bf459008210c85a8566d764cfbf0816e8cedb2 100644 (file)
 #include "Exception.hxx"
 #include "LinkedBlocPoint.hxx"
 #include "ForkBlocPoint.hxx"
+#include "NotSimpleCasePoint.hxx"
+
+#include "Bloc.hxx"
+#include "LinkInfo.hxx"
 
 #include <sstream>
 #include <algorithm>
@@ -31,49 +35,29 @@ BagPoint::BagPoint(const std::list<AbstractPoint *>& nodes, AbstractPoint *fathe
 {
 }
 
-AbstractPoint *BagPoint::getUnique()
+void BagPoint::accept(PointVisitor *pv)
 {
-  if(_nodes.size()!=1)
-    throw YACS::Exception("BagPoint::getUnique : invalid call !");
-  else
+  for(auto it : _nodes)
     {
-      AbstractPoint *ret(*_nodes.begin());
-      if(!ret)
-        throw YACS::Exception("BagPoint::getUnique : Ooops !");
-      return ret;
+      if(!it)
+        throw YACS::Exception("BagPoint::accept : Ooops !");
+      it->accept(pv);
     }
 }
 
-const AbstractPoint *BagPoint::getUnique() const
+AbstractPoint *BagPoint::expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set<Node *>& uncatchedNodes)
 {
-  if(_nodes.size()!=1)
-    throw YACS::Exception("BagPoint::getUnique const : invalid call !");
-  else
-    {
-      AbstractPoint *ret(*_nodes.begin());
-      if(!ret)
-        throw YACS::Exception("BagPoint::getUnique : Ooops !");
-      return ret;
-    }
+  throw YACS::Exception("BagPoint::expandNonSimpleCaseOn : Ooops !");
 }
 
-AbstractPoint *BagPoint::getUniqueAndReleaseIt()
+AbstractPoint *BagPoint::deepCopy(AbstractPoint *father) const
 {
-  AbstractPoint *ret(getUnique());
-  getOutPoint(ret);
+  BagPoint *ret(new BagPoint);
+  ret->deepCopyFrom(*this);
+  ret->setFather(father);
   return ret;
 }
 
-void BagPoint::accept(PointVisitor *pv)
-{
-  if(_nodes.size()!=1)
-    throw YACS::Exception("BagPoint::accept : simplification has failed !");
-  AbstractPoint *ret(*_nodes.begin());
-  if(!ret)
-    throw YACS::Exception("BagPoint::accept : Ooops !");
-  ret->accept(pv);
-}
-
 Node *BagPoint::getFirstNode()
 {
   return getUnique()->getFirstNode();
@@ -191,3 +175,132 @@ void BagPoint::deal2Ter(bool& somethingDone)
       }
 }
 
+void BagPoint::deal2Quatro(bool& somethingDone)
+{
+  somethingDone=false;
+  for(std::list<AbstractPoint *>::iterator it=_nodes.begin();it!=_nodes.end();it++)
+    {
+      if(!(*it)->isNullBeforeNullAfter(this))
+        continue;
+      ForkBlocPoint *try1((*it)->tryAsForkQuatro(this));
+      if(try1)
+        {
+          replaceInMe(try1);
+          somethingDone=true;
+          break;
+        }
+      }
+}
+
+/*!
+ * This method remove 1, 2 or 3 points from this by flagging them as pathological nodes.
+ * By doing so, we hope to simplify enough to have a standart case.
+ */
+void BagPoint::dealNotSimpleCase(bool& somethingDone)
+{
+  somethingDone=false;
+  for(auto it=_nodes.begin();it!=_nodes.end();it++)
+    {
+      std::vector<AbstractPoint *> v{*it};
+      AbstractPoint::TryAsNotSimpleCase((*it)->getFather(),v,_nodes,somethingDone);
+      if(somethingDone)
+        break;
+    }
+  if(somethingDone)
+    return ;
+  //
+  for(auto it=_nodes.cbegin();it!=_nodes.cend();it++)
+    {
+      auto it2(it); it2++;
+      for(;it2!=_nodes.cend();it2++)
+        {
+          std::vector<AbstractPoint *> v{*it,*it2};
+          AbstractPoint::TryAsNotSimpleCase((*it)->getFather(),v,_nodes,somethingDone);
+          if(somethingDone)
+            return;
+        }
+    }
+  if(somethingDone)
+    return ;
+  //
+  for(auto it=_nodes.cbegin();it!=_nodes.cend();it++)
+    {
+      auto it2(it); it2++;
+      for(;it2!=_nodes.cend();it2++)
+        {
+          auto it3(it2); it3++;
+          for(;it3!=_nodes.cend();it3++)
+            {
+              std::vector<AbstractPoint *> v{*it,*it2,*it3};
+              AbstractPoint::TryAsNotSimpleCase((*it)->getFather(),v,_nodes,somethingDone);
+              if(somethingDone)
+                return;
+            }
+        }
+    }
+}
+
+/*!
+ * Append a single pathologicalPt point instance to AbstractPoint instances contained in \a this.
+ * To do that we start to locate in graph dependancy in \a this with ENGINE::Node cannot run in parallel with \a pathologicalPt. These nodes stored in \a nodesBeforeAfter.
+ *
+ * By walking across Points in \a this if a Point has no intersection with \a nodesBeforeAfter this Point is converted to a ForkBlocPoint.
+ */
+void BagPoint::expandNonSimpleCaseOn(AbstractPoint *pathologicalPt)
+{
+  NotSimpleCasePoint *pathologicalPt2(dynamic_cast<NotSimpleCasePoint *>(pathologicalPt));
+  if(!pathologicalPt2)
+    throw YACS::Exception("BagPoint::expandNonSimpleCaseOn : pathologicalPt is expected to be a NotSimpleCasePoint !");
+  std::list<AbstractPoint *> nodes2;
+  std::for_each(_nodes.begin(),_nodes.end(),[&nodes2](AbstractPoint *elt) { if(!dynamic_cast<NotSimpleCasePoint *>(elt)) nodes2.push_back(elt); });
+  if(nodes2.size()!=1)
+    throw YACS::Exception("BagPoint::expandNonSimpleCaseOn : Internal error only one AbstractPoint is expected !");
+  
+  Node *firstNode(pathologicalPt->getFirstNode()),*lastNode(pathologicalPt->getLastNode());
+  //
+  ComposedNode *parent(firstNode->getFather());
+  Bloc *parentc(dynamic_cast<Bloc *>(parent));
+  if(!parentc)
+    throw YACS::Exception("BagPoint::expandNonSimpleCaseOn : internal error, Bloc expected");
+  //
+  std::set<Node *> nodesBefore, nodesAfter;
+  {
+    std::map<Node *, std::set<Node *> > accelStr;
+    LinkInfo info(E_ALL);
+    parentc->findAllNodesStartingFrom<false>(firstNode,nodesBefore,accelStr,info);
+  }
+  {
+    std::map<Node *, std::set<Node *> > accelStr;
+    LinkInfo info(E_ALL);
+    parentc->findAllNodesStartingFrom<true>(lastNode,nodesAfter,accelStr,info);
+  }
+  //
+  std::set<Node *> nodesBeforeAfter(nodesBefore.begin(),nodesBefore.end());
+  nodesBeforeAfter.insert(nodesAfter.begin(),nodesAfter.end());
+  //std::for_each(nodesBeforeAfter.begin(),nodesBeforeAfter.end(),[](Node *elt) { std::cerr << elt->getName() << " "; }); std::cerr << std::endl;
+  //
+  AbstractPoint *onlyOne(*nodes2.begin());
+  AbstractPoint *res(onlyOne->expandNonSimpleCaseOn(pathologicalPt2,nodesBeforeAfter));
+  if(res!=onlyOne)
+    throw YACS::Exception("BagPoint::expandNonSimpleCaseOn : unexpected situation !");// impossible because by construction pathologicalPt cannot be merged to this. If it were possible, algo in simplify would be simply it !
+  {// remove delete pathologicalPt and remove it from this->_nodes
+    std::list<AbstractPoint *> nodes3;
+    std::for_each(_nodes.begin(),_nodes.end(),[&nodes3,pathologicalPt](AbstractPoint *elt) { if(elt!=pathologicalPt) nodes3.push_back(elt); else delete elt; });
+    _nodes = nodes3;
+  }
+}
+
+/*!
+ * All NotSimpleCasePoint instances in this->_nodes are going to be scanned recursively accross this->_nodes.
+ * To do that NotSimpleCasePoint instance are added incrementaly.
+ */
+void BagPoint::expandNonSimpleCase()
+{
+  std::vector<AbstractPoint *> pathologicalPt;
+  std::for_each(_nodes.begin(),_nodes.end(),[&pathologicalPt](AbstractPoint *elt) { if(dynamic_cast<NotSimpleCasePoint *>(elt)) pathologicalPt.push_back(elt); });
+  if(pathologicalPt.empty())
+    throw YACS::Exception("BagPoint::expandNonSimpleCase : Not found any pathological case !");
+  for(auto it : pathologicalPt)
+    this->expandNonSimpleCaseOn(it);
+  
+}