-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable flagser_count capabilities from C++ flagser and have two modul…
…es to handle coeff = or != 2 (#37) * Propagate flagser count_cells binding fix * Add flagser_count bindings * Update CMakeLists for compilation of new flagser count target * Add flagser_count functions * Add tests for flagser_count functions * Remove unsupported arguments * Remove OpenMP and add Threads and add flagser_coeff * Document and add flagser coeff * Update for new pybind11 modules * Improve and document flagser-count bindings * Propagate flagser bug fix * Remove Threads as a C++ dependency * Reshape dgms output of flagser_weight * Update directed docstring Signed-off-by: Guillaume Tauzin <[email protected]> Co-authored-by: Umberto Lupo <[email protected]>
- Loading branch information
Showing
10 changed files
with
385 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule flagser
updated
9 files
+48 −0 | .github/workflows/build.yml | |
+0 −23 | .travis.yml | |
+31 −8 | CMakeLists.txt | |
+1 −1 | include/complex/directed_flag_complex_computer.h | |
+1 −1 | include/complex/directed_flag_complex_in_memory_computer.h | |
+1 −0 | include/persistence.h | |
+6 −4 | src/flagser-count.cpp | |
+7 −1 | test/base.h | |
+0 −4 | test/test_flagser.cpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
"""Implementation of the python API for the cell count of the flagser C++ | ||
library.""" | ||
|
||
import numpy as np | ||
|
||
from ._utils import _extract_unweighted_graph, _extract_weighted_graph | ||
from .modules.flagser_count_pybind import compute_cell_count | ||
|
||
|
||
def flagser_count_unweighted(adjacency_matrix, min_dimension=0, | ||
max_dimension=np.inf, directed=True): | ||
"""Compute the cell count per dimension of a directed/undirected unweighted | ||
flag complex. | ||
From an adjacency matrix construct all cells forming its associated flag | ||
complex and compute their number per dimension. | ||
Parameters | ||
---------- | ||
adjacency_matrix : 2d ndarray or scipy.sparse matrix of shape \ | ||
(n_vertices, n_vertices), required | ||
Adjacency matrix of a directed/undirected unweighted graph. It is | ||
understood as a boolean matrix. Off-diagonal, ``0`` or ``False`` values | ||
denote abstent edges while non-``0`` or ``True`` values denote edges | ||
which are present. Diagonal values are ignored. | ||
directed : bool, optional, default: ``True`` | ||
If ``True``, computes homology for the directed flad complex determined | ||
by `adjacency_matrix`. If ``False``, computes homology for the | ||
undirected flag complex obtained by considering all edges as | ||
undirected, and it is therefore sufficient (but not necessary) | ||
to pass an upper-triangular matrix. | ||
Returns | ||
------- | ||
out : list of int | ||
Cell counts (number of simplices), per dimension greater than or equal | ||
to `min_dimension` and less than `max_dimension`. | ||
Notes | ||
----- | ||
The input graphs cannot contain self-loops, i.e. edges that start and end | ||
in the same vertex, therefore diagonal elements of the input adjacency | ||
matrix will be ignored. | ||
References | ||
---------- | ||
.. [1] D. Luetgehetmann, "Documentation of the C++ flagser library"; | ||
`GitHub: luetge/flagser <https://github.com/luetge/flagser/blob/\ | ||
master/docs/documentation_flagser.pdf>`_. | ||
""" | ||
# Extract vertices and edges | ||
vertices, edges = _extract_unweighted_graph(adjacency_matrix) | ||
|
||
# Call flagser_count binding | ||
cell_count = compute_cell_count(vertices, edges, directed) | ||
|
||
return cell_count | ||
|
||
|
||
def flagser_count_weighted(adjacency_matrix, max_edge_weight=None, | ||
directed=True): | ||
"""Compute the cell count per dimension of a directed/undirected | ||
filtered flag complex. | ||
From an adjacency matrix construct a filtered flag complex as a sequence of | ||
its cells associated to their filtration values and compute the number of | ||
cells per dimension at the end of the filtration. | ||
Parameters | ||
---------- | ||
adjacency_matrix : 2d ndarray or scipy.sparse matrix of shape \ | ||
(n_vertices, n_vertices), required | ||
Matrix representation of a directed/undirected weighted graph. Diagonal | ||
elements are vertex weights. The way zero values are handled depends on | ||
the format of the matrix. If the matrix is a dense ``numpy.ndarray``, | ||
zero values denote zero-weighted edges. If the matrix is a sparse | ||
``scipy.sparse`` matrix, explicitly stored off-diagonal zeros and all | ||
diagonal zeros denote zero-weighted edges. Off-diagonal values that | ||
have not been explicitely stored are treated by ``scipy.sparse`` as | ||
zeros but will be understood as infinitely-valued edges, i.e., edges | ||
absent from the filtration. | ||
max_edge_weight : int or float or ``None``, optional, default: ``None`` | ||
Maximum edge weight to be considered in the filtration. All edge | ||
weights greater than that value will be considered as | ||
infinitely-valued, i.e., absent from the filtration. If ``None``, all | ||
finite edge weights are considered. | ||
directed : bool, optional, default: ``True`` | ||
If ``True``, computes persistent homology for the directed filtered | ||
flag complex determined by `adjacency_matrix`. If ``False``, computes | ||
persistent homology for the undirected filtered flag complex obtained | ||
by considering all weighted edges as undirected, and if two directed | ||
edges corresponding to the same undirected edge are explicitly assigned | ||
different weights and neither exceeds `max_edge_weight`, only the one | ||
in the upper triangular part of the adjacency matrix is considered. | ||
Therefore: | ||
- if `max_edge_weight` is ``numpy.inf``, it is sufficient to pass a | ||
(dense or sparse) upper-triangular matrix; | ||
- if `max_edge_weight` is finite, it is recommended to pass either a | ||
symmetric dense matrix, or a sparse upper-triangular matrix. | ||
Returns | ||
------- | ||
out : list of int | ||
Cell counts (number of simplices) at filtration value | ||
`max_edge_weight`, per dimension. | ||
Notes | ||
----- | ||
The input graphs cannot contain self-loops, i.e. edges that start and end | ||
in the same vertex, therefore diagonal elements of the input adjacency | ||
matrix store vertex weights. | ||
References | ||
---------- | ||
.. [1] D. Luetgehetmann, "Documentation of the C++ flagser library"; | ||
`GitHub: luetge/flagser <https://github.com/luetge/flagser/blob/\ | ||
master/docs/documentation_flagser.pdf>`_. | ||
""" | ||
# Extract vertices and edges weights | ||
vertices, edges = _extract_weighted_graph(adjacency_matrix, | ||
max_edge_weight) | ||
|
||
# Call flagser_count binding | ||
cell_count = compute_cell_count(vertices, edges, directed) | ||
|
||
return cell_count |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
"""Testing for the python bindings of the C++ flagser library.""" | ||
|
||
import os | ||
|
||
from numpy.testing import assert_almost_equal | ||
|
||
from pyflagser import load_unweighted_flag, load_weighted_flag, \ | ||
flagser_count_unweighted, flagser_count_weighted | ||
|
||
|
||
cell_count = { | ||
'a.flag': [5, 7, 1], | ||
'b.flag': [4, 6, 3], | ||
'c.flag': [8, 12], | ||
'd.flag': [5, 9, 6], | ||
'e.flag': [5, 9, 7, 2], | ||
'f.flag': [3, 5, 3], | ||
'd2.flag': [2, 2], | ||
'd3.flag': [3, 6, 6], | ||
'd3-allzero.flag': [3, 6, 6], | ||
'double-d3.flag': [4, 10, 12], | ||
'double-d3-allzero.flag': [4, 10, 12], | ||
'd4.flag': [4, 12, 24, 24], | ||
'd4-allzero.flag': [4, 12, 24, 24], | ||
'd5.flag': [5, 20, 60, 120, 120], | ||
'd7.flag': [7, 42, 210, 840, 2520, 5040, 5040], | ||
'medium-test-data.flag': [31346, 68652, 12694, 250], | ||
'd10.flag': [10, 90, 720, 5040, 30240, 151200, 604800, | ||
1814400, 3628800, 3628800], | ||
} | ||
|
||
|
||
def test_unweighted(flag_file): | ||
adjacency_matrix = load_unweighted_flag(flag_file, fmt='dense') | ||
cell_count_exp = cell_count[os.path.split(flag_file)[1]] | ||
cell_count_res = flagser_count_unweighted(adjacency_matrix) | ||
assert_almost_equal(cell_count_res, cell_count_exp) | ||
|
||
|
||
def test_weighted(flag_file): | ||
adjacency_matrix = load_weighted_flag(flag_file, fmt='coo') | ||
cell_count_exp = cell_count[os.path.split(flag_file)[1]] | ||
cell_count_res = flagser_count_weighted(adjacency_matrix) | ||
assert_almost_equal(cell_count_res, cell_count_exp) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.