1 // Copyright (C) 2015-2019 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "AbstractPoint.hxx"
21 #include "LinkedBlocPoint.hxx"
22 #include "ForkBlocPoint.hxx"
23 #include "NotSimpleCasePoint.hxx"
24 #include "SetOfPoints.hxx"
25 #include "BagPoint.hxx"
26 #include "ElementaryPoint.hxx"
32 using namespace YACS::ENGINE;
34 AbstractPoint::~AbstractPoint()
38 AbstractPoint *AbstractPoint::getGodFather()
43 return _father->getGodFather();
46 bool AbstractPoint::isBegin()
48 Node *beg(getFirstNode());
49 InGate *ing(beg->getInGate());
50 return ing->getBackLinks().empty();
53 bool AbstractPoint::isLast()
55 Node *endd(getLastNode());
56 OutGate *oug(endd->getOutGate());
57 return oug->edSetInGate().empty();
60 bool AbstractPoint::isSimplyLinkedBeforeAfter(BlocPoint *sop)
62 Node *beg(getFirstNode()),*endd(getLastNode());
63 return isSimplyLinkedBefore(sop,beg) && isSimplyLinkedAfter(sop,endd);
66 bool AbstractPoint::isSimplyLinkedAfterNullBefore(BlocPoint *sop)
68 Node *beg(getFirstNode()),*endd(getLastNode());
69 return IsNoLinksBefore(beg) && isSimplyLinkedAfter(sop,endd);
72 bool AbstractPoint::isSimplyLinkedBeforeNullAfter(BlocPoint *sop)
74 Node *beg(getFirstNode()),*endd(getLastNode());
75 return IsNoLinksAfter(endd) && isSimplyLinkedBefore(sop,beg);
78 bool AbstractPoint::isNullBeforeNullAfter(BlocPoint *sop)
80 Node *beg(getFirstNode()),*endd(getLastNode());
81 return IsNoLinksBefore(beg) && IsNoLinksAfter(endd);
85 * precondition : isSimplyLinkedBeforeAfter must return true on \a this.
87 LinkedBlocPoint *AbstractPoint::tryAsLink(BlocPoint *sop)
89 Node *bb(getFirstNode()),*ee(getLastNode());
90 std::list<AbstractPoint *> l; l.push_back(this);
91 AbstractPoint *cur2(0);
93 cur2=sop->getNodeB4(bb);
96 if(dynamic_cast<NotSimpleCasePoint *>(cur2))
98 Node *cur3(cur2->getFirstNode());
99 if(cur2->isSimplyLinkedBeforeAfter(sop))
102 cur2=sop->getNodeB4(cur3);
105 else if(IsGatherB4Ext(cur3) && isSimplyLinkedAfter(sop,cur2->getLastNode()))
114 cur2=sop->getNodeAfter(ee);
117 if(dynamic_cast<NotSimpleCasePoint *>(cur2))
119 Node *cur3(cur2->getLastNode());
120 if(cur2->isSimplyLinkedBeforeAfter(sop))
123 cur2=sop->getNodeAfter(cur3);
126 else if(IsScatterAfterExt(cur3) && isSimplyLinkedBefore(sop,cur2->getFirstNode()))
136 return new LinkedBlocPoint(l,getFather());
143 * precondition : isSimplyLinkedBeforeAfter must return true on \a this.
145 ForkBlocPoint *AbstractPoint::tryAsFork(BlocPoint *sop)
147 Node *bb(GetNodeB4(getFirstNode())),*ee(GetNodeAfter(getLastNode()));
148 AbstractPoint *bb2(sop->findPointWithNode(bb)),*ee2(sop->findPointWithNode(ee));
150 const std::list<AbstractPoint *>& lp(sop->getListOfPoints());
151 std::list<AbstractPoint *> l; l.push_back(this);
152 for(std::list<AbstractPoint *>::const_iterator it=lp.begin();it!=lp.end();it++)
156 if(dynamic_cast<NotSimpleCasePoint *>(*it))
158 Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode());
159 if(!IsSimplyLinkedBeforeExt(curFirst) || !IsSimplyLinkedAfterExt(curEnd))
161 Node *curbb(GetNodeB4(curFirst)),*curee(GetNodeAfter(curEnd));
162 AbstractPoint *bb3(sop->findPointWithNode(curbb)),*ee3(sop->findPointWithNode(curee));
163 if(bb2==bb3 && ee2==ee3)
168 return new ForkBlocPoint(l,getFather());
174 ForkBlocPoint *AbstractPoint::tryAsForkBis(BlocPoint *sop)
176 Node *bb(GetNodeB4(getFirstNode())),*ee(GetNodeAfter(getLastNode()));
177 AbstractPoint *ee2(sop->findPointWithNode(ee));
179 const std::list<AbstractPoint *>& lp(sop->getListOfPoints());
180 std::list<AbstractPoint *> l; l.push_back(this);
181 for(std::list<AbstractPoint *>::const_iterator it=lp.begin();it!=lp.end();it++)
185 if(dynamic_cast<NotSimpleCasePoint *>(*it))
187 Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode());
188 if(!IsNoLinksBefore(curFirst) || !IsSimplyLinkedAfterExt(curEnd))
190 Node *curee(GetNodeAfter(curEnd));
191 AbstractPoint *ee3(sop->findPointWithNode(curee));
197 return new ForkBlocPoint(l,getFather());
203 ForkBlocPoint *AbstractPoint::tryAsForkTer(BlocPoint *sop)
205 Node *bb(GetNodeB4(getFirstNode())),*ee(GetNodeAfter(getLastNode()));
206 AbstractPoint *bb2(sop->findPointWithNode(bb));
208 const std::list<AbstractPoint *>& lp(sop->getListOfPoints());
209 std::list<AbstractPoint *> l; l.push_back(this);
210 for(std::list<AbstractPoint *>::const_iterator it=lp.begin();it!=lp.end();it++)
214 if(dynamic_cast<NotSimpleCasePoint *>(*it))
216 Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode());
217 if(!IsSimplyLinkedBeforeExt(curFirst) || !IsNoLinksAfter(curEnd))
219 Node *curbb(GetNodeB4(curFirst));
220 AbstractPoint *bb3(sop->findPointWithNode(curbb));
226 return new ForkBlocPoint(l,getFather());
232 ForkBlocPoint *AbstractPoint::tryAsForkQuatro(BlocPoint *sop)
234 Node *bb(GetNodeB4(getFirstNode())),*ee(GetNodeAfter(getLastNode()));
235 AbstractPoint *bb2(sop->findPointWithNode(bb));
237 const std::list<AbstractPoint *>& lp(sop->getListOfPoints());
238 std::list<AbstractPoint *> l; l.push_back(this);
239 for(std::list<AbstractPoint *>::const_iterator it=lp.begin();it!=lp.end();it++)
243 if(dynamic_cast<NotSimpleCasePoint *>(*it))
245 Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode());
246 if(!IsNoLinksBefore(curFirst) || !IsNoLinksAfter(curEnd))
248 Node *curbb(GetNodeB4(curFirst));
249 AbstractPoint *bb3(sop->findPointWithNode(curbb));
255 return new ForkBlocPoint(l,getFather());
263 class Visitor1 : public YACS::ENGINE::PointVisitor
266 Visitor1(std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *m):_m(m) { }
267 void beginForkBlocPoint(ForkBlocPoint *pt) { }
268 void endForkBlocPoint(ForkBlocPoint *pt) { }
269 void beginLinkedBlocPoint(LinkedBlocPoint *pt) { }
270 void endLinkedBlocPoint(LinkedBlocPoint *pt) { }
271 void beginElementaryPoint(ElementaryPoint *pt)
273 std::string nodeName(pt->getNodeName());
274 auto it(_m->find(nodeName));
277 (*_m)[nodeName] = std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> >(pt,pt->getNode(),std::make_shared<Bloc>(nodeName));
280 void endElementaryPoint(ElementaryPoint *pt) { }
281 void beginNotSimpleCasePoint(NotSimpleCasePoint *pt) { }
282 void endNotSimpleCasePoint(NotSimpleCasePoint *pt) { }
284 std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *_m;
288 * Feed m with all ElementaryPoints inside \a ptToBeRewired.
290 void AbstractPoint::FeedData(AbstractPoint *ptToBeRewired, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *m)
293 ptToBeRewired->accept(&vis);
297 * Feed m with all ElementaryPoints inside \a ptsToBeRewired.
299 void AbstractPoint::FeedData(const std::list<AbstractPoint *>& ptsToBeRewired, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *m)
301 for(auto it : ptsToBeRewired)
305 bool containsPtsToKill(const std::vector<AbstractPoint *>& ptsToKill, Node *node)
307 for(auto it : ptsToKill)
308 if(it->contains(node))
314 * This method go throw all ElementaryPoints of \a m.
315 * For each ElementaryPoint change the Node instance underneath. And then create links between those new Node by excluding all links going whose destination :
316 * - is inside \a ptToKill
317 * - is not refered by \a m
319 * CF links of old nodes are NOT touched for unrewire phase.
320 * Typically all ElementaryPoints inside \a ptToKill are NOT into \a m.
322 void AbstractPoint::Rewire(const std::vector<AbstractPoint *>& ptsToKill, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *m)
326 ElementaryPoint *pt(std::get<0>(it.second));
327 Node *node(std::get<1>(it.second));
328 auto newNode(std::get<2>(it.second).get());
329 pt->setNode(newNode);
333 ElementaryPoint *pt(std::get<0>(it.second));
334 Node *node(std::get<1>(it.second));
335 auto newNode(std::get<2>(it.second).get());
336 if(containsPtsToKill(ptsToKill,newNode))
338 for(auto it2 : node->getOutGate()->edSetInGate())
340 Node *nodeFwd(it2->getNode());
341 std::string nodeFwdName(nodeFwd->getName());
342 auto it3(m->find(nodeFwdName));
345 Node *nodeFwdNew = std::get<2>(it3->second).get();
346 if(!containsPtsToKill(ptsToKill,newNode))
348 newNode->getOutGate()->edAddInGate(nodeFwdNew->getInGate());
351 // node after nodeFwd is not in m fall into \a ptToKill
355 // node after nodeFwd is not in m. Typically because nodeFwd has not been put in m
356 // concretely : do not link incoming links to Node * inside ptToKill
362 * Unrewire consists into replacing newly created nodes into old one in ElementaryPoints contained in m.
363 * As CF links of old ENGINE::Node * has not be touched the CF graph is the same.
365 void AbstractPoint::UnRewire(std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > >& m)
369 ElementaryPoint *pt(std::get<0>(it.second));
370 Node *node(std::get<1>(it.second));
375 void AbstractPoint::Display(std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > *m)
379 ElementaryPoint *pt(std::get<0>(it.second));
380 auto newNode(pt->getNode());
381 for(auto it2 : newNode->getOutGate()->edSetInGate())
383 std::cerr << pt->getNodeName() << " -> " << it2->getNode()->getName() << " " << newNode->typeName() << std::endl;
389 * This methods tries to deal with \a sop that can t be considered as a composite of Link, Fork.
391 * Do do so, this methods tries to exclude \a this from \a sop and then analyze if the graph can be decomposited into Links and Forks. If yes \a somethingDone is set to true and \a nodes is updated in consequence.
393 * If the algorithm fails \a nodes are let untouched and \a somethingDone is let false.
396 void AbstractPoint::TryAsNotSimpleCase(AbstractPoint *father, const std::vector<AbstractPoint *>& ptsToKill, std::list<AbstractPoint *>& nodes, bool& somethingDone)
398 std::list<AbstractPoint *> lp2;
401 if(std::find(ptsToKill.cbegin(),ptsToKill.cend(),it)==ptsToKill.cend())
402 lp2.push_back(it->deepCopy(nullptr));
404 BagPoint *tmp(new BagPoint(lp2,nullptr));
407 SetOfPoints sopTest(tmp);
408 std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr<Bloc> > > m;
410 Rewire(ptsToKill,&m);
413 sopTest.basicSimplify();
415 catch(YACS::Exception& ex)
416 {// By removing elements in ptsToKill from this impossible to have a classical case -> un rewire to rollback nodes state
420 AbstractPoint *pt(sopTest.getUniqueAndReleaseIt());
421 pt->setFather(father);
424 if(std::find(ptsToKill.cbegin(),ptsToKill.cend(),it)==ptsToKill.cend())
428 for(auto it : ptsToKill)
430 std::list<AbstractPoint *> l; l.push_back(it);
431 nodes.push_back( new NotSimpleCasePoint(l,father) );
433 somethingDone = true;
436 bool AbstractPoint::IsGatherB4Ext(Node *node)
438 InGate *ing(node->getInGate());
439 return ing->getBackLinks().size()!=1;
442 bool AbstractPoint::isSimplyLinkedAfter(BlocPoint *sop, Node *node)
444 OutGate *oug(node->getOutGate());
445 std::list<InGate *> ings(oug->edSetInGate());
450 AbstractPoint *dummy=0;
451 return IsCommonDirectSonOf(sop,ings,dummy);
454 bool AbstractPoint::IsSimplyLinkedAfterExt(Node *node)
456 OutGate *oug(node->getOutGate());
457 return oug->edSetInGate().size()<=1;
460 bool AbstractPoint::IsScatterAfterExt(Node *node)
462 OutGate *oug(node->getOutGate());
463 return oug->edSetInGate().size()!=1;
466 bool AbstractPoint::isSimplyLinkedBefore(BlocPoint *sop, Node *node)
468 InGate *ing(node->getInGate());
469 std::list<OutGate *> outgs(ing->getBackLinks());
474 AbstractPoint *dummy=0;
475 return IsCommonDirectSonOf(sop,outgs,dummy);
478 bool AbstractPoint::IsSimplyLinkedBeforeExt(Node *node)
480 InGate *ing(node->getInGate());
481 return ing->getBackLinks().size()<=1;
484 bool AbstractPoint::IsNoLinksBefore(Node *node)
486 InGate *ing(node->getInGate());
487 return ing->getBackLinks().size()==0;
490 bool AbstractPoint::IsNoLinksAfter(Node *node)
492 OutGate *oug(node->getOutGate());
493 return oug->edSetInGate().size()==0;
496 Node *AbstractPoint::GetNodeB4(Node *node)
498 InGate *ing(node->getInGate());
499 std::list<OutGate *> bl(ing->getBackLinks());
501 throw Exception("AbstractPoint::GetNodeB4 : precond not OK !");
504 return bl.front()->getNode();
507 Node *AbstractPoint::GetNodeAfter(Node *node)
509 OutGate *oug(node->getOutGate());
510 std::list<InGate *> fl(oug->edSetInGate());
512 throw Exception("AbstractPoint::GetNodeAfter : precond not OK !");
515 return (*fl.begin())->getNode();
518 AbstractPoint *AbstractPoint::GetDirectSonOf(AbstractPoint *refFather, AbstractPoint *sonOrLittleSon)
521 throw YACS::Exception("AbstractPoint::GetDirectSonOf : sonOrLittleSon is null !");
522 AbstractPoint *curFath(sonOrLittleSon->getFather()),*cur(sonOrLittleSon);
523 while(curFath && curFath!=refFather)
526 curFath=cur->getFather();
529 throw YACS::Exception("AbstractPoint::GetDirectSonOf : not in the same family !");
533 bool AbstractPoint::IsCommonDirectSonOf(AbstractPoint *refFather, const std::list<OutGate *>& outgs, AbstractPoint *&ret)
536 throw YACS::Exception("AbstractPoint::GetCommonDirectSonOf1 : not enough !");
537 std::list<OutGate *>::const_iterator it(outgs.begin());
538 OutGate *ref(*(it++));
539 AbstractPoint *ref2(GetDirectSonOf(refFather,refFather->findPointWithNode(ref->getNode())));
540 for(;it!=outgs.end();it++)
542 if(!ref2->contains((*it)->getNode()))
549 bool AbstractPoint::IsCommonDirectSonOf(AbstractPoint *refFather, const std::list<InGate *>& ings, AbstractPoint *&ret)
552 throw YACS::Exception("AbstractPoint::GetCommonDirectSonOf2 : not enough !");
553 std::list<InGate *>::const_iterator it(ings.begin());
554 InGate *ref(*(it++));
555 AbstractPoint *ref2(GetDirectSonOf(refFather,refFather->findPointWithNode(ref->getNode())));
556 for(;it!=ings.end();it++)
558 if(!ref2->contains((*it)->getNode()))