Skeleton_blocker_complex.h
1 /* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2  * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3  * Author(s): David Salinas
4  *
5  * Copyright (C) 2014 Inria
6  *
7  * Modification(s):
8  * - YYYY/MM Author: Description of the modification
9  */
10 
11 #ifndef SKELETON_BLOCKER_COMPLEX_H_
12 #define SKELETON_BLOCKER_COMPLEX_H_
13 
14 #include <gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h>
15 #include <gudhi/Skeleton_blocker_link_complex.h>
16 #include <gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h>
17 #include <gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h>
18 #include <gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h>
19 #include <gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h>
20 #include <gudhi/Skeleton_blocker/internal/Top_faces.h>
21 #include <gudhi/Skeleton_blocker/internal/Trie.h>
22 #include <gudhi/Debug_utils.h>
23 
24 #include <boost/graph/adjacency_list.hpp>
25 #include <boost/graph/connected_components.hpp>
26 #include <boost/iterator/transform_iterator.hpp>
27 #include <boost/range/adaptor/map.hpp>
28 
29 #include <iostream>
30 #include <fstream>
31 #include <sstream>
32 #include <memory>
33 #include <map>
34 #include <list>
35 #include <set>
36 #include <vector>
37 #include <string>
38 #include <algorithm>
39 #include <utility>
40 
41 namespace Gudhi {
42 
43 namespace skeleton_blocker {
44 
50 template<class SkeletonBlockerDS>
52  template<class ComplexType> friend class Vertex_iterator;
53  template<class ComplexType> friend class Neighbors_vertices_iterator;
54  template<class ComplexType> friend class Edge_iterator;
55  template<class ComplexType> friend class Edge_around_vertex_iterator;
56 
57  template<class ComplexType> friend class Skeleton_blocker_link_complex;
58  template<class ComplexType> friend class Skeleton_blocker_link_superior;
59  template<class ComplexType> friend class Skeleton_blocker_sub_complex;
60 
61  public:
66 
71 
72  typedef typename SkeletonBlockerDS::Root_vertex_handle Root_vertex_handle;
73 
78  typedef typename Root_vertex_handle::boost_vertex_handle boost_vertex_handle;
79 
85 
89  typedef Simplex* Blocker_handle;
90 
91  typedef typename Root_simplex_handle::Simplex_vertex_const_iterator Root_simplex_iterator;
92  typedef typename Simplex::Simplex_vertex_const_iterator Simplex_handle_iterator;
93 
94  protected:
95  typedef typename boost::adjacency_list<boost::setS, // edges
96  boost::vecS, // vertices
97  boost::undirectedS, Graph_vertex, Graph_edge> Graph;
98  // todo/remark : edges are not sorted, it heavily penalizes computation for SuperiorLink
99  // (eg Link with greater vertices)
100  // that burdens simplex iteration / complex initialization via list of simplices.
101  // to avoid that, one should modify the graph by storing two lists of adjacency for every
102  // vertex, the one with superior and the one with lower vertices, that way there is
103  // no more extra cost for computation of SuperiorLink
104  typedef typename boost::graph_traits<Graph>::vertex_iterator boost_vertex_iterator;
105  typedef typename boost::graph_traits<Graph>::edge_iterator boost_edge_iterator;
106 
107  protected:
108  typedef typename boost::graph_traits<Graph>::adjacency_iterator boost_adjacency_iterator;
109 
110  public:
114  typedef typename boost::graph_traits<Graph>::edge_descriptor Edge_handle;
115 
116  protected:
117  typedef std::multimap<Vertex_handle, Simplex *> BlockerMap;
118  typedef typename std::multimap<Vertex_handle, Simplex *>::value_type BlockerPair;
119  typedef typename std::multimap<Vertex_handle, Simplex *>::iterator BlockerMapIterator;
120  typedef typename std::multimap<Vertex_handle, Simplex *>::const_iterator BlockerMapConstIterator;
121 
122  protected:
123  size_t num_vertices_;
124  size_t num_blockers_;
125 
127  // typedef Visitor* Visitor_ptr;
128  Visitor* visitor;
129 
138  std::vector<boost_vertex_handle> degree_;
139  Graph skeleton;
142  BlockerMap blocker_map_;
143 
144  public:
146 
149 
153  explicit Skeleton_blocker_complex(size_t num_vertices_ = 0, Visitor* visitor_ = NULL)
154  : visitor(visitor_) {
155  clear();
156  for (size_t i = 0; i < num_vertices_; ++i) {
157  add_vertex();
158  }
159  }
160 
161  private:
162  // typedef Trie<Skeleton_blocker_complex<SkeletonBlockerDS>> STrie;
163  typedef Trie<Simplex> STrie;
164 
165  public:
170  template<typename SimpleHandleOutputIterator>
171  Skeleton_blocker_complex(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end,
172  bool is_flag_complex = false, Visitor* visitor_ = NULL)
173  : num_vertices_(0),
174  num_blockers_(0),
175  visitor(visitor_) {
176  add_vertices_and_edges(simplices_begin, simplices_end);
177 
178  if (!is_flag_complex)
179  // need to compute blockers
180  add_blockers(simplices_begin, simplices_end);
181  }
182 
183  private:
187  template<typename SimpleHandleOutputIterator>
188  void add_vertices_and_edges(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end) {
189  std::vector<std::pair<Vertex_handle, Vertex_handle>> edges;
190  // first pass to add vertices and edges
191  int num_vertex = -1;
192  for (auto s_it = simplices_begin; s_it != simplices_end; ++s_it) {
193  if (s_it->dimension() == 0) num_vertex = (std::max)(num_vertex, s_it->first_vertex().vertex);
194  if (s_it->dimension() == 1) edges.emplace_back(s_it->first_vertex(), s_it->last_vertex());
195  }
196  while (num_vertex-- >= 0) add_vertex();
197 
198  for (const auto& e : edges)
199  add_edge_without_blockers(e.first, e.second);
200  }
201 
202  template<typename SimpleHandleOutputIterator>
203  void add_blockers(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end) {
204  Tries<Simplex> tries(num_vertices(), simplices_begin, simplices_end);
205  tries.init_next_dimension();
206  auto simplices(tries.next_dimension_simplices());
207 
208  while (!simplices.empty()) {
209  simplices = tries.next_dimension_simplices();
210  for (auto& sigma : simplices) {
211  // common_positive_neighbors is the set of vertices u such that
212  // for all s in sigma, us is an edge and u>s
213  Simplex common_positive_neighbors(tries.positive_neighbors(sigma.last_vertex()));
214  for (auto sigma_it = sigma.rbegin(); sigma_it != sigma.rend(); ++sigma_it)
215  if (sigma_it != sigma.rbegin())
216  common_positive_neighbors.intersection(tries.positive_neighbors(*sigma_it));
217 
218  for (auto x : common_positive_neighbors) {
219  // first test that all edges sx are here for all s in sigma
220  bool all_edges_here = true;
221  for (auto s : sigma)
222  if (!contains_edge(x, s)) {
223  all_edges_here = false;
224  break;
225  }
226  if (!all_edges_here) continue;
227 
228  // all edges of sigma \cup x are here
229  // we have a blocker if all proper faces of sigma \cup x
230  // are in the complex and if sigma \cup x is not in the complex
231  // the first is equivalent at checking if blocks(sigma \cup x) is true
232  // as all blockers of lower dimension have already been computed
233  sigma.add_vertex(x);
234  if (!tries.contains(sigma) && !blocks(sigma))
235  add_blocker(sigma);
236  sigma.remove_vertex(x);
237  }
238  }
239  }
240  }
241 
242  public:
243  // We cannot use the default copy constructor since we need
244  // to make a copy of each of the blockers
245 
247  visitor = NULL;
248  degree_ = copy.degree_;
249  skeleton = Graph(copy.skeleton);
250  num_vertices_ = copy.num_vertices_;
251 
252  num_blockers_ = 0;
253  // we copy the blockers
254  for (auto blocker : copy.const_blocker_range()) {
255  add_blocker(*blocker);
256  }
257  }
258 
261  Skeleton_blocker_complex& operator=(const Skeleton_blocker_complex& copy) {
262  clear();
263  visitor = NULL;
264  degree_ = copy.degree_;
265  skeleton = Graph(copy.skeleton);
266  num_vertices_ = copy.num_vertices_;
267 
268  num_blockers_ = 0;
269  // we copy the blockers
270  for (auto blocker : copy.const_blocker_range())
271  add_blocker(*blocker);
272  return *this;
273  }
274 
278  bool operator==(const Skeleton_blocker_complex& other) const {
279  if (other.num_vertices() != num_vertices()) return false;
280  if (other.num_edges() != num_edges()) return false;
281  if (other.num_blockers() != num_blockers()) return false;
282 
283  for (auto v : vertex_range())
284  if (!other.contains_vertex(v)) return false;
285 
286  for (auto e : edge_range())
287  if (!other.contains_edge(first_vertex(e), second_vertex(e))) return false;
288 
289  for (const auto b : const_blocker_range())
290  if (!other.contains_blocker(*b)) return false;
291 
292  return true;
293  }
294 
295  bool operator!=(const Skeleton_blocker_complex& other) const {
296  return !(*this == other);
297  }
298 
303  clear();
304  }
305 
311  virtual void clear() {
312  // xxx for now the responsabilty of freeing the visitor is for
313  // the user
314  visitor = NULL;
315 
316  degree_.clear();
317  num_vertices_ = 0;
318 
319  remove_blockers();
320 
321  skeleton.clear();
322  }
323 
327  void set_visitor(Visitor* other_visitor) {
328  visitor = other_visitor;
329  }
330 
332 
334 
337  public:
342  Vertex_handle operator[](Root_vertex_handle global) const {
343  auto local(get_address(global));
344  assert(local);
345  return *local;
346  }
347 
352  Graph_vertex& operator[](Vertex_handle address) {
353  assert(
354  0 <= address.vertex && address.vertex < boost::num_vertices(skeleton));
355  return skeleton[address.vertex];
356  }
357 
362  const Graph_vertex& operator[](Vertex_handle address) const {
363  assert(
364  0 <= address.vertex && address.vertex < boost::num_vertices(skeleton));
365  return skeleton[address.vertex];
366  }
367 
372  Vertex_handle add_vertex() {
373  Vertex_handle address(boost::add_vertex(skeleton));
374  num_vertices_++;
375  (*this)[address].activate();
376  // safe since we now that we are in the root complex and the field 'address' and 'id'
377  // are identical for every vertices
378  (*this)[address].set_id(Root_vertex_handle(address.vertex));
379  degree_.push_back(0);
380  if (visitor)
381  visitor->on_add_vertex(address);
382  return address;
383  }
384 
390  void remove_vertex(Vertex_handle address) {
391  assert(contains_vertex(address));
392  // We remove b
393  boost::clear_vertex(address.vertex, skeleton);
394  (*this)[address].deactivate();
395  num_vertices_--;
396  degree_[address.vertex] = -1;
397  if (visitor)
398  visitor->on_remove_vertex(address);
399  }
400 
403  bool contains_vertex(Vertex_handle u) const {
404  Vertex_handle num_vertices(boost::num_vertices(skeleton));
405  if (u.vertex < 0 || u.vertex >= num_vertices)
406  return false;
407  return (*this)[u].is_active();
408  }
409 
412  bool contains_vertex(Root_vertex_handle u) const {
413  boost::optional<Vertex_handle> address = get_address(u);
414  return address && (*this)[*address].is_active();
415  }
416 
421  bool contains_vertices(const Simplex & sigma) const {
422  for (auto vertex : sigma)
423  if (!contains_vertex(vertex))
424  return false;
425  return true;
426  }
427 
432  virtual boost::optional<Vertex_handle> get_address(Root_vertex_handle id) const {
433  boost::optional<Vertex_handle> res;
434  int num_vertices = boost::num_vertices(skeleton);
435  if (id.vertex < num_vertices)
436  res = Vertex_handle(id.vertex);
437  return res;
438  }
439 
443  Root_vertex_handle get_id(Vertex_handle local) const {
444  assert(0 <= local.vertex && local.vertex < boost::num_vertices(skeleton));
445  return (*this)[local].get_id();
446  }
447 
459  Vertex_handle vh_in_other) const {
460  auto vh_in_current_complex = get_address(other.get_id(vh_in_other));
461  assert(vh_in_current_complex);
462  return *vh_in_current_complex;
463  }
464 
468  int degree(Vertex_handle local) const {
469  assert(0 <= local.vertex && local.vertex < boost::num_vertices(skeleton));
470  return degree_[local.vertex];
471  }
472 
474 
476 
479  public:
484  boost::optional<Edge_handle> operator[](
485  const std::pair<Vertex_handle, Vertex_handle>& ab) const {
486  boost::optional<Edge_handle> res;
487  std::pair<Edge_handle, bool> edge_pair(
488  boost::edge(ab.first.vertex, ab.second.vertex, skeleton));
489  if (edge_pair.second)
490  res = edge_pair.first;
491  return res;
492  }
493 
497  Graph_edge& operator[](Edge_handle edge_handle) {
498  return skeleton[edge_handle];
499  }
500 
504  const Graph_edge& operator[](Edge_handle edge_handle) const {
505  return skeleton[edge_handle];
506  }
507 
512  Vertex_handle first_vertex(Edge_handle edge_handle) const {
513  return static_cast<Vertex_handle> (source(edge_handle, skeleton));
514  }
515 
520  Vertex_handle second_vertex(Edge_handle edge_handle) const {
521  return static_cast<Vertex_handle> (target(edge_handle, skeleton));
522  }
523 
529  Simplex get_vertices(Edge_handle edge_handle) const {
530  auto edge((*this)[edge_handle]);
531  return Simplex((*this)[edge.first()], (*this)[edge.second()]);
532  }
533 
541  Edge_handle add_edge(Vertex_handle a, Vertex_handle b) {
542  // if the edge is already there we musnt go further
543  // as we may add blockers that should not be here
544  if (contains_edge(a, b))
545  return *((*this)[std::make_pair(a, b)]);
546  auto res = add_edge_without_blockers(a, b);
547  add_blockers_after_simplex_insertion(Simplex(a, b));
548  return res;
549  }
550 
554  void add_edge(const Simplex& s) {
555  for (auto i = s.begin(); i != s.end(); ++i)
556  for (auto j = i; ++j != s.end(); )
557  add_edge(*i, *j);
558  }
559 
566  Edge_handle add_edge_without_blockers(Vertex_handle a, Vertex_handle b) {
567  assert(contains_vertex(a) && contains_vertex(b));
568  assert(a != b);
569 
570  auto edge_handle((*this)[std::make_pair(a, b)]);
571  if (!edge_handle) {
572  edge_handle = boost::add_edge(a.vertex, b.vertex, skeleton).first;
573  (*this)[*edge_handle].setId(get_id(a), get_id(b));
574  degree_[a.vertex]++;
575  degree_[b.vertex]++;
576  if (visitor)
577  visitor->on_add_edge_without_blockers(a, b);
578  }
579  return *edge_handle;
580  }
581 
585  void add_edge_without_blockers(Simplex s) {
586  for (auto i = s.begin(); i != s.end(); ++i) {
587  for (auto j = i; ++j != s.end(); )
589  }
590  }
591 
596  virtual Edge_handle remove_edge(Vertex_handle a, Vertex_handle b) {
597  bool found;
598  Edge_handle edge;
599  tie(edge, found) = boost::edge(a.vertex, b.vertex, skeleton);
600  if (found) {
601  if (visitor)
602  visitor->on_remove_edge(a, b);
603  boost::remove_edge(a.vertex, b.vertex, skeleton);
604  degree_[a.vertex]--;
605  degree_[b.vertex]--;
606  }
607  return edge;
608  }
609 
613  void remove_edge(Edge_handle edge) {
614  assert(contains_vertex(first_vertex(edge)));
615  assert(contains_vertex(second_vertex(edge)));
616  remove_edge(first_vertex(edge), second_vertex(edge));
617  }
618 
624  remove_blockers();
625 
626  for (auto u : vertex_range()) {
627  while (this->degree(u) > 0) {
628  Vertex_handle v(*(adjacent_vertices(u.vertex, this->skeleton).first));
629  this->remove_edge(u, v);
630  }
631  }
632  }
633 
638  bool contains_edge(Vertex_handle a, Vertex_handle b) const {
639  // if (a.vertex<0 || b.vertex <0) return false;
640  return boost::edge(a.vertex, b.vertex, skeleton).second;
641  }
642 
647  bool contains_edges(const Simplex & sigma) const {
648  for (auto i = sigma.begin(); i != sigma.end(); ++i) {
649  if (!contains_vertex(*i))
650  return false;
651  for (auto j = i; ++j != sigma.end();) {
652  if (!contains_edge(*i, *j))
653  return false;
654  }
655  }
656  return true;
657  }
659 
661 
664 
669  Blocker_handle add_blocker(const Simplex& blocker) {
670  assert(blocker.dimension() > 1);
671  if (contains_blocker(blocker)) {
672  return 0;
673  } else {
674  if (visitor)
675  visitor->on_add_blocker(blocker);
676  Blocker_handle blocker_pt = new Simplex(blocker);
677  num_blockers_++;
678  auto vertex = blocker_pt->begin();
679  while (vertex != blocker_pt->end()) {
680  blocker_map_.insert(BlockerPair(*vertex, blocker_pt));
681  ++vertex;
682  }
683  return blocker_pt;
684  }
685  }
686 
687  protected:
691  void add_blocker(Blocker_handle blocker) {
692  if (contains_blocker(*blocker)) {
693  // std::cerr << "ATTEMPT TO ADD A BLOCKER ALREADY THERE ---> BLOCKER IGNORED" << endl;
694  return;
695  } else {
696  if (visitor)
697  visitor->on_add_blocker(*blocker);
698  num_blockers_++;
699  auto vertex = blocker->begin();
700  while (vertex != blocker->end()) {
701  blocker_map_.insert(BlockerPair(*vertex, blocker));
702  ++vertex;
703  }
704  }
705  }
706 
707  protected:
711  void remove_blocker(const Blocker_handle sigma, Vertex_handle v) {
713  for (blocker = blocker_range(v).begin(); blocker != blocker_range(v).end();
714  ++blocker) {
715  if (*blocker == sigma)
716  break;
717  }
718  if (*blocker != sigma) {
719  std::cerr
720  << "bug ((*blocker).second == sigma) ie try to remove a blocker not present\n";
721  assert(false);
722  } else {
723  blocker_map_.erase(blocker.current_position());
724  }
725  }
726 
727  public:
732  void remove_blocker(const Blocker_handle sigma) {
733  for (auto vertex : *sigma)
734  remove_blocker(sigma, vertex);
735  num_blockers_--;
736  }
737 
743  // Desallocate the blockers
744  while (!blocker_map_.empty()) {
745  delete_blocker(blocker_map_.begin()->second);
746  }
747  num_blockers_ = 0;
748  blocker_map_.clear();
749  }
750 
751  protected:
758  void remove_blocker(const Simplex& sigma) {
759  assert(contains_blocker(sigma));
760  for (auto vertex : sigma)
761  remove_blocker(sigma, vertex);
762  num_blockers_--;
763  }
764 
765  public:
770  void delete_blocker(Blocker_handle sigma) {
771  if (visitor)
772  visitor->on_delete_blocker(sigma);
773  remove_blocker(sigma);
774  delete sigma;
775  }
776 
780  bool contains_blocker(const Blocker_handle s) const {
781  if (s->dimension() < 2)
782  return false;
783 
784  Vertex_handle a = s->first_vertex();
785 
786  for (const auto blocker : const_blocker_range(a)) {
787  if (s == *blocker)
788  return true;
789  }
790  return false;
791  }
792 
796  bool contains_blocker(const Simplex & s) const {
797  if (s.dimension() < 2)
798  return false;
799 
800  Vertex_handle a = s.first_vertex();
801 
802  for (auto blocker : const_blocker_range(a)) {
803  if (s == *blocker)
804  return true;
805  }
806  return false;
807  }
808 
809  private:
814  bool blocks(const Simplex & sigma) const {
815  for (auto s : sigma)
816  for (auto blocker : const_blocker_range(s))
817  if (sigma.contains(*blocker))
818  return true;
819  return false;
820  }
821 
823 
824  protected:
829  virtual void add_neighbours(Vertex_handle v, Simplex & n,
830  bool keep_only_superior = false) const {
831  boost_adjacency_iterator ai, ai_end;
832  for (tie(ai, ai_end) = adjacent_vertices(v.vertex, skeleton); ai != ai_end;
833  ++ai) {
834  Vertex_handle value(*ai);
835  if (keep_only_superior) {
836  if (value > v.vertex) {
837  n.add_vertex(value);
838  }
839  } else {
840  n.add_vertex(value);
841  }
842  }
843  }
844 
853  virtual void add_neighbours(const Simplex &alpha, Simplex & res,
854  bool keep_only_superior = false) const {
855  res.clear();
856  auto alpha_vertex = alpha.begin();
857  add_neighbours(*alpha_vertex, res, keep_only_superior);
858  for (alpha_vertex = (alpha.begin())++; alpha_vertex != alpha.end();
859  ++alpha_vertex)
860  keep_neighbours(*alpha_vertex, res, keep_only_superior);
861  }
862 
868  virtual void keep_neighbours(Vertex_handle v, Simplex& res,
869  bool keep_only_superior = false) const {
870  Simplex nv;
871  add_neighbours(v, nv, keep_only_superior);
872  res.intersection(nv);
873  }
874 
880  virtual void remove_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.difference(nv);
885  }
886 
887  public:
889 
893  Link_complex link(Vertex_handle v) const {
894  return Link_complex(*this, Simplex(v));
895  }
896 
900  Link_complex link(Edge_handle edge) const {
901  return Link_complex(*this, edge);
902  }
903 
907  Link_complex link(const Simplex& simplex) const {
908  return Link_complex(*this, simplex);
909  }
910 
917  // xxx rename get_address et place un using dans sub_complex
918 
919  boost::optional<Simplex> get_simplex_address(
920  const Root_simplex_handle& s) const {
921  boost::optional<Simplex> res;
922 
923  Simplex s_address;
924  // Root_simplex_const_iterator i;
925  for (auto i = s.begin(); i != s.end(); ++i) {
926  boost::optional<Vertex_handle> address = get_address(*i);
927  if (!address)
928  return res;
929  else
930  s_address.add_vertex(*address);
931  }
932  res = s_address;
933  return res;
934  }
935 
940  Root_simplex_handle get_id(const Simplex& local_simplex) const {
941  Root_simplex_handle global_simplex;
942  for (auto x = local_simplex.begin(); x != local_simplex.end(); ++x) {
943  global_simplex.add_vertex(get_id(*x));
944  }
945  return global_simplex;
946  }
947 
952  virtual bool contains(const Simplex & s) const {
953  if (s.dimension() == -1) {
954  return false;
955  } else if (s.dimension() == 0) {
956  return contains_vertex(s.first_vertex());
957  } else {
958  return (contains_edges(s) && !blocks(s));
959  }
960  }
961 
962  /*
963  * @brief returnrs true iff the complex is empty.
964  */
965  bool empty() const {
966  return num_vertices() == 0;
967  }
968 
969  /*
970  * @brief returns the number of vertices in the complex.
971  */
972  int num_vertices() const {
973  // remark boost::num_vertices(skeleton) counts deactivated vertices
974  return num_vertices_;
975  }
976 
977  /*
978  * @brief returns the number of edges in the complex.
979  * @details currently in O(n)
980  */
981  // todo cache the value
982 
983  int num_edges() const {
984  return boost::num_edges(skeleton);
985  }
986 
987  int num_triangles() const {
988  auto triangles = triangle_range();
989  return std::distance(triangles.begin(), triangles.end());
990  }
991 
992  /*
993  * @brief returns the number of simplices of a given dimension in the complex.
994  */
995  size_t num_simplices() const {
996  auto simplices = complex_simplex_range();
997  return std::distance(simplices.begin(), simplices.end());
998  }
999 
1000  /*
1001  * @brief returns the number of simplices of a given dimension in the complex.
1002  */
1003  size_t num_simplices(int dimension) const {
1004  // TODO(DS): iterator on k-simplices
1005  size_t res = 0;
1006  for (const auto& s : complex_simplex_range())
1007  if (s.dimension() == dimension)
1008  ++res;
1009  return res;
1010  }
1011 
1012  /*
1013  * @brief returns the number of blockers in the complex.
1014  */
1015  size_t num_blockers() const {
1016  return num_blockers_;
1017  }
1018 
1019  /*
1020  * @brief returns true iff the graph of the 1-skeleton of the complex is complete.
1021  */
1022  bool complete() const {
1023  return (num_vertices() * (num_vertices() - 1)) / 2 == num_edges();
1024  }
1025 
1030  int num_vert_collapsed = skeleton.vertex_set().size() - num_vertices();
1031  std::vector<int> component(skeleton.vertex_set().size());
1032  return boost::connected_components(this->skeleton, &component[0])
1033  - num_vert_collapsed;
1034  }
1035 
1040  bool is_cone() const {
1041  if (num_vertices() == 0)
1042  return false;
1043  if (num_vertices() == 1)
1044  return true;
1045  for (auto vi : vertex_range()) {
1046  // xxx todo faire une methode bool is_in_blocker(Vertex_handle)
1047  if (blocker_map_.find(vi) == blocker_map_.end()) {
1048  // no blocker passes through the vertex, we just need to
1049  // check if the current vertex is linked to all others vertices of the complex
1050  if (degree_[vi.vertex] == num_vertices() - 1)
1051  return true;
1052  }
1053  }
1054  return false;
1055  }
1056 
1058 
1061 
1070  bool is_popable_blocker(Blocker_handle sigma) const;
1071 
1076  void remove_popable_blockers();
1077 
1081  void remove_popable_blockers(Vertex_handle v);
1082 
1088  void remove_all_popable_blockers(Vertex_handle v);
1089 
1093  void remove_star(Vertex_handle v);
1094 
1095  private:
1101  void update_blockers_after_remove_star_of_vertex_or_edge(const Simplex& simplex_to_be_removed);
1102 
1103  public:
1108  void remove_star(Vertex_handle a, Vertex_handle b);
1109 
1113  void remove_star(Edge_handle e);
1114 
1118  void remove_star(const Simplex& sigma);
1119 
1124  void add_simplex(const Simplex& sigma);
1125 
1126  private:
1127  void add_blockers_after_simplex_insertion(Simplex s);
1128 
1132  void remove_blocker_containing_simplex(const Simplex& sigma);
1133 
1137  void remove_blocker_include_in_simplex(const Simplex& sigma);
1138 
1139  public:
1140  enum simplifiable_status {
1141  NOT_HOMOTOPY_EQ, MAYBE_HOMOTOPY_EQ, HOMOTOPY_EQ
1142  };
1143 
1144  simplifiable_status is_remove_star_homotopy_preserving(const Simplex& simplex) {
1145  // todo write a virtual method 'link' in Skeleton_blocker_complex which will be overloaded by the current one of
1146  // Skeleton_blocker_geometric_complex
1147  // then call it there to build the link and return the value of link.is_contractible()
1148  return MAYBE_HOMOTOPY_EQ;
1149  }
1150 
1151  enum contractible_status {
1152  NOT_CONTRACTIBLE, MAYBE_CONTRACTIBLE, CONTRACTIBLE
1153  };
1154 
1164  virtual contractible_status is_contractible() const {
1165  if (this->is_cone()) {
1166  return CONTRACTIBLE;
1167  } else {
1168  return MAYBE_CONTRACTIBLE;
1169  }
1170  }
1172 
1176 
1184  bool link_condition(Vertex_handle a, Vertex_handle b, bool ignore_popable_blockers = false) const {
1185  for (auto blocker : this->const_blocker_range(a))
1186  if (blocker->contains(b)) {
1187  // false if ignore_popable_blockers is false
1188  // otherwise the blocker has to be popable
1189  return ignore_popable_blockers && is_popable_blocker(blocker);
1190  }
1191  return true;
1192  }
1193 
1201  bool link_condition(Edge_handle e, bool ignore_popable_blockers = false) const {
1202  const Graph_edge& edge = (*this)[e];
1203  assert(this->get_address(edge.first()));
1204  assert(this->get_address(edge.second()));
1205  Vertex_handle a(*this->get_address(edge.first()));
1206  Vertex_handle b(*this->get_address(edge.second()));
1207  return link_condition(a, b, ignore_popable_blockers);
1208  }
1209 
1210  protected:
1216  void tip_blockers(Vertex_handle a, Vertex_handle b, std::vector<Simplex> & buffer) const;
1217 
1218  private:
1227  void swap_edge(Vertex_handle a, Vertex_handle b, Vertex_handle x);
1228 
1229  private:
1233  void delete_blockers_around_vertex(Vertex_handle v);
1234 
1238  void delete_blockers_around_edge(Vertex_handle a, Vertex_handle b);
1239 
1240  public:
1246  void contract_edge(Edge_handle edge) {
1247  contract_edge(this->first_vertex(edge), this->second_vertex(edge));
1248  }
1249 
1255  void contract_edge(Vertex_handle a, Vertex_handle b);
1256 
1257  private:
1258  void get_blockers_to_be_added_after_contraction(Vertex_handle a, Vertex_handle b,
1259  std::set<Simplex>& blockers_to_add);
1263  void delete_blockers_around_vertices(Vertex_handle a, Vertex_handle b);
1264  void update_edges_after_contraction(Vertex_handle a, Vertex_handle b);
1265  void notify_changed_edges(Vertex_handle a);
1267 
1268  public:
1270 
1274 
1275  //
1276  // Range over the vertices of the simplicial complex.
1277  // Methods .begin() and .end() return a Complex_vertex_iterator.
1278  //
1279  typedef boost::iterator_range<Complex_vertex_iterator> Complex_vertex_range;
1280 
1284  Complex_vertex_range vertex_range() const {
1285  auto begin = Complex_vertex_iterator(this);
1286  auto end = Complex_vertex_iterator(this, 0);
1287  return Complex_vertex_range(begin, end);
1288  }
1289 
1290  typedef Neighbors_vertices_iterator<Skeleton_blocker_complex> Complex_neighbors_vertices_iterator;
1291 
1292 
1293  typedef boost::iterator_range<Complex_neighbors_vertices_iterator> Complex_neighbors_vertices_range;
1294 
1298  Complex_neighbors_vertices_range vertex_range(Vertex_handle v) const {
1299  auto begin = Complex_neighbors_vertices_iterator(this, v);
1300  auto end = Complex_neighbors_vertices_iterator(this, v, 0);
1301  return Complex_neighbors_vertices_range(begin, end);
1302  }
1303 
1305 
1309 
1311 
1312 
1313  typedef boost::iterator_range<Complex_edge_iterator> Complex_edge_range;
1314 
1318  Complex_edge_range edge_range() const {
1319  auto begin = Complex_edge_iterator(this);
1320  auto end = Complex_edge_iterator(this, 0);
1321  return Complex_edge_range(begin, end);
1322  }
1323 
1324 
1325  typedef Edge_around_vertex_iterator<Skeleton_blocker_complex> Complex_edge_around_vertex_iterator;
1326 
1327 
1328  typedef boost::iterator_range <Complex_edge_around_vertex_iterator> Complex_edge_around_vertex_range;
1329 
1334  Complex_edge_around_vertex_range edge_range(Vertex_handle v) const {
1335  auto begin = Complex_edge_around_vertex_iterator(this, v);
1336  auto end = Complex_edge_around_vertex_iterator(this, v, 0);
1337  return Complex_edge_around_vertex_range(begin, end);
1338  }
1339 
1341 
1345  private:
1348 
1349  public:
1352  typedef boost::iterator_range < Triangle_around_vertex_iterator<Skeleton_blocker_complex, Link> >
1353  Complex_triangle_around_vertex_range;
1354 
1360  Complex_triangle_around_vertex_range triangle_range(Vertex_handle v) const {
1363  return Complex_triangle_around_vertex_range(begin, end);
1364  }
1365 
1366  typedef boost::iterator_range<Triangle_iterator<Skeleton_blocker_complex> > Complex_triangle_range;
1368 
1374  Complex_triangle_range triangle_range() const {
1375  auto end = Triangle_iterator<Skeleton_blocker_complex>(this, 0);
1376  if (empty()) {
1377  return Complex_triangle_range(end, end);
1378  } else {
1380  return Complex_triangle_range(begin, end);
1381  }
1382  }
1383 
1385 
1390 
1395  typedef boost::iterator_range < Complex_simplex_around_vertex_iterator > Complex_simplex_around_vertex_range;
1396 
1400  Complex_simplex_around_vertex_range star_simplex_range(Vertex_handle v) const {
1401  assert(contains_vertex(v));
1403  Complex_simplex_around_vertex_iterator(this, v),
1404  Complex_simplex_around_vertex_iterator(this, v, true));
1405  }
1407 
1412  typedef boost::iterator_range < Complex_simplex_coboundary_iterator > Complex_coboundary_range;
1413 
1417  Complex_coboundary_range coboundary_range(const Simplex& s) const {
1418  assert(contains(s));
1419  return Complex_coboundary_range(Complex_simplex_coboundary_iterator(this, s),
1420  Complex_simplex_coboundary_iterator(this, s, true));
1421  }
1422 
1423  // typedef Simplex_iterator<Skeleton_blocker_complex,Superior_link> Complex_simplex_iterator;
1424  typedef Simplex_iterator<Skeleton_blocker_complex> Complex_simplex_iterator;
1425 
1426  typedef boost::iterator_range < Complex_simplex_iterator > Complex_simplex_range;
1427 
1431  Complex_simplex_range complex_simplex_range() const {
1432  Complex_simplex_iterator end(this, true);
1433  if (empty()) {
1434  return Complex_simplex_range(end, end);
1435  } else {
1436  Complex_simplex_iterator begin(this);
1437  return Complex_simplex_range(begin, end);
1438  }
1439  }
1440 
1442 
1446  private:
1451  typename std::multimap<Vertex_handle, Simplex *>::iterator,
1452  Blocker_handle>
1454 
1459  typename std::multimap<Vertex_handle, Simplex *>::const_iterator,
1460  const Blocker_handle>
1462 
1463  typedef boost::iterator_range <Complex_blocker_around_vertex_iterator> Complex_blocker_around_vertex_range;
1464  typedef boost::iterator_range <Const_complex_blocker_around_vertex_iterator>
1465  Const_complex_blocker_around_vertex_range;
1466 
1467  public:
1471  Complex_blocker_around_vertex_range blocker_range(Vertex_handle v) {
1472  auto begin = Complex_blocker_around_vertex_iterator(blocker_map_.lower_bound(v));
1473  auto end = Complex_blocker_around_vertex_iterator(blocker_map_.upper_bound(v));
1474  return Complex_blocker_around_vertex_range(begin, end);
1475  }
1476 
1480  Const_complex_blocker_around_vertex_range const_blocker_range(Vertex_handle v) const {
1481  auto begin = Const_complex_blocker_around_vertex_iterator(blocker_map_.lower_bound(v));
1482  auto end = Const_complex_blocker_around_vertex_iterator(blocker_map_.upper_bound(v));
1483  return Const_complex_blocker_around_vertex_range(begin, end);
1484  }
1485 
1486  private:
1490  typedef Blocker_iterator_internal<
1491  typename std::multimap<Vertex_handle, Simplex *>::iterator,
1492  Blocker_handle>
1494 
1498  typedef Blocker_iterator_internal<
1499  typename std::multimap<Vertex_handle, Simplex *>::const_iterator,
1500  const Blocker_handle>
1502 
1503  typedef boost::iterator_range <Complex_blocker_iterator> Complex_blocker_range;
1504  typedef boost::iterator_range <Const_complex_blocker_iterator> Const_complex_blocker_range;
1505 
1506  public:
1510  Complex_blocker_range blocker_range() {
1511  auto begin = Complex_blocker_iterator(blocker_map_.begin(), blocker_map_.end());
1512  auto end = Complex_blocker_iterator(blocker_map_.end(), blocker_map_.end());
1513  return Complex_blocker_range(begin, end);
1514  }
1515 
1519  Const_complex_blocker_range const_blocker_range() const {
1520  auto begin = Const_complex_blocker_iterator(blocker_map_.begin(), blocker_map_.end());
1521  auto end = Const_complex_blocker_iterator(blocker_map_.end(), blocker_map_.end());
1522  return Const_complex_blocker_range(begin, end);
1523  }
1524 
1526 
1528 
1531  public:
1532  std::string to_string() const {
1533  std::ostringstream stream;
1534  stream << num_vertices() << " vertices:\n" << vertices_to_string() << std::endl;
1535  stream << num_edges() << " edges:\n" << edges_to_string() << std::endl;
1536  stream << num_blockers() << " blockers:\n" << blockers_to_string() << std::endl;
1537  return stream.str();
1538  }
1539 
1540  std::string vertices_to_string() const {
1541  std::ostringstream stream;
1542  for (auto vertex : vertex_range()) {
1543  stream << "{" << (*this)[vertex].get_id() << "} ";
1544  }
1545  stream << std::endl;
1546  return stream.str();
1547  }
1548 
1549  std::string edges_to_string() const {
1550  std::ostringstream stream;
1551  for (auto edge : edge_range())
1552  stream << "{" << (*this)[edge].first() << "," << (*this)[edge].second() << "} ";
1553  stream << std::endl;
1554  return stream.str();
1555  }
1556 
1557  std::string blockers_to_string() const {
1558  std::ostringstream stream;
1559 
1560  for (auto b : const_blocker_range())
1561  stream << *b << std::endl;
1562  return stream.str();
1563  }
1565 };
1566 
1572 template<typename Complex, typename SimplexHandleIterator>
1573 Complex make_complex_from_top_faces(SimplexHandleIterator simplices_begin, SimplexHandleIterator simplices_end,
1574  bool is_flag_complex = false) {
1575  // TODO(DS): use add_simplex instead! should be more efficient and more elegant :)
1576  typedef typename Complex::Simplex Simplex;
1577  std::vector<Simplex> simplices;
1578  for (auto top_face = simplices_begin; top_face != simplices_end; ++top_face) {
1579  auto subfaces_topface = subfaces(*top_face);
1580  simplices.insert(simplices.end(), subfaces_topface.begin(), subfaces_topface.end());
1581  }
1582  return Complex(simplices.begin(), simplices.end(), is_flag_complex);
1583 }
1584 
1585 } // namespace skeleton_blocker
1586 
1587 namespace skbl = skeleton_blocker;
1588 
1589 } // namespace Gudhi
1590 
1591 #include "Skeleton_blocker_simplifiable_complex.h"
1592 
1593 #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:529
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:596
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:1412
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:1480
Simplicial subcomplex of a complex represented by a skeleton/blockers pair.
Definition: Skeleton_blocker_link_superior.h:20
Abstract simplex used in Skeleton blockers data-structure.
Definition: Skeleton_blocker_simplex.h:38
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:432
Iterator through the blockers of a vertex.
Definition: Skeleton_blockers_blockers_iterators.h:79
bool contains_edge(Vertex_handle a, Vertex_handle b) const
Definition: Skeleton_blocker_complex.h:638
Vertex_handle second_vertex(Edge_handle edge_handle) const
returns the first vertex of an edge
Definition: Skeleton_blocker_complex.h:520
Simplex * Blocker_handle
Handle to a blocker of the complex.
Definition: Skeleton_blocker_complex.h:89
void add_vertex(T v)
Definition: Skeleton_blocker_simplex.h:110
bool contains_blocker(const Blocker_handle s) const
Definition: Skeleton_blocker_complex.h:780
Graph_vertex & operator[](Vertex_handle address)
Return the vertex node associated to local Vertex_handle.
Definition: Skeleton_blocker_complex.h:352
virtual void clear()
Definition: Skeleton_blocker_complex.h:311
int dimension() const
Definition: Skeleton_blocker_simplex.h:197
int degree(Vertex_handle local) const
return the graph degree of a vertex.
Definition: Skeleton_blocker_complex.h:468
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:484
SkeletonBlockerDS::Vertex_handle Vertex_handle
The type of an handle to a vertex of the complex.
Definition: Skeleton_blocker_complex.h:77
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:1334
bool contains_vertices(const Simplex &sigma) const
Definition: Skeleton_blocker_complex.h:421
void difference(const Skeleton_blocker_simplex &a)
Definition: Skeleton_blocker_simplex.h:139
void remove_vertex(T v)
Definition: Skeleton_blocker_simplex.h:117
Complex_simplex_range complex_simplex_range() const
Returns a Complex_simplex_range over all the simplices of the complex.
Definition: Skeleton_blocker_complex.h:1431
void contract_edge(Edge_handle edge)
Definition: Skeleton_blocker_complex.h:1246
Edge_handle add_edge(Vertex_handle a, Vertex_handle b)
Adds an edge between vertices a and b.
Definition: Skeleton_blocker_complex.h:541
bool contains_blocker(const Simplex &s) const
Definition: Skeleton_blocker_complex.h:796
Skeleton_blocker_simplex< Vertex_handle > Simplex
A ordered set of integers that represents a simplex.
Definition: Skeleton_blocker_complex.h:83
void remove_star(Vertex_handle v)
Definition: Skeleton_blocker_simplifiable_complex.h:121
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:171
void set_visitor(Visitor *other_visitor)
allows to change the visitor.
Definition: Skeleton_blocker_complex.h:327
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:1360
Iterator on the vertices of a simplicial complex.
Definition: Skeleton_blockers_vertices_iterators.h:28
Iterator through the blockers of a vertex.
Definition: Skeleton_blockers_blockers_iterators.h:27
Definition: SimplicialComplexForAlpha.h:14
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:153
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:93
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:1374
Complex_edge_range edge_range() const
Returns a Complex_edge_range over all edges of the simplicial complex.
Definition: Skeleton_blocker_complex.h:1318
Root_vertex_handle and Vertex_handle are similar to global and local vertex descriptor used in boost ...
Definition: SkeletonBlockerDS.h:47
bool contains_edges(const Simplex &sigma) const
Definition: Skeleton_blocker_complex.h:647
Complex_blocker_range blocker_range()
Returns a range of the blockers of the complex.
Definition: Skeleton_blocker_complex.h:1510
Iterator on the edges of a simplicial complex.
Definition: Skeleton_blockers_edges_iterators.h:85
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:669
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:458
bool contains(const Skeleton_blocker_simplex &a) const
Definition: Skeleton_blocker_simplex.h:228
Root_vertex_handle get_id(Vertex_handle local) const
Definition: Skeleton_blocker_complex.h:443
void add_simplex(const Simplex &sigma)
add a simplex and all its faces.
Definition: Skeleton_blocker_simplifiable_complex.h:197
Iterator over the triangles of the simplicial complex.
Definition: Skeleton_blockers_triangles_iterators.h:102
void remove_edge(Edge_handle edge)
Removes edge and its cofaces from the simplicial complex.
Definition: Skeleton_blocker_complex.h:613
The type of edges that are stored the boost graph. An Edge must be Default Constructible and Equality...
Definition: SkeletonBlockerDS.h:91
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:1471
SkeletonBlockerDS::Graph_edge Graph_edge
The type of stored edge node, specified by the template SkeletonBlockerDS.
Definition: Skeleton_blocker_complex.h:70
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:1395
Graph_edge & operator[](Edge_handle edge_handle)
returns the stored node associated to an edge
Definition: Skeleton_blocker_complex.h:497
virtual bool contains(const Simplex &s) const
returns true iff the simplex s belongs to the simplicial complex.
Definition: Skeleton_blocker_complex.h:952
Definition: Skeleton_blockers_simplices_iterators.h:302
Definition: Skeleton_blockers_simplices_iterators.h:38
void intersection(const Skeleton_blocker_simplex &a)
Definition: Skeleton_blocker_simplex.h:124
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:919
Vertex_handle add_vertex()
Adds a vertex to the simplicial complex and returns its Vertex_handle.
Definition: Skeleton_blocker_complex.h:372
Const_complex_blocker_range const_blocker_range() const
Returns a range of the blockers of the complex.
Definition: Skeleton_blocker_complex.h:1519
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:1298
Iterator over the triangles that are adjacent to a vertex of the simplicial complex.
Definition: Skeleton_blockers_triangles_iterators.h:27
bool is_cone() const
Test if the complex is a cone.
Definition: Skeleton_blocker_complex.h:1040
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:623
void remove_vertex(Vertex_handle address)
Remove a vertex from the simplicial complex.
Definition: Skeleton_blocker_complex.h:390
const Graph_edge & operator[](Edge_handle edge_handle) const
returns the stored node associated to an edge
Definition: Skeleton_blocker_complex.h:504
Link_complex link(Vertex_handle v) const
Definition: Skeleton_blocker_complex.h:893
Vertex_handle first_vertex(Edge_handle edge_handle) const
returns the first vertex of an edge
Definition: Skeleton_blocker_complex.h:512
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:940
boost::graph_traits< Graph >::edge_descriptor Edge_handle
Handle to an edge of the complex.
Definition: Skeleton_blocker_complex.h:114
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:742
Complex_vertex_range vertex_range() const
Returns a Complex_vertex_range over all vertices of the complex.
Definition: Skeleton_blocker_complex.h:1284
void add_edge(const Simplex &s)
Adds all edges of s in the complex.
Definition: Skeleton_blocker_complex.h:554
virtual ~Skeleton_blocker_complex()
Definition: Skeleton_blocker_complex.h:302
Link_complex link(const Simplex &simplex) const
Definition: Skeleton_blocker_complex.h:907
bool is_popable_blocker(Blocker_handle sigma) const
Definition: Skeleton_blocker_simplifiable_complex.h:33
Interface for a visitor of a simplicial complex.
Definition: Skeleton_blocker_complex_visitor.h:26
bool operator==(const Skeleton_blocker_complex &other) const
Definition: Skeleton_blocker_complex.h:278
The type of vertices that are stored the boost graph. A Vertex must be Default Constructible and Equa...
Definition: SkeletonBlockerDS.h:67
int num_connected_components() const
returns the number of connected components in the graph of the 1-skeleton.
Definition: Skeleton_blocker_complex.h:1029
const Graph_vertex & operator[](Vertex_handle address) const
Return the vertex node associated to local Vertex_handle.
Definition: Skeleton_blocker_complex.h:362
void delete_blocker(Blocker_handle sigma)
Definition: Skeleton_blocker_complex.h:770
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:1164
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:342
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:566
SkeletonBlockerDS::Graph_vertex Graph_vertex
The type of stored vertex node, specified by the template SkeletonBlockerDS.
Definition: Skeleton_blocker_complex.h:65
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:1400
void add_edge_without_blockers(Simplex s)
Adds all edges of s in the complex without adding blockers.
Definition: Skeleton_blocker_complex.h:585
void remove_blocker(const Blocker_handle sigma)
Removes the simplex from the set of blockers.
Definition: Skeleton_blocker_complex.h:732
Link_complex link(Edge_handle edge) const
Definition: Skeleton_blocker_complex.h:900
Abstract Simplicial Complex represented with a skeleton/blockers pair.
Definition: Skeleton_blocker_complex.h:51
void remove_popable_blockers()
Definition: Skeleton_blocker_simplifiable_complex.h:45
bool link_condition(Edge_handle e, bool ignore_popable_blockers=false) const
Definition: Skeleton_blocker_complex.h:1201
bool link_condition(Vertex_handle a, Vertex_handle b, bool ignore_popable_blockers=false) const
Definition: Skeleton_blocker_complex.h:1184
T first_vertex() const
Definition: Skeleton_blocker_simplex.h:210
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:1417
GUDHI  Version 3.4.1  - C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding.  - Copyright : MIT Generated on Fri Jan 22 2021 09:41:15 for GUDHI by Doxygen 1.8.13