-
Notifications
You must be signed in to change notification settings - Fork 66
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 part1 #917
Changes from 67 commits
5407637
f03a8bf
3f8409f
2e5a20b
bfc5642
688b381
f7087fc
15fbc53
87ba652
d8d07c5
0644ca6
394e33e
7178d45
5c4f9d7
2c79bc2
f85ffb9
902db3b
da925a0
5208e5d
4436039
e384378
0c7d3e6
ece1294
20ae249
df39f9c
c192cd6
cadfb5c
03e7b7d
26161a7
9c44409
3fb6227
2b46f13
dcc8bad
dfdaaac
f7a431b
8698036
91dca3b
e51a1f3
585432c
55d510a
0c332e3
bf19ed5
46a7d8a
c42a263
efa2546
cfdc161
e025cec
99f99ae
6dc4219
9446bad
32e3053
bbd3d90
c7edb91
3472160
744ac47
7d84dbf
564f751
bd6d9b5
4de6a26
4f40d8b
6a0fad2
2b2a569
1e31a4b
54c00a6
5db9b3a
915b5ea
b3158e3
5213928
f4c5345
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,80 @@ | ||
/* 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) 2024 Inria | ||
* | ||
* Modification(s): | ||
* - YYYY/MM Author: Description of the modification | ||
*/ | ||
|
||
#ifndef CONCEPT_ZZ_OPTIONS_TYPE_H_ | ||
#define CONCEPT_ZZ_OPTIONS_TYPE_H_ | ||
|
||
/** @file ZigzagOptions.h | ||
* @brief Contains @ref Gudhi::zigzag_persistence::ZigzagOptions and | ||
* @ref Gudhi::zigzag_persistence::FilteredZigzagOptions concept. | ||
*/ | ||
|
||
namespace Gudhi { | ||
namespace zigzag_persistence { | ||
|
||
/** | ||
* @ingroup zigzag_persistence | ||
* | ||
* @brief List of options used for the filtered zigzag persistence computation. | ||
*/ | ||
struct FilteredZigzagOptions { | ||
/** | ||
* @brief Numerical type for the cell IDs used internally and other indexations. It must be signed. | ||
*/ | ||
using Internal_key = unspecified; | ||
|
||
/** | ||
* @brief Type for the cell IDs used at insertion and in the boundaries given as argument. | ||
* Has to be usable as key in a hashtable, so "hashable" and comparable. | ||
*/ | ||
using Cell_key = unspecified; | ||
|
||
/** | ||
* @brief Type for filtration values. | ||
*/ | ||
using Filtration_value = unspecified; | ||
|
||
/** | ||
* @brief Type for the dimension values. | ||
*/ | ||
using Dimension = unspecified; | ||
|
||
/** | ||
* @brief Column type used by the internal matrix. | ||
*/ | ||
static const Gudhi::persistence_matrix::Column_types column_type; | ||
}; | ||
|
||
/** | ||
* @ingroup zigzag_persistence | ||
* | ||
* @brief List of options used for the zigzag persistence computation. | ||
*/ | ||
struct ZigzagOptions { | ||
/** | ||
* @brief Numerical type for the cell IDs used internally and other indexations. It must be signed. | ||
*/ | ||
using Internal_key = unspecified; | ||
|
||
/** | ||
* @brief Type for the dimension values. | ||
*/ | ||
using Dimension = unspecified; | ||
|
||
/** | ||
* @brief Column type used by the internal matrix. | ||
*/ | ||
static const Gudhi::persistence_matrix::Column_types column_type; | ||
}; | ||
|
||
} // namespace zigzag_persistence | ||
} // namespace Gudhi | ||
|
||
#endif // CONCEPT_ZZ_OPTIONS_TYPE_H_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
The files of this directory are part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. | ||
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. @VincentRouvreau Can you remind me why we have this file in every doc/ subdirectory? Is it because there are images, where we cannot include the text? And having some global statement somewhere would have been complicated because of exceptions? |
||
See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. | ||
|
||
Author(s): Vincent Rouvreau | ||
|
||
Copyright (C) 2015 Inria | ||
hschreiber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
This gives everyone the freedoms to use openFrameworks in any context: | ||
commercial or non-commercial, public or private, open or closed source. | ||
|
||
You should have received a copy of the MIT License along with this program. | ||
If not, see https://opensource.org/licenses/MIT. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* 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 DOC_ZIGZAG_PERSISTENCE_INTRO_ZIGZAG_PERSISTENCE_H_ | ||
#define DOC_ZIGZAG_PERSISTENCE_INTRO_ZIGZAG_PERSISTENCE_H_ | ||
|
||
// needs namespace for Doxygen to link on classes | ||
namespace Gudhi { | ||
namespace zigzag_persistence { | ||
|
||
/** \defgroup zigzag_persistence Zigzag Persistence | ||
* @{ | ||
* \author Clément Maria, Hannah Schreiber | ||
* | ||
* \section zigzagintro Zigzag Persistence | ||
* | ||
* We refer to the introduction page \ref persistent_cohomology for persistent (co)homology for an introduction | ||
* to the topic. | ||
* Zigzag persistence is a generalization of the latter. While standard persistence only allows to grow the filtered | ||
* complex by adding cells, zigzag persistence also allows removals. Hence the name "zigzag", as the module | ||
* diagram will have arrows alternating between forward and backward. | ||
* | ||
* The module consists of the @ref Zigzag_persistence class and two wrappers @ref Filtered_zigzag_persistence and | ||
* @ref Filtered_zigzag_persistence_with_storage "": | ||
* - @ref Zigzag_persistence computes the persistence of a sequence of insertions and removals. A cell can be inserted | ||
* or removed one at a time and the returned persistence pairs / bars are indexed on the operation numbers. | ||
* For example, if a cycle is born at operation number 6 and dies at operation number 7, it will output a bar starting | ||
* at 6 and ending at 7. | ||
* - @ref Filtered_zigzag_persistence and @ref Filtered_zigzag_persistence_with_storage are adding the notion of | ||
* "filtration value" to @ref Zigzag_persistence. At each call, an operation can be associated to a filtration value, | ||
* which will be used to index the returned bars instead (bars with new length 0 are then ignored). The two classes | ||
* also have more flexible inputs (the boundaries do not have to be ordered, nor identified continuously | ||
* from 0). The difference between both classes is on the way they manage the memory: @ref Filtered_zigzag_persistence | ||
* removes systematically all unnecessary information and outputs a pair as soon it is closed, while | ||
* @ref Filtered_zigzag_persistence_with_storage will store all informations about filtration values and bars until the | ||
* end and output the pairs only when asked. Depending on the use and the length of the filtration, one will be more | ||
* efficient than the other and vice versa. | ||
* | ||
* The implementation is based on the algorithm introduced in \cite zigzag. | ||
* | ||
hschreiber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* \subsection zigzaginterface Stream-like interface | ||
mglisse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* As removals are possible in zigzag filtration, the maximal size of the complex does not depend on the length of the | ||
* filtration anymore. This makes it possible to build very long fine tuned filtrations with relatively small complexes | ||
* 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. | ||
* | ||
* \section zigzagexamples Examples | ||
* | ||
* \subsection zzminusage Minimalistic examples | ||
* | ||
* \li \gudhi_example_link{Zigzag_persistence,example_usage_zigzag_persistence.cpp} - A simple example to showcase how | ||
* to use the @ref Zigzag_persistence class to compute a barcode. | ||
* <details> | ||
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. Note that this doesn't work with the version of doxygen we use in the CI, we really need to upgrade before the next release (not this PR). |
||
* @dontinclude example_usage_zigzag_persistence.cpp | ||
* @skip #include | ||
* @until return 0; | ||
* @skipline } | ||
* </details> | ||
* \li \gudhi_example_link{Zigzag_persistence,example_usage_filtered_zigzag_persistence.cpp} - A simple example to | ||
* showcase how to use the @ref Filtered_zigzag_persistence class to compute a barcode. | ||
* <details> | ||
* @dontinclude example_usage_filtered_zigzag_persistence.cpp | ||
* @skip #include | ||
* @until return 0; | ||
* @skipline } | ||
* </details> | ||
* \li \gudhi_example_link{Zigzag_persistence,example_usage_filtered_zigzag_persistence_with_storage.cpp} - A simple | ||
* example to showcase how to use the @ref Filtered_zigzag_persistence_with_storage class to compute a barcode. | ||
* <details open> | ||
* @dontinclude example_usage_filtered_zigzag_persistence_with_storage.cpp | ||
* @skip #include | ||
* @until return 0; | ||
* @skipline } | ||
* </details> | ||
* | ||
* \subsection zzexamples More elaborate examples | ||
* | ||
* \li \gudhi_example_link{Zigzag_persistence,example_zigzag_filtration_as_input_loop.cpp} - A simple example to showcase how | ||
* 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. | ||
* | ||
* @} | ||
*/ | ||
} // namespace zigzag_persistence | ||
} // namespace Gudhi | ||
|
||
#endif // DOC_ZIGZAG_PERSISTENCE_INTRO_ZIGZAG_PERSISTENCE_H_ |
hschreiber marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
project(Zigzag_persistence_examples) | ||
|
||
add_executable_with_targets(Zigzag_persistence_example_usage_zigzag_persistence example_usage_zigzag_persistence.cpp TBB::tbb) | ||
add_test(NAME Zigzag_persistence_example_usage_zigzag_persistence COMMAND $<TARGET_FILE:Zigzag_persistence_example_usage_zigzag_persistence>) | ||
|
||
add_executable_with_targets(Zigzag_persistence_example_usage_filtered_zigzag_persistence example_usage_filtered_zigzag_persistence.cpp TBB::tbb) | ||
add_test(NAME Zigzag_persistence_example_usage_filtered_zigzag_persistence COMMAND $<TARGET_FILE:Zigzag_persistence_example_usage_filtered_zigzag_persistence>) | ||
|
||
add_executable_with_targets(Zigzag_persistence_example_usage_filtered_zigzag_persistence_with_storage example_usage_filtered_zigzag_persistence_with_storage.cpp TBB::tbb) | ||
add_test(NAME Zigzag_persistence_example_usage_filtered_zigzag_persistence_with_storage COMMAND $<TARGET_FILE:Zigzag_persistence_example_usage_filtered_zigzag_persistence_with_storage>) | ||
|
||
add_executable_with_targets(Zigzag_persistence_example_zigzag_filtration_as_input_loop example_zigzag_filtration_as_input_loop.cpp TBB::tbb) | ||
add_test(NAME Zigzag_persistence_example_zigzag_filtration_as_input_loop COMMAND $<TARGET_FILE:Zigzag_persistence_example_zigzag_filtration_as_input_loop>) | ||
|
||
add_executable_with_targets(Zigzag_persistence_example_zzfiltration_from_file example_zzfiltration_from_file.cpp TBB::tbb) | ||
file(COPY "zigzag_filtration_example.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) | ||
add_test(NAME Zigzag_persistence_example_zzfiltration_from_file COMMAND $<TARGET_FILE:Zigzag_persistence_example_zzfiltration_from_file> "${CMAKE_CURRENT_BINARY_DIR}/zigzag_filtration_example.txt") | ||
|
||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* 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) 2024 Inria | ||
* | ||
* Modification(s): | ||
* - YYYY/MM Author: Description of the modification | ||
*/ | ||
|
||
#include <iostream> | ||
|
||
#include <gudhi/filtered_zigzag_persistence.h> | ||
|
||
using Zigzag_persistence = Gudhi::zigzag_persistence::Filtered_zigzag_persistence<>; | ||
using Dimension = Zigzag_persistence::Dimension; | ||
using Filtration_value = Zigzag_persistence::Filtration_value; | ||
|
||
int main() { | ||
std::clog << "********* Minimalistic example of usage of the Filtered_zigzag_persistence class ********" << std::endl; | ||
|
||
// Filtered_zigzag_persistence(callback) with for example callback method as a anonymous lambda | ||
Zigzag_persistence zp([](Dimension dim, Filtration_value birth, Filtration_value death) { | ||
std::cout << "[" << dim << "] " << birth << " - " << death << std::endl; | ||
}); | ||
|
||
// It is important that the operations of insertions and removals are made **in the same order** as in the zigzag | ||
// filtration ones wants to compute the barcode from. | ||
// A cell can be identified in the boundaries by any given numerical label, it is just important that the given | ||
// filtration values are monotonous (ie., either only increasing or only decreasing). | ||
|
||
// inserts vertex 2 at filtration value 0.1 -> birth at 0.1 of 0-cycle | ||
zp.insert_cell(2, {}, 0, 0.1); | ||
// inserts vertex 4 at filtration value 0.1 -> birth at 0.1 of 0-cycle | ||
zp.insert_cell(4, {}, 0, 0.1); | ||
// inserts edge 5 = (2,4) at filtration value 0.3 -> death at 0.3 -> outputs (0, 0.1, 0.3) | ||
zp.insert_cell(5, {2, 4}, 1, 0.3); | ||
// inserts vertex 3 at filtration value 0.4 -> birth at 0.4 of 0-cycle | ||
zp.insert_cell(3, {}, 0, 0.4); | ||
// inserts edge 6 = (2,3) at filtration value 0.4 -> death at 0.4 of the cycle born at 0.4 -> outputs nothing | ||
zp.insert_cell(6, {2, 3}, 1, 0.4); | ||
// inserts edge 9 = (3,4) at filtration value 1.2 -> birth at 1.2 of 1-cycle | ||
zp.insert_cell(9, {4, 3}, 1, 1.2); | ||
// removes edge 6 at filtration value 1.5 -> death at 1.5 -> outputs (1, 1.2, 1.5) | ||
zp.remove_cell(6, 1.5); | ||
// removes edge 5 at filtration value 2.0 -> birth at 2.0 of 0-cycle | ||
zp.remove_cell(5, 2.0); | ||
|
||
// Only the closed bars where output so far, so the open/infinite bars still need to be retrieved. | ||
|
||
// in this example, computes (0, 0.1) and (0, 2.0) | ||
zp.get_current_infinite_intervals([](Dimension dim, Filtration_value birth) { | ||
std::cout << "[" << dim << "] " << birth << " - inf" << std::endl; | ||
}); | ||
|
||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* 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) 2024 Inria | ||
* | ||
* Modification(s): | ||
* - YYYY/MM Author: Description of the modification | ||
*/ | ||
|
||
#include <iostream> | ||
|
||
#include <gudhi/filtered_zigzag_persistence.h> | ||
|
||
using Zigzag_persistence = Gudhi::zigzag_persistence::Filtered_zigzag_persistence_with_storage<>; | ||
|
||
int main() { | ||
std::clog << "** Minimalistic example of usage of the Filtered_zigzag_persistence_with_storage class **" << std::endl; | ||
hschreiber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Zigzag_persistence zp; | ||
|
||
// It is important that the operations of insertions and removals are made **in the same order** as in the zigzag | ||
// filtration ones wants to compute the barcode from. | ||
// A cell can be identified in the boundaries by any given numerical label, it is just important that the given | ||
// filtration values are monotonous (ie., either only increasing or only decreasing). | ||
|
||
// inserts vertex 2 at filtration value 0.1 -> birth at 0.1 of 0-cycle | ||
zp.insert_cell(2, {}, 0, 0.1); | ||
// inserts vertex 4 at filtration value 0.1 -> birth at 0.1 of 0-cycle | ||
zp.insert_cell(4, {}, 0, 0.1); | ||
// inserts edge 5 = (2,4) at filtration value 0.3 -> death at 0.3 -> stores (0, 0.1, 0.3) | ||
zp.insert_cell(5, {2, 4}, 1, 0.3); | ||
// inserts vertex 3 at filtration value 0.4 -> birth at 0.4 of 0-cycle | ||
zp.insert_cell(3, {}, 0, 0.4); | ||
// inserts edge 6 = (2,3) at filtration value 0.4 -> death at 0.4 of the cycle born at 0.4 -> stores nothing | ||
zp.insert_cell(6, {2, 3}, 1, 0.4); | ||
// inserts edge 9 = (3,4) at filtration value 1.2 -> birth at 1.2 of 1-cycle | ||
zp.insert_cell(9, {4, 3}, 1, 1.2); | ||
// removes edge 6 at filtration value 1.5 -> death at 1.5 -> stores (1, 1.2, 1.5) | ||
zp.remove_cell(6, 1.5); | ||
// removes edge 5 at filtration value 2.0 -> birth at 2.0 of 0-cycle | ||
zp.remove_cell(5, 2.0); | ||
|
||
// The bars are stored within the class and where not output at all for now. | ||
hschreiber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// get all bars in a vector | ||
auto barcode = zp.get_persistence_diagram(); | ||
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 wonder if we should use 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 wanted to keep the example as simple as possible. It shows also what the default parameters do. But I have no strong opinion about it. |
||
|
||
// do something with the vector, e.g., stream out content: | ||
for (auto& bar : barcode) { | ||
std::cout << bar << std::endl; | ||
} | ||
|
||
return 0; | ||
hschreiber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
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.
Would it make sense to derive from ZigzagOptions, as a way to say that this concept refines the other one?
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.
Yes, but I wanted to wait to see what I do with
erase_birth_history
and if there will not be other not-shared options.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.
It looks like no non-shared option has popped up?
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.
Yes. I was just suddenly not sure how clear it is to make one concept inherit the other in the documentation. It risk to be overlooked, no? But you are right. I will change that in the other branch with the oscillating rips.
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.
You can also add in the text that it refines the other concept. Yes, we'll see in the other branch what it looks like.