diff options
Diffstat (limited to 'src/Bottleneck_distance')
8 files changed, 70 insertions, 66 deletions
diff --git a/src/Bottleneck_distance/example/CMakeLists.txt b/src/Bottleneck_distance/example/CMakeLists.txt index b0a19f8b..0d0bff45 100644 --- a/src/Bottleneck_distance/example/CMakeLists.txt +++ b/src/Bottleneck_distance/example/CMakeLists.txt @@ -5,8 +5,6 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) add_executable (bottleneck_read_file_example bottleneck_read_file_example.cpp) add_executable (bottleneck_basic_example bottleneck_basic_example.cpp) - add_test(bottleneck_basic_example ${CMAKE_CURRENT_BINARY_DIR}/bottleneck_basic_example) - add_executable (alpha_rips_persistence_bottleneck_distance alpha_rips_persistence_bottleneck_distance.cpp) target_link_libraries(alpha_rips_persistence_bottleneck_distance ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) if (TBB_FOUND) @@ -14,7 +12,11 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) target_link_libraries(bottleneck_basic_example ${TBB_LIBRARIES}) target_link_libraries(alpha_rips_persistence_bottleneck_distance ${TBB_LIBRARIES}) endif(TBB_FOUND) - add_test(alpha_rips_persistence_bottleneck_distance ${CMAKE_CURRENT_BINARY_DIR}/alpha_rips_persistence_bottleneck_distance - ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off -r 0.15 -m 0.12 -d 3 -p 3) + + add_test(NAME Bottleneck_distance_example_basic COMMAND $<TARGET_FILE:bottleneck_basic_example>) + + add_test(NAME Bottleneck_distance_example_alpha_rips_persistence_bottleneck + COMMAND $<TARGET_FILE:alpha_rips_persistence_bottleneck_distance> + "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.15" "-m" "0.12" "-d" "3" "-p" "3") endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) diff --git a/src/Bottleneck_distance/example/alpha_rips_persistence_bottleneck_distance.cpp b/src/Bottleneck_distance/example/alpha_rips_persistence_bottleneck_distance.cpp index fd9f0858..fd164b22 100644 --- a/src/Bottleneck_distance/example/alpha_rips_persistence_bottleneck_distance.cpp +++ b/src/Bottleneck_distance/example/alpha_rips_persistence_bottleneck_distance.cpp @@ -74,7 +74,7 @@ int main(int argc, char * argv[]) { // -------------------------------------------- // Rips persistence // -------------------------------------------- - Rips_complex rips_complex(off_reader.get_point_cloud(), threshold, Euclidean_distance()); + Rips_complex rips_complex(off_reader.get_point_cloud(), threshold, Gudhi::Euclidean_distance()); // Construct the Rips complex in a Simplex Tree Simplex_tree rips_stree; diff --git a/src/Bottleneck_distance/include/gudhi/Bottleneck.h b/src/Bottleneck_distance/include/gudhi/Bottleneck.h index b90a0ee0..8c97dce9 100644 --- a/src/Bottleneck_distance/include/gudhi/Bottleneck.h +++ b/src/Bottleneck_distance/include/gudhi/Bottleneck.h @@ -101,11 +101,11 @@ double bottleneck_distance_exact(Persistence_graph& g) { */ template<typename Persistence_diagram1, typename Persistence_diagram2> double bottleneck_distance(const Persistence_diagram1 &diag1, const Persistence_diagram2 &diag2, - double e = std::numeric_limits<double>::min()) { + double e = (std::numeric_limits<double>::min)()) { Persistence_graph g(diag1, diag2, e); if (g.bottleneck_alive() == std::numeric_limits<double>::infinity()) return std::numeric_limits<double>::infinity(); - return std::max(g.bottleneck_alive(), e == 0. ? bottleneck_distance_exact(g) : bottleneck_distance_approx(g, e)); + return (std::max)(g.bottleneck_alive(), e == 0. ? bottleneck_distance_exact(g) : bottleneck_distance_approx(g, e)); } } // namespace persistence_diagram diff --git a/src/Bottleneck_distance/include/gudhi/Graph_matching.h b/src/Bottleneck_distance/include/gudhi/Graph_matching.h index e1708c5b..f51e22e9 100644 --- a/src/Bottleneck_distance/include/gudhi/Graph_matching.h +++ b/src/Bottleneck_distance/include/gudhi/Graph_matching.h @@ -26,7 +26,8 @@ #include <gudhi/Neighbors_finder.h> #include <vector> -#include <list> +#include <unordered_set> +#include <algorithm> namespace Gudhi { @@ -40,8 +41,6 @@ class Graph_matching { public: /** \internal \brief Constructor constructing an empty matching. */ explicit Graph_matching(Persistence_graph &g); - /** \internal \brief Copy operator. */ - Graph_matching& operator=(const Graph_matching& m); /** \internal \brief Is the matching perfect ? */ bool perfect() const; /** \internal \brief Augments the matching with a maximal set of edge-disjoint shortest augmenting paths. */ @@ -50,12 +49,12 @@ class Graph_matching { void set_r(double r); private: - Persistence_graph& g; + Persistence_graph* gp; double r; /** \internal \brief Given a point from V, provides its matched point in U, null_point_index() if there isn't. */ std::vector<int> v_to_u; /** \internal \brief All the unmatched points in U. */ - std::list<int> unmatched_in_u; + std::unordered_set<int> unmatched_in_u; /** \internal \brief Provides a Layered_neighbors_finder dividing the graph in layers. Basically a BFS. */ Layered_neighbors_finder layering() const; @@ -66,17 +65,9 @@ class Graph_matching { }; inline Graph_matching::Graph_matching(Persistence_graph& g) - : g(g), r(0.), v_to_u(g.size(), null_point_index()), unmatched_in_u() { + : gp(&g), r(0.), v_to_u(g.size(), null_point_index()), unmatched_in_u(g.size()) { for (int u_point_index = 0; u_point_index < g.size(); ++u_point_index) - unmatched_in_u.emplace_back(u_point_index); -} - -inline Graph_matching& Graph_matching::operator=(const Graph_matching& m) { - g = m.g; - r = m.r; - v_to_u = m.v_to_u; - unmatched_in_u = m.unmatched_in_u; - return *this; + unmatched_in_u.insert(u_point_index); } inline bool Graph_matching::perfect() const { @@ -88,12 +79,12 @@ inline bool Graph_matching::multi_augment() { return false; Layered_neighbors_finder layered_nf(layering()); int max_depth = layered_nf.vlayers_number()*2 - 1; - double rn = sqrt(g.size()); + double rn = sqrt(gp->size()); // verification of a necessary criterion in order to shortcut if possible if (max_depth < 0 || (unmatched_in_u.size() > rn && max_depth >= rn)) return false; bool successful = false; - std::list<int> tries(unmatched_in_u); + std::vector<int> tries(unmatched_in_u.cbegin(), unmatched_in_u.cend()); for (auto it = tries.cbegin(); it != tries.cend(); it++) // 'augment' has side-effects which have to be always executed, don't change order successful = augment(layered_nf, *it, max_depth) || successful; @@ -133,12 +124,12 @@ inline bool Graph_matching::augment(Layered_neighbors_finder & layered_nf, int u } inline Layered_neighbors_finder Graph_matching::layering() const { - std::list<int> u_vertices(unmatched_in_u); - std::list<int> v_vertices; - Neighbors_finder nf(g, r); - for (int v_point_index = 0; v_point_index < g.size(); ++v_point_index) + std::vector<int> u_vertices(unmatched_in_u.cbegin(), unmatched_in_u.cend()); + std::vector<int> v_vertices; + Neighbors_finder nf(*gp, r); + for (int v_point_index = 0; v_point_index < gp->size(); ++v_point_index) nf.add(v_point_index); - Layered_neighbors_finder layered_nf(g, r); + Layered_neighbors_finder layered_nf(*gp, r); for (int layer = 0; !u_vertices.empty(); layer++) { // one layer is one step in the BFS for (auto it1 = u_vertices.cbegin(); it1 != u_vertices.cend(); ++it1) { @@ -166,7 +157,8 @@ inline Layered_neighbors_finder Graph_matching::layering() const { } inline void Graph_matching::update(std::vector<int>& path) { - unmatched_in_u.remove(path.front()); + // Must return 1. + unmatched_in_u.erase(path.front()); for (auto it = path.cbegin(); it != path.cend(); ++it) { // Be careful, the iterator is incremented twice each time int tmp = *it; diff --git a/src/Bottleneck_distance/include/gudhi/Neighbors_finder.h b/src/Bottleneck_distance/include/gudhi/Neighbors_finder.h index cd5486f8..bdc47578 100644 --- a/src/Bottleneck_distance/include/gudhi/Neighbors_finder.h +++ b/src/Bottleneck_distance/include/gudhi/Neighbors_finder.h @@ -25,9 +25,6 @@ // Inclusion order is important for CGAL patch #include <CGAL/Kd_tree.h> -#include <CGAL/Kd_tree_node.h> -#include <CGAL/Orthogonal_k_neighbor_search.h> -#include <CGAL/Weighted_Minkowski_distance.h> #include <CGAL/Search_traits.h> #include <gudhi/Persistence_graph.h> @@ -40,6 +37,33 @@ namespace Gudhi { namespace persistence_diagram { +/** \internal \brief Variant of CGAL::Fuzzy_iso_box to ensure that the box ic closed. It isn't clear how necessary that is. + */ +struct Square_query { + typedef CGAL::Dimension_tag<2> D; + typedef Internal_point Point_d; + typedef double FT; + bool contains(Point_d p) const { + return std::abs(p.x()-c.x())<=size && std::abs(p.y()-c.y())<=size; + } + bool inner_range_intersects(CGAL::Kd_tree_rectangle<FT,D> const&r) const { + return + r.max_coord(0) >= c.x() - size && + r.min_coord(0) <= c.x() + size && + r.max_coord(1) >= c.y() - size && + r.min_coord(1) <= c.y() + size; + } + bool outer_range_contains(CGAL::Kd_tree_rectangle<FT,D> const&r) const { + return + r.min_coord(0) >= c.x() - size && + r.max_coord(0) <= c.x() + size && + r.min_coord(1) >= c.y() - size && + r.max_coord(1) <= c.y() + size; + } + Point_d c; + FT size; +}; + /** \internal \brief data structure used to find any point (including projections) in V near to a query point from U * (which can be a projection). * @@ -51,9 +75,7 @@ namespace persistence_diagram { class Neighbors_finder { typedef CGAL::Dimension_tag<2> D; typedef CGAL::Search_traits<double, Internal_point, const double*, Construct_coord_iterator, D> Traits; - typedef CGAL::Weighted_Minkowski_distance<Traits> Distance; - typedef CGAL::Orthogonal_k_neighbor_search<Traits, Distance> K_neighbor_search; - typedef K_neighbor_search::Tree Kd_tree; + typedef CGAL::Kd_tree<Traits> Kd_tree; public: /** \internal \brief Constructor taking the near distance definition as parameter. */ @@ -123,15 +145,13 @@ inline int Neighbors_finder::pull_near(int u_point_index) { } else { // Is the query point near to a V point in the plane ? Internal_point u_point = g.get_u_point(u_point_index); - std::array<double, 2> w = { - {1., 1.} - }; - K_neighbor_search search(kd_t, u_point, 1, 0., true, Distance(0, 2, w.begin(), w.end())); - auto it = search.begin(); - if (it == search.end() || g.distance(u_point_index, it->first.point_index) > r) + auto neighbor = kd_t.search_any_point(Square_query{u_point, r}); + if(!neighbor) return null_point_index(); - tmp = it->first.point_index; - kd_t.remove(g.get_v_point(tmp)); + tmp = neighbor->point_index; + auto point = g.get_v_point(tmp); + int idx = point.point_index; + kd_t.remove(point, [idx](Internal_point const&p){return p.point_index == idx;}); } return tmp; } diff --git a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h index 44f4b827..622b0691 100644 --- a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h +++ b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h @@ -102,7 +102,7 @@ Persistence_graph::Persistence_graph(const Persistence_diagram1 &diag1, b_alive = std::numeric_limits<double>::infinity(); } else { for (auto it_u = u_alive.cbegin(), it_v = v_alive.cbegin(); it_u != u_alive.cend(); ++it_u, ++it_v) - b_alive = std::max(b_alive, std::fabs(*it_u - *it_v)); + b_alive = (std::max)(b_alive, std::fabs(*it_u - *it_v)); } } @@ -129,7 +129,7 @@ inline double Persistence_graph::distance(int u_point_index, int v_point_index) return 0.; Internal_point p_u = get_u_point(u_point_index); Internal_point p_v = get_v_point(v_point_index); - return std::max(std::fabs(p_u.x() - p_v.x()), std::fabs(p_u.y() - p_v.y())); + return (std::max)(std::fabs(p_u.x() - p_v.x()), std::fabs(p_u.y() - p_v.y())); } inline int Persistence_graph::size() const { @@ -175,9 +175,9 @@ inline Internal_point Persistence_graph::get_v_point(int v_point_index) const { inline double Persistence_graph::diameter_bound() const { double max = 0.; for (auto it = u.cbegin(); it != u.cend(); it++) - max = std::max(max, it->y()); + max = (std::max)(max, it->y()); for (auto it = v.cbegin(); it != v.cend(); it++) - max = std::max(max, it->y()); + max = (std::max)(max, it->y()); return max; } diff --git a/src/Bottleneck_distance/test/CMakeLists.txt b/src/Bottleneck_distance/test/CMakeLists.txt index 3d8e1f95..e1bbbbec 100644 --- a/src/Bottleneck_distance/test/CMakeLists.txt +++ b/src/Bottleneck_distance/test/CMakeLists.txt @@ -1,25 +1,15 @@ cmake_minimum_required(VERSION 2.6) project(Bottleneck_distance_tests) - -if (GCOVR_PATH) - # for gcovr to make coverage reports - Corbera Jenkins plugin - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") -endif() -if (GPROF_PATH) - # for gprof to make coverage reports - Jenkins - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") -endif() - if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) - add_executable ( bottleneckUT bottleneck_unit_test.cpp ) - target_link_libraries(bottleneckUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + include(GUDHI_test_coverage) + + add_executable ( Bottleneck_distance_test_unit bottleneck_unit_test.cpp ) + target_link_libraries(Bottleneck_distance_test_unit ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) if (TBB_FOUND) - target_link_libraries(bottleneckUT ${TBB_LIBRARIES}) + target_link_libraries(Bottleneck_distance_test_unit ${TBB_LIBRARIES}) endif(TBB_FOUND) - # Unitary tests - add_test(NAME bottleneckUT COMMAND ${CMAKE_CURRENT_BINARY_DIR}/bottleneckUT - # XML format for Jenkins xUnit plugin - --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/bottleneckUT.xml --log_level=test_suite --report_level=no) + gudhi_add_coverage_test(Bottleneck_distance_test_unit) + endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) diff --git a/src/Bottleneck_distance/test/README b/src/Bottleneck_distance/test/README index 0e7b8673..00bd9a91 100644 --- a/src/Bottleneck_distance/test/README +++ b/src/Bottleneck_distance/test/README @@ -7,6 +7,6 @@ make To launch with details: *********************** -./BottleneckUnitTest --report_level=detailed --log_level=all +./Bottleneck_distance_unit_test --report_level=detailed --log_level=all ==> echo $? returns 0 in case of success (non-zero otherwise) |