Program listing for file kernel/src/utils/SiconosTools/SiconosGraph.hpp

Program listing for file kernel/src/utils/SiconosTools/SiconosGraph.hpp#

  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