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 Sophia Antipolis-Méditerranée (France)
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #ifndef 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 
53 namespace Gudhi {
54 
55 struct Simplex_tree_options_full_featured;
56 
70 template<typename SimplexTreeOptions = Simplex_tree_options_full_featured>
71 class Simplex_tree {
72  public:
74  typedef typename Options::Indexing_tag Indexing_tag;
87 
88  /* Type of node in the simplex tree. */
89  typedef Simplex_tree_node_explicit_storage<Simplex_tree> Node;
90  /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */
91  // Note: this wastes space when Vertex_handle is 32 bits and Node is aligned on 64 bits. It would be better to use a
92  // flat_set (with our own comparator) where we can control the layout of the struct (put Vertex_handle and
93  // Simplex_key next to each other).
94  typedef typename boost::container::flat_map<Vertex_handle, Node> Dictionary;
95 
96  /* \brief Set of nodes sharing a same parent in the simplex tree. */
97  /* \brief Set of nodes sharing a same parent in the simplex tree. */
98  typedef Simplex_tree_siblings<Simplex_tree, Dictionary> Siblings;
99 
100  struct Key_simplex_base_real {
101  Key_simplex_base_real() : key_(-1) {}
102  void assign_key(Simplex_key k) { key_ = k; }
103  Simplex_key key() const { return key_; }
104  private:
105  Simplex_key key_;
106  };
107  struct Key_simplex_base_dummy {
108  Key_simplex_base_dummy() {}
109  void assign_key(Simplex_key) { }
110  Simplex_key key() const { assert(false); return -1; }
111  };
112  typedef typename std::conditional<Options::store_key, Key_simplex_base_real, Key_simplex_base_dummy>::type
113  Key_simplex_base;
114 
115  struct Filtration_simplex_base_real {
116  Filtration_simplex_base_real() : filt_(0) {}
117  void assign_filtration(Filtration_value f) { filt_ = f; }
118  Filtration_value filtration() const { return filt_; }
119  private:
120  Filtration_value filt_;
121  };
122  struct Filtration_simplex_base_dummy {
123  Filtration_simplex_base_dummy() {}
124  void assign_filtration(Filtration_value f) { assert(f == 0); }
125  Filtration_value filtration() const { return 0; }
126  };
127  typedef typename std::conditional<Options::store_filtration, Filtration_simplex_base_real,
128  Filtration_simplex_base_dummy>::type Filtration_simplex_base;
129 
130  public:
133  typedef typename Dictionary::iterator Simplex_handle;
134 
135  private:
136  typedef typename Dictionary::iterator Dictionary_it;
137  typedef typename Dictionary_it::value_type Dit_value_t;
138 
139  struct return_first {
140  Vertex_handle operator()(const Dit_value_t& p_sh) const {
141  return p_sh.first;
142  }
143  };
144 
145  public:
157  typedef boost::transform_iterator<return_first, Dictionary_it> Complex_vertex_iterator;
159  typedef boost::iterator_range<Complex_vertex_iterator> Complex_vertex_range;
163  typedef Simplex_tree_simplex_vertex_iterator<Simplex_tree> Simplex_vertex_iterator;
165  typedef boost::iterator_range<Simplex_vertex_iterator> Simplex_vertex_range;
167  typedef std::vector<Simplex_handle> Cofaces_simplex_range;
171  typedef Simplex_tree_boundary_simplex_iterator<Simplex_tree> Boundary_simplex_iterator;
173  typedef boost::iterator_range<Boundary_simplex_iterator> Boundary_simplex_range;
177  typedef Simplex_tree_complex_simplex_iterator<Simplex_tree> Complex_simplex_iterator;
179  typedef boost::iterator_range<Complex_simplex_iterator> Complex_simplex_range;
184  typedef Simplex_tree_skeleton_simplex_iterator<Simplex_tree> Skeleton_simplex_iterator;
187  typedef boost::iterator_range<Skeleton_simplex_iterator> Skeleton_simplex_range;
189  typedef std::vector<Simplex_handle> Filtration_simplex_range;
193  typedef typename Filtration_simplex_range::const_iterator Filtration_simplex_iterator;
194 
195  /* @} */ // end name range and iterator types
201  Complex_vertex_range complex_vertex_range() {
202  return Complex_vertex_range(
203  boost::make_transform_iterator(root_.members_.begin(), return_first()),
204  boost::make_transform_iterator(root_.members_.end(), return_first()));
205  }
206 
212  Complex_simplex_range complex_simplex_range() {
215  }
216 
226  Skeleton_simplex_range skeleton_simplex_range(int dim) {
229  }
230 
246  Filtration_simplex_range const& filtration_simplex_range(Indexing_tag = Indexing_tag()) {
247  if (filtration_vect_.empty()) {
249  }
250  return filtration_vect_;
251  }
252 
259  Simplex_vertex_range simplex_vertex_range(Simplex_handle sh) {
260  assert(sh != null_simplex()); // Empty simplex
263  }
264 
279  template<class SimplexHandle>
280  Boundary_simplex_range boundary_simplex_range(SimplexHandle sh) {
283  }
284  // end range and iterator methods
291  : null_vertex_(-1),
292  root_(nullptr, null_vertex_),
293  filtration_vect_(),
294  dimension_(-1) { }
295 
297  Simplex_tree(const Simplex_tree& simplex_source)
298  : null_vertex_(simplex_source.null_vertex_),
299  root_(nullptr, null_vertex_ , simplex_source.root_.members_),
300  filtration_vect_(),
301  dimension_(simplex_source.dimension_) {
302  auto root_source = simplex_source.root_;
303  rec_copy(&root_, &root_source);
304  }
305 
307  void rec_copy(Siblings *sib, Siblings *sib_source) {
308  for (auto sh = sib->members().begin(), sh_source = sib_source->members().begin();
309  sh != sib->members().end(); ++sh, ++sh_source) {
310  if (has_children(sh_source)) {
311  Siblings * newsib = new Siblings(sib, sh_source->first);
312  newsib->members_.reserve(sh_source->second.children()->members().size());
313  for (auto & child : sh_source->second.children()->members())
314  newsib->members_.emplace_hint(newsib->members_.end(), child.first, Node(newsib, child.second.filtration()));
315  rec_copy(newsib, sh_source->second.children());
316  sh->second.assign_children(newsib);
317  }
318  }
319  }
320 
323  : null_vertex_(std::move(old.null_vertex_)),
324  root_(std::move(old.root_)),
325  filtration_vect_(std::move(old.filtration_vect_)),
326  dimension_(std::move(old.dimension_)) {
327  old.dimension_ = -1;
328  old.root_ = Siblings(nullptr, null_vertex_);
329  }
330 
333  for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) {
334  if (has_children(sh)) {
335  rec_delete(sh->second.children());
336  }
337  }
338  } // end constructor/destructor
340  private:
341  // Recursive deletion
342  void rec_delete(Siblings * sib) {
343  for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
344  if (has_children(sh)) {
345  rec_delete(sh->second.children());
346  }
347  }
348  delete sib;
349  }
350 
351  public:
354  if ((null_vertex_ != st2.null_vertex_) ||
355  (dimension_ != st2.dimension_))
356  return false;
357  return rec_equal(&root_, &st2.root_);
358  }
359 
362  return (!(*this == st2));
363  }
364 
365  private:
367  bool rec_equal(Siblings* s1, Siblings* s2) {
368  if (s1->members().size() != s2->members().size())
369  return false;
370  for (auto sh1 = s1->members().begin(), sh2 = s2->members().begin();
371  (sh1 != s1->members().end() && sh2 != s2->members().end()); ++sh1, ++sh2) {
372  if (sh1->first != sh2->first || sh1->second.filtration() != sh2->second.filtration())
373  return false;
374  if (has_children(sh1) != has_children(sh2))
375  return false;
376  // Recursivity on children only if both have children
377  else if (has_children(sh1))
378  if (!rec_equal(sh1->second.children(), sh2->second.children()))
379  return false;
380  }
381  return true;
382  }
383 
384  public:
390  static Simplex_key key(Simplex_handle sh) {
391  return sh->second.key();
392  }
393 
399  Simplex_handle simplex(Simplex_key key) const {
400  return filtration_vect_[key];
401  }
402 
408  static Filtration_value filtration(Simplex_handle sh) {
409  if (sh != null_simplex()) {
410  return sh->second.filtration();
411  } else {
412  return std::numeric_limits<Filtration_value>::infinity();
413  }
414  }
415 
419  void assign_filtration(Simplex_handle sh, Filtration_value fv) {
420  GUDHI_CHECK(sh != null_simplex(),
421  std::invalid_argument("Simplex_tree::assign_filtration - cannot assign filtration on null_simplex"));
422  sh->second.assign_filtration(fv);
423  }
424 
429  static Simplex_handle null_simplex() {
430  return Dictionary_it(nullptr);
431  }
432 
435  static Simplex_key null_key() {
436  return -1;
437  }
438 
441  Vertex_handle null_vertex() const {
442  return null_vertex_;
443  }
444 
446  size_t num_vertices() const {
447  return root_.members_.size();
448  }
449 
450  public:
452  size_t num_simplices() {
453  return num_simplices(&root_);
454  }
455 
456  private:
458  size_t num_simplices(Siblings * sib) {
459  auto sib_begin = sib->members().begin();
460  auto sib_end = sib->members().end();
461  size_t simplices_number = sib_end - sib_begin;
462  for (auto sh = sib_begin; sh != sib_end; ++sh) {
463  if (has_children(sh)) {
464  simplices_number += num_simplices(sh->second.children());
465  }
466  }
467  return simplices_number;
468  }
469 
470  public:
474  int dimension(Simplex_handle sh) {
475  Siblings * curr_sib = self_siblings(sh);
476  int dim = 0;
477  while (curr_sib != nullptr) {
478  ++dim;
479  curr_sib = curr_sib->oncles();
480  }
481  return dim - 1;
482  }
483 
485  int dimension() const {
486  return dimension_;
487  }
488 
491  template<class SimplexHandle>
492  bool has_children(SimplexHandle sh) const {
493  return (sh->second.children()->parent() == sh->first);
494  }
495 
503  template<class InputVertexRange = std::initializer_list<Vertex_handle>>
504  Simplex_handle find(const InputVertexRange & s) {
505  auto first = std::begin(s);
506  auto last = std::end(s);
507 
508  if (first == last)
509  return null_simplex(); // ----->>
510 
511  // Copy before sorting
512  std::vector<Vertex_handle> copy(first, last);
513  std::sort(std::begin(copy), std::end(copy));
514  return find_simplex(copy);
515  }
516 
517  private:
519  Simplex_handle find_simplex(const std::vector<Vertex_handle> & simplex) {
520  Siblings * tmp_sib = &root_;
521  Dictionary_it tmp_dit;
522  Vertex_handle last = simplex.back();
523  for (auto v : simplex) {
524  tmp_dit = tmp_sib->members_.find(v);
525  if (tmp_dit == tmp_sib->members_.end()) {
526  return null_simplex();
527  }
528  if (!has_children(tmp_dit) && v != last) {
529  return null_simplex();
530  }
531  tmp_sib = tmp_dit->second.children();
532  }
533  return tmp_dit;
534  }
535 
538  Simplex_handle find_vertex(Vertex_handle v) {
540  assert(contiguous_vertices());
541  return root_.members_.begin() + v;
542  } else {
543  return root_.members_.find(v);
544  }
545  }
546 
547  public:
549  bool contiguous_vertices() const {
550  if (root_.members_.empty()) return true;
551  if (root_.members_.begin()->first != 0) return false;
552  if (std::prev(root_.members_.end())->first != static_cast<Vertex_handle>(root_.members_.size() - 1)) return false;
553  return true;
554  }
555 
556  private:
571  std::pair<Simplex_handle, bool> insert_vertex_vector(const std::vector<Vertex_handle>& simplex,
572  Filtration_value filtration) {
573  Siblings * curr_sib = &root_;
574  std::pair<Simplex_handle, bool> res_insert;
575  auto vi = simplex.begin();
576  for (; vi != simplex.end() - 1; ++vi) {
577  res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib, filtration));
578  if (!(has_children(res_insert.first))) {
579  res_insert.first->second.assign_children(new Siblings(curr_sib, *vi));
580  }
581  curr_sib = res_insert.first->second.children();
582  }
583  res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib, filtration));
584  if (!res_insert.second) {
585  // if already in the complex
586  if (res_insert.first->second.filtration() > filtration) {
587  // if filtration value modified
588  res_insert.first->second.assign_filtration(filtration);
589  return res_insert;
590  }
591  // if filtration value unchanged
592  return std::pair<Simplex_handle, bool>(null_simplex(), false);
593  }
594  // otherwise the insertion has succeeded
595  return res_insert;
596  }
597 
598  public:
622  template<class InputVertexRange = std::initializer_list<Vertex_handle>>
623  std::pair<Simplex_handle, bool> insert_simplex(const InputVertexRange & simplex,
624  Filtration_value filtration = 0) {
625  auto first = std::begin(simplex);
626  auto last = std::end(simplex);
627 
628  if (first == last)
629  return std::pair<Simplex_handle, bool>(null_simplex(), true); // ----->>
630 
631  // Copy before sorting
632  std::vector<Vertex_handle> copy(first, last);
633  std::sort(std::begin(copy), std::end(copy));
634  return insert_vertex_vector(copy, filtration);
635  }
636 
651  template<class InputVertexRange = std::initializer_list<Vertex_handle>>
652  std::pair<Simplex_handle, bool> insert_simplex_and_subfaces(const InputVertexRange& Nsimplex,
653  Filtration_value filtration = 0) {
654  auto first = std::begin(Nsimplex);
655  auto last = std::end(Nsimplex);
656 
657  if (first == last)
658  return std::pair<Simplex_handle, bool>(null_simplex(), true); // ----->>
659 
660  // Copy before sorting
661  std::vector<Vertex_handle> copy(first, last);
662  std::sort(std::begin(copy), std::end(copy));
663 
664  std::vector<std::vector<Vertex_handle>> to_be_inserted;
665  std::vector<std::vector<Vertex_handle>> to_be_propagated;
666  return rec_insert_simplex_and_subfaces(copy, to_be_inserted, to_be_propagated, filtration);
667  }
668 
669  private:
670  std::pair<Simplex_handle, bool> rec_insert_simplex_and_subfaces(std::vector<Vertex_handle>& the_simplex,
671  std::vector<std::vector<Vertex_handle>>& to_be_inserted,
672  std::vector<std::vector<Vertex_handle>>& to_be_propagated,
673  Filtration_value filtration = 0.0) {
674  std::pair<Simplex_handle, bool> insert_result;
675  if (the_simplex.size() > 1) {
676  // Get and remove last vertex
677  Vertex_handle last_vertex = the_simplex.back();
678  the_simplex.pop_back();
679  // Recursive call after last vertex removal
680  insert_result = rec_insert_simplex_and_subfaces(the_simplex, to_be_inserted, to_be_propagated, filtration);
681 
682  // Concatenation of to_be_inserted and to_be_propagated
683  to_be_inserted.insert(to_be_inserted.begin(), to_be_propagated.begin(), to_be_propagated.end());
684  to_be_propagated = to_be_inserted;
685 
686  // to_be_inserted treatment
687  for (auto& simplex_tbi : to_be_inserted) {
688  simplex_tbi.push_back(last_vertex);
689  }
690  std::vector<Vertex_handle> last_simplex(1, last_vertex);
691  to_be_inserted.insert(to_be_inserted.begin(), last_simplex);
692  // i.e. (0,1,2) =>
693  // [to_be_inserted | to_be_propagated] = [(1) (0,1) | (0)]
694  // [to_be_inserted | to_be_propagated] = [(2) (0,2) (1,2) (0,1,2) | (0) (1) (0,1)]
695  // N.B. : it is important the last inserted to be the highest in dimension
696  // in order to return the "last" insert_simplex result
697 
698  // insert all to_be_inserted
699  for (auto& simplex_tbi : to_be_inserted) {
700  insert_result = insert_vertex_vector(simplex_tbi, filtration);
701  }
702  } else if (the_simplex.size() == 1) {
703  // When reaching the end of recursivity, vector of simplices shall be empty and filled on back recursive
704  if ((to_be_inserted.size() != 0) || (to_be_propagated.size() != 0)) {
705  std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Error vector not empty\n";
706  exit(-1);
707  }
708  std::vector<Vertex_handle> first_simplex(1, the_simplex.back());
709  // i.e. (0,1,2) => [to_be_inserted | to_be_propagated] = [(0) | ]
710  to_be_inserted.push_back(first_simplex);
711 
712  insert_result = insert_vertex_vector(first_simplex, filtration);
713  } else {
714  std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error\n";
715  exit(-1);
716  }
717  return insert_result;
718  }
719 
720  public:
723  void assign_key(Simplex_handle sh, Simplex_key key) {
724  sh->second.assign_key(key);
725  }
726 
730  std::pair<Simplex_handle, Simplex_handle> endpoints(Simplex_handle sh) {
731  assert(dimension(sh) == 1);
732  return { find_vertex(sh->first), find_vertex(self_siblings(sh)->parent()) };
733  }
734 
736  template<class SimplexHandle>
737  Siblings* self_siblings(SimplexHandle sh) {
738  if (sh->second.children()->parent() == sh->first)
739  return sh->second.children()->oncles();
740  else
741  return sh->second.children();
742  }
743 
744  public:
746  Siblings * root() {
747  return &root_;
748  }
749 
752  dimension_ = dimension;
753  }
754 
755  public:
766  filtration_vect_.clear();
767  filtration_vect_.reserve(num_simplices());
768  for (Simplex_handle sh : complex_simplex_range())
769  filtration_vect_.push_back(sh);
770 
771  /* We use stable_sort here because with libstdc++ it is faster than sort.
772  * is_before_in_filtration is now a total order, but we used to call
773  * stable_sort for the following heuristic:
774  * The use of a depth-first traversal of the simplex tree, provided by
775  * complex_simplex_range(), combined with a stable sort is meant to
776  * optimize the order of simplices with same filtration value. The
777  * heuristic consists in inserting the cofaces of a simplex as soon as
778  * possible.
779  */
780 #ifdef GUDHI_USE_TBB
781  tbb::parallel_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration(this));
782 #else
783  std::stable_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration(this));
784 #endif
785  }
786 
787  private:
800  void rec_coface(std::vector<Vertex_handle> &vertices, Siblings *curr_sib, int curr_nbVertices,
801  std::vector<Simplex_handle>& cofaces, bool star, int nbVertices) {
802  if (!(star || curr_nbVertices <= nbVertices)) // dimension of actual simplex <= nbVertices
803  return;
804  for (Simplex_handle simplex = curr_sib->members().begin(); simplex != curr_sib->members().end(); ++simplex) {
805  if (vertices.empty()) {
806  // If we reached the end of the vertices, and the simplex has more vertices than the given simplex
807  // => we found a coface
808 
809  // Add a coface if we wan't the star or if the number of vertices of the current simplex matches with nbVertices
810  bool addCoface = (star || curr_nbVertices == nbVertices);
811  if (addCoface)
812  cofaces.push_back(simplex);
813  if ((!addCoface || star) && has_children(simplex)) // Rec call
814  rec_coface(vertices, simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
815  } else {
816  if (simplex->first == vertices.back()) {
817  // If curr_sib matches with the top vertex
818  bool equalDim = (star || curr_nbVertices == nbVertices); // dimension of actual simplex == nbVertices
819  bool addCoface = vertices.size() == 1 && equalDim;
820  if (addCoface)
821  cofaces.push_back(simplex);
822  if ((!addCoface || star) && has_children(simplex)) {
823  // Rec call
824  Vertex_handle tmp = vertices.back();
825  vertices.pop_back();
826  rec_coface(vertices, simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
827  vertices.push_back(tmp);
828  }
829  } else if (simplex->first > vertices.back()) {
830  return;
831  } else {
832  // (simplex->first < vertices.back()
833  if (has_children(simplex))
834  rec_coface(vertices, simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
835  }
836  }
837  }
838  }
839 
840  public:
846  Cofaces_simplex_range star_simplex_range(const Simplex_handle simplex) {
847  return cofaces_simplex_range(simplex, 0);
848  }
849 
857  Cofaces_simplex_range cofaces_simplex_range(const Simplex_handle simplex, int codimension) {
858  Cofaces_simplex_range cofaces;
859  // codimension must be positive or null integer
860  assert(codimension >= 0);
861  Simplex_vertex_range rg = simplex_vertex_range(simplex);
862  std::vector<Vertex_handle> copy(rg.begin(), rg.end());
863  if (codimension + static_cast<int>(copy.size()) > dimension_ + 1 ||
864  (codimension == 0 && static_cast<int>(copy.size()) > dimension_)) // n+codimension greater than dimension_
865  return cofaces;
866  // must be sorted in decreasing order
867  assert(std::is_sorted(copy.begin(), copy.end(), std::greater<Vertex_handle>()));
868  bool star = codimension == 0;
869  rec_coface(copy, &root_, 1, cofaces, star, codimension + static_cast<int>(copy.size()));
870  return cofaces;
871  }
872 
873  private:
881  bool reverse_lexicographic_order(Simplex_handle sh1, Simplex_handle sh2) {
882  Simplex_vertex_range rg1 = simplex_vertex_range(sh1);
883  Simplex_vertex_range rg2 = simplex_vertex_range(sh2);
884  Simplex_vertex_iterator it1 = rg1.begin();
885  Simplex_vertex_iterator it2 = rg2.begin();
886  while (it1 != rg1.end() && it2 != rg2.end()) {
887  if (*it1 == *it2) {
888  ++it1;
889  ++it2;
890  } else {
891  return *it1 < *it2;
892  }
893  }
894  return ((it1 == rg1.end()) && (it2 != rg2.end()));
895  }
896 
903  struct is_before_in_filtration {
904  explicit is_before_in_filtration(Simplex_tree * st)
905  : st_(st) { }
906 
907  bool operator()(const Simplex_handle sh1, const Simplex_handle sh2) const {
908  // Not using st_->filtration(sh1) because it uselessly tests for null_simplex.
909  if (sh1->second.filtration() != sh2->second.filtration()) {
910  return sh1->second.filtration() < sh2->second.filtration();
911  }
912  // is sh1 a proper subface of sh2
913  return st_->reverse_lexicographic_order(sh1, sh2);
914  }
915 
916  Simplex_tree * st_;
917  };
918 
919  public:
938  template<class OneSkeletonGraph>
939  void insert_graph(const OneSkeletonGraph& skel_graph) {
940  // the simplex tree must be empty
941  assert(num_simplices() == 0);
942 
943  if (boost::num_vertices(skel_graph) == 0) {
944  return;
945  }
946  if (num_edges(skel_graph) == 0) {
947  dimension_ = 0;
948  } else {
949  dimension_ = 1;
950  }
951 
952  root_.members_.reserve(boost::num_vertices(skel_graph));
953 
954  typename boost::graph_traits<OneSkeletonGraph>::vertex_iterator v_it,
955  v_it_end;
956  for (std::tie(v_it, v_it_end) = boost::vertices(skel_graph); v_it != v_it_end;
957  ++v_it) {
958  root_.members_.emplace_hint(
959  root_.members_.end(), *v_it,
960  Node(&root_, boost::get(vertex_filtration_t(), skel_graph, *v_it)));
961  }
962  typename boost::graph_traits<OneSkeletonGraph>::edge_iterator e_it,
963  e_it_end;
964  for (std::tie(e_it, e_it_end) = boost::edges(skel_graph); e_it != e_it_end;
965  ++e_it) {
966  auto u = source(*e_it, skel_graph);
967  auto v = target(*e_it, skel_graph);
968  if (u < v) {
969  // count edges only once { std::swap(u,v); } // u < v
970  auto sh = find_vertex(u);
971  if (!has_children(sh)) {
972  sh->second.assign_children(new Siblings(&root_, sh->first));
973  }
974 
975  sh->second.children()->members().emplace(
976  v,
977  Node(sh->second.children(),
978  boost::get(edge_filtration_t(), skel_graph, *e_it)));
979  }
980  }
981  }
982 
994  void expansion(int max_dim) {
995  dimension_ = max_dim;
996  for (Dictionary_it root_it = root_.members_.begin();
997  root_it != root_.members_.end(); ++root_it) {
998  if (has_children(root_it)) {
999  siblings_expansion(root_it->second.children(), max_dim - 1);
1000  }
1001  }
1002  dimension_ = max_dim - dimension_;
1003  }
1004 
1005  private:
1007  void siblings_expansion(Siblings * siblings, // must contain elements
1008  int k) {
1009  if (dimension_ > k) {
1010  dimension_ = k;
1011  }
1012  if (k == 0)
1013  return;
1014  Dictionary_it next = siblings->members().begin();
1015  ++next;
1016 
1017  thread_local std::vector<std::pair<Vertex_handle, Node> > inter;
1018  for (Dictionary_it s_h = siblings->members().begin();
1019  s_h != siblings->members().end(); ++s_h, ++next) {
1020  Simplex_handle root_sh = find_vertex(s_h->first);
1021  if (has_children(root_sh)) {
1022  intersection(
1023  inter, // output intersection
1024  next, // begin
1025  siblings->members().end(), // end
1026  root_sh->second.children()->members().begin(),
1027  root_sh->second.children()->members().end(),
1028  s_h->second.filtration());
1029  if (inter.size() != 0) {
1030  Siblings * new_sib = new Siblings(siblings, // oncles
1031  s_h->first, // parent
1032  inter); // boost::container::ordered_unique_range_t
1033  inter.clear();
1034  s_h->second.assign_children(new_sib);
1035  siblings_expansion(new_sib, k - 1);
1036  } else {
1037  // ensure the children property
1038  s_h->second.assign_children(siblings);
1039  inter.clear();
1040  }
1041  }
1042  }
1043  }
1044 
1047  static void intersection(std::vector<std::pair<Vertex_handle, Node> >& intersection,
1048  Dictionary_it begin1, Dictionary_it end1,
1049  Dictionary_it begin2, Dictionary_it end2,
1050  Filtration_value filtration_) {
1051  if (begin1 == end1 || begin2 == end2)
1052  return; // ----->>
1053  while (true) {
1054  if (begin1->first == begin2->first) {
1055  Filtration_value filt = (std::max)({begin1->second.filtration(), begin2->second.filtration(), filtration_});
1056  intersection.emplace_back(begin1->first, Node(nullptr, filt));
1057  if (++begin1 == end1 || ++begin2 == end2)
1058  return; // ----->>
1059  } else if (begin1->first < begin2->first) {
1060  if (++begin1 == end1)
1061  return;
1062  } else /* begin1->first > begin2->first */ {
1063  if (++begin2 == end2)
1064  return; // ----->>
1065  }
1066  }
1067  }
1068 
1069  public:
1076  void print_hasse(std::ostream& os) {
1077  os << num_simplices() << " " << std::endl;
1078  for (auto sh : filtration_simplex_range()) {
1079  os << dimension(sh) << " ";
1080  for (auto b_sh : boundary_simplex_range(sh)) {
1081  os << key(b_sh) << " ";
1082  }
1083  os << filtration(sh) << " \n";
1084  }
1085  }
1086 
1087  public:
1097  bool modified = false;
1098  // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree
1099  for (auto& simplex : boost::adaptors::reverse(root_.members())) {
1100  if (has_children(&simplex)) {
1101  modified |= rec_make_filtration_non_decreasing(simplex.second.children());
1102  }
1103  }
1104  return modified;
1105  }
1106 
1107  private:
1112  bool rec_make_filtration_non_decreasing(Siblings * sib) {
1113  bool modified = false;
1114 
1115  // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree
1116  for (auto& simplex : boost::adaptors::reverse(sib->members())) {
1117  // Find the maximum filtration value in the border
1118  Boundary_simplex_range boundary = boundary_simplex_range(&simplex);
1119  Boundary_simplex_iterator max_border = std::max_element(std::begin(boundary), std::end(boundary),
1120  [](Simplex_handle sh1, Simplex_handle sh2) {
1121  return filtration(sh1) < filtration(sh2);
1122  });
1123 
1124  Filtration_value max_filt_border_value = filtration(*max_border);
1125  if (simplex.second.filtration() < max_filt_border_value) {
1126  // Store the filtration modification information
1127  modified = true;
1128  simplex.second.assign_filtration(max_filt_border_value);
1129  }
1130  if (has_children(&simplex)) {
1131  modified |= rec_make_filtration_non_decreasing(simplex.second.children());
1132  }
1133  }
1134  // Make the modified information to be traced by upper call
1135  return modified;
1136  }
1137 
1138  public:
1146  bool prune_above_filtration(Filtration_value filtration) {
1147  return rec_prune_above_filtration(root(), filtration);
1148  }
1149 
1150  private:
1151  bool rec_prune_above_filtration(Siblings* sib, Filtration_value filt) {
1152  auto&& list = sib->members();
1153  auto last = std::remove_if(list.begin(), list.end(), [=](Dit_value_t& simplex) {
1154  if (simplex.second.filtration() <= filt) return false;
1155  if (has_children(&simplex)) rec_delete(simplex.second.children());
1156  return true;
1157  });
1158 
1159  bool modified = (last != list.end());
1160  if (last == list.begin() && sib != root()) {
1161  // Removing the whole siblings, parent becomes a leaf.
1162  sib->oncles()->members()[sib->parent()].assign_children(sib->oncles());
1163  delete sib;
1164  return true;
1165  } else {
1166  // Keeping some elements of siblings. Remove the others, and recurse in the remaining ones.
1167  list.erase(last, list.end());
1168  for (auto&& simplex : list)
1169  if (has_children(&simplex))
1170  modified |= rec_prune_above_filtration(simplex.second.children(), filt);
1171  }
1172  return modified;
1173  }
1174 
1175  public:
1182  void remove_maximal_simplex(Simplex_handle sh) {
1183  // Guarantee the simplex has no children
1184  GUDHI_CHECK(!has_children(sh),
1185  std::invalid_argument("Simplex_tree::remove_maximal_simplex - argument has children"));
1186 
1187  // Simplex is a leaf, it means the child is the Siblings owning the leaf
1188  Siblings* child = sh->second.children();
1189 
1190  if ((child->size() > 1) || (child == root())) {
1191  // Not alone, just remove it from members
1192  // Special case when child is the root of the simplex tree, just remove it from members
1193  child->erase(sh);
1194  } else {
1195  // Sibling is emptied : must be deleted, and its parent must point on his own Sibling
1196  child->oncles()->members().at(child->parent()).assign_children(child->oncles());
1197  delete child;
1198  }
1199  }
1200 
1201  private:
1202  Vertex_handle null_vertex_;
1205  Siblings root_;
1207  std::vector<Simplex_handle> filtration_vect_;
1209  int dimension_;
1210 };
1211 
1212 // Print a Simplex_tree in os.
1213 template<typename...T>
1214 std::ostream& operator<<(std::ostream & os, Simplex_tree<T...> & st) {
1215  for (auto sh : st.filtration_simplex_range()) {
1216  os << st.dimension(sh) << " ";
1217  for (auto v : st.simplex_vertex_range(sh)) {
1218  os << v << " ";
1219  }
1220  os << st.filtration(sh) << "\n"; // TODO(VR): why adding the key ?? not read ?? << " " << st.key(sh) << " \n";
1221  }
1222  return os;
1223 }
1224 
1225 template<typename...T>
1226 std::istream& operator>>(std::istream & is, Simplex_tree<T...> & st) {
1227  typedef Simplex_tree<T...> ST;
1228  std::vector<typename ST::Vertex_handle> simplex;
1229  typename ST::Filtration_value fil;
1230  int max_dim = -1;
1231  while (read_simplex(is, simplex, fil)) {
1232  // read all simplices in the file as a list of vertices
1233  // Warning : simplex_size needs to be casted in int - Can be 0
1234  int dim = static_cast<int> (simplex.size() - 1);
1235  if (max_dim < dim) {
1236  max_dim = dim;
1237  }
1238  // insert every simplex in the simplex tree
1239  st.insert_simplex(simplex, fil);
1240  simplex.clear();
1241  }
1242  st.set_dimension(max_dim);
1243 
1244  return is;
1245 }
1246 
1252  typedef linear_indexing_tag Indexing_tag;
1253  typedef int Vertex_handle;
1254  typedef double Filtration_value;
1255  typedef std::uint32_t Simplex_key;
1256  static const bool store_key = true;
1257  static const bool store_filtration = true;
1258  static const bool contiguous_vertices = false;
1259 };
1260 
1268  typedef linear_indexing_tag Indexing_tag;
1269  typedef int Vertex_handle;
1270  typedef float Filtration_value;
1271  typedef std::uint32_t Simplex_key;
1272  static const bool store_key = true;
1273  static const bool store_filtration = true;
1274  static const bool contiguous_vertices = true;
1275 };
1276  // end defgroup simplex_tree
1278 
1279 } // namespace Gudhi
1280 
1281 #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:184
Dictionary::iterator Simplex_handle
Handle type to a simplex contained in the simplicial complex represented by the simplex tree...
Definition: Simplex_tree.h:133
bool prune_above_filtration(Filtration_value filtration)
Prune above filtration value given as parameter.
Definition: Simplex_tree.h:1146
void expansion(int max_dim)
Expands the Simplex_tree containing only its one skeleton until dimension max_dim.
Definition: Simplex_tree.h:994
Filtration_simplex_range::const_iterator Filtration_simplex_iterator
Iterator over the simplices of the simplicial complex, ordered by the filtration. ...
Definition: Simplex_tree.h:193
Tag for a linear ordering of simplices.
Definition: indexing_tag.h:32
Simplex Tree data structure for representing simplicial complexes.
Definition: Simplex_tree.h:71
Siblings * self_siblings(SimplexHandle sh)
Definition: Simplex_tree.h:737
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:652
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:723
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
bool operator==(Simplex_tree &st2)
Checks if two simplex trees are equal.
Definition: Simplex_tree.h:353
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:390
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:429
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:159
Simplex_tree_simplex_vertex_iterator< Simplex_tree > Simplex_vertex_iterator
Iterator over the vertices of a simplex.
Definition: Simplex_tree.h:163
Definition: SimplicialComplexForAlpha.h:26
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:441
void print_hasse(std::ostream &os)
Write the hasse diagram of the simplicial complex in os.
Definition: Simplex_tree.h:1076
Key type used as simplex identifier.
Definition: SimplexKey.h:27
Siblings * root()
Definition: Simplex_tree.h:746
Simplex_tree(Simplex_tree &&old)
User-defined move constructor moves the whole tree structure.
Definition: Simplex_tree.h:322
Options::Simplex_key Simplex_key
Key associated to each simplex.
Definition: Simplex_tree.h:82
bool operator!=(Simplex_tree &st2)
Checks if two simplex trees are different.
Definition: Simplex_tree.h:361
bool make_filtration_non_decreasing()
Browse the simplex tree to ensure the filtration is not decreasing. The simplex tree is browsed start...
Definition: Simplex_tree.h:1096
std::vector< Simplex_handle > Filtration_simplex_range
Range over the simplices of the simplicial complex, ordered by the filtration.
Definition: Simplex_tree.h:189
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:246
void initialize_filtration()
Initializes the filtrations, i.e. sort the simplices according to their order in the filtration and i...
Definition: Simplex_tree.h:765
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:504
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:857
Complex_simplex_range complex_simplex_range()
Returns a range over the simplices of the simplicial complex.
Definition: Simplex_tree.h:212
Concept of the template parameter for the class Gudhi::Simplex_tree<SimplexTreeOptions>.
Definition: SimplexTreeOptions.h:27
void assign_filtration(Simplex_handle sh, Filtration_value fv)
Sets the filtration value of a simplex. In debug mode, if sh is a null_simplex.
Definition: Simplex_tree.h:419
std::pair< Simplex_handle, Simplex_handle > endpoints(Simplex_handle sh)
Definition: Simplex_tree.h:730
Boundary_simplex_range boundary_simplex_range(SimplexHandle sh)
Returns a range over the simplices of the boundary of a simplex.
Definition: Simplex_tree.h:280
int dimension() const
Returns an upper bound on the dimension of the simplicial complex.
Definition: Simplex_tree.h:485
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:201
Simplex_vertex_range simplex_vertex_range(Simplex_handle sh)
Returns a range over the vertices of a simplex.
Definition: Simplex_tree.h:259
Options::Vertex_handle Vertex_handle
Type for the vertex handle.
Definition: Simplex_tree.h:86
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:226
boost::iterator_range< Boundary_simplex_iterator > Boundary_simplex_range
Range over the simplices of the boundary of a simplex.
Definition: Simplex_tree.h:173
Cofaces_simplex_range star_simplex_range(const Simplex_handle simplex)
Compute the star of a n simplex.
Definition: Simplex_tree.h:846
void set_dimension(int dimension)
Definition: Simplex_tree.h:751
bool has_children(SimplexHandle sh) const
Returns true if the node in the simplex tree pointed by sh has children.
Definition: Simplex_tree.h:492
Simplex_handle simplex(Simplex_key key) const
Returns the simplex associated to a key.
Definition: Simplex_tree.h:399
int dimension(Simplex_handle sh)
Returns the dimension of a simplex.
Definition: Simplex_tree.h:474
static Simplex_key null_key()
Returns a key different for all keys associated to the simplices of the simplicial complex...
Definition: Simplex_tree.h:435
static Filtration_value filtration(Simplex_handle sh)
Returns the filtration value of a simplex.
Definition: Simplex_tree.h:408
Definition: Simplex_tree.h:1267
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:157
~Simplex_tree()
Destructor; deallocates the whole tree structure.
Definition: Simplex_tree.h:332
size_t num_vertices() const
Returns the number of vertices in the complex.
Definition: Simplex_tree.h:446
void remove_maximal_simplex(Simplex_handle sh)
Remove a maximal simplex.
Definition: Simplex_tree.h:1182
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:452
boost::iterator_range< Complex_simplex_iterator > Complex_simplex_range
Range over the simplices of the simplicial complex.
Definition: Simplex_tree.h:179
Options::Filtration_value Filtration_value
Type for the value of the filtration function.
Definition: Simplex_tree.h:78
Simplex_tree()
Constructs an empty simplex tree.
Definition: Simplex_tree.h:290
Simplex_tree_boundary_simplex_iterator< Simplex_tree > Boundary_simplex_iterator
Iterator over the simplices of the boundary of a simplex.
Definition: Simplex_tree.h:171
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:187
Simplex_tree_complex_simplex_iterator< Simplex_tree > Complex_simplex_iterator
Iterator over the simplices of the simplicial complex.
Definition: Simplex_tree.h:177
void insert_graph(const OneSkeletonGraph &skel_graph)
Inserts a 1-skeleton in an empty Simplex_tree.
Definition: Simplex_tree.h:939
Simplex_tree(const Simplex_tree &simplex_source)
User-defined copy constructor reproduces the whole tree structure.
Definition: Simplex_tree.h:297
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:165
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:623
void rec_copy(Siblings *sib, Siblings *sib_source)
depth first search, inserts simplices when reaching a leaf.
Definition: Simplex_tree.h:307
std::vector< Simplex_handle > Cofaces_simplex_range
Range over the cofaces of a simplex.
Definition: Simplex_tree.h:167
GUDHI  Version 2.0.1  - C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding. Generated on Mon Oct 2 2017 10:20:49 for GUDHI by doxygen 1.8.11