8#ifndef model_LoopNetwork_H_
9#define model_LoopNetwork_H_
56#define VerboseLoopNetwork(N,x) if(verboseLevel>=N){std::cout<<x;}
58#define VerboseLoopNetwork(N,x)
64 template<
typename FlowType>
73 template<
typename Derived>
75 ,
public WeakPtrFactory<Derived,typename TypeTraits<Derived>::LoopType>
76 ,
public WeakPtrFactory<Derived,typename TypeTraits<Derived>::LoopNodeType>
77 ,
public WeakPtrFactory<Derived,typename TypeTraits<Derived>::NetworkNodeType>
78 ,
public WeakPtrFactory<Derived,typename TypeTraits<Derived>::NetworkLinkType>
79 ,
private std::map<typename TypeTraits<Derived>::LoopLinkType::KeyType,typename TypeTraits<Derived>::LoopLinkType>
153 const auto loop(Ni->loop());
154 VerboseLoopNetwork(1,
"cutting loop "<<loop->tag()<<
" at "<<Ni->tag()<<
","<<Nj->tag()<<std::endl);
157 const auto linkAtI=loop->linkStartingAt(Ni);
158 const auto linkAtJ=loop->linkStartingAt(Nj);
160 if(linkAtI.first && linkAtJ.first)
162 if(linkAtI.second->sink!=Nj && linkAtJ.second->sink!=Ni)
164 auto currLink(linkAtI.second);
165 if(currLink->sink!=Nj)
167 std::shared_ptr<LoopType> newLoop(
loops().
clone(loop->key));
173 const auto cloneNi(
loopNodes().
clone(Ni->key,newLoop,Ni->networkNode));
174 const auto cloneNj(
loopNodes().
clone(Nj->key,newLoop,Nj->networkNode));
176 std::vector<std::tuple<std::shared_ptr<LoopNodeType>,std::shared_ptr<LoopNodeType>>> linksToDisconect;
177 while(currLink->source!=Nj)
179 linksToDisconect.emplace_back(currLink->source,currLink->sink);
180 currLink=currLink->next;
183 for(
const auto& tup : linksToDisconect)
185 disconnect(std::get<0>(tup),std::get<1>(tup),loop);
189 for(
const auto& tup : linksToDisconect)
191 const std::shared_ptr<LoopNodeType>
source(std::get<0>(tup)==Ni? cloneNi : std::get<0>(tup));
192 const std::shared_ptr<LoopNodeType> sink(std::get<1>(tup)==Nj? cloneNj : std::get<1>(tup));
193 source->resetLoop(newLoop);
194 sink->resetLoop(newLoop);
198 connect(cloneNj,cloneNi,newLoop);
199 connect(std::get<0>(linksToDisconect.front()),std::get<1>(linksToDisconect.back()),loop);
200 return std::make_pair(cloneNi,cloneNj);
213 const std::shared_ptr<LoopType>& tempLoop)
215 VerboseLoopNetwork(1,
"connecting "<<n0->sID<<
"->"<<n1->sID<<
" ("<<tempLoop->sID<<
")"<<std::endl);
219 const auto key=LoopLinkType::loopLinkKey(tempLoop,n0,n1);
227 if(linkIter->second.source->sID==n1->sID && linkIter->second.sink->sID==n0->sID)
237 VerboseLoopNetwork(1,
"disconnecting "<<n0->sID<<
"->"<<n1->sID<<
" ("<<loop->sID<<
")"<<std::endl);
238 return loopLinks().erase(LoopLinkType::loopLinkKey(loop,n0,n1));
247 const std::vector<std::shared_ptr<LoopNodeType>> nodes)
256 for(
size_t k=0;
k<nodes.size();++
k)
258 const size_t next=
k+1<nodes.size()?
k+1 : 0;
262 assert(loop->isLoop() &&
"Not a loop.");
268 const std::deque<std::shared_ptr<LoopNodeType>> nodes)
277 for(
size_t k=0;
k<nodes.size();++
k)
279 const size_t next=
k+1<nodes.size()?
k+1 : 0;
283 assert(loop->isLoop() &&
"Not a loop.");
290 for(
typename LoopLinkContainerType::const_iterator loopIter=
loopLinks().begin();
293 if(loopIter->second.loop->sID==loopID)
306 VerboseLoopNetwork(1,
"expanding NetworkLink "<<Lij->tag()<<
" at node "<<networkNode->tag()<<std::endl);
317 VerboseLoopNetwork(1,
"expanding LoopLink "<<Lij.tag()<<
" at node "<<loopNode->tag()<<std::endl);
320 const std::shared_ptr<LoopType> loop(Lij.loop);
337 std::set<typename LoopNodeType::KeyType> loopNodesSet;
338 for(
const auto& loopNode : node->loopNodes())
340 loopNodesSet.insert(loopNode->key);
343 for(
const auto&
key : loopNodesSet)
364 const auto loop(node->loop());
371 if (node->prev.first && node->next.first)
402 if(Ni!=
nullptr && Nj!=
nullptr)
406 assert(sharedNi && sharedNj);
414 if(Nj->isContractableTo(Ni.get()))
416 const auto clones(cutLoop(Ni,Nj));
419 if(clones.first && clones.second)
430 if(!Ni || !Nj || Ni==Nj || Ni->loopNodes().empty() || Nj->loopNodes().empty() ||
431 !Nj->isContractableTo(Ni))
441 for(
const auto*
i : Ni->loopNodes())
443 for(
const auto*
j : Nj->loopNodes())
445 if(
j->isContractableTo(
i))
465 std::vector<SharedLoopNodePtrType> remaining;
466 for(
const auto* node : Nj->loopNodes())
470 for(
const auto& node : remaining)
472 Nj->removeLoopNode(node.get());
473 node->networkNode=Ni;
474 Ni->addLoopNode(node.get());
475 if(node->prev.second)
477 node->prev.second->resetNetworkLink();
479 if(node->next.second)
481 node->next.second->resetNetworkLink();
489 for(
const auto& loop :
loops())
491 loop.second.lock()->printLoop();
497 std::cout<<
"Printing LoopNodes "<<
loopNodes().size()<<std::endl;
500 std::cout<<node.second.lock()->tag()<<std::endl;
506 std::cout<<
"Printing NetworkNodes "<<
networkNodes().size()<<std::endl;
509 std::cout<<node.second.lock()->tag()<<std::endl;
515 template<
typename Derived>
CRTP()
The default constructor.
NetworkNodeContainerType & networkNodes()
LoopLinkContainerType & loopLinks()
TypeTraits< Derived >::LoopType LoopType
bool contractNetworkNodes(const SharedNetworkNodePtrType &Ni, const SharedNetworkNodePtrType &Nj)
LoopNodeContainerType::SharedPtrType SharedLoopNodePtrType
const LoopContainerType & loops() const
const LoopLinkContainerType & loopLinks() const
WeakPtrFactory< Derived, NetworkNodeType > NetworkNodeContainerType
TypeTraits< Derived >::LoopNodeType LoopNodeType
bool contractLoopNodes(const LoopNodeType *const Ni, const LoopNodeType *const Nj)
void connect(const SharedLoopNodePtrType &n0, const SharedLoopNodePtrType &n1, const std::shared_ptr< LoopType > &tempLoop)
WeakPtrFactory< Derived, LoopNodeType > LoopNodeContainerType
const NetworkLinkContainerType & networkLinks() const
void removeLoopNode(const size_t &nodeID)
const NetworkNodeContainerType & networkNodes() const
void printLoopNodes() const
const LoopNodeContainerType & loopNodes() const
NetworkLinkContainerType & networkLinks()
LoopNodeContainerType & loopNodes()
std::map< typename LoopLinkType::KeyType, LoopLinkType > LoopLinkContainerType
void deleteLoop(const size_t &loopID)
TypeTraits< Derived >::NetworkLinkType NetworkLinkType
LoopContainerType & loops()
bool contractLoopNodes(const SharedLoopNodePtrType &Ni, const SharedLoopNodePtrType &Nj)
TypeTraits< Derived >::NetworkNodeType NetworkNodeType
size_t disconnect(const SharedLoopNodePtrType &n0, const SharedLoopNodePtrType &n1, const std::shared_ptr< LoopType > &loop)
SharedNetworkNodePtrType expandNetworkLink(const std::shared_ptr< NetworkLinkType > &Lij, const SharedNetworkNodePtrType &networkNode)
void removeNetworkNode(const size_t &nodeID)
void removeLoopNode(const SharedLoopNodePtrType &node)
void removeNetworkNode(const SharedNetworkNodePtrType &node)
SharedLoopNodePtrType expandLoopLink(const LoopLinkType &Lij, const SharedLoopNodePtrType &loopNode)
TypeTraits< Derived >::FlowType FlowType
NetworkNodeContainerType::SharedPtrType SharedNetworkNodePtrType
void printNetworkNodes() const
WeakPtrFactory< Derived, NetworkLinkType > NetworkLinkContainerType
WeakPtrFactory< Derived, LoopType > LoopContainerType
void insertLoop(const std::shared_ptr< LoopType > &loop, const std::vector< std::shared_ptr< LoopNodeType > > nodes)
TypeTraits< Derived >::LoopLinkType LoopLinkType
void insertLoop(const std::shared_ptr< LoopType > &loop, const std::deque< std::shared_ptr< LoopNodeType > > nodes)
static bool isZero(const FlowType &)
std::shared_ptr< LoopNodeType > SharedPtrType
SharedPtrType create(const Args &...args)
SharedPtrType get(const KeyType &key) const
SharedPtrType clone(const KeyType &key, const Args &... args)