Salome HOME
Copyright update 2022
[modules/yacs.git] / src / engine / BagPoint.cxx
1 // Copyright (C) 2015-2022  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 "BagPoint.hxx"
21 #include "Exception.hxx"
22 #include "LinkedBlocPoint.hxx"
23 #include "ForkBlocPoint.hxx"
24 #include "NotSimpleCasePoint.hxx"
25
26 #include "Bloc.hxx"
27 #include "LinkInfo.hxx"
28
29 #include <sstream>
30 #include <algorithm>
31
32 using namespace YACS::ENGINE;
33
34 BagPoint::BagPoint(const std::list<AbstractPoint *>& nodes, AbstractPoint *father):BlocPoint(nodes,father)
35 {
36 }
37
38 void BagPoint::accept(PointVisitor *pv)
39 {
40   for(auto it : _nodes)
41     {
42       if(!it)
43         throw YACS::Exception("BagPoint::accept : Ooops !");
44       it->accept(pv);
45     }
46 }
47
48 AbstractPoint *BagPoint::expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set<Node *>& uncatchedNodes)
49 {
50   throw YACS::Exception("BagPoint::expandNonSimpleCaseOn : Ooops !");
51 }
52
53 AbstractPoint *BagPoint::deepCopy(AbstractPoint *father) const
54 {
55   BagPoint *ret(new BagPoint);
56   ret->deepCopyFrom(*this);
57   ret->setFather(father);
58   return ret;
59 }
60
61 Node *BagPoint::getFirstNode()
62 {
63   return getUnique()->getFirstNode();
64 }
65
66 Node *BagPoint::getLastNode()
67 {
68   return getUnique()->getLastNode();
69 }
70
71 int BagPoint::getMaxLevelOfParallelism() const
72 {
73   return getUnique()->getMaxLevelOfParallelism();
74 }
75
76 void BagPoint::getWeightRegardingDPL(ComplexWeight *weight)
77 {
78   getUnique()->getWeightRegardingDPL(weight);
79 }
80
81 void BagPoint::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap) const
82 {
83   getUnique()->partitionRegardingDPL(pd,zeMap);
84 }
85
86 std::string BagPoint::getRepr() const
87 {
88   std::ostringstream oss;
89   for(std::list<AbstractPoint *>::const_iterator it=_nodes.begin();it!=_nodes.end();it++)
90     oss << (*it)->getRepr() << " - ";
91   return oss.str();
92 }
93
94 #include <iostream>
95
96 void BagPoint::replaceInMe(BlocPoint *aSet)
97 {
98   const std::list<AbstractPoint *>& pts(aSet->getListOfPoints());
99   for(std::list<AbstractPoint *>::const_iterator it0=pts.begin();it0!=pts.end();it0++)
100     {
101       std::list<AbstractPoint *>::iterator it1(std::find(_nodes.begin(),_nodes.end(),*it0));
102       if(it1==_nodes.end())
103         throw Exception("SetOfPoints::replaceInMe : internal error !");
104       _nodes.erase(it1);
105     }
106   _nodes.push_back(aSet);
107 }
108
109 void BagPoint::deal1(bool& somethingDone)
110 {
111   somethingDone=false;
112   for(std::list<AbstractPoint *>::iterator it=_nodes.begin();it!=_nodes.end();it++)
113     {
114       if(!(*it)->isSimplyLinkedBeforeAfter(this))
115         if(!(*it)->isSimplyLinkedAfterNullBefore(this) && !(*it)->isSimplyLinkedBeforeNullAfter(this))
116            continue;
117       LinkedBlocPoint *try0((*it)->tryAsLink(this));
118       if(try0)
119         {
120           replaceInMe(try0);
121           somethingDone=true;
122           break;
123         }
124     }
125 }
126
127 void BagPoint::deal2(bool& somethingDone)
128 {
129   somethingDone=false;
130   for(std::list<AbstractPoint *>::iterator it=_nodes.begin();it!=_nodes.end();it++)
131     {
132       if(!(*it)->isSimplyLinkedBeforeAfter(this))
133         continue;
134       ForkBlocPoint *try1((*it)->tryAsFork(this));
135       if(try1)
136         {
137           replaceInMe(try1);
138           somethingDone=true;
139           break;
140         }
141     }
142 }
143
144 void BagPoint::deal2Bis(bool& somethingDone)
145 {
146   somethingDone=false;
147   for(std::list<AbstractPoint *>::iterator it=_nodes.begin();it!=_nodes.end();it++)
148     {
149       if(!(*it)->isSimplyLinkedAfterNullBefore(this))
150         continue;
151       ForkBlocPoint *try1((*it)->tryAsForkBis(this));
152       if(try1)
153         {
154           replaceInMe(try1);
155           somethingDone=true;
156           break;
157         }
158     }
159 }
160
161 void BagPoint::deal2Ter(bool& somethingDone)
162 {
163   somethingDone=false;
164   for(std::list<AbstractPoint *>::iterator it=_nodes.begin();it!=_nodes.end();it++)
165     {
166       if(!(*it)->isSimplyLinkedBeforeNullAfter(this))
167         continue;
168       ForkBlocPoint *try1((*it)->tryAsForkTer(this));
169       if(try1)
170         {
171           replaceInMe(try1);
172           somethingDone=true;
173           break;
174         }
175       }
176 }
177
178 void BagPoint::deal2Quatro(bool& somethingDone)
179 {
180   somethingDone=false;
181   for(std::list<AbstractPoint *>::iterator it=_nodes.begin();it!=_nodes.end();it++)
182     {
183       if(!(*it)->isNullBeforeNullAfter(this))
184         continue;
185       ForkBlocPoint *try1((*it)->tryAsForkQuatro(this));
186       if(try1)
187         {
188           replaceInMe(try1);
189           somethingDone=true;
190           break;
191         }
192       }
193 }
194
195 /*!
196  * This method remove 1, 2 or 3 points from this by flagging them as pathological nodes.
197  * By doing so, we hope to simplify enough to have a standart case.
198  */
199 void BagPoint::dealNotSimpleCase(bool& somethingDone)
200 {
201   somethingDone=false;
202   for(auto it=_nodes.begin();it!=_nodes.end();it++)
203     {
204       std::vector<AbstractPoint *> v{*it};
205       AbstractPoint::TryAsNotSimpleCase((*it)->getFather(),v,_nodes,somethingDone);
206       if(somethingDone)
207         break;
208     }
209   if(somethingDone)
210     return ;
211   //
212   for(auto it=_nodes.cbegin();it!=_nodes.cend();it++)
213     {
214       auto it2(it); it2++;
215       for(;it2!=_nodes.cend();it2++)
216         {
217           std::vector<AbstractPoint *> v{*it,*it2};
218           AbstractPoint::TryAsNotSimpleCase((*it)->getFather(),v,_nodes,somethingDone);
219           if(somethingDone)
220             return;
221         }
222     }
223   if(somethingDone)
224     return ;
225   //
226   for(auto it=_nodes.cbegin();it!=_nodes.cend();it++)
227     {
228       auto it2(it); it2++;
229       for(;it2!=_nodes.cend();it2++)
230         {
231           auto it3(it2); it3++;
232           for(;it3!=_nodes.cend();it3++)
233             {
234               std::vector<AbstractPoint *> v{*it,*it2,*it3};
235               AbstractPoint::TryAsNotSimpleCase((*it)->getFather(),v,_nodes,somethingDone);
236               if(somethingDone)
237                 return;
238             }
239         }
240     }
241 }
242
243 /*!
244  * Append a single pathologicalPt point instance to AbstractPoint instances contained in \a this.
245  * 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.
246  *
247  * By walking across Points in \a this if a Point has no intersection with \a nodesBeforeAfter this Point is converted to a ForkBlocPoint.
248  */
249 void BagPoint::expandNonSimpleCaseOn(AbstractPoint *pathologicalPt)
250 {
251   NotSimpleCasePoint *pathologicalPt2(dynamic_cast<NotSimpleCasePoint *>(pathologicalPt));
252   if(!pathologicalPt2)
253     throw YACS::Exception("BagPoint::expandNonSimpleCaseOn : pathologicalPt is expected to be a NotSimpleCasePoint !");
254   std::list<AbstractPoint *> nodes2;
255   std::for_each(_nodes.begin(),_nodes.end(),[&nodes2](AbstractPoint *elt) { if(!dynamic_cast<NotSimpleCasePoint *>(elt)) nodes2.push_back(elt); });
256   if(nodes2.size()!=1)
257     throw YACS::Exception("BagPoint::expandNonSimpleCaseOn : Internal error only one AbstractPoint is expected !");
258   
259   Node *firstNode(pathologicalPt->getFirstNode()),*lastNode(pathologicalPt->getLastNode());
260   //
261   ComposedNode *parent(firstNode->getFather());
262   Bloc *parentc(dynamic_cast<Bloc *>(parent));
263   if(!parentc)
264     throw YACS::Exception("BagPoint::expandNonSimpleCaseOn : internal error, Bloc expected");
265   //
266   std::set<Node *> nodesBefore, nodesAfter;
267   {
268     std::map<Node *, std::set<Node *> > accelStr;
269     LinkInfo info(E_ALL);
270     parentc->findAllNodesStartingFrom<false>(firstNode,nodesBefore,accelStr,info);
271   }
272   {
273     std::map<Node *, std::set<Node *> > accelStr;
274     LinkInfo info(E_ALL);
275     parentc->findAllNodesStartingFrom<true>(lastNode,nodesAfter,accelStr,info);
276   }
277   //
278   std::set<Node *> nodesBeforeAfter(nodesBefore.begin(),nodesBefore.end());
279   nodesBeforeAfter.insert(nodesAfter.begin(),nodesAfter.end());
280   //std::for_each(nodesBeforeAfter.begin(),nodesBeforeAfter.end(),[](Node *elt) { std::cerr << elt->getName() << " "; }); std::cerr << std::endl;
281   //
282   AbstractPoint *onlyOne(*nodes2.begin());
283   AbstractPoint *res(onlyOne->expandNonSimpleCaseOn(pathologicalPt2,nodesBeforeAfter));
284   if(res!=onlyOne)
285     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 !
286   {// remove delete pathologicalPt and remove it from this->_nodes
287     std::list<AbstractPoint *> nodes3;
288     std::for_each(_nodes.begin(),_nodes.end(),[&nodes3,pathologicalPt](AbstractPoint *elt) { if(elt!=pathologicalPt) nodes3.push_back(elt); else delete elt; });
289     _nodes = nodes3;
290   }
291 }
292
293 /*!
294  * All NotSimpleCasePoint instances in this->_nodes are going to be scanned recursively accross this->_nodes.
295  * To do that NotSimpleCasePoint instance are added incrementaly.
296  */
297 void BagPoint::expandNonSimpleCase()
298 {
299   std::vector<AbstractPoint *> pathologicalPt;
300   std::for_each(_nodes.begin(),_nodes.end(),[&pathologicalPt](AbstractPoint *elt) { if(dynamic_cast<NotSimpleCasePoint *>(elt)) pathologicalPt.push_back(elt); });
301   if(pathologicalPt.empty())
302     throw YACS::Exception("BagPoint::expandNonSimpleCase : Not found any pathological case !");
303   for(auto it : pathologicalPt)
304     this->expandNonSimpleCaseOn(it);
305   
306 }