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
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 SKELETON_BLOCKER_COMPLEX_H_
24 #define SKELETON_BLOCKER_COMPLEX_H_
25 
26 #include <gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h>
27 #include <gudhi/Skeleton_blocker_link_complex.h>
28 #include <gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h>
29 #include <gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h>
30 #include <gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h>
31 #include <gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h>
32 #include <gudhi/Skeleton_blocker/internal/Top_faces.h>
33 #include <gudhi/Skeleton_blocker/internal/Trie.h>
34 #include <gudhi/Debug_utils.h>
35 
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 <iostream>
42 #include <fstream>
43 #include <sstream>
44 #include <memory>
45 #include <map>
46 #include <list>
47 #include <set>
48 #include <vector>
49 #include <string>
50 #include <algorithm>
51 #include <utility>
52 
53 namespace Gudhi {
54 
55 namespace skeleton_blocker {
56 
62 template<class SkeletonBlockerDS>
64  template<class ComplexType> friend class Vertex_iterator;
65  template<class ComplexType> friend class Neighbors_vertices_iterator;
66  template<class ComplexType> friend class Edge_iterator;
67  template<class ComplexType> friend class Edge_around_vertex_iterator;
68 
69  template<class ComplexType> friend class Skeleton_blocker_link_complex;
70  template<class ComplexType> friend class Skeleton_blocker_link_superior;
71  template<class ComplexType> friend class Skeleton_blocker_sub_complex;
72 
73  public:
78 
83 
84  typedef typename SkeletonBlockerDS::Root_vertex_handle Root_vertex_handle;
85 
90  typedef typename Root_vertex_handle::boost_vertex_handle boost_vertex_handle;
91 
97 
101  typedef Simplex* Blocker_handle;
102 
103  typedef typename Root_simplex_handle::Simplex_vertex_const_iterator Root_simplex_iterator;
104  typedef typename Simplex::Simplex_vertex_const_iterator Simplex_handle_iterator;
105 
106  protected:
107  typedef typename boost::adjacency_list<boost::setS, // edges
108  boost::vecS, // vertices
109  boost::undirectedS, Graph_vertex, Graph_edge> Graph;
110  // todo/remark : edges are not sorted, it heavily penalizes computation for SuperiorLink
111  // (eg Link with greater vertices)
112  // that burdens simplex iteration / complex initialization via list of simplices.
113  // to avoid that, one should modify the graph by storing two lists of adjacency for every
114  // vertex, the one with superior and the one with lower vertices, that way there is
115  // no more extra cost for computation of SuperiorLink
116  typedef typename boost::graph_traits<Graph>::vertex_iterator boost_vertex_iterator;
117  typedef typename boost::graph_traits<Graph>::edge_iterator boost_edge_iterator;
118 
119  protected:
120  typedef typename boost::graph_traits<Graph>::adjacency_iterator boost_adjacency_iterator;
121 
122  public:
126  typedef typename boost::graph_traits<Graph>::edge_descriptor Edge_handle;
127 
128  protected:
129  typedef std::multimap<Vertex_handle, Simplex *> BlockerMap;
130  typedef typename std::multimap<Vertex_handle, Simplex *>::value_type BlockerPair;
131  typedef typename std::multimap<Vertex_handle, Simplex *>::iterator BlockerMapIterator;
132  typedef typename std::multimap<Vertex_handle, Simplex *>::const_iterator BlockerMapConstIterator;
133 
134  protected:
135  size_t num_vertices_;
136  size_t num_blockers_;
137 
139  // typedef Visitor* Visitor_ptr;
140  Visitor* visitor;
141 
150  std::vector<boost_vertex_handle> degree_;
151  Graph skeleton;
154  BlockerMap blocker_map_;
155 
156  public:
158 
161 
165  explicit Skeleton_blocker_complex(size_t num_vertices_ = 0, Visitor* visitor_ = NULL)
166  : visitor(visitor_) {
167  clear();
168  for (size_t i = 0; i < num_vertices_; ++i) {
169  add_vertex();
170  }
171  }
172 
173  private:
174  // typedef Trie<Skeleton_blocker_complex<SkeletonBlockerDS>> STrie;
175  typedef Trie<Simplex> STrie;
176 
177  public:
182  template<typename SimpleHandleOutputIterator>
183  Skeleton_blocker_complex(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end,
184  bool is_flag_complex = false, Visitor* visitor_ = NULL)
185  : num_vertices_(0),
186  num_blockers_(0),
187  visitor(visitor_) {
188  add_vertices_and_edges(simplices_begin, simplices_end);
189 
190  if (!is_flag_complex)
191  // need to compute blockers
192  add_blockers(simplices_begin, simplices_end);
193  }
194 
195  private:
199  template<typename SimpleHandleOutputIterator>
200  void add_vertices_and_edges(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end) {
201  std::vector<std::pair<Vertex_handle, Vertex_handle>> edges;
202  // first pass to add vertices and edges
203  int num_vertex = -1;
204  for (auto s_it = simplices_begin; s_it != simplices_end; ++s_it) {
205  if (s_it->dimension() == 0) num_vertex = (std::max)(num_vertex, s_it->first_vertex().vertex);
206  if (s_it->dimension() == 1) edges.emplace_back(s_it->first_vertex(), s_it->last_vertex());
207  }
208  while (num_vertex-- >= 0) add_vertex();
209 
210  for (const auto& e : edges)
211  add_edge_without_blockers(e.first, e.second);
212  }
213 
214  template<typename SimpleHandleOutputIterator>
215  void add_blockers(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end) {
216  Tries<Simplex> tries(num_vertices(), simplices_begin, simplices_end);
217  tries.init_next_dimension();
218  auto simplices(tries.next_dimension_simplices());
219 
220  while (!simplices.empty()) {
221  simplices = tries.next_dimension_simplices();
222  for (auto& sigma : simplices) {
223  // common_positive_neighbors is the set of vertices u such that
224  // for all s in sigma, us is an edge and u>s
225  Simplex common_positive_neighbors(tries.positive_neighbors(sigma.last_vertex()));
226  for (auto sigma_it = sigma.rbegin(); sigma_it != sigma.rend(); ++sigma_it)
227  if (sigma_it != sigma.rbegin())
228  common_positive_neighbors.intersection(tries.positive_neighbors(*sigma_it));
229 
230  for (auto x : common_positive_neighbors) {
231  // first test that all edges sx are here for all s in sigma
232  bool all_edges_here = true;
233  for (auto s : sigma)
234  if (!contains_edge(x, s)) {
235  all_edges_here = false;
236  break;
237  }
238  if (!all_edges_here) continue;
239 
240  // all edges of sigma \cup x are here
241  // we have a blocker if all proper faces of sigma \cup x
242  // are in the complex and if sigma \cup x is not in the complex
243  // the first is equivalent at checking if blocks(sigma \cup x) is true
244  // as all blockers of lower dimension have already been computed
245  sigma.add_vertex(x);
246  if (!tries.contains(sigma) && !blocks(sigma))
247  add_blocker(sigma);
248  sigma.remove_vertex(x);
249  }
250  }
251  }
252  }
253 
254  public:
255  // We cannot use the default copy constructor since we need
256  // to make a copy of each of the blockers
257 
259  visitor = NULL;
260  degree_ = copy.degree_;
261  skeleton = Graph(copy.skeleton);
262  num_vertices_ = copy.num_vertices_;
263 
264  num_blockers_ = 0;
265  // we copy the blockers
266  for (auto blocker : copy.const_blocker_range()) {
267  add_blocker(*blocker);
268  }
269  }
270 
273  Skeleton_blocker_complex& operator=(const Skeleton_blocker_complex& copy) {
274  clear();
275  visitor = NULL;
276  degree_ = copy.degree_;
277  skeleton = Graph(copy.skeleton);
278  num_vertices_ = copy.num_vertices_;
279 
280  num_blockers_ = 0;
281  // we copy the blockers
282  for (auto blocker : copy.const_blocker_range())
283  add_blocker(*blocker);
284  return *this;
285  }
286 
290  bool operator==(const Skeleton_blocker_complex& other) const {
291  if (other.num_vertices() != num_vertices()) return false;
292  if (other.num_edges() != num_edges()) return false;
293  if (other.num_blockers() != num_blockers()) return false;
294 
295  for (auto v : vertex_range())
296  if (!other.contains_vertex(v)) return false;
297 
298  for (auto e : edge_range())
299  if (!other.contains_edge(first_vertex(e), second_vertex(e))) return false;
300 
301  for (const auto b : const_blocker_range())
302  if (!other.contains_blocker(*b)) return false;
303 
304  return true;
305  }
306 
307  bool operator!=(const Skeleton_blocker_complex& other) const {
308  return !(*this == other);
309  }
310 
315  clear();
316  }
317 
323  virtual void clear() {
324  // xxx for now the responsabilty of freeing the visitor is for
325  // the user
326  visitor = NULL;
327 
328  degree_.clear();
329  num_vertices_ = 0;
330 
331  remove_blockers();
332 
333  skeleton.clear();
334  }
335 
339  void set_visitor(Visitor* other_visitor) {
340  visitor = other_visitor;
341  }
342 
344 
346 
349  public:
354  Vertex_handle operator[](Root_vertex_handle global) const {
355  auto local(get_address(global));
356  assert(local);
357  return *local;
358  }
359 
364  Graph_vertex& operator[](Vertex_handle address) {
365  assert(
366  0 <= address.vertex && address.vertex < boost::num_vertices(skeleton));
367  return skeleton[address.vertex];
368  }
369 
374  const Graph_vertex& operator[](Vertex_handle address) const {
375  assert(
376  0 <= address.vertex && address.vertex < boost::num_vertices(skeleton));
377  return skeleton[address.vertex];
378  }
379 
384  Vertex_handle add_vertex() {
385  Vertex_handle address(boost::add_vertex(skeleton));
386  num_vertices_++;
387  (*this)[address].activate();
388  // safe since we now that we are in the root complex and the field 'address' and 'id'
389  // are identical for every vertices
390  (*this)[address].set_id(Root_vertex_handle(address.vertex));
391  degree_.push_back(0);
392  if (visitor)
393  visitor->on_add_vertex(address);
394  return address;
395  }
396 
402  void remove_vertex(Vertex_handle address) {
403  assert(contains_vertex(address));
404  // We remove b
405  boost::clear_vertex(address.vertex, skeleton);
406  (*this)[address].deactivate();
407  num_vertices_--;
408  degree_[address.vertex] = -1;
409  if (visitor)
410  visitor->on_remove_vertex(address);
411  }
412 
415  bool contains_vertex(Vertex_handle u) const {
416  Vertex_handle num_vertices(boost::num_vertices(skeleton));
417  if (u.vertex < 0 || u.vertex >= num_vertices)
418  return false;
419  return (*this)[u].is_active();
420  }
421 
424  bool contains_vertex(Root_vertex_handle u) const {
425  boost::optional<Vertex_handle> address = get_address(u);
426  return address && (*this)[*address].is_active();
427  }
428 
433  bool contains_vertices(const Simplex & sigma) const {
434  for (auto vertex : sigma)
435  if (!contains_vertex(vertex))
436  return false;
437  return true;
438  }
439 
444  virtual boost::optional<Vertex_handle> get_address(Root_vertex_handle id) const {
445  boost::optional<Vertex_handle> res;
446  int num_vertices = boost::num_vertices(skeleton);
447  if (id.vertex < num_vertices)
448  res = Vertex_handle(id.vertex);
449  return res;
450  }
451 
455  Root_vertex_handle get_id(Vertex_handle local) const {
456  assert(0 <= local.vertex && local.vertex < boost::num_vertices(skeleton));
457  return (*this)[local].get_id();
458  }
459 
471  Vertex_handle vh_in_other) const {
472  auto vh_in_current_complex = get_address(other.get_id(vh_in_other));
473  assert(vh_in_current_complex);
474  return *vh_in_current_complex;
475  }
476 
480  int degree(Vertex_handle local) const {
481  assert(0 <= local.vertex && local.vertex < boost::num_vertices(skeleton));
482  return degree_[local.vertex];
483  }
484 
486 
488 
491  public:
496  boost::optional<Edge_handle> operator[](
497  const std::pair<Vertex_handle, Vertex_handle>& ab) const {
498  boost::optional<Edge_handle> res;
499  std::pair<Edge_handle, bool> edge_pair(
500  boost::edge(ab.first.vertex, ab.second.vertex, skeleton));
501  if (edge_pair.second)
502  res = edge_pair.first;
503  return res;
504  }
505 
509  Graph_edge& operator[](Edge_handle edge_handle) {
510  return skeleton[edge_handle];
511  }
512 
516  const Graph_edge& operator[](Edge_handle edge_handle) const {
517  return skeleton[edge_handle];
518  }
519 
524  Vertex_handle first_vertex(Edge_handle edge_handle) const {
525  return static_cast<Vertex_handle> (source(edge_handle, skeleton));
526  }
527 
532  Vertex_handle second_vertex(Edge_handle edge_handle) const {
533  return static_cast<Vertex_handle> (target(edge_handle, skeleton));
534  }
535 
541  Simplex get_vertices(Edge_handle edge_handle) const {
542  auto edge((*this)[edge_handle]);
543  return Simplex((*this)[edge.first()], (*this)[edge.second()]);
544  }
545 
553  Edge_handle add_edge(Vertex_handle a, Vertex_handle b) {
554  // if the edge is already there we musnt go further
555  // as we may add blockers that should not be here
556  if (contains_edge(a, b))
557  return *((*this)[std::make_pair(a, b)]);
558  auto res = add_edge_without_blockers(a, b);
559  add_blockers_after_simplex_insertion(Simplex(a, b));
560  return res;
561  }
562 
566  void add_edge(const Simplex& s) {
567  for (auto i = s.begin(); i != s.end(); ++i)
568  for (auto j = i; ++j != s.end(); )
569  add_edge(*i, *j);
570  }
571 
578  Edge_handle add_edge_without_blockers(Vertex_handle a, Vertex_handle b) {
579  assert(contains_vertex(a) && contains_vertex(b));
580  assert(a != b);
581 
582  auto edge_handle((*this)[std::make_pair(a, b)]);
583  if (!edge_handle) {
584  edge_handle = boost::add_edge(a.vertex, b.vertex, skeleton).first;
585  (*this)[*edge_handle].setId(get_id(a), get_id(b));
586  degree_[a.vertex]++;
587  degree_[b.vertex]++;
588  if (visitor)
589  visitor->on_add_edge_without_blockers(a, b);
590  }
591  return *edge_handle;
592  }
593 
597  void add_edge_without_blockers(Simplex s) {
598  for (auto i = s.begin(); i != s.end(); ++i) {
599  for (auto j = i; ++j != s.end(); )
601  }
602  }
603 
608  virtual Edge_handle remove_edge(Vertex_handle a, Vertex_handle b) {
609  bool found;
610  Edge_handle edge;
611  tie(edge, found) = boost::edge(a.vertex, b.vertex, skeleton);
612  if (found) {
613  if (visitor)
614  visitor->on_remove_edge(a, b);
615  boost::remove_edge(a.vertex, b.vertex, skeleton);
616  degree_[a.vertex]--;
617  degree_[b.vertex]--;
618  }
619  return edge;
620  }
621 
625  void remove_edge(Edge_handle edge) {
626  assert(contains_vertex(first_vertex(edge)));
627  assert(contains_vertex(second_vertex(edge)));
628  remove_edge(first_vertex(edge), second_vertex(edge));
629  }
630 
636  remove_blockers();
637 
638  for (auto u : vertex_range()) {
639  while (this->degree(u) > 0) {
640  Vertex_handle v(*(adjacent_vertices(u.vertex, this->skeleton).first));
641  this->remove_edge(u, v);
642  }
643  }
644  }
645 
650  bool contains_edge(Vertex_handle a, Vertex_handle b) const {
651  // if (a.vertex<0 || b.vertex <0) return false;
652  return boost::edge(a.vertex, b.vertex, skeleton).second;
653  }
654 
659  bool contains_edges(const Simplex & sigma) const {
660  for (auto i = sigma.begin(); i != sigma.end(); ++i) {
661  if (!contains_vertex(*i))
662  return false;
663  for (auto j = i; ++j != sigma.end();) {
664  if (!contains_edge(*i, *j))
665  return false;
666  }
667  }
668  return true;
669  }
671 
673 
676 
681  Blocker_handle add_blocker(const Simplex& blocker) {
682  assert(blocker.dimension() > 1);
683  if (contains_blocker(blocker)) {
684  return 0;
685  } else {
686  if (visitor)
687  visitor->on_add_blocker(blocker);
688  Blocker_handle blocker_pt = new Simplex(blocker);
689  num_blockers_++;
690  auto vertex = blocker_pt->begin();
691  while (vertex != blocker_pt->end()) {
692  blocker_map_.insert(BlockerPair(*vertex, blocker_pt));
693  ++vertex;
694  }
695  return blocker_pt;
696  }
697  }
698 
699  protected:
703  void add_blocker(Blocker_handle blocker) {
704  if (contains_blocker(*blocker)) {
705  // std::cerr << "ATTEMPT TO ADD A BLOCKER ALREADY THERE ---> BLOCKER IGNORED" << endl;
706  return;
707  } else {
708  if (visitor)
709  visitor->on_add_blocker(*blocker);
710  num_blockers_++;
711  auto vertex = blocker->begin();
712  while (vertex != blocker->end()) {
713  blocker_map_.insert(BlockerPair(*vertex, blocker));
714  ++vertex;
715  }
716  }
717  }
718 
719  protected:
723  void remove_blocker(const Blocker_handle sigma, Vertex_handle v) {
725  for (blocker = blocker_range(v).begin(); blocker != blocker_range(v).end();
726  ++blocker) {
727  if (*blocker == sigma)
728  break;
729  }
730  if (*blocker != sigma) {
731  std::cerr
732  << "bug ((*blocker).second == sigma) ie try to remove a blocker not present\n";
733  assert(false);
734  } else {
735  blocker_map_.erase(blocker.current_position());
736  }
737  }
738 
739  public:
744  void remove_blocker(const Blocker_handle sigma) {
745  for (auto vertex : *sigma)
746  remove_blocker(sigma, vertex);
747  num_blockers_--;
748  }
749 
755  // Desallocate the blockers
756  while (!blocker_map_.empty()) {
757  delete_blocker(blocker_map_.begin()->second);
758  }
759  num_blockers_ = 0;
760  blocker_map_.clear();
761  }
762 
763  protected:
770  void remove_blocker(const Simplex& sigma) {
771  assert(contains_blocker(sigma));
772  for (auto vertex : sigma)
773  remove_blocker(sigma, vertex);
774  num_blockers_--;
775  }
776 
777  public:
782  void delete_blocker(Blocker_handle sigma) {
783  if (visitor)
784  visitor->on_delete_blocker(sigma);
785  remove_blocker(sigma);
786  delete sigma;
787  }
788 
792  bool contains_blocker(const Blocker_handle s) const {
793  if (s->dimension() < 2)
794  return false;
795 
796  Vertex_handle a = s->first_vertex();
797 
798  for (const auto blocker : const_blocker_range(a)) {
799  if (s == *blocker)
800  return true;
801  }
802  return false;
803  }
804 
808  bool contains_blocker(const Simplex & s) const {
809  if (s.dimension() < 2)
810  return false;
811 
812  Vertex_handle a = s.first_vertex();
813 
814  for (auto blocker : const_blocker_range(a)) {
815  if (s == *blocker)
816  return true;
817  }
818  return false;
819  }
820 
821  private:
826  bool blocks(const Simplex & sigma) const {
827  for (auto s : sigma)
828  for (auto blocker : const_blocker_range(s))
829  if (sigma.contains(*blocker))
830  return true;
831  return false;
832  }
833 
835 
836  protected:
841  virtual void add_neighbours(Vertex_handle v, Simplex & n,
842  bool keep_only_superior = false) const {
843  boost_adjacency_iterator ai, ai_end;
844  for (tie(ai, ai_end) = adjacent_vertices(v.vertex, skeleton); ai != ai_end;
845  ++ai) {
846  Vertex_handle value(*ai);
847  if (keep_only_superior) {
848  if (value > v.vertex) {
849  n.add_vertex(value);
850  }
851  } else {
852  n.add_vertex(value);
853  }
854  }
855  }
856 
865  virtual void add_neighbours(const Simplex &alpha, Simplex & res,
866  bool keep_only_superior = false) const {
867  res.clear();
868  auto alpha_vertex = alpha.begin();
869  add_neighbours(*alpha_vertex, res, keep_only_superior);
870  for (alpha_vertex = (alpha.begin())++; alpha_vertex != alpha.end();
871  ++alpha_vertex)
872  keep_neighbours(*alpha_vertex, res, keep_only_superior);
873  }
874 
880  virtual void keep_neighbours(Vertex_handle v, Simplex& res,
881  bool keep_only_superior = false) const {
882  Simplex nv;
883  add_neighbours(v, nv, keep_only_superior);
884  res.intersection(nv);
885  }
886 
892  virtual void remove_neighbours(Vertex_handle v, Simplex & res,
893  bool keep_only_superior = false) const {
894  Simplex nv;
895  add_neighbours(v, nv, keep_only_superior);
896  res.difference(nv);
897  }
898 
899  public:
901 
905  Link_complex link(Vertex_handle v) const {
906  return Link_complex(*this, Simplex(v));
907  }
908 
912  Link_complex link(Edge_handle edge) const {
913  return Link_complex(*this, edge);
914  }
915 
919  Link_complex link(const Simplex& simplex) const {
920  return Link_complex(*this, simplex);
921  }
922 
929  // xxx rename get_address et place un using dans sub_complex
930 
931  boost::optional<Simplex> get_simplex_address(
932  const Root_simplex_handle& s) const {
933  boost::optional<Simplex> res;
934 
935  Simplex s_address;
936  // Root_simplex_const_iterator i;
937  for (auto i = s.begin(); i != s.end(); ++i) {
938  boost::optional<Vertex_handle> address = get_address(*i);
939  if (!address)
940  return res;
941  else
942  s_address.add_vertex(*address);
943  }
944  res = s_address;
945  return res;
946  }
947 
952  Root_simplex_handle get_id(const Simplex& local_simplex) const {
953  Root_simplex_handle global_simplex;
954  for (auto x = local_simplex.begin(); x != local_simplex.end(); ++x) {
955  global_simplex.add_vertex(get_id(*x));
956  }
957  return global_simplex;
958  }
959 
964  virtual bool contains(const Simplex & s) const {
965  if (s.dimension() == -1) {
966  return false;
967  } else if (s.dimension() == 0) {
968  return contains_vertex(s.first_vertex());
969  } else {
970  return (contains_edges(s) && !blocks(s));
971  }
972  }
973 
974  /*
975  * @brief returnrs true iff the complex is empty.
976  */
977  bool empty() const {
978  return num_vertices() == 0;
979  }
980 
981  /*
982  * @brief returns the number of vertices in the complex.
983  */
984  int num_vertices() const {
985  // remark boost::num_vertices(skeleton) counts deactivated vertices
986  return num_vertices_;
987  }
988 
989  /*
990  * @brief returns the number of edges in the complex.
991  * @details currently in O(n)
992  */
993  // todo cache the value
994 
995  int num_edges() const {
996  return boost::num_edges(skeleton);
997  }
998 
999  int num_triangles() const {
1000  auto triangles = triangle_range();
1001  return std::distance(triangles.begin(), triangles.end());
1002  }
1003 
1004  /*
1005  * @brief returns the number of simplices of a given dimension in the complex.
1006  */
1007  size_t num_simplices() const {
1008  auto simplices = complex_simplex_range();
1009  return std::distance(simplices.begin(), simplices.end());
1010  }
1011 
1012  /*
1013  * @brief returns the number of simplices of a given dimension in the complex.
1014  */
1015  size_t num_simplices(int dimension) const {
1016  // TODO(DS): iterator on k-simplices
1017  size_t res = 0;
1018  for (const auto& s : complex_simplex_range())
1019  if (s.dimension() == dimension)
1020  ++res;
1021  return res;
1022  }
1023 
1024  /*
1025  * @brief returns the number of blockers in the complex.
1026  */
1027  size_t num_blockers() const {
1028  return num_blockers_;
1029  }
1030 
1031  /*
1032  * @brief returns true iff the graph of the 1-skeleton of the complex is complete.
1033  */
1034  bool complete() const {
1035  return (num_vertices() * (num_vertices() - 1)) / 2 == num_edges();
1036  }
1037 
1042  int num_vert_collapsed = skeleton.vertex_set().size() - num_vertices();
1043  std::vector<int> component(skeleton.vertex_set().size());
1044  return boost::connected_components(this->skeleton, &component[0])
1045  - num_vert_collapsed;
1046  }
1047 
1052  bool is_cone() const {
1053  if (num_vertices() == 0)
1054  return false;
1055  if (num_vertices() == 1)
1056  return true;
1057  for (auto vi : vertex_range()) {
1058  // xxx todo faire une methode bool is_in_blocker(Vertex_handle)
1059  if (blocker_map_.find(vi) == blocker_map_.end()) {
1060  // no blocker passes through the vertex, we just need to
1061  // check if the current vertex is linked to all others vertices of the complex
1062  if (degree_[vi.vertex] == num_vertices() - 1)
1063  return true;
1064  }
1065  }
1066  return false;
1067  }
1068 
1070 
1073 
1082  bool is_popable_blocker(Blocker_handle sigma) const;
1083 
1088  void remove_popable_blockers();
1089 
1093  void remove_popable_blockers(Vertex_handle v);
1094 
1100  void remove_all_popable_blockers(Vertex_handle v);
1101 
1105  void remove_star(Vertex_handle v);
1106 
1107  private:
1113  void update_blockers_after_remove_star_of_vertex_or_edge(const Simplex& simplex_to_be_removed);
1114 
1115  public:
1120  void remove_star(Vertex_handle a, Vertex_handle b);
1121 
1125  void remove_star(Edge_handle e);
1126 
1130  void remove_star(const Simplex& sigma);
1131 
1136  void add_simplex(const Simplex& sigma);
1137 
1138  private:
1139  void add_blockers_after_simplex_insertion(Simplex s);
1140 
1144  void remove_blocker_containing_simplex(const Simplex& sigma);
1145 
1149  void remove_blocker_include_in_simplex(const Simplex& sigma);
1150 
1151  public:
1152  enum simplifiable_status {
1153  NOT_HOMOTOPY_EQ, MAYBE_HOMOTOPY_EQ, HOMOTOPY_EQ
1154  };
1155 
1156  simplifiable_status is_remove_star_homotopy_preserving(const Simplex& simplex) {
1157  // todo write a virtual method 'link' in Skeleton_blocker_complex which will be overloaded by the current one of
1158  // Skeleton_blocker_geometric_complex
1159  // then call it there to build the link and return the value of link.is_contractible()
1160  return MAYBE_HOMOTOPY_EQ;
1161  }
1162 
1163  enum contractible_status {
1164  NOT_CONTRACTIBLE, MAYBE_CONTRACTIBLE, CONTRACTIBLE
1165  };
1166 
1176  virtual contractible_status is_contractible() const {
1177  if (this->is_cone()) {
1178  return CONTRACTIBLE;
1179  } else {
1180  return MAYBE_CONTRACTIBLE;
1181  }
1182  }
1184 
1188 
1196  bool link_condition(Vertex_handle a, Vertex_handle b, bool ignore_popable_blockers = false) const {
1197  for (auto blocker : this->const_blocker_range(a))
1198  if (blocker->contains(b)) {
1199  // false if ignore_popable_blockers is false
1200  // otherwise the blocker has to be popable
1201  return ignore_popable_blockers && is_popable_blocker(blocker);
1202  }
1203  return true;
1204  }
1205 
1213  bool link_condition(Edge_handle e, bool ignore_popable_blockers = false) const {
1214  const Graph_edge& edge = (*this)[e];
1215  assert(this->get_address(edge.first()));
1216  assert(this->get_address(edge.second()));
1217  Vertex_handle a(*this->get_address(edge.first()));
1218  Vertex_handle b(*this->get_address(edge.second()));
1219  return link_condition(a, b, ignore_popable_blockers);
1220  }
1221 
1222  protected:
1228  void tip_blockers(Vertex_handle a, Vertex_handle b, std::vector<Simplex> & buffer) const;
1229 
1230  private:
1239  void swap_edge(Vertex_handle a, Vertex_handle b, Vertex_handle x);
1240 
1241  private:
1245  void delete_blockers_around_vertex(Vertex_handle v);
1246 
1250  void delete_blockers_around_edge(Vertex_handle a, Vertex_handle b);
1251 
1252  public:
1258  void contract_edge(Edge_handle edge) {
1259  contract_edge(this->first_vertex(edge), this->second_vertex(edge));
1260  }
1261 
1267  void contract_edge(Vertex_handle a, Vertex_handle b);
1268 
1269  private:
1270  void get_blockers_to_be_added_after_contraction(Vertex_handle a, Vertex_handle b,
1271  std::set<Simplex>& blockers_to_add);
1275  void delete_blockers_around_vertices(Vertex_handle a, Vertex_handle b);
1276  void update_edges_after_contraction(Vertex_handle a, Vertex_handle b);
1277  void notify_changed_edges(Vertex_handle a);
1279 
1280  public:
1282 
1286 
1287  //
1288  // Range over the vertices of the simplicial complex.
1289  // Methods .begin() and .end() return a Complex_vertex_iterator.
1290  //
1291  typedef boost::iterator_range<Complex_vertex_iterator> Complex_vertex_range;
1292 
1296  Complex_vertex_range vertex_range() const {
1297  auto begin = Complex_vertex_iterator(this);
1298  auto end = Complex_vertex_iterator(this, 0);
1299  return Complex_vertex_range(begin, end);
1300  }
1301 
1302  typedef Neighbors_vertices_iterator<Skeleton_blocker_complex> Complex_neighbors_vertices_iterator;
1303 
1304 
1305  typedef boost::iterator_range<Complex_neighbors_vertices_iterator> Complex_neighbors_vertices_range;
1306 
1310  Complex_neighbors_vertices_range vertex_range(Vertex_handle v) const {
1311  auto begin = Complex_neighbors_vertices_iterator(this, v);
1312  auto end = Complex_neighbors_vertices_iterator(this, v, 0);
1313  return Complex_neighbors_vertices_range(begin, end);
1314  }
1315 
1317 
1321 
1323 
1324 
1325  typedef boost::iterator_range<Complex_edge_iterator> Complex_edge_range;
1326 
1330  Complex_edge_range edge_range() const {
1331  auto begin = Complex_edge_iterator(this);
1332  auto end = Complex_edge_iterator(this, 0);
1333  return Complex_edge_range(begin, end);
1334  }
1335 
1336 
1337  typedef Edge_around_vertex_iterator<Skeleton_blocker_complex> Complex_edge_around_vertex_iterator;
1338 
1339 
1340  typedef boost::iterator_range <Complex_edge_around_vertex_iterator> Complex_edge_around_vertex_range;
1341 
1346  Complex_edge_around_vertex_range edge_range(Vertex_handle v) const {
1347  auto begin = Complex_edge_around_vertex_iterator(this, v);
1348  auto end = Complex_edge_around_vertex_iterator(this, v, 0);
1349  return Complex_edge_around_vertex_range(begin, end);
1350  }
1351 
1353 
1357  private:
1360 
1361  public:
1364  typedef boost::iterator_range < Triangle_around_vertex_iterator<Skeleton_blocker_complex, Link> >
1365  Complex_triangle_around_vertex_range;
1366 
1372  Complex_triangle_around_vertex_range triangle_range(Vertex_handle v) const {
1375  return Complex_triangle_around_vertex_range(begin, end);
1376  }
1377 
1378  typedef boost::iterator_range<Triangle_iterator<Skeleton_blocker_complex> > Complex_triangle_range;
1380 
1386  Complex_triangle_range triangle_range() const {
1387  auto end = Triangle_iterator<Skeleton_blocker_complex>(this, 0);
1388  if (empty()) {
1389  return Complex_triangle_range(end, end);
1390  } else {
1392  return Complex_triangle_range(begin, end);
1393  }
1394  }
1395 
1397 
1402 
1407  typedef boost::iterator_range < Complex_simplex_around_vertex_iterator > Complex_simplex_around_vertex_range;
1408 
1412  Complex_simplex_around_vertex_range star_simplex_range(Vertex_handle v) const {
1413  assert(contains_vertex(v));
1415  Complex_simplex_around_vertex_iterator(this, v),
1416  Complex_simplex_around_vertex_iterator(this, v, true));
1417  }
1419 
1424  typedef boost::iterator_range < Complex_simplex_coboundary_iterator > Complex_coboundary_range;
1425 
1429  Complex_coboundary_range coboundary_range(const Simplex& s) const {
1430  assert(contains(s));
1431  return Complex_coboundary_range(Complex_simplex_coboundary_iterator(this, s),
1432  Complex_simplex_coboundary_iterator(this, s, true));
1433  }
1434 
1435  // typedef Simplex_iterator<Skeleton_blocker_complex,Superior_link> Complex_simplex_iterator;
1436  typedef Simplex_iterator<Skeleton_blocker_complex> Complex_simplex_iterator;
1437 
1438  typedef boost::iterator_range < Complex_simplex_iterator > Complex_simplex_range;
1439 
1443  Complex_simplex_range complex_simplex_range() const {
1444  Complex_simplex_iterator end(this, true);
1445  if (empty()) {
1446  return Complex_simplex_range(end, end);
1447  } else {
1448  Complex_simplex_iterator begin(this);
1449  return Complex_simplex_range(begin, end);
1450  }
1451  }
1452 
1454 
1458  private:
1463  typename std::multimap<Vertex_handle, Simplex *>::iterator,
1464  Blocker_handle>
1466 
1471  typename std::multimap<Vertex_handle, Simplex *>::const_iterator,
1472  const Blocker_handle>
1474 
1475  typedef boost::iterator_range <Complex_blocker_around_vertex_iterator> Complex_blocker_around_vertex_range;
1476  typedef boost::iterator_range <Const_complex_blocker_around_vertex_iterator>
1477  Const_complex_blocker_around_vertex_range;
1478 
1479  public:
1483  Complex_blocker_around_vertex_range blocker_range(Vertex_handle v) {
1484  auto begin = Complex_blocker_around_vertex_iterator(blocker_map_.lower_bound(v));
1485  auto end = Complex_blocker_around_vertex_iterator(blocker_map_.upper_bound(v));
1486  return Complex_blocker_around_vertex_range(begin, end);
1487  }
1488 
1492  Const_complex_blocker_around_vertex_range const_blocker_range(Vertex_handle v) const {
1493  auto begin = Const_complex_blocker_around_vertex_iterator(blocker_map_.lower_bound(v));
1494  auto end = Const_complex_blocker_around_vertex_iterator(blocker_map_.upper_bound(v));
1495  return Const_complex_blocker_around_vertex_range(begin, end);
1496  }
1497 
1498  private:
1502  typedef Blocker_iterator_internal<
1503  typename std::multimap<Vertex_handle, Simplex *>::iterator,
1504  Blocker_handle>
1506 
1510  typedef Blocker_iterator_internal<
1511  typename std::multimap<Vertex_handle, Simplex *>::const_iterator,
1512  const Blocker_handle>
1514 
1515  typedef boost::iterator_range <Complex_blocker_iterator> Complex_blocker_range;
1516  typedef boost::iterator_range <Const_complex_blocker_iterator> Const_complex_blocker_range;
1517 
1518  public:
1522  Complex_blocker_range blocker_range() {
1523  auto begin = Complex_blocker_iterator(blocker_map_.begin(), blocker_map_.end());
1524  auto end = Complex_blocker_iterator(blocker_map_.end(), blocker_map_.end());
1525  return Complex_blocker_range(begin, end);
1526  }
1527 
1531  Const_complex_blocker_range const_blocker_range() const {
1532  auto begin = Const_complex_blocker_iterator(blocker_map_.begin(), blocker_map_.end());
1533  auto end = Const_complex_blocker_iterator(blocker_map_.end(), blocker_map_.end());
1534  return Const_complex_blocker_range(begin, end);
1535  }
1536 
1538 
1540 
1543  public:
1544  std::string to_string() const {
1545  std::ostringstream stream;
1546  stream << num_vertices() << " vertices:\n" << vertices_to_string() << std::endl;
1547  stream << num_edges() << " edges:\n" << edges_to_string() << std::endl;
1548  stream << num_blockers() << " blockers:\n" << blockers_to_string() << std::endl;
1549  return stream.str();
1550  }
1551 
1552  std::string vertices_to_string() const {
1553  std::ostringstream stream;
1554  for (auto vertex : vertex_range()) {
1555  stream << "{" << (*this)[vertex].get_id() << "} ";
1556  }
1557  stream << std::endl;
1558  return stream.str();
1559  }
1560 
1561  std::string edges_to_string() const {
1562  std::ostringstream stream;
1563  for (auto edge : edge_range())
1564  stream << "{" << (*this)[edge].first() << "," << (*this)[edge].second() << "} ";
1565  stream << std::endl;
1566  return stream.str();
1567  }
1568 
1569  std::string blockers_to_string() const {
1570  std::ostringstream stream;
1571 
1572  for (auto b : const_blocker_range())
1573  stream << *b << std::endl;
1574  return stream.str();
1575  }
1577 };
1578 
1584 template<typename Complex, typename SimplexHandleIterator>
1585 Complex make_complex_from_top_faces(SimplexHandleIterator simplices_begin, SimplexHandleIterator simplices_end,
1586  bool is_flag_complex = false) {
1587  // TODO(DS): use add_simplex instead! should be more efficient and more elegant :)
1588  typedef typename Complex::Simplex Simplex;
1589  std::vector<Simplex> simplices;
1590  for (auto top_face = simplices_begin; top_face != simplices_end; ++top_face) {
1591  auto subfaces_topface = subfaces(*top_face);
1592  simplices.insert(simplices.end(), subfaces_topface.begin(), subfaces_topface.end());
1593  }
1594  return Complex(simplices.begin(), simplices.end(), is_flag_complex);
1595 }
1596 
1597 } // namespace skeleton_blocker
1598 
1599 namespace skbl = skeleton_blocker;
1600 
1601 } // namespace Gudhi
1602 
1603 #include "Skeleton_blocker_simplifiable_complex.h"
1604 
1605 #endif // SKELETON_BLOCKER_COMPLEX_H_
Simplex get_vertices(Edge_handle edge_handle) const
returns the simplex made with the two vertices of the edge
Definition: Skeleton_blocker_complex.h:541
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:608
boost::iterator_range< Complex_simplex_coboundary_iterator > Complex_coboundary_range
Range over the simplices of the coboundary of a simplex. Methods .begin() and .end() return a Complex...
Definition: Skeleton_blocker_complex.h:1424
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:1492
Simplicial subcomplex of a complex represented by a skeleton/blockers pair.
Definition: Skeleton_blocker_link_superior.h:32
Abstract simplex used in Skeleton blockers data-structure.
Definition: Skeleton_blocker_simplex.h:50
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:444
Iterator through the blockers of a vertex.
Definition: Skeleton_blockers_blockers_iterators.h:91
bool contains_edge(Vertex_handle a, Vertex_handle b) const
Definition: Skeleton_blocker_complex.h:650
Vertex_handle second_vertex(Edge_handle edge_handle) const
returns the first vertex of an edge
Definition: Skeleton_blocker_complex.h:532
Simplex * Blocker_handle
Handle to a blocker of the complex.
Definition: Skeleton_blocker_complex.h:101
void add_vertex(T v)
Definition: Skeleton_blocker_simplex.h:122
bool contains_blocker(const Blocker_handle s) const
Definition: Skeleton_blocker_complex.h:792
Graph_vertex & operator[](Vertex_handle address)
Return the vertex node associated to local Vertex_handle.
Definition: Skeleton_blocker_complex.h:364
virtual void clear()
Definition: Skeleton_blocker_complex.h:323
int dimension() const
Definition: Skeleton_blocker_simplex.h:209
int degree(Vertex_handle local) const
return the graph degree of a vertex.
Definition: Skeleton_blocker_complex.h:480
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:496
SkeletonBlockerDS::Vertex_handle Vertex_handle
The type of an handle to a vertex of the complex.
Definition: Skeleton_blocker_complex.h:89
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 &#39;v&#39;...
Definition: Skeleton_blocker_complex.h:1346
bool contains_vertices(const Simplex &sigma) const
Definition: Skeleton_blocker_complex.h:433
void difference(const Skeleton_blocker_simplex &a)
Definition: Skeleton_blocker_simplex.h:151
void remove_vertex(T v)
Definition: Skeleton_blocker_simplex.h:129
Complex_simplex_range complex_simplex_range() const
Returns a Complex_simplex_range over all the simplices of the complex.
Definition: Skeleton_blocker_complex.h:1443
void contract_edge(Edge_handle edge)
Definition: Skeleton_blocker_complex.h:1258
Edge_handle add_edge(Vertex_handle a, Vertex_handle b)
Adds an edge between vertices a and b.
Definition: Skeleton_blocker_complex.h:553
bool contains_blocker(const Simplex &s) const
Definition: Skeleton_blocker_complex.h:808
Skeleton_blocker_simplex< Vertex_handle > Simplex
A ordered set of integers that represents a simplex.
Definition: Skeleton_blocker_complex.h:95
void remove_star(Vertex_handle v)
Definition: Skeleton_blocker_simplifiable_complex.h:133
Skeleton_blocker_complex(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end, bool is_flag_complex=false, Visitor *visitor_=NULL)
Constructor with a list of simplices.
Definition: Skeleton_blocker_complex.h:183
void set_visitor(Visitor *other_visitor)
allows to change the visitor.
Definition: Skeleton_blocker_complex.h:339
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:1372
Iterator on the vertices of a simplicial complex.
Definition: Skeleton_blockers_vertices_iterators.h:40
Iterator through the blockers of a vertex.
Definition: Skeleton_blockers_blockers_iterators.h:39
Definition: SimplicialComplexForAlpha.h:26
Skeleton_blocker_complex(size_t num_vertices_=0, Visitor *visitor_=NULL)
constructs a simplicial complex with a given number of vertices and a visitor.
Definition: Skeleton_blocker_complex.h:165
void remove_all_popable_blockers(Vertex_handle v)
Removes all the popable blockers of the complex passing through v and delete them. Also remove popable blockers in the neighborhood if they became popable.
Definition: Skeleton_blocker_simplifiable_complex.h:105
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:1386
Complex_edge_range edge_range() const
Returns a Complex_edge_range over all edges of the simplicial complex.
Definition: Skeleton_blocker_complex.h:1330
Root_vertex_handle and Vertex_handle are similar to global and local vertex descriptor used in boost ...
Definition: SkeletonBlockerDS.h:59
bool contains_edges(const Simplex &sigma) const
Definition: Skeleton_blocker_complex.h:659
Complex_blocker_range blocker_range()
Returns a range of the blockers of the complex.
Definition: Skeleton_blocker_complex.h:1522
Iterator on the edges of a simplicial complex.
Definition: Skeleton_blockers_edges_iterators.h:97
Blocker_handle add_blocker(const Simplex &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:681
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:470
bool contains(const Skeleton_blocker_simplex &a) const
Definition: Skeleton_blocker_simplex.h:240
Root_vertex_handle get_id(Vertex_handle local) const
Definition: Skeleton_blocker_complex.h:455
void add_simplex(const Simplex &sigma)
add a simplex and all its faces.
Definition: Skeleton_blocker_simplifiable_complex.h:209
Iterator over the triangles of the simplicial complex.
Definition: Skeleton_blockers_triangles_iterators.h:114
void remove_edge(Edge_handle edge)
Removes edge and its cofaces from the simplicial complex.
Definition: Skeleton_blocker_complex.h:625
The type of edges that are stored the boost graph. An Edge must be Default Constructible and Equality...
Definition: SkeletonBlockerDS.h:103
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:1483
SkeletonBlockerDS::Graph_edge Graph_edge
The type of stored edge node, specified by the template SkeletonBlockerDS.
Definition: Skeleton_blocker_complex.h:82
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:1407
Graph_edge & operator[](Edge_handle edge_handle)
returns the stored node associated to an edge
Definition: Skeleton_blocker_complex.h:509
virtual bool contains(const Simplex &s) const
returns true iff the simplex s belongs to the simplicial complex.
Definition: Skeleton_blocker_complex.h:964
Definition: Skeleton_blockers_simplices_iterators.h:314
Definition: Skeleton_blockers_simplices_iterators.h:50
void intersection(const Skeleton_blocker_simplex &a)
Definition: Skeleton_blocker_simplex.h:136
boost::optional< Simplex > get_simplex_address(const Root_simplex_handle &s) const
Compute the local vertices of &#39;s&#39; in the current complex If one of them is not present in the complex...
Definition: Skeleton_blocker_complex.h:931
Vertex_handle add_vertex()
Adds a vertex to the simplicial complex and returns its Vertex_handle.
Definition: Skeleton_blocker_complex.h:384
Const_complex_blocker_range const_blocker_range() const
Returns a range of the blockers of the complex.
Definition: Skeleton_blocker_complex.h:1531
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:1310
Iterator over the triangles that are adjacent to a vertex of the simplicial complex.
Definition: Skeleton_blockers_triangles_iterators.h:39
bool is_cone() const
Test if the complex is a cone.
Definition: Skeleton_blocker_complex.h:1052
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:635
void remove_vertex(Vertex_handle address)
Remove a vertex from the simplicial complex.
Definition: Skeleton_blocker_complex.h:402
const Graph_edge & operator[](Edge_handle edge_handle) const
returns the stored node associated to an edge
Definition: Skeleton_blocker_complex.h:516
Link_complex link(Vertex_handle v) const
Definition: Skeleton_blocker_complex.h:905
Vertex_handle first_vertex(Edge_handle edge_handle) const
returns the first vertex of an edge
Definition: Skeleton_blocker_complex.h:524
Root_simplex_handle get_id(const Simplex &local_simplex) const
returns a simplex with vertices which are the id of vertices of the argument.
Definition: Skeleton_blocker_complex.h:952
boost::graph_traits< Graph >::edge_descriptor Edge_handle
Handle to an edge of the complex.
Definition: Skeleton_blocker_complex.h:126
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:754
Complex_vertex_range vertex_range() const
Returns a Complex_vertex_range over all vertices of the complex.
Definition: Skeleton_blocker_complex.h:1296
void add_edge(const Simplex &s)
Adds all edges of s in the complex.
Definition: Skeleton_blocker_complex.h:566
virtual ~Skeleton_blocker_complex()
Definition: Skeleton_blocker_complex.h:314
Link_complex link(const Simplex &simplex) const
Definition: Skeleton_blocker_complex.h:919
bool is_popable_blocker(Blocker_handle sigma) const
Definition: Skeleton_blocker_simplifiable_complex.h:45
Interface for a visitor of a simplicial complex.
Definition: Skeleton_blocker_complex_visitor.h:38
bool operator==(const Skeleton_blocker_complex &other) const
Definition: Skeleton_blocker_complex.h:290
The type of vertices that are stored the boost graph. A Vertex must be Default Constructible and Equa...
Definition: SkeletonBlockerDS.h:79
int num_connected_components() const
returns the number of connected components in the graph of the 1-skeleton.
Definition: Skeleton_blocker_complex.h:1041
const Graph_vertex & operator[](Vertex_handle address) const
Return the vertex node associated to local Vertex_handle.
Definition: Skeleton_blocker_complex.h:374
void delete_blocker(Blocker_handle sigma)
Definition: Skeleton_blocker_complex.h:782
virtual contractible_status is_contractible() const
Test if the complex is reducible using a strategy defined in the class (by default it tests if the co...
Definition: Skeleton_blocker_complex.h:1176
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:354
Edge_handle add_edge_without_blockers(Vertex_handle a, Vertex_handle b)
Adds an edge between vertices a and b without blockers.
Definition: Skeleton_blocker_complex.h:578
SkeletonBlockerDS::Graph_vertex Graph_vertex
The type of stored vertex node, specified by the template SkeletonBlockerDS.
Definition: Skeleton_blocker_complex.h:77
Complex_simplex_around_vertex_range star_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:1412
void add_edge_without_blockers(Simplex s)
Adds all edges of s in the complex without adding blockers.
Definition: Skeleton_blocker_complex.h:597
void remove_blocker(const Blocker_handle sigma)
Removes the simplex from the set of blockers.
Definition: Skeleton_blocker_complex.h:744
Link_complex link(Edge_handle edge) const
Definition: Skeleton_blocker_complex.h:912
Abstract Simplicial Complex represented with a skeleton/blockers pair.
Definition: Skeleton_blocker_complex.h:63
void remove_popable_blockers()
Definition: Skeleton_blocker_simplifiable_complex.h:57
bool link_condition(Edge_handle e, bool ignore_popable_blockers=false) const
Definition: Skeleton_blocker_complex.h:1213
bool link_condition(Vertex_handle a, Vertex_handle b, bool ignore_popable_blockers=false) const
Definition: Skeleton_blocker_complex.h:1196
T first_vertex() const
Definition: Skeleton_blocker_simplex.h:222
Complex_coboundary_range coboundary_range(const Simplex &s) const
Returns a Complex_simplex_coboundary_iterator over the simplices of the coboundary of a simplex...
Definition: Skeleton_blocker_complex.h:1429
GUDHI  Version 2.2.0  - C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding.  - Copyright : GPL v3 Generated on Thu Jun 14 2018 15:00:55 for GUDHI by Doxygen 1.8.13