131 typedef typename boost::container::flat_map<Vertex_handle, Node> flat_map;
134 typedef typename boost::container::map<Vertex_handle, Node> map;
135 typedef typename std::conditional<Options::stable_simplex_handles,
137 flat_map>::type Dictionary;
142 struct Key_simplex_base_real {
143 Key_simplex_base_real() : key_(-1) {}
150 struct Key_simplex_base_dummy {
151 Key_simplex_base_dummy() {}
157 struct Extended_filtration_data {
160 Extended_filtration_data() {}
163 : minval(vmin), maxval(vmax)
166 typedef typename std::conditional<Options::store_key, Key_simplex_base_real, Key_simplex_base_dummy>::type
169 struct Filtration_simplex_base_real {
170 Filtration_simplex_base_real() : filt_() {}
182 inline static const Filtration_value inf_ = std::numeric_limits<Filtration_value>::has_infinity
183 ? std::numeric_limits<Filtration_value>::infinity()
185 inline static const Filtration_value minus_inf_ = std::numeric_limits<Filtration_value>::has_infinity
186 ? -std::numeric_limits<Filtration_value>::infinity()
190 struct Filtration_simplex_base_dummy {
191 Filtration_simplex_base_dummy() {}
193 GUDHI_CHECK(f == null_,
"filtration value specified in the constructor for a complex that does not store them");
196 GUDHI_CHECK(f == null_,
"filtration value assigned for a complex that does not store them");
201 inline static const Filtration_value null_{Gudhi::simplex_tree::empty_filtration_value};
204 Filtration_simplex_base_dummy>::type Filtration_simplex_base;
216 typedef typename Dictionary::iterator Dictionary_it;
217 typedef typename Dictionary::const_iterator Dictionary_const_it;
218 typedef typename Dictionary_it::value_type Dit_value_t;
220 struct return_first {
235 using Optimized_star_simplex_range = boost::iterator_range<Optimized_star_simplex_iterator>;
237 class Fast_cofaces_predicate {
242 Fast_cofaces_predicate(
Simplex_tree const* st,
int codim,
int dim)
243 : st_(st), codim_(codim), dim_(codim + dim) {}
244 bool operator()(
const Simplex_handle iter )
const {
249 return dim_ == st_->dimension(iter);
255 using Optimized_cofaces_simplex_filtered_range = boost::filtered_range<Fast_cofaces_predicate,
256 Optimized_star_simplex_range>;
261 static constexpr int max_dimension() {
return 40; }
284 typedef typename std::conditional<Options::link_nodes_by_label,
285 Optimized_cofaces_simplex_filtered_range,
291 using Static_vertex_vector = boost::container::static_vector<
Vertex_handle, max_dimension()>;
339 return Complex_vertex_range(boost::make_transform_iterator(root_.members_.begin(), return_first()),
340 boost::make_transform_iterator(root_.members_.end(), return_first()));
409 return filtration_vect_;
438 template<
class SimplexHandle>
455 template<
class SimplexHandle>
468 root_(nullptr, null_vertex_),
469 number_of_parameters_(1),
472 dimension_to_be_lowered_(false) {}
489 template<
typename OtherSimplexTreeOptions,
typename F>
490 Simplex_tree(
const Simplex_tree<OtherSimplexTreeOptions>& complex_source, F&& translate_filtration_value) {
492 std::clog <<
"Simplex_tree custom copy constructor" << std::endl;
494 copy_from(complex_source, translate_filtration_value);
502 std::clog <<
"Simplex_tree copy constructor" << std::endl;
504 copy_from(complex_source);
513 std::clog <<
"Simplex_tree move constructor" << std::endl;
515 move_from(complex_source);
520 root_members_recursive_deletion();
526 Simplex_tree&
operator= (
const Simplex_tree& complex_source) {
528 std::clog <<
"Simplex_tree copy assignment" << std::endl;
531 if (&complex_source !=
this) {
533 root_members_recursive_deletion();
535 copy_from(complex_source);
544 Simplex_tree&
operator=(Simplex_tree&& complex_source) {
546 std::clog <<
"Simplex_tree move assignment" << std::endl;
549 if (&complex_source !=
this) {
551 root_members_recursive_deletion();
553 move_from(complex_source);
562 null_vertex_ = complex_source.null_vertex_;
563 filtration_vect_.clear();
564 number_of_parameters_ = complex_source.number_of_parameters_;
565 dimension_ = complex_source.dimension_;
566 dimension_to_be_lowered_ = complex_source.dimension_to_be_lowered_;
567 auto root_source = complex_source.root_;
571 Dictionary(boost::container::ordered_unique_range, root_source.members().begin(), root_source.members().end());
573 for (
auto& map_el : root_.members()) {
574 map_el.second.assign_children(&root_);
577 if constexpr (!std::is_same_v<Simplex_data, No_simplex_data>) {
578 auto dst_iter = root_.members().begin();
579 auto src_iter = root_source.members().begin();
581 while(dst_iter != root_.members().end() || src_iter != root_source.members().end()) {
582 dst_iter->second.data() = src_iter->second.data();
587 assert(dst_iter == root_.members().end());
588 assert(src_iter == root_source.members().end());
590 rec_copy<Options::store_key, true>(
595 template<
typename OtherSimplexTreeOptions,
typename F>
596 void copy_from(
const Simplex_tree<OtherSimplexTreeOptions>& complex_source, F&& translate_filtration_value) {
597 null_vertex_ = complex_source.null_vertex_;
598 filtration_vect_.clear();
599 number_of_parameters_ = complex_source.number_of_parameters_;
600 dimension_ = complex_source.dimension_;
601 dimension_to_be_lowered_ = complex_source.dimension_to_be_lowered_;
602 auto root_source = complex_source.root_;
606 for (
auto& p : root_source.members()){
608 root_.members().try_emplace(
609 root_.members().end(), p.first, &root_, translate_filtration_value(p.second.filtration()), p.second.key());
611 root_.members().try_emplace(
612 root_.members().end(), p.first, &root_, translate_filtration_value(p.second.filtration()));
616 rec_copy<OtherSimplexTreeOptions::store_key, false>(&root_, &root_source, translate_filtration_value);
620 template<
bool store_key,
bool copy_simplex_data,
typename OtherSiblings,
typename F>
621 void rec_copy(
Siblings *sib, OtherSiblings *sib_source, F&& translate_filtration_value) {
622 auto sh_source = sib_source->members().begin();
623 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh, ++sh_source) {
624 update_simplex_tree_after_node_insertion(sh);
628 newsib->members_.reserve(sh_source->second.children()->members().size());
630 for (
auto & child : sh_source->second.children()->members()){
631 Dictionary_it new_it{};
633 new_it = newsib->members_.emplace_hint(
634 newsib->members_.end(),
636 Node(newsib, translate_filtration_value(child.second.filtration()), child.second.key()));
638 new_it = newsib->members_.emplace_hint(newsib->members_.end(),
640 Node(newsib, translate_filtration_value(child.second.filtration())));
643 if constexpr (copy_simplex_data && !std::is_same_v<Simplex_data, No_simplex_data>) {
644 new_it->second.data() = child.second.data();
647 rec_copy<store_key, copy_simplex_data>(newsib, sh_source->second.children(), translate_filtration_value);
648 sh->second.assign_children(newsib);
654 void move_from(Simplex_tree& complex_source) {
655 null_vertex_ = std::move(complex_source.null_vertex_);
656 root_ = std::move(complex_source.root_);
657 filtration_vect_ = std::move(complex_source.filtration_vect_);
658 number_of_parameters_ = std::exchange(complex_source.number_of_parameters_, 1);
659 dimension_ = std::exchange(complex_source.dimension_, -1);
660 dimension_to_be_lowered_ = std::exchange(complex_source.dimension_to_be_lowered_,
false);
662 nodes_label_to_list_.swap(complex_source.nodes_label_to_list_);
665 for (
auto& map_el : root_.members()) {
666 if (map_el.second.children() != &(complex_source.root_)) {
668 map_el.second.children()->oncles_ = &root_;
671 GUDHI_CHECK(map_el.second.children()->oncles_ ==
nullptr,
672 std::invalid_argument(
"Simplex_tree move constructor from an invalid Simplex_tree"));
674 map_el.second.assign_children(&root_);
680 void root_members_recursive_deletion() {
681 for (
auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) {
683 rec_delete(sh->second.children());
686 root_.members().clear();
691 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
693 rec_delete(sh->second.children());
700 template<
typename>
friend class Simplex_tree;
705 template <
class OtherSimplexTreeOptions>
706 bool operator==(
const Simplex_tree<OtherSimplexTreeOptions>& st2)
const {
707 if ((null_vertex_ != st2.null_vertex_) ||
708 (dimension_ != st2.dimension_ && !dimension_to_be_lowered_ && !st2.dimension_to_be_lowered_) ||
709 (number_of_parameters_ != st2.number_of_parameters_))
711 return rec_equal(&root_, &st2.root_);
715 template<
class OtherSimplexTreeOptions>
716 bool operator!=(
const Simplex_tree<OtherSimplexTreeOptions>& st2)
const {
717 return (!(*
this == st2));
722 template<
class OtherSiblings>
723 bool rec_equal(Siblings
const* s1, OtherSiblings
const* s2)
const {
724 if (s1->members().size() != s2->members().size())
726 auto sh2 = s2->members().begin();
727 for (
auto sh1 = s1->members().begin();
728 (sh1 != s1->members().end() && sh2 != s2->members().end());
730 if (sh1->first != sh2->first || !(sh1->second.filtration() == sh2->second.filtration()))
736 if (!rec_equal(sh1->second.children(), sh2->second.children()))
748 return sh->second.filtration();
763 return sh->second.key();
773 return filtration_vect_[idx];
783 return sh->second.filtration();
785 return Filtration_simplex_base_real::get_infinity();
794 std::invalid_argument(
"Simplex_tree::assign_filtration - cannot assign filtration on null_simplex"));
795 _to_node_it(sh)->second.assign_filtration(fv);
803 return Dictionary_const_it();
814 std::invalid_argument(
"Simplex_tree::simplex_data - no data associated to null_simplex"));
815 return _to_node_it(sh)->second.data();
821 std::invalid_argument(
"Simplex_tree::simplex_data - no data associated to null_simplex"));
822 return sh->second.data();
833 return root_.members_.size();
838 return root_.members_.empty();
852 auto sib_begin = sib->members().begin();
853 auto sib_end = sib->members().end();
854 size_t simplices_number = sib->members().size();
855 for (
auto sh = sib_begin; sh != sib_end; ++sh) {
860 return simplices_number;
871 while (curr_sib !=
nullptr) {
873 curr_sib = curr_sib->oncles();
884 auto fun = [&res](
Simplex_handle,
int dim) ->
void { ++res[dim]; };
886 if (dimension_to_be_lowered_) {
887 GUDHI_CHECK(res.front() != 0, std::logic_error(
"Bug in Gudhi: non-empty complex has no vertex"));
888 while (res.back() == 0) res.pop_back();
889 dimension_ =
static_cast<int>(res.size()) - 1;
890 dimension_to_be_lowered_ =
false;
892 GUDHI_CHECK(res.back() != 0,
893 std::logic_error(
"Bug in Gudhi: there is no simplex of dimension the dimension of the complex"));
920 if (dimension_to_be_lowered_)
921 lower_upper_bound_dimension();
931 return number_of_parameters_;
938 number_of_parameters_ = new_number;
946 using ssize_t = std::make_signed_t<std::size_t>;
951 for (
const ssize_t count : dimension_count) {
952 euler += sign * count;
960 template<
class SimplexHandle>
963 return (sh->second.children()->parent() == sh->first);
972 Siblings
const* children(Simplex_handle sh)
const {
973 GUDHI_CHECK(
has_children(sh), std::invalid_argument(
"Simplex_tree::children - argument has no child"));
974 return sh->second.children();
985 template<
class InputVertexRange = std::initializer_list<Vertex_handle>>
987 auto first = std::begin(s);
988 auto last = std::end(s);
994 std::vector<Vertex_handle> copy(first, last);
995 std::sort(std::begin(copy), std::end(copy));
996 return find_simplex(copy);
1001 Simplex_handle find_simplex(
const std::vector<Vertex_handle> &
simplex)
const {
1002 Siblings
const* tmp_sib = &root_;
1003 Dictionary_const_it tmp_dit;
1007 GUDHI_CHECK(contiguous_vertices(),
"non-contiguous vertices");
1008 Vertex_handle v = *vi++;
1009 if(v < 0 || v >=
static_cast<Vertex_handle
>(root_.members_.size()))
1011 tmp_dit = root_.members_.begin() + v;
1016 tmp_sib = tmp_dit->second.children();
1019 tmp_dit = tmp_sib->members_.find(*vi++);
1020 if (tmp_dit == tmp_sib->members_.end())
1026 tmp_sib = tmp_dit->second.children();
1034 assert(contiguous_vertices());
1035 return root_.members_.begin() + v;
1037 return root_.members_.find(v);
1043 bool contiguous_vertices()
const {
1044 if (root_.members_.empty())
return true;
1045 if (root_.members_.begin()->first != 0)
return false;
1046 if (std::prev(root_.members_.end())->first !=
static_cast<Vertex_handle>(root_.members_.size() - 1))
return false;
1066 template<
bool update_fil,
bool update_children,
bool set_to_null,
class Filt>
1067 std::pair<Dictionary_it, bool> insert_node_(
Siblings *sib,
Vertex_handle v, Filt&& filtration_value) {
1068 std::pair<Dictionary_it, bool> ins = sib->members_.try_emplace(v, sib, std::forward<Filt>(filtration_value));
1070 if constexpr (update_children){
1072 ins.first->second.assign_children(
new Siblings(sib, v));
1078 update_simplex_tree_after_node_insertion(ins.first);
1083 if (
unify_lifetimes(ins.first->second.filtration(), filtration_value))
return ins;
1086 if constexpr (set_to_null){
1087 ins.first = Dictionary_it();
1108 template <
class RandomVertexHandleRange = std::initializer_list<Vertex_handle>>
1109 std::pair<Simplex_handle, bool> insert_simplex_raw(
const RandomVertexHandleRange&
simplex,
1112 std::pair<Dictionary_it, bool> res_insert;
1115 for (; vi != std::prev(
simplex.end()); ++vi) {
1116 GUDHI_CHECK(*vi !=
null_vertex(),
"cannot use the dummy null_vertex() as a real vertex");
1117 res_insert = insert_node_<false, true, false>(curr_sib, *vi,
filtration);
1118 curr_sib = res_insert.first->second.children();
1121 GUDHI_CHECK(*vi !=
null_vertex(),
"cannot use the dummy null_vertex() as a real vertex");
1122 res_insert = insert_node_<true, false, true>(curr_sib, *vi,
filtration);
1123 if (res_insert.second){
1124 int dim =
static_cast<int>(boost::size(
simplex)) - 1;
1125 if (dim > dimension_) {
1157 template<
class InputVertexRange = std::initializer_list<Vertex_handle>>
1160 auto first = std::begin(
simplex);
1161 auto last = std::end(
simplex);
1164 return std::pair<Simplex_handle, bool>(
null_simplex(),
true);
1167 std::vector<Vertex_handle> copy(first, last);
1168 std::sort(std::begin(copy), std::end(copy));
1239 template <
class InputVertexRange = std::initializer_list<Vertex_handle> >
1271 template <
class InputVertexRange = std::initializer_list<Vertex_handle>>
1273 const InputVertexRange& n_simplex)
1278 return Filtration_simplex_base_real::get_infinity();
1280 return Filtration_simplex_base_real::get_minus_infinity();
1284 throw std::invalid_argument(
"Given insertion strategy is not available.");
1312 template <
class InputVertexRange = std::initializer_list<Vertex_handle>>
1315 const InputVertexRange& n_simplex,
1318 auto first = std::begin(n_simplex);
1319 auto last = std::end(n_simplex);
1323 thread_local std::vector<Vertex_handle> copy;
1325 copy.insert(copy.end(), first, last);
1326 std::sort(copy.begin(), copy.end());
1327 auto last_unique = std::unique(copy.begin(), copy.end());
1328 copy.erase(last_unique, copy.end());
1330 GUDHI_CHECK(v !=
null_vertex(),
"cannot use the dummy null_vertex() as a real vertex"););
1332 dimension_ = (std::max)(dimension_,
static_cast<int>(std::distance(copy.begin(), copy.end())) - 1);
1334 if constexpr (Options::store_filtration){
1335 switch (insertion_strategy) {
1337 return _rec_insert_simplex_and_subfaces_sorted(
root(), copy.begin(), copy.end(),
filtration);
1339 return _insert_simplex_and_subfaces_at_highest(
root(), copy.begin(), copy.end(),
filtration);
1341 return _insert_simplex_and_subfaces_forcing_filtration_value(
root(), copy.begin(), copy.end(),
filtration);
1343 throw std::invalid_argument(
"Given insertion strategy is not available.");
1347 return _rec_insert_simplex_and_subfaces_sorted(
root(), copy.begin(), copy.end(),
filtration);
1353 template <
class ForwardVertexIterator,
bool update_fil = true>
1354 std::pair<Simplex_handle, bool> _rec_insert_simplex_and_subfaces_sorted(Siblings* sib,
1355 ForwardVertexIterator first,
1356 ForwardVertexIterator last,
1357 const Filtration_value& filt) {
1362 Vertex_handle vertex_one = *first;
1369 if (++first == last)
return insert_node_<update_fil, false, update_fil>(sib, vertex_one, filt);
1372 auto insertion_result = insert_node_<update_fil, true, false>(sib, vertex_one, filt);
1374 auto res = _rec_insert_simplex_and_subfaces_sorted<ForwardVertexIterator, update_fil>(
1375 insertion_result.first->second.children(), first, last, filt);
1378 _rec_insert_simplex_and_subfaces_sorted<ForwardVertexIterator, update_fil>(sib, first, last, filt);
1382 bool _make_subfiltration_non_decreasing(Simplex_handle sh,
const Filtration_value& filt) {
1383 Filtration_value& f = _to_node_it(sh)->second.filtration();
1384 bool changed =
false;
1386 bool b_changed =
true;
1389 if (filt ==
filtration(sh_b)) b_changed = _make_subfiltration_non_decreasing(sh_b, filt);
1396 template <
class ForwardVertexIterator>
1397 std::pair<Simplex_handle, bool> _insert_simplex_and_subfaces_at_highest(
Siblings* sib,
1398 ForwardVertexIterator first,
1399 ForwardVertexIterator last,
1401 auto res = _rec_insert_simplex_and_subfaces_sorted<ForwardVertexIterator, false>(sib, first, last, filt);
1403 _make_subfiltration_non_decreasing(res.first, filt);
1410 template <
class ForwardVertexIterator>
1411 std::pair<Simplex_handle, bool> _insert_simplex_and_subfaces_forcing_filtration_value(
Siblings* sib,
1412 ForwardVertexIterator first,
1413 ForwardVertexIterator last,
1415 auto res = _rec_insert_simplex_and_subfaces_sorted<ForwardVertexIterator, false>(sib, first, last, filt);
1426 _to_node_it(sh)->second.assign_key(
key);
1434 return { find_vertex(sh->first), find_vertex(
self_siblings(sh)->parent()) };
1438 template<
class SimplexHandle>
1440 if (sh->second.children()->parent() == sh->first)
1441 return sh->second.children()->oncles();
1443 return sh->second.children();
1447 template<
class SimplexHandle>
1451 return const_cast<Siblings*
>(std::as_const(*this).self_siblings(sh));
1470 dimension_to_be_lowered_ = !exact;
1471 dimension_ = dimension;
1482 bool reverse_lexicographic_order(Simplex_handle sh1, Simplex_handle sh2)
const {
1487 while (it1 != rg1.end() && it2 != rg2.end()) {
1495 return ((it1 == rg1.end()) && (it2 != rg2.end()));
1504 struct is_before_in_totally_ordered_filtration {
1505 explicit is_before_in_totally_ordered_filtration(Simplex_tree
const* st)
1510 if (!(sh1->second.filtration() == sh2->second.filtration())) {
1511 return sh1->second.filtration() < sh2->second.filtration();
1514 return st_->reverse_lexicographic_order(sh1, sh2);
1517 Simplex_tree
const* st_;
1535 if (ignore_infinite_values){
1579 template<
typename Comparator,
typename Ignorer>
1581 filtration_vect_.clear();
1584 if (ignore_simplex(sh))
continue;
1585 filtration_vect_.push_back(sh);
1589 tbb::parallel_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration);
1591 std::stable_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration);
1602 if (filtration_vect_.empty()) {
1614 filtration_vect_.clear();
1631 void rec_coface(std::vector<Vertex_handle> &vertices, Siblings
const*curr_sib,
int curr_nbVertices,
1632 std::vector<Simplex_handle>& cofaces,
bool star,
int nbVertices)
const {
1633 if (!(star || curr_nbVertices <= nbVertices))
1635 for (Simplex_handle
simplex = curr_sib->members().begin();
simplex != curr_sib->members().end(); ++
simplex) {
1636 if (vertices.empty()) {
1641 bool addCoface = (star || curr_nbVertices == nbVertices);
1645 rec_coface(vertices,
simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
1647 if (
simplex->first == vertices.back()) {
1649 bool equalDim = (star || curr_nbVertices == nbVertices);
1650 bool addCoface = vertices.size() == 1 && equalDim;
1655 Vertex_handle tmp = vertices.back();
1656 vertices.pop_back();
1657 rec_coface(vertices,
simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
1658 vertices.push_back(tmp);
1660 }
else if (
simplex->first > vertices.back()) {
1665 rec_coface(vertices,
simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
1696 assert(codimension >= 0);
1698 if constexpr (Options::link_nodes_by_label) {
1700 Static_vertex_vector simp(rg.begin(), rg.end());
1702 assert(std::is_sorted(simp.begin(), simp.end(), std::greater<Vertex_handle>()));
1703 auto range = Optimized_star_simplex_range(Optimized_star_simplex_iterator(
this, std::move(simp)),
1704 Optimized_star_simplex_iterator());
1706 Fast_cofaces_predicate select(
this, codimension, this->
dimension(simplex));
1707 return boost::adaptors::filter(range, select);
1711 std::vector<Vertex_handle> copy(rg.begin(), rg.end());
1712 if (codimension +
static_cast<int>(copy.size()) > dimension_ + 1 ||
1713 (codimension == 0 &&
static_cast<int>(copy.size()) > dimension_))
1716 assert(std::is_sorted(copy.begin(), copy.end(), std::greater<Vertex_handle>()));
1717 bool star = codimension == 0;
1718 rec_coface(copy, &root_, 1, cofaces, star, codimension +
static_cast<int>(copy.size()));
1747 template<
class OneSkeletonGraph>
1753 using boost::num_vertices;
1758 if (num_edges(skel_graph) == 0) {
1764 if constexpr (!Options::stable_simplex_handles)
1766 auto verts = vertices(skel_graph) | boost::adaptors::transformed([&](
auto v){
1767 return Dit_value_t(v, Node(&root_, get(vertex_filtration_t(), skel_graph, v))); });
1768 root_.members_.insert(boost::begin(verts), boost::end(verts));
1771 for (Dictionary_it it = boost::begin(root_.members_); it != boost::end(root_.members_); it++) {
1772 update_simplex_tree_after_node_insertion(it);
1775 std::pair<typename boost::graph_traits<OneSkeletonGraph>::edge_iterator,
1776 typename boost::graph_traits<OneSkeletonGraph>::edge_iterator> boost_edges = edges(skel_graph);
1779 for (; boost_edges.first != boost_edges.second; boost_edges.first++) {
1780 auto edge = *(boost_edges.first);
1781 auto u = source(edge, skel_graph);
1782 auto v = target(edge, skel_graph);
1783 if (u == v)
throw std::invalid_argument(
"Self-loops are not simplicial");
1791 if (v < u) std::swap(u, v);
1792 auto sh = _to_node_it(find_vertex(u));
1794 sh->second.assign_children(
new Siblings(&root_, sh->first));
1797 insert_node_<false, false, false>(sh->second.children(), v, get(edge_filtration_t(), skel_graph, edge));
1808 template <
class VertexRange = std::initializer_list<Vertex_handle> >
1810 auto verts = vertices | boost::adaptors::transformed([&](
auto v){
1811 return Dit_value_t(v, Node(&root_, filt)); });
1812 root_.members_.insert(boost::begin(verts), boost::end(verts));
1813 if (dimension_ < 0 && !root_.members_.empty()) dimension_ = 0;
1814 if constexpr (Options::link_nodes_by_label) {
1815 for (
auto sh = root_.members().begin(); sh != root_.members().end(); sh++) {
1817 if (!sh->second.list_max_vertex_hook_.is_linked())
1818 update_simplex_tree_after_node_insertion(sh);
1835 if (max_dimension <= 1)
return;
1837 dimension_ = max_dimension;
1838 for (Dictionary_it root_it = root_.members_.begin();
1839 root_it != root_.members_.end(); ++root_it) {
1841 siblings_expansion(root_it->second.children(), max_dimension - 1);
1844 dimension_ = max_dimension - dimension_;
1885 , std::vector<Simplex_handle>& added_simplices)
1906 static_assert(Options::link_nodes_by_label,
"Options::link_nodes_by_label must be true");
1909 auto res_ins = insert_node_<false, false, false>(&root_, u, fil);
1910 if (res_ins.second) {
1911 added_simplices.push_back(res_ins.first);
1912 if (dimension_ == -1) dimension_ = 0;
1917 if (v < u) { std::swap(u,v); }
1926 auto sh_u = root_.members().find(u);
1927 GUDHI_CHECK(sh_u != root_.members().end() &&
1928 root_.members().find(v) != root_.members().end(),
1929 std::invalid_argument(
1930 "Simplex_tree::insert_edge_as_flag - inserts an edge whose vertices are not in the complex")
1933 sh_u->second.children()->members().find(v) == sh_u->second.children()->members().end(),
1934 std::invalid_argument(
1935 "Simplex_tree::insert_edge_as_flag - inserts an already existing edge")
1940 const auto tmp_dim = dimension_;
1941 auto tmp_max_dim = dimension_;
1946 List_max_vertex* nodes_with_label_u = nodes_by_label(u);
1948 GUDHI_CHECK(nodes_with_label_u !=
nullptr,
1949 "Simplex_tree::insert_edge_as_flag - cannot find the list of Nodes with label u");
1951 for (
auto&& node_as_hook : *nodes_with_label_u)
1953 Node& node_u =
static_cast<Node&
>(node_as_hook);
1956 if (sib_u->members().find(v) != sib_u->members().end()) {
1958 if (dim_max == -1 || curr_dim < dim_max){
1962 node_u.assign_children(
new Siblings(sib_u, u));
1964 dimension_ = dim_max - curr_dim - 1;
1965 compute_punctual_expansion(
1969 dim_max - curr_dim - 1,
1971 dimension_ = dim_max - dimension_;
1972 if (dimension_ > tmp_max_dim) tmp_max_dim = dimension_;
1976 if (tmp_dim <= tmp_max_dim){
1977 dimension_ = tmp_max_dim;
1978 dimension_to_be_lowered_ =
false;
1980 dimension_ = tmp_dim;
1994 void compute_punctual_expansion( Vertex_handle v
1996 ,
const Filtration_value& fil
1998 , std::vector<Simplex_handle>& added_simplices )
2000 auto res_ins_v = sib->members().emplace(v, Node(sib,fil));
2001 added_simplices.push_back(res_ins_v.first);
2002 update_simplex_tree_after_node_insertion(res_ins_v.first);
2010 create_local_expansion( res_ins_v.first
2014 , added_simplices );
2017 for (
auto sh = sib->members().begin(); sh != res_ins_v.first; ++sh)
2019 Simplex_handle root_sh = find_vertex(sh->first);
2021 root_sh->second.children()->members().find(v) != root_sh->second.children()->members().end())
2024 sh->second.assign_children(
new Siblings(sib, sh->first));
2027 compute_punctual_expansion( v
2028 , sh->second.children()
2031 , added_simplices );
2042 void create_local_expansion(
2047 , std::vector<Simplex_handle> &added_simplices)
2050 Dictionary_it next_it = sh_v;
2053 if (dimension_ > k) {
2057 create_expansion<true>(curr_sib, sh_v, next_it, fil_uv, k, &added_simplices);
2069 void siblings_expansion(
2073 , std::vector<Simplex_handle> & added_simplices )
2075 if (dimension_ > k) {
2078 if (k == 0) {
return; }
2079 Dictionary_it next = ++(siblings->members().begin());
2081 for (Dictionary_it s_h = siblings->members().begin();
2082 next != siblings->members().end(); ++s_h, ++next)
2084 create_expansion<true>(siblings, s_h, next, fil, k, &added_simplices);
2090 void siblings_expansion(
Siblings * siblings,
2092 if (k >= 0 && dimension_ > k) {
2097 Dictionary_it next = siblings->members().begin();
2100 for (Dictionary_it s_h = siblings->members().begin();
2101 s_h != siblings->members().end(); ++s_h, ++next)
2103 create_expansion<false>(siblings, s_h, next, s_h->second.filtration(), k);
2111 template<
bool force_filtration_value>
2112 void create_expansion(
Siblings * siblings,
2114 Dictionary_it& next,
2117 std::vector<Simplex_handle>* added_simplices =
nullptr)
2120 thread_local std::vector<std::pair<Vertex_handle, Node> > inter;
2124 intersection<force_filtration_value>(
2127 siblings->members().end(),
2128 root_sh->second.children()->members().begin(),
2129 root_sh->second.children()->members().end(),
2131 if (inter.size() != 0) {
2135 for (
auto it = new_sib->members().begin(); it != new_sib->members().end(); ++it) {
2136 update_simplex_tree_after_node_insertion(it);
2137 if constexpr (force_filtration_value){
2139 added_simplices->push_back(it);
2143 s_h->second.assign_children(new_sib);
2144 if constexpr (force_filtration_value){
2145 siblings_expansion(new_sib, fil, k - 1, *added_simplices);
2147 siblings_expansion(new_sib, k - 1);
2151 s_h->second.assign_children(siblings);
2158 template<
bool force_filtration_value = false>
2159 static void intersection(std::vector<std::pair<Vertex_handle, Node> >& intersection,
2160 Dictionary_const_it begin1, Dictionary_const_it end1,
2161 Dictionary_const_it begin2, Dictionary_const_it end2,
2163 if (begin1 == end1 || begin2 == end2)
2166 if (begin1->first == begin2->first) {
2167 if constexpr (force_filtration_value){
2168 intersection.emplace_back(begin1->first, Node(
nullptr, filtration_));
2173 intersection.emplace_back(begin1->first, Node(
nullptr, filt));
2175 if (++begin1 == end1 || ++begin2 == end2)
2177 }
else if (begin1->first < begin2->first) {
2178 if (++begin1 == end1)
2181 if (++begin2 == end2)
2206 template<
typename Blocker >
2209 for (
auto&
simplex : boost::adaptors::reverse(root_.members())) {
2211 siblings_expansion_with_blockers(
simplex.second.children(), max_dim, max_dim - 1, block_simplex);
2218 template<
typename Blocker >
2219 void siblings_expansion_with_blockers(Siblings* siblings,
int max_dim,
int k, Blocker block_simplex) {
2220 if (dimension_ < max_dim - k) {
2221 dimension_ = max_dim - k;
2226 if (siblings->members().size() < 2)
2229 for (
auto simplex = std::next(siblings->members().rbegin());
simplex != siblings->members().rend();
simplex++) {
2230 std::vector<std::pair<Vertex_handle, Node> > intersection;
2231 for(
auto next = siblings->members().rbegin(); next !=
simplex; next++) {
2232 bool to_be_inserted =
true;
2233 Filtration_value filt =
simplex->second.filtration();
2236 Simplex_handle border_child = find_child(border, next->first);
2238 to_be_inserted=
false;
2243 if (to_be_inserted) {
2244 intersection.emplace_back(next->first, Node(
nullptr, filt));
2247 if (intersection.size() != 0) {
2252 boost::adaptors::reverse(intersection));
2253 simplex->second.assign_children(new_sib);
2254 std::vector<Vertex_handle> blocked_new_sib_vertex_list;
2256 for (
auto new_sib_member = new_sib->members().begin();
2257 new_sib_member != new_sib->members().end();
2259 update_simplex_tree_after_node_insertion(new_sib_member);
2260 bool blocker_result = block_simplex(new_sib_member);
2263 if (blocker_result) {
2264 blocked_new_sib_vertex_list.push_back(new_sib_member->first);
2267 update_simplex_tree_before_node_removal(new_sib_member);
2270 if (blocked_new_sib_vertex_list.size() == new_sib->members().size()) {
2274 simplex->second.assign_children(siblings);
2276 for (
auto& blocked_new_sib_member : blocked_new_sib_vertex_list) {
2277 new_sib->members().erase(blocked_new_sib_member);
2280 siblings_expansion_with_blockers(new_sib, max_dim, k - 1, block_simplex);
2284 simplex->second.assign_children(siblings);
2300 if (child == sh->second.children()->members().end())
2322 os <<
key(b_sh) <<
" ";
2341 if constexpr (std::is_same_v<void,
decltype(fun(sh, dim))>) {
2345 return fun(sh, dim);
2349 rec_for_each_simplex(
root(), 0, f);
2354 void rec_for_each_simplex(
const Siblings* sib,
int dim, Fun&& fun)
const {
2355 Simplex_handle sh = sib->members().end();
2356 GUDHI_CHECK(sh != sib->members().begin(),
"Bug in Gudhi: only the root siblings may be empty");
2360 rec_for_each_simplex(sh->second.children(), dim+1, fun);
2364 while(sh != sib->members().begin());
2375 bool modified =
false;
2376 auto fun = [&modified,
this](
Simplex_handle sh,
int dim) ->
void {
2377 if (dim == 0)
return;
2399 root_members_recursive_deletion();
2402 dimension_to_be_lowered_ =
false;
2403 if constexpr (Options::link_nodes_by_label)
2404 nodes_label_to_list_.clear();
2428 bool rec_prune_above_filtration(Siblings* sib,
const Filtration_value& filt) {
2429 auto&& list = sib->members();
2430 bool modified =
false;
2431 bool emptied =
false;
2432 Simplex_handle last;
2434 auto to_remove = [
this, filt](Dit_value_t&
simplex) {
2437 if (filt <
simplex.second.filtration() || !(
simplex.second.filtration() ==
simplex.second.filtration())) {
2440 dimension_to_be_lowered_ =
true;
2450 for (
auto sh = list.begin(); sh != list.end();) {
2451 if (to_remove(*sh)) {
2452 sh = list.erase(sh);
2458 emptied = (list.empty() && sib !=
root());
2460 last = std::remove_if(list.begin(), list.end(), to_remove);
2461 modified = (last != list.end());
2462 emptied = (last == list.begin() && sib !=
root());
2467 sib->oncles()->members()[sib->parent()].assign_children(sib->oncles());
2470 dimension_to_be_lowered_ =
true;
2488 if (dimension >= dimension_)
2491 bool modified =
false;
2492 if (dimension < 0) {
2494 root_members_recursive_deletion();
2500 modified = rec_prune_above_dimension(
root(), dimension, 0);
2504 dimension_ = dimension;
2511 bool rec_prune_above_dimension(Siblings* sib,
int dim,
int actual_dim) {
2512 bool modified =
false;
2513 auto&& list = sib->members();
2517 if (actual_dim >= dim) {
2518 rec_delete(
simplex.second.children());
2519 simplex.second.assign_children(sib);
2522 modified |= rec_prune_above_dimension(
simplex.second.children(), dim, actual_dim + 1);
2535 bool lower_upper_bound_dimension()
const {
2537 dimension_to_be_lowered_ =
false;
2538 int new_dimension = -1;
2543 std::clog <<
" " << vertex;
2545 std::clog << std::endl;
2549 if (sh_dimension >= dimension_)
2552 new_dimension = (std::max)(new_dimension, sh_dimension);
2554 dimension_ = new_dimension;
2571 std::invalid_argument(
"Simplex_tree::remove_maximal_simplex - argument has children"));
2573 update_simplex_tree_before_node_removal(sh);
2576 Dictionary_it nodeIt = _to_node_it(sh);
2577 Siblings* child = nodeIt->second.children();
2579 if ((child->size() > 1) || (child ==
root())) {
2582 child->erase(nodeIt);
2585 child->oncles()->members().at(child->parent()).assign_children(child->oncles());
2588 dimension_to_be_lowered_ =
true;
2610 const Extended_filtration_data& efd)
const
2612 std::pair<Filtration_value, Extended_simplex_type> p;
2615 if (f >= -2 && f <= -1) {
2616 p.first = minval + (maxval - minval) * (f + 2);
2617 p.second = Extended_simplex_type::UP;
2618 }
else if (f >= 1 && f <= 2) {
2619 p.first = minval - (maxval - minval) * (f - 2);
2620 p.second = Extended_simplex_type::DOWN;
2622 p.first = std::numeric_limits<Filtration_value>::quiet_NaN();
2623 p.second = Extended_simplex_type::EXTRA;
2650 Vertex_handle maxvert = std::numeric_limits<Vertex_handle>::min();
2652 Filtration_value maxval = Filtration_simplex_base_real::get_minus_infinity();
2653 for (
auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) {
2655 minval = std::min(minval, f);
2656 maxval = std::max(maxval, f);
2657 maxvert = std::max(sh->first, maxvert);
2660 GUDHI_CHECK(maxvert < std::numeric_limits<Vertex_handle>::max(), std::invalid_argument(
"Simplex_tree contains a vertex with the largest Vertex_handle"));
2663 Simplex_tree st_copy = *
this;
2666 this->insert_simplex_raw({maxvert}, -3);
2673 std::vector<Vertex_handle> vr;
2676 vr.assign(simplex_range.begin(), simplex_range.end());
2677 auto sh = this->
find(vr);
2680 vr.push_back(maxvert);
2699 return Extended_filtration_data(minval, maxval);
2707 auto filt = filtration_(sh);
2709 if(filtration_(find_vertex(v)) == filt)
2723 auto end = std::end(vertices);
2724 auto vi = std::begin(vertices);
2725 GUDHI_CHECK(vi != end,
"empty simplex");
2728 GUDHI_CHECK(vi != end,
"simplex of dimension 0");
2729 if(std::next(vi) == end)
return sh;
2730 Static_vertex_vector suffix;
2731 suffix.push_back(v0);
2732 auto filt = filtration_(sh);
2736 auto&& children1 = find_vertex(v)->second.children()->members_;
2737 for(
auto w : suffix){
2740 if(filtration_(s) == filt)
2743 suffix.push_back(v);
2754 auto filt = filtration_(sh);
2757 if(filtration_(b) == filt)
2765 &Hooks_simplex_base_link_nodes::list_max_vertex_hook_>
2769 boost::intrusive::constant_time_size<false>> List_max_vertex;
2779 std::unordered_map<Vertex_handle, List_max_vertex> nodes_label_to_list_;
2781 List_max_vertex* nodes_by_label(Vertex_handle v) {
2784 return const_cast<List_max_vertex*
>(std::as_const(*this).nodes_by_label(v));
2787 List_max_vertex
const* nodes_by_label(Vertex_handle v)
const {
2789 auto it_v = nodes_label_to_list_.find(v);
2790 if (it_v != nodes_label_to_list_.end()) {
2791 return &(it_v->second);
2801 static Simplex_handle simplex_handle_from_node(
const Node& node) {
2813 Dictionary_const_it testIt = node.children()->members().begin();
2814 const Node* testNode = &testIt->second;
2815 auto testIIt = testIt.get();
2816 auto testPtr = testIIt.pointed_node();
2818 auto shift = (
const char*)(testNode) - (
const char*)(testPtr);
2821 decltype(testPtr) sh_ptr =
decltype(testPtr)((
const char*)(&node) - shift);
2833 decltype(testIIt) sh_ii;
2835 Dictionary_const_it sh(sh_ii);
2840 return (
Simplex_handle)(boost::intrusive::get_parent_from_member<Dit_value_t>(
const_cast<Node*
>(&node),
2841 &Dit_value_t::second));
2847 friend class Simplex_tree_optimized_cofaces_rooted_subtrees_simplex_iterator<Simplex_tree>;
2852 void update_simplex_tree_after_node_insertion(
Simplex_handle sh) {
2854 std::clog <<
"update_simplex_tree_after_node_insertion" << std::endl;
2858 nodes_label_to_list_[sh->first].push_back(_to_node_it(sh)->second);
2864 void update_simplex_tree_before_node_removal(
Simplex_handle sh) {
2866 std::clog <<
"update_simplex_tree_before_node_removal" << std::endl;
2869 _to_node_it(sh)->second.unlink_hooks();
2870 if (nodes_label_to_list_[sh->first].empty())
2871 nodes_label_to_list_.erase(sh->first);
2885 rec_reset_filtration(&root_,
filtration, min_dim);
2895 void rec_reset_filtration(Siblings * sib,
const Filtration_value& filt_value,
int min_depth) {
2896 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
2897 if (min_depth <= 0) {
2898 sh->second.assign_filtration(filt_value);
2901 rec_reset_filtration(sh->second.children(), filt_value, min_depth - 1);
2906 std::size_t num_simplices_and_filtration_serialization_size(
Siblings const* sib, std::size_t& fv_byte_size)
const {
2907 using namespace Gudhi::simplex_tree;
2909 auto sib_begin = sib->members().begin();
2910 auto sib_end = sib->members().end();
2911 size_t simplices_number = sib->members().size();
2912 for (
auto sh = sib_begin; sh != sib_end; ++sh) {
2914 fv_byte_size += get_serialization_size_of(sh->second.filtration());
2916 simplices_number += num_simplices_and_filtration_serialization_size(sh->second.children(), fv_byte_size);
2919 return simplices_number;
2932 std::size_t get_serialization_size()
const {
2933 const std::size_t version_byte_size =
sizeof(std::int16_t);
2934 const std::size_t np_byte_size =
sizeof(
decltype(number_of_parameters_));
2936 std::size_t fv_byte_size = 0;
2937 const std::size_t tree_size = num_simplices_and_filtration_serialization_size(&root_, fv_byte_size);
2938 const std::size_t buffer_byte_size =
2939 version_byte_size + np_byte_size + vh_byte_size + fv_byte_size + tree_size * 2 * vh_byte_size;
2941 std::clog <<
"Gudhi::simplex_tree::get_serialization_size - buffer size = " << buffer_byte_size << std::endl;
2943 return buffer_byte_size;
2979 void serialize(
char* buffer,
const std::size_t buffer_size)
const {
2980 char* buffer_end = serialize_value_to_char_buffer(SERIALIZATION_VERSION, buffer);
2981 buffer_end = serialize_value_to_char_buffer(number_of_parameters_, buffer_end);
2982 buffer_end = rec_serialize(&root_, buffer_end);
2983 if (
static_cast<std::size_t
>(buffer_end - buffer) != buffer_size)
2984 throw std::invalid_argument(
"Serialization does not match end of buffer");
2989 char* rec_serialize(
Siblings const *sib,
char* buffer)
const {
2991 ptr = serialize_value_to_char_buffer(
static_cast<Vertex_handle>(sib->members().size()), ptr);
2993 std::clog <<
"\n" << sib->members().size() <<
" : ";
2995 for (
auto& map_el : sib->members()) {
2996 ptr = serialize_value_to_char_buffer(map_el.first, ptr);
2998 ptr = serialize_value_to_char_buffer(map_el.second.filtration(), ptr);
3000 std::clog <<
" [ " << map_el.first <<
" | " << map_el.second.filtration() <<
" ] ";
3003 for (
auto& map_el : sib->members()) {
3005 ptr = rec_serialize(map_el.second.children(), ptr);
3007 ptr = serialize_value_to_char_buffer(
static_cast<Vertex_handle>(0), ptr);
3009 std::cout <<
"\n0 : ";
3035 void deserialize(
const char* buffer,
const std::size_t buffer_size) {
3037 return deserialize_value_from_char_buffer(
filtration, ptr);
3066 void deserialize(
const char* buffer,
const std::size_t buffer_size, F&& deserialize_filtration_value) {
3067 GUDHI_CHECK(
num_vertices() == 0, std::logic_error(
"Simplex_tree::deserialize - Simplex_tree must be empty"));
3068 const char* ptr = buffer;
3069 std::int16_t version;
3070 ptr = deserialize_value_from_char_buffer(version, ptr);
3071 if (version != SERIALIZATION_VERSION) {
3072 throw std::invalid_argument(
"The buffer comes from an non-compatible serialization version of the simplex tree.");
3074 ptr = deserialize_value_from_char_buffer(number_of_parameters_, ptr);
3077 ptr = deserialize_value_from_char_buffer(members_size, ptr);
3078 ptr = rec_deserialize(&root_, members_size, ptr, 0, deserialize_filtration_value);
3079 if (
static_cast<std::size_t
>(ptr - buffer) != buffer_size) {
3080 throw std::invalid_argument(
"Deserialization does not match end of buffer");
3087 const char* rec_deserialize(
Siblings* sib,
3091 [[maybe_unused]] F&& deserialize_filtration_value)
3094 if (members_size > 0) {
3101 ptr = deserialize_value_from_char_buffer(vertex, ptr);
3103 ptr = deserialize_filtration_value(
filtration, ptr);
3107 sib->members_.emplace_hint(sib->members_.end(), vertex, Node(sib,
filtration));
3110 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
3111 update_simplex_tree_after_node_insertion(sh);
3112 ptr = deserialize_value_from_char_buffer(child_size, ptr);
3113 if (child_size > 0) {
3115 sh->second.assign_children(child);
3116 ptr = rec_deserialize(child, child_size, ptr, dim + 1, deserialize_filtration_value);
3119 if (dim > dimension_) {
3129 friend std::ostream& operator<<(std::ostream& os,
const Simplex_tree& st) {
3141 friend std::istream& operator>>(std::istream & is, Simplex_tree & st) {
3142 std::vector<Vertex_handle>
simplex;
3148 int dim =
static_cast<int> (
simplex.size() - 1);
3149 if (max_dim < dim) {
3165 int number_of_parameters_;
3170 mutable std::vector<Simplex_handle> filtration_vect_;
3172 mutable int dimension_;
3173 mutable bool dimension_to_be_lowered_;
3178 static constexpr std::int16_t SERIALIZATION_VERSION = 1;