Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
LoopNetwork.h
Go to the documentation of this file.
1/* This file is part of MoDELib, the Mechanics Of Defects Evolution Library.
2 *
3 *
4 * MoDELib is distributed without any warranty under the
5 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
6 */
7
8#ifndef model_LoopNetwork_H_
9#define model_LoopNetwork_H_
10
11
12template <typename T>
14
15template <typename T>
17
18template <typename T>
20
21
22#include <iostream>
23#include <assert.h>
24#include <memory>
25#include <tuple>
26#include <map>
27#include <vector>
28#include <deque>
29#include <utility>
30#include <algorithm>
31
32#ifdef _OPENMP
33#include <omp.h>
34#endif
35
36#include <CRTP.h>
37
38//#include <NetworkNode.h>
39//#include <LoopLink.h>
40//#include <NetworkLink.h>
42#include <Loop.h>
43#include <LoopNode.h>
44#include <LoopLink.h>
45
46#include <NetworkNode.h>
47#include <WeakPtrFactories.h>
48
50//#include <NetworkComponent.h>
51//#include <NetworkComponentObserver.h>
52//#include <EqualIteratorRange.h>
53//#include <KeyConstructableSharedPtrFactory.h>
54
55#ifndef NDEBUG
56#define VerboseLoopNetwork(N,x) if(verboseLevel>=N){std::cout<<x;}
57#else
58#define VerboseLoopNetwork(N,x)
59#endif
60
61namespace model
62{
63
64 template<typename FlowType>
65 struct NullFlow
66 {
67 static bool isZero(const FlowType&)
68 {
69 return false;
70 }
71 };
72
73 template<typename Derived>
74 class LoopNetwork : public CRTP<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>
80 {
81
82 public:
83
91 typedef std::map<typename LoopLinkType::KeyType,LoopLinkType> LoopLinkContainerType;
97
98 const LoopContainerType& loops() const
99 {
100 return *this;
101 }
102
104 {
105 return *this;
106 }
107
109 {
110 return *this;
111 }
112
114 {
115 return *this;
116 }
117
119 {
120 return *this;
121 }
122
124 {
125 return *this;
126 }
127
128
130 {
131 return *this;
132 }
133
135 {
136 return *this;
137 }
138
140 {
141 return *this;
142 }
143
145 {
146 return *this;
147 }
148
149 private:
150
151 std::pair<SharedLoopNodePtrType,SharedLoopNodePtrType> cutLoop(const SharedLoopNodePtrType& Ni,const SharedLoopNodePtrType& Nj)
152 {
153 const auto loop(Ni->loop());
154 VerboseLoopNetwork(1,"cutting loop "<<loop->tag()<<" at "<<Ni->tag()<<","<<Nj->tag()<<std::endl);
155 if(Ni!=Nj)
156 {
157 const auto linkAtI=loop->linkStartingAt(Ni);
158 const auto linkAtJ=loop->linkStartingAt(Nj);
159
160 if(linkAtI.first && linkAtJ.first)
161 {
162 if(linkAtI.second->sink!=Nj && linkAtJ.second->sink!=Ni)
163 {
164 auto currLink(linkAtI.second);
165 if(currLink->sink!=Nj)
166 {
167 std::shared_ptr<LoopType> newLoop(loops().clone(loop->key));
168
169// const bool netNodesClonable(Ni->networkNode->loopNodes().size()==1 && Nj->networkNode->loopNodes().size());
170// const auto cloneNi(loopNodes().clone(Ni->key,newLoop,netNodesClonable? networkNodes().clone(Ni->networkNode->sID) : Ni->networkNode));
171// const auto cloneNj(loopNodes().clone(Nj->key,newLoop,netNodesClonable? networkNodes().clone(Nj->networkNode->sID) : Nj->networkNode));
172
173 const auto cloneNi(loopNodes().clone(Ni->key,newLoop,Ni->networkNode));
174 const auto cloneNj(loopNodes().clone(Nj->key,newLoop,Nj->networkNode));
175
176 std::vector<std::tuple<std::shared_ptr<LoopNodeType>,std::shared_ptr<LoopNodeType>>> linksToDisconect;
177 while(currLink->source!=Nj)
178 {
179 linksToDisconect.emplace_back(currLink->source,currLink->sink);
180 currLink=currLink->next;
181 }
182
183 for(const auto& tup : linksToDisconect)
184 {
185 disconnect(std::get<0>(tup),std::get<1>(tup),loop);
186 // connect(std::get<0>(tup),std::get<1>(tup),newLoop);
187 }
188
189 for(const auto& tup : linksToDisconect)
190 {
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);
195 connect(source,sink,newLoop);
196 }
197
198 connect(cloneNj,cloneNi,newLoop); // cloneNj->cloneNi
199 connect(std::get<0>(linksToDisconect.front()),std::get<1>(linksToDisconect.back()),loop); // Ni->Nj
200 return std::make_pair(cloneNi,cloneNj);
201 }
202 }
203 }
204 }
205 return std::make_pair(SharedLoopNodePtrType(nullptr),SharedLoopNodePtrType(nullptr));
206 }
207
208
209 protected:
210 // Derived networks reconcile contours while retaining unchanged links.
212 const SharedLoopNodePtrType& n1,
213 const std::shared_ptr<LoopType>& tempLoop)
214 {
215 VerboseLoopNetwork(1,"connecting "<<n0->sID<<"->"<<n1->sID<<" ("<<tempLoop->sID<<")"<<std::endl);
216
217 if(n0->sID!=n1->sID)
218 {
219 const auto key=LoopLinkType::loopLinkKey(tempLoop,n0,n1); // even for LoopLinks we store with key (minID,maxID)
220 const auto linkIter(loopLinks().find(key));
221 if(linkIter==loopLinks().end())
222 {// link not found
223 loopLinks().try_emplace(key,n0,n1, tempLoop);
224 }
225 else
226 {// link found
227 if(linkIter->second.source->sID==n1->sID && linkIter->second.sink->sID==n0->sID)
228 {// If opposite direction disconnect
229 loopLinks().erase(linkIter);
230 }
231 }
232 }
233 }
234
235 size_t disconnect(const SharedLoopNodePtrType& n0, const SharedLoopNodePtrType& n1, const std::shared_ptr<LoopType>& loop)
236 {
237 VerboseLoopNetwork(1,"disconnecting "<<n0->sID<<"->"<<n1->sID<<" ("<<loop->sID<<")"<<std::endl);
238 return loopLinks().erase(LoopLinkType::loopLinkKey(loop,n0,n1));
239 }
240
241 public:
242
243 static int verboseLevel;
244
245
246 void insertLoop(const std::shared_ptr<LoopType>& loop,
247 const std::vector<std::shared_ptr<LoopNodeType>> nodes)
248 {
255
256 for(size_t k=0;k<nodes.size();++k)
257 {
258 const size_t next=k+1<nodes.size()? k+1 : 0;
259 connect(nodes[k],nodes[next],loop);
260 }
261
262 assert(loop->isLoop() && "Not a loop.");
263
264 loop->update();
265 }
266
267 void insertLoop(const std::shared_ptr<LoopType>& loop,
268 const std::deque<std::shared_ptr<LoopNodeType>> nodes)
269 {
276
277 for(size_t k=0;k<nodes.size();++k)
278 {
279 const size_t next=k+1<nodes.size()? k+1 : 0;
280 connect(nodes[k],nodes[next],loop);
281 }
282
283 assert(loop->isLoop() && "Not a loop.");
284
285 loop->update();
286 }
287
288 void deleteLoop(const size_t& loopID)
289 {
290 for(typename LoopLinkContainerType::const_iterator loopIter=loopLinks().begin();
291 /* */ loopIter!=loopLinks().end();)
292 {
293 if(loopIter->second.loop->sID==loopID)
294 {
295 loopIter=loopLinks().erase(loopIter);
296 }
297 else
298 {
299 loopIter++;
300 }
301 }
302 }
303
304 SharedNetworkNodePtrType expandNetworkLink(const std::shared_ptr<NetworkLinkType>& Lij, const SharedNetworkNodePtrType& networkNode)
305 {
306 VerboseLoopNetwork(1,"expanding NetworkLink "<<Lij->tag()<<" at node "<<networkNode->tag()<<std::endl);
307 const auto loopLinks(Lij->loopLinks()); // copy loop links
308 for(const auto& loopLink : loopLinks)
309 {
310 expandLoopLink(*loopLink,loopNodes().create(loopLink->loop,networkNode,loopLink));
311 }
312 return networkNode;
313 }
314
316 {
317 VerboseLoopNetwork(1,"expanding LoopLink "<<Lij.tag()<<" at node "<<loopNode->tag()<<std::endl);
318 const SharedLoopNodePtrType source(Lij.source);
319 const SharedLoopNodePtrType sink(Lij.sink);
320 const std::shared_ptr<LoopType> loop(Lij.loop);
321 disconnect(source,sink,loop);
322 connect(source,loopNode,loop);
323 connect(loopNode,sink,loop);
324 return loopNode;
325 }
326
327 void removeNetworkNode(const size_t& nodeID)
328 {
329 if(networkNodes().find(nodeID)!=networkNodes().end())
330 {
332 }
333 }
334
336 {
337 std::set<typename LoopNodeType::KeyType> loopNodesSet;
338 for(const auto& loopNode : node->loopNodes())
339 {
340 loopNodesSet.insert(loopNode->key);
341 }
342
343 for(const auto& key : loopNodesSet)
344 {
346 }
347 }
348
349 void removeLoopNode(const size_t& nodeID)
350 {
351 if(loopNodes().find(nodeID)!=loopNodes().end())
352 {
353 removeLoopNode(loopNodes().get(nodeID));
354 }
355 }
356
357
358
360 {
361 // std::cout<<" Starting to remove loopNode "<<std::endl;
362 if(node)
363 {
364 const auto loop(node->loop());
365 // std::cout<<" LoopNodes size of the loop "<<node->loop()->isLoop()<<" "<<node->loop()->linkSequence().size()<<std::endl;
366 if(loop)
367 {
368 // std::cout<<"Getting prev"<<std::endl;
369 // std::cout<<" Checking previous "<<(node->prev.first==nullptr)<<std::endl;
370 // std::cout<<" Checking next "<<(node->next.first==nullptr)<<std::endl;
371 if (node->prev.first && node->next.first)
372 {
373 const SharedLoopNodePtrType prev(loopNodes().get(node->prev.first->key));
374 // std::cout<<"Getting Next"<<std::endl;
375 const SharedLoopNodePtrType next(loopNodes().get(node->next.first->key));
376 // std::cout<<"Moving onto disconnecting"<<std::endl;
377 if (prev)
378 {
379 // std::cout<<"Disconnecting Prev"<<std::endl;
380 disconnect(prev, node, loop);
381 }
382 if (next)
383 {
384 // std::cout<<"Disconnecting Next"<<std::endl;
385
386 disconnect(node, next, loop);
387 }
388 if (prev && next)
389 {
390 // std::cout<<"Connecting Prev and Next"<<std::endl;
391
392 connect(prev, next, loop);
393 }
394 }
395
396 }
397 }
398 }
399
400 bool contractLoopNodes(const LoopNodeType* const Ni,const LoopNodeType* const Nj)
401 {
402 if(Ni!=nullptr && Nj!=nullptr)
403 {
404 const auto sharedNi(loopNodes().get(Ni->key));
405 const auto sharedNj(loopNodes().get(Nj->key));
406 assert(sharedNi && sharedNj);
407 return contractLoopNodes(sharedNi,sharedNj);
408 }
409 return false;
410 }
411
413 {
414 if(Nj->isContractableTo(Ni.get()))
415 {
416 const auto clones(cutLoop(Ni,Nj));
417 // std::cout<<"First => second clone check"<<(clones.first!=nullptr)<<"=>"<<(clones.second!=nullptr)<<std::endl;
418 removeLoopNode(Nj);
419 if(clones.first && clones.second)
420 {
421 removeLoopNode(clones.second);
422 }
423 return true;
424 }
425 return false;
426 }
427
429 {
430 if(!Ni || !Nj || Ni==Nj || Ni->loopNodes().empty() || Nj->loopNodes().empty() ||
431 !Nj->isContractableTo(Ni))
432 {
433 return false;
434 }
435 // Cutting one loop changes membership and may destroy other nodes.
436 // Keep only the current pair alive and rediscover candidates each time.
437 while(true)
438 {
441 for(const auto* i : Ni->loopNodes())
442 {
443 for(const auto* j : Nj->loopNodes())
444 {
445 if(j->isContractableTo(i))
446 {
447 first=loopNodes().get(i->key);
448 second=loopNodes().get(j->key);
449 break;
450 }
451 }
452 if(first)
453 {
454 break;
455 }
456 }
457 if(!first)
458 {
459 break;
460 }
461 contractLoopNodes(first,second);
462 }
463 // Each remaining representation belongs to a different loop/patch.
464 // Reassign it once, even if the survivor no longer has loop nodes.
465 std::vector<SharedLoopNodePtrType> remaining;
466 for(const auto* node : Nj->loopNodes())
467 {
468 remaining.push_back(loopNodes().get(node->key));
469 }
470 for(const auto& node : remaining)
471 {
472 Nj->removeLoopNode(node.get());
473 node->networkNode=Ni;
474 Ni->addLoopNode(node.get());
475 if(node->prev.second)
476 {
477 node->prev.second->resetNetworkLink();
478 }
479 if(node->next.second)
480 {
481 node->next.second->resetNetworkLink();
482 }
483 }
484 return true;
485 }
486
487 void printLoops() const
488 {
489 for(const auto& loop : loops())
490 {
491 loop.second.lock()->printLoop();
492 }
493 }
494
495 void printLoopNodes() const
496 {
497 std::cout<<"Printing LoopNodes "<<loopNodes().size()<<std::endl;
498 for(const auto& node : loopNodes())
499 {
500 std::cout<<node.second.lock()->tag()<<std::endl;
501 }
502 }
503
504 void printNetworkNodes() const
505 {
506 std::cout<<"Printing NetworkNodes "<<networkNodes().size()<<std::endl;
507 for(const auto& node : networkNodes())
508 {
509 std::cout<<node.second.lock()->tag()<<std::endl;
510 }
511 }
512
513 };
514
515 template<typename Derived>
517
518}
519#endif
520
521
522//Giacomo Version (Original Version Working Contraction does not happen if Ni loop nodes is changed by the cutLoop Operation)
523// bool contractNetworkNodes(const SharedNetworkNodePtrType& Ni,const SharedNetworkNodePtrType& Nj)
524// {
525// if(Nj->isContractableTo(Ni))
526// {
527// std::deque<std::pair<const LoopNodeType* const,const LoopNodeType* const>> loopNodesToContract;
528// std::deque<std::pair<const size_t, const size_t>> loopNodesToReassign;
529
530
531// // Contraction should get a precendence over reassignment
532// for(const auto& loopNodeI : Ni->loopNodes())
533// {
534// for(const auto& loopNodeJ : Nj->loopNodes())
535// {
536// if(loopNodeJ->isContractableTo(loopNodeI))
537// {// this implies loopNodeI and loopNodeJ in same loop
538// std::cout<<"Contractable loop nodes "<<loopNodeI->tag()<<" -> "<<loopNodeJ->tag()<<std::endl;
539// // std::cout<<"Contractable loop nodes networkID "<<loopNodeI->networkNode->sID<<" -> "<<loopNodeJ->networkNode->sID<<std::endl;
540// loopNodesToContract.emplace_back(loopNodeI,loopNodeJ);
541// }
542// else
543// {// two cases: 1) loopNodeI and loopNodeJ in different loops 2) loopNodeI and loopNodeJ in same loop but notContractable
544// std::cout<<"Assignable loop nodes "<<loopNodeI->tag()<<" -> "<<loopNodeJ->tag()<<std::endl;
545// // std::cout<<"Assignable loop nodes networkID "<<loopNodeI->networkNode->sID<<" -> "<<loopNodeJ->networkNode->sID<<std::endl;
546// loopNodesToReassign.emplace_back(loopNodeI->sID,loopNodeJ->sID);
547// }
548// }
549// }
550
551// std::cout<<"LoopNodesToContract=>reassign size "<<loopNodesToContract.size()<<"=>"<<loopNodesToReassign.size()<<std::endl;
552// for(const auto pair : loopNodesToContract)
553// {
554// contractLoopNodes(pair.first,pair.second);
555// }
556
557// // std::cout<<"Loop Node Contraction successful "<<std::endl;
558
559// for (auto &pair : loopNodesToReassign)
560// {
561// auto loopNodeIPtr(loopNodes().get(pair.first));
562// auto loopNodeJPtr(loopNodes().get(pair.second));
563// if (loopNodeIPtr && loopNodeJPtr)
564// {
565// loopNodeJPtr->networkNode->removeLoopNode(loopNodeJPtr.get());
566// loopNodeJPtr->networkNode = loopNodeIPtr->networkNode;
567// loopNodeJPtr->networkNode->addLoopNode(loopNodeJPtr.get());
568
569// if (loopNodeJPtr->prev.second)
570// {
571// loopNodeJPtr->prev.second->resetNetworkLink();
572// }
573// if (loopNodeJPtr->next.second)
574// {
575// loopNodeJPtr->next.second->resetNetworkLink();
576// }
577// }
578// }
579// std::cout<<"After contraction and reassignemnt "<<std::endl;
580// std::cout<<"Ni "<<std::endl;
581// for (const auto& niLN : Ni->loopNodes())
582// {
583// std::cout<<niLN->tag()<<std::endl;
584// }
585// std::cout<<"Nj "<<std::endl;
586// for (const auto& njLN : Nj->loopNodes())
587// {
588// std::cout<<njLN->tag()<<std::endl;
589// }
590
591// return true;
592// }
593
594// return false;
595// }
596
597
598//Giacomo Version
599// void removeLoopNode(const SharedLoopNodePtrType& node)
600// {
601// // std::cout<<" Starting to remove loopNode "<<std::endl;
602// if(node)
603// {
604// const auto loop(node->loop());
605// std::cout<<" LoopNodes size of the loop "<<node->loop()->isLoop()<<" "<<node->loop()->linkSequence().size()<<std::endl;
606// if(loop)
607// {
608// std::cout<<"Getting prev"<<std::endl;
609// std::cout<<" Checking previous "<<(node->prev.first==nullptr)<<std::endl;
610// std::cout<<" Checking next "<<(node->next.first==nullptr)<<std::endl;
611// const SharedLoopNodePtrType prev(loopNodes().get(node->prev.first->key));
612// // std::cout<<"Getting Next"<<std::endl;
613// const SharedLoopNodePtrType next(loopNodes().get(node->next.first->key));
614// // std::cout<<"Moving onto disconnecting"<<std::endl;
615// if(prev)
616// {
617// // std::cout<<"Disconnecting Prev"<<std::endl;
618// disconnect(prev,node,loop);
619// }
620// if(next)
621// {
622// // std::cout<<"Disconnecting Next"<<std::endl;
623
624// disconnect(node,next,loop);
625// }
626// if(prev && next)
627// {
628// // std::cout<<"Connecting Prev and Next"<<std::endl;
629
630// connect(prev,next,loop);
631// }
632// }
633// }
634// }
CRTP()
The default constructor.
Definition CRTP.h:37
NetworkNodeContainerType & networkNodes()
LoopLinkContainerType & loopLinks()
TypeTraits< Derived >::LoopType LoopType
Definition LoopNetwork.h:88
bool contractNetworkNodes(const SharedNetworkNodePtrType &Ni, const SharedNetworkNodePtrType &Nj)
LoopNodeContainerType::SharedPtrType SharedLoopNodePtrType
Definition LoopNetwork.h:95
const LoopContainerType & loops() const
Definition LoopNetwork.h:98
const LoopLinkContainerType & loopLinks() const
WeakPtrFactory< Derived, NetworkNodeType > NetworkNodeContainerType
Definition LoopNetwork.h:93
TypeTraits< Derived >::LoopNodeType LoopNodeType
Definition LoopNetwork.h:84
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
Definition LoopNetwork.h:92
const NetworkLinkContainerType & networkLinks() const
void removeLoopNode(const size_t &nodeID)
const NetworkNodeContainerType & networkNodes() const
void printLoops() const
void printLoopNodes() const
const LoopNodeContainerType & loopNodes() const
NetworkLinkContainerType & networkLinks()
LoopNodeContainerType & loopNodes()
std::map< typename LoopLinkType::KeyType, LoopLinkType > LoopLinkContainerType
Definition LoopNetwork.h:91
void deleteLoop(const size_t &loopID)
TypeTraits< Derived >::NetworkLinkType NetworkLinkType
Definition LoopNetwork.h:87
LoopContainerType & loops()
static int verboseLevel
bool contractLoopNodes(const SharedLoopNodePtrType &Ni, const SharedLoopNodePtrType &Nj)
TypeTraits< Derived >::NetworkNodeType NetworkNodeType
Definition LoopNetwork.h:85
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
Definition LoopNetwork.h:89
NetworkNodeContainerType::SharedPtrType SharedNetworkNodePtrType
Definition LoopNetwork.h:96
void printNetworkNodes() const
WeakPtrFactory< Derived, NetworkLinkType > NetworkLinkContainerType
Definition LoopNetwork.h:94
WeakPtrFactory< Derived, LoopType > LoopContainerType
Definition LoopNetwork.h:90
void insertLoop(const std::shared_ptr< LoopType > &loop, const std::vector< std::shared_ptr< LoopNodeType > > nodes)
TypeTraits< Derived >::LoopLinkType LoopLinkType
Definition LoopNetwork.h:86
void insertLoop(const std::shared_ptr< LoopType > &loop, const std::deque< std::shared_ptr< LoopNodeType > > nodes)
static bool isZero(const FlowType &)
Definition LoopNetwork.h:67
std::shared_ptr< LoopNodeType > SharedPtrType
SharedPtrType clone(const KeyType &key, const Args &... args)
int end[2]
int j
int k
int i
newbad key
vertex first