Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Simplex tree] Generalization of filtration values in Simplex_tree #1122

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1966df2
add references for non arithemtic filtration values
hschreiber Aug 14, 2024
b760df2
generalization of filtration value operations
hschreiber Aug 19, 2024
b7269a8
doc
hschreiber Aug 19, 2024
70549af
small fixes
hschreiber Aug 19, 2024
0416788
include fix
hschreiber Aug 19, 2024
c4e04ca
include fix
hschreiber Aug 20, 2024
290de10
doc + bool return for unify_birth and push_to_smallest_common_upper_b…
hschreiber Aug 23, 2024
4d80e13
minor fix for prone_above_filtration + Filtration_value concept
hschreiber Aug 23, 2024
ddb7d20
add references in simplex tree even for arithmetic filtration values
hschreiber Aug 26, 2024
35778b2
Merge branch 'GUDHI:master' into simplex_tree_filtration_value_genera…
hschreiber Aug 27, 2024
9cc2e76
update of SimplexTreeOptions.h
hschreiber Sep 3, 2024
df5a510
XMerge branch 'simplex_tree_filtration_value_generalization' of githu…
hschreiber Sep 3, 2024
7555436
Merge branch 'GUDHI:master' into simplex_tree_filtration_value_genera…
hschreiber Sep 3, 2024
d07a6f1
move 'insert' of Sibling in Simplex_tree and use it
hschreiber Sep 3, 2024
78470f5
minor fixes
hschreiber Sep 16, 2024
6d837af
merge upstream
hschreiber Sep 16, 2024
413b6c1
NaN fix for prune_above_filtration
hschreiber Sep 16, 2024
da79b21
filtration value doc
hschreiber Sep 24, 2024
1495403
Merge branch 'GUDHI:master' into simplex_tree_filtration_value_genera…
hschreiber Oct 22, 2024
aec50c9
doc + minor changes
hschreiber Oct 22, 2024
369a965
doc
hschreiber Oct 22, 2024
c77ca28
Merge branch 'GUDHI:master' into simplex_tree_filtration_value_genera…
hschreiber Oct 25, 2024
1cf4ec7
change unify/intersect name + replaces bool with predicate in second …
hschreiber Oct 28, 2024
95210dc
doc
hschreiber Oct 28, 2024
af820c5
fix (de)serialization for general filtration values
hschreiber Oct 29, 2024
d92d698
Update src/Simplex_tree/include/gudhi/Simplex_tree.h
hschreiber Oct 29, 2024
9c2047f
doc
hschreiber Oct 29, 2024
e46325e
enable deserialization from a simplex tree with different filtration …
hschreiber Nov 7, 2024
bcdad85
doc
hschreiber Nov 13, 2024
b202391
Merge branch 'GUDHI:master' into simplex_tree_filtration_value_genera…
hschreiber Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 60 additions & 59 deletions src/Simplex_tree/include/gudhi/Simplex_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,49 @@ class Simplex_tree {
return true;
}

private:
/**
* @brief Inserts a Node in the set of siblings nodes. Calls `update_simplex_tree_after_node_insertion`
* if the insertion succeeded.
*
* @tparam update_fil If true and the node is already present, assigns the "union" of the input filtration_value
* and the value already present in the node as filtration value.
* @tparam update_children If true and the node has no children, create a child with sib as uncle.
* @tparam set_to_null If true and the node is already present, sets the returned simplex handle to null if the
* filtration value of the simplex was not modified.
* @tparam Filt Filtration value type.
* @param sib Sibling in where the node has to be inserted.
* @param v Label of the node.
* @param filtration_value Filtration value stored in the node.
* @return Pair of the iterator to the new node and a boolean indicating if the insertion succeeded.
*/
template<bool update_fil, bool update_children, bool set_to_null, class Filt>
std::pair<Simplex_handle, bool> insert_node_(Siblings *sib, Vertex_handle v, Filt&& filtration_value) {
std::pair<Simplex_handle, bool> ins = sib->members_.try_emplace(v, sib, std::forward<Filt>(filtration_value));

if constexpr (update_children){
if (!(has_children(ins.first))) {
ins.first->second.assign_children(new Siblings(sib, v));
}
}

if (ins.second){
// Only required when insertion is successful
update_simplex_tree_after_node_insertion(ins.first);
return ins;
}

if constexpr (update_fil){
hschreiber marked this conversation as resolved.
Show resolved Hide resolved
if (unify_births(ins.first->second.filtration_raw(), filtration_value)) return ins;
}

if constexpr (set_to_null){
ins.first = null_simplex();
}

return ins;
}

protected:
/** \brief Inserts a simplex represented by a range of vertex.
* @param[in] simplex range of Vertex_handles, representing the vertices of the new simplex. The range must be
Expand All @@ -876,44 +919,22 @@ class Simplex_tree {
Siblings * curr_sib = &root_;
std::pair<Simplex_handle, bool> res_insert;
auto vi = simplex.begin();

for (; vi != std::prev(simplex.end()); ++vi) {
GUDHI_CHECK(*vi != null_vertex(), "cannot use the dummy null_vertex() as a real vertex");
res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib, filtration));
if (res_insert.second) {
// Only required when insertion is successful
update_simplex_tree_after_node_insertion(res_insert.first);
}
if (!(has_children(res_insert.first))) {
res_insert.first->second.assign_children(new Siblings(curr_sib, *vi));
}
res_insert = insert_node_<false, true, false>(curr_sib, *vi, filtration);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My first reaction is that insert_node_<false, true, false> is not very readable. But after looking at it for a while, I'd say ok, we can always revisit this later if we have a better idea.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree... But I found it better than having 4 methods doing more or less the same with just small variations. The other solution would have been to just keep the try_emplace and the update_simplex_tree_after_node_insertion in the method and letting the rest in the calling methods, but this would have lessen the point of insert_node_. Methods like insert_simplex_raw are so much more readable now.
If someone has a nicer solution, they are welcome!

curr_sib = res_insert.first->second.children();
}

GUDHI_CHECK(*vi != null_vertex(), "cannot use the dummy null_vertex() as a real vertex");
res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib, filtration));
if (!res_insert.second) {
if constexpr (Options::store_filtration){
// if already in the complex
if (unify_births(res_insert.first->second.filtration_raw(), filtration)) {
// if filtration value modified
return res_insert;
}
// if filtration value unchanged
return std::pair<Simplex_handle, bool>(null_simplex(), false);
} else {
return std::pair<Simplex_handle, bool>(null_simplex(), false);
res_insert = insert_node_<Options::store_filtration, false, true>(curr_sib, *vi, filtration);
if (res_insert.second){
int dim = static_cast<int>(boost::size(simplex)) - 1;
if (dim > dimension_) {
// Update dimension if needed
dimension_ = dim;
}
}
// otherwise the insertion has succeeded

// Only required when insertion is successful
update_simplex_tree_after_node_insertion(res_insert.first);

// size is a size_type
int dim = static_cast<int>(boost::size(simplex)) - 1;
if (dim > dimension_) {
// Update dimension if needed
dimension_ = dim;
}
return res_insert;
}

Expand Down Expand Up @@ -1010,30 +1031,13 @@ class Simplex_tree {
// - insert all the vertices at once in sib
// - loop over those (new or not) simplices, with a recursive call(++first, last)
Vertex_handle vertex_one = *first;
auto&& dict = sib->members();
auto insertion_result = dict.emplace(vertex_one, Node(sib, filt));

Simplex_handle simplex_one = insertion_result.first;
bool one_is_new = insertion_result.second;
if (one_is_new) {
// update extra data structures in the insertion is successful
// Only required when insertion is successful
update_simplex_tree_after_node_insertion(insertion_result.first);
} else {
if constexpr (Options::store_filtration){
if (!unify_births(simplex_one->second.filtration_raw(), filt)) {
// FIXME: this interface makes no sense, and it doesn't seem to be tested.
insertion_result.first = null_simplex();
}
} else {
insertion_result.first = null_simplex();
}
}
if (++first == last) return insertion_result;
if (!has_children(simplex_one))
// TODO: have special code here, we know we are building the whole subtree from scratch.
simplex_one->second.assign_children(new Siblings(sib, vertex_one));
auto res = rec_insert_simplex_and_subfaces_sorted(simplex_one->second.children(), first, last, filt);
if (++first == last) return insert_node_<Options::store_filtration, false, true>(sib, vertex_one, filt);

// TODO: have special code here, we know we are building the whole subtree from scratch.
auto insertion_result = insert_node_<Options::store_filtration, true, false>(sib, vertex_one, filt);

auto res = rec_insert_simplex_and_subfaces_sorted(insertion_result.first->second.children(), first, last, filt);
// No need to continue if the full simplex was already there with a low enough filtration value.
if (res.first != null_simplex()) rec_insert_simplex_and_subfaces_sorted(sib, first, last, filt);
return res;
Expand Down Expand Up @@ -1401,9 +1405,7 @@ class Simplex_tree {
sh->second.assign_children(new Siblings(&root_, sh->first));
}

auto insertion_res = sh->second.children()->members().emplace(
v, Node(sh->second.children(), get(edge_filtration_t(), skel_graph, edge)));
if (insertion_res.second) update_simplex_tree_after_node_insertion(insertion_res.first);
insert_node_<false, false, false>(sh->second.children(), v, get(edge_filtration_t(), skel_graph, edge));
}
}

Expand Down Expand Up @@ -1515,10 +1517,9 @@ class Simplex_tree {
static_assert(Options::link_nodes_by_label, "Options::link_nodes_by_label must be true");

if (u == v) { // Are we inserting a vertex?
auto res_ins = root_.members().emplace(u, Node(&root_,fil));
auto res_ins = insert_node_<false, false, false>(&root_, u, fil);
if (res_ins.second) { //if the vertex is not in the complex, insert it
added_simplices.push_back(res_ins.first); //no more insert in root_.members()
update_simplex_tree_after_node_insertion(res_ins.first);
if (dimension_ == -1) dimension_ = 0;
}
return; //because the vertex is isolated, no more insertions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,6 @@ class Simplex_tree_siblings {
}
}

/** \brief Inserts a Node in the set of siblings nodes.
*
* If already present, assigns the minimal filtration value
* between input filtration_value and the value already
* present in the node.
*/
void insert(Vertex_handle v, const Filtration_value& filtration_value) {
auto ins = members_.emplace(v, Node(this, filtration_value));
if (!ins.second){
unify_births(ins.first->second.filtration_raw(), filtration_value);
}
}

Dictionary_it find(Vertex_handle v) {
return members_.find(v);
}
Expand Down
Loading