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

Const simplex tree unitary tests and fix operator== and != #1145

Open
wants to merge 27 commits into
base: master
Choose a base branch
from

Conversation

VincentRouvreau
Copy link
Contributor

This PR is based on and replaces #1119

@hschreiber
Copy link
Collaborator

Thanks for the unitary tests! But I think you forgot to include them?

@VincentRouvreau
Copy link
Contributor Author

Thanks for the unitary tests! But I think you forgot to include them?

Oops yes. Should be better now

@hschreiber
Copy link
Collaborator

Should we update the credit banners with the changes or is it not really necessary? Otherwise, looks good to me.

Copy link
Member

@mglisse mglisse left a comment

Choose a reason for hiding this comment

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

Looks ok. There may be things we can clean-up later, but they don't seem like prerequisites.
The change will have to be mentioned in next_release.md (we can now perform many operations on a const ST, but we are now stricter about undocumented direct use of Simplex_handle).

@@ -715,7 +719,7 @@ class Simplex_tree {
static Simplex_data& simplex_data(Simplex_handle sh) {
Copy link
Member

Choose a reason for hiding this comment

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

Should we make it non-static, with const/non-const overloads?

Copy link
Contributor Author

@VincentRouvreau VincentRouvreau Oct 23, 2024

Choose a reason for hiding this comment

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

Done and tested on 99b37a3

src/Simplex_tree/include/gudhi/Simplex_tree.h Outdated Show resolved Hide resolved
@@ -658,6 +658,10 @@ class Simplex_tree {
return sh->second.filtration();
}

static Dictionary_it _to_node_it(Simplex_handle sh){
Copy link
Member

@mglisse mglisse Oct 18, 2024

Choose a reason for hiding this comment

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

It feels like making this a non-const member function instead of a static one would be safer, but that's an implementation detail, it is ok as static.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No more static on 85efd97
I also added a comment on that method

src/Simplex_tree/include/gudhi/Simplex_tree.h Outdated Show resolved Hide resolved
src/Simplex_tree/include/gudhi/Simplex_tree.h Outdated Show resolved Hide resolved
@@ -1987,7 +1998,7 @@ class Simplex_tree {
if (!(sh->second.filtration() >= max_filt_border_value)) {
// Store the filtration modification information
modified = true;
sh->second.assign_filtration(max_filt_border_value);
_to_node_it(sh)->second.assign_filtration(max_filt_border_value);
Copy link
Member

Choose a reason for hiding this comment

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

It is ok for now, but in the long run, internally, do we want to use _to_node_it or do we want to go through the official interface assign_filtration(sh, max_filt_border_value)? _to_node_it has the advantage (?) of skipping the assertion, but the code is uglier.

Copy link
Contributor Author

@VincentRouvreau VincentRouvreau Nov 12, 2024

Choose a reason for hiding this comment

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

You are right, we should prefer the use of assign_filtration(sh, max_filt_border_value). I modified it on 0d500bc

@@ -2374,10 +2386,21 @@ class Simplex_tree {
}
return nullptr;
}
List_max_vertex const* nodes_by_label(Vertex_handle v) const {
Copy link
Member

Choose a reason for hiding this comment

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

I think you could have the other function call this one and const_cast the result, to avoid duplicating the code.

Copy link
Contributor Author

@VincentRouvreau VincentRouvreau Oct 23, 2024

Choose a reason for hiding this comment

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

I did so on f8de11a but I did not find out how to do it without an indirection

Copy link
Member

Choose a reason for hiding this comment

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

std::as_const(*this).nodes_by_label(v)?

Copy link
Contributor Author

@VincentRouvreau VincentRouvreau Nov 5, 2024

Choose a reason for hiding this comment

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

Oh ? Ok ! I did return const_cast<List_max_vertex*>(std::as_const(*this).nodes_by_label(v)); on 4277a64

}

/** \brief Returns the extra data stored in a simplex. */
const Simplex_data simplex_data(Simplex_handle sh) const {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
const Simplex_data simplex_data(Simplex_handle sh) const {
const Simplex_data& simplex_data(Simplex_handle sh) const {

?

Copy link
Contributor Author

@VincentRouvreau VincentRouvreau Nov 5, 2024

Choose a reason for hiding this comment

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

You are right, done on cbbdc8a

@@ -2374,10 +2386,21 @@ class Simplex_tree {
}
return nullptr;
}
List_max_vertex const* nodes_by_label(Vertex_handle v) const {
Copy link
Member

Choose a reason for hiding this comment

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

std::as_const(*this).nodes_by_label(v)?

assert(dimension(sh) == 1);
return { find_vertex(sh->first), find_vertex(self_siblings(sh)->parent()) };
}

/** Returns the Siblings containing a simplex.*/
template<class SimplexHandle>
static Siblings* self_siblings(SimplexHandle sh) {
static Siblings const* self_siblings(SimplexHandle sh) {
Copy link
Member

Choose a reason for hiding this comment

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

It looks like having const and non-const overloads of self_siblings would avoid a couple const_cast elsewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did so on 85efd97 and it is true that it removes some const_cast

@@ -1129,7 +1143,7 @@ class Simplex_tree {
*
* Any insertion, deletion or change of filtration value invalidates this cache,
* which can be cleared with clear_filtration(). */
void initialize_filtration(bool ignore_infinite_values = false) {
void initialize_filtration(bool ignore_infinite_values = false) const {
Copy link
Member

Choose a reason for hiding this comment

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

Should clear_filtration also be const, or is it different enough that it shouldn't be?

Copy link
Contributor Author

@VincentRouvreau VincentRouvreau Nov 5, 2024

Choose a reason for hiding this comment

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

clear_filtration() constify on 3d21b0c

Comment on lines +2660 to +2661
// all mutable as their content has no impact on the content of the simplex tree itself
// they correspond to some kind of cache or helper attributes.
Copy link
Member

Choose a reason for hiding this comment

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

At some point we should document what functions are safe to use in parallel on a Simplex_tree and what functions are not. Some people have the expectation that const means thread-safe, which isn't the case in the presence of mutable.

Copy link
Contributor Author

@VincentRouvreau VincentRouvreau Nov 5, 2024

Choose a reason for hiding this comment

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

I marked dimension(), upper_bound_dimension(), initialize_filtration(), maybe_initialize_filtration (), clear_filtration(), filtration_simplex_range(), simplex(Simplex_key idx), print_hasse() as not thread-safe in the doc on 3d21b0c
Remark, that print_hasse() should not and use complex_simplex_range() instead of filtration_simplex_range().

BOOST_CHECK(STRoot != nullptr);
BOOST_CHECK(STRoot->oncles() == nullptr);
BOOST_CHECK(STRoot->parent() == DEFAULT_VERTEX_VALUE);
BOOST_CHECK(tst.dimension() == -1);
}

template<class typeST>
void test_iterators_on_empty_simplex_tree(typeST& tst) {
void test_iterators_on_empty_simplex_tree(const typeST& tst) {
std::clog << "Iterator on vertices: " << std::endl;
for (auto vertex : tst.complex_vertex_range()) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It looks like this is the only place where complex_vertex_range is tested. Could be nice to test it also for non empty trees?

Copy link
Contributor Author

@VincentRouvreau VincentRouvreau Nov 12, 2024

Choose a reason for hiding this comment

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

I added a test on 38a751f

@@ -671,6 +679,8 @@ class Simplex_tree {
/** \brief Returns the simplex that has index idx in the filtration.
*
* The filtration must be initialized.
*
* @note Not thread safe
*/
Simplex_handle simplex(Simplex_key idx) const {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I couldn't find any place where this method is tested, is it const or non const. I guess, if filtration_simplex_range works, this method should work too.

Same for contiguous_vertices().

Copy link
Contributor Author

@VincentRouvreau VincentRouvreau Nov 12, 2024

Choose a reason for hiding this comment

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

I added 2 new tests on 38a751f

@@ -827,7 +849,7 @@ class Simplex_tree {
/** \brief Returns the children of the node in the simplex tree pointed by sh.
* \exception std::invalid_argument In debug mode, if sh has no child.
*/
Siblings* children(Simplex_handle sh) const {
Siblings const* children(Simplex_handle sh) const {
GUDHI_CHECK(has_children(sh), std::invalid_argument("Simplex_tree::children - argument has no child"));
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not directly related to this PR, but is there a reason why has_children (just above at line 840, I can't select it) is public? Or even root?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added some const test about has_children() and root() on 323e119

@@ -1934,7 +1971,7 @@ class Simplex_tree {
* the children of this simplex (a subset of the cofaces).
*/
template<class Fun>
void for_each_simplex(Fun&& fun) {
void for_each_simplex(Fun&& fun) const {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should also test the method on a non const simplex tree such that fun modified something in the tree (eg. puts all filtration values to value 2), to ensure that the constness of the method does not block that. I think we already test it indirectly with some use of for_each_simplex in another place, but I suddenly have a doubt.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not tested directly, but this is what is done on assign_MEB_filtration (cf. test_cech_complex, delaunay_cech_persistence utils)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants