From abfa1d4e7de7275fe1a5f28343d67831ad3995d5 Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Thu, 16 May 2019 17:01:24 +0200 Subject: [PATCH] Algorithm of level of parallelism has been extended to more complex cases. --- src/engine/AbstractPoint.cxx | 201 +++++++++++++++++++++++++++++- src/engine/AbstractPoint.hxx | 23 +++- src/engine/BagPoint.cxx | 158 ++++++++++++++++++----- src/engine/BagPoint.hxx | 14 ++- src/engine/BlocPoint.cxx | 73 ++++++++++- src/engine/BlocPoint.hxx | 10 +- src/engine/CMakeLists.txt | 2 + src/engine/ElementaryPoint.cxx | 39 +++++- src/engine/ElementaryPoint.hxx | 13 +- src/engine/ForkBlocPoint.cxx | 25 ++++ src/engine/ForkBlocPoint.hxx | 7 +- src/engine/LinkedBlocPoint.cxx | 40 ++++++ src/engine/LinkedBlocPoint.hxx | 7 +- src/engine/NotSimpleCasePoint.cxx | 102 +++++++++++++++ src/engine/NotSimpleCasePoint.hxx | 47 +++++++ src/engine/PointVisitor.hxx | 3 + src/engine/SetOfPoints.cxx | 31 ++++- src/engine/SetOfPoints.hxx | 2 + src/engine/Test/engineTest.cxx | 162 ++++++++++++++++++++++++ src/engine/Test/engineTest.hxx | 2 + src/engine_swig/pilot.i | 23 ++++ 21 files changed, 924 insertions(+), 60 deletions(-) create mode 100644 src/engine/NotSimpleCasePoint.cxx create mode 100644 src/engine/NotSimpleCasePoint.hxx diff --git a/src/engine/AbstractPoint.cxx b/src/engine/AbstractPoint.cxx index 5ef1ce599..91ce4c246 100644 --- a/src/engine/AbstractPoint.cxx +++ b/src/engine/AbstractPoint.cxx @@ -20,8 +20,14 @@ #include "AbstractPoint.hxx" #include "LinkedBlocPoint.hxx" #include "ForkBlocPoint.hxx" +#include "NotSimpleCasePoint.hxx" #include "SetOfPoints.hxx" +#include "BagPoint.hxx" +#include "ElementaryPoint.hxx" #include "Node.hxx" +#include "Bloc.hxx" + +#include using namespace YACS::ENGINE; @@ -81,6 +87,8 @@ LinkedBlocPoint *AbstractPoint::tryAsLink(BlocPoint *sop) cur2=sop->getNodeB4(bb); while(cur2) { + if(dynamic_cast(cur2)) + continue; Node *cur3(cur2->getFirstNode()); if(cur2->isSimplyLinkedBeforeAfter(sop)) { @@ -100,6 +108,8 @@ LinkedBlocPoint *AbstractPoint::tryAsLink(BlocPoint *sop) cur2=sop->getNodeAfter(ee); while(cur2) { + if(dynamic_cast(cur2)) + continue; Node *cur3(cur2->getLastNode()); if(cur2->isSimplyLinkedBeforeAfter(sop)) { @@ -120,7 +130,7 @@ LinkedBlocPoint *AbstractPoint::tryAsLink(BlocPoint *sop) return new LinkedBlocPoint(l,getFather()); } else - return 0; + return nullptr; } /*! @@ -137,6 +147,8 @@ ForkBlocPoint *AbstractPoint::tryAsFork(BlocPoint *sop) { if(*it==this) continue; + if(dynamic_cast(*it)) + continue; Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode()); if(!IsSimplyLinkedBeforeExt(curFirst) || !IsSimplyLinkedAfterExt(curEnd)) continue; @@ -150,7 +162,7 @@ ForkBlocPoint *AbstractPoint::tryAsFork(BlocPoint *sop) return new ForkBlocPoint(l,getFather()); } else - return 0; + return nullptr; } ForkBlocPoint *AbstractPoint::tryAsForkBis(BlocPoint *sop) @@ -164,6 +176,8 @@ ForkBlocPoint *AbstractPoint::tryAsForkBis(BlocPoint *sop) { if(*it==this) continue; + if(dynamic_cast(*it)) + continue; Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode()); if(!IsNoLinksBefore(curFirst) || !IsSimplyLinkedAfterExt(curEnd)) continue; @@ -177,7 +191,7 @@ ForkBlocPoint *AbstractPoint::tryAsForkBis(BlocPoint *sop) return new ForkBlocPoint(l,getFather()); } else - return 0; + return nullptr; } ForkBlocPoint *AbstractPoint::tryAsForkTer(BlocPoint *sop) @@ -191,6 +205,8 @@ ForkBlocPoint *AbstractPoint::tryAsForkTer(BlocPoint *sop) { if(*it==this) continue; + if(dynamic_cast(*it)) + continue; Node *curFirst((*it)->getFirstNode()),*curEnd((*it)->getLastNode()); if(!IsSimplyLinkedBeforeExt(curFirst) || !IsNoLinksAfter(curEnd)) continue; @@ -204,7 +220,182 @@ ForkBlocPoint *AbstractPoint::tryAsForkTer(BlocPoint *sop) return new ForkBlocPoint(l,getFather()); } else - return 0; + return nullptr; +} + +#include + +class Visitor1 : public YACS::ENGINE::PointVisitor +{ +public: + Visitor1(std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > > *m):_m(m) { } + void beginForkBlocPoint(ForkBlocPoint *pt) { } + void endForkBlocPoint(ForkBlocPoint *pt) { } + void beginLinkedBlocPoint(LinkedBlocPoint *pt) { } + void endLinkedBlocPoint(LinkedBlocPoint *pt) { } + void beginElementaryPoint(ElementaryPoint *pt) + { + std::string nodeName(pt->getNodeName()); + auto it(_m->find(nodeName)); + if(it==_m->end()) + { + (*_m)[nodeName] = std::tuple< ElementaryPoint *, Node *, std::shared_ptr >(pt,pt->getNode(),std::make_shared(nodeName)); + } + } + void endElementaryPoint(ElementaryPoint *pt) { } + void beginNotSimpleCasePoint(NotSimpleCasePoint *pt) { } + void endNotSimpleCasePoint(NotSimpleCasePoint *pt) { } +private: + std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > > *_m; +}; + +/*! + * Feed m with all ElementaryPoints inside \a ptToBeRewired. + */ +void AbstractPoint::FeedData(AbstractPoint *ptToBeRewired, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > > *m) +{ + Visitor1 vis(m); + ptToBeRewired->accept(&vis); +} + +/*! + * Feed m with all ElementaryPoints inside \a ptsToBeRewired. + */ +void AbstractPoint::FeedData(const std::list& ptsToBeRewired, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > > *m) +{ + for(auto it : ptsToBeRewired) + FeedData(it,m); +} + +bool containsPtsToKill(const std::vector& ptsToKill, Node *node) +{ + for(auto it : ptsToKill) + if(it->contains(node)) + return true; + return false; +} + +/*! + * This method go throw all ElementaryPoints of \a m. + * For each ElementaryPoint change the Node instance underneath. And then create links between those new Node by excluding all links going whose destination : + * - is inside \a ptToKill + * - is not refered by \a m + * + * CF links of old nodes are NOT touched for unrewire phase. + * Typically all ElementaryPoints inside \a ptToKill are NOT into \a m. + */ +void AbstractPoint::Rewire(const std::vector& ptsToKill, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > > *m) +{ + for(auto it : *m) + { + ElementaryPoint *pt(std::get<0>(it.second)); + Node *node(std::get<1>(it.second)); + auto newNode(std::get<2>(it.second).get()); + pt->setNode(newNode); + } + for(auto it : *m) + { + ElementaryPoint *pt(std::get<0>(it.second)); + Node *node(std::get<1>(it.second)); + auto newNode(std::get<2>(it.second).get()); + if(containsPtsToKill(ptsToKill,newNode)) + continue; + for(auto it2 : node->getOutGate()->edSetInGate()) + { + Node *nodeFwd(it2->getNode()); + std::string nodeFwdName(nodeFwd->getName()); + auto it3(m->find(nodeFwdName)); + if(it3!=m->end()) + { + Node *nodeFwdNew = std::get<2>(it3->second).get(); + if(!containsPtsToKill(ptsToKill,newNode)) + { + newNode->getOutGate()->edAddInGate(nodeFwdNew->getInGate()); + } + //else + // node after nodeFwd is not in m fall into \a ptToKill + // -> ignore link. + } + //else + // node after nodeFwd is not in m. Typically because nodeFwd has not been put in m + // concretely : do not link incoming links to Node * inside ptToKill + } + } +} + +/*! + * Unrewire consists into replacing newly created nodes into old one in ElementaryPoints contained in m. + * As CF links of old ENGINE::Node * has not be touched the CF graph is the same. + */ +void AbstractPoint::UnRewire(std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > >& m) +{ + for(auto it : m) + { + ElementaryPoint *pt(std::get<0>(it.second)); + Node *node(std::get<1>(it.second)); + pt->setNode(node); + } +} + +void AbstractPoint::Display(std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > > *m) +{ + for(auto it : *m) + { + ElementaryPoint *pt(std::get<0>(it.second)); + auto newNode(pt->getNode()); + for(auto it2 : newNode->getOutGate()->edSetInGate()) + { + std::cerr << pt->getNodeName() << " -> " << it2->getNode()->getName() << " " << newNode->typeName() << std::endl; + } + } +} + +/*! + * This methods tries to deal with \a sop that can t be considered as a composite of Link, Fork. + * + * 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. + * + * If the algorithm fails \a nodes are let untouched and \a somethingDone is let false. + * + */ +void AbstractPoint::TryAsNotSimpleCase(AbstractPoint *father, const std::vector& ptsToKill, std::list& nodes, bool& somethingDone) +{ + std::list lp2; + for(auto it : nodes) + { + if(std::find(ptsToKill.cbegin(),ptsToKill.cend(),it)==ptsToKill.cend()) + lp2.push_back(it->deepCopy(nullptr)); + } + BagPoint *tmp(new BagPoint(lp2,nullptr)); + for(auto it : lp2) + it->setFather(tmp); + SetOfPoints sopTest(tmp); + std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > > m; + FeedData(tmp,&m); + Rewire(ptsToKill,&m); + try + { + sopTest.basicSimplify(); + } + catch(YACS::Exception& ex) + {// By removing elements in ptsToKill from this impossible to have a classical case -> un rewire to rollback nodes state + UnRewire(m); + return ; + } + AbstractPoint *pt(sopTest.getUniqueAndReleaseIt()); + pt->setFather(father); + UnRewire(m); + for(auto it : nodes) + if(std::find(ptsToKill.cbegin(),ptsToKill.cend(),it)==ptsToKill.cend()) + delete it; + nodes.clear(); + nodes.push_back(pt); + for(auto it : ptsToKill) + { + std::list l; l.push_back(it); + nodes.push_back( new NotSimpleCasePoint(l,father) ); + } + somethingDone = true; } bool AbstractPoint::IsGatherB4Ext(Node *node) @@ -291,6 +482,8 @@ Node *AbstractPoint::GetNodeAfter(Node *node) AbstractPoint *AbstractPoint::GetDirectSonOf(AbstractPoint *refFather, AbstractPoint *sonOrLittleSon) { + if(!sonOrLittleSon) + throw YACS::Exception("AbstractPoint::GetDirectSonOf : sonOrLittleSon is null !"); AbstractPoint *curFath(sonOrLittleSon->getFather()),*cur(sonOrLittleSon); while(curFath && curFath!=refFather) { diff --git a/src/engine/AbstractPoint.hxx b/src/engine/AbstractPoint.hxx index f2233ebaa..522acae90 100644 --- a/src/engine/AbstractPoint.hxx +++ b/src/engine/AbstractPoint.hxx @@ -25,15 +25,18 @@ #include "AutoRefCnt.hxx" #include +#include #include #include #include +#include namespace YACS { namespace ENGINE { class Node; + class Bloc; class InGate; class OutGate; class BlocPoint; @@ -41,14 +44,17 @@ namespace YACS class ForkBlocPoint; class PointVisitor; class LinkedBlocPoint; + class NotSimpleCasePoint; + class ElementaryPoint; class YACSLIBENGINE_EXPORT AbstractPoint { public: + AbstractPoint() = default; AbstractPoint(AbstractPoint *father):_father(father) { } AbstractPoint *getFather() const { return _father; } AbstractPoint *getGodFather(); - bool amIGod() { return getGodFather()==0; } + bool amIGod() { return getGodFather()==nullptr; } void setFather(AbstractPoint *father) { _father=father; } // bool isBegin(); @@ -61,17 +67,23 @@ namespace YACS ForkBlocPoint *tryAsFork(BlocPoint *sop); ForkBlocPoint *tryAsForkBis(BlocPoint *sop); ForkBlocPoint *tryAsForkTer(BlocPoint *sop); + //void tryAsNotSimpleCase(BlocPoint *sop, std::list& nodes, bool& somethingDone); + static void TryAsNotSimpleCase(AbstractPoint *father, const std::vector& ptsToKill, std::list& nodes, bool& somethingDone); + // + virtual AbstractPoint *deepCopy(AbstractPoint *father) const = 0; // virtual Node *getFirstNode() = 0; virtual Node *getLastNode() = 0; virtual AbstractPoint *findPointWithNode(Node *node) = 0; - virtual bool contains(Node *node) = 0; + virtual bool contains(Node *node) const = 0; + virtual bool anyOf(const std::set& nodes) const = 0; virtual int getNumberOfNodes() const = 0; virtual int getMaxLevelOfParallelism() const = 0; virtual void getWeightRegardingDPL(ComplexWeight *weight) = 0; virtual void partitionRegardingDPL(const PartDefinition *pd, std::map >& zeMap) const = 0; virtual std::string getRepr() const = 0; virtual void accept(PointVisitor *pv) = 0; + virtual AbstractPoint *expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set& uncatchedNodes) = 0; virtual ~AbstractPoint(); public: static bool IsGatherB4Ext(Node *node); @@ -87,8 +99,13 @@ namespace YACS static AbstractPoint *GetDirectSonOf(AbstractPoint *refFather, AbstractPoint *sonOrLittleSon); static bool IsCommonDirectSonOf(AbstractPoint *refFather, const std::list& outgs, AbstractPoint *&ret); static bool IsCommonDirectSonOf(AbstractPoint *refFather, const std::list& ings, AbstractPoint *&ret); + static void FeedData(AbstractPoint *ptToBeRewired, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > > *m); + static void FeedData(const std::list& ptsToBeRewired, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > > *m); + static void Rewire(const std::vector& ptsToKill, std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > > *m); + static void UnRewire(std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > >& m); + static void Display(std::map< std::string, std::tuple< ElementaryPoint *, Node *, std::shared_ptr > > *m); protected: - AbstractPoint *_father; + AbstractPoint *_father = nullptr; }; } } diff --git a/src/engine/BagPoint.cxx b/src/engine/BagPoint.cxx index 64e0c71cf..f52d150cf 100644 --- a/src/engine/BagPoint.cxx +++ b/src/engine/BagPoint.cxx @@ -21,6 +21,10 @@ #include "Exception.hxx" #include "LinkedBlocPoint.hxx" #include "ForkBlocPoint.hxx" +#include "NotSimpleCasePoint.hxx" + +#include "Bloc.hxx" +#include "LinkInfo.hxx" #include #include @@ -31,49 +35,29 @@ BagPoint::BagPoint(const std::list& 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& 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,115 @@ void BagPoint::deal2Ter(bool& somethingDone) } } +/*! + * 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 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 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 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(pathologicalPt)); + if(!pathologicalPt2) + throw YACS::Exception("BagPoint::expandNonSimpleCaseOn : pathologicalPt is expected to be a NotSimpleCasePoint !"); + std::list nodes2; + std::for_each(_nodes.begin(),_nodes.end(),[&nodes2](AbstractPoint *elt) { if(!dynamic_cast(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(parent)); + if(!parentc) + throw YACS::Exception("BagPoint::expandNonSimpleCaseOn : internal error, Bloc expected"); + // + std::set nodesBefore, nodesAfter; + { + std::map > accelStr; + LinkInfo info(E_ALL); + parentc->findAllNodesStartingFrom(firstNode,nodesBefore,accelStr,info); + } + { + std::map > accelStr; + LinkInfo info(E_ALL); + parentc->findAllNodesStartingFrom(lastNode,nodesAfter,accelStr,info); + } + // + std::set 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 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 pathologicalPt; + std::for_each(_nodes.begin(),_nodes.end(),[&pathologicalPt](AbstractPoint *elt) { if(dynamic_cast(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); + +} diff --git a/src/engine/BagPoint.hxx b/src/engine/BagPoint.hxx index a336a65e2..82d2a45dd 100644 --- a/src/engine/BagPoint.hxx +++ b/src/engine/BagPoint.hxx @@ -32,16 +32,18 @@ namespace YACS class YACSLIBENGINE_EXPORT BagPoint : public BlocPoint { public: + BagPoint() = default; BagPoint(const std::list& nodes, AbstractPoint *father); public://overloading - Node *getFirstNode(); - Node *getLastNode(); + AbstractPoint *deepCopy(AbstractPoint *father) const override; + Node *getFirstNode() override; + Node *getLastNode() override; int getMaxLevelOfParallelism() const; void getWeightRegardingDPL(ComplexWeight *weight); void partitionRegardingDPL(const PartDefinition *pd, std::map >& zeMap) const; std::string getRepr() const; - AbstractPoint *getUniqueAndReleaseIt(); void accept(PointVisitor *pv) override; + AbstractPoint *expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set& uncatchedNodes) override; public: int size() const { return (int)_nodes.size(); } void replaceInMe(BlocPoint *aSet); @@ -49,12 +51,12 @@ namespace YACS void deal2(bool& somethingDone); void deal2Bis(bool& somethingDone); void deal2Ter(bool& somethingDone); + void dealNotSimpleCase(bool& somethingDone); + void expandNonSimpleCase(); private: - AbstractPoint *getUnique(); - const AbstractPoint *getUnique() const; + void expandNonSimpleCaseOn(AbstractPoint *pathologicalPt); }; } } - #endif diff --git a/src/engine/BlocPoint.cxx b/src/engine/BlocPoint.cxx index cd3dbf72f..ec8d4b3c1 100644 --- a/src/engine/BlocPoint.cxx +++ b/src/engine/BlocPoint.cxx @@ -19,6 +19,7 @@ #include "BlocPoint.hxx" #include "Node.hxx" +#include "NotSimpleCasePoint.hxx" #include @@ -30,6 +31,15 @@ BlocPoint::BlocPoint(const std::list& nodes, AbstractPoint *fat (*it)->setFather(this); } +void BlocPoint::deepCopyFrom(const BlocPoint& other) +{ + const std::list& nodesToIterateOn(other.getListOfPoints()); + for(auto it : nodesToIterateOn) + { + _nodes.push_back(it->deepCopy(this)); + } +} + void BlocPoint::getOutPoint(AbstractPoint *node) { std::list::iterator it(std::find(_nodes.begin(),_nodes.end(),node)); @@ -78,16 +88,59 @@ AbstractPoint *BlocPoint::getNodeB4(Node *node) return 0; } -bool BlocPoint::contains(Node *node) +bool BlocPoint::contains(Node *node) const { - for(std::list::iterator it=_nodes.begin();it!=_nodes.end();it++) + for(auto it : _nodes) { - if((*it)->contains(node)) + if(it->contains(node)) return true; } return false; } +bool BlocPoint::anyOf(const std::set& nodes) const +{ + for(auto it : nodes) + { + if(this->contains(it)) + return true; + } + return false; +} + +AbstractPoint *BlocPoint::getUnique() +{ + if(_nodes.size()!=1) + throw YACS::Exception("BlocPoint::getUnique : invalid call !"); + else + { + AbstractPoint *ret(*_nodes.begin()); + if(!ret) + throw YACS::Exception("BlocPoint::getUnique : Ooops !"); + return ret; + } +} + +const AbstractPoint *BlocPoint::getUnique() const +{ + if(_nodes.size()!=1) + throw YACS::Exception("BlocPoint::getUnique const : invalid call !"); + else + { + AbstractPoint *ret(*_nodes.begin()); + if(!ret) + throw YACS::Exception("BlocPoint::getUnique : Ooops !"); + return ret; + } +} + +AbstractPoint *BlocPoint::getUniqueAndReleaseIt() +{ + AbstractPoint *ret(getUnique()); + getOutPoint(ret); + return ret; +} + int BlocPoint::getNumberOfNodes() const { int ret(0); @@ -101,3 +154,17 @@ BlocPoint::~BlocPoint() for(std::list::iterator it=_nodes.begin();it!=_nodes.end();it++) delete *it; } + +bool BlocPoint::internalContinueForSimplify() const +{ + std::size_t i(0); + std::for_each(_nodes.begin(),_nodes.end(),[&i](AbstractPoint *elt) { if(!dynamic_cast(elt)) i++; }); + return i>1; +} + +bool BlocPoint::presenceOfNonSimpleCase() const +{ + std::size_t i(0); + std::for_each(_nodes.begin(),_nodes.end(),[&i](AbstractPoint *elt) { if(dynamic_cast(elt)) i++; }); + return i>0; +} diff --git a/src/engine/BlocPoint.hxx b/src/engine/BlocPoint.hxx index c3034572e..c270f66fb 100644 --- a/src/engine/BlocPoint.hxx +++ b/src/engine/BlocPoint.hxx @@ -34,14 +34,22 @@ namespace YACS protected: std::list _nodes; public: + BlocPoint() = default; BlocPoint(const std::list& nodes, AbstractPoint *father); + void deepCopyFrom(const BlocPoint& other); AbstractPoint *findPointWithNode(Node *node); AbstractPoint *getNodeAfter(Node *node); AbstractPoint *getNodeB4(Node *node); - bool contains(Node *node); + bool contains(Node *node) const override; + bool anyOf(const std::set& nodes) const override; int getNumberOfNodes() const; const std::list& getListOfPoints() const { return _nodes; } virtual ~BlocPoint(); + bool internalContinueForSimplify() const; + bool presenceOfNonSimpleCase() const; + AbstractPoint *getUnique(); + const AbstractPoint *getUnique() const; + AbstractPoint *getUniqueAndReleaseIt(); protected: void getOutPoint(AbstractPoint *node); }; diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 630781421..22c37646a 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -107,6 +107,7 @@ SET(YACSlibEngine_HEADERS BlocPoint.hxx BagPoint.hxx ForkBlocPoint.hxx + NotSimpleCasePoint.hxx LinkedBlocPoint.hxx ElementaryPoint.hxx SetOfPoints.hxx @@ -182,6 +183,7 @@ SET(YACSlibEngine_SOURCES BlocPoint.cxx BagPoint.cxx ForkBlocPoint.cxx + NotSimpleCasePoint.cxx LinkedBlocPoint.cxx ElementaryPoint.cxx SetOfPoints.cxx diff --git a/src/engine/ElementaryPoint.cxx b/src/engine/ElementaryPoint.cxx index b2bb5a827..07a216f87 100644 --- a/src/engine/ElementaryPoint.cxx +++ b/src/engine/ElementaryPoint.cxx @@ -19,6 +19,8 @@ #include "ElementaryPoint.hxx" #include "PointVisitor.hxx" +#include "NotSimpleCasePoint.hxx" +#include "ForkBlocPoint.hxx" #include "Node.hxx" using namespace YACS::ENGINE; @@ -32,14 +34,26 @@ AbstractPoint *ElementaryPoint::findPointWithNode(Node *node) if(node==_node) return this; else - return 0; + return nullptr; } -bool ElementaryPoint::contains(Node *node) +bool ElementaryPoint::contains(Node *node) const { return _node==node; } +bool ElementaryPoint::anyOf(const std::set& nodes) const +{ + return nodes.find(_node)!=nodes.end(); +} + +AbstractPoint *ElementaryPoint::deepCopy(AbstractPoint *father) const +{ + AbstractPoint *ret(new ElementaryPoint(_node)); + ret->setFather(father); + return ret; +} + Node *ElementaryPoint::getFirstNode() { return _node; @@ -80,3 +94,24 @@ void ElementaryPoint::accept(PointVisitor *pv) pv->beginElementaryPoint(this); pv->endElementaryPoint(this); } + +AbstractPoint *ElementaryPoint::expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set& uncatchedNodes) +{ + if(uncatchedNodes.find(_node)!=uncatchedNodes.end()) + return this; + else + { + std::list l; + AbstractPoint *p0(this->deepCopy(getFather())),*p1(pathologicalPt->getUnique()->deepCopy(getFather())); + l.push_back(p0); + l.push_back(p1); + AbstractPoint *ret(new ForkBlocPoint(l,getFather())); + p0->setFather(ret); p1->setFather(ret); + return ret; + } +} + +std::string ElementaryPoint::getNodeName() const +{ + return _node->getName(); +} diff --git a/src/engine/ElementaryPoint.hxx b/src/engine/ElementaryPoint.hxx index 1109094cd..328b1f8e6 100644 --- a/src/engine/ElementaryPoint.hxx +++ b/src/engine/ElementaryPoint.hxx @@ -38,16 +38,23 @@ namespace YACS public: ElementaryPoint(Node *node):AbstractPoint(0),_node(node) { } AbstractPoint *findPointWithNode(Node *node); - bool contains(Node *node); - Node *getFirstNode(); - Node *getLastNode(); + bool contains(Node *node) const override; + bool anyOf(const std::set& nodes) const override; + AbstractPoint *deepCopy(AbstractPoint *father) const override; + Node *getFirstNode() override; + Node *getLastNode() override; int getNumberOfNodes() const; int getMaxLevelOfParallelism() const; void getWeightRegardingDPL(ComplexWeight *weight); void partitionRegardingDPL(const PartDefinition *pd, std::map >& zeMap) const; std::string getRepr() const; void accept(PointVisitor *pv) override; + AbstractPoint *expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set& uncatchedNodes) override; virtual ~ElementaryPoint(); + public: + void setNode(Node *node) { _node=node; } + Node *getNode() const { return _node; } + std::string getNodeName() const; }; } } diff --git a/src/engine/ForkBlocPoint.cxx b/src/engine/ForkBlocPoint.cxx index d2b01ac73..dbd445a56 100644 --- a/src/engine/ForkBlocPoint.cxx +++ b/src/engine/ForkBlocPoint.cxx @@ -29,6 +29,14 @@ ForkBlocPoint::ForkBlocPoint(const std::list& nodes, AbstractPo { } +AbstractPoint *ForkBlocPoint::deepCopy(AbstractPoint *father) const +{ + ForkBlocPoint *ret(new ForkBlocPoint); + ret->deepCopyFrom(*this); + ret->setFather(father); + return ret; +} + ForkBlocPoint::~ForkBlocPoint() { } @@ -118,3 +126,20 @@ void ForkBlocPoint::accept(PointVisitor *pv) it->accept(pv); pv->endForkBlocPoint(this); } + +AbstractPoint *ForkBlocPoint::expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set& uncatchedNodes) +{ + for(auto& it : _nodes) + { + AbstractPoint *ret(it->expandNonSimpleCaseOn(pathologicalPt,uncatchedNodes)); + if(ret!=it) + { + ret->setFather(this); + auto oldIt(it); + it = ret; + delete oldIt; + } + } + return this; +} + diff --git a/src/engine/ForkBlocPoint.hxx b/src/engine/ForkBlocPoint.hxx index fb44b52dc..05f822212 100644 --- a/src/engine/ForkBlocPoint.hxx +++ b/src/engine/ForkBlocPoint.hxx @@ -30,14 +30,17 @@ namespace YACS class YACSLIBENGINE_EXPORT ForkBlocPoint : public BlocPoint { public: + ForkBlocPoint() = default; ForkBlocPoint(const std::list& nodes, AbstractPoint *father); - Node *getFirstNode(); - Node *getLastNode(); + AbstractPoint *deepCopy(AbstractPoint *father) const override; + Node *getFirstNode() override; + Node *getLastNode() override; int getMaxLevelOfParallelism() const; void getWeightRegardingDPL(ComplexWeight *weight); void partitionRegardingDPL(const PartDefinition *pd, std::map >& zeMap) const; std::string getRepr() const; void accept(PointVisitor *pv) override; + AbstractPoint *expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set& uncatchedNodes) override; virtual ~ForkBlocPoint(); }; } diff --git a/src/engine/LinkedBlocPoint.cxx b/src/engine/LinkedBlocPoint.cxx index babe45ddd..c037e9e59 100644 --- a/src/engine/LinkedBlocPoint.cxx +++ b/src/engine/LinkedBlocPoint.cxx @@ -18,6 +18,9 @@ // #include "LinkedBlocPoint.hxx" +#include "ElementaryPoint.hxx" +#include "NotSimpleCasePoint.hxx" +#include "ForkBlocPoint.hxx" #include "PointVisitor.hxx" #include "Exception.hxx" @@ -32,6 +35,14 @@ LinkedBlocPoint::LinkedBlocPoint(const std::list& nodes, Abstra { } +AbstractPoint *LinkedBlocPoint::deepCopy(AbstractPoint *father) const +{ + LinkedBlocPoint *ret(new LinkedBlocPoint); + ret->deepCopyFrom(*this); + ret->setFather(father); + return ret; +} + Node *LinkedBlocPoint::getFirstNode() { if(_nodes.empty()) @@ -85,6 +96,35 @@ std::string LinkedBlocPoint::getRepr() const return ret; } +AbstractPoint *LinkedBlocPoint::expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set& uncatchedNodes) +{ + if(anyOf(uncatchedNodes)) + { + for(auto& it : _nodes) + { + AbstractPoint *ret(it->expandNonSimpleCaseOn(pathologicalPt,uncatchedNodes)); + if(ret!=it) + { + ret->setFather(this); + auto oldIt(it); + it = ret; + delete oldIt; + } + } + return this; + } + else + { + std::list l; + AbstractPoint *p0(this->deepCopy(getFather())),*p1(pathologicalPt->getUnique()->deepCopy(getFather())); + l.push_back(p0); + l.push_back(p1); + AbstractPoint *ret(new ForkBlocPoint(l,getFather())); + p0->setFather(ret); p1->setFather(ret); + return ret; + } +} + void LinkedBlocPoint::accept(PointVisitor *pv) { pv->beginLinkedBlocPoint(this); diff --git a/src/engine/LinkedBlocPoint.hxx b/src/engine/LinkedBlocPoint.hxx index 8d977a17a..185415ac4 100644 --- a/src/engine/LinkedBlocPoint.hxx +++ b/src/engine/LinkedBlocPoint.hxx @@ -32,14 +32,17 @@ namespace YACS class YACSLIBENGINE_EXPORT LinkedBlocPoint : public BlocPoint { public: + LinkedBlocPoint() = default; LinkedBlocPoint(const std::list& nodes, AbstractPoint *father); - Node *getFirstNode(); - Node *getLastNode(); + AbstractPoint *deepCopy(AbstractPoint *father) const override; + Node *getFirstNode() override; + Node *getLastNode() override; int getMaxLevelOfParallelism() const; void getWeightRegardingDPL(ComplexWeight *weight); void partitionRegardingDPL(const PartDefinition *pd, std::map >& zeMap) const; std::string getRepr() const; void accept(PointVisitor *pv) override; + AbstractPoint *expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set& uncatchedNodes) override; virtual ~LinkedBlocPoint(); }; } diff --git a/src/engine/NotSimpleCasePoint.cxx b/src/engine/NotSimpleCasePoint.cxx new file mode 100644 index 000000000..0a0a495d1 --- /dev/null +++ b/src/engine/NotSimpleCasePoint.cxx @@ -0,0 +1,102 @@ +// Copyright (C) 2019 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 +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "NotSimpleCasePoint.hxx" +#include "PointVisitor.hxx" +#include "Exception.hxx" + +using namespace YACS::ENGINE; + +NotSimpleCasePoint::NotSimpleCasePoint(const std::list& nodes, AbstractPoint *father):BlocPoint(nodes,father) +{ +} + +AbstractPoint *NotSimpleCasePoint::deepCopy(AbstractPoint *father) const +{ + NotSimpleCasePoint *ret(new NotSimpleCasePoint); + ret->deepCopyFrom(*this); + ret->setFather(father); + return ret; +} + +Node *NotSimpleCasePoint::getFirstNode() +{ + if(_nodes.empty()) + throw Exception("NotSimpleCasePoint::getFirstNode : error no branches !"); + return _nodes.front()->getFirstNode(); +} + +Node *NotSimpleCasePoint::getLastNode() +{ + if(_nodes.empty()) + throw Exception("NotSimpleCasePoint::getFirstNode : error no branches !"); + return _nodes.back()->getLastNode(); +} + +int NotSimpleCasePoint::getMaxLevelOfParallelism() const +{ + int ret(0); + for(std::list::const_iterator it=_nodes.begin();it!=_nodes.end();it++) + ret=std::max(ret,(*it)->getMaxLevelOfParallelism()); + return ret; +} + +void NotSimpleCasePoint::getWeightRegardingDPL(ComplexWeight *weight) +{ + ComplexWeight localWeight; + for(std::list::const_iterator it=_nodes.begin();it!=_nodes.end();it++) + { + (*it)->getWeightRegardingDPL(&localWeight); + weight->addWeight(&localWeight); + localWeight.setToZero(); + } +} + +void NotSimpleCasePoint::partitionRegardingDPL(const PartDefinition *pd, std::map >& zeMap) const +{ + for(std::list::const_iterator it=_nodes.begin();it!=_nodes.end();it++) + (*it)->partitionRegardingDPL(pd,zeMap); +} + +std::string NotSimpleCasePoint::getRepr() const +{ + std::size_t sz(_nodes.size()),ii(0); + std::string ret("|"); + for(std::list::const_iterator it=_nodes.begin();it!=_nodes.end();it++,ii++) + { + ret+=(*it)->getRepr(); + if(ii!=sz-1) + ret+="^"; + } + ret+="|"; + return ret; +} + +void NotSimpleCasePoint::accept(PointVisitor *pv) +{ + pv->beginNotSimpleCasePoint(this); + for(auto it:_nodes) + it->accept(pv); + pv->endNotSimpleCasePoint(this); +} + +AbstractPoint *NotSimpleCasePoint::expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set& uncatchedNodes) +{ + throw YACS::Exception("NotSimpleCasePoint::expandNonSimpleCaseOn : ooops !"); +} diff --git a/src/engine/NotSimpleCasePoint.hxx b/src/engine/NotSimpleCasePoint.hxx new file mode 100644 index 000000000..f4ed5401e --- /dev/null +++ b/src/engine/NotSimpleCasePoint.hxx @@ -0,0 +1,47 @@ +// Copyright (C) 2019 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 +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#pragma once + +#include "YACSlibEngineExport.hxx" +#include "BlocPoint.hxx" + +namespace YACS +{ + namespace ENGINE + { + class YACSLIBENGINE_EXPORT NotSimpleCasePoint : public BlocPoint + { + public: + NotSimpleCasePoint() = default; + NotSimpleCasePoint(const std::list& nodes, AbstractPoint *father); + ~NotSimpleCasePoint() = default; + AbstractPoint *deepCopy(AbstractPoint *father) const override; + // + Node *getFirstNode() override; + Node *getLastNode() override; + int getMaxLevelOfParallelism() const override; + void getWeightRegardingDPL(ComplexWeight *weight) override; + void partitionRegardingDPL(const PartDefinition *pd, std::map >& zeMap) const override; + std::string getRepr() const override; + void accept(PointVisitor *pv) override; + AbstractPoint *expandNonSimpleCaseOn(NotSimpleCasePoint *pathologicalPt, const std::set& uncatchedNodes) override; + }; + } +} diff --git a/src/engine/PointVisitor.hxx b/src/engine/PointVisitor.hxx index 28f907b85..c84d02589 100644 --- a/src/engine/PointVisitor.hxx +++ b/src/engine/PointVisitor.hxx @@ -25,6 +25,7 @@ namespace YACS { namespace ENGINE { + class NotSimpleCasePoint; class ElementaryPoint; class LinkedBlocPoint; class ForkBlocPoint; @@ -38,6 +39,8 @@ namespace YACS virtual void endLinkedBlocPoint(LinkedBlocPoint *pt) = 0; virtual void beginElementaryPoint(ElementaryPoint *pt) = 0; virtual void endElementaryPoint(ElementaryPoint *pt) = 0; + virtual void beginNotSimpleCasePoint(NotSimpleCasePoint *pt) = 0; + virtual void endNotSimpleCasePoint(NotSimpleCasePoint *pt) = 0; }; } } diff --git a/src/engine/SetOfPoints.cxx b/src/engine/SetOfPoints.cxx index 51a47468c..025edd959 100644 --- a/src/engine/SetOfPoints.cxx +++ b/src/engine/SetOfPoints.cxx @@ -40,12 +40,10 @@ SetOfPoints::SetOfPoints(const std::list& nodes):_bp(0) SetOfPoints::~SetOfPoints() { - if(!_bp) - return; delete _bp; } -void SetOfPoints::simplify() +void SetOfPoints::basicSimplify() { while(_bp->size()>1) { @@ -65,6 +63,33 @@ void SetOfPoints::simplify() } } +void SetOfPoints::simplify() +{ + while( _bp->internalContinueForSimplify() ) + { + bool somethingDone(false); + _bp->deal1(somethingDone); + if(somethingDone) + continue; + _bp->deal2(somethingDone); + if(somethingDone) + continue; + _bp->deal2Bis(somethingDone); + if(somethingDone) + continue; + _bp->deal2Ter(somethingDone); + if(somethingDone) + continue; + _bp->dealNotSimpleCase(somethingDone); + if(!somethingDone) + throw Exception("SetOfPoints::simplify : not implemented yet !\nPlease check if there are any recursively redundant links (can be removed by removeRecursivelyRedundantCL method)."); + } + if( _bp->presenceOfNonSimpleCase() ) + { + _bp->expandNonSimpleCase(); + } +} + std::string SetOfPoints::getRepr() const { return _bp->getRepr(); diff --git a/src/engine/SetOfPoints.hxx b/src/engine/SetOfPoints.hxx index e33e1b3f8..cd2d8485c 100644 --- a/src/engine/SetOfPoints.hxx +++ b/src/engine/SetOfPoints.hxx @@ -42,7 +42,9 @@ namespace YACS { public: SetOfPoints(const std::list& nodes); + SetOfPoints(BagPoint *bp):_bp(bp) { } ~SetOfPoints(); + void basicSimplify(); void simplify(); std::string getRepr() const; AbstractPoint *findPointWithNode(Node *node); diff --git a/src/engine/Test/engineTest.cxx b/src/engine/Test/engineTest.cxx index f537da13d..838f68d8c 100644 --- a/src/engine/Test/engineTest.cxx +++ b/src/engine/Test/engineTest.cxx @@ -1247,3 +1247,165 @@ void EngineTest::checkGraphAnalyser4() CPPUNIT_ASSERT(sop.getRepr()=="(n3+n2+n1) - "); } } + +/*! + * Case revealed by EmC2 on complex managers. + * Here basic combination of Link/Fork is not enough. + */ +void EngineTest::checkGraphAnalyser5() +{ + { + Bloc proc("TOP"); + std::vector vn; + std::vector v{"A","E","C","F","D","G"}; + std::size_t i=0; + for(auto it : v) + { + Bloc *pt(new Bloc(v[i++])); + proc.edAddChild(pt); + vn.push_back(pt); + } + // + proc.edAddCFLink(vn[0],vn[1]);//A -> E + proc.edAddCFLink(vn[0],vn[2]);//A -> C + proc.edAddCFLink(vn[2],vn[3]);//C -> F + proc.edAddCFLink(vn[2],vn[4]);//C -> D + proc.edAddCFLink(vn[1],vn[3]);//E -> F + proc.edAddCFLink(vn[3],vn[5]);//F -> G + // + std::vector< std::list > rrr(proc.splitIntoIndependantGraph()); + CPPUNIT_ASSERT_EQUAL(1,(int)rrr.size()); + CPPUNIT_ASSERT_EQUAL((int)v.size(),(int)rrr[0].size()); + SetOfPoints sop(rrr[0]); + sop.simplify(); + CPPUNIT_ASSERT(sop.getRepr()=="((A+[C*E])+[(F+G)*[D*E]]) - "); + } + // + { + Bloc proc("TOP"); + std::vector vn; + std::vector v{"A","E","C","B","F","D","G"}; + std::size_t i=0; + for(auto it : v) + { + Bloc *pt(new Bloc(v[i++])); + proc.edAddChild(pt); + vn.push_back(pt); + } + // + proc.edAddCFLink(vn[0],vn[1]);//A -> E + proc.edAddCFLink(vn[0],vn[2]);//A -> C + proc.edAddCFLink(vn[0],vn[3]);//A -> B + proc.edAddCFLink(vn[3],vn[4]);//B -> F + proc.edAddCFLink(vn[2],vn[4]);//C -> F + proc.edAddCFLink(vn[2],vn[5]);//C -> D + proc.edAddCFLink(vn[1],vn[4]);//E -> F + proc.edAddCFLink(vn[4],vn[6]);//F -> G + // + std::vector< std::list > rrr(proc.splitIntoIndependantGraph()); + CPPUNIT_ASSERT_EQUAL(1,(int)rrr.size()); + CPPUNIT_ASSERT_EQUAL((int)v.size(),(int)rrr[0].size()); + SetOfPoints sop(rrr[0]); + sop.simplify(); + CPPUNIT_ASSERT(sop.getRepr()=="(A+[C*[[B*D]*[D*E]]]+[(F+G)*D]) - "); + } + // + { + Bloc proc("TOP"); + std::vector vn; + std::vector v{"A","E","C","B","F","D","G"}; + std::size_t i=0; + for(auto it : v) + { + Bloc *pt(new Bloc(v[i++])); + proc.edAddChild(pt); + vn.push_back(pt); + } + // + proc.edAddCFLink(vn[0],vn[1]);//A -> E + proc.edAddCFLink(vn[0],vn[2]);//A -> C + proc.edAddCFLink(vn[0],vn[3]);//A -> B + proc.edAddCFLink(vn[3],vn[4]);//B -> F + proc.edAddCFLink(vn[2],vn[4]);//C -> F + proc.edAddCFLink(vn[2],vn[5]);//C -> D + proc.edAddCFLink(vn[1],vn[4]);//E -> F + proc.edAddCFLink(vn[4],vn[6]);//F -> G + // + std::vector< std::list > rrr(proc.splitIntoIndependantGraph()); + CPPUNIT_ASSERT_EQUAL(1,(int)rrr.size()); + CPPUNIT_ASSERT_EQUAL((int)v.size(),(int)rrr[0].size()); + SetOfPoints sop(rrr[0]); + sop.simplify(); + CPPUNIT_ASSERT(sop.getRepr()=="(A+[C*[[B*D]*[D*E]]]+[(F+G)*D]) - "); + } + // + { + Bloc proc("TOP"); + std::vector vn; + std::vector v{"A","I","E","C","B","J","F","H","D","G"}; + std::size_t i=0; + for(auto it : v) + { + Bloc *pt(new Bloc(v[i++])); + proc.edAddChild(pt); + vn.push_back(pt); + } + // + proc.edAddCFLink(vn[0],vn[1]);//A -> I + proc.edAddCFLink(vn[0],vn[2]);//A -> E + proc.edAddCFLink(vn[0],vn[3]);//A -> C + proc.edAddCFLink(vn[0],vn[4]);//A -> B + proc.edAddCFLink(vn[4],vn[6]);//B -> F + proc.edAddCFLink(vn[3],vn[7]);//C -> H + proc.edAddCFLink(vn[3],vn[6]);//C -> F + proc.edAddCFLink(vn[3],vn[8]);//C -> D + proc.edAddCFLink(vn[2],vn[6]);//E -> F + proc.edAddCFLink(vn[6],vn[9]);//F -> G + proc.edAddCFLink(vn[9],vn[5]);//G -> J + proc.edAddCFLink(vn[7],vn[5]);//H -> J + proc.edAddCFLink(vn[1],vn[5]);//I -> J + // + std::vector< std::list > rrr(proc.splitIntoIndependantGraph()); + CPPUNIT_ASSERT_EQUAL(1,(int)rrr.size()); + CPPUNIT_ASSERT_EQUAL((int)v.size(),(int)rrr[0].size()); + SetOfPoints sop(rrr[0]); + sop.simplify(); + CPPUNIT_ASSERT(sop.getRepr()=="(A+[([C*[(F+G)*I]]+[([[(F+G)*H]*[(F+G)*I]]+J)*[[(F+G)*D]*[(F+G)*I]]])*[[B*[(F+G)*I]]*[E*[(F+G)*I]]]]) - "); + } + // + { + Bloc proc("TOP"); + std::vector vn; + std::vector v{"A","I","E","C","B","J","F","H","D","K","G","L"}; + std::size_t i=0; + for(auto it : v) + { + Bloc *pt(new Bloc(v[i++])); + proc.edAddChild(pt); + vn.push_back(pt); + } + // + proc.edAddCFLink(vn[0],vn[1]);//A -> I + proc.edAddCFLink(vn[0],vn[2]);//A -> E + proc.edAddCFLink(vn[0],vn[3]);//A -> C + proc.edAddCFLink(vn[0],vn[4]);//A -> B + proc.edAddCFLink(vn[4],vn[6]);//B -> F + proc.edAddCFLink(vn[3],vn[7]);//C -> H + proc.edAddCFLink(vn[3],vn[6]);//C -> F + proc.edAddCFLink(vn[3],vn[8]);//C -> D + proc.edAddCFLink(vn[2],vn[6]);//E -> F + proc.edAddCFLink(vn[6],vn[10]);//F -> G + proc.edAddCFLink(vn[10],vn[5]);//G -> J + proc.edAddCFLink(vn[7],vn[5]);//H -> J + proc.edAddCFLink(vn[1],vn[5]);//I -> J + proc.edAddCFLink(vn[5],vn[9]);//J -> K + proc.edAddCFLink(vn[9],vn[11]);//K -> L + // + std::vector< std::list > rrr(proc.splitIntoIndependantGraph()); + CPPUNIT_ASSERT_EQUAL(1,(int)rrr.size()); + CPPUNIT_ASSERT_EQUAL((int)v.size(),(int)rrr[0].size()); + SetOfPoints sop(rrr[0]); + sop.simplify(); + CPPUNIT_ASSERT(sop.getRepr()=="(A+[([C*[(F+G)*I]]+[([[(F+G)*H]*[(F+G)*I]]+(J+K+L))*[[(F+G)*D]*[(F+G)*I]]])*[[B*[(F+G)*I]]*[E*[(F+G)*I]]]]) - "); + } +} diff --git a/src/engine/Test/engineTest.hxx b/src/engine/Test/engineTest.hxx index b29b43d92..9bc72caaf 100644 --- a/src/engine/Test/engineTest.hxx +++ b/src/engine/Test/engineTest.hxx @@ -64,6 +64,7 @@ namespace YACS CPPUNIT_TEST(checkGraphAnalyser2); CPPUNIT_TEST(checkGraphAnalyser3); CPPUNIT_TEST(checkGraphAnalyser4); + CPPUNIT_TEST(checkGraphAnalyser5); CPPUNIT_TEST_SUITE_END(); public: @@ -103,6 +104,7 @@ namespace YACS void checkGraphAnalyser2(); void checkGraphAnalyser3(); void checkGraphAnalyser4(); + void checkGraphAnalyser5(); protected: static std::map _nodeMap; static std::map _compoMap; diff --git a/src/engine_swig/pilot.i b/src/engine_swig/pilot.i index 20475bcb3..f7ad4f1c6 100644 --- a/src/engine_swig/pilot.i +++ b/src/engine_swig/pilot.i @@ -63,6 +63,7 @@ #include "PointVisitor.hxx" #include "ForkBlocPoint.hxx" #include "LinkedBlocPoint.hxx" +#include "NotSimpleCasePoint.hxx" #include "ElementaryPoint.hxx" #include "ObserverAsPlugin.hxx" @@ -589,6 +590,14 @@ namespace YACS ForkBlocPoint(); ForkBlocPoint(const ForkBlocPoint&); }; + + class NotSimpleCasePoint : public BlocPoint + { + private: + ~NotSimpleCasePoint(); + NotSimpleCasePoint(); + NotSimpleCasePoint(const NotSimpleCasePoint&); + }; class SetOfPoints { @@ -647,6 +656,20 @@ namespace YACS PyObject *ret(PyObject_CallMethodObjArgs(_py,meth,ptPy,nullptr)); Py_XDECREF(ret); Py_XDECREF(meth); Py_XDECREF(ptPy); } + void beginNotSimpleCasePoint(NotSimpleCasePoint *pt) + { + PyObject *ptPy(SWIG_NewPointerObj((void*)pt,SWIGTYPE_p_YACS__ENGINE__NotSimpleCasePoint,0));//$descriptor(YACS::ENGINE::NotSimpleCasePoint *) + PyObject *meth(PyString_FromString("beginNotSimpleCasePoint")); + PyObject *ret(PyObject_CallMethodObjArgs(_py,meth,ptPy,nullptr)); + Py_XDECREF(ret); Py_XDECREF(meth); Py_XDECREF(ptPy); + } + void endNotSimpleCasePoint(NotSimpleCasePoint *pt) + { + PyObject *ptPy(SWIG_NewPointerObj((void*)pt,SWIGTYPE_p_YACS__ENGINE__NotSimpleCasePoint,0)); + PyObject *meth(PyString_FromString("endNotSimpleCasePoint")); + PyObject *ret(PyObject_CallMethodObjArgs(_py,meth,ptPy,nullptr)); + Py_XDECREF(ret); Py_XDECREF(meth); Py_XDECREF(ptPy); + } private: PyObject *_py; }; -- 2.39.2