Skip to content

Commit

Permalink
Release v0.2.1 (#25)
Browse files Browse the repository at this point in the history
* Fix forwarding arguments for flagser (#21)

* Add test for filtrations

* Align CMakeLists as used in giotto-tda

Fix windows compilation, disable AVX instructions

* Bump to v0.2.1 (#24)
  • Loading branch information
ulupo authored Mar 21, 2020
1 parent 3aa8968 commit b102b1f
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 17 deletions.
19 changes: 11 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ set(BINDINGS_DIR "src")
find_package(OpenMP)

pybind11_add_module(flagser_pybind "${BINDINGS_DIR}/flagser_bindings.cpp")
include_directories(.)

if(OpenMP_FOUND)
target_link_libraries(flagser_pybind PRIVATE OpenMP::OpenMP_CXX)
endif()
target_compile_options(flagser_pybind PUBLIC -Ofast -DNDEBUG)
target_compile_options(flagser_pybind PUBLIC $<$<CONFIG:DEBUG>:-O2 -ggdb -D_GLIBCXX_DEBUG>)
# Cannot have two inlined namespace !
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(flagser_pybind PUBLIC -march=native -D_GLIBCXX_PARALLEL)
target_link_libraries(flagser_pybind PRIVATE)
endif()

target_compile_definitions(flagser_pybind PRIVATE RETRIEVE_PERSISTENCE=1)
target_include_directories(flagser_pybind PRIVATE .)

if(MSVC)
target_compile_options(flagser_pybind PUBLIC $<$<CONFIG:RELEASE>: /Wall /O2>)
target_compile_options(flagser_pybind PUBLIC $<$<CONFIG:DEBUG>:/O1 /DEBUG:FULL /Zi /Zo>)
else()
target_compile_options(flagser_pybind PUBLIC $<$<CONFIG:RELEASE>: -Ofast>)
target_compile_options(flagser_pybind PUBLIC $<$<CONFIG:DEBUG>: -O2 -ggdb -D_GLIBCXX_DEBUG>)
endif()
71 changes: 67 additions & 4 deletions RELEASE.rst
Original file line number Diff line number Diff line change
@@ -1,16 +1,79 @@
Release 0.2.1
==============

Major Features and Improvements
-------------------------------

``CMakeLists`` updated to enable compile flags on MSVC. This improves performance on Windows systems.

Bug Fixes
---------

Hotfix addressing multiples issues where forwarding arguments to C++ ``flagser``:

- ``filtration`` was not correctly forwarded and it always fallback to zero filtration.
- ``max-dim`` and ``min-dim`` were always equal to 0.

``CMakeLists`` updated to disable AVX instructions. This addresses incompatibilities observed with specific hardware setups.

Backwards-Incompatible Changes
------------------------------

None.

Thanks to our Contributors
--------------------------

This release contains contributions from many people:

Julian Burella Pérez, Umberto Lupo, and Guillaume Tauzin.

We are also grateful to all who filed issues or helped resolve them, asked and
answered questions, and were part of inspiring discussions.


Release 0.2.0
==============

Major Features and Improvements
-------------------------------

The ``flagser`` method now accepts ``filtration`` as an argument. All filtrations available for the C++ flagser software can be used.

Bug Fixes
---------

Fixed bug related to the generation of a file by C++ ``flagser``. Whenever pyflagser's ``flagser`` method was interrupted, it would not remove the generated file, which would prevent the ``flagser`` method to be called again.

Backwards-Incompatible Changes
------------------------------

None.

Thanks to our Contributors
--------------------------

This release contains contributions from many people:

Julian Burella Pérez, Umberto Lupo, and Guillaume Tauzin.

We are also grateful to all who filed issues or helped resolve them, asked and
answered questions, and were part of inspiring discussions.


Release 0.1.0
==============

Initial release of pyflagser.
Initial release of ``pyflagser``.

Major Features and Improvements
-------------------------------

The following methods where added:

- `loadflag` enable the user to load a `.flag` file into a `scipy` or `numpy` matrix.
- `saveflag` enables the user to save a `scipy` or `numpy` matrix into a `.flag` file.
- `flagser` computes the persistent homology of directed/undirected flag complexes.
- ``loadflag`` enable the user to load a ``.flag`` file into a ``scipy`` or ``numpy`` matrix.
- ``saveflag`` enables the user to save a ``scipy`` or ``numpy`` matrix into a ``.flag`` file.
- ``flagser`` computes the persistent homology of directed/undirected flag complexes.

Bug Fixes
---------
Expand Down
2 changes: 1 addition & 1 deletion pyflagser/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
# 'X.Y.dev0' is the canonical version of 'X.Y.dev'
#

__version__ = '0.2.0'
__version__ = '0.2.1'
169 changes: 169 additions & 0 deletions pyflagser/tests/test_flagser.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""Testing for the python bindings of the C++ flagser library."""

import os
import numpy as np

from numpy.testing import assert_almost_equal

from pyflagser import loadflag, flagser
from flagser_pybind import implemented_filtrations

betti = {
'a.flag': [1, 2, 0],
Expand All @@ -26,9 +28,176 @@
'd10.flag': [1, 0, 0, 0, 0, 0, 0, 0, 0, 1334961],
}

"""
Filtrations are only tested for d5.flag
"""
filtrations_results = {
'dimension':
{
'dgms': [
np.array([[0., 1.],
[0., 1.],
[0., 1.],
[0., 1.],
[0., float('inf')]]),
np.array([[1., 2.],
[1., 2.],
[1., 2.],
[1., 2.],
[1., 2.],
[1., 2.]])]
},
'zero':
{
'dgms': [
np.array([[0., float('inf')]])]
},
'max':
{
'dgms': [
np.array([[0.44, 1.00999999],
[0.36000001, 1.125],
[0.33000001, 1.14499998],
[0.88999999, 1.17999995],
[0.11, float('inf')]]),
np.array([[1.29499996, 1.34000003],
[1.20000005, 1.65499997]])]
},
'max3':
{
'dgms': [
np.array([[0.44, 1.00999999],
[0.36000001, 1.125],
[0.33000001, 1.14499998],
[0.88999999, 1.17999995],
[0.11, float('inf')]]),
np.array([[1.29499996, 1.34000003],
[1.20000005, 1.65499997]])]
},
'max_plus_one':
{
'dgms': [
np.array([[0.44, 1.00999999],
[0.36000001, 1.125],
[0.33000001, 1.14499998],
[0.88999999, 1.17999995],
[0.11, float('inf')]]),
np.array([[1.76999998, 2.76999998],
[1.755, 2.75500011],
[1.65499997, 2.65499997],
[1.34000003, 2.34000015],
[1.29499996, 2.34000015],
[1.20000005, 2.65499997]])]
},
'product':
{
'dgms': [
np.array([[0.44, 1.00999999],
[0.36000001, 1.125],
[0.33000001, 1.14499998],
[0.88999999, 1.17999995],
[0.11, float('inf')]]),
np.array([[1.76999998, 2.04691648],
[1.755, 1.99411869],
[1.65499997, 1.97242892],
[1.34000003, 1.77884996],
[1.29499996, 2.08236003],
[1.20000005, 2.27397013]])]
},
'sum':
{
'dgms': [
np.array([[0.44, 1.00999999],
[0.36000001, 1.125],
[0.33000001, 1.14499998],
[0.88999999, 1.17999995],
[0.11, float('inf')]]),
np.array([[1.76999998, 3.92499995],
[1.755, 3.8900001],
[1.65499997, 3.84500003],
[1.34000003, 3.64499998],
[1.29499996, 3.83500004],
[1.20000005, 4.]])]
},
'pmean':
{
'dgms': [
np.array([[0.44, 1.00999999],
[0.36000001, 1.125],
[0.33000001, 1.14499998],
[0.88999999, 1.17999995],
[0.11, float('inf')]]),
np.array([[1.76999998, 2.54917502],
[1.755, 2.52713633],
[1.65499997, 2.41156578],
[1.34000003, 2.04345369],
[1.29499996, 2.07881474],
[1.20000005, 2.43602848]])]
},
'pmoment':
{
'dgms': [
np.array([[0.44, 1.00999999],
[0.36000001, 1.125],
[0.33000001, 1.14499998],
[0.88999999, 1.17999995],
[0.11, float('inf')]]),
np.array([[1.76999998, 1.9275918],
[1.755, 1.85709834],
[1.65499997, 1.7869581],
[1.34000003, 1.37369251],
[1.29499996, 1.39265192],
[1.20000005, 1.81259179]])]
},
'remove_edges':
{
'dgms': [
np.array([[0.44, 1.00999999],
[0.36000001, 1.125],
[0.33000001, 1.14499998],
[0.88999999, 1.17999995],
[0.11, float('inf')]]),
np.array([[1.29499996, 1.34000003],
[1.20000005, 1.65499997]])]
},
}


def test_flagser(flag_file):
betti_exp = betti[os.path.split(flag_file)[1]]
flag_matrix = loadflag(flag_file)
betti_res = flagser(flag_matrix)['betti']
assert_almost_equal(betti_res, betti_exp)


def are_matrix_equal(m1, m2):
for i in range(min(len(m1), len(m2))):
m1f = np.array(m1[i]).flatten()
m2f = np.array(m2[i]).flatten()
if not np.isclose(m1f, m2f).all():
return False
return True


def test_filtrations(flag_file):
"""
Testing all filtrations available for dataset d5.flag
vertex_degree filtrations was disable because it produces a segmentation
fault.
"""
if os.path.split(flag_file)[1] == 'd5.flag':
flag_matrix = loadflag(flag_file)
for filtration in implemented_filtrations:
if filtration not in ['vertex_degree']:
assert filtration in filtrations_results.keys(),\
"Test for {} is not implemented, current implemented tests\
are {}".format(filtration, filtrations_results.keys())
res = flagser(flag_matrix, max_dimension=1, directed=False,
filtration=filtration)
for filt, tests in filtrations_results.items():
if filtration == filt:
tmp = np.array(res['dgms']).tolist()
tmp2 = np.array(tests['dgms']).tolist()
assert are_matrix_equal(tmp, tmp2), \
"diagrams {} \n and {} \n are not equal"\
.format(tmp, tmp2)
13 changes: 9 additions & 4 deletions src/flagser_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ PYBIND11_MODULE(flagser_pybind, m) {
std::string filtration) {
// Save std::cout status
auto cout_buff = std::cout.rdbuf();
named_arguments_t named_arguments;
std::string str_max;
std::string str_min;

HAS_EDGE_FILTRATION has_edge_filtration =
HAS_EDGE_FILTRATION::TOO_EARLY_TO_DECIDE;
Expand All @@ -58,10 +61,12 @@ PYBIND11_MODULE(flagser_pybind, m) {
if (max_dim < 0)
effective_max_dim = std::numeric_limits<unsigned short>::max();

named_arguments_t named_arguments;
str_max = std::to_string(effective_max_dim);
str_min = std::to_string(min_dim);

named_arguments["out"] = "output_flagser_file";
named_arguments["--max-dim"] = std::to_string(effective_max_dim).c_str();
named_arguments["--min-dim"] = std::to_string(min_dim).c_str();
named_arguments["max-dim"] = str_max.c_str();
named_arguments["min-dim"] = str_min.c_str();

// Is filtration supported ?
if (std::find(custom_filtration_computer.begin(),
Expand All @@ -80,7 +85,7 @@ PYBIND11_MODULE(flagser_pybind, m) {
}
}

named_arguments["--filtration"] = filtration.c_str();
named_arguments["filtration"] = filtration.c_str();

remove(named_arguments["out"]);

Expand Down

0 comments on commit b102b1f

Please sign in to comment.