/* This file is part of the Gudhi Library. The Gudhi library * (Geometric Understanding in Higher Dimensions) is a generic C++ * library for computational topology. * * Author(s): David Salinas * * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "gudhi/Utils.h" #include "gudhi/Test.h" #include "gudhi/Skeleton_blocker.h" //#include "gudhi/Skeleton_blocker_link_complex.h" //#include "gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h" //#include "gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h" //#include "gudhi/Skeleton_blocker/internal/Trie.h" using namespace std; using namespace Gudhi; using namespace skbl; typedef Skeleton_blocker_complex Complex; typedef Complex::Vertex_handle Vertex_handle; typedef Complex::Root_vertex_handle Root_vertex_handle; typedef Complex::Simplex_handle Simplex_handle; typedef Complex::Root_simplex_handle Root_simplex_handle; typedef Simplex_handle::Simplex_vertex_const_iterator Simplex_vertex_const_iterator; typedef Complex::Edge_handle Edge_handle; // true if v in complex bool assert_vertex(Complex &complex,Vertex_handle v){ //assert(complex.contains(v)); return complex.contains(static_cast(v)); } bool assert_simplex(Complex &complex,Root_vertex_handle a,Root_vertex_handle b,Root_vertex_handle c){ return true; // AddressSimplex simplex((a),(b),(c)); // return complex.contains(&simplex); } // true iff the blocker (a,b,c) is in complex bool assert_blocker(Complex &complex,Root_vertex_handle a,Root_vertex_handle b,Root_vertex_handle c){ return true; //return complex.contains_blocker((a),(b),(c)); } // true iff the blocker (a,b,c,d) is in complex bool assert_blocker(Complex &complex,Root_vertex_handle a,Root_vertex_handle b,Root_vertex_handle c,Root_vertex_handle d){ return true; //Simplex blocker (a,b,c,d); //return complex.contains_blocker(&blocker); } void build_complete(int n,Complex& complex){ complex.clear(); for(int i=0;i=0;i--) // for(int j=i-1;j>=0;j--) // complex.add_edge(Vertex_handle(i),Vertex_handle(j)); for(int i=0;i expected_num_simplices; expected_num_simplices[Vertex_handle(0)] = 4; expected_num_simplices[Vertex_handle(1)] = 6; expected_num_simplices[Vertex_handle(2)] = 11; expected_num_simplices[Vertex_handle(3)] = 9; expected_num_simplices[Vertex_handle(4)] = 7; expected_num_simplices[Vertex_handle(5)] = 7; for(auto pair : expected_num_simplices){ unsigned num_simplices_around = 0; for(const auto& simplex : complex.simplex_range(pair.first)){ simplex.dimension(); DBGVALUE(simplex); ++num_simplices_around; } correct_number_simplices = correct_number_simplices && (num_simplices_around == pair.second); DBGMSG("current vertex:",pair.first); DBGMSG("expected_num_simplices:",pair.second); DBGMSG("found:",num_simplices_around); } return correct_number_simplices; } bool test_iterator_simplices2(){ Complex complex(2); complex.add_edge(Vertex_handle(0),Vertex_handle(1)); for(const auto& s:complex.triangle_range()){ s.dimension(); return false; // there are no triangles } unsigned num_simplices = 0 ; DBGVALUE(complex.to_string()); for(const auto& simplex : complex.simplex_range(Vertex_handle(0))){ simplex.dimension(); DBGVALUE(simplex); } for(const auto& simplex : complex.simplex_range()){ DBGVALUE(simplex); simplex.dimension(); ++num_simplices; } bool correct_number_simplices = (num_simplices == 3); return correct_number_simplices; } bool test_iterator_simplices3(){ Complex complex(3); complex.add_edge(Vertex_handle(0),Vertex_handle(1)); complex.add_edge(Vertex_handle(1),Vertex_handle(2)); complex.add_edge(Vertex_handle(2),Vertex_handle(0)); complex.add_blocker(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2))); unsigned num_simplices = 0 ; for(const auto& simplex : complex.simplex_range(Vertex_handle(0))){ simplex.dimension(); DBGVALUE(simplex); } for(const auto& simplex : complex.simplex_range()){ DBGVALUE(simplex); simplex.dimension(); ++num_simplices; } bool correct_number_simplices = (num_simplices == 6); return correct_number_simplices; } bool test_iterator_simplices4(){ Complex empty_complex; for(auto v : empty_complex.vertex_range()){ v; } for(auto e : empty_complex.edge_range()){ empty_complex[e]; } for(auto t : empty_complex.triangle_range()){ t.dimension(); } for(auto s : empty_complex.simplex_range()){ s.dimension(); } return true; } template auto blocker_range(Map map) -> decltype( map | boost::adaptors::map_values){ return map| boost::adaptors::map_values ; } bool test_iterator_blockers(){ Complex complex; Simplex_handle alpha; Simplex_handle vertex_set_expected; // Build the complexes for (int i=0;i<20;i++){ complex.add_vertex(); } for (int i=10;i<15;i++){ for (int j=i+1;j<15;j++) complex.add_edge(Vertex_handle(i),Vertex_handle(j)); } complex.add_blocker(Simplex_handle(Vertex_handle(10),Vertex_handle(11),Vertex_handle(12))); complex.add_blocker(Simplex_handle(Vertex_handle(2),Vertex_handle(1),Vertex_handle(10))); complex.add_blocker(Simplex_handle(Vertex_handle(10),Vertex_handle(9),Vertex_handle(15))); complex.add_blocker(Simplex_handle(Vertex_handle(1),Vertex_handle(9),Vertex_handle(8))); // Print result int num_blockers=0; for(auto blockers : complex.blocker_range(Vertex_handle(10))){ TESTVALUE(*blockers) ; num_blockers++; } bool test = (num_blockers==3); num_blockers=0; for (auto blockers : complex.blocker_range()){ TESTVALUE(*blockers) ; num_blockers++; } test = test && (num_blockers==4) ; return test; } bool test_link0(){ enum { a, b, c, d, n }; Complex complex(n); complex.add_edge(Vertex_handle(b),Vertex_handle(c));complex.add_edge(Vertex_handle(c),Vertex_handle(d)); Simplex_handle alpha = Simplex_handle(Vertex_handle(c)); Skeleton_blocker_link_complex L(complex,alpha); auto L2 = complex.link(alpha); if(L!=L2) return false; PRINT(L.num_vertices()); PRINT(L.to_string()); bool test1 = L.contains_vertex(*L.get_address(Root_vertex_handle(b))); bool test2 = L.contains_vertex(*L.get_address(Root_vertex_handle(d))); bool test3 = L.num_edges()==0; bool test4 = L.num_blockers()==0; return test1&&test2&&test3&&test4; } bool test_link1(){ Complex complex; // Build the complexes for (int i=0;i<20;i++){ complex.add_vertex(); } for (int i=10;i<15;i++){ for (int j=i+1;j<15;j++) complex.add_edge(Vertex_handle(i),Vertex_handle(j)); } Simplex_handle alpha(Vertex_handle(12),Vertex_handle(14)); Skeleton_blocker_link_complex L(complex,alpha); // Complexes built auto L2 = complex.link(alpha); if(L!=L2) return false; // verification bool test1 = L.contains_vertex(*L.get_address(Root_vertex_handle(10))); bool test2 = L.contains_vertex(*L.get_address(Root_vertex_handle(11))); bool test3 = L.contains_vertex(*L.get_address(Root_vertex_handle(13))); bool test4 = L.num_edges()==3; bool test5 = L.num_blockers()==0; Root_simplex_handle simplex; simplex.add_vertex(Root_vertex_handle(10)); simplex.add_vertex(Root_vertex_handle(11)); simplex.add_vertex(Root_vertex_handle(13)); bool test6(L.get_simplex_address(simplex)); bool test7 = L.contains(*(L.get_simplex_address(simplex))); cerr <<"----> Ocomplex \n"; return test1&&test2&&test3&&test4&&test5&&test6&&test7 ; } bool test_link2(){ Complex complex; Simplex_handle alpha; Simplex_handle vertex_set_expected; // Build the complexes for (int i=0;i<20;i++){ complex.add_vertex(); } for (int i=10;i<15;i++){ for (int j=i+1;j<15;j++) complex.add_edge(Vertex_handle(i),Vertex_handle(j)); } complex.add_blocker(Simplex_handle(Vertex_handle(10),Vertex_handle(11),Vertex_handle(13))); alpha = Simplex_handle(Vertex_handle(12),Vertex_handle(14)); Skeleton_blocker_link_complex L(complex,alpha); // Complexes built // Print result cerr << "complex complex"<< complex.to_string(); cerr < Ocomplex \n"; return test1&&test2&&test3&&test4&&test5&&test6 ; } bool test_link3(){ Complex complex; Simplex_handle alpha; Simplex_handle vertex_set_expected; // Build the complexes for (int i=0;i<20;i++){ complex.add_vertex(); } for (int i=10;i<15;i++){ for (int j=i+1;j<15;j++) complex.add_edge(Vertex_handle(i),Vertex_handle(j)); } complex.add_blocker(Simplex_handle(Vertex_handle(10),Vertex_handle(11),Vertex_handle(12))); alpha = Simplex_handle(Vertex_handle(12),Vertex_handle(14)); Skeleton_blocker_link_complex L(complex,alpha); // Complexes built // Print result cerr << "complex complex"<< complex.to_string(); cerr < L(complex,alpha); // Complexes built // verification bool test1 = L.contains_vertex(*L.get_address(Root_vertex_handle(10))); bool test2 = L.contains_vertex(*L.get_address(Root_vertex_handle(11))); bool test3 = L.contains_vertex(*L.get_address(Root_vertex_handle(13))); bool test4 = L.num_edges()==3; bool test5 = L.num_blockers()==1; Root_simplex_handle simplex; simplex.add_vertex(Root_vertex_handle(10)); simplex.add_vertex(Root_vertex_handle(11)); simplex.add_vertex(Root_vertex_handle(13)); bool test6 = L.contains_blocker(*(L.get_simplex_address(simplex))); cerr <<"----> Ocomplex \n"; return test1&&test2&&test3&&test4&&test5&&test6 ; } bool test_link5(){ Complex complex(0,new Print_complex_visitor()); // Build the complexes build_complete(4,complex); complex.add_blocker(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2),Vertex_handle(3))); Simplex_handle alpha(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2)); Skeleton_blocker_link_complex L(complex,alpha); // Complexes built // Print result PRINT(complex.to_string()); cerr <()); // Build the complexes build_complete(4,complex); complex.add_blocker(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2))); Simplex_handle alpha(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2)); Skeleton_blocker_link_complex link_blocker_alpha; build_link_of_blocker(complex,alpha,link_blocker_alpha); // Print result PRINT(complex.to_string()); cerr <()); // Build the complexes build_complete(6,complex); complex.add_vertex(); complex.add_vertex(); for(int i = 3; i<6; ++i){ complex.add_edge(Vertex_handle(i),Vertex_handle(6)); complex.add_edge(Vertex_handle(i),Vertex_handle(7)); } complex.add_edge(Vertex_handle(6),Vertex_handle(7)); complex.add_blocker(Simplex_handle(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2))); complex.add_blocker(Simplex_handle(Vertex_handle(3),Vertex_handle(4),Vertex_handle(5))); Simplex_handle alpha(Vertex_handle(3),Vertex_handle(4),Vertex_handle(5)); Skeleton_blocker_link_complex link_blocker_alpha; build_link_of_blocker(complex,alpha,link_blocker_alpha); //the result should be the edge {6,7} plus the blocker {0,1,2} // Print result PRINT(complex.to_string()); cerr < link_blocker_alpha_cpy = link_blocker_alpha; DBGVALUE(link_blocker_alpha_cpy.to_string()); bool equal_complexes = (link_blocker_alpha.num_vertices() == link_blocker_alpha_cpy.num_vertices()) &&(link_blocker_alpha.num_blockers() == link_blocker_alpha_cpy.num_blockers()) &&(link_blocker_alpha.num_edges() == link_blocker_alpha_cpy.num_edges()) ; DBGVALUE((link_blocker_alpha.num_blockers() == link_blocker_alpha_cpy.num_blockers())); DBGVALUE((link_blocker_alpha.num_blockers() )); DBGVALUE(( link_blocker_alpha_cpy.num_blockers())); DBGVALUE(equal_complexes); // verification return link_blocker_alpha.num_vertices()==5 && link_blocker_alpha.num_edges()==4 && link_blocker_alpha.num_blockers()==1 && equal_complexes; } template void add_triangle_edges(int a,int b,int c,list& simplices){ typedef SimplexHandle Simplex_handle; typedef typename SimplexHandle::Vertex_handle Vertex_handle; simplices.push_back(Simplex_handle(Vertex_handle(a),Vertex_handle(b) )); simplices.push_back(Simplex_handle(Vertex_handle(b),Vertex_handle(c) )); simplices.push_back(Simplex_handle(Vertex_handle(c),Vertex_handle(a) )); } template void add_triangle(int a,int b,int c,list& simplices){ typedef SimplexHandle Simplex_handle; typedef typename SimplexHandle::Vertex_handle Vertex_handle; simplices.push_back(Simplex_handle(Vertex_handle(a),Vertex_handle(b),Vertex_handle(c))); } bool test_constructor(){ list simplices; simplices.push_back(Simplex_handle(Vertex_handle(0))); simplices.push_back(Simplex_handle(Vertex_handle(1))); simplices.push_back(Simplex_handle(Vertex_handle(2))); simplices.push_back(Simplex_handle(Vertex_handle(3))); simplices.push_back(Simplex_handle(Vertex_handle(4))); simplices.push_back(Simplex_handle(Vertex_handle(5))); simplices.push_back(Simplex_handle(Vertex_handle(3),Vertex_handle(5) )); add_triangle_edges(0,1,5,simplices); add_triangle_edges(1,2,3,simplices); add_triangle_edges(2,3,4,simplices); add_triangle_edges(1,3,4,simplices); add_triangle_edges(1,2,4,simplices); add_triangle(0,1,5,simplices); add_triangle(1,2,3,simplices); add_triangle(1,3,4,simplices); add_triangle(1,2,4,simplices); add_triangle(2,3,4,simplices); Complex complex(simplices.begin(),simplices.end()); PRINT(complex.to_string()); return ( complex.num_vertices()==6&&complex.num_edges()==10&& complex.num_blockers()==2); } list subfaces(Simplex_handle top_face){ list res; if(top_face.dimension()==-1) return res; if(top_face.dimension()==0) { res.push_back(top_face); return res; } else{ Vertex_handle first_vertex = top_face.first_vertex(); top_face.remove_vertex(first_vertex); res = subfaces(top_face); list copy = res; for(auto& simplex : copy){ simplex.add_vertex(first_vertex); } res.push_back(Simplex_handle(first_vertex)); res.splice(res.end(),copy); return res; } } bool test_constructor2(){ Simplex_handle simplex; for(int i =0 ; i < 5;++i) simplex.add_vertex(static_cast(i)); list simplices(subfaces(simplex)); simplices.remove(simplex); Complex complex(simplices.begin(),simplices.end()); PRINT(complex.to_string()); for(auto b : complex.const_blocker_range()){ cout << "b:"< simplices; auto subf(subfaces(Sh(Vh(0),Vh(1),Vh(2)))); subf.pop_back(); //remove max face -> now a blocker 012 simplices.insert(simplices.begin(),subf.begin(),subf.end()); DBGCONT(simplices); Complex complex(simplices.begin(),simplices.end()); DBGVALUE(complex.to_string()); if(complex.num_blockers()!=1) return false; Sh expected_blocker(Vh(0),Vh(1),Vh(2)); for(auto b : complex.const_blocker_range()) if(*b!=expected_blocker) return false; return complex.num_vertices()==3 && complex.num_blockers()==1; } bool test_constructor4(){ typedef Vertex_handle Vh; typedef Simplex_handle Sh; std::vector simplices; auto subf(subfaces(Sh(Vh(0),Vh(1),Vh(2),Vh(3)))); simplices.insert(simplices.begin(),subf.begin(),subf.end()); simplices.push_back(Sh(Vh(4))); simplices.push_back(Sh(Vh(4),Vh(1))); simplices.push_back(Sh(Vh(4),Vh(0))); DBGCONT(simplices); Complex complex(simplices.begin(),simplices.end()); DBGVALUE(complex.to_string()); if(complex.num_blockers()!=1) return false; Sh expected_blocker(Vh(0),Vh(1),Vh(4)); for(auto b : complex.const_blocker_range()) if(*b!=expected_blocker) return false; return complex.num_vertices()==5 && complex.num_blockers()==1 && complex.num_edges()==8; } bool test_constructor5(){ typedef Vertex_handle Vh; typedef Simplex_handle Sh; std::vector simplices; auto subf(subfaces(Sh(Vh(0),Vh(1),Vh(2)))); simplices.insert(simplices.begin(),subf.begin(),subf.end()); simplices.push_back(Sh(Vh(3))); simplices.push_back(Sh(Vh(3),Vh(1))); simplices.push_back(Sh(Vh(3),Vh(2))); simplices.push_back(Sh(Vh(4))); simplices.push_back(Sh(Vh(4),Vh(1))); simplices.push_back(Sh(Vh(4),Vh(0))); simplices.push_back(Sh(Vh(5))); simplices.push_back(Sh(Vh(5),Vh(2))); simplices.push_back(Sh(Vh(5),Vh(0))); DBGCONT(simplices); Complex complex(simplices.begin(),simplices.end()); DBGVALUE(complex.to_string()); return complex.num_vertices()==6 && complex.num_blockers()==3 && complex.num_edges()==9; } bool test_constructor6(){ typedef Vertex_handle Vh; typedef Simplex_handle Sh; std::vector simplices; auto subf(subfaces(Sh(Vh(0),Vh(1),Vh(2),Vh(3)))); for(auto s:subf){ Sh s1(Vh(0),Vh(1),Vh(2),Vh(3)); Sh s2(Vh(1),Vh(2),Vh(3)); if(s!=s1 && s!=s2) simplices.push_back(s); } DBGCONT(simplices); Complex complex(simplices.begin(),simplices.end()); DBGVALUE(complex.to_string()); if(complex.num_blockers()!=1) return false; Sh expected_blocker(Vh(1),Vh(2),Vh(3)); for(auto b : complex.const_blocker_range()) if(*b!=expected_blocker) return false; return complex.num_vertices()==4 && complex.num_blockers()==1 && complex.num_edges()==6; } bool test_constructor7(){ typedef Vertex_handle Vh; typedef Simplex_handle Sh; std::vector simplices; simplices.push_back(Sh(Vh(0),Vh(1),Vh(2))); simplices.push_back(Sh(Vh(1),Vh(2),Vh(3))); simplices.push_back(Sh(Vh(3),Vh(0),Vh(2))); simplices.push_back(Sh(Vh(3),Vh(0),Vh(1))); //get complex from top faces Complex complex(make_complex_from_top_faces(simplices.begin(),simplices.end())); DBGVALUE(complex.to_string()); if(complex.num_blockers()!=1) return false; Sh expected_blocker(Vh(0),Vh(1),Vh(2),Vh(3)); for(auto b : complex.const_blocker_range()) if(*b!=expected_blocker) return false; return complex.num_vertices()==4 && complex.num_blockers()==1 && complex.num_edges()==6; } bool test_constructor8(){ typedef Vertex_handle Vh; typedef Simplex_handle Sh; std::vector simplices; simplices.push_back(Sh(Vh(0),Vh(1))); simplices.push_back(Sh(Vh(2),Vh(1))); simplices.push_back(Sh(Vh(0),Vh(2))); simplices.push_back(Sh(Vh(3),Vh(1))); simplices.push_back(Sh(Vh(2),Vh(3))); //get complex from top faces Complex complex(make_complex_from_top_faces(simplices.begin(),simplices.end())); DBGVALUE(complex.to_string()); return complex.num_vertices()==4 && complex.num_blockers()==2 && complex.num_edges()==5; } int main (int argc, char *argv[]) { Tests tests_complex; tests_complex.add("test simplex",test_simplex); tests_complex.add("test_link0",test_link0); tests_complex.add("test_link1",test_link1); tests_complex.add("test_link2",test_link2); tests_complex.add("test_link3",test_link3); tests_complex.add("test_link4",test_link4); tests_complex.add("test_link5",test_link5); tests_complex.add("test_link6",test_link6); tests_complex.add("test_link7",test_link7); tests_complex.add("test iterator vertices 1",test_iterator_vertices1); tests_complex.add("test iterator vertices 2",test_iterator_vertices2); tests_complex.add("test iterator edges",test_iterator_edge); tests_complex.add("test iterator edges 2",test_iterator_edge2); tests_complex.add("test iterator edges 3",test_iterator_edge3); tests_complex.add("test iterator simplices",test_iterator_simplices); tests_complex.add("test iterator simplices2",test_iterator_simplices2); tests_complex.add("test iterator simplices3",test_iterator_simplices3); tests_complex.add("test iterator simplices4",test_iterator_simplices4); tests_complex.add("test iterator blockers",test_iterator_blockers); tests_complex.add("test_iterator_triangles",test_iterator_triangles); tests_complex.add("test_constructor_list_simplices",test_constructor); tests_complex.add("test_constructor_list_simplices2",test_constructor2); tests_complex.add("test_constructor_list_simplices3",test_constructor3); tests_complex.add("test_constructor_list_simplices4",test_constructor4); tests_complex.add("test_constructor_list_simplices5",test_constructor5); tests_complex.add("test_constructor_list_simplices6",test_constructor6); tests_complex.add("test_constructor_list_simplices7",test_constructor7); tests_complex.add("test_constructor_list_simplices8",test_constructor8); if(tests_complex.run()){ return EXIT_SUCCESS; } else{ return EXIT_FAILURE; } // test_iterator_simplices(); }