diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/multi_filtrations/finitely_critical_filtrations.h b/src/Simplex_tree/include/gudhi/Simplex_tree/multi_filtrations/finitely_critical_filtrations.h index a75c45c641..188fde79a1 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/multi_filtrations/finitely_critical_filtrations.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/multi_filtrations/finitely_critical_filtrations.h @@ -96,6 +96,16 @@ class Finitely_critical_multi_filtration : public std::vector { return result; } + // template + friend bool operator==(Finitely_critical_multi_filtration &self, const Finitely_critical_multi_filtration &to_compare){ + if (self.size() != to_compare.size()) return false; + auto it = to_compare.begin(); + for (auto i = 0u; i> to_python(const std::vector>& to_convert){ return std::vector>(to_convert.begin(), to_convert.end()); } @@ -131,7 +141,8 @@ class Finitely_critical_multi_filtration : public std::vector { // easy debug friend std::ostream& operator<<(std::ostream& stream, const Finitely_critical_multi_filtration& truc){ - stream << "["; + if (truc.empty()) {stream << "[]"; return stream;} + stream << "["; for(unsigned int i = 0; i < truc.size()-1; i++){ stream << truc[i] << ", "; } diff --git a/src/Simplex_tree/test/CMakeLists.txt b/src/Simplex_tree/test/CMakeLists.txt index e4535e1b7e..a6bc2f44c0 100644 --- a/src/Simplex_tree/test/CMakeLists.txt +++ b/src/Simplex_tree/test/CMakeLists.txt @@ -11,6 +11,12 @@ if(TARGET TBB::tbb) endif() gudhi_add_boost_test(Simplex_tree_test_unit) +add_executable ( Simplex_tree_multi_test_unit simplex_tree_multi_unit_test.cpp ) +if(TARGET TBB::tbb) + target_link_libraries(Simplex_tree_multi_test_unit TBB::tbb) +endif() +gudhi_add_boost_test(Simplex_tree_multi_test_unit) + add_executable ( Simplex_tree_remove_test_unit simplex_tree_remove_unit_test.cpp ) if(TARGET TBB::tbb) target_link_libraries(Simplex_tree_remove_test_unit TBB::tbb) diff --git a/src/Simplex_tree/test/simplex_tree_multi_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_multi_unit_test.cpp new file mode 100644 index 0000000000..b094908246 --- /dev/null +++ b/src/Simplex_tree/test/simplex_tree_multi_unit_test.cpp @@ -0,0 +1,686 @@ +/* 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): Vincent Rouvreau + * + * Copyright (C) 2014 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include +#include +#include +#include +#include // std::pair, std::make_pair +#include // float comparison +#include +#include // greater +#include // std::tie +#include // for std::distance +#include // for std::size_t + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "simplex_tree" +#include +#include + +// ^ +// /!\ Nothing else from Simplex_tree shall be included to test includes are well defined. +#include "gudhi/Simplex_tree/Simplex_tree_multi.h" +#include "gudhi/Simplex_tree/multi_filtrations/finitely_critical_filtrations.h" + +using namespace Gudhi; +using namespace Gudhi::multiparameter; +using Gudhi::multiparameter::multi_filtrations::Finitely_critical_multi_filtration; +using vec=Finitely_critical_multi_filtration; + +typedef boost::mpl::list> list_of_tested_variants; + +template +void test_empty_simplex_tree(typeST& tst) { + typedef typename typeST::Vertex_handle Vertex_handle; + const Vertex_handle DEFAULT_VERTEX_VALUE = Vertex_handle(- 1); + BOOST_CHECK(tst.null_vertex() == DEFAULT_VERTEX_VALUE); + BOOST_CHECK(tst.num_vertices() == (size_t) 0); + BOOST_CHECK(tst.num_simplices() == (size_t) 0); + BOOST_CHECK(tst.is_empty()); + BOOST_CHECK(tst.num_simplices_by_dimension() == std::vector()); + typename typeST::Siblings* STRoot = tst.root(); + BOOST_CHECK(STRoot != nullptr); + BOOST_CHECK(STRoot->oncles() == nullptr); + BOOST_CHECK(STRoot->parent() == DEFAULT_VERTEX_VALUE); + BOOST_CHECK(tst.dimension() == -1); +} + +template +void test_iterators_on_empty_simplex_tree(typeST& tst) { + std::clog << "Iterator on vertices: " << std::endl; + for (auto vertex : tst.complex_vertex_range()) { + std::clog << "vertice:" << vertex << std::endl; + BOOST_CHECK(false); // shall be empty + } + std::clog << "Iterator on simplices: " << std::endl; + for (auto simplex : tst.complex_simplex_range()) { + BOOST_CHECK(simplex != simplex); // shall be empty - to remove warning of non-used simplex + } + + std::clog + << "Iterator on Simplices in the filtration, with [filtration value]:" + << std::endl; + for (auto f_simplex : tst.filtration_simplex_range()) { + BOOST_CHECK(false); // shall be empty + std::clog << "test_iterators_on_empty_simplex_tree - filtration=" + << tst.filtration(f_simplex) << std::endl; + } +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_when_empty, typeST, list_of_tested_variants) { + typedef std::pair typePairSimplexBool; + typedef std::vector typeVectorVertex; + + std::clog << "********************************************************************" << std::endl; + std::clog << "TEST OF DEFAULT CONSTRUCTOR" << std::endl; + typeST st; + + test_empty_simplex_tree(st); + + test_iterators_on_empty_simplex_tree(st); + // TEST OF EMPTY INSERTION + std::clog << "TEST OF EMPTY INSERTION" << std::endl; + typeVectorVertex simplexVectorEmpty; + BOOST_CHECK(simplexVectorEmpty.empty() == true); + typePairSimplexBool returnEmptyValue = st.insert_simplex(simplexVectorEmpty, 0.0); + BOOST_CHECK(returnEmptyValue.first == typeST::null_simplex()); + BOOST_CHECK(returnEmptyValue.second == true); + + test_empty_simplex_tree(st); + + test_iterators_on_empty_simplex_tree(st); +} + +bool AreAlmostTheSame(float a, float b) { + return std::fabs(a - b) < std::numeric_limits::epsilon(); +} +bool AreAlmostTheSame(Finitely_critical_multi_filtration a, Finitely_critical_multi_filtration b) { + assert(a.size() == b.size()); + for (auto i=0u; i std::numeric_limits::epsilon()) + return false; + return true; +} + + +template +void test_simplex_tree_contains(typeST& simplexTree, typeSimplex& simplex, int pos) { + auto f_simplex = simplexTree.filtration_simplex_range().begin() + pos; + + std::clog << "test_simplex_tree_contains - filtration=" << simplexTree.filtration(*f_simplex) << "||" << simplex.second << std::endl; + BOOST_CHECK(AreAlmostTheSame(simplexTree.filtration(*f_simplex), simplex.second)); + + int simplexIndex = simplex.first.size() - 1; + std::sort(simplex.first.begin(), simplex.first.end()); // if the simplex wasn't sorted, the next test could fail + for (auto vertex : simplexTree.simplex_vertex_range(*f_simplex)) { + std::clog << "test_simplex_tree_contains - vertex=" << vertex << "||" << simplex.first.at(simplexIndex) << std::endl; + BOOST_CHECK(vertex == simplex.first.at(simplexIndex)); + BOOST_CHECK(simplexIndex >= 0); + simplexIndex--; + } +} + +template +void test_simplex_tree_insert_returns_true(const typePairSimplexBool& returnValue) { + BOOST_CHECK(returnValue.second == true); + // Simplex_handle = boost::container::flat_map< typeST::Vertex_handle, Node >::iterator + typename typeST::Simplex_handle shReturned = returnValue.first; + BOOST_CHECK(shReturned != typeST::null_simplex()); +} + +// Global variables +int dim_max = -1; + +template +void set_and_test_simplex_tree_dim_fil(typeST& simplexTree, int vectorSize, const Filtration_value& fil) { + if (vectorSize > dim_max + 1) { + dim_max = vectorSize - 1; + simplexTree.set_dimension(dim_max); + std::clog << " set_and_test_simplex_tree_dim_fil - dim_max=" << dim_max + << std::endl; + } + + BOOST_CHECK(simplexTree.dimension() == dim_max); + + // Another way to count simplices: + size_t num_simp = 0; + for (auto f_simplex : simplexTree.complex_simplex_range()) { + // Remove warning + (void) f_simplex; + num_simp++; + } + + BOOST_CHECK(simplexTree.num_simplices() == num_simp); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_insertion, typeST, list_of_tested_variants) { + typedef typename typeST::Filtration_value Filtration_value; + typedef std::pair typePairSimplexBool; + typedef std::vector typeVectorVertex; + typedef std::pair typeSimplex; + const Filtration_value FIRST_FILTRATION_VALUE = {0.1,0.15}; + const Filtration_value SECOND_FILTRATION_VALUE = {0.2, 0.25}; + const Filtration_value THIRD_FILTRATION_VALUE = {0.3, 0.35}; + const Filtration_value FOURTH_FILTRATION_VALUE = {0.4, 0.45}; + // reset since we run the test several times + dim_max = -1; + + // TEST OF INSERTION + std::clog << "********************************************************************" << std::endl; + std::clog << "TEST OF INSERTION" << std::endl; + typeST st; + + // ++ FIRST + std::clog << " - INSERT 0" << std::endl; + typeVectorVertex firstSimplexVector{0}; + BOOST_CHECK(firstSimplexVector.size() == 1); + typeSimplex firstSimplex = std::make_pair(firstSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); + typePairSimplexBool returnValue = st.insert_simplex(firstSimplex.first, firstSimplex.second); + + test_simplex_tree_insert_returns_true(returnValue); + set_and_test_simplex_tree_dim_fil(st, firstSimplexVector.size(), firstSimplex.second); + BOOST_CHECK(st.num_vertices() == (size_t) 1); + + // ++ SECOND + std::clog << " - INSERT 1" << std::endl; + typeVectorVertex secondSimplexVector{1}; + BOOST_CHECK(secondSimplexVector.size() == 1); + typeSimplex secondSimplex = std::make_pair(secondSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); + returnValue = st.insert_simplex(secondSimplex.first, secondSimplex.second); + + test_simplex_tree_insert_returns_true(returnValue); + set_and_test_simplex_tree_dim_fil(st, secondSimplexVector.size(), secondSimplex.second); + BOOST_CHECK(st.num_vertices() == (size_t) 2); + + // ++ THIRD + std::clog << " - INSERT (0,1)" << std::endl; + typeVectorVertex thirdSimplexVector{0, 1}; + BOOST_CHECK(thirdSimplexVector.size() == 2); + typeSimplex thirdSimplex = std::make_pair(thirdSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); + returnValue = st.insert_simplex(thirdSimplex.first, thirdSimplex.second); + + test_simplex_tree_insert_returns_true(returnValue); + set_and_test_simplex_tree_dim_fil(st, thirdSimplexVector.size(), thirdSimplex.second); + BOOST_CHECK(st.num_vertices() == (size_t) 2); // Not incremented !! + + // ++ FOURTH + std::clog << " - INSERT 2" << std::endl; + typeVectorVertex fourthSimplexVector{2}; + BOOST_CHECK(fourthSimplexVector.size() == 1); + typeSimplex fourthSimplex = std::make_pair(fourthSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); + returnValue = st.insert_simplex(fourthSimplex.first, fourthSimplex.second); + + test_simplex_tree_insert_returns_true(returnValue); + set_and_test_simplex_tree_dim_fil(st, fourthSimplexVector.size(), fourthSimplex.second); + BOOST_CHECK(st.num_vertices() == (size_t) 3); + + // ++ FIFTH + std::clog << " - INSERT (2,0)" << std::endl; + typeVectorVertex fifthSimplexVector{2, 0}; + BOOST_CHECK(fifthSimplexVector.size() == 2); + typeSimplex fifthSimplex = std::make_pair(fifthSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); + returnValue = st.insert_simplex(fifthSimplex.first, fifthSimplex.second); + + test_simplex_tree_insert_returns_true(returnValue); + set_and_test_simplex_tree_dim_fil(st, fifthSimplexVector.size(), fifthSimplex.second); + BOOST_CHECK(st.num_vertices() == (size_t) 3); // Not incremented !! + + // ++ SIXTH + std::clog << " - INSERT (2,1)" << std::endl; + typeVectorVertex sixthSimplexVector{2, 1}; + BOOST_CHECK(sixthSimplexVector.size() == 2); + typeSimplex sixthSimplex = std::make_pair(sixthSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); + returnValue = st.insert_simplex(sixthSimplex.first, sixthSimplex.second); + + test_simplex_tree_insert_returns_true(returnValue); + set_and_test_simplex_tree_dim_fil(st, sixthSimplexVector.size(), sixthSimplex.second); + BOOST_CHECK(st.num_vertices() == (size_t) 3); // Not incremented !! + + // ++ SEVENTH + std::clog << " - INSERT (2,1,0)" << std::endl; + typeVectorVertex seventhSimplexVector{2, 1, 0}; + BOOST_CHECK(seventhSimplexVector.size() == 3); + typeSimplex seventhSimplex = std::make_pair(seventhSimplexVector, Filtration_value(THIRD_FILTRATION_VALUE)); + returnValue = st.insert_simplex(seventhSimplex.first, seventhSimplex.second); + + test_simplex_tree_insert_returns_true(returnValue); + set_and_test_simplex_tree_dim_fil(st, seventhSimplexVector.size(), seventhSimplex.second); + BOOST_CHECK(st.num_vertices() == (size_t) 3); // Not incremented !! + + // ++ EIGHTH + std::clog << " - INSERT 3" << std::endl; + typeVectorVertex eighthSimplexVector{3}; + BOOST_CHECK(eighthSimplexVector.size() == 1); + typeSimplex eighthSimplex = std::make_pair(eighthSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); + returnValue = st.insert_simplex(eighthSimplex.first, eighthSimplex.second); + + test_simplex_tree_insert_returns_true(returnValue); + set_and_test_simplex_tree_dim_fil(st, eighthSimplexVector.size(), eighthSimplex.second); + BOOST_CHECK(st.num_vertices() == (size_t) 4); + + // ++ NINTH + std::clog << " - INSERT (3,0)" << std::endl; + typeVectorVertex ninethSimplexVector{3, 0}; + BOOST_CHECK(ninethSimplexVector.size() == 2); + typeSimplex ninethSimplex = std::make_pair(ninethSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); + returnValue = st.insert_simplex(ninethSimplex.first, ninethSimplex.second); + + test_simplex_tree_insert_returns_true(returnValue); + set_and_test_simplex_tree_dim_fil(st, ninethSimplexVector.size(), ninethSimplex.second); + BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented !! + + // ++ TENTH + std::clog << " - INSERT 0 (already inserted)" << std::endl; + typeVectorVertex tenthSimplexVector{0}; + BOOST_CHECK(tenthSimplexVector.size() == 1); + // With a different filtration value + typeSimplex tenthSimplex = std::make_pair(tenthSimplexVector, Filtration_value(FOURTH_FILTRATION_VALUE)); + returnValue = st.insert_simplex(tenthSimplex.first, tenthSimplex.second); + + BOOST_CHECK(returnValue.second == false); + // Simplex_handle = boost::container::flat_map< typeST::Vertex_handle, Node >::iterator + typename typeST::Simplex_handle shReturned = returnValue.first; + BOOST_CHECK(shReturned == typeST::null_simplex()); + std::clog << "st.num_vertices()=" << st.num_vertices() << std::endl; + BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented !! + BOOST_CHECK(st.dimension() == dim_max); + + // ++ ELEVENTH + std::clog << " - INSERT (2,1,0) (already inserted)" << std::endl; + typeVectorVertex eleventhSimplexVector{2, 1, 0}; + BOOST_CHECK(eleventhSimplexVector.size() == 3); + typeSimplex eleventhSimplex = std::make_pair(eleventhSimplexVector, Filtration_value(FOURTH_FILTRATION_VALUE)); + returnValue = st.insert_simplex(eleventhSimplex.first, eleventhSimplex.second); + + BOOST_CHECK(returnValue.second == false); + // Simplex_handle = boost::container::flat_map< typeST::Vertex_handle, Node >::iterator + shReturned = returnValue.first; + BOOST_CHECK(shReturned == typeST::null_simplex()); + BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented !! + BOOST_CHECK(st.dimension() == dim_max); + BOOST_CHECK(st.num_simplices_by_dimension() == std::vector({4, 4, 1})); + + /* Inserted simplex: */ + /* 1 */ + /* o */ + /* /X\ */ + /* o---o---o */ + /* 2 0 3 */ + + // [0.1] 0 + // [0.1] 1 + // [0.1] 2 + // [0.1] 3 + // [0.2] 1 0 + // [0.2] 2 0 + // [0.2] 2 1 + // [0.2] 3 0 + // [0.3] 2 1 0 + // !! Be careful, simplex are sorted by filtration value on insertion !! + std::clog << "simplex_tree_insertion - first - 0" << std::endl; + test_simplex_tree_contains(st, firstSimplex, 0); // (0) -> 0 + std::clog << "simplex_tree_insertion - second - 1" << std::endl; + test_simplex_tree_contains(st, secondSimplex, 1); // (1) -> 1 + std::clog << "simplex_tree_insertion - third - 4" << std::endl; + test_simplex_tree_contains(st, thirdSimplex, 4); // (0,1) -> 4 + std::clog << "simplex_tree_insertion - fourth - 2" << std::endl; + test_simplex_tree_contains(st, fourthSimplex, 2); // (2) -> 2 + std::clog << "simplex_tree_insertion - fifth - 5" << std::endl; + test_simplex_tree_contains(st, fifthSimplex, 5); // (2,0) -> 5 + std::clog << "simplex_tree_insertion - sixth - 6" << std::endl; + test_simplex_tree_contains(st, sixthSimplex, 6); //(2,1) -> 6 + std::clog << "simplex_tree_insertion - seventh - 8" << std::endl; + test_simplex_tree_contains(st, seventhSimplex, 8); // (2,1,0) -> 8 + std::clog << "simplex_tree_insertion - eighth - 3" << std::endl; + test_simplex_tree_contains(st, eighthSimplex, 3); // (3) -> 3 + std::clog << "simplex_tree_insertion - ninth - 7" << std::endl; + test_simplex_tree_contains(st, ninethSimplex, 7); // (3,0) -> 7 + + // Display the Simplex_tree - Can not be done in the middle of 2 inserts + std::clog << "The complex contains " << st.num_simplices() << " simplices" << std::endl; + std::clog << " - dimension " << st.dimension() << std::endl; + std::clog << std::endl << std::endl << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; + for (auto f_simplex : st.filtration_simplex_range()) { + std::clog << " " << "[" << st.filtration(f_simplex) << "] "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::clog << (int) vertex << " "; + } + std::clog << std::endl; + } + +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(NSimplexAndSubfaces_tree_insertion, typeST, list_of_tested_variants) { + typedef std::pair typePairSimplexBool; + typedef std::vector typeVectorVertex; + typedef std::pair typeSimplex; + std::clog << "********************************************************************" << std::endl; + std::clog << "TEST OF RECURSIVE INSERTION" << std::endl; + typeST st; + typePairSimplexBool returnValue; + int position = 0; + + // ++ FIRST + std::clog << " - INSERT (2,1,0)" << std::endl; + typeVectorVertex SimplexVector1{2, 1, 0}; + BOOST_CHECK(SimplexVector1.size() == 3); + returnValue = st.insert_simplex_and_subfaces(SimplexVector1); + + BOOST_CHECK(st.num_vertices() == (size_t) 3); // +3 (2, 1 and 0 are not existing) + + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector1.begin(), SimplexVector1.end(), std::greater()); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::clog << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector1[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector1[position]); + position++; + } + + // ++ SECOND + std::clog << " - INSERT 3" << std::endl; + typeVectorVertex SimplexVector2{3}; + BOOST_CHECK(SimplexVector2.size() == 1); + returnValue = st.insert_simplex_and_subfaces(SimplexVector2); + + BOOST_CHECK(st.num_vertices() == (size_t) 4); // +1 (3 is not existing) + + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector2.begin(), SimplexVector2.end(), std::greater()); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::clog << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector2[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector2[position]); + position++; + } + + // ++ THIRD + std::clog << " - INSERT (0,3)" << std::endl; + typeVectorVertex SimplexVector3{3, 0}; + BOOST_CHECK(SimplexVector3.size() == 2); + returnValue = st.insert_simplex_and_subfaces(SimplexVector3); + + BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented (all are existing) + + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector3.begin(), SimplexVector3.end(), std::greater()); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::clog << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector3[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector3[position]); + position++; + } + + // ++ FOURTH + std::clog << " - INSERT (1,0) (already inserted)" << std::endl; + typeVectorVertex SimplexVector4{1, 0}; + BOOST_CHECK(SimplexVector4.size() == 2); + returnValue = st.insert_simplex_and_subfaces(SimplexVector4); + + BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented (all are existing) + + // Check it was not inserted (already there from {2,1,0} insertion) + BOOST_CHECK(false == returnValue.second); + + // ++ FIFTH + std::clog << " - INSERT (3,4,5)" << std::endl; + typeVectorVertex SimplexVector5{3, 4, 5}; + BOOST_CHECK(SimplexVector5.size() == 3); + returnValue = st.insert_simplex_and_subfaces(SimplexVector5); + + BOOST_CHECK(st.num_vertices() == (size_t) 6); + + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector5.begin(), SimplexVector5.end(), std::greater()); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::clog << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector5[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector5[position]); + position++; + } + + // ++ SIXTH + std::clog << " - INSERT (0,1,6,7)" << std::endl; + typeVectorVertex SimplexVector6{0, 1, 6, 7}; + BOOST_CHECK(SimplexVector6.size() == 4); + returnValue = st.insert_simplex_and_subfaces(SimplexVector6); + + BOOST_CHECK(st.num_vertices() == (size_t) 8); // +2 (6 and 7 are not existing - 0 and 1 are already existing) + + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector6.begin(), SimplexVector6.end(), std::greater()); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::clog << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector6[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector6[position]); + position++; + } + + /* Inserted simplex: */ + /* 1 6 */ + /* o---o */ + /* /X\7/ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + /* */ + /* In other words: */ + /* A facet [2,1,0] */ + /* An edge [0,3] */ + /* A facet [3,4,5] */ + /* A cell [0,1,6,7] */ + + typeSimplex simplexPair1 = std::make_pair(SimplexVector1, 0.0); + typeSimplex simplexPair2 = std::make_pair(SimplexVector2, 0.0); + typeSimplex simplexPair3 = std::make_pair(SimplexVector3, 0.0); + typeSimplex simplexPair4 = std::make_pair(SimplexVector4, 0.0); + typeSimplex simplexPair5 = std::make_pair(SimplexVector5, 0.0); + typeSimplex simplexPair6 = std::make_pair(SimplexVector6, 0.0); + test_simplex_tree_contains(st, simplexPair1, 6); // (2,1,0) is in position 6 + test_simplex_tree_contains(st, simplexPair2, 7); // (3) is in position 7 + test_simplex_tree_contains(st, simplexPair3, 8); // (3,0) is in position 8 + test_simplex_tree_contains(st, simplexPair4, 2); // (1,0) is in position 2 + test_simplex_tree_contains(st, simplexPair5, 14); // (3,4,5) is in position 14 + test_simplex_tree_contains(st, simplexPair6, 26); // (7,6,1,0) is in position 26 + + // ------------------------------------------------------------------------------------------------------------------ + // Find in the simplex_tree + // ------------------------------------------------------------------------------------------------------------------ + typeVectorVertex simpleSimplexVector{1}; + typename typeST::Simplex_handle simplexFound = st.find(simpleSimplexVector); + std::clog << "**************IS THE SIMPLEX {1} IN THE SIMPLEX TREE ?\n"; + if (simplexFound != st.null_simplex()) + std::clog << "***+ YES IT IS!\n"; + else + std::clog << "***- NO IT ISN'T\n"; + // Check it is found + BOOST_CHECK(simplexFound != st.null_simplex()); + + typeVectorVertex unknownSimplexVector{15}; + simplexFound = st.find(unknownSimplexVector); + std::clog << "**************IS THE SIMPLEX {15} IN THE SIMPLEX TREE ?\n"; + if (simplexFound != st.null_simplex()) + std::clog << "***+ YES IT IS!\n"; + else + std::clog << "***- NO IT ISN'T\n"; + // Check it is NOT found + BOOST_CHECK(simplexFound == st.null_simplex()); + + simplexFound = st.find(SimplexVector6); + std::clog << "**************IS THE SIMPLEX {0,1,6,7} IN THE SIMPLEX TREE ?\n"; + if (simplexFound != st.null_simplex()) + std::clog << "***+ YES IT IS!\n"; + else + std::clog << "***- NO IT ISN'T\n"; + // Check it is found + BOOST_CHECK(simplexFound != st.null_simplex()); + + typeVectorVertex otherSimplexVector{1, 15}; + simplexFound = st.find(otherSimplexVector); + std::clog << "**************IS THE SIMPLEX {15,1} IN THE SIMPLEX TREE ?\n"; + if (simplexFound != st.null_simplex()) + std::clog << "***+ YES IT IS!\n"; + else + std::clog << "***- NO IT ISN'T\n"; + // Check it is NOT found + BOOST_CHECK(simplexFound == st.null_simplex()); + + typeVectorVertex invSimplexVector{1, 2, 0}; + simplexFound = st.find(invSimplexVector); + std::clog << "**************IS THE SIMPLEX {1,2,0} IN THE SIMPLEX TREE ?\n"; + if (simplexFound != st.null_simplex()) + std::clog << "***+ YES IT IS!\n"; + else + std::clog << "***- NO IT ISN'T\n"; + // Check it is found + BOOST_CHECK(simplexFound != st.null_simplex()); + + // Display the Simplex_tree - Can not be done in the middle of 2 inserts + std::clog << "The complex contains " << st.num_simplices() << " simplices" << std::endl; + std::clog << " - dimension " << st.dimension() << std::endl; + std::clog << std::endl << std::endl << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; + for (auto f_simplex : st.filtration_simplex_range()) { + std::clog << " " << "[" << st.filtration(f_simplex) << "] "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::clog << (int) vertex << " "; + } + std::clog << std::endl; + } +} + + +template +void test_simplex_is_vertex(typeST& st, typename typeST::Simplex_handle sh, typename typeST::Vertex_handle v) { + BOOST_CHECK(st.dimension(sh) == 0); + auto&& r = st.simplex_vertex_range(sh); + auto i = std::begin(r); + BOOST_CHECK(*i == v); + BOOST_CHECK(++i == std::end(r)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_reset_filtration, typeST, list_of_tested_variants) { + std::clog << "********************************************************************" << std::endl; + std::clog << "TEST RESET FILTRATION" << std::endl; + typeST st; + + st.insert_simplex_and_subfaces({2, 1, 0}, 3.); + st.insert_simplex_and_subfaces({3, 0}, 2.); + st.insert_simplex_and_subfaces({3, 4, 5}, 3.); + st.insert_simplex_and_subfaces({0, 1, 6, 7}, 4.); + + /* Inserted simplex: */ + /* 1 6 */ + /* o---o */ + /* /X\7/ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + + for (auto f_simplex : st.skeleton_simplex_range(3)) { + std::clog << "vertex = ("; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::clog << vertex << ","; + } + std::clog << ") - filtration = " << st.filtration(f_simplex); + std::clog << " - dimension = " << st.dimension(f_simplex) << std::endl; + // Guaranteed by construction + BOOST_CHECK(st.filtration(f_simplex) >= 2.); + } + + // dimension until 5 even if simplex tree is of dimension 3 to test the limits + for(int dimension = 5; dimension >= 0; dimension --) { + std::clog << "### reset_filtration - dimension = " << dimension << "\n"; + st.reset_filtration(0., dimension); + for (auto f_simplex : st.skeleton_simplex_range(3)) { + std::clog << "vertex = ("; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::clog << vertex << ","; + } + std::clog << ") - filtration = " << st.filtration(f_simplex); + std::clog << " - dimension = " << st.dimension(f_simplex) << std::endl; + if (st.dimension(f_simplex) < dimension) + BOOST_CHECK(st.filtration(f_simplex) >= 2.); + else + BOOST_CHECK(st.filtration(f_simplex) == st.inf_); + } + } + +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_clear, typeST, list_of_tested_variants) { + std::clog << "********************************************************************" << std::endl; + std::clog << "TEST SIMPLEX TREE CLEAR" << std::endl; + typeST st; + st.insert_simplex_and_subfaces({0, 1}, vec{1.5}); + st.initialize_filtration(); + st.clear(); + BOOST_CHECK(st.num_vertices() == 0); + BOOST_CHECK(st.num_simplices() == 0); + BOOST_CHECK(st.upper_bound_dimension() == -1); + BOOST_CHECK(st.dimension() == -1); + BOOST_CHECK(boost::size(st.filtration_simplex_range()) == 0); + typeST st_empty; + BOOST_CHECK(st == st_empty); + st.insert_simplex_and_subfaces({0}, vec{2.5}); + BOOST_CHECK(boost::size(st.cofaces_simplex_range(st.find({0}), 1)) == 0); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(for_each_simplex_skip_iteration, typeST, list_of_tested_variants) { + std::clog << "********************************************************************" << std::endl; + std::clog << "TEST FOR_EACH ITERATION SKIP MECHANISM" << std::endl; + typeST st; + + st.insert_simplex_and_subfaces({2, 1, 0}, 3.); + st.insert_simplex_and_subfaces({3, 0}, 2.); + st.insert_simplex_and_subfaces({3, 4, 5}, 3.); + st.insert_simplex_and_subfaces({0, 1, 6, 7}, 4.); + + /* Inserted simplex: */ + /* 1 6 */ + /* o---o */ + /* /X\7/ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + + std::vector num_simplices_by_dim_until_two(2); + auto lambda_nb_simp_by_dim = [&num_simplices_by_dim_until_two](typename typeST::Simplex_handle, int dim) + { + BOOST_CHECK (dim < 2); + ++num_simplices_by_dim_until_two[dim]; + return dim >= 1; // The iteration will skip the children in this case + }; + st.for_each_simplex(lambda_nb_simp_by_dim); + for (auto num_simplices : num_simplices_by_dim_until_two) + std::cout << num_simplices << ", "; + std::cout << std::endl; + + auto num_simplices_by_dim = st.num_simplices_by_dimension(); + for (auto num_simplices : num_simplices_by_dim) + std::cout << num_simplices << ", "; + std::cout << std::endl; + + BOOST_CHECK(num_simplices_by_dim_until_two[0] == num_simplices_by_dim[0]); + BOOST_CHECK(num_simplices_by_dim_until_two[1] == num_simplices_by_dim[1]); +}