127 typedef typename boost::container::flat_map<Vertex_handle, Node> flat_map;
130 typedef typename boost::container::map<Vertex_handle, Node> map;
131 typedef typename std::conditional<Options::stable_simplex_handles,
133 flat_map>::type Dictionary;
140 struct Key_simplex_base_real {
141 Key_simplex_base_real() : key_(-1) {}
148 struct Key_simplex_base_dummy {
149 Key_simplex_base_dummy() {}
155 struct Extended_filtration_data {
158 Extended_filtration_data(){}
161 typedef typename std::conditional<Options::store_key, Key_simplex_base_real, Key_simplex_base_dummy>::type
164 struct Filtration_simplex_base_real {
165 Filtration_simplex_base_real() : filt_(0) {}
172 struct Filtration_simplex_base_dummy {
173 Filtration_simplex_base_dummy() {}
175 GUDHI_CHECK(f == 0,
"filtration value specified for a complex that does not store them");
178 GUDHI_CHECK(f == 0,
"filtration value specified for a complex that does not store them");
183 Filtration_simplex_base_dummy>::type Filtration_simplex_base;
195 typedef typename Dictionary::iterator Dictionary_it;
196 typedef typename Dictionary::const_iterator Dictionary_const_it;
197 typedef typename Dictionary_it::value_type Dit_value_t;
199 struct return_first {
214 using Optimized_star_simplex_range = boost::iterator_range<Optimized_star_simplex_iterator>;
216 class Fast_cofaces_predicate {
221 Fast_cofaces_predicate(
Simplex_tree const* st,
int codim,
int dim)
222 : st_(st), codim_(codim), dim_(codim + dim) {}
223 bool operator()(
const Simplex_handle iter )
const {
228 return dim_ == st_->dimension(iter);
234 using Optimized_cofaces_simplex_filtered_range = boost::filtered_range<Fast_cofaces_predicate,
235 Optimized_star_simplex_range>;
240 static constexpr int max_dimension() {
return 40; }
263 typedef typename std::conditional<Options::link_nodes_by_label,
264 Optimized_cofaces_simplex_filtered_range,
270 using Static_vertex_vector = boost::container::static_vector<
Vertex_handle, max_dimension()>;
312 return Complex_vertex_range(boost::make_transform_iterator(root_.members_.begin(), return_first()),
313 boost::make_transform_iterator(root_.members_.end(), return_first()));
360 return filtration_vect_;
389 template<
class SimplexHandle>
406 template<
class SimplexHandle>
419 root_(nullptr, null_vertex_),
438 template<
typename OtherSimplexTreeOptions,
typename F>
439 Simplex_tree(
const Simplex_tree<OtherSimplexTreeOptions>& complex_source, F&& translate_filtration_value) {
441 std::clog <<
"Simplex_tree custom copy constructor" << std::endl;
443 copy_from(complex_source, translate_filtration_value);
451 std::clog <<
"Simplex_tree copy constructor" << std::endl;
453 copy_from(complex_source);
462 std::clog <<
"Simplex_tree move constructor" << std::endl;
464 move_from(complex_source);
468 complex_source.dimension_ = -1;
473 root_members_recursive_deletion();
479 Simplex_tree&
operator= (
const Simplex_tree& complex_source) {
481 std::clog <<
"Simplex_tree copy assignment" << std::endl;
484 if (&complex_source !=
this) {
486 root_members_recursive_deletion();
488 copy_from(complex_source);
497 Simplex_tree&
operator=(Simplex_tree&& complex_source) {
499 std::clog <<
"Simplex_tree move assignment" << std::endl;
502 if (&complex_source !=
this) {
504 root_members_recursive_deletion();
506 move_from(complex_source);
515 null_vertex_ = complex_source.null_vertex_;
516 filtration_vect_.clear();
517 dimension_ = complex_source.dimension_;
518 auto root_source = complex_source.root_;
522 Dictionary(boost::container::ordered_unique_range, root_source.members().begin(), root_source.members().end());
524 for (
auto& map_el : root_.members()) {
525 map_el.second.assign_children(&root_);
528 if constexpr (!std::is_same_v<Simplex_data, No_simplex_data>) {
529 auto dst_iter = root_.members().begin();
530 auto src_iter = root_source.members().begin();
532 while(dst_iter != root_.members().end() || src_iter != root_source.members().end()) {
533 dst_iter->second.data() = src_iter->second.data();
538 assert(dst_iter == root_.members().end());
539 assert(src_iter == root_source.members().end());
541 rec_copy<Options::store_key, true>(
546 template<
typename OtherSimplexTreeOptions,
typename F>
547 void copy_from(
const Simplex_tree<OtherSimplexTreeOptions>& complex_source, F&& translate_filtration_value) {
548 null_vertex_ = complex_source.null_vertex_;
549 filtration_vect_.clear();
550 dimension_ = complex_source.dimension_;
551 auto root_source = complex_source.root_;
555 for (
auto& p : root_source.members()){
557 auto it = root_.members().try_emplace(
558 root_.members().end(), p.first, &root_, translate_filtration_value(p.second.filtration()), p.second.key());
560 auto it = root_.members().try_emplace(
561 root_.members().end(), p.first, &root_, translate_filtration_value(p.second.filtration()));
565 rec_copy<OtherSimplexTreeOptions::store_key, false>(&root_, &root_source, translate_filtration_value);
569 template<
bool store_key,
bool copy_simplex_data,
typename OtherSiblings,
typename F>
570 void rec_copy(
Siblings *sib, OtherSiblings *sib_source, F&& translate_filtration_value) {
571 auto sh_source = sib_source->members().begin();
572 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh, ++sh_source) {
573 update_simplex_tree_after_node_insertion(sh);
577 newsib->members_.reserve(sh_source->second.children()->members().size());
579 for (
auto & child : sh_source->second.children()->members()){
580 Dictionary_it new_it{};
582 new_it = newsib->members_.emplace_hint(
583 newsib->members_.end(),
585 Node(newsib, translate_filtration_value(child.second.filtration()), child.second.key()));
587 new_it = newsib->members_.emplace_hint(newsib->members_.end(),
589 Node(newsib, translate_filtration_value(child.second.filtration())));
592 if constexpr (copy_simplex_data && !std::is_same_v<Simplex_data, No_simplex_data>) {
593 new_it->second.data() = child.second.data();
596 rec_copy<store_key, copy_simplex_data>(newsib, sh_source->second.children(), translate_filtration_value);
597 sh->second.assign_children(newsib);
603 void move_from(Simplex_tree& complex_source) {
604 null_vertex_ = std::move(complex_source.null_vertex_);
605 root_ = std::move(complex_source.root_);
606 filtration_vect_ = std::move(complex_source.filtration_vect_);
607 dimension_ = complex_source.dimension_;
609 nodes_label_to_list_.swap(complex_source.nodes_label_to_list_);
612 for (
auto& map_el : root_.members()) {
613 if (map_el.second.children() != &(complex_source.root_)) {
615 map_el.second.children()->oncles_ = &root_;
618 GUDHI_CHECK(map_el.second.children()->oncles_ ==
nullptr,
619 std::invalid_argument(
"Simplex_tree move constructor from an invalid Simplex_tree"));
621 map_el.second.assign_children(&root_);
627 void root_members_recursive_deletion() {
628 for (
auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) {
630 rec_delete(sh->second.children());
633 root_.members().clear();
638 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
640 rec_delete(sh->second.children());
647 template<
typename>
friend class Simplex_tree;
652 template<
class OtherSimplexTreeOptions>
653 bool operator==(
const Simplex_tree<OtherSimplexTreeOptions>& st2)
const {
654 if ((null_vertex_ != st2.null_vertex_) ||
655 (dimension_ != st2.dimension_ && !dimension_to_be_lowered_ && !st2.dimension_to_be_lowered_))
657 return rec_equal(&root_, &st2.root_);
661 template<
class OtherSimplexTreeOptions>
662 bool operator!=(
const Simplex_tree<OtherSimplexTreeOptions>& st2)
const {
663 return (!(*
this == st2));
668 template<
class OtherSiblings>
669 bool rec_equal(Siblings
const* s1, OtherSiblings
const* s2)
const {
670 if (s1->members().size() != s2->members().size())
672 auto sh2 = s2->members().begin();
673 for (
auto sh1 = s1->members().begin();
674 (sh1 != s1->members().end() && sh2 != s2->members().end());
676 if (sh1->first != sh2->first || sh1->second.filtration() != sh2->second.filtration())
682 if (!rec_equal(sh1->second.children(), sh2->second.children()))
694 return sh->second.filtration();
709 return sh->second.key();
719 return filtration_vect_[idx];
729 return sh->second.filtration();
731 return std::numeric_limits<Filtration_value>::infinity();
740 std::invalid_argument(
"Simplex_tree::assign_filtration - cannot assign filtration on null_simplex"));
741 _to_node_it(sh)->second.assign_filtration(fv);
749 return Dictionary_const_it();
760 std::invalid_argument(
"Simplex_tree::simplex_data - no data associated to null_simplex"));
761 return _to_node_it(sh)->second.data();
767 std::invalid_argument(
"Simplex_tree::simplex_data - no data associated to null_simplex"));
768 return sh->second.data();
779 return root_.members_.size();
784 return root_.members_.empty();
798 auto sib_begin = sib->members().begin();
799 auto sib_end = sib->members().end();
800 size_t simplices_number = sib->members().size();
801 for (
auto sh = sib_begin; sh != sib_end; ++sh) {
806 return simplices_number;
817 while (curr_sib !=
nullptr) {
819 curr_sib = curr_sib->oncles();
830 auto fun = [&res](
Simplex_handle,
int dim) ->
void { ++res[dim]; };
832 if (dimension_to_be_lowered_) {
833 GUDHI_CHECK(res.front() != 0, std::logic_error(
"Bug in Gudhi: non-empty complex has no vertex"));
834 while (res.back() == 0) res.pop_back();
835 dimension_ =
static_cast<int>(res.size()) - 1;
836 dimension_to_be_lowered_ =
false;
838 GUDHI_CHECK(res.back() != 0,
839 std::logic_error(
"Bug in Gudhi: there is no simplex of dimension the dimension of the complex"));
866 if (dimension_to_be_lowered_)
867 lower_upper_bound_dimension();
873 template<
class SimplexHandle>
876 return (sh->second.children()->parent() == sh->first);
885 Siblings
const* children(Simplex_handle sh)
const {
886 GUDHI_CHECK(
has_children(sh), std::invalid_argument(
"Simplex_tree::children - argument has no child"));
887 return sh->second.children();
898 template<
class InputVertexRange = std::initializer_list<Vertex_handle>>
900 auto first = std::begin(s);
901 auto last = std::end(s);
907 std::vector<Vertex_handle> copy(first, last);
908 std::sort(std::begin(copy), std::end(copy));
909 return find_simplex(copy);
914 Simplex_handle find_simplex(
const std::vector<Vertex_handle> &
simplex)
const {
915 Siblings
const* tmp_sib = &root_;
916 Dictionary_const_it tmp_dit;
920 GUDHI_CHECK(contiguous_vertices(),
"non-contiguous vertices");
921 Vertex_handle v = *vi++;
922 if(v < 0 || v >=
static_cast<Vertex_handle
>(root_.members_.size()))
924 tmp_dit = root_.members_.begin() + v;
929 tmp_sib = tmp_dit->second.children();
932 tmp_dit = tmp_sib->members_.find(*vi++);
933 if (tmp_dit == tmp_sib->members_.end())
939 tmp_sib = tmp_dit->second.children();
947 assert(contiguous_vertices());
948 return root_.members_.begin() + v;
950 return root_.members_.find(v);
956 bool contiguous_vertices()
const {
957 if (root_.members_.empty())
return true;
958 if (root_.members_.begin()->first != 0)
return false;
959 if (std::prev(root_.members_.end())->first !=
static_cast<Vertex_handle>(root_.members_.size() - 1))
return false;
978 template <
class RandomVertexHandleRange = std::initializer_list<Vertex_handle>>
979 std::pair<Simplex_handle, bool> insert_simplex_raw(
const RandomVertexHandleRange&
simplex,
982 std::pair<Dictionary_it, bool> res_insert;
984 for (; vi != std::prev(
simplex.end()); ++vi) {
985 GUDHI_CHECK(*vi !=
null_vertex(),
"cannot use the dummy null_vertex() as a real vertex");
986 res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib,
filtration));
987 if (res_insert.second) {
989 update_simplex_tree_after_node_insertion(res_insert.first);
992 res_insert.first->second.assign_children(
new Siblings(curr_sib, *vi));
994 curr_sib = res_insert.first->second.children();
996 GUDHI_CHECK(*vi !=
null_vertex(),
"cannot use the dummy null_vertex() as a real vertex");
997 res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib,
filtration));
998 if (!res_insert.second) {
1000 if (res_insert.first->second.filtration() >
filtration) {
1002 res_insert.first->second.assign_filtration(
filtration);
1006 return std::pair<Simplex_handle, bool>(
null_simplex(),
false);
1009 update_simplex_tree_after_node_insertion(res_insert.first);
1012 int dim =
static_cast<int>(boost::size(
simplex)) - 1;
1013 if (dim > dimension_) {
1044 template<
class InputVertexRange = std::initializer_list<Vertex_handle>>
1047 auto first = std::begin(
simplex);
1048 auto last = std::end(
simplex);
1051 return std::pair<Simplex_handle, bool>(
null_simplex(),
true);
1054 std::vector<Vertex_handle> copy(first, last);
1055 std::sort(std::begin(copy), std::end(copy));
1073 template<
class InputVertexRange = std::initializer_list<Vertex_handle>>
1076 auto first = std::begin(Nsimplex);
1077 auto last = std::end(Nsimplex);
1082 thread_local std::vector<Vertex_handle> copy;
1084 copy.insert(copy.end(), first, last);
1085 std::sort(copy.begin(), copy.end());
1086 auto last_unique = std::unique(copy.begin(), copy.end());
1087 copy.erase(last_unique, copy.end());
1090 GUDHI_CHECK(v !=
null_vertex(),
"cannot use the dummy null_vertex() as a real vertex");
1093 dimension_ = (std::max)(dimension_,
static_cast<int>(std::distance(copy.begin(), copy.end())) - 1);
1095 return rec_insert_simplex_and_subfaces_sorted(
root(), copy.begin(), copy.end(),
filtration);
1100 template<
class ForwardVertexIterator>
1101 std::pair<Simplex_handle, bool> rec_insert_simplex_and_subfaces_sorted(Siblings* sib,
1102 ForwardVertexIterator first,
1103 ForwardVertexIterator last,
1104 Filtration_value filt) {
1109 Vertex_handle vertex_one = *first;
1110 auto&& dict = sib->members();
1111 auto insertion_result = dict.emplace(vertex_one, Node(sib, filt));
1112 std::pair<Simplex_handle, bool> result(insertion_result);
1114 auto simplex_one = insertion_result.first;
1115 bool one_is_new = insertion_result.second;
1118 update_simplex_tree_after_node_insertion(insertion_result.first);
1127 if (++first == last)
return result;
1130 simplex_one->second.assign_children(
new Siblings(sib, vertex_one));
1131 auto res = rec_insert_simplex_and_subfaces_sorted(simplex_one->second.children(), first, last, filt);
1133 if (res.first !=
null_simplex()) rec_insert_simplex_and_subfaces_sorted(sib, first, last, filt);
1141 _to_node_it(sh)->second.assign_key(
key);
1149 return { find_vertex(sh->first), find_vertex(
self_siblings(sh)->parent()) };
1153 template<
class SimplexHandle>
1155 if (sh->second.children()->parent() == sh->first)
1156 return sh->second.children()->oncles();
1158 return sh->second.children();
1162 template<
class SimplexHandle>
1166 return const_cast<Siblings*
>(std::as_const(*this).self_siblings(sh));
1185 dimension_to_be_lowered_ = !exact;
1186 dimension_ = dimension;
1201 filtration_vect_.clear();
1204 if (ignore_infinite_values &&
1205 std::numeric_limits<Filtration_value>::has_infinity &&
1206 filtration(sh) == std::numeric_limits<Filtration_value>::infinity())
continue;
1207 filtration_vect_.push_back(sh);
1220 tbb::parallel_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration(
this));
1222 std::stable_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration(
this));
1232 if (filtration_vect_.empty()) {
1244 filtration_vect_.clear();
1261 void rec_coface(std::vector<Vertex_handle> &vertices, Siblings
const*curr_sib,
int curr_nbVertices,
1262 std::vector<Simplex_handle>& cofaces,
bool star,
int nbVertices)
const {
1263 if (!(star || curr_nbVertices <= nbVertices))
1265 for (Simplex_handle
simplex = curr_sib->members().begin();
simplex != curr_sib->members().end(); ++
simplex) {
1266 if (vertices.empty()) {
1271 bool addCoface = (star || curr_nbVertices == nbVertices);
1275 rec_coface(vertices,
simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
1277 if (
simplex->first == vertices.back()) {
1279 bool equalDim = (star || curr_nbVertices == nbVertices);
1280 bool addCoface = vertices.size() == 1 && equalDim;
1285 Vertex_handle tmp = vertices.back();
1286 vertices.pop_back();
1287 rec_coface(vertices,
simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
1288 vertices.push_back(tmp);
1290 }
else if (
simplex->first > vertices.back()) {
1295 rec_coface(vertices,
simplex->second.children(), curr_nbVertices + 1, cofaces, star, nbVertices);
1326 assert(codimension >= 0);
1328 if constexpr (Options::link_nodes_by_label) {
1330 Static_vertex_vector simp(rg.begin(), rg.end());
1332 assert(std::is_sorted(simp.begin(), simp.end(), std::greater<Vertex_handle>()));
1333 auto range = Optimized_star_simplex_range(Optimized_star_simplex_iterator(
this, std::move(simp)),
1334 Optimized_star_simplex_iterator());
1336 Fast_cofaces_predicate select(
this, codimension, this->
dimension(simplex));
1337 return boost::adaptors::filter(range, select);
1341 std::vector<Vertex_handle> copy(rg.begin(), rg.end());
1342 if (codimension +
static_cast<int>(copy.size()) > dimension_ + 1 ||
1343 (codimension == 0 &&
static_cast<int>(copy.size()) > dimension_))
1346 assert(std::is_sorted(copy.begin(), copy.end(), std::greater<Vertex_handle>()));
1347 bool star = codimension == 0;
1348 rec_coface(copy, &root_, 1, cofaces, star, codimension +
static_cast<int>(copy.size()));
1361 bool reverse_lexicographic_order(Simplex_handle sh1, Simplex_handle sh2)
const {
1366 while (it1 != rg1.end() && it2 != rg2.end()) {
1374 return ((it1 == rg1.end()) && (it2 != rg2.end()));
1383 struct is_before_in_filtration {
1384 explicit is_before_in_filtration(Simplex_tree
const* st)
1389 if (sh1->second.filtration() != sh2->second.filtration()) {
1390 return sh1->second.filtration() < sh2->second.filtration();
1393 return st_->reverse_lexicographic_order(sh1, sh2);
1396 Simplex_tree
const* st_;
1423 template<
class OneSkeletonGraph>
1429 using boost::num_vertices;
1434 if (num_edges(skel_graph) == 0) {
1440 if constexpr (!Options::stable_simplex_handles)
1442 auto verts = vertices(skel_graph) | boost::adaptors::transformed([&](
auto v){
1443 return Dit_value_t(v, Node(&root_, get(vertex_filtration_t(), skel_graph, v))); });
1444 root_.members_.insert(boost::begin(verts), boost::end(verts));
1447 for (Dictionary_it it = boost::begin(root_.members_); it != boost::end(root_.members_); it++) {
1448 update_simplex_tree_after_node_insertion(it);
1451 std::pair<typename boost::graph_traits<OneSkeletonGraph>::edge_iterator,
1452 typename boost::graph_traits<OneSkeletonGraph>::edge_iterator> boost_edges = edges(skel_graph);
1455 for (; boost_edges.first != boost_edges.second; boost_edges.first++) {
1456 auto edge = *(boost_edges.first);
1457 auto u = source(edge, skel_graph);
1458 auto v = target(edge, skel_graph);
1459 if (u == v)
throw std::invalid_argument(
"Self-loops are not simplicial");
1467 if (v < u) std::swap(u, v);
1468 auto sh = _to_node_it(find_vertex(u));
1470 sh->second.assign_children(
new Siblings(&root_, sh->first));
1473 auto insertion_res = sh->second.children()->members().emplace(
1474 v, Node(sh->second.children(), get(edge_filtration_t(), skel_graph, edge)));
1475 if (insertion_res.second) update_simplex_tree_after_node_insertion(insertion_res.first);
1486 template <
class VertexRange>
1488 auto verts = vertices | boost::adaptors::transformed([&](
auto v){
1489 return Dit_value_t(v, Node(&root_, filt)); });
1490 root_.members_.insert(boost::begin(verts), boost::end(verts));
1491 if (dimension_ < 0 && !root_.members_.empty()) dimension_ = 0;
1492 if constexpr (Options::link_nodes_by_label) {
1493 for (
auto sh = root_.members().begin(); sh != root_.members().end(); sh++) {
1495 if (!sh->second.list_max_vertex_hook_.is_linked())
1496 update_simplex_tree_after_node_insertion(sh);
1513 if (max_dim <= 1)
return;
1515 dimension_ = max_dim;
1516 for (Dictionary_it root_it = root_.members_.begin();
1517 root_it != root_.members_.end(); ++root_it) {
1519 siblings_expansion(root_it->second.children(), max_dim - 1);
1522 dimension_ = max_dim - dimension_;
1563 , std::vector<Simplex_handle>& added_simplices)
1584 static_assert(Options::link_nodes_by_label,
"Options::link_nodes_by_label must be true");
1587 auto res_ins = root_.members().emplace(u, Node(&root_,fil));
1588 if (res_ins.second) {
1589 added_simplices.push_back(res_ins.first);
1590 update_simplex_tree_after_node_insertion(res_ins.first);
1591 if (dimension_ == -1) dimension_ = 0;
1596 if (v < u) { std::swap(u,v); }
1605 auto sh_u = root_.members().find(u);
1606 GUDHI_CHECK(sh_u != root_.members().end() &&
1607 root_.members().find(v) != root_.members().end(),
1608 std::invalid_argument(
1609 "Simplex_tree::insert_edge_as_flag - inserts an edge whose vertices are not in the complex")
1612 sh_u->second.children()->members().find(v) == sh_u->second.children()->members().end(),
1613 std::invalid_argument(
1614 "Simplex_tree::insert_edge_as_flag - inserts an already existing edge")
1619 const auto tmp_dim = dimension_;
1620 auto tmp_max_dim = dimension_;
1625 List_max_vertex* nodes_with_label_u = nodes_by_label(u);
1627 GUDHI_CHECK(nodes_with_label_u !=
nullptr,
1628 "Simplex_tree::insert_edge_as_flag - cannot find the list of Nodes with label u");
1630 for (
auto&& node_as_hook : *nodes_with_label_u)
1632 Node& node_u =
static_cast<Node&
>(node_as_hook);
1635 if (sib_u->members().find(v) != sib_u->members().end()) {
1637 if (dim_max == -1 || curr_dim < dim_max){
1641 node_u.assign_children(
new Siblings(sib_u, u));
1643 dimension_ = dim_max - curr_dim - 1;
1644 compute_punctual_expansion(
1648 dim_max - curr_dim - 1,
1650 dimension_ = dim_max - dimension_;
1651 if (dimension_ > tmp_max_dim) tmp_max_dim = dimension_;
1655 if (tmp_dim <= tmp_max_dim){
1656 dimension_ = tmp_max_dim;
1657 dimension_to_be_lowered_ =
false;
1659 dimension_ = tmp_dim;
1673 void compute_punctual_expansion( Vertex_handle v
1675 , Filtration_value fil
1677 , std::vector<Simplex_handle>& added_simplices )
1679 auto res_ins_v = sib->members().emplace(v, Node(sib,fil));
1680 added_simplices.push_back(res_ins_v.first);
1681 update_simplex_tree_after_node_insertion(res_ins_v.first);
1689 create_local_expansion( res_ins_v.first
1693 , added_simplices );
1696 for (
auto sh = sib->members().begin(); sh != res_ins_v.first; ++sh)
1698 Simplex_handle root_sh = find_vertex(sh->first);
1700 root_sh->second.children()->members().find(v) != root_sh->second.children()->members().end())
1703 sh->second.assign_children(
new Siblings(sib, sh->first));
1706 compute_punctual_expansion( v
1707 , sh->second.children()
1710 , added_simplices );
1721 void create_local_expansion(
1726 , std::vector<Simplex_handle> &added_simplices)
1729 Dictionary_it next_it = sh_v;
1732 if (dimension_ > k) {
1736 create_expansion<true>(curr_sib, sh_v, next_it, fil_uv, k, &added_simplices);
1748 void siblings_expansion(
1752 , std::vector<Simplex_handle> & added_simplices )
1754 if (dimension_ > k) {
1757 if (k == 0) {
return; }
1758 Dictionary_it next = ++(siblings->members().begin());
1760 for (Dictionary_it s_h = siblings->members().begin();
1761 next != siblings->members().end(); ++s_h, ++next)
1763 create_expansion<true>(siblings, s_h, next, fil, k, &added_simplices);
1769 void siblings_expansion(
Siblings * siblings,
1771 if (k >= 0 && dimension_ > k) {
1776 Dictionary_it next = siblings->members().begin();
1779 for (Dictionary_it s_h = siblings->members().begin();
1780 s_h != siblings->members().end(); ++s_h, ++next)
1782 create_expansion<false>(siblings, s_h, next, s_h->second.filtration(), k);
1790 template<
bool force_filtration_value>
1791 void create_expansion(
Siblings * siblings,
1793 Dictionary_it& next,
1796 std::vector<Simplex_handle>* added_simplices =
nullptr)
1799 thread_local std::vector<std::pair<Vertex_handle, Node> > inter;
1803 intersection<force_filtration_value>(
1806 siblings->members().end(),
1807 root_sh->second.children()->members().begin(),
1808 root_sh->second.children()->members().end(),
1810 if (inter.size() != 0) {
1814 for (
auto it = new_sib->members().begin(); it != new_sib->members().end(); ++it) {
1815 update_simplex_tree_after_node_insertion(it);
1816 if constexpr (force_filtration_value){
1818 added_simplices->push_back(it);
1822 s_h->second.assign_children(new_sib);
1823 if constexpr (force_filtration_value){
1824 siblings_expansion(new_sib, fil, k - 1, *added_simplices);
1826 siblings_expansion(new_sib, k - 1);
1830 s_h->second.assign_children(siblings);
1837 template<
bool force_filtration_value = false>
1838 static void intersection(std::vector<std::pair<Vertex_handle, Node> >& intersection,
1839 Dictionary_const_it begin1, Dictionary_const_it end1,
1840 Dictionary_const_it begin2, Dictionary_const_it end2,
1842 if (begin1 == end1 || begin2 == end2)
1845 if (begin1->first == begin2->first) {
1846 if constexpr (force_filtration_value){
1847 intersection.emplace_back(begin1->first, Node(
nullptr, filtration_));
1849 Filtration_value filt = (std::max)({begin1->second.filtration(), begin2->second.filtration(), filtration_});
1850 intersection.emplace_back(begin1->first, Node(
nullptr, filt));
1852 if (++begin1 == end1 || ++begin2 == end2)
1854 }
else if (begin1->first < begin2->first) {
1855 if (++begin1 == end1)
1858 if (++begin2 == end2)
1883 template<
typename Blocker >
1886 for (
auto&
simplex : boost::adaptors::reverse(root_.members())) {
1888 siblings_expansion_with_blockers(
simplex.second.children(), max_dim, max_dim - 1, block_simplex);
1895 template<
typename Blocker >
1896 void siblings_expansion_with_blockers(Siblings* siblings,
int max_dim,
int k, Blocker block_simplex) {
1897 if (dimension_ < max_dim - k) {
1898 dimension_ = max_dim - k;
1903 if (siblings->members().size() < 2)
1906 for (
auto simplex = std::next(siblings->members().rbegin());
simplex != siblings->members().rend();
simplex++) {
1907 std::vector<std::pair<Vertex_handle, Node> > intersection;
1908 for(
auto next = siblings->members().rbegin(); next !=
simplex; next++) {
1909 bool to_be_inserted =
true;
1910 Filtration_value filt =
simplex->second.filtration();
1913 Simplex_handle border_child = find_child(border, next->first);
1915 to_be_inserted=
false;
1918 filt = (std::max)(filt,
filtration(border_child));
1920 if (to_be_inserted) {
1921 intersection.emplace_back(next->first, Node(
nullptr, filt));
1924 if (intersection.size() != 0) {
1929 boost::adaptors::reverse(intersection));
1930 simplex->second.assign_children(new_sib);
1931 std::vector<Vertex_handle> blocked_new_sib_vertex_list;
1933 for (
auto new_sib_member = new_sib->members().begin();
1934 new_sib_member != new_sib->members().end();
1936 update_simplex_tree_after_node_insertion(new_sib_member);
1937 bool blocker_result = block_simplex(new_sib_member);
1940 if (blocker_result) {
1941 blocked_new_sib_vertex_list.push_back(new_sib_member->first);
1944 update_simplex_tree_before_node_removal(new_sib_member);
1947 if (blocked_new_sib_vertex_list.size() == new_sib->members().size()) {
1951 simplex->second.assign_children(siblings);
1953 for (
auto& blocked_new_sib_member : blocked_new_sib_vertex_list) {
1954 new_sib->members().erase(blocked_new_sib_member);
1957 siblings_expansion_with_blockers(new_sib, max_dim, k - 1, block_simplex);
1961 simplex->second.assign_children(siblings);
1977 if (child == sh->second.children()->members().end())
1999 os <<
key(b_sh) <<
" ";
2018 if constexpr (std::is_same_v<void,
decltype(fun(sh, dim))>) {
2022 return fun(sh, dim);
2026 rec_for_each_simplex(
root(), 0, f);
2031 void rec_for_each_simplex(
const Siblings* sib,
int dim, Fun&& fun)
const {
2032 Simplex_handle sh = sib->members().end();
2033 GUDHI_CHECK(sh != sib->members().begin(),
"Bug in Gudhi: only the root siblings may be empty");
2037 rec_for_each_simplex(sh->second.children(), dim+1, fun);
2041 while(sh != sib->members().begin());
2052 bool modified =
false;
2053 auto fun = [&modified,
this](
Simplex_handle sh,
int dim) ->
void {
2054 if (dim == 0)
return;
2065 if (!(sh->second.filtration() >= max_filt_border_value)) {
2082 root_members_recursive_deletion();
2085 dimension_to_be_lowered_ =
false;
2086 if constexpr (Options::link_nodes_by_label)
2087 nodes_label_to_list_.clear();
2098 if (std::numeric_limits<Filtration_value>::has_infinity &&
filtration == std::numeric_limits<Filtration_value>::infinity())
2107 bool rec_prune_above_filtration(Siblings* sib, Filtration_value filt) {
2108 auto&& list = sib->members();
2109 bool modified =
false;
2110 bool emptied =
false;
2111 Simplex_handle last;
2113 auto to_remove = [
this, filt](Dit_value_t&
simplex) {
2114 if (
simplex.second.filtration() <= filt)
return false;
2117 dimension_to_be_lowered_ =
true;
2125 for (
auto sh = list.begin(); sh != list.end();) {
2126 if (to_remove(*sh)) {
2127 sh = list.erase(sh);
2133 emptied = (list.empty() && sib !=
root());
2135 last = std::remove_if(list.begin(), list.end(), to_remove);
2136 modified = (last != list.end());
2137 emptied = (last == list.begin() && sib !=
root());
2142 sib->oncles()->members()[sib->parent()].assign_children(sib->oncles());
2145 dimension_to_be_lowered_ =
true;
2163 if (dimension >= dimension_)
2166 bool modified =
false;
2167 if (dimension < 0) {
2169 root_members_recursive_deletion();
2175 modified = rec_prune_above_dimension(
root(), dimension, 0);
2179 dimension_ = dimension;
2186 bool rec_prune_above_dimension(Siblings* sib,
int dim,
int actual_dim) {
2187 bool modified =
false;
2188 auto&& list = sib->members();
2192 if (actual_dim >= dim) {
2193 rec_delete(
simplex.second.children());
2194 simplex.second.assign_children(sib);
2197 modified |= rec_prune_above_dimension(
simplex.second.children(), dim, actual_dim + 1);
2210 bool lower_upper_bound_dimension()
const {
2212 dimension_to_be_lowered_ =
false;
2213 int new_dimension = -1;
2218 std::clog <<
" " << vertex;
2220 std::clog << std::endl;
2224 if (sh_dimension >= dimension_)
2227 new_dimension = (std::max)(new_dimension, sh_dimension);
2229 dimension_ = new_dimension;
2246 std::invalid_argument(
"Simplex_tree::remove_maximal_simplex - argument has children"));
2248 update_simplex_tree_before_node_removal(sh);
2251 Dictionary_it nodeIt = _to_node_it(sh);
2252 Siblings* child = nodeIt->second.children();
2254 if ((child->size() > 1) || (child ==
root())) {
2257 child->erase(nodeIt);
2260 child->oncles()->members().at(child->parent()).assign_children(child->oncles());
2263 dimension_to_be_lowered_ =
true;
2284 std::pair<Filtration_value, Extended_simplex_type> p;
2287 if (f >= -2 && f <= -1) {
2288 p.first = minval + (maxval-minval)*(f + 2); p.second = Extended_simplex_type::UP;
2289 }
else if (f >= 1 && f <= 2) {
2290 p.first = minval - (maxval-minval)*(f - 2); p.second = Extended_simplex_type::DOWN;
2292 p.first = std::numeric_limits<Filtration_value>::quiet_NaN(); p.second = Extended_simplex_type::EXTRA;
2314 Vertex_handle maxvert = std::numeric_limits<Vertex_handle>::min();
2315 Filtration_value minval = std::numeric_limits<Filtration_value>::infinity();
2316 Filtration_value maxval = -std::numeric_limits<Filtration_value>::infinity();
2317 for (
auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) {
2319 minval = std::min(minval, f);
2320 maxval = std::max(maxval, f);
2321 maxvert = std::max(sh->first, maxvert);
2324 GUDHI_CHECK(maxvert < std::numeric_limits<Vertex_handle>::max(), std::invalid_argument(
"Simplex_tree contains a vertex with the largest Vertex_handle"));
2327 Simplex_tree st_copy = *
this;
2330 this->insert_simplex_raw({maxvert}, -3);
2337 std::vector<Vertex_handle> vr;
2340 vr.assign(simplex_range.begin(), simplex_range.end());
2341 auto sh = this->
find(vr);
2344 vr.push_back(maxvert);
2363 return Extended_filtration_data(minval, maxval);
2371 auto filt = filtration_(sh);
2373 if(filtration_(find_vertex(v)) == filt)
2387 auto end = std::end(vertices);
2388 auto vi = std::begin(vertices);
2389 GUDHI_CHECK(vi != end,
"empty simplex");
2392 GUDHI_CHECK(vi != end,
"simplex of dimension 0");
2393 if(std::next(vi) == end)
return sh;
2394 Static_vertex_vector suffix;
2395 suffix.push_back(v0);
2396 auto filt = filtration_(sh);
2400 auto&& children1 = find_vertex(v)->second.children()->members_;
2401 for(
auto w : suffix){
2404 if(filtration_(s) == filt)
2407 suffix.push_back(v);
2418 auto filt = filtration_(sh);
2421 if(filtration_(b) == filt)
2429 &Hooks_simplex_base_link_nodes::list_max_vertex_hook_>
2433 boost::intrusive::constant_time_size<false>> List_max_vertex;
2443 std::unordered_map<Vertex_handle, List_max_vertex> nodes_label_to_list_;
2445 List_max_vertex* nodes_by_label(Vertex_handle v) {
2448 return const_cast<List_max_vertex*
>(std::as_const(*this).nodes_by_label(v));
2451 List_max_vertex
const* nodes_by_label(Vertex_handle v)
const {
2453 auto it_v = nodes_label_to_list_.find(v);
2454 if (it_v != nodes_label_to_list_.end()) {
2455 return &(it_v->second);
2465 static Simplex_handle simplex_handle_from_node(
const Node& node) {
2477 Dictionary_const_it testIt = node.children()->members().begin();
2478 const Node* testNode = &testIt->second;
2479 auto testIIt = testIt.get();
2480 auto testPtr = testIIt.pointed_node();
2482 auto shift = (
const char*)(testNode) - (
const char*)(testPtr);
2485 decltype(testPtr) sh_ptr =
decltype(testPtr)((
const char*)(&node) - shift);
2497 decltype(testIIt) sh_ii;
2499 Dictionary_const_it sh(sh_ii);
2504 return (
Simplex_handle)(boost::intrusive::get_parent_from_member<Dit_value_t>(
const_cast<Node*
>(&node),
2505 &Dit_value_t::second));
2511 friend class Simplex_tree_optimized_cofaces_rooted_subtrees_simplex_iterator<Simplex_tree>;
2516 void update_simplex_tree_after_node_insertion(
Simplex_handle sh) {
2518 std::clog <<
"update_simplex_tree_after_node_insertion" << std::endl;
2522 nodes_label_to_list_[sh->first].push_back(_to_node_it(sh)->second);
2528 void update_simplex_tree_before_node_removal(
Simplex_handle sh) {
2530 std::clog <<
"update_simplex_tree_before_node_removal" << std::endl;
2533 _to_node_it(sh)->second.unlink_hooks();
2534 if (nodes_label_to_list_[sh->first].empty())
2535 nodes_label_to_list_.erase(sh->first);
2549 rec_reset_filtration(&root_, filt_value, min_dim);
2559 void rec_reset_filtration(Siblings * sib, Filtration_value filt_value,
int min_depth) {
2560 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
2561 if (min_depth <= 0) {
2562 sh->second.assign_filtration(filt_value);
2565 rec_reset_filtration(sh->second.children(), filt_value, min_depth - 1);
2578 std::size_t get_serialization_size()
const {
2581 const std::size_t buffer_byte_size = vh_byte_size +
num_simplices() * (fv_byte_size + 2 * vh_byte_size);
2583 std::clog <<
"Gudhi::simplex_tree::get_serialization_size - buffer size = " << buffer_byte_size << std::endl;
2585 return buffer_byte_size;
2619 void serialize(
char* buffer,
const std::size_t buffer_size)
const {
2620 char* buffer_end = rec_serialize(&root_, buffer);
2621 if (
static_cast<std::size_t
>(buffer_end - buffer) != buffer_size)
2622 throw std::invalid_argument(
"Serialization does not match end of buffer");
2627 char* rec_serialize(
Siblings const *sib,
char* buffer)
const {
2629 ptr = Gudhi::simplex_tree::serialize_trivial(
static_cast<Vertex_handle>(sib->members().size()), ptr);
2631 std::clog <<
"\n" << sib->members().size() <<
" : ";
2633 for (
auto& map_el : sib->members()) {
2634 ptr = Gudhi::simplex_tree::serialize_trivial(map_el.first, ptr);
2636 ptr = Gudhi::simplex_tree::serialize_trivial(map_el.second.filtration(), ptr);
2638 std::clog <<
" [ " << map_el.first <<
" | " << map_el.second.filtration() <<
" ] ";
2641 for (
auto& map_el : sib->members()) {
2643 ptr = rec_serialize(map_el.second.children(), ptr);
2645 ptr = Gudhi::simplex_tree::serialize_trivial(
static_cast<Vertex_handle>(0), ptr);
2647 std::cout <<
"\n0 : ";
2669 void deserialize(
const char* buffer,
const std::size_t buffer_size) {
2670 GUDHI_CHECK(
num_vertices() == 0, std::logic_error(
"Simplex_tree::deserialize - Simplex_tree must be empty"));
2671 const char* ptr = buffer;
2674 ptr = Gudhi::simplex_tree::deserialize_trivial(members_size, ptr);
2675 ptr = rec_deserialize(&root_, members_size, ptr, 0);
2676 if (
static_cast<std::size_t
>(ptr - buffer) != buffer_size) {
2677 throw std::invalid_argument(
"Deserialization does not match end of buffer");
2685 if (members_size > 0) {
2690 ptr = Gudhi::simplex_tree::deserialize_trivial(vertex, ptr);
2692 ptr = Gudhi::simplex_tree::deserialize_trivial(
filtration, ptr);
2694 sib->members_.emplace_hint(sib->members_.end(), vertex, Node(sib,
filtration));
2697 sib->members_.emplace_hint(sib->members_.end(), vertex, Node(sib));
2701 for (
auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
2702 update_simplex_tree_after_node_insertion(sh);
2703 ptr = Gudhi::simplex_tree::deserialize_trivial(child_size, ptr);
2704 if (child_size > 0) {
2706 sh->second.assign_children(child);
2707 ptr = rec_deserialize(child, child_size, ptr, dim + 1);
2710 if (dim > dimension_) {
2727 mutable std::vector<Simplex_handle> filtration_vect_;
2729 mutable int dimension_;
2730 mutable bool dimension_to_be_lowered_ =
false;