From a9d06f12ecbaa055d17970e09827ea7b67d1f53c Mon Sep 17 00:00:00 2001 From: Arnur Nigmetov Date: Sun, 3 Jun 2018 22:39:49 +0200 Subject: First tests added Preparation for longest edge computation. --- geom_bottleneck/tests/test_hera_bottleneck.cpp | 446 +++++++++++++++++++++++++ geom_bottleneck/tests/tests_main.cpp | 3 + 2 files changed, 449 insertions(+) create mode 100644 geom_bottleneck/tests/test_hera_bottleneck.cpp create mode 100644 geom_bottleneck/tests/tests_main.cpp (limited to 'geom_bottleneck/tests') diff --git a/geom_bottleneck/tests/test_hera_bottleneck.cpp b/geom_bottleneck/tests/test_hera_bottleneck.cpp new file mode 100644 index 0000000..f3b160b --- /dev/null +++ b/geom_bottleneck/tests/test_hera_bottleneck.cpp @@ -0,0 +1,446 @@ +#include "catch/catch.hpp" + +#include +#include + +#include "bottleneck.h" + +using PairVector = std::vector>; + +std::vector split_on_delim(const std::string& s, char delim) +{ + std::stringstream ss(s); + std::string token; + std::vector tokens; + while(std::getline(ss, token, delim)) { + tokens.push_back(token); + } + return tokens; +} + + +// single row in a file with test cases +struct TestFromFileCase { + + std::string file_1; + std::string file_2; + double q; + double internal_p; + double answer; + + TestFromFileCase(std::string s) + { + auto tokens = split_on_delim(s, ' '); + assert(tokens.size() == 5); + + file_1 = tokens.at(0); + file_2 = tokens.at(1); + q = std::stod(tokens.at(2)); + internal_p = std::stod(tokens.at(3)); + answer = std::stod(tokens.at(4)); + + if ( q < 1.0 or std::isinf(q) or + (internal_p != hera::get_infinity() and internal_p < 1.0)) { + throw std::runtime_error("Bad line in test_list.txt"); + } + } +}; + +std::ostream& operator<<(std::ostream& out, const TestFromFileCase& s) +{ + out << "[" << s.file_1 << ", " << s.file_2 << ", q = " << s.q << ", norm = "; + if (s.internal_p != hera::get_infinity()) { + out << s.internal_p; + } else { + out << "infinity"; + } + out << ", answer = " << s.answer << "]"; + return out; +} + + +TEST_CASE("simple cases", "bottleneckDistApprox") +{ + PairVector diagram_A, diagram_B; + double delta = 0.01; + //double internal_p = hera::get_infinity(); + + SECTION("trivial: two empty diagrams") { + REQUIRE( 0.0 == hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta)); + } + + SECTION("trivial: one empty diagram, one single-point diagram") { + + diagram_A.emplace_back(1.0, 2.0); + + double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + REQUIRE( fabs(d1 - 0.5) <= 0.00000000001 ); + + double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta); + REQUIRE( fabs(d2 - 0.5) <= 0.00000000001 ); + } + + SECTION("trivial: two single-point diagrams-1") { + + diagram_A.emplace_back(10.0, 20.0); // (5, 5) + diagram_B.emplace_back(13.0, 19.0); // (3, 3) + + double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta); + double correct_answer = 3.0; + REQUIRE( fabs(d1 - correct_answer) <= delta * correct_answer); + REQUIRE( fabs(d2 - correct_answer) <= delta * correct_answer); + } + + SECTION("trivial: two single-point diagrams-2") { + + diagram_A.emplace_back(10.0, 20.0); // (5, 5) + diagram_B.emplace_back(130.0, 138.0); // (4, 4) + + double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta); + double correct_answer = 5.0; + REQUIRE( fabs(d1 - correct_answer) <= delta * correct_answer ); + REQUIRE( fabs(d2 - correct_answer) <= delta * correct_answer ); + + } + +} + + +TEST_CASE("infinity points", "bottleneckDistApprox") +{ + PairVector diagram_A, diagram_B; + double delta = 0.01; + + // do not use Hera's infinity! it is -1 + double inf = std::numeric_limits::infinity(); + + SECTION("two points at infinity, no finite points") { + + // edge cost 1.0 + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + double d = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double corr_answer = 1.0; + REQUIRE( fabs(d - corr_answer) <= delta * corr_answer); + } + + SECTION("two points at infinity") { + + // edge cost 3.0 + diagram_A.emplace_back(10.0, 20.0); // (5, 5) + diagram_B.emplace_back(13.0, 19.0); // (3, 3) + + // edge cost 1.0 + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + double d = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double corr_answer = 3.0; + REQUIRE( fabs(d - corr_answer) <= delta * corr_answer); + } + + SECTION("three points at infinity, no finite points") { + + // edge cost 1.0 + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + diagram_B.emplace_back(2.0, inf); + + double d = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double corr_answer = inf; + REQUIRE( d == corr_answer ); + } + + SECTION("three points at infinity") { + + // edge cost 3.0 + diagram_A.emplace_back(10.0, 20.0); // (5, 5) + diagram_B.emplace_back(13.0, 19.0); // (3, 3) + + // edge cost 1.0 + diagram_A.emplace_back(1.0, inf); + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + double d = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double corr_answer = inf; + REQUIRE( d == corr_answer ); + } + + + SECTION("all four corners at infinity, no finite points, finite answer") { + + // edge cost 1.0 + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + // edge cost 1.0 + diagram_A.emplace_back(1.0, -inf); + diagram_B.emplace_back(2.0, -inf); + + // edge cost 1.0 + diagram_A.emplace_back(inf, 1.0); + diagram_B.emplace_back(inf, 2.0); + + // edge cost 1.0 + diagram_A.emplace_back(-inf, 1.0); + diagram_B.emplace_back(-inf, 2.0); + + double d = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double corr_answer = 1.0; + + REQUIRE( d == corr_answer ); + } + + SECTION("all four corners at infinity, no finite points, infinite answer-1") { + + // edge cost 1.0 + diagram_A.emplace_back(1.0, inf); + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + // edge cost 1.0 + diagram_A.emplace_back(1.0, -inf); + diagram_B.emplace_back(2.0, -inf); + + // edge cost 1.0 + diagram_A.emplace_back(inf, 1.0); + diagram_B.emplace_back(inf, 2.0); + + // edge cost 1.0 + diagram_A.emplace_back(-inf, 1.0); + diagram_B.emplace_back(-inf, 2.0); + + double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta); + double corr_answer = inf; + + REQUIRE( d1 == corr_answer ); + REQUIRE( d2 == corr_answer ); + } + + SECTION("all four corners at infinity, no finite points, infinite answer-2") { + + // edge cost 1.0 + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + // edge cost 1.0 + diagram_A.emplace_back(1.0, -inf); + diagram_B.emplace_back(2.0, -inf); + diagram_B.emplace_back(2.0, -inf); + + // edge cost 1.0 + diagram_A.emplace_back(inf, 1.0); + diagram_B.emplace_back(inf, 2.0); + + // edge cost 1.0 + diagram_A.emplace_back(-inf, 1.0); + diagram_B.emplace_back(-inf, 2.0); + + double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta); + double corr_answer = inf; + + REQUIRE( d1 == corr_answer ); + REQUIRE( d2 == corr_answer ); + } + + SECTION("all four corners at infinity, no finite points, infinite answer-3") { + + // edge cost 1.0 + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + // edge cost 1.0 + diagram_A.emplace_back(1.0, -inf); + diagram_B.emplace_back(2.0, -inf); + + // edge cost 1.0 + diagram_A.emplace_back(inf, 1.0); + diagram_A.emplace_back(inf, 1.0); + diagram_B.emplace_back(inf, 2.0); + + // edge cost 1.0 + diagram_A.emplace_back(-inf, 1.0); + diagram_B.emplace_back(-inf, 2.0); + + double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta); + double corr_answer = inf; + + REQUIRE( d1 == corr_answer ); + REQUIRE( d2 == corr_answer ); + } + + SECTION("all four corners at infinity, no finite points, infinite answer-4") { + + // edge cost 1.0 + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + // edge cost 1.0 + diagram_A.emplace_back(1.0, -inf); + diagram_B.emplace_back(2.0, -inf); + + // edge cost 1.0 + diagram_A.emplace_back(inf, 1.0); + diagram_B.emplace_back(inf, 2.0); + + // edge cost 1.0 + diagram_A.emplace_back(-inf, 1.0); + diagram_B.emplace_back(-inf, 2.0); + diagram_B.emplace_back(-inf, 2.0); + + double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta); + double corr_answer = inf; + + REQUIRE( d1 == corr_answer ); + REQUIRE( d2 == corr_answer ); + } + + SECTION("all four corners at infinity, with finite points, infinite answer-1") { + + diagram_A.emplace_back(1.0, inf); + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + diagram_A.emplace_back(1.0, -inf); + diagram_B.emplace_back(2.0, -inf); + + diagram_A.emplace_back(inf, 1.0); + diagram_B.emplace_back(inf, 2.0); + + diagram_A.emplace_back(-inf, 1.0); + diagram_B.emplace_back(-inf, 2.0); + + // finite edge + diagram_A.emplace_back(10.0, 20.0); + diagram_B.emplace_back(13.0, 19.0); + + double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta); + double corr_answer = inf; + + REQUIRE( d1 == corr_answer ); + REQUIRE( d2 == corr_answer ); + } + + SECTION("all four corners at infinity, with finite points, infinite answer-2") { + + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + diagram_A.emplace_back(1.0, -inf); + diagram_B.emplace_back(2.0, -inf); + diagram_B.emplace_back(2.0, -inf); + + diagram_A.emplace_back(inf, 1.0); + diagram_B.emplace_back(inf, 2.0); + + diagram_A.emplace_back(-inf, 1.0); + diagram_B.emplace_back(-inf, 2.0); + + // finite edge + diagram_A.emplace_back(10.0, 20.0); + diagram_B.emplace_back(13.0, 19.0); + + double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta); + double corr_answer = inf; + + REQUIRE( d1 == corr_answer ); + REQUIRE( d2 == corr_answer ); + } + + SECTION("all four corners at infinity, with finite points, infinite answer-3") { + + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + diagram_A.emplace_back(1.0, -inf); + diagram_B.emplace_back(2.0, -inf); + + diagram_A.emplace_back(inf, 1.0); + diagram_A.emplace_back(inf, 1.0); + diagram_B.emplace_back(inf, 2.0); + + diagram_A.emplace_back(-inf, 1.0); + diagram_B.emplace_back(-inf, 2.0); + + // finite edge + diagram_A.emplace_back(10.0, 20.0); + diagram_B.emplace_back(13.0, 19.0); + + double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta); + double corr_answer = inf; + + REQUIRE( d1 == corr_answer ); + REQUIRE( d2 == corr_answer ); + } + + SECTION("all four corners at infinity, no finite points, infinite answer-4") { + + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + diagram_A.emplace_back(1.0, -inf); + diagram_B.emplace_back(2.0, -inf); + + diagram_A.emplace_back(inf, 1.0); + diagram_B.emplace_back(inf, 2.0); + + diagram_A.emplace_back(-inf, 1.0); + diagram_B.emplace_back(-inf, 2.0); + diagram_B.emplace_back(-inf, 2.0); + + // finite edge + diagram_A.emplace_back(10.0, 20.0); + diagram_B.emplace_back(13.0, 19.0); + + double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta); + double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta); + double corr_answer = inf; + + REQUIRE( d1 == corr_answer ); + REQUIRE( d2 == corr_answer ); + } + + + SECTION("simple small example with finite answer") { + diagram_A.emplace_back(1.0, inf); + diagram_B.emplace_back(2.0, inf); + + diagram_A.emplace_back(1.9, inf); + diagram_B.emplace_back(1.1, inf); + + // 1.1 - 1.0 + 2.0 - 1.9 = 0.2 + + diagram_A.emplace_back(inf, 1.0); + diagram_B.emplace_back(inf, 2.0); + + diagram_A.emplace_back(inf, 1.9); + diagram_B.emplace_back(inf, 1.1); + + + // finite edge + diagram_A.emplace_back(10.0, 20.0); + diagram_B.emplace_back(13.0, 19.0); + + double d1 = hera::bottleneckDistExact<>(diagram_A, diagram_B); + double d2 = hera::bottleneckDistExact<>(diagram_B, diagram_A); + double corr_answer = 3.0; + + REQUIRE( d1 == corr_answer ); + REQUIRE( d2 == corr_answer ); + + + } + +} + diff --git a/geom_bottleneck/tests/tests_main.cpp b/geom_bottleneck/tests/tests_main.cpp new file mode 100644 index 0000000..d24407e --- /dev/null +++ b/geom_bottleneck/tests/tests_main.cpp @@ -0,0 +1,3 @@ +#define LOG_AUCTION +#define CATCH_CONFIG_MAIN +#include "catch/catch.hpp" -- cgit v1.2.3