diff options
author | Arnur Nigmetov <nigmetov@tugraz.at> | 2020-03-06 18:29:25 +0100 |
---|---|---|
committer | Arnur Nigmetov <nigmetov@tugraz.at> | 2020-03-06 18:29:25 +0100 |
commit | 5ebf7142b00554b3f5d151c8b4e81b746962a5b8 (patch) | |
tree | fc5306ab414ef803e6bcbe13817e1c1d990b08b5 /matching/tests | |
parent | 3809e4071827a5959f27e472514eaed08ba6d15e (diff) |
Reorganize matching_dist code, minor fixes.
Diffstat (limited to 'matching/tests')
-rw-r--r-- | matching/tests/prism_1.bif | 28 | ||||
-rw-r--r-- | matching/tests/prism_2.bif | 29 | ||||
-rw-r--r-- | matching/tests/test_bifiltration.cpp | 36 | ||||
l--------- | matching/tests/test_bifiltration_1.txt | 1 | ||||
l--------- | matching/tests/test_bifiltration_full_triangle_rene.txt | 1 | ||||
-rw-r--r-- | matching/tests/test_common.cpp | 156 | ||||
-rw-r--r-- | matching/tests/test_list.txt | 1 | ||||
-rw-r--r-- | matching/tests/test_matching_distance.cpp | 167 | ||||
-rw-r--r-- | matching/tests/tests_main.cpp | 2 |
9 files changed, 421 insertions, 0 deletions
diff --git a/matching/tests/prism_1.bif b/matching/tests/prism_1.bif new file mode 100644 index 0000000..b37e807 --- /dev/null +++ b/matching/tests/prism_1.bif @@ -0,0 +1,28 @@ +bifiltration_phat_like +26 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +1 1 0 1 0 +1 1 0 2 1 +1 0 0 3 1 +1 0 1 5 4 +1 0 0 4 1 +1 0 0 3 0 +1 0 0 5 0 +1 0 0 4 2 +1 0 0 5 2 +1 0 1 4 3 +1 1 0 2 0 +1 0 1 5 3 +2 1 1 13 10 7 +2 1 1 9 14 13 +2 1 1 8 11 6 +2 1 1 15 10 8 +2 1 1 14 12 16 +2 1 1 17 12 11 +2 4 0 7 16 6 +2 0 4 9 17 15 diff --git a/matching/tests/prism_2.bif b/matching/tests/prism_2.bif new file mode 100644 index 0000000..49885e6 --- /dev/null +++ b/matching/tests/prism_2.bif @@ -0,0 +1,29 @@ +bifiltration_phat_like +27 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +1 0 0 2 1 +1 0 0 1 0 +1 0 0 5 3 +1 0 0 3 1 +1 0 0 5 4 +1 0 0 2 0 +1 0 0 4 1 +1 0 0 3 2 +1 0 0 5 2 +1 0 0 4 3 +1 0 0 4 2 +1 0 0 3 0 +2 0 0 16 12 6 +2 0 0 10 14 16 +2 0 0 9 17 7 +2 0 0 15 12 9 +2 0 0 13 17 11 +2 0 0 8 14 13 +2 4 0 6 11 7 +2 0 4 10 8 15 +2 3 3 15 16 13 diff --git a/matching/tests/test_bifiltration.cpp b/matching/tests/test_bifiltration.cpp new file mode 100644 index 0000000..742dab8 --- /dev/null +++ b/matching/tests/test_bifiltration.cpp @@ -0,0 +1,36 @@ +#include "catch/catch.hpp" + +#include <sstream> +#include <iostream> + +#include "common_util.h" +#include "box.h" +#include "bifiltration.h" + +using namespace md; + +//TEST_CASE("Small check", "[bifiltration][dim2]") +//{ +// Bifiltration bif("/home/narn/code/matching_distance/code/src/tests/test_bifiltration_full_triangle_phat_like.txt", BifiltrationFormat::phat_like); +// auto simplices = bif.simplices(); +// bif.sanity_check(); +// +// REQUIRE( simplices.size() == 7 ); +// +// REQUIRE( simplices[0].dim() == 0 ); +// REQUIRE( simplices[1].dim() == 0 ); +// REQUIRE( simplices[2].dim() == 0 ); +// REQUIRE( simplices[3].dim() == 1 ); +// REQUIRE( simplices[4].dim() == 1 ); +// REQUIRE( simplices[5].dim() == 1 ); +// REQUIRE( simplices[6].dim() == 2); +// +// REQUIRE( simplices[0].position() == Point(0, 0)); +// REQUIRE( simplices[1].position() == Point(0, 0)); +// REQUIRE( simplices[2].position() == Point(0, 0)); +// REQUIRE( simplices[3].position() == Point(3, 1)); +// REQUIRE( simplices[6].position() == Point(30, 40)); +// +// Line line_1(Line::pi / 2.0, 0.0); +// auto dgm = bif.slice_diagram(line_1); +//} diff --git a/matching/tests/test_bifiltration_1.txt b/matching/tests/test_bifiltration_1.txt new file mode 120000 index 0000000..ddd23e9 --- /dev/null +++ b/matching/tests/test_bifiltration_1.txt @@ -0,0 +1 @@ +../../data/test_bifiltration_1.txt
\ No newline at end of file diff --git a/matching/tests/test_bifiltration_full_triangle_rene.txt b/matching/tests/test_bifiltration_full_triangle_rene.txt new file mode 120000 index 0000000..47f49fd --- /dev/null +++ b/matching/tests/test_bifiltration_full_triangle_rene.txt @@ -0,0 +1 @@ +../../data/test_bifiltration_full_triangle_rene.txt
\ No newline at end of file diff --git a/matching/tests/test_common.cpp b/matching/tests/test_common.cpp new file mode 100644 index 0000000..9079a56 --- /dev/null +++ b/matching/tests/test_common.cpp @@ -0,0 +1,156 @@ +#include "catch/catch.hpp" + +#include <sstream> +#include <iostream> +#include <string> + +#include "common_util.h" +#include "simplex.h" +#include "matching_distance.h" + +//using namespace md; +using Real = double; +using Point = md::Point<Real>; +using Bifiltration = md::Bifiltration<Real>; +using BifiltrationProxy = md::BifiltrationProxy<Real>; +using CalculationParams = md::CalculationParams<Real>; +using CellWithValue = md::CellWithValue<Real>; +using DualPoint = md::DualPoint<Real>; +using DualBox = md::DualBox<Real>; +using Simplex = md::Simplex<Real>; +using AbstractSimplex = md::AbstractSimplex; +using BoundStrategy = md::BoundStrategy; +using TraverseStrategy = md::TraverseStrategy; +using AxisType = md::AxisType; +using AngleType = md::AngleType; +using ValuePoint = md::ValuePoint; +using Column = md::Column; + + +TEST_CASE("AbstractSimplex", "[abstract_simplex]") +{ + AbstractSimplex as; + REQUIRE(as.dim() == -1); + + as.push_back(1); + REQUIRE(as.dim() == 0); + REQUIRE(as.facets().size() == 0); + + as.push_back(0); + REQUIRE(as.dim() == 1); + REQUIRE(as.facets().size() == 2); + REQUIRE(as.facets()[0].dim() == 0); + REQUIRE(as.facets()[1].dim() == 0); + +} + +TEST_CASE("Vertical line", "[vertical_line]") +{ + // line x = 1 + DualPoint l_vertical(AxisType::x_type, AngleType::steep, 0, 1); + + REQUIRE(l_vertical.is_vertical()); + REQUIRE(l_vertical.is_steep()); + + Point p_1(0.5, 0.5); + Point p_2(1.5, 0.5); + Point p_3(1.5, 1.5); + Point p_4(0.5, 1.5); + Point p_5(1, 10); + + REQUIRE(l_vertical.x_from_y(10) == 1); + REQUIRE(l_vertical.x_from_y(-10) == 1); + REQUIRE(l_vertical.x_from_y(0) == 1); + + REQUIRE(not l_vertical.contains(p_1)); + REQUIRE(not l_vertical.contains(p_2)); + REQUIRE(not l_vertical.contains(p_3)); + REQUIRE(not l_vertical.contains(p_4)); + REQUIRE(l_vertical.contains(p_5)); + + REQUIRE(l_vertical.goes_below(p_1)); + REQUIRE(not l_vertical.goes_below(p_2)); + REQUIRE(not l_vertical.goes_below(p_3)); + REQUIRE(l_vertical.goes_below(p_4)); + + REQUIRE(not l_vertical.goes_above(p_1)); + REQUIRE(l_vertical.goes_above(p_2)); + REQUIRE(l_vertical.goes_above(p_3)); + REQUIRE(not l_vertical.goes_above(p_4)); + +} + +TEST_CASE("Horizontal line", "[horizontal_line]") +{ + // line y = 1 + DualPoint l_horizontal(AxisType::y_type, AngleType::flat, 0, 1); + + REQUIRE(l_horizontal.is_horizontal()); + REQUIRE(l_horizontal.is_flat()); + REQUIRE(l_horizontal.y_slope() == 0); + REQUIRE(l_horizontal.y_intercept() == 1); + + Point p_1(0.5, 0.5); + Point p_2(1.5, 0.5); + Point p_3(1.5, 1.5); + Point p_4(0.5, 1.5); + Point p_5(2, 1); + + REQUIRE((not l_horizontal.contains(p_1) and + not l_horizontal.contains(p_2) and + not l_horizontal.contains(p_3) and + not l_horizontal.contains(p_4) and + l_horizontal.contains(p_5))); + + REQUIRE(not l_horizontal.goes_below(p_1)); + REQUIRE(not l_horizontal.goes_below(p_2)); + REQUIRE(l_horizontal.goes_below(p_3)); + REQUIRE(l_horizontal.goes_below(p_4)); + REQUIRE(l_horizontal.goes_below(p_5)); + + REQUIRE(l_horizontal.goes_above(p_1)); + REQUIRE(l_horizontal.goes_above(p_2)); + REQUIRE(not l_horizontal.goes_above(p_3)); + REQUIRE(not l_horizontal.goes_above(p_4)); + REQUIRE(l_horizontal.goes_above(p_5)); +} + +TEST_CASE("Flat Line with positive slope", "[flat_line]") +{ + // line y = x / 2 + 1 + DualPoint l_flat(AxisType::y_type, AngleType::flat, 0.5, 1); + + REQUIRE(not l_flat.is_horizontal()); + REQUIRE(l_flat.is_flat()); + REQUIRE(l_flat.y_slope() == 0.5); + REQUIRE(l_flat.y_intercept() == 1); + + REQUIRE(l_flat.y_from_x(0) == 1); + REQUIRE(l_flat.y_from_x(1) == 1.5); + REQUIRE(l_flat.y_from_x(2) == 2); + + Point p_1(3, 2); + Point p_2(-2, 0.01); + Point p_3(0, 1.25); + Point p_4(6, 4.5); + Point p_5(2, 2); + + REQUIRE((not l_flat.contains(p_1) and + not l_flat.contains(p_2) and + not l_flat.contains(p_3) and + not l_flat.contains(p_4) and + l_flat.contains(p_5))); + + REQUIRE(not l_flat.goes_below(p_1)); + REQUIRE(l_flat.goes_below(p_2)); + REQUIRE(l_flat.goes_below(p_3)); + REQUIRE(l_flat.goes_below(p_4)); + REQUIRE(l_flat.goes_below(p_5)); + + REQUIRE(l_flat.goes_above(p_1)); + REQUIRE(not l_flat.goes_above(p_2)); + REQUIRE(not l_flat.goes_above(p_3)); + REQUIRE(not l_flat.goes_above(p_4)); + REQUIRE(l_flat.goes_above(p_5)); + +} diff --git a/matching/tests/test_list.txt b/matching/tests/test_list.txt new file mode 100644 index 0000000..1984606 --- /dev/null +++ b/matching/tests/test_list.txt @@ -0,0 +1 @@ +prism_lesnick_1.bif prism_lesnick_2.bif 1.0 diff --git a/matching/tests/test_matching_distance.cpp b/matching/tests/test_matching_distance.cpp new file mode 100644 index 0000000..82da530 --- /dev/null +++ b/matching/tests/test_matching_distance.cpp @@ -0,0 +1,167 @@ +#include "catch/catch.hpp" + +#include <sstream> +#include <iostream> +#include <string> + +#include "spdlog/spdlog.h" +#include "spdlog/fmt/ostr.h" + +#include "common_util.h" +#include "simplex.h" +#include "matching_distance.h" + +using Real = double; +using Point = md::Point<Real>; +using Bifiltration = md::Bifiltration<Real>; +using BifiltrationProxy = md::BifiltrationProxy<Real>; +using CalculationParams = md::CalculationParams<Real>; +using CellWithValue = md::CellWithValue<Real>; +using DualPoint = md::DualPoint<Real>; +using DualBox = md::DualBox<Real>; +using Simplex = md::Simplex<Real>; +using AbstractSimplex = md::AbstractSimplex; +using BoundStrategy = md::BoundStrategy; +using TraverseStrategy = md::TraverseStrategy; +using AxisType = md::AxisType; +using AngleType = md::AngleType; +using ValuePoint = md::ValuePoint; +using Column = md::Column; + +using md::k_corner_vps; + +namespace spd = spdlog; + +TEST_CASE("Different bounds", "[bounds]") +{ + std::vector<Simplex> simplices; + std::vector<Point> points; + + Real max_x = 10; + Real max_y = 20; + + int simplex_id = 0; + for(int i = 0; i <= max_x; ++i) { + for(int j = 0; j <= max_y; ++j) { + Point p(i, j); + simplices.emplace_back(simplex_id++, p, 0, Column()); + points.push_back(p); + } + } + + Bifiltration bif_a(simplices.begin(), simplices.end()); + Bifiltration bif_b(simplices.begin(), simplices.end()); + + CalculationParams params; + params.initialization_depth = 2; + + BifiltrationProxy bifp_a(bif_a, params.dim); + BifiltrationProxy bifp_b(bif_b, params.dim); + + md::DistanceCalculator<Real, BifiltrationProxy> calc(bifp_a, bifp_b, params); + +// REQUIRE(calc.max_x_ == Approx(max_x)); +// REQUIRE(calc.max_y_ == Approx(max_y)); + + std::vector<DualBox> boxes; + + for(CellWithValue c : calc.get_refined_grid(5, false, false)) { + boxes.push_back(c.dual_box()); + } + + // fill in boxes and points + + for(DualBox db : boxes) { + Real local_bound = calc.get_local_dual_bound(db); + Real local_bound_refined = calc.get_local_refined_bound(db); + REQUIRE(local_bound >= local_bound_refined); + for(Point p : points) { + for(ValuePoint vp_a : k_corner_vps) { + CellWithValue dual_cell(db, 1); + DualPoint corner_a = dual_cell.value_point(vp_a); + Real wp_a = corner_a.weighted_push(p); + dual_cell.set_value_at(vp_a, wp_a); + Real point_bound = calc.get_max_displacement_single_point(dual_cell, vp_a, p); + for(ValuePoint vp_b : k_corner_vps) { + if (vp_b <= vp_a) + continue; + DualPoint corner_b = dual_cell.value_point(vp_b); + Real wp_b = corner_b.weighted_push(p); + Real diff = fabs(wp_a - wp_b); + if (not(point_bound <= Approx(local_bound_refined))) { + std::cerr << "ERROR point: " << p << ", box = " << db << ", point bound = " << point_bound + << ", refined local = " << local_bound_refined << std::endl; + spd::set_level(spd::level::debug); + calc.get_max_displacement_single_point(dual_cell, vp_a, p); + calc.get_local_refined_bound(db); + spd::set_level(spd::level::info); + } + + REQUIRE(point_bound <= Approx(local_bound_refined)); + REQUIRE(diff <= Approx(point_bound)); + REQUIRE(diff <= Approx(local_bound_refined)); + } + + for(DualPoint l_random : db.random_points(100)) { + Real wp_random = l_random.weighted_push(p); + Real diff = fabs(wp_a - wp_random); + if (not(diff <= Approx(point_bound))) { + if (db.critical_points(p).size() > 4) { + std::cerr << "ERROR interesting case" << std::endl; + } else { + std::cerr << "ERROR boring case" << std::endl; + } + spd::set_level(spd::level::debug); + l_random.weighted_push(p); + spd::set_level(spd::level::info); + std::cerr << "ERROR point: " << p << ", box = " << db << ", point bound = " << point_bound + << ", refined local = " << local_bound_refined; + std::cerr << ", random_dual_point = " << l_random << ", wp_random = " << wp_random + << ", diff = " << diff << std::endl; + } + REQUIRE(diff <= Approx(point_bound)); + } + } + } + } +} + +TEST_CASE("Bifiltrations from file", "[matching_distance][small_example][lesnick]") +{ + std::string fname_a, fname_b; + + fname_a = "../src/tests/prism_1.bif"; + fname_b = "../src/tests/prism_2.bif"; + + Bifiltration bif_a(fname_a); + Bifiltration bif_b(fname_b); + + CalculationParams params; + + std::vector<BoundStrategy> bound_strategies {BoundStrategy::local_combined, + BoundStrategy::local_dual_bound_refined}; + + std::vector<TraverseStrategy> traverse_strategies {TraverseStrategy::breadth_first, TraverseStrategy::depth_first}; + + std::vector<double> scaling_factors {10, 1.0}; + + for(auto bs : bound_strategies) { + for(auto ts : traverse_strategies) { + for(double lambda : scaling_factors) { + Bifiltration bif_a_copy(bif_a); + Bifiltration bif_b_copy(bif_b); + bif_a_copy.scale(lambda); + bif_b_copy.scale(lambda); + params.bound_strategy = bs; + params.traverse_strategy = ts; + params.max_depth = 7; + params.delta = 0.1; + params.dim = 1; + Real answer = matching_distance(bif_a_copy, bif_b_copy, params); + Real correct_answer = lambda * 1.0; + REQUIRE(fabs(answer - correct_answer) / correct_answer < params.delta); + } + } + } +} + diff --git a/matching/tests/tests_main.cpp b/matching/tests/tests_main.cpp new file mode 100644 index 0000000..1c77b13 --- /dev/null +++ b/matching/tests/tests_main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch/catch.hpp" |