Loading [MathJax]/jax/output/HTML-CSS/config.js
All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Modules Pages
Simplex_tree.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): Clément Maria
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 SIMPLEX_TREE_H_
24 #define SIMPLEX_TREE_H_
25 
26 #include <gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h>
27 #include <gudhi/Simplex_tree/Simplex_tree_siblings.h>
28 #include <gudhi/Simplex_tree/Simplex_tree_iterators.h>
29 #include <gudhi/Simplex_tree/indexing_tag.h>
30 
31 #include <gudhi/reader_utils.h>
32 #include <gudhi/graph_simplicial_complex.h>
33 #include <gudhi/Debug_utils.h>
34 
35 #include <boost/container/flat_map.hpp>
36 #include <boost/iterator/transform_iterator.hpp>
37 #include <boost/graph/adjacency_list.hpp>
38 #include <boost/range/adaptor/reversed.hpp>
39 
40 #ifdef GUDHI_USE_TBB
41 #include <tbb/parallel_sort.h>
42 #endif
43 
44 #include <utility>
45 #include <vector>
46 #include <functional> // for greater<>
47 #include <stdexcept>
48 #include <limits> // Inf
49 #include <initializer_list>
50 #include <algorithm> // for std::max
51 #include <cstdint> // for std::uint32_t
52 #include <iterator> // for std::distance
53 
54 namespace Gudhi {
55 
56 struct Simplex_tree_options_full_featured;
57 
71 template<typename SimplexTreeOptions = Simplex_tree_options_full_featured>
72 class Simplex_tree {
73  public:
75  typedef typename Options::Indexing_tag Indexing_tag;
88 
89  /* Type of node in the simplex tree. */
90  typedef Simplex_tree_node_explicit_storage<Simplex_tree> Node;
91  /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */
92  // Note: this wastes space when Vertex_handle is 32 bits and Node is aligned on 64 bits. It would be better to use a
93  // flat_set (with our own comparator) where we can control the layout of the struct (put Vertex_handle and
94  // Simplex_key next to each other).
95  typedef typename boost::container::flat_map<Vertex_handle, Node> Dictionary;
96 
97  /* \brief Set of nodes sharing a same parent in the simplex tree. */
98  /* \brief Set of nodes sharing a same parent in the simplex tree. */
99  typedef Simplex_tree_siblings<Simplex_tree, Dictionary> Siblings;
100 
101  struct Key_simplex_base_real {
102  Key_simplex_base_real() : key_(-1) {}
103  void assign_key(Simplex_key k) { key_ = k; }
104  Simplex_key key() const { return key_; }
105  private:
106  Simplex_key key_;
107  };
108  struct Key_simplex_base_dummy {
109  Key_simplex_base_dummy() {}
110  // Undefined so it will not link
111  void assign_key(Simplex_key);
112  Simplex_key key() const;
113  };
114  typedef typename std::conditional<Options::store_key, Key_simplex_base_real, Key_simplex_base_dummy>::type
115  Key_simplex_base;
116 
117  struct Filtration_simplex_base_real {
118  Filtration_simplex_base_real() : filt_(0) {}
119  void assign_filtration(Filtration_value f) { filt_ = f; }
120  Filtration_value filtration() const { return filt_; }
121  private:
122  Filtration_value filt_;
123  };
124  struct Filtration_simplex_base_dummy {
125  Filtration_simplex_base_dummy() {}
126  void assign_filtration(Filtration_value GUDHI_CHECK_code(f)) { GUDHI_CHECK(f == 0, "filtration value specified for a complex that does not store them"); }
127  Filtration_value filtration() const { return 0; }
128  };
129  typedef typename std::conditional<Options::store_filtration, Filtration_simplex_base_real,
130  Filtration_simplex_base_dummy>::type Filtration_simplex_base;
131 
132  public:
135  typedef typename Dictionary::iterator Simplex_handle;
136 
137  private:
138  typedef typename Dictionary::iterator Dictionary_it;
139  typedef typename Dictionary_it::value_type Dit_value_t;
140 
141  struct return_first {
142  Vertex_handle operator()(const Dit_value_t& p_sh) const {
143  return p_sh.first;
144  }
145  };
146 
147  public:
159  typedef boost::transform_iterator<return_first, Dictionary_it> Complex_vertex_iterator;
161  typedef boost::iterator_range<Complex_vertex_iterator> Complex_vertex_range;
165  typedef Simplex_tree_simplex_vertex_iterator<Simplex_tree> Simplex_vertex_iterator;
167  typedef boost::iterator_range<Simplex_vertex_iterator> Simplex_vertex_range;
169  typedef std::vector<Simplex_handle> Cofaces_simplex_range;
173  typedef Simplex_tree_boundary_simplex_iterator<Simplex_tree> Boundary_simplex_iterator;
175  typedef boost::iterator_range<Boundary_simplex_iterator> Boundary_simplex_range;
179  typedef Simplex_tree_complex_simplex_iterator<Simplex_tree> Complex_simplex_iterator;
181  typedef boost::iterator_range<Complex_simplex_iterator> Complex_simplex_range;
186  typedef Simplex_tree_skeleton_simplex_iterator<Simplex_tree> Skeleton_simplex_iterator;
189  typedef boost::iterator_range<Skeleton_simplex_iterator> Skeleton_simplex_range;
191  typedef std::vector<Simplex_handle> Filtration_simplex_range;
195  typedef typename Filtration_simplex_range::const_iterator Filtration_simplex_iterator;
196 
197  /* @} */ // end name range and iterator types
203  Complex_vertex_range complex_vertex_range() {
204  return Complex_vertex_range(
205  boost::make_transform_iterator(root_.members_.begin(), return_first()),
206  boost::make_transform_iterator(root_.members_.end(), return_first()));
207  }
208 
214  Complex_simplex_range complex_simplex_range() {
217  }
218 
228  Skeleton_simplex_range skeleton_simplex_range(int dim) {
231  }
232 
248  Filtration_simplex_range const& filtration_simplex_range(Indexing_tag = Indexing_tag()) {
249  if (filtration_vect_.empty()) {
251  }
252  return filtration_vect_;
253  }
254 
261  Simplex_vertex_range simplex_vertex_range(Simplex_handle sh) {
262  assert(sh != null_simplex()); // Empty simplex
265  }
266 
281  template<class SimplexHandle>
282  Boundary_simplex_range boundary_simplex_range(SimplexHandle sh) {
285  }
286  // end range and iterator methods
293  : null_vertex_(-1),
294  root_(nullptr, null_vertex_),
295  filtration_vect_(),
296  dimension_(-1) { }
297 
299  Simplex_tree(const Simplex_tree& simplex_source)
300  : null_vertex_(simplex_source.null_vertex_),
301  root_(nullptr, null_vertex_ , simplex_source.root_.members_),
302  filtration_vect_(),
303  dimension_(simplex_source.dimension_) {
304  auto root_source = simplex_source.root_;
305  rec_copy(&root_, &root_source);
306  }
307 
309  void rec_copy(Siblings *sib, Siblings *sib_source) {
310  for (auto sh = sib->members().begin(), sh_source = sib_source->members().begin();
311  sh != sib->members().end(); ++sh, ++sh_source) {
312  if (has_children(sh_source)) {
313  Siblings * newsib = new Siblings(sib, sh_source->first);
314  newsib->members_.reserve(sh_source->second.children()->members().size());
315  for (auto & child : sh_source->second.children()->members())
316  newsib->members_.emplace_hint(newsib->members_.end(), child.first, Node(newsib, child.second.filtration()));
317  rec_copy(newsib, sh_source->second.children());
318  sh->second.assign_children(newsib);
319  }
320  }
321  }
322 
325  : null_vertex_(std::move(old.null_vertex_)),
326  root_(std::move(old.root_)),
327  filtration_vect_(std::move(old.filtration_vect_)),
328  dimension_(std::move(old.dimension_)) {
329  old.dimension_ = -1;
330  old.root_ = Siblings(nullptr, null_vertex_);
331  }
332 
335  for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) {
336  if (has_children(sh)) {
337  rec_delete(sh->second.children());
338  }
339  }
340  } // end constructor/destructor
342  private:
343  // Recursive deletion
344  void rec_delete(Siblings * sib) {
345  for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
346  if (has_children(sh)) {
347  rec_delete(sh->second.children());
348  }
349  }
350  delete sib;
351  }
352 
353  public:
356  if ((null_vertex_ != st2.null_vertex_) ||
357  (dimension_ != st2.dimension_))
358  return false;
359  return rec_equal(&root_, &st2.root_);
360  }
361 
364  return (!(*this == st2));
365  }
366 
367  private:
369  bool rec_equal(Siblings* s1, Siblings* s2) {
370  if (s1->members().size() != s2->members().size())
371  return false;
372  for (auto sh1 = s1->members().begin(), sh2 = s2->members().begin();
373  (sh1 != s1->members().end() && sh2 != s2->members().end()); ++sh1, ++sh2) {
374  if (sh1->first != sh2->first || sh1->second.filtration() != sh2->second.filtration())
375  return false;
376  if (has_children(sh1) != has_children(sh2))
377  return false;
378  // Recursivity on children only if both have children
379  else if (has_children(sh1))
380  if (!rec_equal(sh1->second.children(), sh2->second.children()))
381  return false;
382  }
383  return true;
384  }
385 
386  public:
392  static Simplex_key key(Simplex_handle sh) {
393  return sh->second.key();
394  }
395 
401  Simplex_handle simplex(Simplex_key idx) const {
402  return filtration_vect_[idx];
403  }
404 
410  static Filtration_value filtration(Simplex_handle sh) {
411  if (sh != null_simplex()) {
412  return sh->second.filtration();
413  } else {
414  return std::numeric_limits<Filtration_value>::infinity();
415  }
416  }
417 
421  void assign_filtration(Simplex_handle sh, Filtration_value fv) {
422  GUDHI_CHECK(sh != null_simplex(),
423  std::invalid_argument("Simplex_tree::assign_filtration - cannot assign filtration on null_simplex"));
424  sh->second.assign_filtration(fv);
425  }
426 
431  static Simplex_handle null_simplex() {
432  return Dictionary_it(nullptr);
433  }
434 
437  static Simplex_key null_key() {
438  return -1;
439  }
440 
443  Vertex_handle null_vertex() const {
444  return null_vertex_;
445  }
446 
448  size_t num_vertices() const {
449  return root_.members_.size();
450  }
451 
452  public:
454  size_t num_simplices() {
455  return num_simplices(&root_);
456  }
457 
458  private:
460  size_t num_simplices(Siblings * sib) {
461  auto sib_begin = sib->members().begin();
462  auto sib_end = sib->members().end();
463  size_t simplices_number = sib_end - sib_begin;
464  for (auto sh = sib_begin; sh != sib_end; ++sh) {
465  if (has_children(sh)) {
466  simplices_number += num_simplices(sh->second.children());
467  }
468  }
469  return simplices_number;
470  }
471 
472  public:
476  int dimension(Simplex_handle sh) {
477  Siblings * curr_sib = self_siblings(sh);
478  int dim = 0;
479  while (curr_sib != nullptr) {
480  ++dim;
481  curr_sib = curr_sib->oncles();
482  }
483  return dim - 1;
484  }
485 
487  int upper_bound_dimension() const {
488  return dimension_;
489  }
490 
495  int dimension() {
496  if (dimension_to_be_lowered_)
497  lower_upper_bound_dimension();
498  return dimension_;
499  }
500 
503  template<class SimplexHandle>
504  bool has_children(SimplexHandle sh) const {
505  // Here we rely on the root using null_vertex(), which cannot match any real vertex.
506  return (sh->second.children()->parent() == sh->first);
507  }
508 
516  template<class InputVertexRange = std::initializer_list<Vertex_handle>>
517  Simplex_handle find(const InputVertexRange & s) {
518  auto first = std::begin(s);
519  auto last = std::end(s);
520 
521  if (first == last)
522  return null_simplex(); // ----->>
523 
524  // Copy before sorting
525  std::vector<Vertex_handle> copy(first, last);
526  std::sort(std::begin(copy), std::end(copy));
527  return find_simplex(copy);
528  }
529 
530  private:
532  Simplex_handle find_simplex(const std::vector<Vertex_handle> & simplex) {
533  Siblings * tmp_sib = &root_;
534  Dictionary_it tmp_dit;
535  auto vi = simplex.begin();
537  // Equivalent to the first iteration of the normal loop
538  GUDHI_CHECK(contiguous_vertices(), "non-contiguous vertices");
539  Vertex_handle v = *vi++;
540  if(v < 0 || v >= static_cast<Vertex_handle>(root_.members_.size()))
541  return null_simplex();
542  tmp_dit = root_.members_.begin() + v;
543  if (vi == simplex.end())
544  return tmp_dit;
545  if (!has_children(tmp_dit))
546  return null_simplex();
547  tmp_sib = tmp_dit->second.children();
548  }
549  for (;;) {
550  tmp_dit = tmp_sib->members_.find(*vi++);
551  if (tmp_dit == tmp_sib->members_.end())
552  return null_simplex();
553  if (vi == simplex.end())
554  return tmp_dit;
555  if (!has_children(tmp_dit))
556  return null_simplex();
557  tmp_sib = tmp_dit->second.children();
558  }
559  }
560 
563  Simplex_handle find_vertex(Vertex_handle v) {
565  assert(contiguous_vertices());
566  return root_.members_.begin() + v;
567  } else {
568  return root_.members_.find(v);
569  }
570  }
571 
572  public:
574  bool contiguous_vertices() const {
575  if (root_.members_.empty()) return true;
576  if (root_.members_.begin()->first != 0) return false;
577  if (std::prev(root_.members_.end())->first != static_cast<Vertex_handle>(root_.members_.size() - 1)) return false;
578  return true;
579  }
580 
581  private:
596  std::pair<Simplex_handle, bool> insert_vertex_vector(const std::vector<Vertex_handle>& simplex,
597  Filtration_value filtration) {
598  Siblings * curr_sib = &root_;
599  std::pair<Simplex_handle, bool> res_insert;
600  auto vi = simplex.begin();
601  for (; vi != simplex.end() - 1; ++vi) {
602  GUDHI_CHECK(*vi != null_vertex(), "cannot use the dummy null_vertex() as a real vertex");
603  res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib, filtration));
604  if (!(has_children(res_insert.first))) {
605  res_insert.first->second.assign_children(new Siblings(curr_sib, *vi));
606  }
607  curr_sib = res_insert.first->second.children();
608  }
609  GUDHI_CHECK(*vi != null_vertex(), "cannot use the dummy null_vertex() as a real vertex");
610  res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib, filtration));
611  if (!res_insert.second) {
612  // if already in the complex
613  if (res_insert.first->second.filtration() > filtration) {
614  // if filtration value modified
615  res_insert.first->second.assign_filtration(filtration);
616  return res_insert;
617  }
618  // if filtration value unchanged
619  return std::pair<Simplex_handle, bool>(null_simplex(), false);
620  }
621  // otherwise the insertion has succeeded - size is a size_type
622  if (static_cast<int>(simplex.size()) - 1 > dimension_) {
623  // Update dimension if needed
624  dimension_ = static_cast<int>(simplex.size()) - 1;
625  }
626  return res_insert;
627  }
628 
629  public:
653  template<class InputVertexRange = std::initializer_list<Vertex_handle>>
654  std::pair<Simplex_handle, bool> insert_simplex(const InputVertexRange & simplex,
655  Filtration_value filtration = 0) {
656  auto first = std::begin(simplex);
657  auto last = std::end(simplex);
658 
659  if (first == last)
660  return std::pair<Simplex_handle, bool>(null_simplex(), true); // ----->>
661 
662  // Copy before sorting
663  std::vector<Vertex_handle> copy(first, last);
664  std::sort(std::begin(copy), std::end(copy));
665  return insert_vertex_vector(copy, filtration);
666  }
667 
682  template<class InputVertexRange = std::initializer_list<Vertex_handle>>
683  std::pair<Simplex_handle, bool> insert_simplex_and_subfaces(const InputVertexRange& Nsimplex,
684  Filtration_value filtration = 0) {
685  auto first = std::begin(Nsimplex);
686  auto last = std::end(Nsimplex);
687 
688  if (first == last)
689  return { null_simplex(), true }; // ----->>
690 
691  // Copy before sorting
692  // Thread local is not available on XCode version < V.8 - It will slow down computation
693 #ifdef GUDHI_CAN_USE_CXX11_THREAD_LOCAL
694  thread_local
695 #endif // GUDHI_CAN_USE_CXX11_THREAD_LOCAL
696  std::vector<Vertex_handle> copy;
697  copy.clear();
698  copy.insert(copy.end(), first, last);
699  std::sort(std::begin(copy), std::end(copy));
700  GUDHI_CHECK_code(
701  for (Vertex_handle v : copy)
702  GUDHI_CHECK(v != null_vertex(), "cannot use the dummy null_vertex() as a real vertex");
703  )
704 
705  return insert_simplex_and_subfaces_sorted(copy, filtration);
706  }
707 
708  private:
710  template<class ForwardVertexRange = std::initializer_list<Vertex_handle>>
711  std::pair<Simplex_handle, bool> insert_simplex_and_subfaces_sorted(const ForwardVertexRange& Nsimplex, Filtration_value filt = 0) {
712  auto first = std::begin(Nsimplex);
713  auto last = std::end(Nsimplex);
714  if (first == last)
715  return { null_simplex(), true }; // FIXME: false would make more sense to me.
716  GUDHI_CHECK(std::is_sorted(first, last), "simplex vertices listed in unsorted order");
717  // Update dimension if needed. We could wait to see if the insertion succeeds, but I doubt there is much to gain.
718  dimension_ = (std::max)(dimension_, static_cast<int>(std::distance(first, last)) - 1);
719  return rec_insert_simplex_and_subfaces_sorted(root(), first, last, filt);
720  }
721  // To insert {1,2,3,4}, we insert {2,3,4} twice, once at the root, and once below 1.
722  template<class ForwardVertexIterator>
723  std::pair<Simplex_handle, bool> rec_insert_simplex_and_subfaces_sorted(Siblings* sib, ForwardVertexIterator first, ForwardVertexIterator last, Filtration_value filt) {
724  // An alternative strategy would be:
725  // - try to find the complete simplex, if found (and low filtration) exit
726  // - insert all the vertices at once in sib
727  // - loop over those (new or not) simplices, with a recursive call(++first, last)
728  Vertex_handle vertex_one = *first;
729  auto&& dict = sib->members();
730  auto insertion_result = dict.emplace(vertex_one, Node(sib, filt));
731  Simplex_handle simplex_one = insertion_result.first;
732  bool one_is_new = insertion_result.second;
733  if (!one_is_new) {
734  if (filtration(simplex_one) > filt) {
735  assign_filtration(simplex_one, filt);
736  } else {
737  // FIXME: this interface makes no sense, and it doesn't seem to be tested.
738  insertion_result.first = null_simplex();
739  }
740  }
741  if (++first == last) return insertion_result;
742  if (!has_children(simplex_one))
743  // TODO: have special code here, we know we are building the whole subtree from scratch.
744  simplex_one->second.assign_children(new Siblings(sib, vertex_one));
745  auto res = rec_insert_simplex_and_subfaces_sorted(simplex_one->second.children(), first, last, filt);
746  // No need to continue if the full simplex was already there with a low enough filtration value.
747  if (res.first != null_simplex()) rec_insert_simplex_and_subfaces_sorted(sib, first, last, filt);
748  return res;
749  }
750 
751  public:
754  void assign_key(Simplex_handle sh, Simplex_key key) {
755  sh->second.assign_key(key);
756  }
757 
761  std::pair<Simplex_handle, Simplex_handle> endpoints(Simplex_handle sh) {
762  assert(dimension(sh) == 1);
763  return { find_vertex(sh->first), find_vertex(self_siblings(sh)->parent()) };
764  }
765 
767  template<class SimplexHandle>
768  Siblings* self_siblings(SimplexHandle sh) {
769  if (sh->second.children()->parent() == sh->first)
770  return sh->second.children()->oncles();
771  else
772  return sh->second.children();
773  }
774 
775  public:
777  Siblings * root() {
778  return &root_;
779  }
780 
786  dimension_to_be_lowered_ = false;
787  dimension_ = dimension;
788  }
789 
790  public:
801  filtration_vect_.clear();
802  filtration_vect_.reserve(num_simplices());
803  for (Simplex_handle sh : complex_simplex_range())
804  filtration_vect_.push_back(sh);
805 
806  /* We use stable_sort here because with libstdc++ it is faster than sort.
807  * is_before_in_filtration is now a total order, but we used to call
808  * stable_sort for the following heuristic:
809  * The use of a depth-first traversal of the simplex tree, provided by
810  * complex_simplex_range(), combined with a stable sort is meant to
811  * optimize the order of simplices with same filtration value. The
812  * heuristic consists in inserting the cofaces of a simplex as soon as
813  * possible.
814  */
815 #ifdef GUDHI_USE_TBB
816  tbb::parallel_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration(this));
817 #else
818  std::stable_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration(this));
819 #endif
820  }
821 
822  private:
835  void rec_coface(std::vector<Vertex_handle> &vertices, Siblings *curr_sib, int curr_nbVertices,
836  std::vector<Simplex_handle>& cofaces, bool star, int nbVertices) {
837  if (!(star || curr_nbVertices <= nbVertices)) // dimension of actual simplex <= nbVertices
838  return;
839  for (Simplex_handle simplex = curr_sib->members().begin(); simplex != curr_sib->members().end(); ++simplex) {
840  if (vertices.empty()) {
841  // If we reached the end of the vertices, and the simplex has more vertices than the given simplex
842  // => we found a coface
843 
844  // Add a coface if we wan't the star or if the number of vertices of the current simplex matches with nbVertices
845  bool addCoface = (star || curr_nbVertices == nbVertices);
846  if (addCoface)
847  cofaces.push_back(simplex);
848  if ((!addCoface || star) && has_children(simplex)) // Rec call
849  rec_coface(vertices, simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
850  } else {
851  if (simplex->first == vertices.back()) {
852  // If curr_sib matches with the top vertex
853  bool equalDim = (star || curr_nbVertices == nbVertices); // dimension of actual simplex == nbVertices
854  bool addCoface = vertices.size() == 1 && equalDim;
855  if (addCoface)
856  cofaces.push_back(simplex);
857  if ((!addCoface || star) && has_children(simplex)) {
858  // Rec call
859  Vertex_handle tmp = vertices.back();
860  vertices.pop_back();
861  rec_coface(vertices, simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
862  vertices.push_back(tmp);
863  }
864  } else if (simplex->first > vertices.back()) {
865  return;
866  } else {
867  // (simplex->first < vertices.back()
868  if (has_children(simplex))
869  rec_coface(vertices, simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
870  }
871  }
872  }
873  }
874 
875  public:
881  Cofaces_simplex_range star_simplex_range(const Simplex_handle simplex) {
882  return cofaces_simplex_range(simplex, 0);
883  }
884 
892  Cofaces_simplex_range cofaces_simplex_range(const Simplex_handle simplex, int codimension) {
893  Cofaces_simplex_range cofaces;
894  // codimension must be positive or null integer
895  assert(codimension >= 0);
896  Simplex_vertex_range rg = simplex_vertex_range(simplex);
897  std::vector<Vertex_handle> copy(rg.begin(), rg.end());
898  if (codimension + static_cast<int>(copy.size()) > dimension_ + 1 ||
899  (codimension == 0 && static_cast<int>(copy.size()) > dimension_)) // n+codimension greater than dimension_
900  return cofaces;
901  // must be sorted in decreasing order
902  assert(std::is_sorted(copy.begin(), copy.end(), std::greater<Vertex_handle>()));
903  bool star = codimension == 0;
904  rec_coface(copy, &root_, 1, cofaces, star, codimension + static_cast<int>(copy.size()));
905  return cofaces;
906  }
907 
908  private:
916  bool reverse_lexicographic_order(Simplex_handle sh1, Simplex_handle sh2) {
917  Simplex_vertex_range rg1 = simplex_vertex_range(sh1);
918  Simplex_vertex_range rg2 = simplex_vertex_range(sh2);
919  Simplex_vertex_iterator it1 = rg1.begin();
920  Simplex_vertex_iterator it2 = rg2.begin();
921  while (it1 != rg1.end() && it2 != rg2.end()) {
922  if (*it1 == *it2) {
923  ++it1;
924  ++it2;
925  } else {
926  return *it1 < *it2;
927  }
928  }
929  return ((it1 == rg1.end()) && (it2 != rg2.end()));
930  }
931 
938  struct is_before_in_filtration {
939  explicit is_before_in_filtration(Simplex_tree * st)
940  : st_(st) { }
941 
942  bool operator()(const Simplex_handle sh1, const Simplex_handle sh2) const {
943  // Not using st_->filtration(sh1) because it uselessly tests for null_simplex.
944  if (sh1->second.filtration() != sh2->second.filtration()) {
945  return sh1->second.filtration() < sh2->second.filtration();
946  }
947  // is sh1 a proper subface of sh2
948  return st_->reverse_lexicographic_order(sh1, sh2);
949  }
950 
951  Simplex_tree * st_;
952  };
953 
954  public:
977  template<class OneSkeletonGraph>
978  void insert_graph(const OneSkeletonGraph& skel_graph) {
979  // the simplex tree must be empty
980  assert(num_simplices() == 0);
981 
982  if (boost::num_vertices(skel_graph) == 0) {
983  return;
984  }
985  if (num_edges(skel_graph) == 0) {
986  dimension_ = 0;
987  } else {
988  dimension_ = 1;
989  }
990 
991  root_.members_.reserve(boost::num_vertices(skel_graph));
992 
993  typename boost::graph_traits<OneSkeletonGraph>::vertex_iterator v_it,
994  v_it_end;
995  for (std::tie(v_it, v_it_end) = boost::vertices(skel_graph); v_it != v_it_end;
996  ++v_it) {
997  root_.members_.emplace_hint(
998  root_.members_.end(), *v_it,
999  Node(&root_, boost::get(vertex_filtration_t(), skel_graph, *v_it)));
1000  }
1001  typename boost::graph_traits<OneSkeletonGraph>::edge_iterator e_it,
1002  e_it_end;
1003  for (std::tie(e_it, e_it_end) = boost::edges(skel_graph); e_it != e_it_end;
1004  ++e_it) {
1005  auto u = source(*e_it, skel_graph);
1006  auto v = target(*e_it, skel_graph);
1007  if (u == v) throw "Self-loops are not simplicial";
1008  // We cannot skip edges with the wrong orientation and expect them to
1009  // come a second time with the right orientation, that does not always
1010  // happen in practice. emplace() should be a NOP when an element with the
1011  // same key is already there, so seeing the same edge multiple times is
1012  // ok.
1013  // Should we actually forbid multiple edges? That would be consistent
1014  // with rejecting self-loops.
1015  if (v < u) std::swap(u, v);
1016  auto sh = find_vertex(u);
1017  if (!has_children(sh)) {
1018  sh->second.assign_children(new Siblings(&root_, sh->first));
1019  }
1020 
1021  sh->second.children()->members().emplace(v,
1022  Node(sh->second.children(), boost::get(edge_filtration_t(), skel_graph, *e_it)));
1023  }
1024  }
1025 
1037  void expansion(int max_dim) {
1038  dimension_ = max_dim;
1039  for (Dictionary_it root_it = root_.members_.begin();
1040  root_it != root_.members_.end(); ++root_it) {
1041  if (has_children(root_it)) {
1042  siblings_expansion(root_it->second.children(), max_dim - 1);
1043  }
1044  }
1045  dimension_ = max_dim - dimension_;
1046  }
1047 
1048  private:
1050  void siblings_expansion(Siblings * siblings, // must contain elements
1051  int k) {
1052  if (dimension_ > k) {
1053  dimension_ = k;
1054  }
1055  if (k == 0)
1056  return;
1057  Dictionary_it next = siblings->members().begin();
1058  ++next;
1059 
1060 #ifdef GUDHI_CAN_USE_CXX11_THREAD_LOCAL
1061  thread_local
1062 #endif // GUDHI_CAN_USE_CXX11_THREAD_LOCAL
1063  std::vector<std::pair<Vertex_handle, Node> > inter;
1064  for (Dictionary_it s_h = siblings->members().begin();
1065  s_h != siblings->members().end(); ++s_h, ++next) {
1066  Simplex_handle root_sh = find_vertex(s_h->first);
1067  if (has_children(root_sh)) {
1068  intersection(
1069  inter, // output intersection
1070  next, // begin
1071  siblings->members().end(), // end
1072  root_sh->second.children()->members().begin(),
1073  root_sh->second.children()->members().end(),
1074  s_h->second.filtration());
1075  if (inter.size() != 0) {
1076  Siblings * new_sib = new Siblings(siblings, // oncles
1077  s_h->first, // parent
1078  inter); // boost::container::ordered_unique_range_t
1079  inter.clear();
1080  s_h->second.assign_children(new_sib);
1081  siblings_expansion(new_sib, k - 1);
1082  } else {
1083  // ensure the children property
1084  s_h->second.assign_children(siblings);
1085  inter.clear();
1086  }
1087  }
1088  }
1089  }
1090 
1093  static void intersection(std::vector<std::pair<Vertex_handle, Node> >& intersection,
1094  Dictionary_it begin1, Dictionary_it end1,
1095  Dictionary_it begin2, Dictionary_it end2,
1096  Filtration_value filtration_) {
1097  if (begin1 == end1 || begin2 == end2)
1098  return; // ----->>
1099  while (true) {
1100  if (begin1->first == begin2->first) {
1101  Filtration_value filt = (std::max)({begin1->second.filtration(), begin2->second.filtration(), filtration_});
1102  intersection.emplace_back(begin1->first, Node(nullptr, filt));
1103  if (++begin1 == end1 || ++begin2 == end2)
1104  return; // ----->>
1105  } else if (begin1->first < begin2->first) {
1106  if (++begin1 == end1)
1107  return;
1108  } else /* begin1->first > begin2->first */ {
1109  if (++begin2 == end2)
1110  return; // ----->>
1111  }
1112  }
1113  }
1114 
1115  public:
1134  template< typename Blocker >
1135  void expansion_with_blockers(int max_dim, Blocker block_simplex) {
1136  // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree
1137  for (auto& simplex : boost::adaptors::reverse(root_.members())) {
1138  if (has_children(&simplex)) {
1139  siblings_expansion_with_blockers(simplex.second.children(), max_dim, max_dim - 1, block_simplex);
1140  }
1141  }
1142  }
1143 
1144  private:
1146  template< typename Blocker >
1147  void siblings_expansion_with_blockers(Siblings* siblings, int max_dim, int k, Blocker block_simplex) {
1148  if (dimension_ < max_dim - k) {
1149  dimension_ = max_dim - k;
1150  }
1151  if (k == 0)
1152  return;
1153  // No need to go deeper
1154  if (siblings->members().size() < 2)
1155  return;
1156  // Reverse loop starting before the last one for 'next' to be the last one
1157  for (auto simplex = siblings->members().rbegin() + 1; simplex != siblings->members().rend(); simplex++) {
1158  std::vector<std::pair<Vertex_handle, Node> > intersection;
1159  for(auto next = siblings->members().rbegin(); next != simplex; next++) {
1160  bool to_be_inserted = true;
1161  Filtration_value filt = simplex->second.filtration();
1162  // If all the boundaries are present, 'next' needs to be inserted
1163  for (Simplex_handle border : boundary_simplex_range(simplex)) {
1164  Simplex_handle border_child = find_child(border, next->first);
1165  if (border_child == null_simplex()) {
1166  to_be_inserted=false;
1167  break;
1168  }
1169  filt = (std::max)(filt, filtration(border_child));
1170  }
1171  if (to_be_inserted) {
1172  intersection.emplace_back(next->first, Node(nullptr, filt));
1173  }
1174  }
1175  if (intersection.size() != 0) {
1176  // Reverse the order to insert
1177  Siblings * new_sib = new Siblings(siblings, // oncles
1178  simplex->first, // parent
1179  boost::adaptors::reverse(intersection)); // boost::container::ordered_unique_range_t
1180  std::vector<Vertex_handle> blocked_new_sib_vertex_list;
1181  // As all intersections are inserted, we can call the blocker function on all new_sib members
1182  for (auto new_sib_member = new_sib->members().begin();
1183  new_sib_member != new_sib->members().end();
1184  new_sib_member++) {
1185  bool blocker_result = block_simplex(new_sib_member);
1186  // new_sib member has been blocked by the blocker function
1187  // add it to the list to be removed - do not perform it while looping on it
1188  if (blocker_result) {
1189  blocked_new_sib_vertex_list.push_back(new_sib_member->first);
1190  }
1191  }
1192  if (blocked_new_sib_vertex_list.size() == new_sib->members().size()) {
1193  // Specific case where all have to be deleted
1194  delete new_sib;
1195  // ensure the children property
1196  simplex->second.assign_children(siblings);
1197  } else {
1198  for (auto& blocked_new_sib_member : blocked_new_sib_vertex_list) {
1199  new_sib->members().erase(blocked_new_sib_member);
1200  }
1201  // ensure recursive call
1202  simplex->second.assign_children(new_sib);
1203  siblings_expansion_with_blockers(new_sib, max_dim, k - 1, block_simplex);
1204  }
1205  } else {
1206  // ensure the children property
1207  simplex->second.assign_children(siblings);
1208  }
1209  }
1210  }
1211 
1212  /* \private Returns the Simplex_handle composed of the vertex list (from the Simplex_handle), plus the given
1213  * Vertex_handle if the Vertex_handle is found in the Simplex_handle children list.
1214  * Returns null_simplex() if it does not exist
1215  */
1216  Simplex_handle find_child(Simplex_handle sh, Vertex_handle vh) const {
1217  if (!has_children(sh))
1218  return null_simplex();
1219 
1220  Simplex_handle child = sh->second.children()->find(vh);
1221  // Specific case of boost::flat_map does not find, returns boost::flat_map::end()
1222  // in simplex tree we want a null_simplex()
1223  if (child == sh->second.children()->members().end())
1224  return null_simplex();
1225 
1226  return child;
1227  }
1228 
1229  public:
1236  void print_hasse(std::ostream& os) {
1237  os << num_simplices() << " " << std::endl;
1238  for (auto sh : filtration_simplex_range()) {
1239  os << dimension(sh) << " ";
1240  for (auto b_sh : boundary_simplex_range(sh)) {
1241  os << key(b_sh) << " ";
1242  }
1243  os << filtration(sh) << " \n";
1244  }
1245  }
1246 
1247  public:
1256  bool modified = false;
1257  // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree
1258  for (auto& simplex : boost::adaptors::reverse(root_.members())) {
1259  if (has_children(&simplex)) {
1260  modified |= rec_make_filtration_non_decreasing(simplex.second.children());
1261  }
1262  }
1263  return modified;
1264  }
1265 
1266  private:
1271  bool rec_make_filtration_non_decreasing(Siblings * sib) {
1272  bool modified = false;
1273 
1274  // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree
1275  for (auto& simplex : boost::adaptors::reverse(sib->members())) {
1276  // Find the maximum filtration value in the border
1277  Boundary_simplex_range boundary = boundary_simplex_range(&simplex);
1278  Boundary_simplex_iterator max_border = std::max_element(std::begin(boundary), std::end(boundary),
1279  [](Simplex_handle sh1, Simplex_handle sh2) {
1280  return filtration(sh1) < filtration(sh2);
1281  });
1282 
1283  Filtration_value max_filt_border_value = filtration(*max_border);
1284  if (simplex.second.filtration() < max_filt_border_value) {
1285  // Store the filtration modification information
1286  modified = true;
1287  simplex.second.assign_filtration(max_filt_border_value);
1288  }
1289  if (has_children(&simplex)) {
1290  modified |= rec_make_filtration_non_decreasing(simplex.second.children());
1291  }
1292  }
1293  // Make the modified information to be traced by upper call
1294  return modified;
1295  }
1296 
1297  public:
1308  bool prune_above_filtration(Filtration_value filtration) {
1309  return rec_prune_above_filtration(root(), filtration);
1310  }
1311 
1312  private:
1313  bool rec_prune_above_filtration(Siblings* sib, Filtration_value filt) {
1314  auto&& list = sib->members();
1315  auto last = std::remove_if(list.begin(), list.end(), [=](Dit_value_t& simplex) {
1316  if (simplex.second.filtration() <= filt) return false;
1317  if (has_children(&simplex)) rec_delete(simplex.second.children());
1318  // dimension may need to be lowered
1319  dimension_to_be_lowered_ = true;
1320  return true;
1321  });
1322 
1323  bool modified = (last != list.end());
1324  if (last == list.begin() && sib != root()) {
1325  // Removing the whole siblings, parent becomes a leaf.
1326  sib->oncles()->members()[sib->parent()].assign_children(sib->oncles());
1327  delete sib;
1328  // dimension may need to be lowered
1329  dimension_to_be_lowered_ = true;
1330  return true;
1331  } else {
1332  // Keeping some elements of siblings. Remove the others, and recurse in the remaining ones.
1333  list.erase(last, list.end());
1334  for (auto&& simplex : list)
1335  if (has_children(&simplex))
1336  modified |= rec_prune_above_filtration(simplex.second.children(), filt);
1337  }
1338  return modified;
1339  }
1340 
1341  private:
1347  bool lower_upper_bound_dimension() {
1348  // reset automatic detection to recompute
1349  dimension_to_be_lowered_ = false;
1350  int new_dimension = -1;
1351  // Browse the tree from the left to the right as higher dimension cells are more likely on the left part of the tree
1352  for (Simplex_handle sh : complex_simplex_range()) {
1353 #ifdef DEBUG_TRACES
1354  for (auto vertex : simplex_vertex_range(sh)) {
1355  std::cout << " " << vertex;
1356  }
1357  std::cout << std::endl;
1358 #endif // DEBUG_TRACES
1359 
1360  int sh_dimension = dimension(sh);
1361  if (sh_dimension >= dimension_)
1362  // Stop browsing as soon as the dimension is reached, no need to go furter
1363  return false;
1364  new_dimension = (std::max)(new_dimension, sh_dimension);
1365  }
1366  dimension_ = new_dimension;
1367  return true;
1368  }
1369 
1370 
1371  public:
1381  void remove_maximal_simplex(Simplex_handle sh) {
1382  // Guarantee the simplex has no children
1383  GUDHI_CHECK(!has_children(sh),
1384  std::invalid_argument("Simplex_tree::remove_maximal_simplex - argument has children"));
1385 
1386  // Simplex is a leaf, it means the child is the Siblings owning the leaf
1387  Siblings* child = sh->second.children();
1388 
1389  if ((child->size() > 1) || (child == root())) {
1390  // Not alone, just remove it from members
1391  // Special case when child is the root of the simplex tree, just remove it from members
1392  child->erase(sh);
1393  } else {
1394  // Sibling is emptied : must be deleted, and its parent must point on his own Sibling
1395  child->oncles()->members().at(child->parent()).assign_children(child->oncles());
1396  delete child;
1397  // dimension may need to be lowered
1398  dimension_to_be_lowered_ = true;
1399  }
1400  }
1401 
1402  private:
1403  Vertex_handle null_vertex_;
1406  Siblings root_;
1408  std::vector<Simplex_handle> filtration_vect_;
1410  int dimension_;
1411  bool dimension_to_be_lowered_ = false;
1412 };
1413 
1414 // Print a Simplex_tree in os.
1415 template<typename...T>
1416 std::ostream& operator<<(std::ostream & os, Simplex_tree<T...> & st) {
1417  for (auto sh : st.filtration_simplex_range()) {
1418  os << st.dimension(sh) << " ";
1419  for (auto v : st.simplex_vertex_range(sh)) {
1420  os << v << " ";
1421  }
1422  os << st.filtration(sh) << "\n"; // TODO(VR): why adding the key ?? not read ?? << " " << st.key(sh) << " \n";
1423  }
1424  return os;
1425 }
1426 
1427 template<typename...T>
1428 std::istream& operator>>(std::istream & is, Simplex_tree<T...> & st) {
1429  typedef Simplex_tree<T...> ST;
1430  std::vector<typename ST::Vertex_handle> simplex;
1431  typename ST::Filtration_value fil;
1432  int max_dim = -1;
1433  while (read_simplex(is, simplex, fil)) {
1434  // read all simplices in the file as a list of vertices
1435  // Warning : simplex_size needs to be casted in int - Can be 0
1436  int dim = static_cast<int> (simplex.size() - 1);
1437  if (max_dim < dim) {
1438  max_dim = dim;
1439  }
1440  // insert every simplex in the simplex tree
1441  st.insert_simplex(simplex, fil);
1442  simplex.clear();
1443  }
1444  st.set_dimension(max_dim);
1445 
1446  return is;
1447 }
1448 
1454  typedef linear_indexing_tag Indexing_tag;
1455  typedef int Vertex_handle;
1456  typedef double Filtration_value;
1457  typedef std::uint32_t Simplex_key;
1458  static const bool store_key = true;
1459  static const bool store_filtration = true;
1460  static const bool contiguous_vertices = false;
1461 };
1462 
1470  typedef linear_indexing_tag Indexing_tag;
1471  typedef int Vertex_handle;
1472  typedef float Filtration_value;
1473  typedef std::uint32_t Simplex_key;
1474  static const bool store_key = true;
1475  static const bool store_filtration = true;
1476  static const bool contiguous_vertices = true;
1477 };
1478  // end defgroup simplex_tree
1480 
1481 } // namespace Gudhi
1482 
1483 #endif // SIMPLEX_TREE_H_
Simplex_tree_skeleton_simplex_iterator< Simplex_tree > Skeleton_simplex_iterator
Iterator over the simplices of the skeleton of the simplicial complex, for a given dimension...
Definition: Simplex_tree.h:186
Dictionary::iterator Simplex_handle
Handle type to a simplex contained in the simplicial complex represented by the simplex tree...
Definition: Simplex_tree.h:135
bool prune_above_filtration(Filtration_value filtration)
Prune above filtration value given as parameter.
Definition: Simplex_tree.h:1308
void expansion(int max_dim)
Expands the Simplex_tree containing only its one skeleton until dimension max_dim.
Definition: Simplex_tree.h:1037
Filtration_simplex_range::const_iterator Filtration_simplex_iterator
Iterator over the simplices of the simplicial complex, ordered by the filtration. ...
Definition: Simplex_tree.h:195
Tag for a linear ordering of simplices.
Definition: indexing_tag.h:32
Simplex Tree data structure for representing simplicial complexes.
Definition: Simplex_tree.h:72
Siblings * self_siblings(SimplexHandle sh)
Definition: Simplex_tree.h:768
std::pair< Simplex_handle, bool > insert_simplex_and_subfaces(const InputVertexRange &Nsimplex, Filtration_value filtration=0)
Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of Vertex_handles...
Definition: Simplex_tree.h:683
void assign_key(Simplex_handle sh, Simplex_key key)
Assign a value &#39;key&#39; to the key of the simplex represented by the Simplex_handle &#39;sh&#39;.
Definition: Simplex_tree.h:754
bool operator==(Simplex_tree &st2)
Checks if two simplex trees are equal.
Definition: Simplex_tree.h:355
Concept describing an indexing scheme (see FilteredComplex) for applying continuous maps to a cell co...
Definition: IndexingTag.h:30
static Simplex_key key(Simplex_handle sh)
Returns the key associated to a simplex.
Definition: Simplex_tree.h:392
static Simplex_handle null_simplex()
Returns a Simplex_handle different from all Simplex_handles associated to the simplices in the simpli...
Definition: Simplex_tree.h:431
static constexpr bool contiguous_vertices
If true, the list of vertices present in the complex must always be 0, ..., num_vertices-1, without any hole.
Definition: SimplexTreeOptions.h:41
boost::iterator_range< Complex_vertex_iterator > Complex_vertex_range
Range over the vertices of the simplicial complex.
Definition: Simplex_tree.h:161
Vertex_handle null_vertex() const
Returns a Vertex_handle different from all Vertex_handles associated to the vertices of the simplicia...
Definition: Simplex_tree.h:443
Simplex_tree_simplex_vertex_iterator< Simplex_tree > Simplex_vertex_iterator
Iterator over the vertices of a simplex.
Definition: Simplex_tree.h:165
Definition: SimplicialComplexForAlpha.h:26
void print_hasse(std::ostream &os)
Write the hasse diagram of the simplicial complex in os.
Definition: Simplex_tree.h:1236
Key type used as simplex identifier.
Definition: SimplexKey.h:27
Siblings * root()
Definition: Simplex_tree.h:777
Simplex_tree(Simplex_tree &&old)
User-defined move constructor moves the whole tree structure.
Definition: Simplex_tree.h:324
Options::Simplex_key Simplex_key
Key associated to each simplex.
Definition: Simplex_tree.h:83
bool operator!=(Simplex_tree &st2)
Checks if two simplex trees are different.
Definition: Simplex_tree.h:363
bool make_filtration_non_decreasing()
This function ensures that each simplex has a higher filtration value than its faces by increasing th...
Definition: Simplex_tree.h:1255
std::vector< Simplex_handle > Filtration_simplex_range
Range over the simplices of the simplicial complex, ordered by the filtration.
Definition: Simplex_tree.h:191
int dimension()
Returns the dimension of the simplicial complex.
Definition: Simplex_tree.h:495
Filtration_simplex_range const & filtration_simplex_range(Indexing_tag=Indexing_tag())
Returns a range over the simplices of the simplicial complex, in the order of the filtration...
Definition: Simplex_tree.h:248
void initialize_filtration()
Initializes the filtrations, i.e. sort the simplices according to their order in the filtration and i...
Definition: Simplex_tree.h:800
Simplex_handle find(const InputVertexRange &s)
Given a range of Vertex_handles, returns the Simplex_handle of the simplex in the simplicial complex ...
Definition: Simplex_tree.h:517
Value type for a filtration function on a cell complex.
Definition: FiltrationValue.h:32
Cofaces_simplex_range cofaces_simplex_range(const Simplex_handle simplex, int codimension)
Compute the cofaces of a n simplex.
Definition: Simplex_tree.h:892
Complex_simplex_range complex_simplex_range()
Returns a range over the simplices of the simplicial complex.
Definition: Simplex_tree.h:214
Concept of the template parameter for the class Gudhi::Simplex_tree<SimplexTreeOptions>.
Definition: SimplexTreeOptions.h:27
size_t num_vertices() const
Returns the number of vertices in the complex.
Definition: Simplex_tree.h:448
void assign_filtration(Simplex_handle sh, Filtration_value fv)
Sets the filtration value of a simplex.
Definition: Simplex_tree.h:421
std::pair< Simplex_handle, Simplex_handle > endpoints(Simplex_handle sh)
Definition: Simplex_tree.h:761
Boundary_simplex_range boundary_simplex_range(SimplexHandle sh)
Returns a range over the simplices of the boundary of a simplex.
Definition: Simplex_tree.h:282
Complex_vertex_range complex_vertex_range()
Returns a range over the vertices of the simplicial complex. The order is increasing according to < o...
Definition: Simplex_tree.h:203
Simplex_vertex_range simplex_vertex_range(Simplex_handle sh)
Returns a range over the vertices of a simplex.
Definition: Simplex_tree.h:261
Options::Vertex_handle Vertex_handle
Type for the vertex handle.
Definition: Simplex_tree.h:87
Skeleton_simplex_range skeleton_simplex_range(int dim)
Returns a range over the simplices of the dim-skeleton of the simplicial complex. ...
Definition: Simplex_tree.h:228
boost::iterator_range< Boundary_simplex_iterator > Boundary_simplex_range
Range over the simplices of the boundary of a simplex.
Definition: Simplex_tree.h:175
bool has_children(SimplexHandle sh) const
Returns true if the node in the simplex tree pointed by sh has children.
Definition: Simplex_tree.h:504
Cofaces_simplex_range star_simplex_range(const Simplex_handle simplex)
Compute the star of a n simplex.
Definition: Simplex_tree.h:881
void set_dimension(int dimension)
Set a dimension for the simplicial complex.
Definition: Simplex_tree.h:785
int upper_bound_dimension() const
Returns an upper bound on the dimension of the simplicial complex.
Definition: Simplex_tree.h:487
int dimension(Simplex_handle sh)
Returns the dimension of a simplex.
Definition: Simplex_tree.h:476
static Simplex_key null_key()
Returns a key different for all keys associated to the simplices of the simplicial complex...
Definition: Simplex_tree.h:437
static Filtration_value filtration(Simplex_handle sh)
Returns the filtration value of a simplex.
Definition: Simplex_tree.h:410
bool read_simplex(std::istream &in_, std::vector< Vertex_handle > &simplex, Filtration_value &fil)
Read a face from a file.
Definition: reader_utils.h:170
Definition: Simplex_tree.h:1469
Handle type for the vertices of a cell complex.
Definition: VertexHandle.h:27
boost::transform_iterator< return_first, Dictionary_it > Complex_vertex_iterator
Iterator over the vertices of the simplicial complex.
Definition: Simplex_tree.h:159
~Simplex_tree()
Destructor; deallocates the whole tree structure.
Definition: Simplex_tree.h:334
void remove_maximal_simplex(Simplex_handle sh)
Remove a maximal simplex.
Definition: Simplex_tree.h:1381
static const bool store_filtration
If true, each simplex has extra storage for one Filtration_value, and this value is propagated by ope...
Definition: SimplexTreeOptions.h:39
size_t num_simplices()
returns the number of simplices in the simplex_tree.
Definition: Simplex_tree.h:454
boost::iterator_range< Complex_simplex_iterator > Complex_simplex_range
Range over the simplices of the simplicial complex.
Definition: Simplex_tree.h:181
Options::Filtration_value Filtration_value
Type for the value of the filtration function.
Definition: Simplex_tree.h:79
Simplex_tree()
Constructs an empty simplex tree.
Definition: Simplex_tree.h:292
Simplex_tree_boundary_simplex_iterator< Simplex_tree > Boundary_simplex_iterator
Iterator over the simplices of the boundary of a simplex.
Definition: Simplex_tree.h:173
boost::iterator_range< Skeleton_simplex_iterator > Skeleton_simplex_range
Range over the simplices of the skeleton of the simplicial complex, for a given dimension.
Definition: Simplex_tree.h:189
Simplex_tree_complex_simplex_iterator< Simplex_tree > Complex_simplex_iterator
Iterator over the simplices of the simplicial complex.
Definition: Simplex_tree.h:179
void insert_graph(const OneSkeletonGraph &skel_graph)
Inserts a 1-skeleton in an empty Simplex_tree.
Definition: Simplex_tree.h:978
Simplex_handle simplex(Simplex_key idx) const
Returns the simplex that has index idx in the filtration.
Definition: Simplex_tree.h:401
Simplex_tree(const Simplex_tree &simplex_source)
User-defined copy constructor reproduces the whole tree structure.
Definition: Simplex_tree.h:299
This file includes common file reader for GUDHI.
boost::iterator_range< Simplex_vertex_iterator > Simplex_vertex_range
Range over the vertices of a simplex.
Definition: Simplex_tree.h:167
std::pair< Simplex_handle, bool > insert_simplex(const InputVertexRange &simplex, Filtration_value filtration=0)
Insert a simplex, represented by a range of Vertex_handles, in the simplicial complex.
Definition: Simplex_tree.h:654
void expansion_with_blockers(int max_dim, Blocker block_simplex)
Expands a simplex tree containing only a graph. Simplices corresponding to cliques in the graph are a...
Definition: Simplex_tree.h:1135
void rec_copy(Siblings *sib, Siblings *sib_source)
depth first search, inserts simplices when reaching a leaf.
Definition: Simplex_tree.h:309
std::vector< Simplex_handle > Cofaces_simplex_range
Range over the cofaces of a simplex.
Definition: Simplex_tree.h:169
GUDHI  Version 2.3.0  - C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding.  - Copyright : GPL v3 Generated on Tue Sep 4 2018 14:32:59 for GUDHI by Doxygen 1.8.13