diff options
author | vrouvrea <vrouvrea@636b058d-ea47-450e-bf9e-a15bfbe3eedb> | 2017-01-16 09:20:20 +0000 |
---|---|---|
committer | vrouvrea <vrouvrea@636b058d-ea47-450e-bf9e-a15bfbe3eedb> | 2017-01-16 09:20:20 +0000 |
commit | df601fe3e27210133e3551352382be779a4408ca (patch) | |
tree | 9cd934f71a340540c798e8c92076625f1992b3ad /src/Subsampling | |
parent | a2977f4038b8cfc375f037de7c5c805a9079f9f7 (diff) | |
parent | e3707de64413df06f83770a40ed8ba4ad9a69951 (diff) |
Merge last trunk modifications
git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/distance_matrix_in_rips_module@1938 636b058d-ea47-450e-bf9e-a15bfbe3eedb
Former-commit-id: 8af39a00b9134dbcc77883412c29d7184479979b
Diffstat (limited to 'src/Subsampling')
6 files changed, 162 insertions, 16 deletions
diff --git a/src/Subsampling/example/CMakeLists.txt b/src/Subsampling/example/CMakeLists.txt index 54349f0c..0fd3335c 100644 --- a/src/Subsampling/example/CMakeLists.txt +++ b/src/Subsampling/example/CMakeLists.txt @@ -6,6 +6,7 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) add_executable(Subsampling_example_pick_n_random_points example_pick_n_random_points.cpp) add_executable(Subsampling_example_choose_n_farthest_points example_choose_n_farthest_points.cpp) + add_executable(Subsampling_example_custom_kernel example_custom_kernel.cpp) add_executable(Subsampling_example_sparsify_point_set example_sparsify_point_set.cpp) target_link_libraries(Subsampling_example_sparsify_point_set ${CGAL_LIBRARY}) diff --git a/src/Subsampling/example/example_custom_kernel.cpp b/src/Subsampling/example/example_custom_kernel.cpp new file mode 100644 index 00000000..25b5bf6c --- /dev/null +++ b/src/Subsampling/example/example_custom_kernel.cpp @@ -0,0 +1,63 @@ +#include <gudhi/choose_n_farthest_points.h> + +#include <CGAL/Epick_d.h> +#include <CGAL/Random.h> + +#include <vector> +#include <iterator> + + +/* The class Kernel contains a distance function defined on the set of points {0, 1, 2, 3} + * and computes a distance according to the matrix: + * 0 1 2 4 + * 1 0 4 2 + * 2 4 0 1 + * 4 2 1 0 + */ +class Kernel { + public: + typedef double FT; + typedef unsigned Point_d; + + // Class Squared_distance_d + class Squared_distance_d { + private: + std::vector<std::vector<FT>> matrix_; + + public: + Squared_distance_d() { + matrix_.push_back(std::vector<FT>({0, 1, 2, 4})); + matrix_.push_back(std::vector<FT>({1, 0, 4, 2})); + matrix_.push_back(std::vector<FT>({2, 4, 0, 1})); + matrix_.push_back(std::vector<FT>({4, 2, 1, 0})); + } + + FT operator()(Point_d p1, Point_d p2) { + return matrix_[p1][p2]; + } + }; + + // Constructor + Kernel() {} + + // Object of type Squared_distance_d + Squared_distance_d squared_distance_d_object() const { + return Squared_distance_d(); + } +}; + +int main(void) { + typedef Kernel K; + typedef typename K::Point_d Point_d; + + K k; + std::vector<Point_d> points = {0, 1, 2, 3}; + std::vector<Point_d> results; + + Gudhi::subsampling::choose_n_farthest_points(k, points, 2, std::back_inserter(results)); + std::cout << "Before sparsification: " << points.size() << " points.\n"; + std::cout << "After sparsification: " << results.size() << " points.\n"; + std::cout << "Result table: {" << results[0] << "," << results[1] << "}\n"; + + return 0; +} diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h index 40c7808d..5e908090 100644 --- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h +++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h @@ -48,22 +48,40 @@ namespace subsampling { * \brief Subsample by a greedy strategy of iteratively adding the farthest point from the * current chosen point set to the subsampling. * The iteration starts with the landmark `starting point`. + * \tparam Kernel must provide a type Kernel::Squared_distance_d which is a model of the + * concept <a target="_blank" + * href="http://doc.cgal.org/latest/Kernel_d/classKernel__d_1_1Squared__distance__d.html">Kernel_d::Squared_distance_d</a> + * concept. + * It must also contain a public member 'squared_distance_d_object' of this type. + * \tparam Point_range Range whose value type is Kernel::Point_d. It must provide random-access + * via `operator[]` and the points should be stored contiguously in memory. + * \tparam OutputIterator Output iterator whose value type is Kernel::Point_d. * \details It chooses `final_size` points from a random access range `input_pts` and * outputs it in the output iterator `output_it`. + * @param[in] k A kernel object. + * @param[in] input_pts Const reference to the input points. + * @param[in] final_size The size of the subsample to compute. + * @param[in] starting_point The seed in the farthest point algorithm. + * @param[out] output_it The output iterator. * */ template < typename Kernel, -typename Point_container, +typename Point_range, typename OutputIterator> void choose_n_farthest_points(Kernel const &k, - Point_container const &input_pts, + Point_range const &input_pts, std::size_t final_size, std::size_t starting_point, OutputIterator output_it) { - typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object(); - std::size_t nb_points = boost::size(input_pts); - assert(nb_points >= final_size); + if (final_size > nb_points) + final_size = nb_points; + + // Tests to the limit + if (final_size < 1) + return; + + typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object(); std::size_t current_number_of_landmarks = 0; // counter for landmarks const double infty = std::numeric_limits<double>::infinity(); // infinity (see next entry) @@ -96,22 +114,39 @@ void choose_n_farthest_points(Kernel const &k, * \brief Subsample by a greedy strategy of iteratively adding the farthest point from the * current chosen point set to the subsampling. * The iteration starts with a random landmark. + * \tparam Kernel must provide a type Kernel::Squared_distance_d which is a model of the + * concept <a target="_blank" + * href="http://doc.cgal.org/latest/Kernel_d/classKernel__d_1_1Squared__distance__d.html">Kernel_d::Squared_distance_d</a> + * concept. + * It must also contain a public member 'squared_distance_d_object' of this type. + * \tparam Point_range Range whose value type is Kernel::Point_d. It must provide random-access + * via `operator[]` and the points should be stored contiguously in memory. + * \tparam OutputIterator Output iterator whose value type is Kernel::Point_d. * \details It chooses `final_size` points from a random access range `input_pts` and * outputs it in the output iterator `output_it`. + * @param[in] k A kernel object. + * @param[in] input_pts Const reference to the input points. + * @param[in] final_size The size of the subsample to compute. + * @param[out] output_it The output iterator. * */ template < typename Kernel, -typename Point_container, +typename Point_range, typename OutputIterator> void choose_n_farthest_points(Kernel const& k, - Point_container const &input_pts, + Point_range const &input_pts, unsigned final_size, OutputIterator output_it) { + // Tests to the limit + if ((final_size < 1) || (input_pts.size() == 0)) + return; + // Choose randomly the first landmark std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 6); - int starting_point = dis(gen); + std::uniform_int_distribution<> dis(0, (input_pts.size() - 1)); + std::size_t starting_point = dis(gen); + choose_n_farthest_points(k, input_pts, final_size, starting_point, output_it); } diff --git a/src/Subsampling/include/gudhi/pick_n_random_points.h b/src/Subsampling/include/gudhi/pick_n_random_points.h index e89b2b2d..f0e3f1f1 100644 --- a/src/Subsampling/include/gudhi/pick_n_random_points.h +++ b/src/Subsampling/include/gudhi/pick_n_random_points.h @@ -57,7 +57,9 @@ void pick_n_random_points(Point_container const &points, #endif std::size_t nbP = boost::size(points); - assert(nbP >= final_size); + if (final_size > nbP) + final_size = nbP; + std::vector<int> landmarks(nbP); std::iota(landmarks.begin(), landmarks.end(), 0); diff --git a/src/Subsampling/include/gudhi/sparsify_point_set.h b/src/Subsampling/include/gudhi/sparsify_point_set.h index 7ff11b4c..507f8c79 100644 --- a/src/Subsampling/include/gudhi/sparsify_point_set.h +++ b/src/Subsampling/include/gudhi/sparsify_point_set.h @@ -64,8 +64,6 @@ sparsify_point_set( typedef typename Gudhi::spatial_searching::Kd_tree_search< Kernel, Point_range> Points_ds; - typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object(); - #ifdef GUDHI_SUBSAMPLING_PROFILING Gudhi::Clock t; #endif diff --git a/src/Subsampling/test/test_choose_n_farthest_points.cpp b/src/Subsampling/test/test_choose_n_farthest_points.cpp index d064899a..0bc0dff4 100644 --- a/src/Subsampling/test/test_choose_n_farthest_points.cpp +++ b/src/Subsampling/test/test_choose_n_farthest_points.cpp @@ -39,18 +39,65 @@ typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> K; typedef typename K::FT FT; typedef typename K::Point_d Point_d; -BOOST_AUTO_TEST_CASE(test_choose_farthest_point) { +typedef boost::mpl::list<CGAL::Epick_d<CGAL::Dynamic_dimension_tag>, CGAL::Epick_d<CGAL::Dimension_tag<4>>> list_of_tested_kernels; + +BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point, Kernel, list_of_tested_kernels) { + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point_d; std::vector< Point_d > points, landmarks; // Add grid points (625 points) for (FT i = 0; i < 5; i += 1.0) for (FT j = 0; j < 5; j += 1.0) for (FT k = 0; k < 5; k += 1.0) - for (FT l = 0; l < 5; l += 1.0) - points.push_back(Point_d(std::vector<FT>({i, j, k, l}))); + for (FT l = 0; l < 5; l += 1.0) { + std::vector<FT> point({i, j, k, l}); + points.push_back(Point_d(point.begin(), point.end())); + } landmarks.clear(); - K k; + Kernel k; Gudhi::subsampling::choose_n_farthest_points(k, points, 100, std::back_inserter(landmarks)); BOOST_CHECK(landmarks.size() == 100); + for (auto landmark : landmarks) + { + // Check all landmarks are in points + BOOST_CHECK(std::find (points.begin(), points.end(), landmark) != points.end()); + } +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point_limits, Kernel, list_of_tested_kernels) { + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point_d; + std::vector< Point_d > points, landmarks; + landmarks.clear(); + Kernel k; + // Choose -1 farthest points in an empty point cloud + Gudhi::subsampling::choose_n_farthest_points(k, points, -1, std::back_inserter(landmarks)); + BOOST_CHECK(landmarks.size() == 0); + landmarks.clear(); + // Choose 0 farthest points in an empty point cloud + Gudhi::subsampling::choose_n_farthest_points(k, points, 0, std::back_inserter(landmarks)); + BOOST_CHECK(landmarks.size() == 0); + landmarks.clear(); + // Choose 1 farthest points in an empty point cloud + Gudhi::subsampling::choose_n_farthest_points(k, points, 1, std::back_inserter(landmarks)); + BOOST_CHECK(landmarks.size() == 0); + landmarks.clear(); + + std::vector<FT> point({0.0, 0.0, 0.0, 0.0}); + points.push_back(Point_d(point.begin(), point.end())); + // Choose -1 farthest points in an empty point cloud + Gudhi::subsampling::choose_n_farthest_points(k, points, -1, std::back_inserter(landmarks)); + BOOST_CHECK(landmarks.size() == 1); + landmarks.clear(); + // Choose 0 farthest points in a one point cloud + Gudhi::subsampling::choose_n_farthest_points(k, points, 0, std::back_inserter(landmarks)); + BOOST_CHECK(landmarks.size() == 0); + landmarks.clear(); + // Choose 1 farthest points in a one point cloud + Gudhi::subsampling::choose_n_farthest_points(k, points, 1, std::back_inserter(landmarks)); + BOOST_CHECK(landmarks.size() == 1); + landmarks.clear(); + } |