From 0c47b28201093851140ab499331017ef42312ce7 Mon Sep 17 00:00:00 2001 From: yuichi-ike Date: Thu, 21 May 2020 11:02:00 +0900 Subject: DTM Rips added (straightforward way) --- src/python/gudhi/dtm_rips_complex.py | 46 ++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/python/gudhi/dtm_rips_complex.py (limited to 'src/python/gudhi/dtm_rips_complex.py') diff --git a/src/python/gudhi/dtm_rips_complex.py b/src/python/gudhi/dtm_rips_complex.py new file mode 100644 index 00000000..6d2f9f31 --- /dev/null +++ b/src/python/gudhi/dtm_rips_complex.py @@ -0,0 +1,46 @@ +# 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): Yuichi Ike, Raphaƫl Tinarrage +# +# Copyright (C) 2020 Inria, Copyright (C) 2020 FUjitsu Laboratories Ltd. +# +# Modification(s): +# - YYYY/MM Author: Description of the modification + + +from gudhi.weighted_rips_complex import WeightedRipsComplex +from gudhi.point_cloud.dtm import DistanceToMeasure +from scipy.spatial.distance import cdist + +class DtmRipsComplex(WeightedRipsComplex): + """ + Class to generate a DTM Rips complex from a distance matrix or a point set, + in the way described in :cite:`dtmfiltrations`. + Remark that all the filtration values are doubled compared to the definition in the paper + for the consistency with RipsComplex. + """ + def __init__(self, + points=None, + distance_matrix=None, + k=1, + q=2, + max_filtration=float('inf')): + """ + Args: + points (Sequence[Sequence[float]]): list of points. + distance_matrix (ndarray): full distance matrix. + k (int): number of neighbors for the computation of DTM. Defaults to 1, which is equivalent to the usual Rips complex. + q (float): order used to compute the distance to measure. Defaults to 2. + max_filtration (float): specifies the maximal filtration value to be considered. + """ + if distance_matrix is None: + if points is None: + # Empty Rips construction + points=[] + distance_matrix = cdist(points,points) + self.distance_matrix = distance_matrix + dtm = DistanceToMeasure(k, q=q, metric="precomputed") + # TODO: address the error when k is too large + self.weights = dtm.fit_transform(distance_matrix) + self.max_filtration = max_filtration + -- cgit v1.2.3 From 2ccc5ea97a5979f80fec93863da5549e4e6f2eea Mon Sep 17 00:00:00 2001 From: yuichi-ike Date: Fri, 22 May 2020 10:22:31 +0900 Subject: class name changed, documents modified --- src/python/doc/rips_complex_ref.rst | 4 ++-- src/python/doc/rips_complex_user.rst | 8 +++++--- src/python/gudhi/dtm_rips_complex.py | 12 ++++++++---- src/python/test/test_dtm_rips_complex.py | 6 +++--- 4 files changed, 18 insertions(+), 12 deletions(-) (limited to 'src/python/gudhi/dtm_rips_complex.py') diff --git a/src/python/doc/rips_complex_ref.rst b/src/python/doc/rips_complex_ref.rst index f781fd92..2aa6b268 100644 --- a/src/python/doc/rips_complex_ref.rst +++ b/src/python/doc/rips_complex_ref.rst @@ -32,9 +32,9 @@ Weighted Rips complex reference manual DTM Rips complex reference manual ================================= -.. autoclass:: gudhi.dtm_rips_complex.DtmRipsComplex +.. autoclass:: gudhi.dtm_rips_complex.DTMRipsComplex :members: :undoc-members: :show-inheritance: - .. automethod:: gudhi.dtm_rips_complex.DtmRipsComplex.__init__ \ No newline at end of file + .. automethod:: gudhi.dtm_rips_complex.DTMRipsComplex.__init__ \ No newline at end of file diff --git a/src/python/doc/rips_complex_user.rst b/src/python/doc/rips_complex_user.rst index ac11a4b6..450e6c1a 100644 --- a/src/python/doc/rips_complex_user.rst +++ b/src/python/doc/rips_complex_user.rst @@ -378,6 +378,7 @@ Example from a point cloud combined with DistanceToMeasure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Combining with DistanceToMeasure, one can compute the DTM-filtration of a point set, as in `this notebook `_. +Remark that DTMRipsComplex class provides exactly this function. .. testcode:: @@ -402,14 +403,15 @@ The output is: DTM Rips Complex ---------------- -`DtmdRipsComplex `_ builds a simplicial complex from a point set or a full distence matrix (in the form of ndarray), as described in the above example. +`DTMRipsComplex `_ builds a simplicial complex from a point set or a full distence matrix (in the form of ndarray), as described in the above example. +This class constructs a weighted Rips complex giving larger weights to outliers, which reduces their impact on the persistence diagram. See `this notebook `_ for some experiments. .. testcode:: import numpy as np - from gudhi.dtm_rips_complex import DtmRipsComplex + from gudhi.dtm_rips_complex import DTMRipsComplex pts = np.array([[2.0, 2.0], [0.0, 1.0], [3.0, 4.0]]) - dtm_rips = DtmRipsComplex(points=pts, k=2) + dtm_rips = DTMRipsComplex(points=pts, k=2) st = dtm_rips.create_simplex_tree(max_dimension=2) print(st.persistence()) diff --git a/src/python/gudhi/dtm_rips_complex.py b/src/python/gudhi/dtm_rips_complex.py index 6d2f9f31..70c8e5dd 100644 --- a/src/python/gudhi/dtm_rips_complex.py +++ b/src/python/gudhi/dtm_rips_complex.py @@ -12,7 +12,7 @@ from gudhi.weighted_rips_complex import WeightedRipsComplex from gudhi.point_cloud.dtm import DistanceToMeasure from scipy.spatial.distance import cdist -class DtmRipsComplex(WeightedRipsComplex): +class DTMRipsComplex(WeightedRipsComplex): """ Class to generate a DTM Rips complex from a distance matrix or a point set, in the way described in :cite:`dtmfiltrations`. @@ -28,7 +28,7 @@ class DtmRipsComplex(WeightedRipsComplex): """ Args: points (Sequence[Sequence[float]]): list of points. - distance_matrix (ndarray): full distance matrix. + distance_matrix (numpy.ndarray): full distance matrix. k (int): number of neighbors for the computation of DTM. Defaults to 1, which is equivalent to the usual Rips complex. q (float): order used to compute the distance to measure. Defaults to 2. max_filtration (float): specifies the maximal filtration value to be considered. @@ -39,8 +39,12 @@ class DtmRipsComplex(WeightedRipsComplex): points=[] distance_matrix = cdist(points,points) self.distance_matrix = distance_matrix - dtm = DistanceToMeasure(k, q=q, metric="precomputed") + # TODO: address the error when k is too large - self.weights = dtm.fit_transform(distance_matrix) + if k <= 1: + self.weights = [0] * len(distance_matrix) + else: + dtm = DistanceToMeasure(k, q=q, metric="precomputed") + self.weights = dtm.fit_transform(distance_matrix) self.max_filtration = max_filtration diff --git a/src/python/test/test_dtm_rips_complex.py b/src/python/test/test_dtm_rips_complex.py index bc6e5a59..7cd2ad90 100644 --- a/src/python/test/test_dtm_rips_complex.py +++ b/src/python/test/test_dtm_rips_complex.py @@ -8,14 +8,14 @@ - YYYY/MM Author: Description of the modification """ -from gudhi.dtm_rips_complex import DtmRipsComplex +from gudhi.dtm_rips_complex import DTMRipsComplex import numpy as np from math import sqrt import pytest def test_dtm_rips_complex(): pts = np.array([[2.0, 2.0], [0.0, 1.0], [3.0, 4.0]]) - dtm_rips = DtmRipsComplex(points=pts, k=2) + dtm_rips = DTMRipsComplex(points=pts, k=2) st = dtm_rips.create_simplex_tree(max_dimension=2) st.persistence() persistence_intervals0 = st.persistence_intervals_in_dimension(0) @@ -23,7 +23,7 @@ def test_dtm_rips_complex(): def test_compatibility_with_rips(): distance_matrix = np.array([[0, 1, 1, sqrt(2)], [1, 0, sqrt(2), 1], [1, sqrt(2), 0, 1], [sqrt(2), 1, 1, 0]]) - dtm_rips = DtmRipsComplex(distance_matrix=distance_matrix, max_filtration=42) + dtm_rips = DTMRipsComplex(distance_matrix=distance_matrix, max_filtration=42) st = dtm_rips.create_simplex_tree(max_dimension=1) assert list(st.get_filtration()) == [ ([0], 0.0), -- cgit v1.2.3 From 55316205b2c7c2e3d7e3fe3ea92e20f3f8b29b11 Mon Sep 17 00:00:00 2001 From: yuichi-ike Date: Tue, 26 May 2020 18:22:14 +0900 Subject: test fixed, documents modified --- src/python/doc/rips_complex_user.rst | 6 ++++-- src/python/gudhi/dtm_rips_complex.py | 1 + src/python/test/test_dtm_rips_complex.py | 16 ++++------------ 3 files changed, 9 insertions(+), 14 deletions(-) (limited to 'src/python/gudhi/dtm_rips_complex.py') diff --git a/src/python/doc/rips_complex_user.rst b/src/python/doc/rips_complex_user.rst index 450e6c1a..dd2f2cc0 100644 --- a/src/python/doc/rips_complex_user.rst +++ b/src/python/doc/rips_complex_user.rst @@ -378,7 +378,7 @@ Example from a point cloud combined with DistanceToMeasure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Combining with DistanceToMeasure, one can compute the DTM-filtration of a point set, as in `this notebook `_. -Remark that DTMRipsComplex class provides exactly this function. +Remark that `DTMRipsComplex `_ class provides exactly this function. .. testcode:: @@ -400,10 +400,12 @@ The output is: [(0, (3.1622776601683795, inf)), (0, (3.1622776601683795, 5.39834563766817)), (0, (3.1622776601683795, 5.39834563766817))] +.. _dtm-rips-complex: + DTM Rips Complex ---------------- -`DTMRipsComplex `_ builds a simplicial complex from a point set or a full distence matrix (in the form of ndarray), as described in the above example. +`DTMRipsComplex `_ builds a simplicial complex from a point set or a full distance matrix (in the form of ndarray), as described in the above example. This class constructs a weighted Rips complex giving larger weights to outliers, which reduces their impact on the persistence diagram. See `this notebook `_ for some experiments. .. testcode:: diff --git a/src/python/gudhi/dtm_rips_complex.py b/src/python/gudhi/dtm_rips_complex.py index 70c8e5dd..d77ad36e 100644 --- a/src/python/gudhi/dtm_rips_complex.py +++ b/src/python/gudhi/dtm_rips_complex.py @@ -18,6 +18,7 @@ class DTMRipsComplex(WeightedRipsComplex): in the way described in :cite:`dtmfiltrations`. Remark that all the filtration values are doubled compared to the definition in the paper for the consistency with RipsComplex. + :Requires: `SciPy `_ """ def __init__(self, points=None, diff --git a/src/python/test/test_dtm_rips_complex.py b/src/python/test/test_dtm_rips_complex.py index 7cd2ad90..e1c0ee44 100644 --- a/src/python/test/test_dtm_rips_complex.py +++ b/src/python/test/test_dtm_rips_complex.py @@ -9,6 +9,7 @@ """ from gudhi.dtm_rips_complex import DTMRipsComplex +from gudhi import RipsComplex import numpy as np from math import sqrt import pytest @@ -25,16 +26,7 @@ def test_compatibility_with_rips(): distance_matrix = np.array([[0, 1, 1, sqrt(2)], [1, 0, sqrt(2), 1], [1, sqrt(2), 0, 1], [sqrt(2), 1, 1, 0]]) dtm_rips = DTMRipsComplex(distance_matrix=distance_matrix, max_filtration=42) st = dtm_rips.create_simplex_tree(max_dimension=1) - assert list(st.get_filtration()) == [ - ([0], 0.0), - ([1], 0.0), - ([2], 0.0), - ([3], 0.0), - ([0, 1], 1.0), - ([0, 2], 1.0), - ([1, 3], 1.0), - ([2, 3], 1.0), - ([1, 2], sqrt(2)), - ([0, 3], sqrt(2)), - ] + rips_complex = RipsComplex(distance_matrix=distance_matrix, max_edge_length=42) + st_from_rips = rips_complex.create_simplex_tree(max_dimension=1) + assert list(st.get_filtration()) == list(st_from_rips.get_filtration()) -- cgit v1.2.3 From a9e1f9bbb4b39bca0d59857f57f5182701532820 Mon Sep 17 00:00:00 2001 From: yuichi-ike Date: Thu, 28 May 2020 09:19:55 +0900 Subject: comment modified --- src/python/gudhi/dtm_rips_complex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/python/gudhi/dtm_rips_complex.py') diff --git a/src/python/gudhi/dtm_rips_complex.py b/src/python/gudhi/dtm_rips_complex.py index d77ad36e..63c9b138 100644 --- a/src/python/gudhi/dtm_rips_complex.py +++ b/src/python/gudhi/dtm_rips_complex.py @@ -28,7 +28,7 @@ class DTMRipsComplex(WeightedRipsComplex): max_filtration=float('inf')): """ Args: - points (Sequence[Sequence[float]]): list of points. + points (numpy.ndarray): array of points. distance_matrix (numpy.ndarray): full distance matrix. k (int): number of neighbors for the computation of DTM. Defaults to 1, which is equivalent to the usual Rips complex. q (float): order used to compute the distance to measure. Defaults to 2. -- cgit v1.2.3