Skip to content

Commit

Permalink
Merge pull request GUDHI#917 from hschreiber/zigzag_persistence
Browse files Browse the repository at this point in the history
Zigzag persistence part1
  • Loading branch information
VincentRouvreau authored Oct 24, 2024
2 parents 1cf5a3d + f4c5345 commit 139e285
Show file tree
Hide file tree
Showing 20 changed files with 2,485 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ add_gudhi_module(Toplex_map)
add_gudhi_module(Witness_complex)
add_gudhi_module(Nerve_GIC)
add_gudhi_module(Persistence_matrix)
add_gudhi_module(Zigzag_persistence)

# Include module CMake subdirectories
# GUDHI_SUB_DIRECTORIES is managed in CMAKE_MODULE_PATH/GUDHI_modules.cmake
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ add_gudhi_module(Toplex_map)
add_gudhi_module(Witness_complex)
add_gudhi_module(Nerve_GIC)
add_gudhi_module(Persistence_matrix)
add_gudhi_module(Zigzag_persistence)

set(GUDHI_BIBLIO_DIR ${CMAKE_SOURCE_DIR})
# For "make doxygen" - Requires GUDHI_USER_VERSION_DIR to be set
Expand Down
80 changes: 80 additions & 0 deletions src/Zigzag_persistence/concept/ZigzagOptions.h
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_
12 changes: 12 additions & 0 deletions src/Zigzag_persistence/doc/COPYRIGHT
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.
See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.

Author(s): Hannah Schreiber

Copyright (C) 2024 Inria

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.
97 changes: 97 additions & 0 deletions src/Zigzag_persistence/doc/Intro_zigzag_persistence.h
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.
*
* \subsection zigzaginterface Stream-like interface
*
* 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>
* @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_
Binary file added src/Zigzag_persistence/doc/zigzag_ex.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions src/Zigzag_persistence/example/CMakeLists.txt
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;

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.

// 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;
}

return 0;
}
Loading

0 comments on commit 139e285

Please sign in to comment.