130 typedef typename boost::container::flat_map<Vertex_handle, Node> flat_map;
133 typedef typename boost::container::map<Vertex_handle, Node> map;
134 typedef typename std::conditional<Options::stable_simplex_handles,
136 flat_map>::type Dictionary;
141 struct Key_simplex_base_real {
142 Key_simplex_base_real() : key_(-1) {}
149 struct Key_simplex_base_dummy {
150 Key_simplex_base_dummy() {}
156 struct Extended_filtration_data {
159 Extended_filtration_data() {}
162 : minval(vmin), maxval(vmax)
165 typedef typename std::conditional<Options::store_key, Key_simplex_base_real, Key_simplex_base_dummy>::type
168 struct Filtration_simplex_base_real {
169 Filtration_simplex_base_real() : filt_() {}
181 inline static const Filtration_value inf_ = std::numeric_limits<Filtration_value>::has_infinity
182 ? std::numeric_limits<Filtration_value>::infinity()
184 inline static const Filtration_value minus_inf_ = std::numeric_limits<Filtration_value>::has_infinity
185 ? -std::numeric_limits<Filtration_value>::infinity()
189 struct Filtration_simplex_base_dummy {
190 Filtration_simplex_base_dummy() {}
192 GUDHI_CHECK(f == null_,
"filtration value specified in the constructor for a complex that does not store them");
195 GUDHI_CHECK(f == null_,
"filtration value assigned for a complex that does not store them");
200 inline static const Filtration_value null_{Gudhi::simplex_tree::empty_filtration_value};
203 Filtration_simplex_base_dummy>::type Filtration_simplex_base;
215 typedef typename Dictionary::iterator Dictionary_it;
216 typedef typename Dictionary::const_iterator Dictionary_const_it;
217 typedef typename Dictionary_it::value_type Dit_value_t;
219 struct return_first {
234 using Optimized_star_simplex_range = boost::iterator_range<Optimized_star_simplex_iterator>;
236 class Fast_cofaces_predicate {
241 Fast_cofaces_predicate(
Simplex_tree const* st,
int codim,
int dim)
242 : st_(st), codim_(codim), dim_(codim + dim) {}
243 bool operator()(
const Simplex_handle iter )
const {
248 return dim_ == st_->dimension(iter);
254 using Optimized_cofaces_simplex_filtered_range = boost::filtered_range<Fast_cofaces_predicate,
255 Optimized_star_simplex_range>;
260 static constexpr int max_dimension() {
return 40; }
283 typedef typename std::conditional<Options::link_nodes_by_label,
284 Optimized_cofaces_simplex_filtered_range,
290 using Static_vertex_vector = boost::container::static_vector<
Vertex_handle, max_dimension()>;
338 return Complex_vertex_range(boost::make_transform_iterator(root_.members_.begin(), return_first()),
339 boost::make_transform_iterator(root_.members_.end(), return_first()));
398 return filtration_vect_;
427 template<
class SimplexHandle>
444 template<
class SimplexHandle>
457 root_(nullptr, null_vertex_),
460 dimension_to_be_lowered_(false) {}
477 template<
typename OtherSimplexTreeOptions,
typename F>
478 Simplex_tree(
const Simplex_tree<OtherSimplexTreeOptions>& complex_source, F&& translate_filtration_value) {
480 std::clog <<
"Simplex_tree custom copy constructor" << std::endl;
482 copy_from(complex_source, translate_filtration_value);
490 std::clog <<
"Simplex_tree copy constructor" << std::endl;
492 copy_from(complex_source);
501 std::clog <<
"Simplex_tree move constructor" << std::endl;
503 move_from(complex_source);
508 root_members_recursive_deletion();
514 Simplex_tree&
operator= (
const Simplex_tree& complex_source) {
516 std::clog <<
"Simplex_tree copy assignment" << std::endl;
519 if (&complex_source !=
this) {
521 root_members_recursive_deletion();
523 copy_from(complex_source);
532 Simplex_tree&
operator=(Simplex_tree&& complex_source) {
534 std::clog <<
"Simplex_tree move assignment" << std::endl;
537 if (&complex_source !=
this) {
539 root_members_recursive_deletion();
541 move_from(complex_source);
550 null_vertex_ = complex_source.null_vertex_;
551 filtration_vect_.clear();
552 dimension_ = complex_source.dimension_;
553 dimension_to_be_lowered_ = complex_source.dimension_to_be_lowered_;
554 auto root_source = complex_source.root_;
558 Dictionary(boost::container::ordered_unique_range, root_source.members().begin(), root_source.members().end());
560 for (
auto& map_el : root_.members()) {
561 map_el.second.assign_children(&root_);
564 if constexpr (!std::is_same_v<Simplex_data, No_simplex_data>) {
565 auto dst_iter = root_.members().begin();
566 auto src_iter = root_source.members().begin();
568 while(dst_iter != root_.members().end() || src_iter != root_source.members().end()) {
569 dst_iter->second.data() = src_iter->second.data();
574 assert(dst_iter == root_.members().end());
575 assert(src_iter == root_source.members().end());
577 rec_copy<Options::store_key, true>(
582 template<
typename OtherSimplexTreeOptions,
typename F>
583 void copy_from(
const Simplex_tree<OtherSimplexTreeOptions>& complex_source, F&& translate_filtration_value) {
584 null_vertex_ = complex_source.null_vertex_;
585 filtration_vect_.clear();
586 dimension_ = complex_source.dimension_;
587 dimension_to_be_lowered_ = complex_source.dimension_to_be_lowered_;
588 auto root_source = complex_source.root_;
592 for (
auto& p : root_source.members()){
594 root_.members().try_emplace(
595 root_.members().end(), p.first, &root_, translate_filtration_value(p.second.filtration()), p.second.key());
597 root_.members().try_emplace(
598 root_.members().end(), p.first, &root_, translate_filtration_value(p.second.filtration()));
602 rec_copy<OtherSimplexTreeOptions::store_key, false>(&root_, &root_source, translate_filtration_value);
606 template<
bool store_key,
bool copy_simplex_data,
typename OtherSiblings,
typename F>
607 void rec_copy(
Siblings *sib, OtherSiblings *sib_source, F&& translate_filtration_value) {
608 auto sh_source = sib_source->members().begin();
609 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh, ++sh_source) {
610 update_simplex_tree_after_node_insertion(sh);
614 newsib->members_.reserve(sh_source->second.children()->members().size());
616 for (
auto & child : sh_source->second.children()->members()){
617 Dictionary_it new_it{};
619 new_it = newsib->members_.emplace_hint(
620 newsib->members_.end(),
622 Node(newsib, translate_filtration_value(child.second.filtration()), child.second.key()));
624 new_it = newsib->members_.emplace_hint(newsib->members_.end(),
626 Node(newsib, translate_filtration_value(child.second.filtration())));
629 if constexpr (copy_simplex_data && !std::is_same_v<Simplex_data, No_simplex_data>) {
630 new_it->second.data() = child.second.data();
633 rec_copy<store_key, copy_simplex_data>(newsib, sh_source->second.children(), translate_filtration_value);
634 sh->second.assign_children(newsib);
640 void move_from(Simplex_tree& complex_source) {
641 null_vertex_ = std::move(complex_source.null_vertex_);
642 root_ = std::move(complex_source.root_);
643 filtration_vect_ = std::move(complex_source.filtration_vect_);
644 dimension_ = std::exchange(complex_source.dimension_, -1);
645 dimension_to_be_lowered_ = std::exchange(complex_source.dimension_to_be_lowered_,
false);
647 nodes_label_to_list_.swap(complex_source.nodes_label_to_list_);
650 for (
auto& map_el : root_.members()) {
651 if (map_el.second.children() != &(complex_source.root_)) {
653 map_el.second.children()->oncles_ = &root_;
656 GUDHI_CHECK(map_el.second.children()->oncles_ ==
nullptr,
657 std::invalid_argument(
"Simplex_tree move constructor from an invalid Simplex_tree"));
659 map_el.second.assign_children(&root_);
665 void root_members_recursive_deletion() {
666 for (
auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) {
668 rec_delete(sh->second.children());
671 root_.members().clear();
676 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
678 rec_delete(sh->second.children());
685 template<
typename>
friend class Simplex_tree;
690 template<
class OtherSimplexTreeOptions>
691 bool operator==(
const Simplex_tree<OtherSimplexTreeOptions>& st2)
const {
692 if ((null_vertex_ != st2.null_vertex_) ||
693 (dimension_ != st2.dimension_ && !dimension_to_be_lowered_ && !st2.dimension_to_be_lowered_))
695 return rec_equal(&root_, &st2.root_);
699 template<
class OtherSimplexTreeOptions>
700 bool operator!=(
const Simplex_tree<OtherSimplexTreeOptions>& st2)
const {
701 return (!(*
this == st2));
706 template<
class OtherSiblings>
707 bool rec_equal(Siblings
const* s1, OtherSiblings
const* s2)
const {
708 if (s1->members().size() != s2->members().size())
710 auto sh2 = s2->members().begin();
711 for (
auto sh1 = s1->members().begin();
712 (sh1 != s1->members().end() && sh2 != s2->members().end());
714 if (sh1->first != sh2->first || !(sh1->second.filtration() == sh2->second.filtration()))
720 if (!rec_equal(sh1->second.children(), sh2->second.children()))
732 return sh->second.filtration();
747 return sh->second.key();
757 return filtration_vect_[idx];
767 return sh->second.filtration();
769 return Filtration_simplex_base_real::get_infinity();
778 std::invalid_argument(
"Simplex_tree::assign_filtration - cannot assign filtration on null_simplex"));
779 _to_node_it(sh)->second.assign_filtration(fv);
787 return Dictionary_const_it();
798 std::invalid_argument(
"Simplex_tree::simplex_data - no data associated to null_simplex"));
799 return _to_node_it(sh)->second.data();
805 std::invalid_argument(
"Simplex_tree::simplex_data - no data associated to null_simplex"));
806 return sh->second.data();
817 return root_.members_.size();
822 return root_.members_.empty();
836 auto sib_begin = sib->members().begin();
837 auto sib_end = sib->members().end();
838 size_t simplices_number = sib->members().size();
839 for (
auto sh = sib_begin; sh != sib_end; ++sh) {
844 return simplices_number;
855 while (curr_sib !=
nullptr) {
857 curr_sib = curr_sib->oncles();
868 auto fun = [&res](
Simplex_handle,
int dim) ->
void { ++res[dim]; };
870 if (dimension_to_be_lowered_) {
871 GUDHI_CHECK(res.front() != 0, std::logic_error(
"Bug in Gudhi: non-empty complex has no vertex"));
872 while (res.back() == 0) res.pop_back();
873 dimension_ =
static_cast<int>(res.size()) - 1;
874 dimension_to_be_lowered_ =
false;
876 GUDHI_CHECK(res.back() != 0,
877 std::logic_error(
"Bug in Gudhi: there is no simplex of dimension the dimension of the complex"));
904 if (dimension_to_be_lowered_)
905 lower_upper_bound_dimension();
911 template<
class SimplexHandle>
914 return (sh->second.children()->parent() == sh->first);
923 Siblings
const* children(Simplex_handle sh)
const {
924 GUDHI_CHECK(
has_children(sh), std::invalid_argument(
"Simplex_tree::children - argument has no child"));
925 return sh->second.children();
936 template<
class InputVertexRange = std::initializer_list<Vertex_handle>>
938 auto first = std::begin(s);
939 auto last = std::end(s);
945 std::vector<Vertex_handle> copy(first, last);
946 std::sort(std::begin(copy), std::end(copy));
947 return find_simplex(copy);
952 Simplex_handle find_simplex(
const std::vector<Vertex_handle> &
simplex)
const {
953 Siblings
const* tmp_sib = &root_;
954 Dictionary_const_it tmp_dit;
958 GUDHI_CHECK(contiguous_vertices(),
"non-contiguous vertices");
959 Vertex_handle v = *vi++;
960 if(v < 0 || v >=
static_cast<Vertex_handle
>(root_.members_.size()))
962 tmp_dit = root_.members_.begin() + v;
967 tmp_sib = tmp_dit->second.children();
970 tmp_dit = tmp_sib->members_.find(*vi++);
971 if (tmp_dit == tmp_sib->members_.end())
977 tmp_sib = tmp_dit->second.children();
985 assert(contiguous_vertices());
986 return root_.members_.begin() + v;
988 return root_.members_.find(v);
994 bool contiguous_vertices()
const {
995 if (root_.members_.empty())
return true;
996 if (root_.members_.begin()->first != 0)
return false;
997 if (std::prev(root_.members_.end())->first !=
static_cast<Vertex_handle>(root_.members_.size() - 1))
return false;
1017 template<
bool update_fil,
bool update_children,
bool set_to_null,
class Filt>
1018 std::pair<Dictionary_it, bool> insert_node_(
Siblings *sib,
Vertex_handle v, Filt&& filtration_value) {
1019 std::pair<Dictionary_it, bool> ins = sib->members_.try_emplace(v, sib, std::forward<Filt>(filtration_value));
1021 if constexpr (update_children){
1023 ins.first->second.assign_children(
new Siblings(sib, v));
1029 update_simplex_tree_after_node_insertion(ins.first);
1034 if (
unify_lifetimes(ins.first->second.filtration(), filtration_value))
return ins;
1037 if constexpr (set_to_null){
1038 ins.first = Dictionary_it();
1059 template <
class RandomVertexHandleRange = std::initializer_list<Vertex_handle>>
1060 std::pair<Simplex_handle, bool> insert_simplex_raw(
const RandomVertexHandleRange&
simplex,
1063 std::pair<Dictionary_it, bool> res_insert;
1066 for (; vi != std::prev(
simplex.end()); ++vi) {
1067 GUDHI_CHECK(*vi !=
null_vertex(),
"cannot use the dummy null_vertex() as a real vertex");
1068 res_insert = insert_node_<false, true, false>(curr_sib, *vi,
filtration);
1069 curr_sib = res_insert.first->second.children();
1072 GUDHI_CHECK(*vi !=
null_vertex(),
"cannot use the dummy null_vertex() as a real vertex");
1073 res_insert = insert_node_<true, false, true>(curr_sib, *vi,
filtration);
1074 if (res_insert.second){
1075 int dim =
static_cast<int>(boost::size(
simplex)) - 1;
1076 if (dim > dimension_) {
1108 template<
class InputVertexRange = std::initializer_list<Vertex_handle>>
1111 auto first = std::begin(
simplex);
1112 auto last = std::end(
simplex);
1115 return std::pair<Simplex_handle, bool>(
null_simplex(),
true);
1118 std::vector<Vertex_handle> copy(first, last);
1119 std::sort(std::begin(copy), std::end(copy));
1190 template <
class InputVertexRange = std::initializer_list<Vertex_handle> >
1222 template <
class InputVertexRange = std::initializer_list<Vertex_handle>>
1224 const InputVertexRange& n_simplex)
1229 return Filtration_simplex_base_real::get_infinity();
1231 return Filtration_simplex_base_real::get_minus_infinity();
1235 throw std::invalid_argument(
"Given insertion strategy is not available.");
1263 template <
class InputVertexRange = std::initializer_list<Vertex_handle>>
1266 const InputVertexRange& n_simplex,
1269 auto first = std::begin(n_simplex);
1270 auto last = std::end(n_simplex);
1274 thread_local std::vector<Vertex_handle> copy;
1276 copy.insert(copy.end(), first, last);
1277 std::sort(copy.begin(), copy.end());
1278 auto last_unique = std::unique(copy.begin(), copy.end());
1279 copy.erase(last_unique, copy.end());
1281 GUDHI_CHECK(v !=
null_vertex(),
"cannot use the dummy null_vertex() as a real vertex"););
1283 dimension_ = (std::max)(dimension_,
static_cast<int>(std::distance(copy.begin(), copy.end())) - 1);
1285 if constexpr (Options::store_filtration){
1286 switch (insertion_strategy) {
1288 return _rec_insert_simplex_and_subfaces_sorted(
root(), copy.begin(), copy.end(),
filtration);
1290 return _insert_simplex_and_subfaces_at_highest(
root(), copy.begin(), copy.end(),
filtration);
1292 return _insert_simplex_and_subfaces_forcing_filtration_value(
root(), copy.begin(), copy.end(),
filtration);
1294 throw std::invalid_argument(
"Given insertion strategy is not available.");
1298 return _rec_insert_simplex_and_subfaces_sorted(
root(), copy.begin(), copy.end(),
filtration);
1304 template <
class ForwardVertexIterator,
bool update_fil = true>
1305 std::pair<Simplex_handle, bool> _rec_insert_simplex_and_subfaces_sorted(Siblings* sib,
1306 ForwardVertexIterator first,
1307 ForwardVertexIterator last,
1308 const Filtration_value& filt) {
1313 Vertex_handle vertex_one = *first;
1320 if (++first == last)
return insert_node_<update_fil, false, update_fil>(sib, vertex_one, filt);
1323 auto insertion_result = insert_node_<update_fil, true, false>(sib, vertex_one, filt);
1325 auto res = _rec_insert_simplex_and_subfaces_sorted<ForwardVertexIterator, update_fil>(
1326 insertion_result.first->second.children(), first, last, filt);
1329 _rec_insert_simplex_and_subfaces_sorted<ForwardVertexIterator, update_fil>(sib, first, last, filt);
1333 bool _make_subfiltration_non_decreasing(Simplex_handle sh,
const Filtration_value& filt) {
1334 Filtration_value& f = _to_node_it(sh)->second.filtration();
1335 bool changed =
false;
1337 bool b_changed =
true;
1340 if (filt ==
filtration(sh_b)) b_changed = _make_subfiltration_non_decreasing(sh_b, filt);
1347 template <
class ForwardVertexIterator>
1348 std::pair<Simplex_handle, bool> _insert_simplex_and_subfaces_at_highest(
Siblings* sib,
1349 ForwardVertexIterator first,
1350 ForwardVertexIterator last,
1352 auto res = _rec_insert_simplex_and_subfaces_sorted<ForwardVertexIterator, false>(sib, first, last, filt);
1354 _make_subfiltration_non_decreasing(res.first, filt);
1361 template <
class ForwardVertexIterator>
1362 std::pair<Simplex_handle, bool> _insert_simplex_and_subfaces_forcing_filtration_value(
Siblings* sib,
1363 ForwardVertexIterator first,
1364 ForwardVertexIterator last,
1366 auto res = _rec_insert_simplex_and_subfaces_sorted<ForwardVertexIterator, false>(sib, first, last, filt);
1377 _to_node_it(sh)->second.assign_key(
key);
1385 return { find_vertex(sh->first), find_vertex(
self_siblings(sh)->parent()) };
1389 template<
class SimplexHandle>
1391 if (sh->second.children()->parent() == sh->first)
1392 return sh->second.children()->oncles();
1394 return sh->second.children();
1398 template<
class SimplexHandle>
1402 return const_cast<Siblings*
>(std::as_const(*this).self_siblings(sh));
1421 dimension_to_be_lowered_ = !exact;
1422 dimension_ = dimension;
1433 bool reverse_lexicographic_order(Simplex_handle sh1, Simplex_handle sh2)
const {
1438 while (it1 != rg1.end() && it2 != rg2.end()) {
1446 return ((it1 == rg1.end()) && (it2 != rg2.end()));
1455 struct is_before_in_totally_ordered_filtration {
1456 explicit is_before_in_totally_ordered_filtration(Simplex_tree
const* st)
1461 if (!(sh1->second.filtration() == sh2->second.filtration())) {
1462 return sh1->second.filtration() < sh2->second.filtration();
1465 return st_->reverse_lexicographic_order(sh1, sh2);
1468 Simplex_tree
const* st_;
1486 if (ignore_infinite_values){
1530 template<
typename Comparator,
typename Ignorer>
1532 filtration_vect_.clear();
1535 if (ignore_simplex(sh))
continue;
1536 filtration_vect_.push_back(sh);
1540 tbb::parallel_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration);
1542 std::stable_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration);
1553 if (filtration_vect_.empty()) {
1565 filtration_vect_.clear();
1582 void rec_coface(std::vector<Vertex_handle> &vertices, Siblings
const*curr_sib,
int curr_nbVertices,
1583 std::vector<Simplex_handle>& cofaces,
bool star,
int nbVertices)
const {
1584 if (!(star || curr_nbVertices <= nbVertices))
1586 for (Simplex_handle
simplex = curr_sib->members().begin();
simplex != curr_sib->members().end(); ++
simplex) {
1587 if (vertices.empty()) {
1592 bool addCoface = (star || curr_nbVertices == nbVertices);
1596 rec_coface(vertices,
simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
1598 if (
simplex->first == vertices.back()) {
1600 bool equalDim = (star || curr_nbVertices == nbVertices);
1601 bool addCoface = vertices.size() == 1 && equalDim;
1606 Vertex_handle tmp = vertices.back();
1607 vertices.pop_back();
1608 rec_coface(vertices,
simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
1609 vertices.push_back(tmp);
1611 }
else if (
simplex->first > vertices.back()) {
1616 rec_coface(vertices,
simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
1647 assert(codimension >= 0);
1649 if constexpr (Options::link_nodes_by_label) {
1651 Static_vertex_vector simp(rg.begin(), rg.end());
1653 assert(std::is_sorted(simp.begin(), simp.end(), std::greater<Vertex_handle>()));
1654 auto range = Optimized_star_simplex_range(Optimized_star_simplex_iterator(
this, std::move(simp)),
1655 Optimized_star_simplex_iterator());
1657 Fast_cofaces_predicate select(
this, codimension, this->
dimension(simplex));
1658 return boost::adaptors::filter(range, select);
1662 std::vector<Vertex_handle> copy(rg.begin(), rg.end());
1663 if (codimension +
static_cast<int>(copy.size()) > dimension_ + 1 ||
1664 (codimension == 0 &&
static_cast<int>(copy.size()) > dimension_))
1667 assert(std::is_sorted(copy.begin(), copy.end(), std::greater<Vertex_handle>()));
1668 bool star = codimension == 0;
1669 rec_coface(copy, &root_, 1, cofaces, star, codimension +
static_cast<int>(copy.size()));
1698 template<
class OneSkeletonGraph>
1704 using boost::num_vertices;
1709 if (num_edges(skel_graph) == 0) {
1715 if constexpr (!Options::stable_simplex_handles)
1717 auto verts = vertices(skel_graph) | boost::adaptors::transformed([&](
auto v){
1718 return Dit_value_t(v, Node(&root_, get(vertex_filtration_t(), skel_graph, v))); });
1719 root_.members_.insert(boost::begin(verts), boost::end(verts));
1722 for (Dictionary_it it = boost::begin(root_.members_); it != boost::end(root_.members_); it++) {
1723 update_simplex_tree_after_node_insertion(it);
1726 std::pair<typename boost::graph_traits<OneSkeletonGraph>::edge_iterator,
1727 typename boost::graph_traits<OneSkeletonGraph>::edge_iterator> boost_edges = edges(skel_graph);
1730 for (; boost_edges.first != boost_edges.second; boost_edges.first++) {
1731 auto edge = *(boost_edges.first);
1732 auto u = source(edge, skel_graph);
1733 auto v = target(edge, skel_graph);
1734 if (u == v)
throw std::invalid_argument(
"Self-loops are not simplicial");
1742 if (v < u) std::swap(u, v);
1743 auto sh = _to_node_it(find_vertex(u));
1745 sh->second.assign_children(
new Siblings(&root_, sh->first));
1748 insert_node_<false, false, false>(sh->second.children(), v, get(edge_filtration_t(), skel_graph, edge));
1759 template <
class VertexRange = std::initializer_list<Vertex_handle> >
1761 auto verts = vertices | boost::adaptors::transformed([&](
auto v){
1762 return Dit_value_t(v, Node(&root_, filt)); });
1763 root_.members_.insert(boost::begin(verts), boost::end(verts));
1764 if (dimension_ < 0 && !root_.members_.empty()) dimension_ = 0;
1765 if constexpr (Options::link_nodes_by_label) {
1766 for (
auto sh = root_.members().begin(); sh != root_.members().end(); sh++) {
1768 if (!sh->second.list_max_vertex_hook_.is_linked())
1769 update_simplex_tree_after_node_insertion(sh);
1786 if (max_dimension <= 1)
return;
1788 dimension_ = max_dimension;
1789 for (Dictionary_it root_it = root_.members_.begin();
1790 root_it != root_.members_.end(); ++root_it) {
1792 siblings_expansion(root_it->second.children(), max_dimension - 1);
1795 dimension_ = max_dimension - dimension_;
1836 , std::vector<Simplex_handle>& added_simplices)
1857 static_assert(Options::link_nodes_by_label,
"Options::link_nodes_by_label must be true");
1860 auto res_ins = insert_node_<false, false, false>(&root_, u, fil);
1861 if (res_ins.second) {
1862 added_simplices.push_back(res_ins.first);
1863 if (dimension_ == -1) dimension_ = 0;
1868 if (v < u) { std::swap(u,v); }
1877 auto sh_u = root_.members().find(u);
1878 GUDHI_CHECK(sh_u != root_.members().end() &&
1879 root_.members().find(v) != root_.members().end(),
1880 std::invalid_argument(
1881 "Simplex_tree::insert_edge_as_flag - inserts an edge whose vertices are not in the complex")
1884 sh_u->second.children()->members().find(v) == sh_u->second.children()->members().end(),
1885 std::invalid_argument(
1886 "Simplex_tree::insert_edge_as_flag - inserts an already existing edge")
1891 const auto tmp_dim = dimension_;
1892 auto tmp_max_dim = dimension_;
1897 List_max_vertex* nodes_with_label_u = nodes_by_label(u);
1899 GUDHI_CHECK(nodes_with_label_u !=
nullptr,
1900 "Simplex_tree::insert_edge_as_flag - cannot find the list of Nodes with label u");
1902 for (
auto&& node_as_hook : *nodes_with_label_u)
1904 Node& node_u =
static_cast<Node&
>(node_as_hook);
1907 if (sib_u->members().find(v) != sib_u->members().end()) {
1909 if (dim_max == -1 || curr_dim < dim_max){
1913 node_u.assign_children(
new Siblings(sib_u, u));
1915 dimension_ = dim_max - curr_dim - 1;
1916 compute_punctual_expansion(
1920 dim_max - curr_dim - 1,
1922 dimension_ = dim_max - dimension_;
1923 if (dimension_ > tmp_max_dim) tmp_max_dim = dimension_;
1927 if (tmp_dim <= tmp_max_dim){
1928 dimension_ = tmp_max_dim;
1929 dimension_to_be_lowered_ =
false;
1931 dimension_ = tmp_dim;
1945 void compute_punctual_expansion( Vertex_handle v
1947 ,
const Filtration_value& fil
1949 , std::vector<Simplex_handle>& added_simplices )
1951 auto res_ins_v = sib->members().emplace(v, Node(sib,fil));
1952 added_simplices.push_back(res_ins_v.first);
1953 update_simplex_tree_after_node_insertion(res_ins_v.first);
1961 create_local_expansion( res_ins_v.first
1965 , added_simplices );
1968 for (
auto sh = sib->members().begin(); sh != res_ins_v.first; ++sh)
1970 Simplex_handle root_sh = find_vertex(sh->first);
1972 root_sh->second.children()->members().find(v) != root_sh->second.children()->members().end())
1975 sh->second.assign_children(
new Siblings(sib, sh->first));
1978 compute_punctual_expansion( v
1979 , sh->second.children()
1982 , added_simplices );
1993 void create_local_expansion(
1998 , std::vector<Simplex_handle> &added_simplices)
2001 Dictionary_it next_it = sh_v;
2004 if (dimension_ > k) {
2008 create_expansion<true>(curr_sib, sh_v, next_it, fil_uv, k, &added_simplices);
2020 void siblings_expansion(
2024 , std::vector<Simplex_handle> & added_simplices )
2026 if (dimension_ > k) {
2029 if (k == 0) {
return; }
2030 Dictionary_it next = ++(siblings->members().begin());
2032 for (Dictionary_it s_h = siblings->members().begin();
2033 next != siblings->members().end(); ++s_h, ++next)
2035 create_expansion<true>(siblings, s_h, next, fil, k, &added_simplices);
2041 void siblings_expansion(
Siblings * siblings,
2043 if (k >= 0 && dimension_ > k) {
2048 Dictionary_it next = siblings->members().begin();
2051 for (Dictionary_it s_h = siblings->members().begin();
2052 s_h != siblings->members().end(); ++s_h, ++next)
2054 create_expansion<false>(siblings, s_h, next, s_h->second.filtration(), k);
2062 template<
bool force_filtration_value>
2063 void create_expansion(
Siblings * siblings,
2065 Dictionary_it& next,
2068 std::vector<Simplex_handle>* added_simplices =
nullptr)
2071 thread_local std::vector<std::pair<Vertex_handle, Node> > inter;
2075 intersection<force_filtration_value>(
2078 siblings->members().end(),
2079 root_sh->second.children()->members().begin(),
2080 root_sh->second.children()->members().end(),
2082 if (inter.size() != 0) {
2086 for (
auto it = new_sib->members().begin(); it != new_sib->members().end(); ++it) {
2087 update_simplex_tree_after_node_insertion(it);
2088 if constexpr (force_filtration_value){
2090 added_simplices->push_back(it);
2094 s_h->second.assign_children(new_sib);
2095 if constexpr (force_filtration_value){
2096 siblings_expansion(new_sib, fil, k - 1, *added_simplices);
2098 siblings_expansion(new_sib, k - 1);
2102 s_h->second.assign_children(siblings);
2109 template<
bool force_filtration_value = false>
2110 static void intersection(std::vector<std::pair<Vertex_handle, Node> >& intersection,
2111 Dictionary_const_it begin1, Dictionary_const_it end1,
2112 Dictionary_const_it begin2, Dictionary_const_it end2,
2114 if (begin1 == end1 || begin2 == end2)
2117 if (begin1->first == begin2->first) {
2118 if constexpr (force_filtration_value){
2119 intersection.emplace_back(begin1->first, Node(
nullptr, filtration_));
2124 intersection.emplace_back(begin1->first, Node(
nullptr, filt));
2126 if (++begin1 == end1 || ++begin2 == end2)
2128 }
else if (begin1->first < begin2->first) {
2129 if (++begin1 == end1)
2132 if (++begin2 == end2)
2157 template<
typename Blocker >
2160 for (
auto&
simplex : boost::adaptors::reverse(root_.members())) {
2162 siblings_expansion_with_blockers(
simplex.second.children(), max_dim, max_dim - 1, block_simplex);
2169 template<
typename Blocker >
2170 void siblings_expansion_with_blockers(Siblings* siblings,
int max_dim,
int k, Blocker block_simplex) {
2171 if (dimension_ < max_dim - k) {
2172 dimension_ = max_dim - k;
2177 if (siblings->members().size() < 2)
2180 for (
auto simplex = std::next(siblings->members().rbegin());
simplex != siblings->members().rend();
simplex++) {
2181 std::vector<std::pair<Vertex_handle, Node> > intersection;
2182 for(
auto next = siblings->members().rbegin(); next !=
simplex; next++) {
2183 bool to_be_inserted =
true;
2184 Filtration_value filt =
simplex->second.filtration();
2187 Simplex_handle border_child = find_child(border, next->first);
2189 to_be_inserted=
false;
2194 if (to_be_inserted) {
2195 intersection.emplace_back(next->first, Node(
nullptr, filt));
2198 if (intersection.size() != 0) {
2203 boost::adaptors::reverse(intersection));
2204 simplex->second.assign_children(new_sib);
2205 std::vector<Vertex_handle> blocked_new_sib_vertex_list;
2207 for (
auto new_sib_member = new_sib->members().begin();
2208 new_sib_member != new_sib->members().end();
2210 update_simplex_tree_after_node_insertion(new_sib_member);
2211 bool blocker_result = block_simplex(new_sib_member);
2214 if (blocker_result) {
2215 blocked_new_sib_vertex_list.push_back(new_sib_member->first);
2218 update_simplex_tree_before_node_removal(new_sib_member);
2221 if (blocked_new_sib_vertex_list.size() == new_sib->members().size()) {
2225 simplex->second.assign_children(siblings);
2227 for (
auto& blocked_new_sib_member : blocked_new_sib_vertex_list) {
2228 new_sib->members().erase(blocked_new_sib_member);
2231 siblings_expansion_with_blockers(new_sib, max_dim, k - 1, block_simplex);
2235 simplex->second.assign_children(siblings);
2251 if (child == sh->second.children()->members().end())
2273 os <<
key(b_sh) <<
" ";
2292 if constexpr (std::is_same_v<void,
decltype(fun(sh, dim))>) {
2296 return fun(sh, dim);
2300 rec_for_each_simplex(
root(), 0, f);
2305 void rec_for_each_simplex(
const Siblings* sib,
int dim, Fun&& fun)
const {
2306 Simplex_handle sh = sib->members().end();
2307 GUDHI_CHECK(sh != sib->members().begin(),
"Bug in Gudhi: only the root siblings may be empty");
2311 rec_for_each_simplex(sh->second.children(), dim+1, fun);
2315 while(sh != sib->members().begin());
2326 bool modified =
false;
2327 auto fun = [&modified,
this](
Simplex_handle sh,
int dim) ->
void {
2328 if (dim == 0)
return;
2350 root_members_recursive_deletion();
2353 dimension_to_be_lowered_ =
false;
2354 if constexpr (Options::link_nodes_by_label)
2355 nodes_label_to_list_.clear();
2379 bool rec_prune_above_filtration(Siblings* sib,
const Filtration_value& filt) {
2380 auto&& list = sib->members();
2381 bool modified =
false;
2382 bool emptied =
false;
2383 Simplex_handle last;
2385 auto to_remove = [
this, filt](Dit_value_t&
simplex) {
2388 if (filt <
simplex.second.filtration() || !(
simplex.second.filtration() ==
simplex.second.filtration())) {
2391 dimension_to_be_lowered_ =
true;
2401 for (
auto sh = list.begin(); sh != list.end();) {
2402 if (to_remove(*sh)) {
2403 sh = list.erase(sh);
2409 emptied = (list.empty() && sib !=
root());
2411 last = std::remove_if(list.begin(), list.end(), to_remove);
2412 modified = (last != list.end());
2413 emptied = (last == list.begin() && sib !=
root());
2418 sib->oncles()->members()[sib->parent()].assign_children(sib->oncles());
2421 dimension_to_be_lowered_ =
true;
2439 if (dimension >= dimension_)
2442 bool modified =
false;
2443 if (dimension < 0) {
2445 root_members_recursive_deletion();
2451 modified = rec_prune_above_dimension(
root(), dimension, 0);
2455 dimension_ = dimension;
2462 bool rec_prune_above_dimension(Siblings* sib,
int dim,
int actual_dim) {
2463 bool modified =
false;
2464 auto&& list = sib->members();
2468 if (actual_dim >= dim) {
2469 rec_delete(
simplex.second.children());
2470 simplex.second.assign_children(sib);
2473 modified |= rec_prune_above_dimension(
simplex.second.children(), dim, actual_dim + 1);
2486 bool lower_upper_bound_dimension()
const {
2488 dimension_to_be_lowered_ =
false;
2489 int new_dimension = -1;
2494 std::clog <<
" " << vertex;
2496 std::clog << std::endl;
2500 if (sh_dimension >= dimension_)
2503 new_dimension = (std::max)(new_dimension, sh_dimension);
2505 dimension_ = new_dimension;
2522 std::invalid_argument(
"Simplex_tree::remove_maximal_simplex - argument has children"));
2524 update_simplex_tree_before_node_removal(sh);
2527 Dictionary_it nodeIt = _to_node_it(sh);
2528 Siblings* child = nodeIt->second.children();
2530 if ((child->size() > 1) || (child ==
root())) {
2533 child->erase(nodeIt);
2536 child->oncles()->members().at(child->parent()).assign_children(child->oncles());
2539 dimension_to_be_lowered_ =
true;
2561 const Extended_filtration_data& efd)
const
2563 std::pair<Filtration_value, Extended_simplex_type> p;
2566 if (f >= -2 && f <= -1) {
2567 p.first = minval + (maxval - minval) * (f + 2);
2568 p.second = Extended_simplex_type::UP;
2569 }
else if (f >= 1 && f <= 2) {
2570 p.first = minval - (maxval - minval) * (f - 2);
2571 p.second = Extended_simplex_type::DOWN;
2573 p.first = std::numeric_limits<Filtration_value>::quiet_NaN();
2574 p.second = Extended_simplex_type::EXTRA;
2601 Vertex_handle maxvert = std::numeric_limits<Vertex_handle>::min();
2604 for (
auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) {
2606 minval = std::min(minval, f);
2607 maxval = std::max(maxval, f);
2608 maxvert = std::max(sh->first, maxvert);
2611 GUDHI_CHECK(maxvert < std::numeric_limits<Vertex_handle>::max(), std::invalid_argument(
"Simplex_tree contains a vertex with the largest Vertex_handle"));
2614 Simplex_tree st_copy = *
this;
2617 this->insert_simplex_raw({maxvert}, -3);
2624 std::vector<Vertex_handle> vr;
2627 vr.assign(simplex_range.begin(), simplex_range.end());
2628 auto sh = this->
find(vr);
2631 vr.push_back(maxvert);
2650 return Extended_filtration_data(minval, maxval);
2658 auto filt = filtration_(sh);
2660 if(filtration_(find_vertex(v)) == filt)
2674 auto end = std::end(vertices);
2675 auto vi = std::begin(vertices);
2676 GUDHI_CHECK(vi != end,
"empty simplex");
2679 GUDHI_CHECK(vi != end,
"simplex of dimension 0");
2680 if(std::next(vi) == end)
return sh;
2681 Static_vertex_vector suffix;
2682 suffix.push_back(v0);
2683 auto filt = filtration_(sh);
2687 auto&& children1 = find_vertex(v)->second.children()->members_;
2688 for(
auto w : suffix){
2691 if(filtration_(s) == filt)
2694 suffix.push_back(v);
2705 auto filt = filtration_(sh);
2708 if(filtration_(b) == filt)
2716 &Hooks_simplex_base_link_nodes::list_max_vertex_hook_>
2720 boost::intrusive::constant_time_size<false>> List_max_vertex;
2730 std::unordered_map<Vertex_handle, List_max_vertex> nodes_label_to_list_;
2732 List_max_vertex* nodes_by_label(Vertex_handle v) {
2735 return const_cast<List_max_vertex*
>(std::as_const(*this).nodes_by_label(v));
2738 List_max_vertex
const* nodes_by_label(Vertex_handle v)
const {
2740 auto it_v = nodes_label_to_list_.find(v);
2741 if (it_v != nodes_label_to_list_.end()) {
2742 return &(it_v->second);
2752 static Simplex_handle simplex_handle_from_node(
const Node& node) {
2764 Dictionary_const_it testIt = node.children()->members().begin();
2765 const Node* testNode = &testIt->second;
2766 auto testIIt = testIt.get();
2767 auto testPtr = testIIt.pointed_node();
2769 auto shift = (
const char*)(testNode) - (
const char*)(testPtr);
2772 decltype(testPtr) sh_ptr =
decltype(testPtr)((
const char*)(&node) - shift);
2784 decltype(testIIt) sh_ii;
2786 Dictionary_const_it sh(sh_ii);
2791 return (
Simplex_handle)(boost::intrusive::get_parent_from_member<Dit_value_t>(
const_cast<Node*
>(&node),
2792 &Dit_value_t::second));
2798 friend class Simplex_tree_optimized_cofaces_rooted_subtrees_simplex_iterator<Simplex_tree>;
2803 void update_simplex_tree_after_node_insertion(
Simplex_handle sh) {
2805 std::clog <<
"update_simplex_tree_after_node_insertion" << std::endl;
2809 nodes_label_to_list_[sh->first].push_back(_to_node_it(sh)->second);
2815 void update_simplex_tree_before_node_removal(
Simplex_handle sh) {
2817 std::clog <<
"update_simplex_tree_before_node_removal" << std::endl;
2820 _to_node_it(sh)->second.unlink_hooks();
2821 if (nodes_label_to_list_[sh->first].empty())
2822 nodes_label_to_list_.erase(sh->first);
2836 rec_reset_filtration(&root_,
filtration, min_dim);
2846 void rec_reset_filtration(Siblings * sib,
const Filtration_value& filt_value,
int min_depth) {
2847 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
2848 if (min_depth <= 0) {
2849 sh->second.assign_filtration(filt_value);
2852 rec_reset_filtration(sh->second.children(), filt_value, min_depth - 1);
2857 std::size_t num_simplices_and_filtration_serialization_size(
Siblings const* sib, std::size_t& fv_byte_size)
const {
2858 using namespace Gudhi::simplex_tree;
2860 auto sib_begin = sib->members().begin();
2861 auto sib_end = sib->members().end();
2862 size_t simplices_number = sib->members().size();
2863 for (
auto sh = sib_begin; sh != sib_end; ++sh) {
2865 fv_byte_size += get_serialization_size_of(sh->second.filtration());
2867 simplices_number += num_simplices_and_filtration_serialization_size(sh->second.children(), fv_byte_size);
2870 return simplices_number;
2883 std::size_t get_serialization_size()
const {
2885 std::size_t fv_byte_size = 0;
2886 const std::size_t tree_size = num_simplices_and_filtration_serialization_size(&root_, fv_byte_size);
2887 const std::size_t buffer_byte_size = vh_byte_size + fv_byte_size + tree_size * 2 * vh_byte_size;
2889 std::clog <<
"Gudhi::simplex_tree::get_serialization_size - buffer size = " << buffer_byte_size << std::endl;
2891 return buffer_byte_size;
2927 void serialize(
char* buffer,
const std::size_t buffer_size)
const {
2928 char* buffer_end = rec_serialize(&root_, buffer);
2929 if (
static_cast<std::size_t
>(buffer_end - buffer) != buffer_size)
2930 throw std::invalid_argument(
"Serialization does not match end of buffer");
2935 char* rec_serialize(
Siblings const *sib,
char* buffer)
const {
2937 ptr = serialize_value_to_char_buffer(
static_cast<Vertex_handle>(sib->members().size()), ptr);
2939 std::clog <<
"\n" << sib->members().size() <<
" : ";
2941 for (
auto& map_el : sib->members()) {
2942 ptr = serialize_value_to_char_buffer(map_el.first, ptr);
2944 ptr = serialize_value_to_char_buffer(map_el.second.filtration(), ptr);
2946 std::clog <<
" [ " << map_el.first <<
" | " << map_el.second.filtration() <<
" ] ";
2949 for (
auto& map_el : sib->members()) {
2951 ptr = rec_serialize(map_el.second.children(), ptr);
2953 ptr = serialize_value_to_char_buffer(
static_cast<Vertex_handle>(0), ptr);
2955 std::cout <<
"\n0 : ";
2979 void deserialize(
const char* buffer,
const std::size_t buffer_size) {
2981 return deserialize_value_from_char_buffer(
filtration, ptr);
3008 void deserialize(
const char* buffer,
const std::size_t buffer_size, F&& deserialize_filtration_value) {
3009 GUDHI_CHECK(
num_vertices() == 0, std::logic_error(
"Simplex_tree::deserialize - Simplex_tree must be empty"));
3010 const char* ptr = buffer;
3013 ptr = deserialize_value_from_char_buffer(members_size, ptr);
3014 ptr = rec_deserialize(&root_, members_size, ptr, 0, deserialize_filtration_value);
3015 if (
static_cast<std::size_t
>(ptr - buffer) != buffer_size) {
3016 throw std::invalid_argument(
"Deserialization does not match end of buffer");
3023 const char* rec_deserialize(
Siblings* sib,
3027 [[maybe_unused]] F&& deserialize_filtration_value)
3030 if (members_size > 0) {
3037 ptr = deserialize_value_from_char_buffer(vertex, ptr);
3039 ptr = deserialize_filtration_value(
filtration, ptr);
3043 sib->members_.emplace_hint(sib->members_.end(), vertex, Node(sib,
filtration));
3046 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
3047 update_simplex_tree_after_node_insertion(sh);
3048 ptr = deserialize_value_from_char_buffer(child_size, ptr);
3049 if (child_size > 0) {
3051 sh->second.assign_children(child);
3052 ptr = rec_deserialize(child, child_size, ptr, dim + 1, deserialize_filtration_value);
3055 if (dim > dimension_) {
3072 mutable std::vector<Simplex_handle> filtration_vect_;
3074 mutable int dimension_;
3075 mutable bool dimension_to_be_lowered_;