-
Notifications
You must be signed in to change notification settings - Fork 67
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
Zigzag persistence part2 #953
base: master
Are you sure you want to change the base?
Changes from 26 commits
4f06e5c
9eb1e01
0dcf241
5e530f7
40bb36a
9b0a7cc
63aad6a
951cbb8
d63e697
b640b89
52376df
8f2dc9c
67637b9
ba7ee4d
f0978fc
d8a8273
da86ef5
0655678
3618262
656435e
8e1512a
f76a682
9a526f6
aac903d
b69b288
2e973f1
f09a1a0
6d5d901
3cf9a49
ba0d7db
b0ebdcb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. | ||
* See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. | ||
* Author(s): Hannah Schreiber | ||
* | ||
* Copyright (C) 2023 Inria | ||
* | ||
* Modification(s): | ||
* - YYYY/MM Author: Description of the modification | ||
*/ | ||
|
||
#ifndef CONCEPT_ZZ_DISTANCE_FUNCTION_H_ | ||
#define CONCEPT_ZZ_DISTANCE_FUNCTION_H_ | ||
|
||
/** @file DistanceFunction.h | ||
* @brief Contains @ref Gudhi::zigzag_persistence::DistanceFunction concept. | ||
*/ | ||
|
||
#include "PointRange.h" | ||
|
||
namespace Gudhi { | ||
namespace zigzag_persistence { | ||
|
||
/** | ||
* @brief Distance function taking two points as input and returning the distance between them. | ||
*/ | ||
using DistanceFunction = double (*)(const Point&, const Point&); | ||
|
||
} // namespace zigzag_persistence | ||
} // namespace Gudhi | ||
|
||
#endif // CONCEPT_ZZ_DISTANCE_FUNCTION_H_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. | ||
* See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. | ||
* Author(s): Hannah Schreiber | ||
* | ||
* Copyright (C) 2023 Inria | ||
* | ||
* Modification(s): | ||
* - YYYY/MM Author: Description of the modification | ||
*/ | ||
|
||
#ifndef CONCEPT_ZZ_EDGE_MODIFIER_H_ | ||
#define CONCEPT_ZZ_EDGE_MODIFIER_H_ | ||
|
||
/** @file EdgeModifier.h | ||
* @brief Contains @ref Gudhi::zigzag_persistence::EdgeModifier concept. | ||
*/ | ||
|
||
namespace Gudhi { | ||
namespace zigzag_persistence { | ||
|
||
/** | ||
* @brief Methods whose purposes are to modify the filtration value of a given edge following a rule. | ||
* The concept is for example realized by @ref Identity_edge_modifier or @ref Square_root_edge_modifier "". | ||
*/ | ||
template <typename Filtration_value> | ||
class EdgeModifier { | ||
public: | ||
/** | ||
* @brief Applies the modifier to the given value and returns it. | ||
* | ||
* @param f Value to modify. | ||
* @return The modified value of @p f. | ||
*/ | ||
static Filtration_value apply_modifier(Filtration_value f); | ||
|
||
/** | ||
* @brief Applies the inverse modifier to the given value and returns it. | ||
* So, apply_inverse_modifier(apply_modifier(f)) == f (modulo some possible precision errors.). | ||
* | ||
* @param f Value to modify. | ||
* @return The modified value of @p f. | ||
*/ | ||
static Filtration_value apply_inverse_modifier(Filtration_value f); | ||
}; | ||
|
||
} // namespace zigzag_persistence | ||
} // namespace Gudhi | ||
|
||
#endif // CONCEPT_ZZ_EDGE_MODIFIER_H_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. | ||
* See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. | ||
* Author(s): Hannah Schreiber | ||
* | ||
* Copyright (C) 2023 Inria | ||
* | ||
* Modification(s): | ||
* - YYYY/MM Author: Description of the modification | ||
*/ | ||
|
||
#ifndef CONCEPT_ZZ_POINT_RANGE_H_ | ||
#define CONCEPT_ZZ_POINT_RANGE_H_ | ||
|
||
/** @file PointRange.h | ||
* @brief Contains @ref Gudhi::zigzag_persistence::Point and @ref Gudhi::zigzag_persistence::PointRange concept. | ||
*/ | ||
|
||
namespace Gudhi { | ||
namespace zigzag_persistence { | ||
|
||
/** | ||
* @brief Data structure representing a point of fixed dimension. The structure of the point does not matter | ||
* it-self as long as it corresponds to the input type of the @ref DistanceFunction concept. | ||
*/ | ||
class Point{}; | ||
|
||
/** | ||
* @brief Range of @ref Point. If used with @ref Oscillating_rips_edge_order_policy::FARTHEST_POINT_ORDERING | ||
* order policy, it has to be a random access range. | ||
*/ | ||
class PointRange { | ||
public: | ||
/** | ||
* @brief Returns begin iterator. | ||
*/ | ||
auto begin(); | ||
|
||
/** | ||
* @brief Returns end iterator. | ||
*/ | ||
auto end(); | ||
|
||
/** | ||
* @brief Returns size of the range. | ||
*/ | ||
std::size_t size(); | ||
|
||
/** | ||
* @brief Necessary only if used with @ref Oscillating_rips_edge_order_policy::FARTHEST_POINT_ORDERING. | ||
* Returns the element at the given index. | ||
* | ||
* @param index Index of the element to return. | ||
* @return Point at index @p index. | ||
*/ | ||
Point operator[](std::size_t index); | ||
}; | ||
|
||
} // namespace zigzag_persistence | ||
} // namespace Gudhi | ||
|
||
#endif // CONCEPT_ZZ_POINT_RANGE_H_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. | ||
* See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. | ||
* Author(s): Hannah Schreiber | ||
* | ||
* Copyright (C) 2023 Inria | ||
* | ||
* Modification(s): | ||
* - YYYY/MM Author: Description of the modification | ||
*/ | ||
|
||
#ifndef CONCEPT_ZZ_STABLE_COMPLEX_TYPE_H_ | ||
#define CONCEPT_ZZ_STABLE_COMPLEX_TYPE_H_ | ||
|
||
/** @file StableFilteredComplex.h | ||
* @brief Contains @ref Gudhi::zigzag_persistence::StableFilteredComplex concept. | ||
*/ | ||
|
||
namespace Gudhi { | ||
namespace zigzag_persistence { | ||
|
||
/** | ||
* @brief Data structure storing the simplices and their filtration values in the current complex. | ||
* The concept is realized for example by | ||
* @ref Gudhi::Simplex_tree < Gudhi::zigzag_persistence::Simplex_tree_options_oscillating_rips >. | ||
*/ | ||
class StableFilteredComplex { | ||
public: | ||
/** | ||
* @brief Integer type that needs to be long enough to store the numbers of arrows in the zigzag filtration. | ||
*/ | ||
typename Simplex_key; | ||
|
||
/** | ||
* @brief Handle to specify a simplex. The simplex handles have to be stable, that is, they do not invalidate when | ||
* a simplex is added or removed from the complex (except for the removed simplices them-selves of course). | ||
*/ | ||
typename Simplex_handle; | ||
|
||
/** | ||
* @brief Type for filtration values. Usually 'double'. | ||
*/ | ||
typename Filtration_value; | ||
|
||
/** | ||
* @brief Removes the given simplex. Assumes that the simplex is maximal and can be safely removed. | ||
* | ||
* @param sh Simplex handle representing the simplex to remove. | ||
*/ | ||
void remove_maximal_simplex(Simplex_handle sh); | ||
|
||
/** | ||
* @brief Adds a vertex or an edge in a flag complex, as well as all | ||
* simplices of its star, defined to maintain the property | ||
* of the complex to be a flag complex, truncated at dimension dim_max. | ||
* | ||
* @param u ID of one end of the edge. | ||
* @param v ID of the other end of the edge. If @p u == @p v, then the input is considered as a vertex. | ||
* @param fil Filtration value of the edge. | ||
* @param dim_max Maximal dimension of the expansion. If set to -1, the expansion goes as far as possible. | ||
* @param added_simplices Container for all new simplices induced by the insertion of the edge. | ||
* If not empty at start, the content of the container should @b not be erased by the method. | ||
*/ | ||
void insert_edge_as_flag(int u, | ||
int v, | ||
Filtration_value fil, | ||
int dim_max, | ||
std::vector<Simplex_handle>& added_simplices); | ||
|
||
/** | ||
* @brief Returns the key associated to the given simplex. | ||
*/ | ||
Simplex_key key(Simplex_handle sh); | ||
|
||
/** | ||
* @brief Assignes the given value to the given simplex as a key. | ||
*/ | ||
void assign_key(Simplex_handle sh, Simplex_key key); | ||
|
||
/** | ||
* @brief Finds the given simplex in the complex and returns the associated simplex handle. | ||
* | ||
* @tparam VertexRange Range over the vertices of a simplex. | ||
* @param simplex Simplex to find represented by its vertices. | ||
* @return The simplex handle associated to @p simplex if the simplex is found. | ||
*/ | ||
template <class VertexRange> | ||
Simplex_handle find(const VertexRange& simplex); | ||
|
||
/** | ||
* @brief Returns the filtration value of the given simplex. | ||
*/ | ||
Filtration_value filtration(Simplex_handle sh); | ||
|
||
/** | ||
* @brief Returns a range (with begin() and end() methods) over the star of the given simplex, including the simplex. | ||
* | ||
* @param simplex Simplex to compute the star from. | ||
* @return A iterable range over the star of @p simplex. | ||
*/ | ||
auto star_simplex_range(const Simplex_handle simplex); | ||
|
||
/** | ||
* @brief Returns a range over the vertices of a simplex. The vertices have to be ordered monotonously by their | ||
* labels. | ||
*/ | ||
auto simplex_vertex_range(Simplex_handle sh) const; | ||
}; | ||
|
||
} // namespace zigzag_persistence | ||
} // namespace Gudhi | ||
|
||
#endif // CONCEPT_ZZ_STABLE_COMPLEX_TYPE_H_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,43 @@ namespace zigzag_persistence { | |
* which can be processed without overreaching memory space. For this purpose, it is possible to feed the module with | ||
* information about the filtration "on the fly" to avoid loading the whole filtration at once. Information about the | ||
* current barcode can be retrieved between any steps via callback methods. | ||
* | ||
* \subsection zigzagrips Oscillating Rips | ||
* | ||
* A typical example of zigzag filtrations are oscillating Rips filtrations. Similar to standard | ||
* @ref ripsdefinition "Rips filtrations", they completely depend on their edges. But here we look at neighborhoods | ||
* "oscillating" in size around the points, so edges are added but also removed. We refer for example to \cite osc_zz | ||
* for more theoretical details. | ||
* | ||
* This module implements the construction of such an oscillating Rips filtration as follows: | ||
* \image html "osc_rips.svg" width=70% | ||
* | ||
* If \f$ P \f$ is the set of points generating the rips filtration, \f$ P_i \f$ corresponds to the subset containing | ||
hschreiber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* the \f$ i \f$ first points. So, at each forward inclusion, one vertex is added. | ||
* | ||
* The superscript of \f$ \mathcal{R} \f$ corresponds to the filtration values which will be associated to the cycles. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe say that later? First we describe the zigzag. And once that's done, we can say that we (arbitrarily?) use this as "filtration value" for the output barcode. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was not the one who chose the epsilon values as filtration values, but yes, I think the reason was going in this direction. And it does make sense, so I didn't contested it. I presented it like that, because I didn't wanted to confuse the reader with theoretical details, but describing directly how it was actually implemented in Gudhi (while still making clear how the filtration looks like). In particular, because there exists other implemented variants which don't chose the exact same parametrization (for example, Dionysus, even though I can't find its documentation anymore...). But I could invert the positions of this paragraph with the one below and be more explicit about the fact that the choice of filtration is not part of the definition, just our choice. |
||
* The sequence of \f$ \varepsilon \f$ should be decreasing and end with \f$ 0 \f$. The sequence can either be specified | ||
* by the user or automatically generated by choosing the distance of the added point from the other already added | ||
* points from the set. In the second case, the user has to specify how the order of the points should be decided. | ||
* | ||
* The subscript of \f$ \mathcal{R} \f$ corresponds like usual to the radius of the Rips complex. It is generated from | ||
* the current epsilon / filtration value by multiplying it alternatively by two coefficients: \f$ \nu \leqslant \mu \f$. | ||
* Both multipliers have to be specified by the user. | ||
* | ||
* The construction is based on two types of classes: | ||
* - @ref Oscillating_rips_edge_iterator_range and @ref Oscillating_rips_edge_vector_range_constructor computes the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not shorten Oscillating_rips_edge_iterator_range to Oscillating_rips_edge_range? IIUC there is a range, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was just to contrast it with the vector version, i.e., to highlight that |
||
* range of inserted and removed vertices and edges in the filtration based on the elements descipted above. | ||
hschreiber marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it explained somewhere that one stores the whole filtration in a vector while the other computes the edges lazily as you iterate on it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is explained in the description of the classes themselves. But I am okay with repeating it here. |
||
* - @ref Oscillating_rips_simplex_iterator_range and @ref Oscillating_rips_simplex_vector_range_constructor infers | ||
* from @ref Oscillating_rips_edge_iterator_range or @ref Oscillating_rips_edge_vector_range_constructor all simplices | ||
* from higher dimensions (i.e. > 1) of the filtration if necessary. | ||
* For this purpose, a data structure able to represent a flag complex is additionally needed | ||
* (such as @ref Gudhi::Simplex_tree). Note that the edge range is passed by template, so the user | ||
* can potentially pass any other type of edge range as long as the dereferenced format corresponds and the sequence | ||
* makes sense as a zigzag filtration. | ||
* | ||
* If only the barcode of the filtration is of interest and not the filtration it-self, the helper method | ||
hschreiber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @ref compute_oscillating_rips_persistence can be used. It will directly feed to the filtration constructed by the | ||
* two classes above into @ref Zigzag_persistence "". | ||
* | ||
* \section zigzagexamples Examples | ||
* | ||
|
@@ -88,6 +125,8 @@ namespace zigzag_persistence { | |
* to use the @ref Filtered_zigzag_persistence_with_storage class within an input loop. | ||
* \li \gudhi_example_link{Zigzag_persistence,example_zzfiltration_from_file.cpp} - An example of a "stream-like" usage | ||
* with @ref Filtered_zigzag_persistence by reading off the filtration from a file. | ||
* \li \gudhi_example_link{Zigzag_persistence,example_oscillating_rips_persistence.cpp} - An example of a how to | ||
* compute the persistence of an oscillating rips filtration. | ||
* | ||
* @} | ||
*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want it on this page, which is more about persistence, while it is more about the geometry of building a zigzag filtration?
I am asking because Rips_complex and Persistent_cohomology are in 2 clearly separated pages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. I always saw it as an extension of the zigzag module, so I found it natural to put it there. But when you think about it without this point of view, the placement is a bit weird indeed. We could put it together with the Rips complex like you suggested above.
But then, should I also move the actual code ? For now the import of the ranges is via
#include <gudhi/Zigzag_persistence/oscillating_rips_simplex_ranges.h>
and only the helper method is imported directly with#include <gudhi/Oscillating_rips_persistence.h>
.