-
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 54 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 Type for the face IDs used internally and other indexations. It must be signed. | ||
*/ | ||
using internal_key = unspecified; | ||
|
||
/** | ||
* @brief Type for the face IDs used at insertion and in the boundaries given as argument. | ||
hschreiber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* Has to be usable as key in a hashtable, so "hashable" and comparable. | ||
*/ | ||
using face_key = unspecified; | ||
|
||
/** | ||
* @brief Type for filtration values. | ||
*/ | ||
using filtration_value = unspecified; | ||
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 would have to weigh in, but I think the type 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 use lower case for all types which are or have high probability to be native types and upper case for classes/structs. But true, it makes 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. Did you get inspiration from somewhere for this style? Since we haven't used that in the rest of Gudhi, I am a bit reluctant to introduce this inconsistency whose benefits are not really obvious to me. 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 don't remember where I got it from, but I think it was from a comment of someone, as I didn't paid much attention to this detail before. So either it was from someone working on Gudhi, or from one of my coauthors. Like I said, I can change that for Gudhi if you prefer. Is it only for 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 don't know specifically about Gudhi (although we seem to have mostly done it this way), but it is fairly common to capitalize all types, so you can tell immediately if something is a type or a variable (in a wide sense that also includes functions). You can wait for Vincent to come back, but I think I would prefer to stick to this convention. It also makes it unnecessary (although not forbidden) to end a type name in |
||
|
||
/** | ||
* @brief Type for the dimension values. | ||
*/ | ||
using dimension_type = 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 Type for the face IDs used internally and other indexations. It must be signed. | ||
*/ | ||
using internal_key = unspecified; | ||
|
||
/** | ||
* @brief Type for the dimension values. | ||
*/ | ||
using dimension_type = 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,206 @@ | ||
/* 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 faces, 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 face 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. | ||
* | ||
hschreiber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* \section zigzagexamples Examples | ||
* | ||
* \subsection zzminusage Minimalistic example of usage | ||
* | ||
* ### Includes | ||
* | ||
* #### Zigzag_persistence | ||
* ``` | ||
* #include <gudhi/zigzag_persistence.h> | ||
* ``` | ||
* #### Filtered_zigzag_persistence and Filtered_zigzag_persistence_with_storage | ||
* ``` | ||
* #include <gudhi/filtered_zigzag_persistence.h> | ||
* ``` | ||
* | ||
* ### Useful aliases | ||
* | ||
* ``` | ||
* using Zigzag_persistence = Gudhi::zigzag_persistence::Zigzag_persistence<>; | ||
* using Filtered_zigzag_persistence = Gudhi::zigzag_persistence::Filtered_zigzag_persistence<>; | ||
* using Filtered_zigzag_persistence_with_storage = Gudhi::zigzag_persistence::Filtered_zigzag_persistence_with_storage<>; | ||
* | ||
* using dimension_type = Zigzag_persistence::dimension_type; | ||
* using index_type = Zigzag_persistence::index; | ||
* using filtration_value_type = Filtered_zigzag_persistence::filtration_value; | ||
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 looks strange that 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 agree, but when I just write Like I said, I have no preferences on this. But then I would change all type names once and for all to homogenize them. So, if I understood well, your preference would be: all types start with a capitalized letter and only the name of object without any "_type" or "_t" at the end? Eg. 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.
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. Ok, then I would do a PR for the matrix module too, to keep things coherent. |
||
* ``` | ||
* | ||
* ### Construction with default values | ||
* | ||
* #### Zigzag_persistence | ||
* ``` | ||
* //Zigzag_persistence(callback) with for example callback method as a anonymous lambda | ||
* Zigzag_persistence zp([](dimension_type dim, index_type birth, index_type death) { | ||
* std::cout << "[" << dim << "] " << birth << " - " << death << std::endl; | ||
* }); | ||
* ``` | ||
* | ||
* #### Filtered_zigzag_persistence | ||
* ``` | ||
* //Filtered_zigzag_persistence(callback) with for example callback method as a anonymous lambda | ||
* Filtered_zigzag_persistence zp([](dimension_type dim, filtration_value_type birth, filtration_value_type death) { | ||
* std::cout << "[" << dim << "] " << birth << " - " << death << std::endl; | ||
* }); | ||
* ``` | ||
* | ||
* #### Filtered_zigzag_persistence_with_storage | ||
* ``` | ||
* Filtered_zigzag_persistence_with_storage zp; | ||
* ``` | ||
* | ||
* ### Input of the zigzag sequence/filtration | ||
* | ||
* In all cases, 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. | ||
* | ||
* #### Zigzag_persistence | ||
* | ||
* A face has to be identified in the boundaries by the operation number the face was inserted with in the sequence. | ||
* | ||
* ``` | ||
* //inserts vertex 0 -> birth at 0 of 0-cycle | ||
* zp.insert_face({}, 0); | ||
* //inserts vertex 1 -> birth at 1 of 0-cycle | ||
* zp.insert_face({}, 0); | ||
* //inserts edge 2 = (0,1) -> death at 2 -> outputs (0, 1, 2) | ||
* zp.insert_face({0, 1}, 1); | ||
* //inserts vertex 3 -> birth at 3 of 0-cycle | ||
* zp.insert_face({}, 0); | ||
* //inserts edge 4 = (0,3) -> death at 4 -> outputs (0, 3, 4) | ||
* zp.insert_face({0, 3}, 1); | ||
* //inserts edge 5 = (1,3) -> birth at 5 of 1-cycle | ||
* zp.insert_face({1, 3}, 1); | ||
* //removes edge 4 -> death at 6 -> outputs (1, 5, 6) | ||
* zp.remove_face(4, 1); | ||
* //removes edge 2 -> birth at 7 of 0-cycle | ||
* zp.remove_face(2, 1); | ||
* ``` | ||
* | ||
* #### Filtered_zigzag_persistence and Filtered_zigzag_persistence_with_storage | ||
* | ||
* A face 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_face(2, {}, 0, 0.1); | ||
* //inserts vertex 4 at filtration value 0.1 -> birth at 0.1 of 0-cycle | ||
* zp.insert_face(4, {}, 0, 0.1); | ||
* //inserts edge 5 = (2,4) at filtration value 0.3 -> death at 0.3 -> outputs/stores (0, 0.1, 0.3) | ||
* zp.insert_face(5, {2, 4}, 1, 0.3); | ||
* //inserts vertex 3 at filtration value 0.4 -> birth at 0.4 of 0-cycle | ||
* zp.insert_face(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/stores nothing | ||
* zp.insert_face(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_face(9, {4, 3}, 1, 1.2); | ||
* //removes edge 6 at filtration value 1.5 -> death at 1.5 -> outputs/stores (1, 1.2, 1.5) | ||
* zp.remove_face(6, 1, 1.5); | ||
* //removes edge 5 at filtration value 2.0 -> birth at 2.0 of 0-cycle | ||
* zp.remove_face(5, 1, 2.0); | ||
* ``` | ||
* | ||
* ### Finalizations | ||
* | ||
* For Zigzag_persistence and Filtered_zigzag_persistence, only the closed bars where output so far, so | ||
* the open/infinite bars still need to be retrieved. For Filtered_zigzag_persistence_with_storage, the bars are | ||
* stored within the class and where not output at all for now. | ||
* | ||
* #### Zigzag_persistence | ||
* ``` | ||
* //retrieve infinite bars, that is cycles which were born but did not die. | ||
* //in this example, outputs (0, 0) and (0, 7) | ||
* zp.get_current_infinite_intervals([](dimension_type dim, index_type birth){ | ||
* std::cout << "[" << dim << "] " << birth << " - inf" << std::endl; | ||
* }); | ||
* ``` | ||
* | ||
* #### Filtered_zigzag_persistence | ||
* ``` | ||
* //retrieve infinite bars, that is cycles which were born but did not die. | ||
* //in this example, outputs (0, 0.1) and (0, 2.0) | ||
* zp.get_current_infinite_intervals([](dimension_type dim, filtration_value_type birth){ | ||
* std::cout << "[" << dim << "] " << birth << " - inf" << std::endl; | ||
* }); | ||
* ``` | ||
* | ||
* #### Filtered_zigzag_persistence_with_storage | ||
* ``` | ||
* //get all bars in a vector | ||
* auto barcode = zp.get_persistence_diagram(); | ||
* | ||
* //do something with the vector, e.g., stream out content: | ||
* for (auto& bar : barcode) { | ||
* std::cout << bar << std::endl; | ||
* } | ||
* ``` | ||
* | ||
* \subsection zzexamples More elaborate examples | ||
* | ||
* \li \gudhi_example_link{Zigzag_persistence,example_simple_zigzag_filtration.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,11 @@ | ||
project(Zigzag_persistence_examples) | ||
|
||
add_executable_with_targets(Zigzag_persistence_example_simple_zigzag_filtration example_simple_zigzag_filtration.cpp TBB::tbb) | ||
add_test(NAME Zigzag_persistence_example_simple_zigzag_filtration COMMAND $<TARGET_FILE:Zigzag_persistence_example_simple_zigzag_filtration>) | ||
|
||
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") | ||
|
||
|
||
|
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.