Gudhi  1.1.0
 All Classes Functions Typedefs Friends Groups Pages
Skeleton_blocker_complex.h
1 /* This file is part of the Gudhi Library. The Gudhi library
2  * (Geometric Understanding in Higher Dimensions) is a generic C++
3  * library for computational topology.
4  *
5  * Author(s): David Salinas
6  *
7  * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #ifndef GUDHI_SKELETON_BLOCKER_COMPLEX_H
24 #define GUDHI_SKELETON_BLOCKER_COMPLEX_H
25 
26 
27 #include <map>
28 #include <list>
29 #include <set>
30 #include <vector>
31 #include <iostream>
32 #include <string>
33 #include <fstream>
34 #include <sstream>
35 #include <memory>
36 #include <boost/graph/adjacency_list.hpp>
37 #include <boost/graph/connected_components.hpp>
38 #include <boost/iterator/transform_iterator.hpp>
39 #include <boost/range/adaptor/map.hpp>
40 
41 #include "gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h"
42 #include "gudhi/Skeleton_blocker_link_complex.h"
43 #include "gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h"
44 #include "gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h"
45 #include "gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h"
46 
47 #include "gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h"
48 #include "gudhi/Skeleton_blocker/internal/Top_faces.h"
49 #include "gudhi/Utils.h"
50 
51 
52 namespace Gudhi {
53 
54 namespace skbl {
55 
56 
62 template<class SkeletonBlockerDS>
64 {
65  template<class ComplexType> friend class Complex_vertex_iterator;
66  template<class ComplexType> friend class Complex_neighbors_vertices_iterator;
67  template<class ComplexType> friend class Complex_edge_iterator;
68  template<class ComplexType> friend class Complex_edge_around_vertex_iterator;
69 
70 
71  template<class ComplexType> friend class Skeleton_blocker_link_complex;
72  template<class ComplexType> friend class Skeleton_blocker_link_superior;
73  template<class ComplexType> friend class Skeleton_blocker_sub_complex;
74 
75 public:
76 
81 
86 
88 
93  typedef typename Root_vertex_handle::boost_vertex_handle boost_vertex_handle;
94 
95 
101 
102 
107 
108 
109 
110  typedef typename Root_simplex_handle::Simplex_vertex_const_iterator Root_simplex_iterator;
111  typedef typename Simplex_handle::Simplex_vertex_const_iterator Simplex_handle_iterator;
112 
113 
114 protected:
115 
116  typedef typename boost::adjacency_list
117  < boost::setS, //edges
118  boost::vecS, // vertices
119  boost::undirectedS,
120  Graph_vertex,
121  Graph_edge
122  > Graph;
123  //todo/remark : edges are not sorted, it heavily penalizes computation for SuperiorLink
124  // (eg Link with greater vertices)
125  // that burdens simplex iteration / complex initialization via list of simplices.
126  // to avoid that, one should modify the graph by storing two lists of adjacency for every
127  // vertex, the one with superior and the one with lower vertices, that way there is
128  // no more extra cost for computation of SuperiorLink
129  typedef typename boost::graph_traits<Graph>::vertex_iterator boost_vertex_iterator;
130  typedef typename boost::graph_traits<Graph>::edge_iterator boost_edge_iterator;
131 
132 protected:
133  typedef typename boost::graph_traits<Graph>::adjacency_iterator boost_adjacency_iterator;
134 
135 public:
139  typedef typename boost::graph_traits<Graph>::edge_descriptor Edge_handle;
140 
141 
142 protected:
143  typedef std::multimap<Vertex_handle,Simplex_handle *> BlockerMap;
144  typedef typename std::multimap<Vertex_handle,Simplex_handle *>::value_type BlockerPair;
145  typedef typename std::multimap<Vertex_handle,Simplex_handle *>::iterator BlockerMapIterator;
146  typedef typename std::multimap<Vertex_handle,Simplex_handle *>::const_iterator BlockerMapConstIterator;
147 
148 protected:
149  int num_vertices_;
150  int num_blockers_;
151 
153  // typedef Visitor* Visitor_ptr;
154  Visitor* visitor;
155 
164  std::vector<boost_vertex_handle> degree_;
165  Graph skeleton;
168  //todo remove!!!
169 
171  BlockerMap blocker_map_;
172 
173 
174 
175 
176 public:
177 
178 
179 
180 
182 
188  Skeleton_blocker_complex(int num_vertices_ = 0,Visitor* visitor_=NULL):visitor(visitor_){
189  clear();
190  for (int i=0; i<num_vertices_; ++i){
191  add_vertex();
192  }
193  }
194 
195 private:
196 
202  class Simplices_sets_from_list{
203  private:
204  typedef std::set< Simplex_handle> Container_simplices;
205  typedef typename Container_simplices::iterator Simplices_iterator;
206  int dimension_;
207  std::vector<Container_simplices > simplices_;
208 
209  public:
210  Simplices_sets_from_list(std::list<Simplex_handle>& simplices):
211  dimension_(-1){
212  assert(!simplices.empty());
213 
214  for(auto simplex = simplices.begin() ; simplex != simplices.end(); ++simplex ){
215  dimension_ = std::max(dimension_,(int)simplex->dimension());
216  }
217  simplices_ = std::vector<Container_simplices >(dimension_+1);
218 
219  // compute k-simplices
220  for(auto simplex = simplices.begin() ; simplex != simplices.end(); ++simplex ){
221  simplices_[simplex->dimension()].insert(*simplex);
222  }
223  }
224 
225  Simplices_iterator begin(int k){
226  assert(0<= k && k<= dimension_);
227  return simplices_[k].begin();
228  }
229 
230  Simplices_iterator end(int k){
231  assert(0<= k && k<= dimension_);
232  return simplices_[k].end();
233  }
234 
235 
236  Container_simplices& simplices(int k){
237  return simplices_[k];
238  }
239 
240  int dimension(){
241  return dimension_;
242  }
243 
244  bool contains(const Simplex_handle& simplex) const{
245  if(simplex.dimension()>dimension_)
246  return false;
247  else
248  return simplices_[simplex.dimension()].find(simplex)!= simplices_[simplex.dimension()].end();
249  }
250 
251  void print(){
252  for(int i = 0; i < dimension_; ++i){
253  std::cout << i<<"-simplices"<<std::endl;
254  auto l = simplices_[i];
255  for(auto s : l){
256  std::cout << s<<std::endl;
257  }
258  }
259  }
260  };
261 
262 
263  void compute_next_expand(
264  Simplices_sets_from_list& simplices,
265  int dim,
266  std::list<Simplex_handle>& next_expand)
267  {
268  next_expand.clear();
269 
270  // high_resolution_clock::time_point tbeginfor = high_resolution_clock::now();
271  // auto durationlooplink = std::chrono::duration_cast<std::chrono::microseconds>( tbeginfor - tbeginfor ).count();
272 
273  for(auto sigma = simplices.begin(dim); sigma != simplices.end(dim); ++sigma){
274  // high_resolution_clock::time_point tbeg = high_resolution_clock::now();
275  Simplex_handle t(*sigma);
276  Skeleton_blocker_link_superior<Skeleton_blocker_complex> link(*this,t);
277  // xxx all time here, most likely because accessing superior edges needs passing through lower one
278  // currently
279 
280  // durationlooplink += std::chrono::duration_cast<std::chrono::microseconds>( high_resolution_clock::now() - tbeg ).count();
281 
282  for(auto v : link.vertex_range()){
283  Vertex_handle v_in_complex(*this->get_address( link.get_id(v)) );
284  t.add_vertex(v_in_complex);
285  next_expand.push_back(t);
286  t.remove_vertex(v_in_complex);
287  }
288  }
289  // high_resolution_clock::time_point t2 = high_resolution_clock::now();
290  // auto durationlooptotal = std::chrono::duration_cast<std::chrono::microseconds>( t2 - tbeginfor ).count();
291  // DBGVALUE(durationlooptotal);
292  // DBGVALUE(durationlooplink);
293  }
294 
295 
296 
297 public:
303  Skeleton_blocker_complex(std::list<Simplex_handle>& simplices,Visitor* visitor_=NULL):
304  num_vertices_(0),num_blockers_(0),
305  visitor(visitor_){
306  Simplices_sets_from_list set_simplices(simplices);
307 
308  int dim = set_simplices.dimension();
309 
310 
311  // add 1-skeleton to the complex
312  for(auto v_it = set_simplices.begin(0); v_it != set_simplices.end(0); ++v_it)
313  add_vertex();
314 
315  for(auto e_it = set_simplices.begin(1); e_it != set_simplices.end(1); ++e_it){
316  Vertex_handle a = e_it->first_vertex();
317  Vertex_handle b = e_it->last_vertex();
318  assert(contains_vertex(a) && contains_vertex(b));
319  add_edge(a,b);
320  }
321 
322  // then add blockers
323  for(int current_dim = 1 ; current_dim <=dim ; ++current_dim){
324  std::list<Simplex_handle> expansion_simplices;
325  compute_next_expand(set_simplices,current_dim,expansion_simplices);
326 
327  for(const auto &simplex : expansion_simplices) {
328  if(!set_simplices.contains(simplex)){
329  add_blocker(simplex);
330  }
331  }
332  }
333  }
334 
335 
336  // We cannot use the default copy constructor since we need
337  // to make a copy of each of the blockers
339  visitor = NULL;
340  degree_ = copy.degree_;
341  skeleton = Graph(copy.skeleton);
342  num_vertices_ = copy.num_vertices_;
343 
344  num_blockers_ = 0;
345  // we copy the blockers
346  for (auto blocker : copy.const_blocker_range()){
347  add_blocker(*blocker);
348  }
349  }
350 
353  Skeleton_blocker_complex& operator=(const Skeleton_blocker_complex& copy){
354  clear();
355  visitor = NULL;
356  degree_ = copy.degree_;
357  skeleton = Graph(copy.skeleton);
358  num_vertices_ = copy.num_vertices_;
359 
360  num_blockers_ = 0;
361  // we copy the blockers
362  for (auto blocker : copy.const_blocker_range())
363  add_blocker(*blocker);
364  return *this;
365  }
366 
367 
372  clear();
373  }
374 
380  virtual void clear(){
381  // xxx for now the responsabilty of freeing the visitor is for
382  // the user
383  visitor = NULL;
384 
385  degree_.clear();
386  num_vertices_ =0;
387 
388  remove_blockers();
389 
390  skeleton.clear();
391  }
392 
396  void set_visitor(Visitor* other_visitor){
397  visitor = other_visitor;
398  }
399 
401 
402 
403 
404 
406 
409 
410 public:
411 
417  auto local(get_address(global));
418  assert(local);
419  return *local;
420  }
421 
427  assert(0<=address.vertex && address.vertex< boost::num_vertices(skeleton));
428  return skeleton[address.vertex];
429  }
430 
435  const Graph_vertex& operator[](Vertex_handle address) const{
436  assert(0<=address.vertex && address.vertex< boost::num_vertices(skeleton));
437  return skeleton[address.vertex];
438  }
439 
444  Vertex_handle address(boost::add_vertex(skeleton));
445  num_vertices_++;
446  (*this)[address].activate();
447  // safe since we now that we are in the root complex and the field 'address' and 'id'
448  // are identical for every vertices
449  (*this)[address].set_id(Root_vertex_handle(address.vertex));
450  degree_.push_back(0);
451  if (visitor) visitor->on_add_vertex(address);
452  return address;
453  }
454 
455 
462  assert(contains_vertex(address));
463  // We remove b
464  boost::clear_vertex(address.vertex,skeleton);
465  (*this)[address].deactivate();
466  num_vertices_--;
467  degree_[address.vertex]=-1;
468  if (visitor) visitor->on_remove_vertex(address);
469  }
470 
473  bool contains_vertex(Vertex_handle u) const{
474  if (u.vertex<0 || u.vertex>=boost::num_vertices(skeleton)) return false;
475  return (*this)[u].is_active();
476  }
477 
480  bool contains_vertex(Root_vertex_handle u) const{
481  boost::optional<Vertex_handle> address = get_address(u);
482  return address && (*this)[*address].is_active();
483  }
484 
485 
490  bool contains_vertices(const Simplex_handle & sigma) const{
491  for (auto vertex : sigma)
492  if(!contains_vertex(vertex)) return false;
493  return true;
494  }
495 
500  virtual boost::optional<Vertex_handle> get_address(Root_vertex_handle id) const{
501  boost::optional<Vertex_handle> res;
502  if ( id.vertex< boost::num_vertices(skeleton) ) res = Vertex_handle(id.vertex);//xxx
503  return res;
504  }
505 
506 
507 
512  assert(0<=local.vertex && local.vertex< boost::num_vertices(skeleton));
513  return (*this)[local].get_id();
514  }
515 
516 
528  const Skeleton_blocker_complex& other,Vertex_handle vh_in_other) const{
529  auto vh_in_current_complex = get_address(other.get_id(vh_in_other));
530  assert(vh_in_current_complex);
531  return *vh_in_current_complex;
532  }
533 
537  int degree(Vertex_handle local) const{
538  assert(0<=local.vertex && local.vertex< boost::num_vertices(skeleton));
539  return degree_[local.vertex];
540  }
541 
543 
545 
548 
549 public:
550 
555  boost::optional<Edge_handle> operator[](const std::pair<Vertex_handle,Vertex_handle>& ab) const{
556  boost::optional<Edge_handle> res;
557  std::pair<Edge_handle,bool> edge_pair(boost::edge(ab.first.vertex,ab.second.vertex,skeleton));
558  if (edge_pair.second)
559  res = edge_pair.first;
560  return res;
561  }
562 
567  return skeleton[edge_handle];
568  }
569 
573  const Graph_edge& operator[](Edge_handle edge_handle) const{
574  return skeleton[edge_handle];
575  }
576 
582  return source(edge_handle,skeleton);
583  }
584 
590  return target(edge_handle,skeleton);
591  }
592 
599  auto edge((*this)[edge_handle]);
600  return Simplex_handle((*this)[edge.first()],(*this)[edge.second()]);
601  }
602 
607  assert(contains_vertex(a) && contains_vertex(b));
608  assert(a!=b);
609 
610  auto edge_handle((*this)[std::make_pair(a,b)]);
611  // std::pair<Edge_handle,bool> pair_descr_bool = (*this)[std::make_pair(a,b)];
612  // Edge_handle edge_descr;
613  // bool edge_present = pair_descr_bool.second;
614  if (!edge_handle)
615  {
616  edge_handle = boost::add_edge(a.vertex,b.vertex,skeleton).first;
617  (*this)[*edge_handle].setId(get_id(a),get_id(b));
618  degree_[a.vertex]++;
619  degree_[b.vertex]++;
620  if (visitor) visitor->on_add_edge(a,b);
621  }
622  return *edge_handle;
623  }
624 
628  void add_edges(const Simplex_handle & sigma){
629  Simplex_handle_iterator i, j;
630  for (i = sigma.begin() ; i != sigma.end() ; ++i)
631  for (j = i, j++ ; j != sigma.end() ; ++j)
632  add_edge(*i,*j);
633  }
634 
640  bool found;
641  Edge_handle edge;
642  tie(edge,found) = boost::edge(a.vertex,b.vertex,skeleton);
643  if (found)
644  {
645  if (visitor) visitor->on_remove_edge(a,b);
646  // if (heapCollapse.Contains(edge)) heapCollapse.Delete(edge);
647  boost::remove_edge(a.vertex,b.vertex,skeleton);
648  degree_[a.vertex]--;
649  degree_[b.vertex]--;
650  }
651  return edge;
652  }
653 
654 
659  assert(contains_vertex(first_vertex(edge)));
660  assert(contains_vertex(second_vertex(edge)));
662  }
663 
664 
670  remove_blockers();
671 
672  for(auto u : vertex_range()){
673  while (this->degree(u)> 0)
674  {
675  Vertex_handle v(*(adjacent_vertices(u.vertex, this->skeleton).first));
676  this->remove_edge(u,v);
677  }
678  }
679  }
680 
681 
687  //if (a.vertex<0 || b.vertex <0) return false;
688  return boost::edge(a.vertex,b.vertex,skeleton).second;
689  }
690 
691 
696  bool contains_edges(const Simplex_handle & sigma) const{
697  for (auto i = sigma.begin() ; i != sigma.end() ; ++i){
698  if(!contains_vertex(*i)) return false;
699  for (auto j=i; ++j != sigma.end() ; ){
700  if (!contains_edge(*i,*j))
701  return false;
702  }
703  }
704  return true;
705  }
707 
708 
709 
711 
714 
720  assert(blocker.dimension()>1);
721  if (contains_blocker(blocker))
722  {
723  //std::cerr << "ATTEMPT TO ADD A BLOCKER ALREADY THERE ---> BLOCKER IGNORED" << endl;
724  return 0;
725  }
726  else{
727  if (visitor) visitor->on_add_blocker(blocker);
728  Blocker_handle blocker_pt = new Simplex_handle(blocker);
729  num_blockers_++;
730  auto vertex = blocker_pt->begin();
731  while(vertex != blocker_pt->end())
732  {
733  blocker_map_.insert(BlockerPair(*vertex,blocker_pt));
734  ++vertex;
735  }
736  return blocker_pt;
737  }
738  }
739 
740 protected:
744  void add_blocker(Blocker_handle blocker){
745  if (contains_blocker(*blocker))
746  {
747  //std::cerr << "ATTEMPT TO ADD A BLOCKER ALREADY THERE ---> BLOCKER IGNORED" << endl;
748  return;
749  }
750  else{
751  if (visitor) visitor->on_add_blocker(*blocker);
752  num_blockers_++;
753  auto vertex = blocker->begin();
754  while(vertex != blocker->end())
755  {
756  blocker_map_.insert(BlockerPair(*vertex,blocker));
757  ++vertex;
758  }
759  }
760  }
761 
762 
763 protected:
767  void remove_blocker(const Blocker_handle sigma, Vertex_handle v){
768  Complex_blocker_around_vertex_iterator blocker;
769  for (blocker = blocker_range(v).begin();
770  blocker != blocker_range(v).end();
771  ++blocker
772  ){
773  if (*blocker == sigma) break;
774  }
775  if (*blocker != sigma){
776  std::cerr << "bug ((*blocker).second == sigma) ie try to remove a blocker not present\n";
777  assert(false);
778  }
779  else{
780  blocker_map_.erase(blocker.current_position());
781  }
782  }
783 
784 public:
789  void remove_blocker(const Blocker_handle sigma){
790  for (auto vertex : *sigma){
791  remove_blocker(sigma,vertex);
792  }
793  num_blockers_--;
794  }
795 
796 
797 
798 
804  // Desallocate the blockers
805  while (!blocker_map_.empty()){
806  delete_blocker(blocker_map_.begin()->second);
807  }
808  num_blockers_ = 0;
809  blocker_map_.clear();
810  }
811 
812 protected:
819  void remove_blocker(const Simplex_handle& sigma){
820  assert(contains_blocker(sigma));
821  for (auto vertex : sigma)
822  remove_blocker(sigma,vertex);
823  num_blockers_--;
824  }
825 
826 
827 
828 
829 public:
835  if (visitor) visitor->on_delete_blocker(sigma);
836  remove_blocker(sigma);
837  delete sigma;
838  }
839 
840 
844  bool contains_blocker(const Blocker_handle s) const{
845  if (s->dimension()<2)
846  return false;
847 
848  Vertex_handle a = s->first_vertex();
849 
850  for (auto blocker : const_blocker_range(a)){
851  if ( s == *blocker )
852  return true;
853  }
854  return false;
855  }
856 
860  bool contains_blocker(const Simplex_handle & s) const{
861  if (s.dimension()<2)
862  return false;
863 
864  Vertex_handle a = s.first_vertex();
865 
866  for (auto blocker : const_blocker_range(a)){
867  if ( s == *blocker )
868  return true;
869  }
870  return false;
871  }
872 
873 
874 private:
879  bool blocks(const Simplex_handle & sigma) const{
880 
881  for(auto blocker : const_blocker_range()){
882  if ( sigma.contains(*blocker) )
883  return true;
884  }
885  return false;
886  }
887 
889 
890 
891 
892 protected:
897  virtual void add_neighbours(Vertex_handle v, Simplex_handle & n,bool keep_only_superior=false) const{
898  boost_adjacency_iterator ai, ai_end;
899  for (tie(ai, ai_end) = adjacent_vertices(v.vertex, skeleton); ai != ai_end; ++ai){
900  if (keep_only_superior){
901  if (*ai>v.vertex)
902  n.add_vertex(Vertex_handle(*ai));
903  }
904  else
905  n.add_vertex(Vertex_handle(*ai));
906  }
907  }
908 
917  virtual void add_neighbours(const Simplex_handle &alpha, Simplex_handle & res,bool keep_only_superior=false) const{
918  res.clear();
919  auto alpha_vertex = alpha.begin();
920  add_neighbours(*alpha_vertex,res,keep_only_superior);
921  for (alpha_vertex = (alpha.begin())++ ; alpha_vertex != alpha.end() ; ++alpha_vertex)
922  keep_neighbours(*alpha_vertex,res,keep_only_superior);
923  }
924 
930  virtual void keep_neighbours(Vertex_handle v, Simplex_handle& res,bool keep_only_superior=false) const{
931  Simplex_handle nv;
932  add_neighbours(v,nv,keep_only_superior);
933  res.intersection(nv);
934  }
935 
941  virtual void remove_neighbours(Vertex_handle v, Simplex_handle & res,bool keep_only_superior=false) const{
942  Simplex_handle nv;
943  add_neighbours(v,nv,keep_only_superior);
944  res.difference(nv);
945  }
946 
947 
948 public:
949 
956  //xxx rename get_address et place un using dans sub_complex
957  boost::optional<Simplex_handle> get_simplex_address(const Root_simplex_handle& s) const
958  {
959  boost::optional<Simplex_handle> res;
960 
961  Simplex_handle s_address;
962  //Root_simplex_const_iterator i;
963  for (auto i = s.begin() ; i != s.end() ; ++i)
964  {
965  boost::optional<Vertex_handle> address = get_address(*i);
966  if (!address)
967  return res;
968  else
969  s_address.add_vertex(*address);
970  }
971  res = s_address;
972  return res;
973  }
974 
979  Root_simplex_handle get_id(const Simplex_handle& local_simplex) const{
980  Root_simplex_handle global_simplex;
981  for (auto x = local_simplex.begin(); x!= local_simplex.end();++x){
982  global_simplex.add_vertex(get_id(*x));
983 
984  }
985  return global_simplex;
986 
987  }
988 
989 
994  virtual bool contains(const Simplex_handle & s) const{
995  if (s.dimension() == -1 ) return false;
996  else
997  if (s.dimension() ==0 ){
998  return contains_vertex(s.first_vertex());
999  }
1000  else
1001  return ( contains_edges(s) && !blocks(s) );
1002  }
1003 
1004  /*
1005  * @brief returnrs true iff the complex is empty.
1006  */
1007  bool empty() const{
1008  return num_vertices()==0;
1009  }
1010 
1011  /*
1012  * @brief returns the number of vertices in the complex.
1013  */
1014  int num_vertices() const{
1015  //remark boost::num_vertices(skeleton) counts deactivated vertices
1016  return num_vertices_;
1017  }
1018 
1019  /*
1020  * @brief returns the number of edges in the complex.
1021  * @details currently in O(n)
1022  */
1023  // todo cache the value
1024  int num_edges() const{
1025  return boost::num_edges(skeleton);
1026  }
1027 
1028  /*
1029  * @brief returns the number of blockers in the complex.
1030  */
1031  int num_blockers() const{
1032  return num_blockers_;
1033  }
1034 
1035  /*
1036  * @brief returns true iff the graph of the 1-skeleton of the complex is complete.
1037  */
1038  bool complete() const{
1039  return (num_vertices()*(num_vertices()-1))/2 == num_edges();
1040  }
1041 
1046  int num_vert_collapsed = skeleton.vertex_set().size() - num_vertices();
1047  std::vector<int> component(skeleton.vertex_set().size());
1048  return boost::connected_components(this->skeleton,&component[0]) - num_vert_collapsed;
1049  }
1050 
1055  bool is_cone() const{
1056  if (num_vertices()==0) return false;
1057  if (num_vertices()==1) return true;
1058  for(auto vi : vertex_range()){
1059  //xxx todo faire une methode bool is_in_blocker(Vertex_handle)
1060  if (blocker_map_.find(vi)==blocker_map_.end()){
1061  // no blocker passes through the vertex, we just need to
1062  // check if the current vertex is linked to all others vertices of the complex
1063  if (degree_[vi.vertex] == num_vertices()-1)
1064  return true;
1065  }
1066  }
1067  return false;
1068  }
1069 
1071 
1072 
1074 
1077 
1078  typedef Complex_vertex_iterator<Skeleton_blocker_complex> CVI; //todo rename
1079 
1080  // /**
1081  // * @brief Range over the vertices of the simplicial complex.
1082  // * Methods .begin() and .end() return a Complex_vertex_iterator.
1083  // */
1084  typedef boost::iterator_range < Complex_vertex_iterator<Skeleton_blocker_complex> > Complex_vertex_range;
1085 
1090  {
1093  return Complex_vertex_range(begin,end);
1094  }
1095 
1096  typedef boost::iterator_range < Complex_neighbors_vertices_iterator<Skeleton_blocker_complex> > Complex_neighbors_vertices_range;
1097 
1101  Complex_neighbors_vertices_range vertex_range(Vertex_handle v) const
1102  {
1103  auto begin = Complex_neighbors_vertices_iterator<Skeleton_blocker_complex>(this,v);
1104  auto end = Complex_neighbors_vertices_iterator<Skeleton_blocker_complex>(this,v,0);
1105  return Complex_neighbors_vertices_range(begin,end);
1106  }
1107 
1109 
1110 
1114 
1115 
1116  typedef boost::iterator_range <Complex_edge_iterator<Skeleton_blocker_complex<SkeletonBlockerDS>>>
1117  Complex_edge_range;
1118 
1122  Complex_edge_range edge_range() const
1123  {
1126  return Complex_edge_range(begin,end);
1127  }
1128 
1129 
1130 
1131  typedef boost::iterator_range <Complex_edge_around_vertex_iterator<Skeleton_blocker_complex<SkeletonBlockerDS>>>
1132  Complex_edge_around_vertex_range;
1137  Complex_edge_around_vertex_range edge_range(Vertex_handle v) const
1138  {
1139  auto begin = Complex_edge_around_vertex_iterator<Skeleton_blocker_complex<SkeletonBlockerDS>>(this,v);
1140  auto end = Complex_edge_around_vertex_iterator<Skeleton_blocker_complex<SkeletonBlockerDS>>(this,v,0);
1141  return Complex_edge_around_vertex_range(begin,end);
1142  }
1143 
1144 
1145 
1147 
1148 
1152 private:
1155 public:
1156  typedef Triangle_around_vertex_iterator<Skeleton_blocker_complex,Superior_link> Superior_triangle_around_vertex_iterator;
1157 
1158 
1159  typedef boost::iterator_range < Triangle_around_vertex_iterator<Skeleton_blocker_complex,Link> > Complex_triangle_around_vertex_range;
1160 
1166  Complex_triangle_around_vertex_range triangle_range(Vertex_handle v) const
1167  {
1170  return Complex_triangle_around_vertex_range(begin,end);
1171  }
1172 
1173 
1174  typedef boost::iterator_range<Triangle_iterator<Skeleton_blocker_complex> > Complex_triangle_range;
1175 
1181  Complex_triangle_range triangle_range() const
1182  {
1184  if(empty()){
1185  return Complex_triangle_range(end,end);
1186  }
1187  else{
1189  return Complex_triangle_range(begin,end);
1190  }
1191 
1192  }
1193 
1194 
1196 
1197 
1198 
1202  typedef Simplex_around_vertex_iterator<Skeleton_blocker_complex,Link> Complex_simplex_around_vertex_iterator;
1203 
1208  typedef boost::iterator_range < Complex_simplex_around_vertex_iterator > Complex_simplex_around_vertex_range;
1209 
1214  {
1215  assert(contains_vertex(v));
1219  );
1220  }
1221 
1222  // typedef Simplex_iterator<Skeleton_blocker_complex,Superior_link> Complex_simplex_iterator;
1223  typedef Simplex_iterator<Skeleton_blocker_complex> Complex_simplex_iterator;
1224 
1225  typedef boost::iterator_range < Complex_simplex_iterator > Complex_simplex_range;
1226 
1230  Complex_simplex_range simplex_range() const
1231  {
1232  Complex_simplex_iterator end(this,true);
1233  if(empty()){
1234  return Complex_simplex_range(end,end);
1235  }
1236  else{
1237  Complex_simplex_iterator begin(this);
1238  return Complex_simplex_range(begin,end);
1239  }
1240  }
1241 
1242 
1244 
1245 
1249 private:
1254  typename std::multimap<Vertex_handle,Simplex_handle *>::iterator,
1256  Complex_blocker_around_vertex_iterator;
1257 
1262  typename std::multimap<Vertex_handle,Simplex_handle *>::const_iterator,
1263  const Blocker_handle>
1264  Const_complex_blocker_around_vertex_iterator;
1265 
1266  typedef boost::iterator_range <Complex_blocker_around_vertex_iterator> Complex_blocker_around_vertex_range;
1267  typedef boost::iterator_range <Const_complex_blocker_around_vertex_iterator> Const_complex_blocker_around_vertex_range;
1268 
1269 public:
1270 
1271 
1275  Complex_blocker_around_vertex_range blocker_range(Vertex_handle v)
1276  {
1277  auto begin = Complex_blocker_around_vertex_iterator(blocker_map_.lower_bound(v));
1278  auto end = Complex_blocker_around_vertex_iterator(blocker_map_.upper_bound(v));
1279  return Complex_blocker_around_vertex_range(begin,end);
1280  }
1281 
1285  Const_complex_blocker_around_vertex_range const_blocker_range(Vertex_handle v) const
1286  {
1287  auto begin = Const_complex_blocker_around_vertex_iterator(blocker_map_.lower_bound(v));
1288  auto end = Const_complex_blocker_around_vertex_iterator(blocker_map_.upper_bound(v));
1289  return Const_complex_blocker_around_vertex_range(begin,end);
1290  }
1291 
1292 
1293 
1294 
1295 private:
1296 
1300  typedef Blocker_iterator_internal<
1301  typename std::multimap<Vertex_handle,Simplex_handle *>::iterator,
1303  Complex_blocker_iterator;
1304 
1308  typedef Blocker_iterator_internal<
1309  typename std::multimap<Vertex_handle,Simplex_handle *>::const_iterator,
1310  const Blocker_handle>
1311  Const_complex_blocker_iterator;
1312 
1313  typedef boost::iterator_range <Complex_blocker_iterator> Complex_blocker_range;
1314  typedef boost::iterator_range <Const_complex_blocker_iterator> Const_complex_blocker_range;
1315 
1316 
1317 public:
1318 
1322  Complex_blocker_range blocker_range()
1323  {
1324  auto begin = Complex_blocker_iterator(blocker_map_.begin(), blocker_map_.end() );
1325  auto end = Complex_blocker_iterator(blocker_map_.end() , blocker_map_.end() );
1326  return Complex_blocker_range(begin,end);
1327  }
1328 
1332  Const_complex_blocker_range const_blocker_range() const
1333  {
1334  auto begin = Const_complex_blocker_iterator(blocker_map_.begin(), blocker_map_.end() );
1335  auto end = Const_complex_blocker_iterator(blocker_map_.end() , blocker_map_.end() );
1336  return Const_complex_blocker_range(begin,end);
1337  }
1338 
1339 
1340 
1341 
1343 
1344 
1345 
1346 
1347 
1349 
1352 public:
1353 
1354  std::string to_string() const{
1355  std::ostringstream stream;
1356  stream<<num_vertices()<<" vertices:\n"<<vertices_to_string()<<std::endl;
1357  stream<<num_edges()<<" edges:\n"<<edges_to_string()<<std::endl;
1358  stream<<num_blockers()<<" blockers:\n"<<blockers_to_string()<<std::endl;
1359  return stream.str();
1360  }
1361 
1362  std::string vertices_to_string() const{
1363  std::ostringstream stream;
1364  for(auto vertex : vertex_range())
1365  stream << "("<<(*this)[vertex].get_id()<<"),";
1366  stream<< std::endl;
1367  return stream.str();
1368  }
1369 
1370  std::string edges_to_string() const{
1371  std::ostringstream stream;
1372  for(auto edge : edge_range())
1373  stream << "("<< (*this)[edge].first()<<","<< (*this)[edge].second() << ")"<<" id = "<< (*this)[edge].index()<< std::endl;
1374  stream<< std::endl;
1375  return stream.str();
1376  }
1377 
1378 
1379  std::string blockers_to_string() const{
1380  std::ostringstream stream;
1381  for (auto bl:blocker_map_){
1382  stream << bl.first << " => " << bl.second << ":"<<*bl.second <<"\n";
1383  }
1384  return stream.str();
1385  }
1386 
1388 
1389 };
1390 
1391 
1392 
1397 template<typename Complex,typename SimplexHandleIterator>
1398 unsigned make_complex_from_top_faces(Complex& complex,SimplexHandleIterator begin,SimplexHandleIterator end){
1399  typedef typename Complex::Simplex_handle Simplex_handle;
1400 
1401  int dimension = 0;
1402  for(auto top_face = begin; top_face != end; ++top_face)
1403  dimension = std::max(dimension,top_face->dimension());
1404 
1405  std::vector< std::set<Simplex_handle> > simplices_per_dimension(dimension+1);
1406 
1407 
1408  for(auto top_face = begin; top_face != end; ++top_face){
1409  register_faces(simplices_per_dimension,*top_face);
1410  }
1411 
1412  // compute list of simplices
1413  std::list<Simplex_handle> simplices;
1414  for(int dim = 0 ; dim <= dimension ; ++dim){
1415  std::copy(
1416  simplices_per_dimension[dim].begin(),
1417  simplices_per_dimension[dim].end(),
1418  std::back_inserter(simplices)
1419  );
1420  }
1421  complex = Complex(simplices);
1422  return simplices.size();
1423 }
1424 
1425 } // namespace skbl
1426 
1427 } // namespace GUDHI
1428 
1429 
1430 
1431 #endif
1432 
void remove_blockers()
Remove all blockers, in other words, it expand the simplicial complex to the smallest flag complex th...
Definition: Skeleton_blocker_complex.h:803
void add_vertex(T v)
Definition: Skeleton_blocker_simplex.h:133
Const_complex_blocker_range const_blocker_range() const
Returns a range of the blockers of the complex.
Definition: Skeleton_blocker_complex.h:1332
void remove_blocker(const Blocker_handle sigma)
Removes the simplex from the set of blockers.
Definition: Skeleton_blocker_complex.h:789
bool contains_blocker(const Blocker_handle s) const
Definition: Skeleton_blocker_complex.h:844
Complex_triangle_range triangle_range() const
Range over triangles of the simplicial complex. Methods .begin() and .end() return a Triangle_around_...
Definition: Skeleton_blocker_complex.h:1181
void remove_edge(Edge_handle edge)
Removes edge and its cofaces from the simplicial complex.
Definition: Skeleton_blocker_complex.h:658
Blocker_handle add_blocker(const Simplex_handle &blocker)
Adds the simplex to the set of blockers and returns a Blocker_handle toward it if was not present bef...
Definition: Skeleton_blocker_complex.h:719
void set_visitor(Visitor *other_visitor)
allows to change the visitor.
Definition: Skeleton_blocker_complex.h:396
const Graph_vertex & operator[](Vertex_handle address) const
Return the vertex node associated to local Vertex_handle.
Definition: Skeleton_blocker_complex.h:435
Complex_blocker_range blocker_range()
Returns a range of the blockers of the complex.
Definition: Skeleton_blocker_complex.h:1322
Iterator on the edges of a simplicial complex.
Definition: Skeleton_blockers_edges_iterators.h:105
boost::optional< Edge_handle > operator[](const std::pair< Vertex_handle, Vertex_handle > &ab) const
return an edge handle if the two vertices forms an edge in the complex
Definition: Skeleton_blocker_complex.h:555
Vertex_handle second_vertex(Edge_handle edge_handle) const
returns the first vertex of an edge
Definition: Skeleton_blocker_complex.h:589
void delete_blocker(Blocker_handle sigma)
Definition: Skeleton_blocker_complex.h:834
SkeletonBlockerDS::Graph_vertex Graph_vertex
The type of stored vertex node, specified by the template SkeletonBlockerDS.
Definition: Skeleton_blocker_complex.h:80
boost::graph_traits< Graph >::edge_descriptor Edge_handle
Handle to an edge of the complex.
Definition: Skeleton_blocker_complex.h:139
Skeleton_blocker_complex(std::list< Simplex_handle > &simplices, Visitor *visitor_=NULL)
Constructor with a list of simplices.
Definition: Skeleton_blocker_complex.h:303
Complex_neighbors_vertices_range vertex_range(Vertex_handle v) const
Returns a Complex_edge_range over all edges of the simplicial complex that passes trough v...
Definition: Skeleton_blocker_complex.h:1101
Vertex_handle operator[](Root_vertex_handle global) const
Return a local Vertex_handle of a vertex given a global one.
Definition: Skeleton_blocker_complex.h:416
Vertex_handle first_vertex(Edge_handle edge_handle) const
returns the first vertex of an edge
Definition: Skeleton_blocker_complex.h:581
Iterator through the blockers of a vertex.
Definition: Skeleton_blockers_blockers_iterators.h:37
The type of edges that are stored the boost graph. An Edge must be Default Constructible and Equality...
Definition: SkeletonBlockerDS.h:97
Graph_vertex & operator[](Vertex_handle address)
Return the vertex node associated to local Vertex_handle.
Definition: Skeleton_blocker_complex.h:426
boost::iterator_range< Complex_vertex_iterator< Skeleton_blocker_complex > > Complex_vertex_range
Range over the vertices of the simplicial complex. Methods .begin() and .end() return a Complex_verte...
Definition: Skeleton_blocker_complex.h:1084
virtual boost::optional< Vertex_handle > get_address(Root_vertex_handle id) const
Given an Id return the address of the vertex having this Id in the complex.
Definition: Skeleton_blocker_complex.h:500
Const_complex_blocker_around_vertex_range const_blocker_range(Vertex_handle v) const
Returns a range of the blockers of the complex passing through a vertex.
Definition: Skeleton_blocker_complex.h:1285
Iterator over the triangles that are adjacent to a vertex of the simplicial complex.
Definition: Skeleton_blockers_triangles_iterators.h:39
int degree(Vertex_handle local) const
return the graph degree of a vertex.
Definition: Skeleton_blocker_complex.h:537
Abstract Simplicial Complex represented with a skeleton/blockers pair.
Definition: Skeleton_blocker_complex.h:63
Skeleton_blocker_complex(int num_vertices_=0, Visitor *visitor_=NULL)
constructs a simplicial complex with a given number of vertices and a visitor.
Definition: Skeleton_blocker_complex.h:188
Simplex_handle * Blocker_handle
Handle to a blocker of the complex.
Definition: Skeleton_blocker_complex.h:106
T first_vertex() const
Definition: Skeleton_blocker_simplex.h:235
Iterator on the vertices of a simplicial complex.
Definition: Skeleton_blockers_vertices_iterators.h:38
bool contains_edges(const Simplex_handle &sigma) const
Definition: Skeleton_blocker_complex.h:696
int num_connected_components() const
returns the number of connected components in the graph of the 1-skeleton.
Definition: Skeleton_blocker_complex.h:1045
Simplex_handle get_vertices(Edge_handle edge_handle) const
returns the simplex made with the two vertices of the edge
Definition: Skeleton_blocker_complex.h:598
virtual ~Skeleton_blocker_complex()
Definition: Skeleton_blocker_complex.h:371
Vertex_handle convert_handle_from_another_complex(const Skeleton_blocker_complex &other, Vertex_handle vh_in_other) const
Convert an address of a vertex of a complex to the address in the current complex.
Definition: Skeleton_blocker_complex.h:527
Edge_handle add_edge(Vertex_handle a, Vertex_handle b)
Adds an edge between vertices a and b and all its cofaces.
Definition: Skeleton_blocker_complex.h:606
Simplicial subcomplex of a complex represented by a skeleton/blockers pair.
Definition: Skeleton_blocker_link_superior.h:31
boost::optional< Simplex_handle > get_simplex_address(const Root_simplex_handle &s) const
Compute the local vertices of 's' in the current complex If one of them is not present in the complex...
Definition: Skeleton_blocker_complex.h:957
virtual void clear()
Definition: Skeleton_blocker_complex.h:380
Complex_vertex_range vertex_range() const
Returns a Complex_vertex_range over all vertices of the complex.
Definition: Skeleton_blocker_complex.h:1089
Root_vertex_handle get_id(Vertex_handle local) const
Definition: Skeleton_blocker_complex.h:511
void remove_vertex(Vertex_handle address)
Remove a vertex from the simplicial complex.
Definition: Skeleton_blocker_complex.h:461
Vertex that stores a point.
Definition: SkeletonBlockerGeometricDS.h:41
virtual Edge_handle remove_edge(Vertex_handle a, Vertex_handle b)
Removes an edge from the simplicial complex and all its cofaces.
Definition: Skeleton_blocker_complex.h:639
bool contains_edge(Vertex_handle a, Vertex_handle b) const
Definition: Skeleton_blocker_complex.h:686
Vertex_handle add_vertex()
Adds a vertex to the simplicial complex and returns its Vertex_handle.
Definition: Skeleton_blocker_complex.h:443
Abstract simplex used in Skeleton blockers data-structure.
Definition: Skeleton_blocker_simplex.h:48
Complex_simplex_range simplex_range() const
Returns a Complex_simplex_range over all the simplices of the complex.
Definition: Skeleton_blocker_complex.h:1230
SkeletonBlockerDS::Vertex_handle Vertex_handle
The type of an handle to a vertex of the complex.
Definition: Skeleton_blocker_complex.h:92
bool is_cone() const
Test if the complex is a cone.
Definition: Skeleton_blocker_complex.h:1055
Graph_edge & operator[](Edge_handle edge_handle)
returns the stored node associated to an edge
Definition: Skeleton_blocker_complex.h:566
Iterator through the blockers of a vertex.
Definition: Skeleton_blockers_blockers_iterators.h:91
Interface for a visitor of a simplicial complex.
Definition: Skeleton_blocker_complex_visitor.h:38
bool contains_blocker(const Simplex_handle &s) const
Definition: Skeleton_blocker_complex.h:860
Complex_triangle_around_vertex_range triangle_range(Vertex_handle v) const
Range over triangles around a vertex of the simplicial complex. Methods .begin() and ...
Definition: Skeleton_blocker_complex.h:1166
Skeleton_blocker_simplex< Vertex_handle > Simplex_handle
A ordered set of integers that represents a simplex.
Definition: Skeleton_blocker_complex.h:99
int dimension() const
Definition: Skeleton_blocker_simplex.h:222
Definition: Skeleton_blockers_simplices_iterators.h:53
void add_edges(const Simplex_handle &sigma)
Adds all edges and their cofaces of a simplex to the simplicial complex.
Definition: Skeleton_blocker_complex.h:628
Definition: SkeletonBlockerDS.h:60
SkeletonBlockerDS::Graph_edge Graph_edge
The type of stored edge node, specified by the template SkeletonBlockerDS.
Definition: Skeleton_blocker_complex.h:85
Complex_edge_around_vertex_range edge_range(Vertex_handle v) const
Returns a Complex_edge_range over all edges of the simplicial complex that passes through 'v'...
Definition: Skeleton_blocker_complex.h:1137
Root_simplex_handle get_id(const Simplex_handle &local_simplex) const
returns a simplex with vertices which are the id of vertices of the argument.
Definition: Skeleton_blocker_complex.h:979
The type of vertices that are stored the boost graph. A Vertex must be Default Constructible and Equa...
Definition: SkeletonBlockerDS.h:72
bool contains_vertices(const Simplex_handle &sigma) const
Definition: Skeleton_blocker_complex.h:490
Complex_simplex_around_vertex_range simplex_range(Vertex_handle v) const
Returns a Complex_simplex_around_vertex_range over all the simplices around a vertex of the complex...
Definition: Skeleton_blocker_complex.h:1213
boost::iterator_range< Complex_simplex_around_vertex_iterator > Complex_simplex_around_vertex_range
Range over the simplices of the simplicial complex around a vertex. Methods .begin() and ...
Definition: Skeleton_blocker_complex.h:1208
Root_vertex_handle and Vertex_handle are similar to global and local vertex descriptor used in boost ...
Definition: SkeletonBlockerDS.h:50
Complex_blocker_around_vertex_range blocker_range(Vertex_handle v)
Returns a range of the blockers of the complex passing through a vertex.
Definition: Skeleton_blocker_complex.h:1275
void keep_only_vertices()
The complex is reduced to its set of vertices. All the edges and blockers are removed.
Definition: Skeleton_blocker_complex.h:669
Iterator over the triangles of the simplicial complex.
Definition: Skeleton_blockers_triangles_iterators.h:122
virtual bool contains(const Simplex_handle &s) const
returns true iff the simplex s belongs to the simplicial complex.
Definition: Skeleton_blocker_complex.h:994
const Graph_edge & operator[](Edge_handle edge_handle) const
returns the stored node associated to an edge
Definition: Skeleton_blocker_complex.h:573
Complex_edge_range edge_range() const
Returns a Complex_edge_range over all edges of the simplicial complex.
Definition: Skeleton_blocker_complex.h:1122