From 1ef113ff6f5db7288e4dc4c18c053b18d90dbf1a Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Fri, 30 Apr 2021 11:17:35 +0200 Subject: First version of points generation on torus --- src/python/CMakeLists.txt | 4 ++ .../gudhi/datasets/generators/points/__init__.py | 0 .../gudhi/datasets/generators/points/_torus.cc | 70 ++++++++++++++++++++++ .../gudhi/datasets/generators/points/torus.py | 52 ++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 src/python/gudhi/datasets/generators/points/__init__.py create mode 100644 src/python/gudhi/datasets/generators/points/_torus.cc create mode 100644 src/python/gudhi/datasets/generators/points/torus.py (limited to 'src/python') diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index a1440cbc..1b9db2b5 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -46,6 +46,7 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'bottleneck', ") set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'hera', ") set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'clustering', ") + set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'datasets/generators/points', ") endif() if(CYTHON_FOUND) set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'off_reader', ") @@ -151,6 +152,7 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'hera/wasserstein', ") set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'hera/bottleneck', ") if (NOT CGAL_VERSION VERSION_LESS 4.11.0) + set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'datasets/generators/points/_torus', ") set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'bottleneck', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'nerve_gic', ") endif () @@ -262,6 +264,8 @@ if(PYTHONINTERP_FOUND) file(COPY "gudhi/weighted_rips_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") file(COPY "gudhi/dtm_rips_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") file(COPY "gudhi/hera/__init__.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/hera") + file(COPY "gudhi/datasets/generators/points/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/datasets/generators/points/" FILES_MATCHING PATTERN "*.py") + # Some files for pip package file(COPY "introduction.rst" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/") diff --git a/src/python/gudhi/datasets/generators/points/__init__.py b/src/python/gudhi/datasets/generators/points/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/python/gudhi/datasets/generators/points/_torus.cc b/src/python/gudhi/datasets/generators/points/_torus.cc new file mode 100644 index 00000000..21638bb8 --- /dev/null +++ b/src/python/gudhi/datasets/generators/points/_torus.cc @@ -0,0 +1,70 @@ +/* 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): Hind Montassif + * + * Copyright (C) 2021 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include +#include + +#include +#include + +#include + +namespace py = pybind11; + + +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kern; + + +py::array_t generate_points_on_torus(size_t num_points, int dim, bool uniform) { + + std::vector points_generated; + + { + py::gil_scoped_release release; + points_generated = Gudhi::generate_points_on_torus_d(num_points, dim, uniform); + } + + size_t npoints = points_generated.size(); + + py::print("points generated size: "); + py::print(points_generated.size()); + py::print(points_generated[0].size()); + + GUDHI_CHECK(2*dim == points_generated[0].size(), "Py array second dimension not matching the double ambient space dimension"); + + py::array_t points({npoints, (size_t)2*dim}); + + py::buffer_info buf = points.request(); + double *ptr = static_cast(buf.ptr); + + for (size_t i = 0; i < npoints; i++) + for (int j = 0; j < 2*dim; j++) + ptr[i*(2*dim)+j] = points_generated[i][j]; + + return points; +} + +PYBIND11_MODULE(_torus, m) { + m.attr("__license__") = "LGPL v3"; + m.def("generate_random_points", &generate_points_on_torus, + py::arg("num_points"), py::arg("dim"), py::arg("uniform") = false, + R"pbdoc( + Generate random i.i.d. points on a d-torus in R^2d + + :param num_points: The number of points to be generated. + :type num_points: unsigned integer + :param dim: The dimension. + :type dim: integer + :param uniform: A flag to define if the points generation is uniform (generated as a grid). + :type uniform: bool + :rtype: numpy array of float + :returns: the generated points on a torus. + )pbdoc"); +} diff --git a/src/python/gudhi/datasets/generators/points/torus.py b/src/python/gudhi/datasets/generators/points/torus.py new file mode 100644 index 00000000..2de696b2 --- /dev/null +++ b/src/python/gudhi/datasets/generators/points/torus.py @@ -0,0 +1,52 @@ +# 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): Hind Montassif +# +# Copyright (C) 2021 Inria +# +# Modification(s): +# - YYYY/MM Author: Description of the modification + +import numpy as np +import math + + +def generate_random_points(num_points, dim): + + # Generate random angles of size num_points*dim + alpha = 2*math.pi*np.random.rand(num_points*dim) + + # Based on angles, construct points of size num_points*dim on a circle and reshape the result in a num_points*2*dim array + array_points = np.asarray([[np.cos(a), np.sin(a)] for a in alpha]).ravel().reshape(num_points, 2*dim) + + return array_points + + +def generate_grid_points(num_points, dim): + + num_points_grid = (int(num_points**(1./dim)))**dim + + alpha = 2*math.pi*np.random.rand(num_points_grid*dim) + + array_points = np.asarray([[np.cos(a), np.sin(a)] for a in alpha]).ravel().reshape(num_points_grid, 2*dim) + + return array_points + +def generate_points(num_points, dim, sample='random'): + if sample == 'random': + print("Sample is random") + npoints = num_points + elif sample == 'grid': + print("Sample is grid") + npoints = (int(num_points**(1./dim)))**dim + else: + print("Sample type '{}' is not supported".format(sample)) + return + + # Generate random angles of size num_points*dim + alpha = 2*math.pi*np.random.rand(npoints*dim) + + # Based on angles, construct points of size num_points*dim on a circle and reshape the result in a num_points*2*dim array + array_points = np.asarray([[np.cos(a), np.sin(a)] for a in alpha]).ravel().reshape(npoints, 2*dim) + + return array_points -- cgit v1.2.3