From 68b6e3f3d641cd4a1e86f08bff96e417cc17ac59 Mon Sep 17 00:00:00 2001 From: takeshimeonerespect Date: Fri, 31 Jan 2020 08:08:43 +0100 Subject: timedelay added on fork --- src/python/CMakeLists.txt | 5 +++ src/python/doc/point_cloud.rst | 7 ++++ src/python/gudhi/point_cloud/timedelay.py | 56 +++++++++++++++++++++++++++++++ src/python/test/test_point_cloud.py | 35 +++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 src/python/gudhi/point_cloud/timedelay.py create mode 100755 src/python/test/test_point_cloud.py diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index b558d4c4..b23ec8a9 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -52,6 +52,7 @@ if(PYTHONINTERP_FOUND) # Modules that should not be auto-imported in __init__.py set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'representations', ") set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'wasserstein', ") + set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'point_cloud', ") add_gudhi_debug_info("Python version ${PYTHON_VERSION_STRING}") add_gudhi_debug_info("Cython version ${CYTHON_VERSION}") @@ -221,6 +222,7 @@ endif(CGAL_FOUND) file(COPY "gudhi/persistence_graphical_tools.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") file(COPY "gudhi/representations" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/") file(COPY "gudhi/wasserstein.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") + file(COPY "gudhi/point_cloud" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") add_custom_command( OUTPUT gudhi.so @@ -399,6 +401,9 @@ endif(CGAL_FOUND) add_gudhi_py_test(test_representations) endif() + # Point cloud + add_gudhi_py_test(test_point_cloud) + # Documentation generation is available through sphinx - requires all modules if(SPHINX_PATH) if(MATPLOTLIB_FOUND) diff --git a/src/python/doc/point_cloud.rst b/src/python/doc/point_cloud.rst index d668428a..55c74ff3 100644 --- a/src/python/doc/point_cloud.rst +++ b/src/python/doc/point_cloud.rst @@ -20,3 +20,10 @@ Subsampling :members: :special-members: :show-inheritance: + +TimeDelayEmbedding +------------------ + +.. autoclass:: gudhi.point_cloud.timedelay.TimeDelayEmbedding + :members: + diff --git a/src/python/gudhi/point_cloud/timedelay.py b/src/python/gudhi/point_cloud/timedelay.py new file mode 100644 index 00000000..5c7ba542 --- /dev/null +++ b/src/python/gudhi/point_cloud/timedelay.py @@ -0,0 +1,56 @@ +import numpy as np + +class TimeDelayEmbedding: + """Point cloud transformation class. + + Embeds time-series data in the R^d according to Takens' Embedding Theorem + and obtains the coordinates of each point. + + Parameters + ---------- + dim : int, optional (default=3) + `d` of R^d to be embedded. + + delay : int, optional (default=1) + Time-Delay embedding. + + skip : int, optional (default=1) + How often to skip embedded points. + + """ + def __init__(self, dim=3, delay=1, skip=1): + self._dim = dim + self._delay = delay + self._skip = skip + + def __call__(self, *args, **kwargs): + return self.transform(*args, **kwargs) + + def _transform(self, ts): + """Guts of transform method.""" + return ts[ + np.add.outer( + np.arange(0, len(ts)-self._delay*(self._dim-1), self._skip), + np.arange(0, self._dim*self._delay, self._delay)) + ] + + def transform(self, ts): + """Transform method. + + Parameters + ---------- + ts : list[float] or list[list[float]] + A single or multiple time-series data. + + Returns + ------- + point clouds : list[list[float, float, float]] or list[list[list[float, float, float]]] + Makes point cloud every a single time-series data. + """ + ndts = np.array(ts) + if ndts.ndim == 1: + # for single. + return self._transform(ndts).tolist() + else: + # for multiple. + return np.apply_along_axis(self._transform, 1, ndts).tolist() diff --git a/src/python/test/test_point_cloud.py b/src/python/test/test_point_cloud.py new file mode 100755 index 00000000..2ee0c1fb --- /dev/null +++ b/src/python/test/test_point_cloud.py @@ -0,0 +1,35 @@ +from gudhi.point_cloud.timedelay import TimeDelayEmbedding + +def test_normal(): + # Sample array + ts = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + # Normal case. + prep = TimeDelayEmbedding() + attractor = prep(ts) + assert (attractor[0] == [1, 2, 3]) + assert (attractor[1] == [2, 3, 4]) + assert (attractor[2] == [3, 4, 5]) + assert (attractor[3] == [4, 5, 6]) + assert (attractor[4] == [5, 6, 7]) + assert (attractor[5] == [6, 7, 8]) + assert (attractor[6] == [7, 8, 9]) + assert (attractor[7] == [8, 9, 10]) + # Delay = 3 + prep = TimeDelayEmbedding(delay=3) + attractor = prep(ts) + assert (attractor[0] == [1, 4, 7]) + assert (attractor[1] == [2, 5, 8]) + assert (attractor[2] == [3, 6, 9]) + assert (attractor[3] == [4, 7, 10]) + # Skip = 3 + prep = TimeDelayEmbedding(skip=3) + attractor = prep(ts) + assert (attractor[0] == [1, 2, 3]) + assert (attractor[1] == [4, 5, 6]) + assert (attractor[2] == [7, 8, 9]) + # Delay = 2 / Skip = 2 + prep = TimeDelayEmbedding(delay=2, skip=2) + attractor = prep(ts) + assert (attractor[0] == [1, 3, 5]) + assert (attractor[1] == [3, 5, 7]) + assert (attractor[2] == [5, 7, 9]) -- cgit v1.2.3 From d6afaa8300daa6204282a7d34df6bea33ea59fd2 Mon Sep 17 00:00:00 2001 From: takeshimeonerespect <58589594+takeshimeonerespect@users.noreply.github.com> Date: Mon, 3 Feb 2020 14:13:52 +0900 Subject: Update timedelay.py --- src/python/gudhi/point_cloud/timedelay.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/python/gudhi/point_cloud/timedelay.py b/src/python/gudhi/point_cloud/timedelay.py index 5c7ba542..f283916d 100644 --- a/src/python/gudhi/point_cloud/timedelay.py +++ b/src/python/gudhi/point_cloud/timedelay.py @@ -1,3 +1,11 @@ +# 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): Martin Royer, Yuichi Ike, Masatoshi Takenouchi +# +# Copyright (C) 2020 Inria, Copyright (C) 2020 Fujitsu Laboratories Ltd. +# Modification(s): +# - YYYY/MM Author: Description of the modification + import numpy as np class TimeDelayEmbedding: -- cgit v1.2.3 From eded147ffffe5b7143cad19ecd134fb7a63991a3 Mon Sep 17 00:00:00 2001 From: takenouchi Date: Tue, 4 Feb 2020 14:08:19 +0900 Subject: change a file name --- src/python/test/test_time_delay.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100755 src/python/test/test_time_delay.py diff --git a/src/python/test/test_time_delay.py b/src/python/test/test_time_delay.py new file mode 100755 index 00000000..2ee0c1fb --- /dev/null +++ b/src/python/test/test_time_delay.py @@ -0,0 +1,35 @@ +from gudhi.point_cloud.timedelay import TimeDelayEmbedding + +def test_normal(): + # Sample array + ts = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + # Normal case. + prep = TimeDelayEmbedding() + attractor = prep(ts) + assert (attractor[0] == [1, 2, 3]) + assert (attractor[1] == [2, 3, 4]) + assert (attractor[2] == [3, 4, 5]) + assert (attractor[3] == [4, 5, 6]) + assert (attractor[4] == [5, 6, 7]) + assert (attractor[5] == [6, 7, 8]) + assert (attractor[6] == [7, 8, 9]) + assert (attractor[7] == [8, 9, 10]) + # Delay = 3 + prep = TimeDelayEmbedding(delay=3) + attractor = prep(ts) + assert (attractor[0] == [1, 4, 7]) + assert (attractor[1] == [2, 5, 8]) + assert (attractor[2] == [3, 6, 9]) + assert (attractor[3] == [4, 7, 10]) + # Skip = 3 + prep = TimeDelayEmbedding(skip=3) + attractor = prep(ts) + assert (attractor[0] == [1, 2, 3]) + assert (attractor[1] == [4, 5, 6]) + assert (attractor[2] == [7, 8, 9]) + # Delay = 2 / Skip = 2 + prep = TimeDelayEmbedding(delay=2, skip=2) + attractor = prep(ts) + assert (attractor[0] == [1, 3, 5]) + assert (attractor[1] == [3, 5, 7]) + assert (attractor[2] == [5, 7, 9]) -- cgit v1.2.3 From 5ddb724824798fe194a66285e29ea4c5cc2713e2 Mon Sep 17 00:00:00 2001 From: takeshimeonerespect Date: Tue, 4 Feb 2020 14:24:27 +0900 Subject: Delete test_point_cloud.py --- src/python/test/test_point_cloud.py | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100755 src/python/test/test_point_cloud.py diff --git a/src/python/test/test_point_cloud.py b/src/python/test/test_point_cloud.py deleted file mode 100755 index 2ee0c1fb..00000000 --- a/src/python/test/test_point_cloud.py +++ /dev/null @@ -1,35 +0,0 @@ -from gudhi.point_cloud.timedelay import TimeDelayEmbedding - -def test_normal(): - # Sample array - ts = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - # Normal case. - prep = TimeDelayEmbedding() - attractor = prep(ts) - assert (attractor[0] == [1, 2, 3]) - assert (attractor[1] == [2, 3, 4]) - assert (attractor[2] == [3, 4, 5]) - assert (attractor[3] == [4, 5, 6]) - assert (attractor[4] == [5, 6, 7]) - assert (attractor[5] == [6, 7, 8]) - assert (attractor[6] == [7, 8, 9]) - assert (attractor[7] == [8, 9, 10]) - # Delay = 3 - prep = TimeDelayEmbedding(delay=3) - attractor = prep(ts) - assert (attractor[0] == [1, 4, 7]) - assert (attractor[1] == [2, 5, 8]) - assert (attractor[2] == [3, 6, 9]) - assert (attractor[3] == [4, 7, 10]) - # Skip = 3 - prep = TimeDelayEmbedding(skip=3) - attractor = prep(ts) - assert (attractor[0] == [1, 2, 3]) - assert (attractor[1] == [4, 5, 6]) - assert (attractor[2] == [7, 8, 9]) - # Delay = 2 / Skip = 2 - prep = TimeDelayEmbedding(delay=2, skip=2) - attractor = prep(ts) - assert (attractor[0] == [1, 3, 5]) - assert (attractor[1] == [3, 5, 7]) - assert (attractor[2] == [5, 7, 9]) -- cgit v1.2.3 From 596355344e6205d02110e38a0cb7e0a94e8dbd27 Mon Sep 17 00:00:00 2001 From: takenouchi Date: Thu, 6 Feb 2020 16:00:47 +0900 Subject: modify CMakeLists.txt --- src/python/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index b23ec8a9..798e2907 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -401,8 +401,8 @@ endif(CGAL_FOUND) add_gudhi_py_test(test_representations) endif() - # Point cloud - add_gudhi_py_test(test_point_cloud) + # Time Delay + add_gudhi_py_test(test_time_delay) # Documentation generation is available through sphinx - requires all modules if(SPHINX_PATH) -- cgit v1.2.3 From a6a4f375822cf3e2ca1866d78472e4350140ddbc Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Fri, 14 Feb 2020 11:02:56 +0900 Subject: Add __init__.py --- src/python/gudhi/point_cloud/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/python/gudhi/point_cloud/__init__.py diff --git a/src/python/gudhi/point_cloud/__init__.py b/src/python/gudhi/point_cloud/__init__.py new file mode 100644 index 00000000..e69de29b -- cgit v1.2.3 From 9cc9e1cf3cd9ea42908324d410ef68fa12e8e832 Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Fri, 14 Feb 2020 11:08:50 +0900 Subject: Update timedelay.py --- src/python/gudhi/point_cloud/timedelay.py | 66 ++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/src/python/gudhi/point_cloud/timedelay.py b/src/python/gudhi/point_cloud/timedelay.py index f283916d..d899da67 100644 --- a/src/python/gudhi/point_cloud/timedelay.py +++ b/src/python/gudhi/point_cloud/timedelay.py @@ -10,30 +10,55 @@ import numpy as np class TimeDelayEmbedding: """Point cloud transformation class. - Embeds time-series data in the R^d according to Takens' Embedding Theorem and obtains the coordinates of each point. - Parameters ---------- dim : int, optional (default=3) `d` of R^d to be embedded. - delay : int, optional (default=1) Time-Delay embedding. - skip : int, optional (default=1) How often to skip embedded points. - + Given delay=3 and skip=2, an point cloud which is obtained by embedding + a single time-series data into R^3 is as follows. + + .. code-block:: none + + time-series = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + point clouds = [[1, 4, 7], + [3, 6, 9]] + """ def __init__(self, dim=3, delay=1, skip=1): self._dim = dim self._delay = delay self._skip = skip - def __call__(self, *args, **kwargs): - return self.transform(*args, **kwargs) + def __call__(self, ts): + """Transform method for single time-series data. + Parameters + ---------- + ts : list[float] + A single time-series data. + Returns + ------- + point clouds : list[list[float, float, float]] + Makes point cloud every a single time-series data. + Raises + ------- + TypeError + If the parameter's type does not match the desired type. + """ + ndts = np.array(ts) + if ndts.ndim == 1: + return self._transform(ndts) + else: + raise TypeError("Expects 1-dimensional array.") + def fit(self, ts, y=None): + return self + def _transform(self, ts): """Guts of transform method.""" return ts[ @@ -43,22 +68,27 @@ class TimeDelayEmbedding: ] def transform(self, ts): - """Transform method. - + """Transform method for multiple time-series data. Parameters ---------- - ts : list[float] or list[list[float]] - A single or multiple time-series data. - + ts : list[list[float]] + Multiple time-series data. + Attributes + ---------- + ndts : + The ndts means that all time series need to have exactly + the same size. Returns ------- - point clouds : list[list[float, float, float]] or list[list[list[float, float, float]]] + point clouds : list[list[list[float, float, float]]] Makes point cloud every a single time-series data. + Raises + ------- + TypeError + If the parameter's type does not match the desired type. """ ndts = np.array(ts) - if ndts.ndim == 1: - # for single. - return self._transform(ndts).tolist() + if ndts.ndim == 2: + return np.apply_along_axis(self._transform, 1, ndts) else: - # for multiple. - return np.apply_along_axis(self._transform, 1, ndts).tolist() + raise TypeError("Expects 2-dimensional array.") -- cgit v1.2.3 From 2253fd03bb49aea455309f6d633a6edeb2362d79 Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Fri, 14 Feb 2020 17:52:07 +0900 Subject: Update test_time_delay.py --- src/python/test/test_time_delay.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/python/test/test_time_delay.py b/src/python/test/test_time_delay.py index 2ee0c1fb..d2ffbf40 100755 --- a/src/python/test/test_time_delay.py +++ b/src/python/test/test_time_delay.py @@ -6,30 +6,30 @@ def test_normal(): # Normal case. prep = TimeDelayEmbedding() attractor = prep(ts) - assert (attractor[0] == [1, 2, 3]) - assert (attractor[1] == [2, 3, 4]) - assert (attractor[2] == [3, 4, 5]) - assert (attractor[3] == [4, 5, 6]) - assert (attractor[4] == [5, 6, 7]) - assert (attractor[5] == [6, 7, 8]) - assert (attractor[6] == [7, 8, 9]) - assert (attractor[7] == [8, 9, 10]) + assert (attractor[0] == np.array[1, 2, 3]) + assert (attractor[1] == np.array[2, 3, 4]) + assert (attractor[2] == np.array[3, 4, 5]) + assert (attractor[3] == np.array[4, 5, 6]) + assert (attractor[4] == np.array[5, 6, 7]) + assert (attractor[5] == np.array[6, 7, 8]) + assert (attractor[6] == np.array[7, 8, 9]) + assert (attractor[7] == np.array[8, 9, 10]) # Delay = 3 prep = TimeDelayEmbedding(delay=3) attractor = prep(ts) - assert (attractor[0] == [1, 4, 7]) - assert (attractor[1] == [2, 5, 8]) - assert (attractor[2] == [3, 6, 9]) - assert (attractor[3] == [4, 7, 10]) + assert (attractor[0] == np.array[1, 4, 7]) + assert (attractor[1] == np.array[2, 5, 8]) + assert (attractor[2] == np.array[3, 6, 9]) + assert (attractor[3] == np.array[4, 7, 10]) # Skip = 3 prep = TimeDelayEmbedding(skip=3) attractor = prep(ts) - assert (attractor[0] == [1, 2, 3]) - assert (attractor[1] == [4, 5, 6]) - assert (attractor[2] == [7, 8, 9]) + assert (attractor[0] == np.array[1, 2, 3]) + assert (attractor[1] == np.array[4, 5, 6]) + assert (attractor[2] == np.array[7, 8, 9]) # Delay = 2 / Skip = 2 prep = TimeDelayEmbedding(delay=2, skip=2) attractor = prep(ts) - assert (attractor[0] == [1, 3, 5]) - assert (attractor[1] == [3, 5, 7]) - assert (attractor[2] == [5, 7, 9]) + assert (attractor[0] == np.array[1, 3, 5]) + assert (attractor[1] == np.array[3, 5, 7]) + assert (attractor[2] == np.array[5, 7, 9]) -- cgit v1.2.3 From f58a4120b70487aede3cb4e81fbb15171e34fa37 Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Fri, 14 Feb 2020 18:24:18 +0900 Subject: Update test_time_delay.py --- src/python/test/test_time_delay.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/python/test/test_time_delay.py b/src/python/test/test_time_delay.py index d2ffbf40..1cdf56f9 100755 --- a/src/python/test/test_time_delay.py +++ b/src/python/test/test_time_delay.py @@ -6,30 +6,30 @@ def test_normal(): # Normal case. prep = TimeDelayEmbedding() attractor = prep(ts) - assert (attractor[0] == np.array[1, 2, 3]) - assert (attractor[1] == np.array[2, 3, 4]) - assert (attractor[2] == np.array[3, 4, 5]) - assert (attractor[3] == np.array[4, 5, 6]) - assert (attractor[4] == np.array[5, 6, 7]) - assert (attractor[5] == np.array[6, 7, 8]) - assert (attractor[6] == np.array[7, 8, 9]) - assert (attractor[7] == np.array[8, 9, 10]) + assert (attractor[0] == np.array([1, 2, 3])) + assert (attractor[1] == np.array([2, 3, 4])) + assert (attractor[2] == np.array([3, 4, 5])) + assert (attractor[3] == np.array([4, 5, 6])) + assert (attractor[4] == np.array([5, 6, 7])) + assert (attractor[5] == np.array([6, 7, 8])) + assert (attractor[6] == np.array([7, 8, 9])) + assert (attractor[7] == np.array([8, 9, 10])) # Delay = 3 prep = TimeDelayEmbedding(delay=3) attractor = prep(ts) - assert (attractor[0] == np.array[1, 4, 7]) - assert (attractor[1] == np.array[2, 5, 8]) - assert (attractor[2] == np.array[3, 6, 9]) - assert (attractor[3] == np.array[4, 7, 10]) + assert (attractor[0] == np.array([1, 4, 7])) + assert (attractor[1] == np.array([2, 5, 8])) + assert (attractor[2] == np.array([3, 6, 9])) + assert (attractor[3] == np.array([4, 7, 10])) # Skip = 3 prep = TimeDelayEmbedding(skip=3) attractor = prep(ts) - assert (attractor[0] == np.array[1, 2, 3]) - assert (attractor[1] == np.array[4, 5, 6]) - assert (attractor[2] == np.array[7, 8, 9]) + assert (attractor[0] == np.array([1, 2, 3])) + assert (attractor[1] == np.array([4, 5, 6])) + assert (attractor[2] == np.array([7, 8, 9])) # Delay = 2 / Skip = 2 prep = TimeDelayEmbedding(delay=2, skip=2) attractor = prep(ts) - assert (attractor[0] == np.array[1, 3, 5]) - assert (attractor[1] == np.array[3, 5, 7]) - assert (attractor[2] == np.array[5, 7, 9]) + assert (attractor[0] == np.array([1, 3, 5])) + assert (attractor[1] == np.array([3, 5, 7])) + assert (attractor[2] == np.array([5, 7, 9])) -- cgit v1.2.3 From 1c0f48fb26bb2e606dfe0a22e62618357686e2c2 Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Fri, 14 Feb 2020 18:49:27 +0900 Subject: Update test_time_delay.py --- src/python/test/test_time_delay.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python/test/test_time_delay.py b/src/python/test/test_time_delay.py index 1cdf56f9..3b586ad2 100755 --- a/src/python/test/test_time_delay.py +++ b/src/python/test/test_time_delay.py @@ -1,4 +1,5 @@ from gudhi.point_cloud.timedelay import TimeDelayEmbedding +import numpy as np def test_normal(): # Sample array -- cgit v1.2.3 From 39873c0cf43ca7352dddeab8c1cc6a3fc40a2e58 Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Fri, 14 Feb 2020 19:08:50 +0900 Subject: Update test_time_delay.py --- src/python/test/test_time_delay.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python/test/test_time_delay.py b/src/python/test/test_time_delay.py index 3b586ad2..7b6562a5 100755 --- a/src/python/test/test_time_delay.py +++ b/src/python/test/test_time_delay.py @@ -7,7 +7,8 @@ def test_normal(): # Normal case. prep = TimeDelayEmbedding() attractor = prep(ts) - assert (attractor[0] == np.array([1, 2, 3])) + assert (attractor[0] == np.array([1, 2, 3]) + print(attractor[0].all())) assert (attractor[1] == np.array([2, 3, 4])) assert (attractor[2] == np.array([3, 4, 5])) assert (attractor[3] == np.array([4, 5, 6])) -- cgit v1.2.3 From 7c6966ee9821aaeb60d282616445a47071ac1fee Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Fri, 14 Feb 2020 19:20:25 +0900 Subject: Update test_time_delay.py --- src/python/test/test_time_delay.py | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/python/test/test_time_delay.py b/src/python/test/test_time_delay.py index 7b6562a5..f652fc88 100755 --- a/src/python/test/test_time_delay.py +++ b/src/python/test/test_time_delay.py @@ -7,31 +7,30 @@ def test_normal(): # Normal case. prep = TimeDelayEmbedding() attractor = prep(ts) - assert (attractor[0] == np.array([1, 2, 3]) - print(attractor[0].all())) - assert (attractor[1] == np.array([2, 3, 4])) - assert (attractor[2] == np.array([3, 4, 5])) - assert (attractor[3] == np.array([4, 5, 6])) - assert (attractor[4] == np.array([5, 6, 7])) - assert (attractor[5] == np.array([6, 7, 8])) - assert (attractor[6] == np.array([7, 8, 9])) - assert (attractor[7] == np.array([8, 9, 10])) + assert (attractor[0].all() == np.array([1, 2, 3])) + assert (attractor[1].all() == np.array([2, 3, 4])) + assert (attractor[2].all() == np.array([3, 4, 5])) + assert (attractor[3].all() == np.array([4, 5, 6])) + assert (attractor[4].all() == np.array([5, 6, 7])) + assert (attractor[5].all() == np.array([6, 7, 8])) + assert (attractor[6].all() == np.array([7, 8, 9])) + assert (attractor[7].all() == np.array([8, 9, 10])) # Delay = 3 prep = TimeDelayEmbedding(delay=3) attractor = prep(ts) - assert (attractor[0] == np.array([1, 4, 7])) - assert (attractor[1] == np.array([2, 5, 8])) - assert (attractor[2] == np.array([3, 6, 9])) - assert (attractor[3] == np.array([4, 7, 10])) + assert (attractor[0].all() == np.array([1, 4, 7])) + assert (attractor[1].all() == np.array([2, 5, 8])) + assert (attractor[2].all() == np.array([3, 6, 9])) + assert (attractor[3].all() == np.array([4, 7, 10])) # Skip = 3 prep = TimeDelayEmbedding(skip=3) attractor = prep(ts) - assert (attractor[0] == np.array([1, 2, 3])) - assert (attractor[1] == np.array([4, 5, 6])) - assert (attractor[2] == np.array([7, 8, 9])) + assert (attractor[0].all() == np.array([1, 2, 3])) + assert (attractor[1].all() == np.array([4, 5, 6])) + assert (attractor[2].all() == np.array([7, 8, 9])) # Delay = 2 / Skip = 2 prep = TimeDelayEmbedding(delay=2, skip=2) attractor = prep(ts) - assert (attractor[0] == np.array([1, 3, 5])) - assert (attractor[1] == np.array([3, 5, 7])) - assert (attractor[2] == np.array([5, 7, 9])) + assert (attractor[0].all() == np.array([1, 3, 5])) + assert (attractor[1].all() == np.array([3, 5, 7])) + assert (attractor[2].all() == np.array([5, 7, 9])) -- cgit v1.2.3 From 5023aa0ff30474a96783152844e7fb0ed52e0c98 Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Fri, 14 Feb 2020 20:25:14 +0900 Subject: Update test_time_delay.py --- src/python/test/test_time_delay.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/python/test/test_time_delay.py b/src/python/test/test_time_delay.py index f652fc88..5464a185 100755 --- a/src/python/test/test_time_delay.py +++ b/src/python/test/test_time_delay.py @@ -7,30 +7,30 @@ def test_normal(): # Normal case. prep = TimeDelayEmbedding() attractor = prep(ts) - assert (attractor[0].all() == np.array([1, 2, 3])) - assert (attractor[1].all() == np.array([2, 3, 4])) - assert (attractor[2].all() == np.array([3, 4, 5])) - assert (attractor[3].all() == np.array([4, 5, 6])) - assert (attractor[4].all() == np.array([5, 6, 7])) - assert (attractor[5].all() == np.array([6, 7, 8])) - assert (attractor[6].all() == np.array([7, 8, 9])) - assert (attractor[7].all() == np.array([8, 9, 10])) + assert (attractor[0] == np.array([1, 2, 3])).all() + assert (attractor[1] == np.array([2, 3, 4])).all() + assert (attractor[2] == np.array([3, 4, 5])).all() + assert (attractor[3] == np.array([4, 5, 6])).all() + assert (attractor[4] == np.array([5, 6, 7])).all() + assert (attractor[5] == np.array([6, 7, 8])).all() + assert (attractor[6] == np.array([7, 8, 9])).all() + assert (attractor[7] == np.array([8, 9, 10])).all() # Delay = 3 prep = TimeDelayEmbedding(delay=3) attractor = prep(ts) - assert (attractor[0].all() == np.array([1, 4, 7])) - assert (attractor[1].all() == np.array([2, 5, 8])) - assert (attractor[2].all() == np.array([3, 6, 9])) - assert (attractor[3].all() == np.array([4, 7, 10])) + assert (attractor[0] == np.array([1, 4, 7])).all() + assert (attractor[1] == np.array([2, 5, 8])).all() + assert (attractor[2] == np.array([3, 6, 9])).all() + assert (attractor[3] == np.array([4, 7, 10])).all() # Skip = 3 prep = TimeDelayEmbedding(skip=3) attractor = prep(ts) - assert (attractor[0].all() == np.array([1, 2, 3])) - assert (attractor[1].all() == np.array([4, 5, 6])) - assert (attractor[2].all() == np.array([7, 8, 9])) + assert (attractor[0] == np.array([1, 2, 3])).all() + assert (attractor[1] == np.array([4, 5, 6])).all() + assert (attractor[2] == np.array([7, 8, 9])).all() # Delay = 2 / Skip = 2 prep = TimeDelayEmbedding(delay=2, skip=2) attractor = prep(ts) - assert (attractor[0].all() == np.array([1, 3, 5])) - assert (attractor[1].all() == np.array([3, 5, 7])) - assert (attractor[2].all() == np.array([5, 7, 9])) + assert (attractor[0] == np.array([1, 3, 5])).all() + assert (attractor[1] == np.array([3, 5, 7])).all() + assert (attractor[2] == np.array([5, 7, 9])).all() -- cgit v1.2.3 From 80d84e5d8f9a24de745d23f7d721ea3e62217ff4 Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Wed, 19 Feb 2020 12:32:00 +0900 Subject: Update timedelay.py --- src/python/gudhi/point_cloud/timedelay.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python/gudhi/point_cloud/timedelay.py b/src/python/gudhi/point_cloud/timedelay.py index d899da67..6ad87cdc 100644 --- a/src/python/gudhi/point_cloud/timedelay.py +++ b/src/python/gudhi/point_cloud/timedelay.py @@ -43,7 +43,7 @@ class TimeDelayEmbedding: A single time-series data. Returns ------- - point clouds : list[list[float, float, float]] + point clouds : list of n x 2 numpy arrays Makes point cloud every a single time-series data. Raises ------- @@ -80,7 +80,7 @@ class TimeDelayEmbedding: the same size. Returns ------- - point clouds : list[list[list[float, float, float]]] + point clouds : list of n x 3 numpy arrays Makes point cloud every a single time-series data. Raises ------- -- cgit v1.2.3 From 88964b4ff10798d6d9c3d0a342c004ee6b8b1496 Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Tue, 25 Feb 2020 13:21:55 +0900 Subject: Update timedelay.py --- src/python/gudhi/point_cloud/timedelay.py | 89 +++++++++++++++---------------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/src/python/gudhi/point_cloud/timedelay.py b/src/python/gudhi/point_cloud/timedelay.py index 6ad87cdc..d7a1dab7 100644 --- a/src/python/gudhi/point_cloud/timedelay.py +++ b/src/python/gudhi/point_cloud/timedelay.py @@ -8,10 +8,12 @@ import numpy as np + class TimeDelayEmbedding: """Point cloud transformation class. Embeds time-series data in the R^d according to Takens' Embedding Theorem and obtains the coordinates of each point. + Parameters ---------- dim : int, optional (default=3) @@ -20,16 +22,27 @@ class TimeDelayEmbedding: Time-Delay embedding. skip : int, optional (default=1) How often to skip embedded points. - Given delay=3 and skip=2, an point cloud which is obtained by embedding - a single time-series data into R^3 is as follows. - - .. code-block:: none - - time-series = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - point clouds = [[1, 4, 7], - [3, 6, 9]] - + + Example + ------- + + Given delay=3 and skip=2, a point cloud which is obtained by embedding + a scalar time-series into R^3 is as follows:: + + time-series = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + point cloud = [[1, 4, 7], + [3, 6, 9]] + + Given delay=1 and skip=1, a point cloud which is obtained by embedding + a 2D vector time-series data into R^4 is as follows:: + + time-series = [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]] + point cloud = [[0, 1, 2, 3], + [2, 3, 4, 5], + [4, 5, 6, 7], + [6, 7, 8, 9]] """ + def __init__(self, dim=3, delay=1, skip=1): self._dim = dim self._delay = delay @@ -39,56 +52,42 @@ class TimeDelayEmbedding: """Transform method for single time-series data. Parameters ---------- - ts : list[float] - A single time-series data. + ts : Iterable[float] or Iterable[Iterable[float]] + A single time-series data, with scalar or vector values. + Returns ------- - point clouds : list of n x 2 numpy arrays - Makes point cloud every a single time-series data. - Raises - ------- - TypeError - If the parameter's type does not match the desired type. + point cloud : n x dim numpy arrays + Makes point cloud from a single time-series data. """ - ndts = np.array(ts) - if ndts.ndim == 1: - return self._transform(ndts) - else: - raise TypeError("Expects 1-dimensional array.") + return self._transform(np.array(ts)) def fit(self, ts, y=None): return self def _transform(self, ts): """Guts of transform method.""" - return ts[ - np.add.outer( - np.arange(0, len(ts)-self._delay*(self._dim-1), self._skip), - np.arange(0, self._dim*self._delay, self._delay)) - ] + if ts.ndim == 1: + repeat = self._dim + else: + assert self._dim % ts.shape[1] == 0 + repeat = self._dim // ts.shape[1] + end = len(ts) - self._delay * (repeat - 1) + short = np.arange(0, end, self._skip) + vertical = np.arange(0, repeat * self._delay, self._delay) + return ts[np.add.outer(short, vertical)].reshape(len(short), -1) def transform(self, ts): """Transform method for multiple time-series data. + Parameters ---------- - ts : list[list[float]] - Multiple time-series data. - Attributes - ---------- - ndts : - The ndts means that all time series need to have exactly - the same size. + ts : Iterable[Iterable[float]] or Iterable[Iterable[Iterable[float]]] + Multiple time-series data, with scalar or vector values. + Returns ------- - point clouds : list of n x 3 numpy arrays - Makes point cloud every a single time-series data. - Raises - ------- - TypeError - If the parameter's type does not match the desired type. + point clouds : list of n x dim numpy arrays + Makes point cloud from each time-series data. """ - ndts = np.array(ts) - if ndts.ndim == 2: - return np.apply_along_axis(self._transform, 1, ndts) - else: - raise TypeError("Expects 2-dimensional array.") + return [self._transform(np.array(s)) for s in ts] -- cgit v1.2.3 From 66c96498b994fea1fcaa6877121023410f4209f9 Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Tue, 25 Feb 2020 13:24:48 +0900 Subject: Update test_time_delay.py --- src/python/test/test_time_delay.py | 51 ++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/python/test/test_time_delay.py b/src/python/test/test_time_delay.py index 5464a185..1ead9bca 100755 --- a/src/python/test/test_time_delay.py +++ b/src/python/test/test_time_delay.py @@ -1,36 +1,43 @@ from gudhi.point_cloud.timedelay import TimeDelayEmbedding import numpy as np + def test_normal(): # Sample array ts = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # Normal case. prep = TimeDelayEmbedding() - attractor = prep(ts) - assert (attractor[0] == np.array([1, 2, 3])).all() - assert (attractor[1] == np.array([2, 3, 4])).all() - assert (attractor[2] == np.array([3, 4, 5])).all() - assert (attractor[3] == np.array([4, 5, 6])).all() - assert (attractor[4] == np.array([5, 6, 7])).all() - assert (attractor[5] == np.array([6, 7, 8])).all() - assert (attractor[6] == np.array([7, 8, 9])).all() - assert (attractor[7] == np.array([8, 9, 10])).all() + pointclouds = prep(ts) + assert (pointclouds[0] == np.array([1, 2, 3])).all() + assert (pointclouds[1] == np.array([2, 3, 4])).all() + assert (pointclouds[2] == np.array([3, 4, 5])).all() + assert (pointclouds[3] == np.array([4, 5, 6])).all() + assert (pointclouds[4] == np.array([5, 6, 7])).all() + assert (pointclouds[5] == np.array([6, 7, 8])).all() + assert (pointclouds[6] == np.array([7, 8, 9])).all() + assert (pointclouds[7] == np.array([8, 9, 10])).all() # Delay = 3 prep = TimeDelayEmbedding(delay=3) - attractor = prep(ts) - assert (attractor[0] == np.array([1, 4, 7])).all() - assert (attractor[1] == np.array([2, 5, 8])).all() - assert (attractor[2] == np.array([3, 6, 9])).all() - assert (attractor[3] == np.array([4, 7, 10])).all() + pointclouds = prep(ts) + assert (pointclouds[0] == np.array([1, 4, 7])).all() + assert (pointclouds[1] == np.array([2, 5, 8])).all() + assert (pointclouds[2] == np.array([3, 6, 9])).all() + assert (pointclouds[3] == np.array([4, 7, 10])).all() # Skip = 3 prep = TimeDelayEmbedding(skip=3) - attractor = prep(ts) - assert (attractor[0] == np.array([1, 2, 3])).all() - assert (attractor[1] == np.array([4, 5, 6])).all() - assert (attractor[2] == np.array([7, 8, 9])).all() + pointclouds = prep(ts) + assert (pointclouds[0] == np.array([1, 2, 3])).all() + assert (pointclouds[1] == np.array([4, 5, 6])).all() + assert (pointclouds[2] == np.array([7, 8, 9])).all() # Delay = 2 / Skip = 2 prep = TimeDelayEmbedding(delay=2, skip=2) - attractor = prep(ts) - assert (attractor[0] == np.array([1, 3, 5])).all() - assert (attractor[1] == np.array([3, 5, 7])).all() - assert (attractor[2] == np.array([5, 7, 9])).all() + pointclouds = prep(ts) + assert (pointclouds[0] == np.array([1, 3, 5])).all() + assert (pointclouds[1] == np.array([3, 5, 7])).all() + assert (pointclouds[2] == np.array([5, 7, 9])).all() + + # Vector series + ts = np.arange(0, 10).reshape(-1, 2) + prep = TimeDelayEmbedding(dim=4) + prep.fit([ts]) + assert (prep.transform([ts])[0] == [[0, 1, 2, 3], [2, 3, 4, 5], [4, 5, 6, 7], [6, 7, 8, 9]]).all() -- cgit v1.2.3 From a74ec878560bbe5fa340b2650ca9c16471b685af Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Tue, 25 Feb 2020 13:27:03 +0900 Subject: Update point_cloud.rst --- src/python/doc/point_cloud.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python/doc/point_cloud.rst b/src/python/doc/point_cloud.rst index 55c74ff3..c0d4b303 100644 --- a/src/python/doc/point_cloud.rst +++ b/src/python/doc/point_cloud.rst @@ -26,4 +26,5 @@ TimeDelayEmbedding .. autoclass:: gudhi.point_cloud.timedelay.TimeDelayEmbedding :members: + :special-members: __call__ -- cgit v1.2.3 From f25d0f86fcd4ac9ab2939b2919d7a66df8b21269 Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Tue, 25 Feb 2020 16:35:41 +0900 Subject: Update timedelay.py --- src/python/gudhi/point_cloud/timedelay.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python/gudhi/point_cloud/timedelay.py b/src/python/gudhi/point_cloud/timedelay.py index d7a1dab7..576f4386 100644 --- a/src/python/gudhi/point_cloud/timedelay.py +++ b/src/python/gudhi/point_cloud/timedelay.py @@ -50,6 +50,7 @@ class TimeDelayEmbedding: def __call__(self, ts): """Transform method for single time-series data. + Parameters ---------- ts : Iterable[float] or Iterable[Iterable[float]] -- cgit v1.2.3 From 2c1edeb7fd241c8718a22618438b482704703b4a Mon Sep 17 00:00:00 2001 From: mtakenouchi Date: Tue, 25 Feb 2020 17:46:28 +0900 Subject: Update timedelay.py --- src/python/gudhi/point_cloud/timedelay.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/python/gudhi/point_cloud/timedelay.py b/src/python/gudhi/point_cloud/timedelay.py index 576f4386..f01df442 100644 --- a/src/python/gudhi/point_cloud/timedelay.py +++ b/src/python/gudhi/point_cloud/timedelay.py @@ -11,8 +11,9 @@ import numpy as np class TimeDelayEmbedding: """Point cloud transformation class. - Embeds time-series data in the R^d according to Takens' Embedding Theorem - and obtains the coordinates of each point. + Embeds time-series data in the R^d according to [Takens' Embedding Theorem] + (https://en.wikipedia.org/wiki/Takens%27s_theorem) and obtains the + coordinates of each point. Parameters ---------- -- cgit v1.2.3 From 73194242e1c8012c1320a7581a382a3b2b59eb09 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 3 Mar 2020 16:30:22 +0100 Subject: Fix #172 and add a proper comment on the modification --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 76608008..5110819f 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1347,7 +1347,9 @@ class Simplex_tree { }); Filtration_value max_filt_border_value = filtration(*max_border); - if (simplex.second.filtration() < max_filt_border_value) { + // Replacing if(f=max)) would mean that if f is NaN, we replace it with the max of the children. + // That seems more useful than keeping NaN. + if (!(simplex.second.filtration() >= max_filt_border_value)) { // Store the filtration modification information modified = true; simplex.second.assign_filtration(max_filt_border_value); -- cgit v1.2.3 From 5b5e9fce6a80151f29f98dde67f5e4150edb9a5b Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 5 Mar 2020 10:03:26 +0100 Subject: Add some tests and documentation for NaN management in make_filtration_non_decreasing Simplex tree method --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 2 + src/Simplex_tree/test/CMakeLists.txt | 6 + ...ee_make_filtration_non_decreasing_unit_test.cpp | 148 +++++++++++++++++++++ src/Simplex_tree/test/simplex_tree_unit_test.cpp | 84 ------------ 4 files changed, 156 insertions(+), 84 deletions(-) create mode 100644 src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 5110819f..7b39a500 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1317,6 +1317,8 @@ class Simplex_tree { * \post Some simplex tree functions require the filtration to be valid. `make_filtration_non_decreasing()` * function is not launching `initialize_filtration()` but returns the filtration modification information. If the * complex has changed , please call `initialize_filtration()` to recompute it. + * + * If a simplex has a `NaN` filtration value, it is considered lower than any other defined filtration value. */ bool make_filtration_non_decreasing() { bool modified = false; diff --git a/src/Simplex_tree/test/CMakeLists.txt b/src/Simplex_tree/test/CMakeLists.txt index 8b9163f5..cf2b0153 100644 --- a/src/Simplex_tree/test/CMakeLists.txt +++ b/src/Simplex_tree/test/CMakeLists.txt @@ -28,3 +28,9 @@ if (TBB_FOUND) target_link_libraries(Simplex_tree_ctor_and_move_test_unit ${TBB_LIBRARIES}) endif() gudhi_add_boost_test(Simplex_tree_ctor_and_move_test_unit) + +add_executable ( Simplex_tree_make_filtration_non_decreasing_test_unit simplex_tree_make_filtration_non_decreasing_unit_test.cpp ) +if (TBB_FOUND) + target_link_libraries(Simplex_tree_make_filtration_non_decreasing_test_unit ${TBB_LIBRARIES}) +endif() +gudhi_add_boost_test(Simplex_tree_make_filtration_non_decreasing_test_unit) diff --git a/src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp new file mode 100644 index 00000000..a8130e25 --- /dev/null +++ b/src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp @@ -0,0 +1,148 @@ +/* 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): Vincent Rouvreau + * + * Copyright (C) 2020 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include +#include // for NaN +#include // for isNaN + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "simplex_tree_make_filtration_non_decreasing" +#include +#include + +// ^ +// /!\ Nothing else from Simplex_tree shall be included to test includes are well defined. +#include "gudhi/Simplex_tree.h" + +using namespace Gudhi; + +typedef boost::mpl::list, Simplex_tree> list_of_tested_variants; + +BOOST_AUTO_TEST_CASE_TEMPLATE(make_filtration_non_decreasing, typeST, list_of_tested_variants) { + typeST st; + + st.insert_simplex_and_subfaces({2, 1, 0}, 2.0); + st.insert_simplex_and_subfaces({3, 0}, 2.0); + st.insert_simplex_and_subfaces({3, 4, 5}, 2.0); + + /* Inserted simplex: */ + /* 1 */ + /* o */ + /* /X\ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + + std::cout << "Check default insertion ensures the filtration values are non decreasing" << std::endl; + BOOST_CHECK(!st.make_filtration_non_decreasing()); + + // Because of non decreasing property of simplex tree, { 0 } , { 1 } and { 0, 1 } are going to be set from value 2.0 + // to 1.0 + st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); + + // Inserted simplex: + // 1 6 + // o---o + // /X\7/ + // o---o---o---o + // 2 0 3\X/4 + // o + // 5 + + std::cout << "Check default second insertion ensures the filtration values are non decreasing" << std::endl; + BOOST_CHECK(!st.make_filtration_non_decreasing()); + + // Copy original simplex tree + typeST st_copy = st; + + // Modify specific values for st to become like st_copy thanks to make_filtration_non_decreasing + st.assign_filtration(st.find({0,1,6,7}), 0.8); + st.assign_filtration(st.find({0,1,6}), 0.9); + st.assign_filtration(st.find({0,6}), 0.6); + st.assign_filtration(st.find({3,4,5}), 1.2); + st.assign_filtration(st.find({3,4}), 1.1); + st.assign_filtration(st.find({4,5}), 1.99); + + std::cout << "Check the simplex_tree is rolled back in case of decreasing filtration values" << std::endl; + BOOST_CHECK(st.make_filtration_non_decreasing()); + BOOST_CHECK(st == st_copy); + + // Other simplex tree + typeST st_other; + st_other.insert_simplex_and_subfaces({2, 1, 0}, 3.0); // This one is different from st + st_other.insert_simplex_and_subfaces({3, 0}, 2.0); + st_other.insert_simplex_and_subfaces({3, 4, 5}, 2.0); + st_other.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); + + // Modify specific values for st to become like st_other thanks to make_filtration_non_decreasing + st.assign_filtration(st.find({2}), 3.0); + // By modifying just the simplex {2} + // {0,1,2}, {1,2} and {0,2} will be modified + + std::cout << "Check the simplex_tree is repaired in case of decreasing filtration values" << std::endl; + BOOST_CHECK(st.make_filtration_non_decreasing()); + BOOST_CHECK(st == st_other); + + // Modify specific values for st still to be non-decreasing + st.assign_filtration(st.find({0,1,2}), 10.0); + st.assign_filtration(st.find({0,2}), 9.0); + st.assign_filtration(st.find({0,1,6,7}), 50.0); + st.assign_filtration(st.find({0,1,6}), 49.0); + st.assign_filtration(st.find({0,1,7}), 48.0); + // Other copy simplex tree + typeST st_other_copy = st; + + std::cout << "Check the simplex_tree is not modified in case of non-decreasing filtration values" << std::endl; + BOOST_CHECK(!st.make_filtration_non_decreasing()); + BOOST_CHECK(st == st_other_copy); + +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(make_filtration_non_decreasing_on_nan_values, typeST, list_of_tested_variants) { + typeST st; + + st.insert_simplex_and_subfaces({2, 1, 0}, std::numeric_limits::quiet_NaN()); + st.insert_simplex_and_subfaces({3, 0}, std::numeric_limits::quiet_NaN()); + st.insert_simplex_and_subfaces({3, 4, 5}, std::numeric_limits::quiet_NaN()); + + /* Inserted simplex: */ + /* 1 */ + /* o */ + /* /X\ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + + std::cout << "SPECIFIC CASE:" << std::endl; + std::cout << "Insertion with NaN values does not ensure the filtration values are non decreasing" << std::endl; + st.make_filtration_non_decreasing(); + + std::cout << "Check all filtration values are NaN" << std::endl; + for (auto f_simplex : st.filtration_simplex_range()) { + BOOST_CHECK(std::isnan(st.filtration(f_simplex))); + } + + st.assign_filtration(st.find({0}), 0.); + st.assign_filtration(st.find({1}), 0.); + st.assign_filtration(st.find({2}), 0.); + st.assign_filtration(st.find({3}), 0.); + st.assign_filtration(st.find({4}), 0.); + st.assign_filtration(st.find({5}), 0.); + + std::cout << "Check make_filtration_non_decreasing is modifying the simplicial complex" << std::endl; + BOOST_CHECK(st.make_filtration_non_decreasing()); + + std::cout << "Check all filtration values are now defined" << std::endl; + for (auto f_simplex : st.filtration_simplex_range()) { + BOOST_CHECK(!std::isnan(st.filtration(f_simplex))); + } +} \ No newline at end of file diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 58bfa8db..e739ad0a 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -791,90 +791,6 @@ BOOST_AUTO_TEST_CASE(non_contiguous) { BOOST_CHECK(++i == std::end(b)); } -BOOST_AUTO_TEST_CASE(make_filtration_non_decreasing) { - std::cout << "********************************************************************" << std::endl; - std::cout << "MAKE FILTRATION NON DECREASING" << std::endl; - typedef Simplex_tree<> typeST; - typeST st; - - st.insert_simplex_and_subfaces({2, 1, 0}, 2.0); - st.insert_simplex_and_subfaces({3, 0}, 2.0); - st.insert_simplex_and_subfaces({3, 4, 5}, 2.0); - - /* Inserted simplex: */ - /* 1 */ - /* o */ - /* /X\ */ - /* o---o---o---o */ - /* 2 0 3\X/4 */ - /* o */ - /* 5 */ - - std::cout << "Check default insertion ensures the filtration values are non decreasing" << std::endl; - BOOST_CHECK(!st.make_filtration_non_decreasing()); - - // Because of non decreasing property of simplex tree, { 0 } , { 1 } and { 0, 1 } are going to be set from value 2.0 - // to 1.0 - st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); - - // Inserted simplex: - // 1 6 - // o---o - // /X\7/ - // o---o---o---o - // 2 0 3\X/4 - // o - // 5 - - std::cout << "Check default second insertion ensures the filtration values are non decreasing" << std::endl; - BOOST_CHECK(!st.make_filtration_non_decreasing()); - - // Copy original simplex tree - typeST st_copy = st; - - // Modify specific values for st to become like st_copy thanks to make_filtration_non_decreasing - st.assign_filtration(st.find({0,1,6,7}), 0.8); - st.assign_filtration(st.find({0,1,6}), 0.9); - st.assign_filtration(st.find({0,6}), 0.6); - st.assign_filtration(st.find({3,4,5}), 1.2); - st.assign_filtration(st.find({3,4}), 1.1); - st.assign_filtration(st.find({4,5}), 1.99); - - std::cout << "Check the simplex_tree is rolled back in case of decreasing filtration values" << std::endl; - BOOST_CHECK(st.make_filtration_non_decreasing()); - BOOST_CHECK(st == st_copy); - - // Other simplex tree - typeST st_other; - st_other.insert_simplex_and_subfaces({2, 1, 0}, 3.0); // This one is different from st - st_other.insert_simplex_and_subfaces({3, 0}, 2.0); - st_other.insert_simplex_and_subfaces({3, 4, 5}, 2.0); - st_other.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); - - // Modify specific values for st to become like st_other thanks to make_filtration_non_decreasing - st.assign_filtration(st.find({2}), 3.0); - // By modifying just the simplex {2} - // {0,1,2}, {1,2} and {0,2} will be modified - - std::cout << "Check the simplex_tree is repaired in case of decreasing filtration values" << std::endl; - BOOST_CHECK(st.make_filtration_non_decreasing()); - BOOST_CHECK(st == st_other); - - // Modify specific values for st still to be non-decreasing - st.assign_filtration(st.find({0,1,2}), 10.0); - st.assign_filtration(st.find({0,2}), 9.0); - st.assign_filtration(st.find({0,1,6,7}), 50.0); - st.assign_filtration(st.find({0,1,6}), 49.0); - st.assign_filtration(st.find({0,1,7}), 48.0); - // Other copy simplex tree - typeST st_other_copy = st; - - std::cout << "Check the simplex_tree is not modified in case of non-decreasing filtration values" << std::endl; - BOOST_CHECK(!st.make_filtration_non_decreasing()); - BOOST_CHECK(st == st_other_copy); - -} - typedef boost::mpl::list, -- cgit v1.2.3 From 19ea0c10f283188282a78ebebf4c1a51f2f40040 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 5 Mar 2020 14:14:27 +0100 Subject: CR: use complex_simplex_range instead of filtration_simplex_range --- .../test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp index a8130e25..4697ec05 100644 --- a/src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp @@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(make_filtration_non_decreasing_on_nan_values, type st.make_filtration_non_decreasing(); std::cout << "Check all filtration values are NaN" << std::endl; - for (auto f_simplex : st.filtration_simplex_range()) { + for (auto f_simplex : st.complex_simplex_range()) { BOOST_CHECK(std::isnan(st.filtration(f_simplex))); } @@ -142,7 +142,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(make_filtration_non_decreasing_on_nan_values, type BOOST_CHECK(st.make_filtration_non_decreasing()); std::cout << "Check all filtration values are now defined" << std::endl; - for (auto f_simplex : st.filtration_simplex_range()) { + for (auto f_simplex : st.complex_simplex_range()) { BOOST_CHECK(!std::isnan(st.filtration(f_simplex))); } } \ No newline at end of file -- cgit v1.2.3 From b0bd6dfc34a3c93073e9f326292047f8debb7fb3 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 12 Mar 2020 23:46:03 +0100 Subject: Update hera --- ext/hera | 2 +- src/cmake/modules/GUDHI_third_party_libraries.cmake | 2 +- src/cmake/modules/GUDHI_user_version_target.cmake | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/hera b/ext/hera index cb1838e6..0019cae9 160000 --- a/ext/hera +++ b/ext/hera @@ -1 +1 @@ -Subproject commit cb1838e682ec07f80720241cf9098400caeb83c7 +Subproject commit 0019cae9dc1e9d11aa03bc59681435ba7f21eea8 diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 6db2c76b..2d010483 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -68,7 +68,7 @@ if(CGAL_FOUND) endif() # For those who dislike bundled dependencies, this indicates where to find a preinstalled Hera. -set(HERA_WASSERSTEIN_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/ext/hera/geom_matching/wasserstein/include CACHE PATH "Directory where one can find Hera's wasserstein.h") +set(HERA_WASSERSTEIN_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/ext/hera/wasserstein/include CACHE PATH "Directory where one can find Hera's wasserstein.h") option(WITH_GUDHI_USE_TBB "Build with Intel TBB parallelization" ON) diff --git a/src/cmake/modules/GUDHI_user_version_target.cmake b/src/cmake/modules/GUDHI_user_version_target.cmake index 5047252f..257d1939 100644 --- a/src/cmake/modules/GUDHI_user_version_target.cmake +++ b/src/cmake/modules/GUDHI_user_version_target.cmake @@ -55,7 +55,7 @@ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/src/GudhUI ${GUDHI_USER_VERSION_DIR}/GudhUI) add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${CMAKE_SOURCE_DIR}/ext/hera/geom_matching/wasserstein/include ${GUDHI_USER_VERSION_DIR}/ext/hera/geom_matching/wasserstein/include) + copy_directory ${CMAKE_SOURCE_DIR}/ext/hera/wasserstein/include ${GUDHI_USER_VERSION_DIR}/ext/hera/wasserstein/include) set(GUDHI_DIRECTORIES "doc;example;concept;utilities") -- cgit v1.2.3 From ba24c58487f9a62e024138127c1b8375449334f9 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 13 Mar 2020 09:17:25 +0100 Subject: Mention git submodule sync --- .github/how_to_use_github_to_contribute_to_gudhi.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/how_to_use_github_to_contribute_to_gudhi.md b/.github/how_to_use_github_to_contribute_to_gudhi.md index 6ab05e36..747ca39b 100644 --- a/.github/how_to_use_github_to_contribute_to_gudhi.md +++ b/.github/how_to_use_github_to_contribute_to_gudhi.md @@ -25,10 +25,10 @@ This creates a directory gudhi-devel, which you are free to move around or renam cd gudhi-devel ``` -Everytime you clone the repository, you will have to download the *submodules*. +When you clone the repository, you also need to download the *submodules*. ## Submodules -An interface to Hera for Wasserstein distance is available on an external git repository. To download it: +Hera, used for Wasserstein distance, is available on an external git repository. To download it: ```bash git submodule update --init ``` @@ -60,8 +60,9 @@ This is a command you can run quite regularly. It tells git to check all that happened on github. It is safe, it will not mess with your files. -**Reminder:** Everytime you checkout master or merge from master, afterwards, if the version of one the submodule has changed, or if a submodule was added, you will have to: +**Reminder:** If the version of a submodule has changed, or if a submodule was added, you may need to: ```bash +git submodule sync git submodule update --init ``` -- cgit v1.2.3