Program listing for file kernel/src/utils/SiconosTools/SiconosGraph.hpp#
Return to documentation for this file
1#ifndef SICONOS_GRAPH_HPP
2#define SICONOS_GRAPH_HPP
3
4#ifndef BOOST_NO_HASH
5#define BOOST_NO_HASH
6#endif
7
8#include <boost/config.hpp>
9#include <boost/version.hpp>
10
11#include <SiconosConfig.h>
12#if !defined(SICONOS_USE_MAP_FOR_HASH)
13#include <unordered_map>
14#else
15#include <map>
16#endif
17
18#include <limits>
19#include <boost/graph/graph_utility.hpp>
20#include <boost/graph/adjacency_list.hpp>
21#include <boost/graph/graph_concepts.hpp>
22#include <boost/graph/directed_graph.hpp>
23#include <boost/property_map/property_map.hpp>
24#include <boost/static_assert.hpp>
25#include "SiconosSerialization.hpp"
26
27enum vertex_properties_t { vertex_properties };
28enum edge_properties_t { edge_properties };
29enum graph_properties_t { graph_properties };
30
31
32
33
34enum vertex_siconos_bundle_t { vertex_siconos_bundle };
35enum edge_siconos_bundle_t { edge_siconos_bundle };
36
37namespace boost
38{
39 using std::size_t;
40
41 BOOST_INSTALL_PROPERTY(vertex, properties);
42 BOOST_INSTALL_PROPERTY(edge, properties);
43 BOOST_INSTALL_PROPERTY(graph, properties);
44 BOOST_INSTALL_PROPERTY(vertex, siconos_bundle);
45 BOOST_INSTALL_PROPERTY(edge, siconos_bundle);
46}
47
48
49
50template < class V, class E, class VProperties,
51 class EProperties, class GProperties >
52class SiconosGraph
53{
54public:
55
56
57 typedef boost::adjacency_list < boost::listS, boost::listS,
58 boost::undirectedS > proxy_graph_t;
59
60 typedef typename
61 boost::graph_traits<proxy_graph_t>::edge_descriptor EDescriptor;
62
63 typedef typename
64 boost::graph_traits<proxy_graph_t>::vertex_descriptor VDescriptor;
65
66
67 typedef boost::adjacency_list <
68 boost::listS, boost::listS, boost::undirectedS,
69 boost::property
70 < vertex_siconos_bundle_t, V,
71 boost::property <
72 boost::vertex_color_t ,
73 boost::default_color_type ,
74 boost::property < boost::vertex_index_t,
75 size_t,
76 boost::property < vertex_properties_t,
77 VProperties
78 > > > > ,
79 boost::property
80 < edge_siconos_bundle_t, E,
81 boost::property <
82 boost::edge_color_t ,
83 boost::default_color_type ,
84 boost::property < boost::edge_index_t,
85 size_t,
86 boost::property < edge_properties_t ,
87 EProperties
88 > > > > ,
89 boost::property < graph_properties_t, GProperties > >
90 graph_t;
91
92 typedef V vertex_t;
93
94 typedef E edge_t;
95
96 typedef typename
97 boost::graph_traits<graph_t>::edge_iterator EIterator;
98
99 typedef typename
100 boost::graph_traits<graph_t>::vertex_iterator VIterator;
101
102
103
104
105
106
107
108 typedef typename
109 boost::graph_traits<graph_t>::out_edge_iterator OEIterator;
110
111 typedef typename
112 boost::graph_traits<graph_t>::adjacency_iterator AVIterator;
113
114 typedef typename
115 boost::property_map<graph_t, edge_siconos_bundle_t >::type EBundleAccess;
116
117 typedef typename
118 boost::property_map<graph_t, vertex_siconos_bundle_t >::type VBundleAccess;
119
120 typedef typename
121 boost::property_map<graph_t, boost::edge_color_t >::type EColorAccess;
122
123 typedef typename
124 boost::property_map<graph_t, boost::vertex_color_t >::type VColorAccess;
125
126 typedef typename
127 boost::property_map<graph_t, boost::edge_index_t >::type EIndexAccess;
128
129 typedef typename
130 boost::property_map<graph_t, boost::vertex_index_t >::type VIndexAccess;
131
132 typedef typename
133 boost::property_map<graph_t, edge_properties_t >::type EPropertiesAccess;
134
135 typedef typename
136 boost::property_map<graph_t, vertex_properties_t >::type VPropertiesAccess;
137
138
139
140
141
142#if !defined(SICONOS_USE_MAP_FOR_HASH)
143 typedef typename std::unordered_map<V, VDescriptor> VMap;
144#else
145 typedef typename std::map<V, VDescriptor> VMap;
146#endif
147
148
149 int _stamp;
150 VMap vertex_descriptor;
151
152protected:
153
154 typedef void serializable;
155 template<typename Archive>
156 friend void siconos_io(Archive&, SiconosGraph < V, E, VProperties, EProperties,
157 GProperties > &,
158 const unsigned int);
159 friend class boost::serialization::access;
160
161 graph_t g;
162
163private:
164
165 SiconosGraph(const SiconosGraph&);
166
167public:
168
169
170 SiconosGraph() : _stamp(0)
171 {
172 };
173
174 ~SiconosGraph()
175 {
176 g.clear();
177 };
178
179 const graph_t& storage() const
180 {
181 return g;
182 }
183
184
185 std::pair<EDescriptor, bool>
186 edge(VDescriptor u, VDescriptor v) const
187 {
188 return boost::edge(u, v, g);
189 }
190
191 bool edge_exists(const VDescriptor& vd1, const VDescriptor& vd2) const
192 {
193 bool ret = false;
194 EDescriptor tmped;
195 std::tie(tmped, ret) = edge(vd1, vd2);
196
197#ifndef NDEBUG
198 bool check_ret = false;
199 AVIterator avi, aviend;
200 for (std::tie(avi, aviend) = adjacent_vertices(vd1);
201 avi != aviend; ++avi)
202 {
203 if (*avi == vd2)
204 {
205 check_ret = true;
206 break;
207 }
208 assert(is_vertex(bundle(*avi)));
209 assert(bundle(descriptor(bundle(*avi))) == bundle(*avi));
210 }
211 assert(ret == check_ret);
212#endif
213
214 return ret;
215 }
216
217
218 std::pair<EDescriptor, EDescriptor>
219 edges(VDescriptor u, VDescriptor v) const
220 {
221
222
223 OEIterator oei, oeiend;
224 bool ifirst = false;
225 bool isecond = false;
226 EDescriptor first, second;
227 for (std::tie(oei, oeiend) = out_edges(u); oei != oeiend; ++oei)
228 {
229 if (target(*oei) == v)
230 {
231 if (!ifirst)
232 {
233 ifirst = true;
234 first = *oei;
235 }
236 else
237 {
238 isecond = true;
239 second = *oei;
240 break;
241 }
242 }
243 }
244
245 if (ifirst && isecond)
246 {
247 if (index(first) < index(second))
248 {
249 return std::pair<EDescriptor, EDescriptor>(first, second);
250 }
251 else
252 {
253 return std::pair<EDescriptor, EDescriptor>(second, first);
254 }
255 }
256 else if (ifirst)
257 {
258 return std::pair<EDescriptor, EDescriptor>(first, first);
259 }
260 else
261 {
262 throw(1);
263 }
264
265 }
266
267 bool is_edge(const VDescriptor& vd1, const VDescriptor& vd2,
268 const E& e_bundle) const
269 {
270 bool found = false;
271 OEIterator oei, oeiend;
272 for (std::tie(oei, oeiend) = out_edges(vd1);
273 oei != oeiend; ++oei)
274 {
275 if (target(*oei) == vd2 && bundle(*oei) == e_bundle)
276 {
277 found = true;
278 break;
279 }
280 }
281 return found;
282 }
283
284 bool adjacent_vertex_exists(const VDescriptor& vd) const
285 {
286 bool ret = false;
287 VIterator vi, viend;
288 for (std::tie(vi, viend) = vertices(); vi != viend; ++vi)
289 {
290 assert(is_vertex(bundle(*vi)));
291 assert(bundle(descriptor(bundle(*vi))) == bundle(*vi));
292
293 ret = edge_exists(vd, *vi);
294 if (ret) break;
295 }
296 return ret;
297 }
298
299
300 size_t size() const
301 {
302 return boost::num_vertices(g);
303 };
304
305 size_t vertices_number() const
306 {
307 return boost::num_vertices(g);
308 };
309
310 size_t edges_number() const
311 {
312 return boost::num_edges(g);
313 };
314
315 inline V& bundle(const VDescriptor& vd)
316 {
317 return boost::get(vertex_siconos_bundle, g)[vd];
318 };
319
320 inline const V& bundle(const VDescriptor& vd) const
321 {
322 return boost::get(vertex_siconos_bundle, g)[vd];
323 };
324
325 inline E& bundle(const EDescriptor& ed)
326 {
327 return boost::get(edge_siconos_bundle, g)[ed];
328 };
329
330 inline const E& bundle(const EDescriptor& ed) const
331 {
332 return boost::get(edge_siconos_bundle, g)[ed];
333 };
334
335 inline boost::default_color_type& color(const VDescriptor& vd)
336 {
337 return boost::get(boost::vertex_color, g)[vd];
338 };
339
340 inline const boost::default_color_type& color(const VDescriptor& vd) const
341 {
342 return boost::get(boost::vertex_color, g)[vd];
343 };
344
345 inline boost::default_color_type& color(const EDescriptor& ed)
346 {
347 return boost::get(boost::edge_color, g)[ed];
348 };
349
350 inline const boost::default_color_type& color(const EDescriptor& ed) const
351 {
352 return boost::get(boost::edge_color, g)[ed];
353 };
354
355 inline GProperties& properties()
356 {
357 return boost::get_property(g, graph_properties);
358 };
359
360 inline size_t& index(const VDescriptor& vd)
361 {
362 return boost::get(boost::vertex_index, g)[vd];
363 };
364
365 inline const size_t& index(const VDescriptor& vd) const
366 {
367 return boost::get(boost::vertex_index, g)[vd];
368 };
369
370 inline size_t& index(const EDescriptor& ed)
371 {
372 return boost::get(boost::edge_index, g)[ed];
373 };
374
375 inline const size_t& index(const EDescriptor& ed) const
376 {
377 return boost::get(boost::edge_index, g)[ed];
378 };
379
380 inline VProperties& properties(const VDescriptor& vd)
381 {
382 return boost::get(vertex_properties, g)[vd];
383 };
384
385 inline EProperties& properties(const EDescriptor& ed)
386 {
387 return boost::get(edge_properties, g)[ed];
388 };
389
390
391
392
393
394
395
396
397
398
399
400 inline bool is_vertex(const V& vertex) const
401 {
402 return (vertex_descriptor.find(vertex) != vertex_descriptor.end());
403 }
404
405 inline const VDescriptor& descriptor(const V& vertex) const
406 {
407 assert(size() == vertex_descriptor.size());
408 assert(vertex_descriptor.find(vertex) != vertex_descriptor.end());
409 return (*vertex_descriptor.find(vertex)).second;
410 }
411
412 inline std::pair<VIterator, VIterator> vertices() const
413 {
414 return boost::vertices(g);
415 };
416
417 inline VIterator begin() const
418 {
419 VIterator vi, viend;
420 std::tie(vi, viend) = vertices();
421 return vi;
422 }
423
424 inline VIterator end() const
425 {
426 VIterator vi, viend;
427 std::tie(vi, viend) = vertices();
428 return viend;
429 }
430
431 inline std::pair<AVIterator, AVIterator> adjacent_vertices(const VDescriptor& vd) const
432 {
433 return boost::adjacent_vertices(vd, g);
434 };
435
436 inline std::pair<EIterator, EIterator> edges() const
437 {
438 return boost::edges(g);
439 };
440
441 inline std::pair<OEIterator, OEIterator> out_edges(const VDescriptor& vd) const
442 {
443 return boost::out_edges(vd, g);
444 };
445
446 inline VDescriptor target(const EDescriptor& ed) const
447 {
448 return boost::target(ed, g);
449 };
450
451 inline VDescriptor source(const EDescriptor& ed) const
452 {
453 return boost::source(ed, g);
454 };
455
456
457 VDescriptor add_vertex(const V& vertex_bundle)
458 {
459 assert(vertex_descriptor.size() == size()) ;
460
461 VDescriptor new_vertex_descriptor;
462 typename VMap::iterator current_vertex_iterator =
463 vertex_descriptor.find(vertex_bundle);
464
465 if (current_vertex_iterator == vertex_descriptor.end())
466 {
467 new_vertex_descriptor = boost::add_vertex(g);
468
469 assert(vertex(size() - 1, g) == new_vertex_descriptor);
470 assert(size() == vertex_descriptor.size() + 1);
471
472 vertex_descriptor[vertex_bundle] = new_vertex_descriptor;
473 assert(size() == vertex_descriptor.size());
474
475 bundle(new_vertex_descriptor) = vertex_bundle;
476
477 assert(descriptor(vertex_bundle) == new_vertex_descriptor);
478 assert(bundle(descriptor(vertex_bundle)) == vertex_bundle);
479
480 index(new_vertex_descriptor) = std::numeric_limits<size_t>::max() ;
481 return new_vertex_descriptor;
482 }
483 else
484 {
485 assert(descriptor(vertex_bundle) == current_vertex_iterator->second);
486 assert(bundle(descriptor(vertex_bundle)) == vertex_bundle);
487 return current_vertex_iterator->second;
488 }
489
490
491 assert(false) ;
492 }
493
494 template<class G> void copy_vertex(const V& vertex_bundle, G& og)
495 {
496
497
498 BOOST_STATIC_ASSERT((boost::is_same
499 <typename G::vertex_t, vertex_t>::value));
500 BOOST_STATIC_ASSERT((boost::is_same
501 <typename G::edge_t, edge_t>::value));
502
503 assert(og.is_vertex(vertex_bundle));
504
505 VDescriptor descr = add_vertex(vertex_bundle);
506 properties(descr) = og.properties(og.descriptor(vertex_bundle));
507
508
509 assert(bundle(descr) == vertex_bundle);
510
511
512 typename G::OEIterator ogoei, ogoeiend;
513 for (std::tie(ogoei, ogoeiend) =
514 og.out_edges(og.descriptor(vertex_bundle));
515 ogoei != ogoeiend; ++ogoei)
516 {
517 typename G::VDescriptor ognext_descr = og.target(*ogoei);
518
519 assert(og.is_vertex(og.bundle(ognext_descr)));
520
521
522 if (is_vertex(og.bundle(ognext_descr)))
523 {
524 assert(bundle(descriptor(og.bundle(ognext_descr)))
525 == og.bundle(ognext_descr));
526
527 EDescriptor edescr =
528 add_edge(descr, descriptor(og.bundle(ognext_descr)),
529 og.bundle(*ogoei));
530
531 properties(edescr) = og.properties(*ogoei);
532
533
534 assert(bundle(edescr) == og.bundle(*ogoei));
535 }
536 }
537 }
538
539 void remove_vertex(const V& vertex_bundle)
540 {
541 assert(is_vertex(vertex_bundle));
542 assert(vertex_descriptor.size() == size());
543 assert(bundle(descriptor(vertex_bundle)) == vertex_bundle);
544
545
546 VDescriptor vd = descriptor(vertex_bundle);
547
548#ifndef NDEBUG
549 assert(adjacent_vertices_ok());
550#endif
551 boost::clear_vertex(vd, g);
552
553#ifndef NDEBUG
554 assert(adjacent_vertices_ok());
555 assert(!adjacent_vertex_exists(vd));
556#endif
557 boost::remove_vertex(vd, g);
558
559 assert(vertex_descriptor.size() == (size() + 1));
560
561 vertex_descriptor.erase(vertex_bundle);
562
563
564#ifndef NDEBUG
565 assert(adjacent_vertices_ok());
566 assert(vertex_descriptor.size() == size());
567 assert(!is_vertex(vertex_bundle));
568 assert(state_assert());
569#endif
570 }
571
572
573 EDescriptor add_edge(const VDescriptor& vd1,
574 const VDescriptor& vd2,
575 const E& e_bundle)
576 {
577
578 EDescriptor new_edge;
579 bool inserted;
580
581 assert(is_vertex(bundle(vd1)));
582 assert(is_vertex(bundle(vd2)));
583
584 assert(descriptor(bundle(vd1)) == vd1);
585 assert(descriptor(bundle(vd2)) == vd2);
586
587 assert(!is_edge(vd1, vd2, e_bundle));
588
589 std::tie(new_edge, inserted) = boost::add_edge(vd1, vd2, g);
590
591
592
593 assert(inserted);
594
595 index(new_edge) = std::numeric_limits<size_t>::max();
596
597 bundle(new_edge) = e_bundle;
598
599 assert(is_edge(vd1, vd2, e_bundle));
600
601 return new_edge;
602 }
603
604
605
606
607 template<class AdjointG>
608 std::pair<EDescriptor, typename AdjointG::VDescriptor>
609 add_edge(const VDescriptor& vd1,
610 const VDescriptor& vd2,
611 const E& e_bundle,
612 AdjointG& ag)
613 {
614
615
616 BOOST_STATIC_ASSERT((boost::is_same
617 <typename AdjointG::vertex_t, edge_t>::value));
618 BOOST_STATIC_ASSERT((boost::is_same
619 <typename AdjointG::edge_t, vertex_t>::value));
620
621
622 EDescriptor new_ed = add_edge(vd1, vd2, e_bundle);
623
624 typename AdjointG::VDescriptor new_ve = ag.add_vertex(e_bundle);
625
626 assert(bundle(new_ed) == ag.bundle(new_ve));
627 assert(ag.size() == edges_number());
628
629
630 bool endl = false;
631 for (VDescriptor vdx = vd1; !endl; vdx = vd2)
632 {
633 assert(vdx == vd1 || vdx == vd2);
634
635 if (vdx == vd2) endl = true;
636
637#if !defined(SICONOS_USE_MAP_FOR_HASH)
638 std::unordered_map<E, EDescriptor> Edone;
639#else
640 std::map<E, EDescriptor> Edone;
641#endif
642
643
644 OEIterator ied, iedend;
645 for (std::tie(ied, iedend) = out_edges(vdx);
646 ied != iedend; ++ied)
647 {
648 if (Edone.find(bundle(*ied)) == Edone.end())
649 {
650 Edone[bundle(*ied)] = *ied;
651
652 assert(source(*ied) == vdx);
653
654 if (*ied != new_ed)
655
656 {
657 assert(bundle(*ied) != e_bundle);
658
659 assert(ag.bundle(ag.descriptor(bundle(*ied))) == bundle(*ied));
660
661 assert(ag.is_vertex(bundle(*ied)));
662
663 assert(new_ve != ag.descriptor(bundle(*ied)));
664
665 assert(!ag.is_edge(new_ve, ag.descriptor(bundle(*ied)),
666 bundle(vdx)));
667
668 typename AdjointG::EDescriptor aed =
669 ag.add_edge(new_ve, ag.descriptor(bundle(*ied)),
670 bundle(vdx));
671
672 assert(ag.bundle(aed) == bundle(vdx));
673
674 }
675 }
676
677 }
678 }
679 assert(ag.size() == edges_number());
680 return std::pair<EDescriptor, typename AdjointG::VDescriptor>(new_ed,
681 new_ve);
682 }
683
684 void remove_edge(const EDescriptor& ed)
685 {
686 assert(adjacent_vertex_exists(target(ed)));
687 assert(adjacent_vertex_exists(source(ed)));
688
689 boost::remove_edge(ed, g);
690
691#ifndef NDEBUG
692 assert(state_assert());
693#endif
694 }
695
696 template<class AdjointG>
697 void remove_edge(const EDescriptor& ed, AdjointG& ag)
698 {
699
700
701 BOOST_STATIC_ASSERT((boost::is_same
702 <typename AdjointG::vertex_t, edge_t>::value));
703 BOOST_STATIC_ASSERT((boost::is_same
704 <typename AdjointG::edge_t, vertex_t>::value));
705
706
707 assert(ag.size() == edges_number());
708
709 assert(bundle(ed) == ag.bundle(ag.descriptor(bundle(ed))));
710
711 remove_vertex(ag.bundle(ag.descriptor(bundle(ed))));
712 remove_edge(ed);
713
714 assert(ag.size() == edges_number());
715
716#ifndef NDEBUG
717 assert(state_assert());
718#endif
719 }
720
721
722 template<class Predicate>
723 void remove_out_edge_if(const VDescriptor& vd,
724 const Predicate& pred)
725
726 {
727
728 BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept<graph_t>));
729 BOOST_CONCEPT_ASSERT((boost::MutableGraphConcept<graph_t>));
730
731 boost::remove_out_edge_if(vd, pred, g);
732
733
734#ifndef NDEBUG
735 assert(state_assert());
736#endif
737 }
738
739
740
741 template<class Predicate>
742 void remove_in_edge_if(const VDescriptor& vd,
743 const Predicate& pred)
744
745 {
746
747 BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept<graph_t>));
748 BOOST_CONCEPT_ASSERT((boost::MutableGraphConcept<graph_t>));
749
750 boost::remove_in_edge_if(vd, pred, g);
751
752#ifndef NDEBUG
753 assert(state_assert());
754#endif
755 }
756
757
758 template<class Predicate>
759 void remove_edge_if(const VDescriptor& vd,
760 const Predicate& pred)
761
762 {
763
764 BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept<graph_t>));
765 BOOST_CONCEPT_ASSERT((boost::MutableGraphConcept<graph_t>));
766
767 boost::remove_edge_if(pred, g);
768
769#ifndef NDEBUG
770 assert(state_assert());
771#endif
772 }
773
774
775 int stamp() const
776 {
777 return _stamp;
778 }
779
780 void update_vertices_indices()
781 {
782 VIterator vi, viend;
783 size_t i;
784 for (std::tie(vi, viend) = boost::vertices(g), i = 0;
785 vi != viend; ++vi, ++i)
786 {
787 index(*vi) = i;
788 }
789 _stamp++;
790 };
791
792 void update_edges_indices()
793 {
794 EIterator ei, eiend;
795 size_t i;
796 for (std::tie(ei, eiend) = boost::edges(g), i = 0;
797 ei != eiend; ++ei, ++i)
798 {
799 index(*ei) = i;
800 }
801 _stamp++;
802 };
803
804 void clear()
805 {
806 g.clear();
807 vertex_descriptor.clear();
808 };
809
810 VMap vertex_descriptor_map() const
811 {
812 return vertex_descriptor;
813 };
814
815 void display() const
816 {
817 std::cout << "vertices number :" << vertices_number() << std::endl;
818
819 std::cout << "edges number :" << edges_number() << std::endl;
820 VIterator vi, viend;
821 for (std::tie(vi, viend) = vertices();
822 vi != viend; ++vi)
823 {
824 std::cout << "vertex :"
825 << *vi
826 << ", bundle :"
827 << bundle(*vi)
828 << ", index : "
829 << index(*vi)
830 << ", color : "
831 << color(*vi);
832 OEIterator oei, oeiend, next;
833 for (std::tie(oei, oeiend) = out_edges(*vi);
834 oei != oeiend; ++oei)
835 {
836 std::cout << "---"
837 << bundle(*oei)
838 << "-->"
839 << "bundle : "
840 << bundle(target(*oei))
841 << ", index : "
842 << index(target(*oei))
843 << ", color : "
844 << color(target(*oei));
845 }
846 std::cout << std::endl;
847 }
848 }
849
850
851#ifndef SWIG
852#ifndef NDEBUG
853 bool state_assert() const
854 {
855 VIterator vi, viend;
856 for (std::tie(vi, viend) = vertices(); vi != viend; ++vi)
857 {
858 assert(is_vertex(bundle(*vi)));
859 assert(bundle(descriptor(bundle(*vi))) == bundle(*vi));
860
861 OEIterator ei, eiend;
862 for (std::tie(ei, eiend) = out_edges(*vi);
863 ei != eiend; ++ei)
864 {
865 assert(is_vertex(bundle(target(*ei))));
866 assert(source(*ei) == *vi);
867 }
868 AVIterator avi, aviend;
869 for (std::tie(avi, aviend) = adjacent_vertices(*vi);
870 avi != aviend; ++avi)
871 {
872 assert(is_vertex(bundle(*avi)));
873 assert(bundle(descriptor(bundle(*avi))) == bundle(*avi));
874 }
875 }
876 return true;
877
878 }
879
880 bool adjacent_vertices_ok() const
881 {
882
883 VIterator vi, viend;
884 for (std::tie(vi, viend) = vertices(); vi != viend; ++vi)
885 {
886 assert(is_vertex(bundle(*vi)));
887 assert(bundle(descriptor(bundle(*vi))) == bundle(*vi));
888
889 AVIterator avi, aviend;
890 for (std::tie(avi, aviend) = adjacent_vertices(*vi);
891 avi != aviend; ++avi)
892 {
893 assert(is_vertex(bundle(*avi)));
894 assert(bundle(descriptor(bundle(*avi))) == bundle(*avi));
895 }
896 }
897 return true;
898 }
899#endif
900#endif
901
902
903};
904
905
906#endif