From beca11e4969f7d312b2307251e28dec18193a93f Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 18 Mar 2015 13:59:57 +0000 Subject: Added an empty file for wc git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@486 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fd12027f5ae859c8caaa6a04182c19ff734bdf43 --- src/CMakeLists.txt | 1 + .../include/gudhi/Witness_complex.h | 183 +++++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 src/Witness_complex/include/gudhi/Witness_complex.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b67ab2f8..04c4369c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,5 +37,6 @@ else() add_subdirectory(example/Skeleton_blocker) add_subdirectory(example/Contraction) add_subdirectory(example/Hasse_complex) + add_subdirectort(example/Witness_complex) endif() diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h new file mode 100644 index 00000000..fbebea57 --- /dev/null +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -0,0 +1,183 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 . + */ + +#ifndef GUDHI_WITNESS_COMPLEX_H_ +#define GUDHI_WITNESS_COMPLEX_H_ + +#include +#include +#include +#include "gudhi/reader_utils.h" +#include "gudhi/Simplex_tree.h" +#include +#include + +namespace Gudhi { + + /* +template +class Simplex_tree; + */ + + /* +template +class Witness_complex: public Simplex_tree { + //class Witness_complex: public Simplex_tree { +public: + +// typedef int Simplex_handle; //index in vector complex_ + +// typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; +// typedef boost::iterator_range Boundary_simplex_range; + +// typedef typename std::vector< Simplex_handle >::iterator Skeleton_simplex_iterator; +// typedef boost::iterator_range< Skeleton_simplex_iterator > Skeleton_simplex_range; + +// typedef IndexingTag Indexing_tag; + /** \brief Type for the value of the filtration function. + * + * Must be comparable with <. */ +// typedef FiltrationValue Filtration_value; + /** \brief Key associated to each simplex. + * + * Must be a signed integer type. */ +// typedef SimplexKey Simplex_key; + /** \brief Type for the vertex handle. + * + * Must be a signed integer type. It admits a total order <. */ +// typedef VertexHandle Vertex_handle; + + /* Type of node in the simplex tree. */ +// typedef Simplex_tree_node_explicit_storage Node; + /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ +// typedef typename boost::container::flat_map Dictionary; + +/* + friend class Simplex_tree_node_explicit_storage< Simplex_tree >; + friend class Simplex_tree_siblings< Simplex_tree, Dictionary>; + friend class Simplex_tree_simplex_vertex_iterator< Simplex_tree >; + friend class Simplex_tree_boundary_simplex_iterator< Simplex_tree >; + friend class Simplex_tree_complex_simplex_iterator< Simplex_tree >; + friend class Simplex_tree_skeleton_simplex_iterator< Simplex_tree >; +*/ + + /* \brief Set of nodes sharing a same parent in the simplex tree. */ + /* \brief Set of nodes sharing a same parent in the simplex tree. */ +// typedef Simplex_tree_siblings Siblings; + +/* + typedef std::vector< double > Point_t; + typedef std::vector< Point_t > Point_Vector; + +Witness_complex(int number_of_landmarks, std::string file_name) +{ + /* + Point_Vector & points; + read_points(file_name, points); + landmark_extraction(points); + */ +/* +} + +private: + + +/** + * \brief Permutes the vector in such a way that the landmarks appear first + */ + +/* +void landmark_extraction(int nbP, Point_Vector & points, int inL) +{ + int i,j; + for (i = 0; i != nbP; ++i) + { + for (j = 0; j != nbP; ) + } +} +*/ + + /* + +double distPoints(Point_t &p, Point_t &q) { + double dist = 0.; + Point_t::iterator itp = p.begin(); + Point_t::iterator itq = q.begin(); + while(itp!=p.end()) { + dist += (*itp - *itq)*(*itp - *itq); + itp++; itq++;} + return dist; +} + +void furthestPoints(Point_Vector &W, int nbP, std::string file_land, int dim, int nbL, Point_Vector &L) { + //std::cout << "Enter furthestPoints "<< endl; + //Point_Vector *L = new Point_Vector(); + double density = 5.; + int current_number_of_landmarks=0; + double curr_max_dist; + double curr_dist; + double mindist = 10005.; + int curr_max_w=0; + int curr_w=0; + srand(354698); + int rand_int = rand()% nbP; + //std::cout << rand_int << endl; + L.push_back(W[rand_int]);// first landmark is random + current_number_of_landmarks++; + while (1) { + curr_w = 0; + curr_max_dist = -1; + for(Point_Vector::iterator itW = W.begin(); itW != W.end(); itW++) { + //compute distance from w and L + mindist = 100000.; + for(Point_Vector::iterator itL = L.begin(); itL != L.end(); itL++) { + curr_dist = distPoints(*itW,*itL); + if(curr_dist < mindist) { + mindist = curr_dist; + } + } + if(mindist > curr_max_dist) { + curr_max_w = curr_w; //??? + curr_max_dist = mindist; + } + curr_w++; + } + L.push_back(W[curr_max_w]); + current_number_of_landmarks++; + density = sqrt(curr_max_dist); + //std::cout << "[" << current_number_of_landmarks << ":" << density <<"] "; + if(L.size() == nbL) break; + } + //std::cout << endl; + return L; +} + */ +}; //class Witness_complex +*/ + +} // namespace Guhdi + +#endif -- cgit v1.2.3 From 246aa7e8de4d6dbfd8ab3fd745a8322e9d5db5dd Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 18 Mar 2015 14:02:17 +0000 Subject: added an empty example file as well git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@487 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 72220440cab950b50ecc192d27bc319bb4dd2d2d --- src/Witness_complex/example/CMakeLists.txt | 17 ++++++++++ .../example/simple_witness_complex.cpp | 37 ++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/Witness_complex/example/CMakeLists.txt create mode 100644 src/Witness_complex/example/simple_witness_complex.cpp (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt new file mode 100644 index 00000000..d02522f8 --- /dev/null +++ b/src/Witness_complex/example/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHIWitnessComplex) + +add_executable ( simple_witness_complex simple_witness_complex.cpp ) +add_test(simple_witness_complex ${CMAKE_CURRENT_BINARY_DIR}/simple_witness_complex) + + +# An example with Simplex-tree using CGAL alpha_shapes_3 +#if(GMP_FOUND AND CGAL_FOUND) +# message("CGAL_lib = ${CGAL_LIBRARIES_DIR}") +# message("GMP_LIBRARIES = ${GMP_LIBRARIES}") +# INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) +# INCLUDE_DIRECTORIES(${CGAL_INCLUDE_DIRS}) +# add_executable ( simplex_tree_from_alpha_shapes_3 simplex_tree_from_alpha_shapes_3.cpp ) +# target_link_libraries(simplex_tree_from_alpha_shapes_3 ${GMP_LIBRARIES} ${CGAL_LIBRARY}) +# add_test(simplex_tree_from_alpha_shapes_3 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_alpha_shapes_3 ${CMAKE_SOURCE_DIR}/data/points/bunny_5000) +#endif() diff --git a/src/Witness_complex/example/simple_witness_complex.cpp b/src/Witness_complex/example/simple_witness_complex.cpp new file mode 100644 index 00000000..9147763f --- /dev/null +++ b/src/Witness_complex/example/simple_witness_complex.cpp @@ -0,0 +1,37 @@ +/* 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): Vincent Rouvreau + * + * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (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 "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex.h" + +using namespace Gudhi; + +//typedef std::vector< Vertex_handle > typeVectorVertex; +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + +int main (int argc, char * const argv[]) +{ + std::cout << "Howdy world!\n"; +} -- cgit v1.2.3 From 6536cb935d5702425f33d10f514fa450c470096a Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 18 Mar 2015 17:35:25 +0000 Subject: Added witness_complex function carcas git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@489 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 542dd6740b0ae233ea5fb8ea5c6fe313bf1f27d9 --- CMakeLists.txt | 2 + .../include/gudhi/Witness_complex.h | 113 ++++++++++++++------- 2 files changed, 79 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/CMakeLists.txt b/CMakeLists.txt index 3afec463..0c8f6ea3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,7 @@ else() include_directories(src/Persistent_cohomology/include/) include_directories(src/Simplex_tree/include/) include_directories(src/Skeleton_blocker/include/) + include_directories(src/Witness_complex/include/) add_subdirectory(src/Simplex_tree/test) add_subdirectory(src/Simplex_tree/example) @@ -83,6 +84,7 @@ else() add_subdirectory(src/Skeleton_blocker/example) add_subdirectory(src/Contraction/example) add_subdirectory(src/Hasse_complex/example) + add_subdirectory(src/Witness_complex/example) endif() diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index fbebea57..0651e38e 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -27,8 +27,10 @@ #include #include #include "gudhi/reader_utils.h" +#include "gudhi/distance_functions.h" #include "gudhi/Simplex_tree.h" #include +#include #include namespace Gudhi { @@ -40,14 +42,16 @@ template -class Witness_complex: public Simplex_tree { - //class Witness_complex: public Simplex_tree { + class Witness_complex: public Simplex_tree<> { + //class Witness_complex: public Simplex_tree { + //class Witness_complex { public: +//Simplex_tree<> st; // typedef int Simplex_handle; //index in vector complex_ // typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; @@ -88,50 +92,86 @@ public: /* \brief Set of nodes sharing a same parent in the simplex tree. */ // typedef Simplex_tree_siblings Siblings; -/* - typedef std::vector< double > Point_t; - typedef std::vector< Point_t > Point_Vector; +typedef std::vector< double > Point_t; +typedef std::vector< Point_t > Point_Vector; + +typedef std::vector< Vertex_handle > typeVectorVertex; +typedef std::pair typeSimplex; +typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; +/* Witness_complex(int number_of_landmarks, std::string file_name) { - /* - Point_Vector & points; - read_points(file_name, points); - landmark_extraction(points); - */ -/* } - -private: - +*/ /** - * \brief Permutes the vector in such a way that the landmarks appear first + * /brief Iterative construction of the witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks}. + * Landmarks are supposed to be in [0,nbL-1] */ -/* -void landmark_extraction(int nbP, Point_Vector & points, int inL) +template< typename KNearestNeighbours > +void witness_complex(KNearestNeighbours & knn) { - int i,j; - for (i = 0; i != nbP; ++i) - { - for (j = 0; j != nbP; ) + int k=1; /* current dimension in iterative construction */ + //Construction of the active witness list + int nbW = knn.size(); + int nbL = knn.at(0).size(); + VertexHandle vh; + typeVectorVertex vv; + typeSimplex simplex; + typePairSimplexBool returnValue; + /* The list of still useful witnesses + * it will diminuish in the course of iterations + */ + std::forward_list active_w = new std::forward_list(); + for (int i=0; i != nbW; ++i) { + // initial fill of active witnesses list + active_w.push_front(i); } + for (int i=0; i != nbL; ++i) { + // initial fill of 0-dimensional simplices + // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore + vh = (Vertex_handle)i; + vv = {i}; + /* TODO Filtration */ + simplex = std::make_pair(vv,Filtration_value(0.0)); + returnValue = this.insert_simplex(simplex.first, simplex.second); + /* TODO Error if not inserted : normally no need here though*/ + } + while (!active_w.empty() && k+1 < nbL ) { + std::forward_list::iterator it = active_w.begin(); + while (it != active_w.end()) { + typeVectorVertex simplex_vector; + for (int i=0; i != k+1; ++i) { + // create a (k+1) element array for the given active landmark + /* + typeVectorVertex::iterator itSV = simplex_vector.begin(); + while (itSV != simplex_vector.end() && *itSV < knn[*it][i]) { + itSV++; + } + simplex_vector.insert(itSV,knn[*it][i]); + */ + simplex_vector.push_back(knn[*it][i]); + } + /* THE INSERTION: Checking if all the subfaces are in the simplex tree is mandatory */ + bool ok = all_faces_in(simplex_vecter); + returnValue = this.insert_simplex(simplex_vector,0.0); + } + } } -*/ - /* - -double distPoints(Point_t &p, Point_t &q) { - double dist = 0.; - Point_t::iterator itp = p.begin(); - Point_t::iterator itq = q.begin(); - while(itp!=p.end()) { - dist += (*itp - *itq)*(*itp - *itq); - itp++; itq++;} - return dist; +private: + +bool all_faces_in(typeVectorVertex v) +{ +return true; } +/** + * \brief Permutes the vector in such a way that the landmarks appear first + */ + void furthestPoints(Point_Vector &W, int nbP, std::string file_land, int dim, int nbL, Point_Vector &L) { //std::cout << "Enter furthestPoints "<< endl; //Point_Vector *L = new Point_Vector(); @@ -154,7 +194,8 @@ void furthestPoints(Point_Vector &W, int nbP, std::string file_land, int dim, in //compute distance from w and L mindist = 100000.; for(Point_Vector::iterator itL = L.begin(); itL != L.end(); itL++) { - curr_dist = distPoints(*itW,*itL); + //curr_dist = distPoints(*itW,*itL); + curr_dist = euclidean_distance(*itW,*itL); if(curr_dist < mindist) { mindist = curr_dist; } @@ -174,9 +215,9 @@ void furthestPoints(Point_Vector &W, int nbP, std::string file_land, int dim, in //std::cout << endl; return L; } - */ + }; //class Witness_complex -*/ + } // namespace Guhdi -- cgit v1.2.3 From b364c0f0f5a6a6e8cd363403c85480be1e63bcf5 Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 19 Mar 2015 15:51:54 +0000 Subject: fixed the edge addition git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@494 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 63206a9ddb444046e6b4202f600637780c0acc05 --- .../include/gudhi/Witness_complex.h | 107 +++++++++++++++------ 1 file changed, 76 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 0651e38e..62ce9187 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -30,7 +30,7 @@ #include "gudhi/distance_functions.h" #include "gudhi/Simplex_tree.h" #include -#include +#include #include namespace Gudhi { @@ -42,17 +42,43 @@ template - class Witness_complex: public Simplex_tree<> { +class Witness_complex: public Simplex_tree<> { //class Witness_complex: public Simplex_tree { //class Witness_complex { -public: +private: + + /* + template < typename Witness_id = int, + typename Landmark_id = int, + typename Simplex_handle = Simplex_handle > + struct Active_witness { + Witness_id witness_id; + Landmark_id landmark_id; + Simplex_handle simplex_handle; + }; + */ + +struct Active_witness { + int witness_id; + int landmark_id; + Simplex_handle simplex_handle; +}; + + + +public: + //Simplex_tree<> st; -// typedef int Simplex_handle; //index in vector complex_ // typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; // typedef boost::iterator_range Boundary_simplex_range; @@ -69,16 +95,18 @@ public: * * Must be a signed integer type. */ // typedef SimplexKey Simplex_key; + /** \brief Type for the vertex handle. * * Must be a signed integer type. It admits a total order <. */ -// typedef VertexHandle Vertex_handle; + typedef VertexHandle Vertex_handle; - /* Type of node in the simplex tree. */ -// typedef Simplex_tree_node_explicit_storage Node; + /* Type of node in the simplex tree. */ + typedef Simplex_tree_node_explicit_storage Node; /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ -// typedef typename boost::container::flat_map Dictionary; - + typedef typename boost::container::flat_map Dictionary; + typedef typename Dictionary::iterator Simplex_handle; + /* friend class Simplex_tree_node_explicit_storage< Simplex_tree >; friend class Simplex_tree_siblings< Simplex_tree, Dictionary>; @@ -93,17 +121,16 @@ public: // typedef Simplex_tree_siblings Siblings; -typedef std::vector< double > Point_t; -typedef std::vector< Point_t > Point_Vector; + typedef std::vector< double > Point_t; + typedef std::vector< Point_t > Point_Vector; + + typedef std::vector< Vertex_handle > typeVectorVertex; + typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; + typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; -typedef std::vector< Vertex_handle > typeVectorVertex; -typedef std::pair typeSimplex; -typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; -/* -Witness_complex(int number_of_landmarks, std::string file_name) -{ -} -*/ + typedef int Witness_id; + typedef int Landmark_id; + typedef std::list< Active_witness > ActiveWitnessList; /** * /brief Iterative construction of the witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks}. @@ -124,27 +151,41 @@ void witness_complex(KNearestNeighbours & knn) /* The list of still useful witnesses * it will diminuish in the course of iterations */ - std::forward_list active_w = new std::forward_list(); - for (int i=0; i != nbW; ++i) { - // initial fill of active witnesses list - active_w.push_front(i); - } + ActiveWitnessList active_w = new ActiveWitnessList(); for (int i=0; i != nbL; ++i) { // initial fill of 0-dimensional simplices // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore vh = (Vertex_handle)i; vv = {i}; /* TODO Filtration */ - simplex = std::make_pair(vv,Filtration_value(0.0)); + simplex = std::make_pair(vv, Filtration_value(0.0)); returnValue = this.insert_simplex(simplex.first, simplex.second); /* TODO Error if not inserted : normally no need here though*/ } + int u,v; // two extremities of an edge + if (nbL > 1) // if the supposed dimension of the complex is >0 + for (int i=0; i != nbW; ++i) { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + if (u > v) { + u = v; + v = knn[i][0]; + } + //Siblings * curr_sib = &root_; + vh = (Vertex_handle)i; + vv = {u,v}; + returnValue = this.insert_simplex(vv,Filtration_value(0.0)); + active_w.push_back(i,v,returnValue.first); + //Simplex_handle sh = root_.members_.begin()+u; + //active_w.push_front(i); + } while (!active_w.empty() && k+1 < nbL ) { - std::forward_list::iterator it = active_w.begin(); + typename ActiveWitnessList::iterator it = active_w.begin(); while (it != active_w.end()) { typeVectorVertex simplex_vector; for (int i=0; i != k+1; ++i) { - // create a (k+1) element array for the given active landmark + // create a (k+1) element array for the given active witness /* typeVectorVertex::iterator itSV = simplex_vector.begin(); while (itSV != simplex_vector.end() && *itSV < knn[*it][i]) { @@ -152,11 +193,14 @@ void witness_complex(KNearestNeighbours & knn) } simplex_vector.insert(itSV,knn[*it][i]); */ - simplex_vector.push_back(knn[*it][i]); + // simplex_vector.push_back(knn[*it][i]); } /* THE INSERTION: Checking if all the subfaces are in the simplex tree is mandatory */ - bool ok = all_faces_in(simplex_vecter); - returnValue = this.insert_simplex(simplex_vector,0.0); + bool ok = all_faces_in(simplex_vector); + if (ok) + returnValue = this.insert_simplex(simplex_vector,0.0); + else + active_w.erase(it++); //First increase the iterator and then erase the previous element } } } @@ -165,6 +209,7 @@ private: bool all_faces_in(typeVectorVertex v) { + return true; } -- cgit v1.2.3 From bd9882e11ba5c8602196d416d04849766226e6ed Mon Sep 17 00:00:00 2001 From: skachano Date: Fri, 20 Mar 2015 14:02:39 +0000 Subject: witness_complex now compiles git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@495 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8699acb60641842e40874ece61a5a0ecad3fa039 --- .../example/simple_witness_complex.cpp | 20 ++- .../include/gudhi/Witness_complex.h | 177 ++++++++++++++------- 2 files changed, 137 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/simple_witness_complex.cpp b/src/Witness_complex/example/simple_witness_complex.cpp index 9147763f..5eb39eb0 100644 --- a/src/Witness_complex/example/simple_witness_complex.cpp +++ b/src/Witness_complex/example/simple_witness_complex.cpp @@ -27,11 +27,27 @@ using namespace Gudhi; -//typedef std::vector< Vertex_handle > typeVectorVertex; +typedef std::vector< Vertex_handle > typeVectorVertex; //typedef std::pair typeSimplex; //typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; int main (int argc, char * const argv[]) { - std::cout << "Howdy world!\n"; + Witness_complex<> wc; + std::vector< typeVectorVertex > KNN; + typeVectorVertex witness0 = {1,7,5,2,6,3,4}; KNN.push_back(witness0 ); + typeVectorVertex witness1 = {2,6,4,5,7,1,3}; KNN.push_back(witness1 ); + typeVectorVertex witness2 = {3,4,2,1,5,6,7}; KNN.push_back(witness2 ); + typeVectorVertex witness3 = {4,2,1,3,5,6,7}; KNN.push_back(witness3 ); + typeVectorVertex witness4 = {5,1,6,7,2,3,4}; KNN.push_back(witness4 ); + typeVectorVertex witness5 = {6,7,5,2,1,3,4}; KNN.push_back(witness5 ); + typeVectorVertex witness6 = {7,5,6,1,2,3,4}; KNN.push_back(witness6 ); + typeVectorVertex witness7 = {2,6,4,5,3,1,7}; KNN.push_back(witness7 ); + typeVectorVertex witness8 = {1,2,5,4,3,6,7}; KNN.push_back(witness8 ); + typeVectorVertex witness9 = {3,4,5,2,6,3,4}; KNN.push_back(witness9 ); + typeVectorVertex witness10 = {5,7,1,3,6,2,4}; KNN.push_back(witness10); + typeVectorVertex witness11 = {5,6,1,7,2,3,4}; KNN.push_back(witness11); + typeVectorVertex witness12 = {1,6,7,5,2,3,4}; KNN.push_back(witness12); + wc.witness_complex(KNN); + std::cout << "Howdy world!\n"; } diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 62ce9187..624b2a51 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -71,6 +71,12 @@ struct Active_witness { int witness_id; int landmark_id; Simplex_handle simplex_handle; + + Active_witness(int witness_id_, int landmark_id_, Simplex_handle simplex_handle_) + : witness_id(witness_id_), + landmark_id(landmark_id_), + simplex_handle(simplex_handle_) + {} }; @@ -144,22 +150,22 @@ void witness_complex(KNearestNeighbours & knn) //Construction of the active witness list int nbW = knn.size(); int nbL = knn.at(0).size(); - VertexHandle vh; + //VertexHandle vh; typeVectorVertex vv; typeSimplex simplex; typePairSimplexBool returnValue; /* The list of still useful witnesses * it will diminuish in the course of iterations */ - ActiveWitnessList active_w = new ActiveWitnessList(); + ActiveWitnessList active_w;// = new ActiveWitnessList(); for (int i=0; i != nbL; ++i) { // initial fill of 0-dimensional simplices // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore - vh = (Vertex_handle)i; + //vh = (Vertex_handle)i; vv = {i}; /* TODO Filtration */ simplex = std::make_pair(vv, Filtration_value(0.0)); - returnValue = this.insert_simplex(simplex.first, simplex.second); + returnValue = this->insert_simplex(simplex.first, simplex.second); /* TODO Error if not inserted : normally no need here though*/ } int u,v; // two extremities of an edge @@ -173,10 +179,10 @@ void witness_complex(KNearestNeighbours & knn) v = knn[i][0]; } //Siblings * curr_sib = &root_; - vh = (Vertex_handle)i; + //vh = (Vertex_handle)i; vv = {u,v}; - returnValue = this.insert_simplex(vv,Filtration_value(0.0)); - active_w.push_back(i,v,returnValue.first); + returnValue = this->insert_simplex(vv,Filtration_value(0.0)); + active_w.push_back(Active_witness(i,v,returnValue.first)); //Simplex_handle sh = root_.members_.begin()+u; //active_w.push_front(i); } @@ -184,21 +190,19 @@ void witness_complex(KNearestNeighbours & knn) typename ActiveWitnessList::iterator it = active_w.begin(); while (it != active_w.end()) { typeVectorVertex simplex_vector; - for (int i=0; i != k+1; ++i) { + typeVectorVertex suffix; + /* + for (int i=0; i != k; ++i) { // create a (k+1) element array for the given active witness - /* - typeVectorVertex::iterator itSV = simplex_vector.begin(); - while (itSV != simplex_vector.end() && *itSV < knn[*it][i]) { - itSV++; - } - simplex_vector.insert(itSV,knn[*it][i]); - */ - // simplex_vector.push_back(knn[*it][i]); + simplex_vector.push_back(knn[it->witness_id][i]); } + + sort(simplex_vector.begin(),simplex_vector.end()); + */ /* THE INSERTION: Checking if all the subfaces are in the simplex tree is mandatory */ - bool ok = all_faces_in(simplex_vector); + bool ok = all_faces_in(knn[it->witness_id][k],it->simplex_handle); if (ok) - returnValue = this.insert_simplex(simplex_vector,0.0); + returnValue = insert_simplex(simplex_vector,0.0); else active_w.erase(it++); //First increase the iterator and then erase the previous element } @@ -207,59 +211,116 @@ void witness_complex(KNearestNeighbours & knn) private: -bool all_faces_in(typeVectorVertex v) -{ - -return true; -} + bool all_faces_in(VertexHandle last, Simplex_handle sh) + { + std::list< VertexHandle > suffix; + Simplex_handle curr_sh = sh; + Siblings * curr_sibl = self_siblings(sh); + VertexHandle curr_vh = curr_sh->first; + while (curr_vh > last) { + suffix.push_front(curr_vh); + curr_vh = curr_sibl->parent(); + curr_sibl = curr_sibl->oncles(); + curr_sh = curr_sibl->find(curr_vh); + } + suffix.push_front(last); + typename std::list< VertexHandle >::iterator itVV = suffix.begin(); + Simplex_handle sh_bup = curr_sh; // Back up the pointer + while (itVV != suffix.end() && curr_sh->second.children()->find(*itVV) != null_simplex()) { + // If the node doesn't exist then stop, else go down the tree + curr_sh = curr_sh->second.children()->find(*itVV); + } + if (itVV == suffix.end()) { + // the simplex is already in the tree + return true; + } + else if (itVV != suffix.end()) { + // the father of the simplex is not in the tree + return false; + } + else { + // CHECK ALL THE FACETS + curr_sh = sh_bup; + while (curr_sibl != root()) { + suffix.push_front(curr_vh); + curr_vh = curr_sibl->parent(); + curr_sibl = curr_sibl->oncles(); + curr_sh = curr_sibl->find(curr_vh); + } + suffix.push_front(curr_vh); + sh_bup = curr_sh; // the first vertex lexicographicly + for (typename std::list< VertexHandle >::iterator itExcl = suffix.begin(); itExcl != suffix.end(); ++itExcl) { + if (*itExcl != last) { + itVV = suffix.begin(); + while (itVV != itExcl) { + if (curr_sibl->find(*itVV) == null_simplex()) + return false; + curr_sh = curr_sibl->find(*itVV); + curr_sibl = self_siblings(curr_sh); + itVV++; + } + itVV++; + while (itVV != suffix.end()) { + if (curr_sibl->find(*itVV) == null_simplex()) + return false; + curr_sh = curr_sibl->find(*itVV); + curr_sibl = self_siblings(curr_sh); + itVV++; + } //endwhile + } //endif + } //endfor + return true; + } //end check all the facets + } /** * \brief Permutes the vector in such a way that the landmarks appear first */ -void furthestPoints(Point_Vector &W, int nbP, std::string file_land, int dim, int nbL, Point_Vector &L) { + void furthestPoints(Point_Vector &W, int nbP, std::string file_land, int dim, int nbL, Point_Vector &L) + { //std::cout << "Enter furthestPoints "<< endl; //Point_Vector *L = new Point_Vector(); - double density = 5.; - int current_number_of_landmarks=0; - double curr_max_dist; - double curr_dist; - double mindist = 10005.; - int curr_max_w=0; - int curr_w=0; - srand(354698); - int rand_int = rand()% nbP; - //std::cout << rand_int << endl; - L.push_back(W[rand_int]);// first landmark is random - current_number_of_landmarks++; - while (1) { - curr_w = 0; - curr_max_dist = -1; - for(Point_Vector::iterator itW = W.begin(); itW != W.end(); itW++) { - //compute distance from w and L - mindist = 100000.; - for(Point_Vector::iterator itL = L.begin(); itL != L.end(); itL++) { + double density = 5.; + int current_number_of_landmarks=0; + double curr_max_dist; + double curr_dist; + double mindist = 10005.; + int curr_max_w=0; + int curr_w=0; + srand(354698); + int rand_int = rand()% nbP; + //std::cout << rand_int << endl; + L.push_back(W[rand_int]);// first landmark is random + current_number_of_landmarks++; + while (1) { + curr_w = 0; + curr_max_dist = -1; + for(Point_Vector::iterator itW = W.begin(); itW != W.end(); itW++) { + //compute distance from w and L + mindist = 100000.; + for(Point_Vector::iterator itL = L.begin(); itL != L.end(); itL++) { //curr_dist = distPoints(*itW,*itL); curr_dist = euclidean_distance(*itW,*itL); - if(curr_dist < mindist) { - mindist = curr_dist; + if(curr_dist < mindist) { + mindist = curr_dist; + } } + if(mindist > curr_max_dist) { + curr_max_w = curr_w; //??? + curr_max_dist = mindist; + } + curr_w++; } - if(mindist > curr_max_dist) { - curr_max_w = curr_w; //??? - curr_max_dist = mindist; - } - curr_w++; + L.push_back(W[curr_max_w]); + current_number_of_landmarks++; + density = sqrt(curr_max_dist); + //std::cout << "[" << current_number_of_landmarks << ":" << density <<"] "; + if(L.size() == nbL) break; } - L.push_back(W[curr_max_w]); - current_number_of_landmarks++; - density = sqrt(curr_max_dist); - //std::cout << "[" << current_number_of_landmarks << ":" << density <<"] "; - if(L.size() == nbL) break; + //std::cout << endl; + return L; } - //std::cout << endl; - return L; -} }; //class Witness_complex -- cgit v1.2.3 From fe296c664a0655fbc4814c51105570773731fb88 Mon Sep 17 00:00:00 2001 From: skachano Date: Fri, 20 Mar 2015 15:55:02 +0000 Subject: Started tests git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@496 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: cd644bc64c0183dbadb8bbdecde6ccc77e7d3c84 --- .../example/simple_witness_complex.cpp | 29 ++++++++++--------- .../include/gudhi/Witness_complex.h | 33 ++++++++++++++-------- 2 files changed, 37 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/simple_witness_complex.cpp b/src/Witness_complex/example/simple_witness_complex.cpp index 5eb39eb0..853918b8 100644 --- a/src/Witness_complex/example/simple_witness_complex.cpp +++ b/src/Witness_complex/example/simple_witness_complex.cpp @@ -33,21 +33,22 @@ typedef std::vector< Vertex_handle > typeVectorVertex; int main (int argc, char * const argv[]) { - Witness_complex<> wc; + Witness_complex<> witnessComplex = Witness_complex<>(); std::vector< typeVectorVertex > KNN; - typeVectorVertex witness0 = {1,7,5,2,6,3,4}; KNN.push_back(witness0 ); - typeVectorVertex witness1 = {2,6,4,5,7,1,3}; KNN.push_back(witness1 ); - typeVectorVertex witness2 = {3,4,2,1,5,6,7}; KNN.push_back(witness2 ); - typeVectorVertex witness3 = {4,2,1,3,5,6,7}; KNN.push_back(witness3 ); - typeVectorVertex witness4 = {5,1,6,7,2,3,4}; KNN.push_back(witness4 ); - typeVectorVertex witness5 = {6,7,5,2,1,3,4}; KNN.push_back(witness5 ); - typeVectorVertex witness6 = {7,5,6,1,2,3,4}; KNN.push_back(witness6 ); - typeVectorVertex witness7 = {2,6,4,5,3,1,7}; KNN.push_back(witness7 ); - typeVectorVertex witness8 = {1,2,5,4,3,6,7}; KNN.push_back(witness8 ); + typeVectorVertex witness0 = {1,0,5,2,6,3,4}; KNN.push_back(witness0 ); + typeVectorVertex witness1 = {2,6,4,5,0,1,3}; KNN.push_back(witness1 ); + typeVectorVertex witness2 = {3,4,2,1,5,6,0}; KNN.push_back(witness2 ); + typeVectorVertex witness3 = {4,2,1,3,5,6,0}; KNN.push_back(witness3 ); + typeVectorVertex witness4 = {5,1,6,0,2,3,4}; KNN.push_back(witness4 ); + typeVectorVertex witness5 = {6,0,5,2,1,3,4}; KNN.push_back(witness5 ); + typeVectorVertex witness6 = {0,5,6,1,2,3,4}; KNN.push_back(witness6 ); + typeVectorVertex witness7 = {2,6,4,5,3,1,0}; KNN.push_back(witness7 ); + typeVectorVertex witness8 = {1,2,5,4,3,6,0}; KNN.push_back(witness8 ); typeVectorVertex witness9 = {3,4,5,2,6,3,4}; KNN.push_back(witness9 ); - typeVectorVertex witness10 = {5,7,1,3,6,2,4}; KNN.push_back(witness10); - typeVectorVertex witness11 = {5,6,1,7,2,3,4}; KNN.push_back(witness11); - typeVectorVertex witness12 = {1,6,7,5,2,3,4}; KNN.push_back(witness12); - wc.witness_complex(KNN); + typeVectorVertex witness10 = {5,0,1,3,6,2,4}; KNN.push_back(witness10); + typeVectorVertex witness11 = {5,6,1,0,2,3,4}; KNN.push_back(witness11); + typeVectorVertex witness12 = {1,6,0,5,2,3,4}; KNN.push_back(witness12); + std::cout << "Let the carnage begin!\n"; + witnessComplex.witness_complex(KNN); std::cout << "Howdy world!\n"; } diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 624b2a51..985660d4 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -33,6 +33,8 @@ #include #include +#include + namespace Gudhi { /* @@ -143,13 +145,17 @@ public: * Landmarks are supposed to be in [0,nbL-1] */ + template< typename KNearestNeighbours > void witness_complex(KNearestNeighbours & knn) +//void witness_complex(std::vector< std::vector< Vertex_handle > > & knn) { - int k=1; /* current dimension in iterative construction */ + std::cout << "**Start the procedure witness_complex" << std::endl; + int k=2; /* current dimension in iterative construction */ //Construction of the active witness list int nbW = knn.size(); int nbL = knn.at(0).size(); + std::cout << "Eh?\n"; //VertexHandle vh; typeVectorVertex vv; typeSimplex simplex; @@ -164,10 +170,12 @@ void witness_complex(KNearestNeighbours & knn) //vh = (Vertex_handle)i; vv = {i}; /* TODO Filtration */ - simplex = std::make_pair(vv, Filtration_value(0.0)); - returnValue = this->insert_simplex(simplex.first, simplex.second); + //simplex = std::make_pair(vv, Filtration_value(0.0)); + //returnValue = this->insert_simplex(simplex.first, simplex.second); + returnValue = this->insert_simplex(vv, Filtration_value(0.0)); /* TODO Error if not inserted : normally no need here though*/ } + std::cout << "Successfully added landmarks" << std::endl; int u,v; // two extremities of an edge if (nbL > 1) // if the supposed dimension of the complex is >0 for (int i=0; i != nbW; ++i) { @@ -183,22 +191,17 @@ void witness_complex(KNearestNeighbours & knn) vv = {u,v}; returnValue = this->insert_simplex(vv,Filtration_value(0.0)); active_w.push_back(Active_witness(i,v,returnValue.first)); + if (returnValue.second) std::cout << "Added edge " << u << v << std::endl; //Simplex_handle sh = root_.members_.begin()+u; //active_w.push_front(i); } + std::cout << "Successfully added edges" << std::endl; while (!active_w.empty() && k+1 < nbL ) { + std::cout << "Started the step k=" << k << std::endl; typename ActiveWitnessList::iterator it = active_w.begin(); while (it != active_w.end()) { typeVectorVertex simplex_vector; typeVectorVertex suffix; - /* - for (int i=0; i != k; ++i) { - // create a (k+1) element array for the given active witness - simplex_vector.push_back(knn[it->witness_id][i]); - } - - sort(simplex_vector.begin(),simplex_vector.end()); - */ /* THE INSERTION: Checking if all the subfaces are in the simplex tree is mandatory */ bool ok = all_faces_in(knn[it->witness_id][k],it->simplex_handle); if (ok) @@ -206,6 +209,7 @@ void witness_complex(KNearestNeighbours & knn) else active_w.erase(it++); //First increase the iterator and then erase the previous element } + k++; } } @@ -213,16 +217,23 @@ private: bool all_faces_in(VertexHandle last, Simplex_handle sh) { + std::cout << "All face in with the landmark " << last << std::endl; std::list< VertexHandle > suffix; Simplex_handle curr_sh = sh; Siblings * curr_sibl = self_siblings(sh); VertexHandle curr_vh = curr_sh->first; while (curr_vh > last) { + std::cout << "We are at " << curr_vh << "\n"; suffix.push_front(curr_vh); + std::cout << "Still fine 1\n"; curr_vh = curr_sibl->parent(); + std::cout << "Still fine 2\n"; curr_sibl = curr_sibl->oncles(); + std::cout << "Still fine 3\n"; curr_sh = curr_sibl->find(curr_vh); + std::cout << "Still fine 4\n"; } + std::cout << "Arrived at the mid-parent" << std::endl; suffix.push_front(last); typename std::list< VertexHandle >::iterator itVV = suffix.begin(); Simplex_handle sh_bup = curr_sh; // Back up the pointer -- cgit v1.2.3 From 14278a8f1a9a066636a595372cf41025b17fe1d8 Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 23 Mar 2015 10:02:28 +0000 Subject: Wild Bug appeared git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@497 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b057061087ac0442ec51ee18c40c227dc721f9b5 --- .../include/gudhi/Witness_complex.h | 105 ++++++++++++++++++--- 1 file changed, 92 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 985660d4..3deb8bc3 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -23,6 +23,7 @@ #ifndef GUDHI_WITNESS_COMPLEX_H_ #define GUDHI_WITNESS_COMPLEX_H_ +#include #include #include #include @@ -155,11 +156,11 @@ void witness_complex(KNearestNeighbours & knn) //Construction of the active witness list int nbW = knn.size(); int nbL = knn.at(0).size(); - std::cout << "Eh?\n"; //VertexHandle vh; typeVectorVertex vv; typeSimplex simplex; typePairSimplexBool returnValue; + int counter = 0; /* The list of still useful witnesses * it will diminuish in the course of iterations */ @@ -168,33 +169,73 @@ void witness_complex(KNearestNeighbours & knn) // initial fill of 0-dimensional simplices // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore //vh = (Vertex_handle)i; + counter++; vv = {i}; /* TODO Filtration */ //simplex = std::make_pair(vv, Filtration_value(0.0)); //returnValue = this->insert_simplex(simplex.first, simplex.second); - returnValue = this->insert_simplex(vv, Filtration_value(0.0)); + //returnValue = insert_simplex(vv, Filtration_value(0.0)); /* TODO Error if not inserted : normally no need here though*/ } + vv = {0}; + returnValue = insert_simplex(vv,Filtration_value(0.0)); std::cout << "Successfully added landmarks" << std::endl; + // PRINT2 + print_sc(root()); int u,v; // two extremities of an edge if (nbL > 1) // if the supposed dimension of the complex is >0 - for (int i=0; i != nbW; ++i) { + /* + // THE BUGGY CODE + for (int i=0; i != nbW; ++i) { // initial fill of active witnesses list u = knn[i][0]; v = knn[i][1]; - if (u > v) { - u = v; - v = knn[i][0]; - } //Siblings * curr_sib = &root_; //vh = (Vertex_handle)i; vv = {u,v}; - returnValue = this->insert_simplex(vv,Filtration_value(0.0)); - active_w.push_back(Active_witness(i,v,returnValue.first)); - if (returnValue.second) std::cout << "Added edge " << u << v << std::endl; + counter++; + returnValue = this->insert_simplex(vv,Filtration_value((double)counter)); + //std::cout << "Null simplex is " << null_simplex()->first << std::endl; + if (returnValue.first != null_simplex()) + { + active_w.push_back(*(new Active_witness(i,v,returnValue.first))); + } + for (typename ActiveWitnessList::iterator it1 = active_w.begin(); it1 != active_w.end(); ++it1) + std::cout << it1->simplex_handle->first << " "; + std::cout << std::endl; //Simplex_handle sh = root_.members_.begin()+u; //active_w.push_front(i); } + */ + for (int i=0; i != nbW; ++i) { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + //Siblings * curr_sib = &root_; + //vh = (Vertex_handle)i; + vv = {u,v}; + returnValue = this->insert_simplex(vv,Filtration_value(0.0)); + //std::cout << "Added edges" << std::endl; + } + //print_sc(root()); + for (int i=0; i != nbW; ++i) { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + if ( u > v) { + u = v; + v = knn[i][0]; + } + Simplex_handle sh; + vv = {u,v}; + sh = (root()->find(u))->second.children()->find(v); + + active_w.push_back(*(new Active_witness(i,v,sh))); + for (typename ActiveWitnessList::iterator it1 = active_w.begin(); it1 != active_w.end(); ++it1) + std::cout << it1->simplex_handle->first << " "; + std::cout << std::endl; + } + std::cout << "Successfully added edges" << std::endl; while (!active_w.empty() && k+1 < nbL ) { std::cout << "Started the step k=" << k << std::endl; @@ -202,12 +243,14 @@ void witness_complex(KNearestNeighbours & knn) while (it != active_w.end()) { typeVectorVertex simplex_vector; typeVectorVertex suffix; - /* THE INSERTION: Checking if all the subfaces are in the simplex tree is mandatory */ + /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/ + std::cout << it->simplex_handle->first << std::endl; bool ok = all_faces_in(knn[it->witness_id][k],it->simplex_handle); if (ok) returnValue = insert_simplex(simplex_vector,0.0); else - active_w.erase(it++); //First increase the iterator and then erase the previous element + active_w.erase(it); //First increase the iterator and then erase the previous element + it++; } k++; } @@ -215,6 +258,34 @@ void witness_complex(KNearestNeighbours & knn) private: + void print_sc(Siblings * sibl) + { + if (sibl == NULL) + std::cout << "&"; + else + print_children(sibl->members_); + } + + void print_children(Dictionary map) + { + std::cout << "("; + if (!map.empty()) + { + std::cout << map.begin()->first; + print_sc(map.begin()->second.children()); + typename Dictionary::iterator it; + for (it = map.begin()+1; it != map.end(); ++it) + { + std::cout << "," << it->first; + } + } + std::cout << ")\n"; + } + + + /** Check if all the facets of a simplex we are going to insert are in the simplex tree or not. + * The only purpose is to test if the witness is still active or not. + */ bool all_faces_in(VertexHandle last, Simplex_handle sh) { std::cout << "All face in with the landmark " << last << std::endl; @@ -223,7 +294,7 @@ private: Siblings * curr_sibl = self_siblings(sh); VertexHandle curr_vh = curr_sh->first; while (curr_vh > last) { - std::cout << "We are at " << curr_vh << "\n"; + std::cout << "We are at " << curr_sh->first << " " << sh->first << "\n"; suffix.push_front(curr_vh); std::cout << "Still fine 1\n"; curr_vh = curr_sibl->parent(); @@ -239,14 +310,22 @@ private: Simplex_handle sh_bup = curr_sh; // Back up the pointer while (itVV != suffix.end() && curr_sh->second.children()->find(*itVV) != null_simplex()) { // If the node doesn't exist then stop, else go down the tree + std::cout << "DOWN!" << curr_sh->first << " -> " << *itVV << std::endl; + std::cout << "Children of " << curr_sh->first << " are "; + for (typename Dictionary::iterator itt = curr_sh->second.children()->members_.begin(); itt != curr_sh->second.children()->members_.end(); ++itt) + std::cout << itt->first << ","; + std::cout << std::endl; curr_sh = curr_sh->second.children()->find(*itVV); + itVV++; } if (itVV == suffix.end()) { // the simplex is already in the tree + std::cout << "The simplex is there" << std::endl; return true; } else if (itVV != suffix.end()) { // the father of the simplex is not in the tree + std::cout << "The father is not there. Deleting witness." << std::endl; return false; } else { -- cgit v1.2.3 From b11daa7d34fc4f3870d8f247895dd5da28526ada Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 23 Mar 2015 15:28:11 +0000 Subject: Fixed the print bug git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@498 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 89201b558bfb27542e9e187b53a2307fb0054fbc --- CMakeLists.txt | 1 + src/Simplex_tree/include/gudhi/Simplex_tree.h | 1 + src/Witness_complex/include/gudhi/Witness_complex.h | 20 ++++++++++++++------ 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c8f6ea3..f3b29994 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,7 @@ else() add_subdirectory(src/Skeleton_blocker/example) add_subdirectory(src/Contraction/example) add_subdirectory(src/Hasse_complex/example) + add_subdirectory(src/Witness_complex/test) add_subdirectory(src/Witness_complex/example) endif() diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index a1758680..e52fe1ae 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -35,6 +35,7 @@ #include #include #include +#include namespace Gudhi { diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 3deb8bc3..e999928f 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -174,14 +174,14 @@ void witness_complex(KNearestNeighbours & knn) /* TODO Filtration */ //simplex = std::make_pair(vv, Filtration_value(0.0)); //returnValue = this->insert_simplex(simplex.first, simplex.second); - //returnValue = insert_simplex(vv, Filtration_value(0.0)); + returnValue = insert_simplex(vv, Filtration_value(0.0)); /* TODO Error if not inserted : normally no need here though*/ } - vv = {0}; - returnValue = insert_simplex(vv,Filtration_value(0.0)); + //vv = {0}; + //returnValue = insert_simplex(vv,Filtration_value(0.0)); std::cout << "Successfully added landmarks" << std::endl; // PRINT2 - print_sc(root()); + print_sc(root()); std::cout << std::endl; int u,v; // two extremities of an edge if (nbL > 1) // if the supposed dimension of the complex is >0 /* @@ -215,6 +215,7 @@ void witness_complex(KNearestNeighbours & knn) //vh = (Vertex_handle)i; vv = {u,v}; returnValue = this->insert_simplex(vv,Filtration_value(0.0)); + print_sc(root()); std::cout << std::endl; //std::cout << "Added edges" << std::endl; } //print_sc(root()); @@ -272,14 +273,21 @@ private: if (!map.empty()) { std::cout << map.begin()->first; - print_sc(map.begin()->second.children()); + if (map.begin()->second.children() == root()) + std::cout << "Sweet potato"; + if (has_children(map.begin())) + print_sc(map.begin()->second.children()); typename Dictionary::iterator it; for (it = map.begin()+1; it != map.end(); ++it) { std::cout << "," << it->first; + if (map.begin()->second.children() == root()) + std::cout << "Sweet potato"; + if (has_children(it)) + print_sc(it->second.children()); } } - std::cout << ")\n"; + std::cout << ")"; } -- cgit v1.2.3 From 4544ed4a3f4ae834a2c7bd0a8f7139a40889657d Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 23 Mar 2015 19:02:01 +0000 Subject: Added an altrnative Witness_complex.h git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@499 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6a7014da8d37c88e0e87317f185d1daa989c87d1 --- .../example/simple_witness_complex.cpp | 2 +- .../include/gudhi/Witness_complex.h | 18 +- .../include/gudhi/Witness_complex1.h | 400 +++++++++++++++++++++ 3 files changed, 410 insertions(+), 10 deletions(-) create mode 100644 src/Witness_complex/include/gudhi/Witness_complex1.h (limited to 'src') diff --git a/src/Witness_complex/example/simple_witness_complex.cpp b/src/Witness_complex/example/simple_witness_complex.cpp index 853918b8..6c70d300 100644 --- a/src/Witness_complex/example/simple_witness_complex.cpp +++ b/src/Witness_complex/example/simple_witness_complex.cpp @@ -23,7 +23,7 @@ #include #include //#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Witness_complex.h" +#include "gudhi/Witness_complex1.h" using namespace Gudhi; diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index e999928f..1a96128f 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -231,10 +231,10 @@ void witness_complex(KNearestNeighbours & knn) vv = {u,v}; sh = (root()->find(u))->second.children()->find(v); - active_w.push_back(*(new Active_witness(i,v,sh))); - for (typename ActiveWitnessList::iterator it1 = active_w.begin(); it1 != active_w.end(); ++it1) - std::cout << it1->simplex_handle->first << " "; - std::cout << std::endl; + active_w.push_back(Active_witness(i,v,sh)); + /*for (typename ActiveWitnessList::iterator it1 = active_w.begin(); it1 != active_w.end(); ++it1) + std::cout << it1->simplex->first << " "; + std::cout << std::endl; */ } std::cout << "Successfully added edges" << std::endl; @@ -245,7 +245,7 @@ void witness_complex(KNearestNeighbours & knn) typeVectorVertex simplex_vector; typeVectorVertex suffix; /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/ - std::cout << it->simplex_handle->first << std::endl; + // std::cout << it->simplex->first << std::endl; bool ok = all_faces_in(knn[it->witness_id][k],it->simplex_handle); if (ok) returnValue = insert_simplex(simplex_vector,0.0); @@ -304,13 +304,13 @@ private: while (curr_vh > last) { std::cout << "We are at " << curr_sh->first << " " << sh->first << "\n"; suffix.push_front(curr_vh); - std::cout << "Still fine 1\n"; + //std::cout << "Still fine 1\n"; curr_vh = curr_sibl->parent(); - std::cout << "Still fine 2\n"; + //std::cout << "Still fine 2\n"; curr_sibl = curr_sibl->oncles(); - std::cout << "Still fine 3\n"; + //std::cout << "Still fine 3\n"; curr_sh = curr_sibl->find(curr_vh); - std::cout << "Still fine 4\n"; + //std::cout << "Still fine 4\n"; } std::cout << "Arrived at the mid-parent" << std::endl; suffix.push_front(last); diff --git a/src/Witness_complex/include/gudhi/Witness_complex1.h b/src/Witness_complex/include/gudhi/Witness_complex1.h new file mode 100644 index 00000000..911dcbe7 --- /dev/null +++ b/src/Witness_complex/include/gudhi/Witness_complex1.h @@ -0,0 +1,400 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 . + */ + +#ifndef GUDHI_WITNESS_COMPLEX_H_ +#define GUDHI_WITNESS_COMPLEX_H_ + +#include +#include +#include +#include +#include "gudhi/reader_utils.h" +#include "gudhi/distance_functions.h" +#include "gudhi/Simplex_tree.h" +#include +#include +#include + +#include + +namespace Gudhi { + + /* +template +class Simplex_tree; + */ + + /* + typedef int Witness_id; +typedef int Landmark_id; +typedef int Simplex_handle; //index in vector complex_ + */ + +template +class Witness_complex: public Simplex_tree<> { + //class Witness_complex: public Simplex_tree { + //class Witness_complex { +private: + + /* + template < typename Witness_id = int, + typename Landmark_id = int, + typename Simplex_handle = Simplex_handle > + struct Active_witness { + Witness_id witness_id; + Landmark_id landmark_id; + Simplex_handle simplex_handle; + }; + */ + +struct Active_witness { + int witness_id; + int landmark_id; + Simplex_handle simplex_handle; + + Active_witness(int witness_id_, int landmark_id_, Simplex_handle simplex_handle_) + : witness_id(witness_id_), + landmark_id(landmark_id_), + simplex_handle(simplex_handle_) + {} +}; + + + + +public: + +//Simplex_tree<> st; + +// typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; +// typedef boost::iterator_range Boundary_simplex_range; + +// typedef typename std::vector< Simplex_handle >::iterator Skeleton_simplex_iterator; +// typedef boost::iterator_range< Skeleton_simplex_iterator > Skeleton_simplex_range; + +// typedef IndexingTag Indexing_tag; + /** \brief Type for the value of the filtration function. + * + * Must be comparable with <. */ +// typedef FiltrationValue Filtration_value; + /** \brief Key associated to each simplex. + * + * Must be a signed integer type. */ +// typedef SimplexKey Simplex_key; + + /** \brief Type for the vertex handle. + * + * Must be a signed integer type. It admits a total order <. */ + typedef VertexHandle Vertex_handle; + + /* Type of node in the simplex tree. */ + typedef Simplex_tree_node_explicit_storage Node; + /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ + typedef typename boost::container::flat_map Dictionary; + typedef typename Dictionary::iterator Simplex_handle; + +/* + friend class Simplex_tree_node_explicit_storage< Simplex_tree >; + friend class Simplex_tree_siblings< Simplex_tree, Dictionary>; + friend class Simplex_tree_simplex_vertex_iterator< Simplex_tree >; + friend class Simplex_tree_boundary_simplex_iterator< Simplex_tree >; + friend class Simplex_tree_complex_simplex_iterator< Simplex_tree >; + friend class Simplex_tree_skeleton_simplex_iterator< Simplex_tree >; +*/ + + /* \brief Set of nodes sharing a same parent in the simplex tree. */ + /* \brief Set of nodes sharing a same parent in the simplex tree. */ +// typedef Simplex_tree_siblings Siblings; + + + typedef std::vector< double > Point_t; + typedef std::vector< Point_t > Point_Vector; + + typedef std::vector< Vertex_handle > typeVectorVertex; + typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; + typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + + typedef int Witness_id; + typedef int Landmark_id; + typedef std::list< Vertex_handle > ActiveWitnessList; + +/** + * /brief Iterative construction of the witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks}. + * Landmarks are supposed to be in [0,nbL-1] + */ + + +template< typename KNearestNeighbours > +void witness_complex(KNearestNeighbours & knn) +//void witness_complex(std::vector< std::vector< Vertex_handle > > & knn) +{ + std::cout << "**Start the procedure witness_complex" << std::endl; + int k=2; /* current dimension in iterative construction */ + //Construction of the active witness list + int nbW = knn.size(); + int nbL = knn.at(0).size(); + //VertexHandle vh; + typeVectorVertex vv; + typeSimplex simplex; + typePairSimplexBool returnValue; + int counter = 0; + /* The list of still useful witnesses + * it will diminuish in the course of iterations + */ + ActiveWitnessList active_w;// = new ActiveWitnessList(); + for (int i=0; i != nbL; ++i) { + // initial fill of 0-dimensional simplices + // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore + //vh = (Vertex_handle)i; + counter++; + vv = {i}; + /* TODO Filtration */ + //simplex = std::make_pair(vv, Filtration_value(0.0)); + //returnValue = this->insert_simplex(simplex.first, simplex.second); + returnValue = insert_simplex(vv, Filtration_value(0.0)); + /* TODO Error if not inserted : normally no need here though*/ + } + //vv = {0}; + //returnValue = insert_simplex(vv,Filtration_value(0.0)); + std::cout << "Successfully added landmarks" << std::endl; + // PRINT2 + print_sc(root()); std::cout << std::endl; + int u,v; // two extremities of an edge + if (nbL > 1) // if the supposed dimension of the complex is >0 + /* + // THE BUGGY CODE + for (int i=0; i != nbW; ++i) { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + //Siblings * curr_sib = &root_; + //vh = (Vertex_handle)i; + vv = {u,v}; + counter++; + returnValue = this->insert_simplex(vv,Filtration_value((double)counter)); + //std::cout << "Null simplex is " << null_simplex()->first << std::endl; + if (returnValue.first != null_simplex()) + { + active_w.push_back(*(new Active_witness(i,v,returnValue.first))); + } + for (typename ActiveWitnessList::iterator it1 = active_w.begin(); it1 != active_w.end(); ++it1) + std::cout << it1->simplex_handle->first << " "; + std::cout << std::endl; + //Simplex_handle sh = root_.members_.begin()+u; + //active_w.push_front(i); + } + */ + for (int i=0; i != nbW; ++i) { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + //Siblings * curr_sib = &root_; + //vh = (Vertex_handle)i; + vv = {u,v}; + returnValue = this->insert_simplex(vv,Filtration_value(0.0)); + print_sc(root()); std::cout << std::endl; + //std::cout << "Added edges" << std::endl; + } + //print_sc(root()); + for (int i=0; i != nbW; ++i) { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + if ( u > v) { + u = v; + v = knn[i][0]; + knn[i][0] = knn[i][1]; + knn[i][1] = v; + } + Simplex_handle sh; + vv = {u,v}; + sh = (root()->find(u))->second.children()->find(v); + + active_w.push_back(i); + /*for (typename ActiveWitnessList::iterator it1 = active_w.begin(); it1 != active_w.end(); ++it1) + std::cout << it1->simplex->first << " "; + std::cout << std::endl; */ + } + + std::cout << "Successfully added edges" << std::endl; + while (!active_w.empty() && k+1 < nbL ) { + std::cout << "Started the step k=" << k << std::endl; + typename ActiveWitnessList::iterator it = active_w.begin(); + while (it != active_w.end()) { + typeVectorVertex simplex_vector; + /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/ + // First sort the first k landmarks + int i = k; + int temp_swap; + VertexHandle inserted_vertex = knn[*it][k]; + while (i>0 && knn[*it][i-1] > knn[*it][i]) + { + temp_swap = knn[*it][i]; + knn[*it][i] = knn[*it][i-1]; + knn[*it][i-1] = temp_swap; + i--; + } + bool ok = all_faces_in(knn, *it, k, inserted_vertex); + if (ok) + { + for (i = 0; i != k+1; ++i) + { + simplex_vector.push_back(knn[*it][i]); + } + returnValue = insert_simplex(simplex_vector,0.0); + } + else + active_w.erase(it); //First increase the iterator and then erase the previous element + it++; + } + print_sc(root()); + k++; + } +} + +private: + + void print_sc(Siblings * sibl) + { + if (sibl == NULL) + std::cout << "&"; + else + print_children(sibl->members_); + } + + void print_children(Dictionary map) + { + std::cout << "("; + if (!map.empty()) + { + std::cout << map.begin()->first; + /*if (map.begin()->second.children() == root()) + std::cout << "Sweet potato"; */ + if (has_children(map.begin())) + print_sc(map.begin()->second.children()); + typename Dictionary::iterator it; + for (it = map.begin()+1; it != map.end(); ++it) + { + std::cout << "," << it->first; + /*if (map.begin()->second.children() == root()) + std::cout << "Sweet potato";*/ + if (has_children(it)) + print_sc(it->second.children()); + } + } + std::cout << ")"; + } + + + /** Check if all the facets of a simplex we are going to insert are in the simplex tree or not. + * The only purpose is to test if the witness is still active or not. + * Assuming here that the list of the first k witnessed landmarks is sorted + */ + template< typename KNearestNeighbours > + bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) + { + std::cout << "All face in with the landmark " << inserted_vertex << std::endl; + //std::list< VertexHandle > suffix; + Simplex_handle curr_sh = root()->find(knn[witness_id][0]); + Siblings * curr_sibl = root(); + //VertexHandle curr_vh = curr_sh->first; + // CHECK ALL THE FACETS + Simplex_handle sh_bup = curr_sh; // the first vertex lexicographicly + for (int i = 0; i != k+1; ++i) + { + curr_sh = sh_bup; + if (knn[witness_id][i] != inserted_vertex) + { + for (int j = 0; j != k+1; ++j) + { + if (j != i) + { + if (curr_sibl->find(knn[witness_id][j]) == null_simplex()) + return false; + curr_sh = curr_sibl->find(knn[witness_id][j]); + curr_sibl = self_siblings(curr_sh); + }//endif j!=i + }//endfor + }//endif + } //endfor + return true; + } + +/** + * \brief Permutes the vector in such a way that the landmarks appear first + */ + + void furthestPoints(Point_Vector &W, int nbP, std::string file_land, int dim, int nbL, Point_Vector &L) + { + //std::cout << "Enter furthestPoints "<< endl; + //Point_Vector *L = new Point_Vector(); + double density = 5.; + int current_number_of_landmarks=0; + double curr_max_dist; + double curr_dist; + double mindist = 10005.; + int curr_max_w=0; + int curr_w=0; + srand(354698); + int rand_int = rand()% nbP; + //std::cout << rand_int << endl; + L.push_back(W[rand_int]);// first landmark is random + current_number_of_landmarks++; + while (1) { + curr_w = 0; + curr_max_dist = -1; + for(Point_Vector::iterator itW = W.begin(); itW != W.end(); itW++) { + //compute distance from w and L + mindist = 100000.; + for(Point_Vector::iterator itL = L.begin(); itL != L.end(); itL++) { + //curr_dist = distPoints(*itW,*itL); + curr_dist = euclidean_distance(*itW,*itL); + if(curr_dist < mindist) { + mindist = curr_dist; + } + } + if(mindist > curr_max_dist) { + curr_max_w = curr_w; //??? + curr_max_dist = mindist; + } + curr_w++; + } + L.push_back(W[curr_max_w]); + current_number_of_landmarks++; + density = sqrt(curr_max_dist); + //std::cout << "[" << current_number_of_landmarks << ":" << density <<"] "; + if(L.size() == nbL) break; + } + //std::cout << endl; + return L; + } + +}; //class Witness_complex + + +} // namespace Guhdi + +#endif -- cgit v1.2.3 From 5b97c28ac4414198458de285768460500531e7ec Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 23 Mar 2015 19:11:13 +0000 Subject: Adding everything to the simplex tree, but no more segmentation fault. 500th commit :-) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@500 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2f8d28811e6801ba18f53ca627a3839878c46708 --- src/Witness_complex/example/simple_witness_complex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Witness_complex/example/simple_witness_complex.cpp b/src/Witness_complex/example/simple_witness_complex.cpp index 6c70d300..7a46ffb3 100644 --- a/src/Witness_complex/example/simple_witness_complex.cpp +++ b/src/Witness_complex/example/simple_witness_complex.cpp @@ -44,7 +44,7 @@ int main (int argc, char * const argv[]) typeVectorVertex witness6 = {0,5,6,1,2,3,4}; KNN.push_back(witness6 ); typeVectorVertex witness7 = {2,6,4,5,3,1,0}; KNN.push_back(witness7 ); typeVectorVertex witness8 = {1,2,5,4,3,6,0}; KNN.push_back(witness8 ); - typeVectorVertex witness9 = {3,4,5,2,6,3,4}; KNN.push_back(witness9 ); + typeVectorVertex witness9 = {3,4,0,6,5,1,2}; KNN.push_back(witness9 ); typeVectorVertex witness10 = {5,0,1,3,6,2,4}; KNN.push_back(witness10); typeVectorVertex witness11 = {5,6,1,0,2,3,4}; KNN.push_back(witness11); typeVectorVertex witness12 = {1,6,0,5,2,3,4}; KNN.push_back(witness12); -- cgit v1.2.3 From b33bcf4bb496870b73ee6c4783777bf794e28fb7 Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 23 Mar 2015 19:16:09 +0000 Subject: Prevented a possible bug in witness_complex git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@501 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fa192bb3623622dde84686e8eaa36d2cc51db2c5 --- src/Witness_complex/include/gudhi/Witness_complex1.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex1.h b/src/Witness_complex/include/gudhi/Witness_complex1.h index 911dcbe7..acb83647 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex1.h +++ b/src/Witness_complex/include/gudhi/Witness_complex1.h @@ -265,10 +265,10 @@ void witness_complex(KNearestNeighbours & knn) simplex_vector.push_back(knn[*it][i]); } returnValue = insert_simplex(simplex_vector,0.0); + it++ } else - active_w.erase(it); //First increase the iterator and then erase the previous element - it++; + active_w.erase(it++); //First increase the iterator and then erase the previous element } print_sc(root()); k++; -- cgit v1.2.3 From 1ec3e1ae82dab1109ce871f690df716fb05c6a16 Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 24 Mar 2015 12:31:43 +0000 Subject: Now at every loop curr_sibl to root() as it should git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@502 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 618fbf7be18e0caa150132a63466d77205634479 --- src/Witness_complex/include/gudhi/Witness_complex1.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex1.h b/src/Witness_complex/include/gudhi/Witness_complex1.h index acb83647..6950c3bf 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex1.h +++ b/src/Witness_complex/include/gudhi/Witness_complex1.h @@ -265,12 +265,12 @@ void witness_complex(KNearestNeighbours & knn) simplex_vector.push_back(knn[*it][i]); } returnValue = insert_simplex(simplex_vector,0.0); - it++ + it++; } else active_w.erase(it++); //First increase the iterator and then erase the previous element + print_sc(root()); std::cout << std::endl; } - print_sc(root()); k++; } } @@ -326,16 +326,28 @@ private: for (int i = 0; i != k+1; ++i) { curr_sh = sh_bup; + curr_sibl = root(); if (knn[witness_id][i] != inserted_vertex) { for (int j = 0; j != k+1; ++j) { if (j != i) { + std::cout << "+++ We are at vertex=" << knn[witness_id][j] << std::endl; if (curr_sibl->find(knn[witness_id][j]) == null_simplex()) return false; + std::cout << "++++ the simplex is there\n"; curr_sh = curr_sibl->find(knn[witness_id][j]); - curr_sibl = self_siblings(curr_sh); + std::cout << "++++ curr_sh affectation is OK\n"; + if (has_children(curr_sh)) + curr_sibl = curr_sh->second.children(); + else + if (j < k || (j < k-1 && i == k)) + { + std::cout << "++++ the values: j=" << j << ", k=" << k << std::endl; + return false; + } + std::cout << "++++ finished loop safely\n"; }//endif j!=i }//endfor }//endif -- cgit v1.2.3 From 932b79f06816cf9425f9ff37e09ee5daf2c65597 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 25 Mar 2015 15:36:42 +0000 Subject: witness_complex worked on a small example git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@506 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 77a0284610e0376a827adfe516aeedfcd634348d --- .../include/gudhi/Witness_complex1.h | 47 +++++++++++++++++----- 1 file changed, 37 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex1.h b/src/Witness_complex/include/gudhi/Witness_complex1.h index 49ba7529..5333e5a8 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex1.h +++ b/src/Witness_complex/include/gudhi/Witness_complex1.h @@ -313,6 +313,8 @@ private: * The only purpose is to test if the witness is still active or not. * Assuming here that the list of the first k witnessed landmarks is sorted */ + + /* template< typename KNearestNeighbours > bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) { @@ -334,19 +336,17 @@ private: if (j != i) { std::cout << "+++ We are at vertex=" << knn[witness_id][j] << std::endl; - if (curr_sibl->members().find(knn[witness_id][j]) == null_simplex()) + if (curr_sibl->find(knn[witness_id][j]) == null_simplex()) return false; std::cout << "++++ the simplex is there\n"; - curr_sh = curr_sibl->members().find(knn[witness_id][j]); + curr_sh = curr_sibl->find(knn[witness_id][j]); std::cout << "++++ curr_sh affectation is OK\n"; - if (has_children(curr_sh)) - curr_sibl = curr_sh->second.children(); - else - if (j < k || (j < k-1 && i == k)) - { - std::cout << "++++ the values: j=" << j << ", k=" << k << std::endl; - return false; - } + if (!has_children(curr_sh) && (j < k || (j < k-1 && i == k))) + { + std::cout << "++++ the values: j=" << j << ", k=" << k << std::endl; + return false; + } + curr_sibl = curr_sh->second.children(); std::cout << "++++ finished loop safely\n"; }//endif j!=i }//endfor @@ -354,6 +354,33 @@ private: } //endfor return true; } + */ + template + bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) + { + std::cout << "All face in with the landmark " << inserted_vertex << std::endl; + std::vector< VertexHandle > facet; + //VertexHandle curr_vh = curr_sh->first; + // CHECK ALL THE FACETS + for (int i = 0; i != k+1; ++i) + { + if (knn[witness_id][i] != inserted_vertex) + { + facet = {}; + for (int j = 0; j != k+1; ++j) + { + if (j != i) + { + facet.push_back(knn[witness_id][j]); + } + }//endfor + if (find(facet) == null_simplex()) + return false; + std::cout << "++++ finished loop safely\n"; + }//endif + } //endfor + return true; + } /** * \brief Permutes the vector in such a way that the landmarks appear first -- cgit v1.2.3 From db7c80ba7f521ab63af8c2759a76ea1f0c27e525 Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 26 Mar 2015 10:02:13 +0000 Subject: witness_complex_from_file finally compiles git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@507 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 86f8c736d4a5260a54e58ce2deb4045d27bd3524 --- src/Witness_complex/example/CMakeLists.txt | 4 +- .../include/gudhi/Witness_complex.h | 2 +- .../include/gudhi/Witness_complex1.h | 220 +++++++++------------ 3 files changed, 102 insertions(+), 124 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index d02522f8..74007c65 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -3,7 +3,9 @@ project(GUDHIWitnessComplex) add_executable ( simple_witness_complex simple_witness_complex.cpp ) add_test(simple_witness_complex ${CMAKE_CURRENT_BINARY_DIR}/simple_witness_complex) - + +add_executable( witness_complex_from_file witness_complex_from_file.cpp ) +add_test( witness_complex_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 ) # An example with Simplex-tree using CGAL alpha_shapes_3 #if(GMP_FOUND AND CGAL_FOUND) diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index c6968e44..8bc04022 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -373,7 +373,7 @@ private: void furthestPoints(Point_Vector &W, int nbP, std::string file_land, int dim, int nbL, Point_Vector &L) { - //std::cout << "Enter furthestPoints "<< endl; + std::cout << "Enter furthestPoints "<< std::endl; //Point_Vector *L = new Point_Vector(); double density = 5.; int current_number_of_landmarks=0; diff --git a/src/Witness_complex/include/gudhi/Witness_complex1.h b/src/Witness_complex/include/gudhi/Witness_complex1.h index 5333e5a8..e1e81b0f 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex1.h +++ b/src/Witness_complex/include/gudhi/Witness_complex1.h @@ -32,6 +32,7 @@ #include "gudhi/Simplex_tree.h" #include #include +#include #include #include @@ -184,97 +185,75 @@ void witness_complex(KNearestNeighbours & knn) print_sc(root()); std::cout << std::endl; int u,v; // two extremities of an edge if (nbL > 1) // if the supposed dimension of the complex is >0 - /* - // THE BUGGY CODE - for (int i=0; i != nbW; ++i) { + { + for (int i=0; i != nbW; ++i) + { // initial fill of active witnesses list u = knn[i][0]; v = knn[i][1]; //Siblings * curr_sib = &root_; //vh = (Vertex_handle)i; vv = {u,v}; - counter++; - returnValue = this->insert_simplex(vv,Filtration_value((double)counter)); - //std::cout << "Null simplex is " << null_simplex()->first << std::endl; - if (returnValue.first != null_simplex()) + returnValue = this->insert_simplex(vv,Filtration_value(0.0)); + print_sc(root()); std::cout << std::endl; + //std::cout << "Added edges" << std::endl; + } + //print_sc(root()); + for (int i=0; i != nbW; ++i) + { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + if ( u > v) { - active_w.push_back(*(new Active_witness(i,v,returnValue.first))); + u = v; + v = knn[i][0]; + knn[i][0] = knn[i][1]; + knn[i][1] = v; } - for (typename ActiveWitnessList::iterator it1 = active_w.begin(); it1 != active_w.end(); ++it1) - std::cout << it1->simplex_handle->first << " "; - std::cout << std::endl; - //Simplex_handle sh = root_.members_.begin()+u; - //active_w.push_front(i); - } - */ - for (int i=0; i != nbW; ++i) { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - //Siblings * curr_sib = &root_; - //vh = (Vertex_handle)i; - vv = {u,v}; - returnValue = this->insert_simplex(vv,Filtration_value(0.0)); - print_sc(root()); std::cout << std::endl; - //std::cout << "Added edges" << std::endl; - } - //print_sc(root()); - for (int i=0; i != nbW; ++i) { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - if ( u > v) { - u = v; - v = knn[i][0]; - knn[i][0] = knn[i][1]; - knn[i][1] = v; + Simplex_handle sh; + vv = {u,v}; + sh = (root()->find(u))->second.children()->find(v); + active_w.push_back(i); } - Simplex_handle sh; - vv = {u,v}; - sh = (root()->find(u))->second.children()->find(v); - - active_w.push_back(i); - /*for (typename ActiveWitnessList::iterator it1 = active_w.begin(); it1 != active_w.end(); ++it1) - std::cout << it1->simplex->first << " "; - std::cout << std::endl; */ } - std::cout << "Successfully added edges" << std::endl; - while (!active_w.empty() && k+1 < nbL ) { - std::cout << "Started the step k=" << k << std::endl; + while (!active_w.empty() && k+1 < nbL ) + { + std::cout << "Started the step k=" << k << std::endl; typename ActiveWitnessList::iterator it = active_w.begin(); - while (it != active_w.end()) { + while (it != active_w.end()) + { typeVectorVertex simplex_vector; /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/ // First sort the first k landmarks - int i = k; - int temp_swap; VertexHandle inserted_vertex = knn[*it][k]; - while (i>0 && knn[*it][i-1] > knn[*it][i]) - { - temp_swap = knn[*it][i]; - knn[*it][i] = knn[*it][i-1]; - knn[*it][i-1] = temp_swap; - i--; - } bool ok = all_faces_in(knn, *it, k, inserted_vertex); if (ok) { - for (i = 0; i != k+1; ++i) - { - simplex_vector.push_back(knn[*it][i]); - } + for (int i = 0; i != k+1; ++i) + simplex_vector.push_back(knn[*it][i]); returnValue = insert_simplex(simplex_vector,0.0); it++; } else active_w.erase(it++); //First increase the iterator and then erase the previous element print_sc(root()); std::cout << std::endl; - } + } k++; } } + void witness_complex_from_file(std::string file_name, int nbL) + { + //READ THE FILE INTO A POINT VECTOR + std::vector< std::vector< double > > point_vector; + read_points(file_name, point_vector); + std::vector > WL; + furthestPoints(point_vector, point_vector.size(), nbL, WL); + witness_complex(WL); + } + private: void print_sc(Siblings * sibl) @@ -308,53 +287,6 @@ private: std::cout << ")"; } - - /** Check if all the facets of a simplex we are going to insert are in the simplex tree or not. - * The only purpose is to test if the witness is still active or not. - * Assuming here that the list of the first k witnessed landmarks is sorted - */ - - /* - template< typename KNearestNeighbours > - bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) - { - std::cout << "All face in with the landmark " << inserted_vertex << std::endl; - //std::list< VertexHandle > suffix; - Simplex_handle curr_sh = root()->find(knn[witness_id][0]); - Siblings * curr_sibl = root(); - //VertexHandle curr_vh = curr_sh->first; - // CHECK ALL THE FACETS - Simplex_handle sh_bup = curr_sh; // the first vertex lexicographicly - for (int i = 0; i != k+1; ++i) - { - curr_sh = sh_bup; - curr_sibl = root(); - if (knn[witness_id][i] != inserted_vertex) - { - for (int j = 0; j != k+1; ++j) - { - if (j != i) - { - std::cout << "+++ We are at vertex=" << knn[witness_id][j] << std::endl; - if (curr_sibl->find(knn[witness_id][j]) == null_simplex()) - return false; - std::cout << "++++ the simplex is there\n"; - curr_sh = curr_sibl->find(knn[witness_id][j]); - std::cout << "++++ curr_sh affectation is OK\n"; - if (!has_children(curr_sh) && (j < k || (j < k-1 && i == k))) - { - std::cout << "++++ the values: j=" << j << ", k=" << k << std::endl; - return false; - } - curr_sibl = curr_sh->second.children(); - std::cout << "++++ finished loop safely\n"; - }//endif j!=i - }//endfor - }//endif - } //endfor - return true; - } - */ template bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) { @@ -384,30 +316,73 @@ private: /** * \brief Permutes the vector in such a way that the landmarks appear first + * \arg W is the vector of points which will be the witnesses + * \arg nbP is the number of witnesses + * \arg nbL is the number of landmarks + * \arg WL is the matrix of the nearest landmarks with respect to witnesses (output) */ - void furthestPoints(Point_Vector &W, int nbP, std::string file_land, int dim, int nbL, Point_Vector &L) + template + void furthestPoints(Point_Vector &W, int nbP, int nbL, KNearestNeighbours &WL) + //void furthestPoints(Point_Vector &W, int nbP, int nbL, Point_Vector &L) { - //std::cout << "Enter furthestPoints "<< endl; - //Point_Vector *L = new Point_Vector(); - double density = 5.; + std::cout << "Enter furthestPoints "<< std::endl; + // What is density and why we need it. + // basically it is the stop indicator for "no more landmarks" + + //double density = 5.; + std::vector< std::vector > wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks + std::vector< int > chosen_landmarks; // landmark list + WL = KNearestNeighbours(nbP,std::vector()); //nbP copies of empty vectors int current_number_of_landmarks=0; - double curr_max_dist; + double curr_max_dist = 0; double curr_dist; - double mindist = 10005.; + //double infty = std::numeric_limits::infinity(); + // double mindist = infty; int curr_max_w=0; - int curr_w=0; + int j; + int temp_swap_int; + double temp_swap_double; + + //CHOICE OF THE FIRST LANDMARK + std::cout << "Enter the first landmark stage\n"; srand(354698); int rand_int = rand()% nbP; - //std::cout << rand_int << endl; - L.push_back(W[rand_int]);// first landmark is random - current_number_of_landmarks++; + curr_max_w = rand_int; + + for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + { + chosen_landmarks.push_back(curr_max_w); // first landmark is random + for (auto v: WL) + v.push_back(current_number_of_landmarks); + for (unsigned int i = 0; i < wit_land_dist.size(); ++i) + { + curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); + wit_land_dist[i].push_back(curr_dist); + if (curr_dist > curr_max_dist) + { + curr_max_dist = curr_dist; + curr_max_w = i; + } + j = current_number_of_landmarks; + while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) + { + temp_swap_int = WL[i][j]; + WL[i][j] = WL[i][j-1]; + WL[i][j-1] = temp_swap_int; + temp_swap_double = wit_land_dist[i][j]; + wit_land_dist[i][j] = wit_land_dist[i][j-1]; + wit_land_dist[i][j-1] = temp_swap_double; + } + } + } + /* while (1) { curr_w = 0; curr_max_dist = -1; for(Point_Vector::iterator itW = W.begin(); itW != W.end(); itW++) { //compute distance from w and L - mindist = 100000.; + mindist = infty; for(Point_Vector::iterator itL = L.begin(); itL != L.end(); itL++) { //curr_dist = distPoints(*itW,*itL); curr_dist = euclidean_distance(*itW,*itL); @@ -423,12 +398,13 @@ private: } L.push_back(W[curr_max_w]); current_number_of_landmarks++; - density = sqrt(curr_max_dist); + //density = sqrt(curr_max_dist); //std::cout << "[" << current_number_of_landmarks << ":" << density <<"] "; if(L.size() == nbL) break; } + */ //std::cout << endl; - return L; + //return L; } }; //class Witness_complex -- cgit v1.2.3 From 9c81b9f5e5308091e9f10d5df4bfc6fd8f303b12 Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 26 Mar 2015 12:59:39 +0000 Subject: witness_complex_from_file works on small examples + corrected a small bug in witness_complex git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@508 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3294e22959ca0c5f43a843e851870edfce0999ad --- .../include/gudhi/Witness_complex1.h | 82 +++++++++++++++++----- 1 file changed, 65 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex1.h b/src/Witness_complex/include/gudhi/Witness_complex1.h index e1e81b0f..c9d421c4 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex1.h +++ b/src/Witness_complex/include/gudhi/Witness_complex1.h @@ -180,9 +180,9 @@ void witness_complex(KNearestNeighbours & knn) } //vv = {0}; //returnValue = insert_simplex(vv,Filtration_value(0.0)); - std::cout << "Successfully added landmarks" << std::endl; + //std::cout << "Successfully added landmarks" << std::endl; // PRINT2 - print_sc(root()); std::cout << std::endl; + //print_sc(root()); std::cout << std::endl; int u,v; // two extremities of an edge if (nbL > 1) // if the supposed dimension of the complex is >0 { @@ -195,7 +195,7 @@ void witness_complex(KNearestNeighbours & knn) //vh = (Vertex_handle)i; vv = {u,v}; returnValue = this->insert_simplex(vv,Filtration_value(0.0)); - print_sc(root()); std::cout << std::endl; + //print_sc(root()); std::cout << std::endl; //std::cout << "Added edges" << std::endl; } //print_sc(root()); @@ -217,10 +217,10 @@ void witness_complex(KNearestNeighbours & knn) active_w.push_back(i); } } - std::cout << "Successfully added edges" << std::endl; - while (!active_w.empty() && k+1 < nbL ) + //std::cout << "Successfully added edges" << std::endl; + while (!active_w.empty() && k < nbL ) { - std::cout << "Started the step k=" << k << std::endl; + //std::cout << "Started the step k=" << k << std::endl; typename ActiveWitnessList::iterator it = active_w.begin(); while (it != active_w.end()) { @@ -238,17 +238,17 @@ void witness_complex(KNearestNeighbours & knn) } else active_w.erase(it++); //First increase the iterator and then erase the previous element - print_sc(root()); std::cout << std::endl; } k++; - } + } + print_sc(root()); std::cout << std::endl; } - void witness_complex_from_file(std::string file_name, int nbL) + void witness_complex_from_file(Point_Vector point_vector, int nbL) { //READ THE FILE INTO A POINT VECTOR - std::vector< std::vector< double > > point_vector; - read_points(file_name, point_vector); + //std::vector< std::vector< double > > point_vector; + //read_points(file_name, point_vector); std::vector > WL; furthestPoints(point_vector, point_vector.size(), nbL, WL); witness_complex(WL); @@ -290,7 +290,7 @@ private: template bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) { - std::cout << "All face in with the landmark " << inserted_vertex << std::endl; + //std::cout << "All face in with the landmark " << inserted_vertex << std::endl; std::vector< VertexHandle > facet; //VertexHandle curr_vh = curr_sh->first; // CHECK ALL THE FACETS @@ -314,6 +314,38 @@ private: return true; } + template + void print_vector(std::vector v) + { + std::cout << "["; + if (!v.empty()) + { + std::cout << *(v.begin()); + for (auto it = v.begin()+1; it != v.end(); ++it) + { + std::cout << ","; + std::cout << *it; + } + } + std::cout << "]"; + } + + template + void print_vvector(std::vector< std::vector > vv) + { + std::cout << "["; + if (!vv.empty()) + { + print_vector(*(vv.begin())); + for (auto it = vv.begin()+1; it != vv.end(); ++it) + { + std::cout << ","; + print_vector(*it); + } + } + std::cout << "]\n"; + } + /** * \brief Permutes the vector in such a way that the landmarks appear first * \arg W is the vector of points which will be the witnesses @@ -329,7 +361,7 @@ private: std::cout << "Enter furthestPoints "<< std::endl; // What is density and why we need it. // basically it is the stop indicator for "no more landmarks" - + //std::cout << "W="; print_vvector(W); //double density = 5.; std::vector< std::vector > wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks std::vector< int > chosen_landmarks; // landmark list @@ -345,26 +377,41 @@ private: double temp_swap_double; //CHOICE OF THE FIRST LANDMARK - std::cout << "Enter the first landmark stage\n"; + //std::cout << "Enter the first landmark stage\n"; srand(354698); int rand_int = rand()% nbP; curr_max_w = rand_int; for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) { - chosen_landmarks.push_back(curr_max_w); // first landmark is random + chosen_landmarks.push_back(curr_max_w); + //std::cout << "Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; + //std::cout << "WL="; print_vvector(WL); + //std::cout << "WLD="; print_vvector(wit_land_dist); + //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; for (auto v: WL) v.push_back(current_number_of_landmarks); - for (unsigned int i = 0; i < wit_land_dist.size(); ++i) + for (int i = 0; i < nbP; ++i) { - curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); + //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; + //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; + if (i != chosen_landmarks[current_number_of_landmarks]) + curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); + else + curr_dist = 0; + //std::cout << "The problem is not in distance function\n"; wit_land_dist[i].push_back(curr_dist); + WL[i].push_back(current_number_of_landmarks); + //std::cout << "Push't back\n"; if (curr_dist > curr_max_dist) { curr_max_dist = curr_dist; curr_max_w = i; } j = current_number_of_landmarks; + //std::cout << "First half complete\n"; + //std::cout << "WL="; print_vvector(WL); + //std::cout << "WLD="; print_vvector(wit_land_dist); while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) { temp_swap_int = WL[i][j]; @@ -374,6 +421,7 @@ private: wit_land_dist[i][j] = wit_land_dist[i][j-1]; wit_land_dist[i][j-1] = temp_swap_double; } + //std::cout << "End loop\n"; } } /* -- cgit v1.2.3 From c41277f640fa6d59af11970e7c281ff9d5221d06 Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 26 Mar 2015 13:43:55 +0000 Subject: fixed bug in landmark sorting + fixed bug in landmark choice git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@509 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 862c72f48dd6fe24e4e6c02a9cda5d99645c3f71 --- .../include/gudhi/Witness_complex1.h | 29 ++++++++++++++-------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex1.h b/src/Witness_complex/include/gudhi/Witness_complex1.h index c9d421c4..f75c3e66 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex1.h +++ b/src/Witness_complex/include/gudhi/Witness_complex1.h @@ -308,7 +308,7 @@ private: }//endfor if (find(facet) == null_simplex()) return false; - std::cout << "++++ finished loop safely\n"; + //std::cout << "++++ finished loop safely\n"; }//endif } //endfor return true; @@ -365,11 +365,13 @@ private: //double density = 5.; std::vector< std::vector > wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks std::vector< int > chosen_landmarks; // landmark list + WL = KNearestNeighbours(nbP,std::vector()); //nbP copies of empty vectors int current_number_of_landmarks=0; double curr_max_dist = 0; double curr_dist; - //double infty = std::numeric_limits::infinity(); + double infty = std::numeric_limits::infinity(); + std::vector< double > dist_to_L(nbP,infty); // double mindist = infty; int curr_max_w=0; int j; @@ -385,15 +387,16 @@ private: for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) { chosen_landmarks.push_back(curr_max_w); - //std::cout << "Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; - //std::cout << "WL="; print_vvector(WL); - //std::cout << "WLD="; print_vvector(wit_land_dist); - //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; + curr_max_dist = 0; + std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; + std::cout << "WL="; print_vvector(WL); + std::cout << "WLD="; print_vvector(wit_land_dist); + std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; for (auto v: WL) v.push_back(current_number_of_landmarks); for (int i = 0; i < nbP; ++i) { - //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; + std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; if (i != chosen_landmarks[current_number_of_landmarks]) curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); @@ -403,15 +406,15 @@ private: wit_land_dist[i].push_back(curr_dist); WL[i].push_back(current_number_of_landmarks); //std::cout << "Push't back\n"; - if (curr_dist > curr_max_dist) + if (curr_dist < dist_to_L[i]) + dist_to_L[i] = curr_dist; + if (dist_to_L[i] > curr_max_dist) { curr_max_dist = curr_dist; curr_max_w = i; } j = current_number_of_landmarks; //std::cout << "First half complete\n"; - //std::cout << "WL="; print_vvector(WL); - //std::cout << "WLD="; print_vvector(wit_land_dist); while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) { temp_swap_int = WL[i][j]; @@ -420,8 +423,12 @@ private: temp_swap_double = wit_land_dist[i][j]; wit_land_dist[i][j] = wit_land_dist[i][j-1]; wit_land_dist[i][j-1] = temp_swap_double; + --j; } - //std::cout << "End loop\n"; + std::cout << "result WL="; print_vvector(WL); + std::cout << "result WLD="; print_vvector(wit_land_dist); + + std::cout << "End loop\n"; } } /* -- cgit v1.2.3 From 4b8b6dce9c433b8a0081d3310a123ee2abda76c8 Mon Sep 17 00:00:00 2001 From: skachano Date: Fri, 27 Mar 2015 13:09:02 +0000 Subject: Added witness_complex_from_file git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@510 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 22b61b82bae5fa75545c1eff22619426d5b8b469 --- .../example/witness_complex_from_file.cpp | 89 ++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/Witness_complex/example/witness_complex_from_file.cpp (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp new file mode 100644 index 00000000..a0e192f7 --- /dev/null +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -0,0 +1,89 @@ +/* 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): Vincent Rouvreau + * + * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (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 "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex1.h" + + +using namespace Gudhi; + +typedef std::vector< Vertex_handle > typeVectorVertex; +typedef std::vector< std::vector > Point_Vector; +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , std::vector< std::vector< double > > & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + if (point.size() != 1) + points.push_back(point); + } + in_file.close(); +} + +int main (int argc, char * const argv[]) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] + << " path_to_point_file nbL \n"; + return 0; + } + std::string file_name = argv[1]; + int nbL = atoi(argv[2]); + + clock_t start, end; + //Construct the Simplex Tree + Witness_complex<> witnessComplex; + + std::cout << "Let the carnage begin!\n"; + start = clock(); + Point_Vector point_vector; + read_points_cust(file_name, point_vector); + witnessComplex.witness_complex_from_file(point_vector, nbL); + end = clock(); + std::cout << "Howdy world! The process took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + +} -- cgit v1.2.3 From dfc3485f4a497c8dca7b160f5eb76a17c3556045 Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 31 Mar 2015 09:29:45 +0000 Subject: Added a bit more of comments git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@518 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b00e0c8a2a48efd443c943d3b76a12c5581e79bc --- .../include/gudhi/Witness_complex.h | 631 ++++++++++----------- 1 file changed, 295 insertions(+), 336 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 8bc04022..57b89af8 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -32,388 +32,347 @@ #include "gudhi/Simplex_tree.h" #include #include +#include #include #include namespace Gudhi { - /* -template -class Simplex_tree; - */ - /* - typedef int Witness_id; -typedef int Landmark_id; -typedef int Simplex_handle; //index in vector complex_ - */ + /** \addtogroup simplex_tree + * Witness complex is a simplicial complex defined on two sets of points in \f$\mathbf{R}^D\f$: + * \f$W\f$ set of witnesses and \f$L \subseteq W\f$ set of landmarks. The simplices are based on points in \f$L\f$ + * and a simplex belongs to the witness complex if and only if it is witnessed (there exists a point \f$w \in W\f$ such that + * w is closer to the vertices of this simplex than others) and all of its faces are witnessed as well. + */ + template + class Witness_complex: public Simplex_tree<> { -template -class Witness_complex: public Simplex_tree<> { - //class Witness_complex: public Simplex_tree { - //class Witness_complex { -private: - - /* - template < typename Witness_id = int, - typename Landmark_id = int, - typename Simplex_handle = Simplex_handle > - struct Active_witness { - Witness_id witness_id; - Landmark_id landmark_id; - Simplex_handle simplex_handle; - }; - */ + private: + + struct Active_witness { + int witness_id; + int landmark_id; + Simplex_handle simplex_handle; -struct Active_witness { - int witness_id; - int landmark_id; - Simplex_handle simplex_handle; - - Active_witness(int witness_id_, int landmark_id_, Simplex_handle simplex_handle_) - : witness_id(witness_id_), - landmark_id(landmark_id_), - simplex_handle(simplex_handle_) - {} -}; + Active_witness(int witness_id_, int landmark_id_, Simplex_handle simplex_handle_) + : witness_id(witness_id_), + landmark_id(landmark_id_), + simplex_handle(simplex_handle_) + {} + }; -public: - -//Simplex_tree<> st; - -// typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; -// typedef boost::iterator_range Boundary_simplex_range; - -// typedef typename std::vector< Simplex_handle >::iterator Skeleton_simplex_iterator; -// typedef boost::iterator_range< Skeleton_simplex_iterator > Skeleton_simplex_range; - -// typedef IndexingTag Indexing_tag; - /** \brief Type for the value of the filtration function. - * - * Must be comparable with <. */ -// typedef FiltrationValue Filtration_value; - /** \brief Key associated to each simplex. - * - * Must be a signed integer type. */ -// typedef SimplexKey Simplex_key; - - /** \brief Type for the vertex handle. - * - * Must be a signed integer type. It admits a total order <. */ - typedef VertexHandle Vertex_handle; - - /* Type of node in the simplex tree. */ - typedef Simplex_tree_node_explicit_storage Node; - /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ - typedef typename boost::container::flat_map Dictionary; - typedef typename Dictionary::iterator Simplex_handle; + public: -/* - friend class Simplex_tree_node_explicit_storage< Simplex_tree >; - friend class Simplex_tree_siblings< Simplex_tree, Dictionary>; - friend class Simplex_tree_simplex_vertex_iterator< Simplex_tree >; - friend class Simplex_tree_boundary_simplex_iterator< Simplex_tree >; - friend class Simplex_tree_complex_simplex_iterator< Simplex_tree >; - friend class Simplex_tree_skeleton_simplex_iterator< Simplex_tree >; -*/ - - /* \brief Set of nodes sharing a same parent in the simplex tree. */ - /* \brief Set of nodes sharing a same parent in the simplex tree. */ -// typedef Simplex_tree_siblings Siblings; - - - typedef std::vector< double > Point_t; - typedef std::vector< Point_t > Point_Vector; - - typedef std::vector< Vertex_handle > typeVectorVertex; - typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; - typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; - - typedef int Witness_id; - typedef int Landmark_id; - typedef std::list< Active_witness > ActiveWitnessList; - -/** - * /brief Iterative construction of the witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks}. - * Landmarks are supposed to be in [0,nbL-1] - */ - + + /** \brief Type for the vertex handle. + * + * Must be a signed integer type. It admits a total order <. */ + typedef VertexHandle Vertex_handle; + + /* Type of node in the simplex tree. */ + typedef Simplex_tree_node_explicit_storage Node; + /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ + typedef typename boost::container::flat_map Dictionary; + typedef typename Dictionary::iterator Simplex_handle; -template< typename KNearestNeighbours > -void witness_complex(KNearestNeighbours & knn) -//void witness_complex(std::vector< std::vector< Vertex_handle > > & knn) -{ - std::cout << "**Start the procedure witness_complex" << std::endl; - int k=2; /* current dimension in iterative construction */ - //Construction of the active witness list - int nbW = knn.size(); - int nbL = knn.at(0).size(); - //VertexHandle vh; - typeVectorVertex vv; - typeSimplex simplex; - typePairSimplexBool returnValue; - int counter = 0; - /* The list of still useful witnesses - * it will diminuish in the course of iterations + typedef std::vector< double > Point_t; + typedef std::vector< Point_t > Point_Vector; + + typedef std::vector< Vertex_handle > typeVectorVertex; + typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; + typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + + typedef int Witness_id; + typedef int Landmark_id; + typedef std::list< Vertex_handle > ActiveWitnessList; + + /** + * /brief Iterative construction of the witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks}. + * Landmarks are supposed to be in [0,nbL-1] */ - ActiveWitnessList active_w;// = new ActiveWitnessList(); - for (int i=0; i != nbL; ++i) { + + template< typename KNearestNeighbours > + void witness_complex(KNearestNeighbours & knn) + //void witness_complex(std::vector< std::vector< Vertex_handle > > & knn) + { + std::cout << "**Start the procedure witness_complex" << std::endl; + int k=2; /* current dimension in iterative construction */ + //Construction of the active witness list + int nbW = knn.size(); + int nbL = knn.at(0).size(); + //VertexHandle vh; + typeVectorVertex vv; + typeSimplex simplex; + typePairSimplexBool returnValue; + int counter = 0; + /* The list of still useful witnesses + * it will diminuish in the course of iterations + */ + ActiveWitnessList active_w;// = new ActiveWitnessList(); + for (int i=0; i != nbL; ++i) { // initial fill of 0-dimensional simplices // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore - //vh = (Vertex_handle)i; - counter++; + counter++; vv = {i}; /* TODO Filtration */ - //simplex = std::make_pair(vv, Filtration_value(0.0)); - //returnValue = this->insert_simplex(simplex.first, simplex.second); returnValue = insert_simplex(vv, Filtration_value(0.0)); /* TODO Error if not inserted : normally no need here though*/ - } - //vv = {0}; - //returnValue = insert_simplex(vv,Filtration_value(0.0)); - std::cout << "Successfully added landmarks" << std::endl; - // PRINT2 - print_sc(root()); std::cout << std::endl; - int u,v; // two extremities of an edge - if (nbL > 1) // if the supposed dimension of the complex is >0 - /* - // THE BUGGY CODE - for (int i=0; i != nbW; ++i) { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - //Siblings * curr_sib = &root_; - //vh = (Vertex_handle)i; - vv = {u,v}; - counter++; - returnValue = this->insert_simplex(vv,Filtration_value((double)counter)); - //std::cout << "Null simplex is " << null_simplex()->first << std::endl; - if (returnValue.first != null_simplex()) - { - active_w.push_back(*(new Active_witness(i,v,returnValue.first))); - } - for (typename ActiveWitnessList::iterator it1 = active_w.begin(); it1 != active_w.end(); ++it1) - std::cout << it1->simplex_handle->first << " "; - std::cout << std::endl; - //Simplex_handle sh = root_.members_.begin()+u; - //active_w.push_front(i); - } - */ - for (int i=0; i != nbW; ++i) { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - //Siblings * curr_sib = &root_; - //vh = (Vertex_handle)i; - vv = {u,v}; - returnValue = this->insert_simplex(vv,Filtration_value(0.0)); - print_sc(root()); std::cout << std::endl; - //std::cout << "Added edges" << std::endl; } - //print_sc(root()); - for (int i=0; i != nbW; ++i) { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - if ( u > v) { - u = v; - v = knn[i][0]; + //std::cout << "Successfully added landmarks" << std::endl; + // PRINT2 + //print_sc(root()); std::cout << std::endl; + int u,v; // two extremities of an edge + if (nbL > 1) // if the supposed dimension of the complex is >0 + { + for (int i=0; i != nbW; ++i) + { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + vv = {u,v}; + returnValue = this->insert_simplex(vv,Filtration_value(0.0)); + //print_sc(root()); std::cout << std::endl; + //std::cout << "Added edges" << std::endl; + } + //print_sc(root()); + for (int i=0; i != nbW; ++i) + { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + if ( u > v) + { + u = v; + v = knn[i][0]; + knn[i][0] = knn[i][1]; + knn[i][1] = v; + } + Simplex_handle sh; + vv = {u,v}; + sh = (root()->find(u))->second.children()->find(v); + active_w.push_back(i); + } } - Simplex_handle sh; - vv = {u,v}; - sh = (root()->find(u))->second.children()->find(v); - - active_w.push_back(Active_witness(i,v,sh)); - /*for (typename ActiveWitnessList::iterator it1 = active_w.begin(); it1 != active_w.end(); ++it1) - std::cout << it1->simplex->first << " "; - std::cout << std::endl; */ - } - - std::cout << "Successfully added edges" << std::endl; - while (!active_w.empty() && k+1 < nbL ) { - std::cout << "Started the step k=" << k << std::endl; - typename ActiveWitnessList::iterator it = active_w.begin(); - while (it != active_w.end()) { - typeVectorVertex simplex_vector; - typeVectorVertex suffix; - /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/ - // std::cout << it->simplex->first << std::endl; - bool ok = all_faces_in(knn[it->witness_id][k],it->simplex_handle); - if (ok) - returnValue = insert_simplex(simplex_vector,0.0); - else - active_w.erase(it); //First increase the iterator and then erase the previous element - it++; + //std::cout << "Successfully added edges" << std::endl; + while (!active_w.empty() && k < nbL ) + { + //std::cout << "Started the step k=" << k << std::endl; + typename ActiveWitnessList::iterator it = active_w.begin(); + while (it != active_w.end()) + { + typeVectorVertex simplex_vector; + /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/ + // First sort the first k landmarks + VertexHandle inserted_vertex = knn[*it][k]; + bool ok = all_faces_in(knn, *it, k, inserted_vertex); + if (ok) + { + for (int i = 0; i != k+1; ++i) + simplex_vector.push_back(knn[*it][i]); + returnValue = insert_simplex(simplex_vector,0.0); + it++; + } + else + active_w.erase(it++); //First increase the iterator and then erase the previous element + } + k++; } - k++; - } -} - -private: - - void print_sc(Siblings * sibl) - { - if (sibl == NULL) - std::cout << "&"; - else - print_children(sibl->members_); - } + //print_sc(root()); std::cout << std::endl; + } - void print_children(Dictionary map) + /** \brief Construction of witness complex from points given explicitly + */ + void witness_complex_from_file(Point_Vector point_vector, int nbL) { - std::cout << "("; - if (!map.empty()) - { - std::cout << map.begin()->first; - if (has_children(map.begin())) - print_sc(map.begin()->second.children()); - typename Dictionary::iterator it; - for (it = map.begin()+1; it != map.end(); ++it) - { - std::cout << "," << it->first; - if (has_children(it)) - print_sc(it->second.children()); - } - } - std::cout << ")"; + std::vector > WL; + furthestPoints(point_vector, point_vector.size(), nbL, WL); + witness_complex(WL); } + +private: - - /** Check if all the facets of a simplex we are going to insert are in the simplex tree or not. - * The only purpose is to test if the witness is still active or not. - */ - bool all_faces_in(VertexHandle last, Simplex_handle sh) - { - std::cout << "All face in with the landmark " << last << std::endl; - std::list< VertexHandle > suffix; - Simplex_handle curr_sh = sh; - Siblings * curr_sibl = self_siblings(sh); - VertexHandle curr_vh = curr_sh->first; - while (curr_vh > last) { - std::cout << "We are at " << curr_sh->first << " " << sh->first << "\n"; - suffix.push_front(curr_vh); - //std::cout << "Still fine 1\n"; - curr_vh = curr_sibl->parent(); - //std::cout << "Still fine 2\n"; - curr_sibl = curr_sibl->oncles(); - //std::cout << "Still fine 3\n"; - curr_sh = curr_sibl->find(curr_vh); - //std::cout << "Still fine 4\n"; + /** \brief Print functions + */ + void print_sc(Siblings * sibl) + { + if (sibl == NULL) + std::cout << "&"; + else + print_children(sibl->members_); } - std::cout << "Arrived at the mid-parent" << std::endl; - suffix.push_front(last); - typename std::list< VertexHandle >::iterator itVV = suffix.begin(); - Simplex_handle sh_bup = curr_sh; // Back up the pointer - while (itVV != suffix.end() && curr_sh->second.children()->find(*itVV) != null_simplex()) { - // If the node doesn't exist then stop, else go down the tree - std::cout << "DOWN!" << curr_sh->first << " -> " << *itVV << std::endl; - std::cout << "Children of " << curr_sh->first << " are "; - for (typename Dictionary::iterator itt = curr_sh->second.children()->members_.begin(); itt != curr_sh->second.children()->members_.end(); ++itt) - std::cout << itt->first << ","; - std::cout << std::endl; - curr_sh = curr_sh->second.children()->find(*itVV); - itVV++; + + void print_children(Dictionary map) + { + std::cout << "("; + if (!map.empty()) + { + std::cout << map.begin()->first; + if (has_children(map.begin())) + print_sc(map.begin()->second.children()); + typename Dictionary::iterator it; + for (it = map.begin()+1; it != map.end(); ++it) + { + std::cout << "," << it->first; + if (has_children(it)) + print_sc(it->second.children()); + } + } + std::cout << ")"; } - if (itVV == suffix.end()) { - // the simplex is already in the tree - std::cout << "The simplex is there" << std::endl; + + template + bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) + { + //std::cout << "All face in with the landmark " << inserted_vertex << std::endl; + std::vector< VertexHandle > facet; + //VertexHandle curr_vh = curr_sh->first; + // CHECK ALL THE FACETS + for (int i = 0; i != k+1; ++i) + { + if (knn[witness_id][i] != inserted_vertex) + { + facet = {}; + for (int j = 0; j != k+1; ++j) + { + if (j != i) + { + facet.push_back(knn[witness_id][j]); + } + }//endfor + if (find(facet) == null_simplex()) + return false; + //std::cout << "++++ finished loop safely\n"; + }//endif + } //endfor return true; } - else if (itVV != suffix.end()) { - // the father of the simplex is not in the tree - std::cout << "The father is not there. Deleting witness." << std::endl; - return false; - } - else { - // CHECK ALL THE FACETS - curr_sh = sh_bup; - while (curr_sibl != root()) { - suffix.push_front(curr_vh); - curr_vh = curr_sibl->parent(); - curr_sibl = curr_sibl->oncles(); - curr_sh = curr_sibl->find(curr_vh); + + template + void print_vector(std::vector v) + { + std::cout << "["; + if (!v.empty()) + { + std::cout << *(v.begin()); + for (auto it = v.begin()+1; it != v.end(); ++it) + { + std::cout << ","; + std::cout << *it; + } } - suffix.push_front(curr_vh); - sh_bup = curr_sh; // the first vertex lexicographicly - for (typename std::list< VertexHandle >::iterator itExcl = suffix.begin(); itExcl != suffix.end(); ++itExcl) { - if (*itExcl != last) { - itVV = suffix.begin(); - while (itVV != itExcl) { - if (curr_sibl->find(*itVV) == null_simplex()) - return false; - curr_sh = curr_sibl->find(*itVV); - curr_sibl = self_siblings(curr_sh); - itVV++; - } - itVV++; - while (itVV != suffix.end()) { - if (curr_sibl->find(*itVV) == null_simplex()) - return false; - curr_sh = curr_sibl->find(*itVV); - curr_sibl = self_siblings(curr_sh); - itVV++; - } //endwhile - } //endif - } //endfor - return true; - } //end check all the facets - } - + std::cout << "]"; + } + + template + void print_vvector(std::vector< std::vector > vv) + { + std::cout << "["; + if (!vv.empty()) + { + print_vector(*(vv.begin())); + for (auto it = vv.begin()+1; it != vv.end(); ++it) + { + std::cout << ","; + print_vector(*it); + } + } + std::cout << "]\n"; + } + /** - * \brief Permutes the vector in such a way that the landmarks appear first + * \brief Landmark choice strategy by iteratively adding the landmark the furthest from the + * current landmark set + * \arg W is the vector of points which will be the witnesses + * \arg nbP is the number of witnesses + * \arg nbL is the number of landmarks + * \arg WL is the matrix of the nearest landmarks with respect to witnesses (output) */ - void furthestPoints(Point_Vector &W, int nbP, std::string file_land, int dim, int nbL, Point_Vector &L) + template + void furthestPoints(Point_Vector &W, int nbP, int nbL, KNearestNeighbours &WL) + //void furthestPoints(Point_Vector &W, int nbP, int nbL, Point_Vector &L) { - std::cout << "Enter furthestPoints "<< std::endl; - //Point_Vector *L = new Point_Vector(); - double density = 5.; + //std::cout << "Enter furthestPoints "<< std::endl; + // What is density and why we need it. + // basically it is the stop indicator for "no more landmarks" + //std::cout << "W="; print_vvector(W); + //double density = 5.; + std::vector< std::vector > wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks + std::vector< int > chosen_landmarks; // landmark list + + WL = KNearestNeighbours(nbP,std::vector()); //nbP copies of empty vectors int current_number_of_landmarks=0; - double curr_max_dist; + double curr_max_dist = 0; double curr_dist; - double mindist = 10005.; + double infty = std::numeric_limits::infinity(); + std::vector< double > dist_to_L(nbP,infty); + // double mindist = infty; int curr_max_w=0; - int curr_w=0; + int j; + int temp_swap_int; + double temp_swap_double; + + //CHOICE OF THE FIRST LANDMARK + //std::cout << "Enter the first landmark stage\n"; srand(354698); int rand_int = rand()% nbP; - //std::cout << rand_int << endl; - L.push_back(W[rand_int]);// first landmark is random - current_number_of_landmarks++; - while (1) { - curr_w = 0; - curr_max_dist = -1; - for(Point_Vector::iterator itW = W.begin(); itW != W.end(); itW++) { - //compute distance from w and L - mindist = 100000.; - for(Point_Vector::iterator itL = L.begin(); itL != L.end(); itL++) { - //curr_dist = distPoints(*itW,*itL); - curr_dist = euclidean_distance(*itW,*itL); - if(curr_dist < mindist) { - mindist = curr_dist; + curr_max_w = rand_int; + + for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + { + chosen_landmarks.push_back(curr_max_w); + curr_max_dist = 0; + //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; + //std::cout << "WL="; print_vvector(WL); + //std::cout << "WLD="; print_vvector(wit_land_dist); + //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; + for (auto v: WL) + v.push_back(current_number_of_landmarks); + for (int i = 0; i < nbP; ++i) + { + //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; + //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; + if (i != chosen_landmarks[current_number_of_landmarks]) + curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); + else + curr_dist = 0; + //std::cout << "The problem is not in distance function\n"; + wit_land_dist[i].push_back(curr_dist); + WL[i].push_back(current_number_of_landmarks); + //std::cout << "Push't back\n"; + if (curr_dist < dist_to_L[i]) + dist_to_L[i] = curr_dist; + if (dist_to_L[i] > curr_max_dist) + { + curr_max_dist = curr_dist; + curr_max_w = i; + } + j = current_number_of_landmarks; + //std::cout << "First half complete\n"; + while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) + { + temp_swap_int = WL[i][j]; + WL[i][j] = WL[i][j-1]; + WL[i][j-1] = temp_swap_int; + temp_swap_double = wit_land_dist[i][j]; + wit_land_dist[i][j] = wit_land_dist[i][j-1]; + wit_land_dist[i][j-1] = temp_swap_double; + --j; + } + //std::cout << "result WL="; print_vvector(WL); + //std::cout << "result WLD="; print_vvector(wit_land_dist); + //std::cout << "result distL="; print_vector(dist_to_L); std::cout << std::endl; + //std::cout << "End loop\n"; } - } - if(mindist > curr_max_dist) { - curr_max_w = curr_w; //??? - curr_max_dist = mindist; - } - curr_w++; } - L.push_back(W[curr_max_w]); - current_number_of_landmarks++; - density = sqrt(curr_max_dist); - //std::cout << "[" << current_number_of_landmarks << ":" << density <<"] "; - if(L.size() == nbL) break; - } //std::cout << endl; - return L; } }; //class Witness_complex -- cgit v1.2.3 From 7f864c8d1b8c019d4f239bc343e7a14e5853bf0d Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 31 Mar 2015 12:58:48 +0000 Subject: Wrote code for random landmark choice strategy git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@520 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 079b9ec46dcdd93416315ec101cd4e53b444154f --- .../include/gudhi/Witness_complex.h | 163 +++++-- .../include/gudhi/Witness_complex1.h | 470 --------------------- 2 files changed, 133 insertions(+), 500 deletions(-) delete mode 100644 src/Witness_complex/include/gudhi/Witness_complex1.h (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 57b89af8..d5a35801 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -32,9 +32,10 @@ #include "gudhi/Simplex_tree.h" #include #include +#include #include #include - +#include #include namespace Gudhi { @@ -92,6 +93,30 @@ namespace Gudhi { typedef int Witness_id; typedef int Landmark_id; typedef std::list< Vertex_handle > ActiveWitnessList; + + private: + /** Number of landmarks + */ + int nbL; + /** Desired density + */ + double density; + + public: + + /** \brief Set number of landmarks to nbL_ + */ + void setNbL(int nbL_) + { + nbL = nbL_; + } + + /** \brief Set density to density_ + */ + void setDensity(double density_) + { + density = density_; + } /** * /brief Iterative construction of the witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks}. @@ -106,8 +131,7 @@ namespace Gudhi { int k=2; /* current dimension in iterative construction */ //Construction of the active witness list int nbW = knn.size(); - int nbL = knn.at(0).size(); - //VertexHandle vh; + //int nbL = knn.at(0).size(); typeVectorVertex vv; typeSimplex simplex; typePairSimplexBool returnValue; @@ -184,15 +208,18 @@ namespace Gudhi { } k++; } - //print_sc(root()); std::cout << std::endl; + print_sc(root()); std::cout << std::endl; } /** \brief Construction of witness complex from points given explicitly + * nbL must be set to the right value of landmarks for strategies + * FURTHEST_POINT_STRATEGY and RANDOM_POINT_STRATEGY and + * density must be set to the right value for DENSITY_STRATEGY */ - void witness_complex_from_file(Point_Vector point_vector, int nbL) + void witness_complex_from_points(Point_Vector point_vector) { std::vector > WL; - furthestPoints(point_vector, point_vector.size(), nbL, WL); + landmark_choice_by_random_points(point_vector, point_vector.size(), WL); witness_complex(WL); } @@ -226,7 +253,11 @@ private: } std::cout << ")"; } - + + /** \brief Check if the facets of the k-dimensional simplex witnessed + * by witness witness_id are already in the complex. + * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id + */ template bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) { @@ -296,53 +327,50 @@ private: */ template - void furthestPoints(Point_Vector &W, int nbP, int nbL, KNearestNeighbours &WL) - //void furthestPoints(Point_Vector &W, int nbP, int nbL, Point_Vector &L) + void landmark_choice_by_furthest_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) { - //std::cout << "Enter furthestPoints "<< std::endl; - // What is density and why we need it. - // basically it is the stop indicator for "no more landmarks" + //std::cout << "Enter landmark_choice_by_furthest_points "<< std::endl; //std::cout << "W="; print_vvector(W); //double density = 5.; - std::vector< std::vector > wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks - std::vector< int > chosen_landmarks; // landmark list + Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks + typeVectorVertex chosen_landmarks; // landmark list - WL = KNearestNeighbours(nbP,std::vector()); //nbP copies of empty vectors - int current_number_of_landmarks=0; - double curr_max_dist = 0; - double curr_dist; - double infty = std::numeric_limits::infinity(); - std::vector< double > dist_to_L(nbP,infty); + WL = KNearestNeighbours(nbP,std::vector()); + int current_number_of_landmarks=0; // counter for landmarks + double curr_max_dist = 0; // used for defining the furhest point from L + double curr_dist; // used to stock the distance from the current point to L + double infty = std::numeric_limits::infinity(); // infinity (see next entry) + std::vector< double > dist_to_L(nbP,infty); // vector of current distances to L from points // double mindist = infty; - int curr_max_w=0; + int curr_max_w=0; // the point currently furthest from L int j; - int temp_swap_int; + int temp_swap_int; double temp_swap_double; //CHOICE OF THE FIRST LANDMARK - //std::cout << "Enter the first landmark stage\n"; + std::cout << "Enter the first landmark stage\n"; srand(354698); int rand_int = rand()% nbP; - curr_max_w = rand_int; + curr_max_w = rand_int; //For testing purposes a pseudo-random number is used here for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) { + //curr_max_w at this point is the next landmark chosen_landmarks.push_back(curr_max_w); curr_max_dist = 0; //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; //std::cout << "WL="; print_vvector(WL); //std::cout << "WLD="; print_vvector(wit_land_dist); - //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; + std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; for (auto v: WL) v.push_back(current_number_of_landmarks); for (int i = 0; i < nbP; ++i) { + // iteration on points in W. update of distance vectors + //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; - if (i != chosen_landmarks[current_number_of_landmarks]) - curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); - else - curr_dist = 0; + curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); //std::cout << "The problem is not in distance function\n"; wit_land_dist[i].push_back(curr_dist); WL[i].push_back(current_number_of_landmarks); @@ -358,6 +386,7 @@ private: //std::cout << "First half complete\n"; while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) { + // sort the closest landmark vector for every witness temp_swap_int = WL[i][j]; WL[i][j] = WL[i][j-1]; WL[i][j-1] = temp_swap_int; @@ -374,9 +403,83 @@ private: } //std::cout << endl; } - + + /** \brief Landmark choice strategy by taking random vertices for landmarks. + * + */ + + template + void landmark_choice_by_random_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) + { + //std::cout << "Enter landmark_choice_by_random_points "<< std::endl; + //std::cout << "W="; print_vvector(W); + std::unordered_set< int > chosen_landmarks; // landmark set + + Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks + + WL = KNearestNeighbours(nbP,std::vector()); + int current_number_of_landmarks=0; // counter for landmarks + + srand(24660); + int chosen_landmark = rand()%nbP; + double curr_dist; + + int j; + int temp_swap_int; + double temp_swap_double; + + + for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + { + while (chosen_landmarks.find(chosen_landmark) != chosen_landmarks.end()) + { + srand((int)clock()); + chosen_landmark = rand()% nbP; + //std::cout << chosen_landmark << "\n"; + } + chosen_landmarks.insert(chosen_landmark); + //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; + //std::cout << "WL="; print_vvector(WL); + //std::cout << "WLD="; print_vvector(wit_land_dist); + //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; + for (auto v: WL) + v.push_back(current_number_of_landmarks); + for (int i = 0; i < nbP; ++i) + { + // iteration on points in W. update of distance vectors + + //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; + //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; + curr_dist = euclidean_distance(W[i],W[chosen_landmark]); + //std::cout << "The problem is not in distance function\n"; + wit_land_dist[i].push_back(curr_dist); + WL[i].push_back(current_number_of_landmarks); + //std::cout << "Push't back\n"; + j = current_number_of_landmarks; + //std::cout << "First half complete\n"; + while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) + { + // sort the closest landmark vector for every witness + temp_swap_int = WL[i][j]; + WL[i][j] = WL[i][j-1]; + WL[i][j-1] = temp_swap_int; + temp_swap_double = wit_land_dist[i][j]; + wit_land_dist[i][j] = wit_land_dist[i][j-1]; + wit_land_dist[i][j-1] = temp_swap_double; + --j; + } + //std::cout << "result WL="; print_vvector(WL); + //std::cout << "result WLD="; print_vvector(wit_land_dist); + //std::cout << "End loop\n"; + } + } + //std::cout << endl; + } + + }; //class Witness_complex + } // namespace Guhdi diff --git a/src/Witness_complex/include/gudhi/Witness_complex1.h b/src/Witness_complex/include/gudhi/Witness_complex1.h deleted file mode 100644 index f75c3e66..00000000 --- a/src/Witness_complex/include/gudhi/Witness_complex1.h +++ /dev/null @@ -1,470 +0,0 @@ -/* 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): Siargey Kachanovich - * - * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 . - */ - -#ifndef GUDHI_WITNESS_COMPLEX_H_ -#define GUDHI_WITNESS_COMPLEX_H_ - -#include -#include -#include -#include -#include "gudhi/reader_utils.h" -#include "gudhi/distance_functions.h" -#include "gudhi/Simplex_tree.h" -#include -#include -#include -#include - -#include - -namespace Gudhi { - - /* -template -class Simplex_tree; - */ - - /* - typedef int Witness_id; -typedef int Landmark_id; -typedef int Simplex_handle; //index in vector complex_ - */ - -template -class Witness_complex: public Simplex_tree<> { - //class Witness_complex: public Simplex_tree { - //class Witness_complex { -private: - - /* - template < typename Witness_id = int, - typename Landmark_id = int, - typename Simplex_handle = Simplex_handle > - struct Active_witness { - Witness_id witness_id; - Landmark_id landmark_id; - Simplex_handle simplex_handle; - }; - */ - -struct Active_witness { - int witness_id; - int landmark_id; - Simplex_handle simplex_handle; - - Active_witness(int witness_id_, int landmark_id_, Simplex_handle simplex_handle_) - : witness_id(witness_id_), - landmark_id(landmark_id_), - simplex_handle(simplex_handle_) - {} -}; - - - - -public: - -//Simplex_tree<> st; - -// typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; -// typedef boost::iterator_range Boundary_simplex_range; - -// typedef typename std::vector< Simplex_handle >::iterator Skeleton_simplex_iterator; -// typedef boost::iterator_range< Skeleton_simplex_iterator > Skeleton_simplex_range; - -// typedef IndexingTag Indexing_tag; - /** \brief Type for the value of the filtration function. - * - * Must be comparable with <. */ -// typedef FiltrationValue Filtration_value; - /** \brief Key associated to each simplex. - * - * Must be a signed integer type. */ -// typedef SimplexKey Simplex_key; - - /** \brief Type for the vertex handle. - * - * Must be a signed integer type. It admits a total order <. */ - typedef VertexHandle Vertex_handle; - - /* Type of node in the simplex tree. */ - typedef Simplex_tree_node_explicit_storage Node; - /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ - typedef typename boost::container::flat_map Dictionary; - typedef typename Dictionary::iterator Simplex_handle; - -/* - friend class Simplex_tree_node_explicit_storage< Simplex_tree >; - friend class Simplex_tree_siblings< Simplex_tree, Dictionary>; - friend class Simplex_tree_simplex_vertex_iterator< Simplex_tree >; - friend class Simplex_tree_boundary_simplex_iterator< Simplex_tree >; - friend class Simplex_tree_complex_simplex_iterator< Simplex_tree >; - friend class Simplex_tree_skeleton_simplex_iterator< Simplex_tree >; -*/ - - /* \brief Set of nodes sharing a same parent in the simplex tree. */ - /* \brief Set of nodes sharing a same parent in the simplex tree. */ -// typedef Simplex_tree_siblings Siblings; - - - typedef std::vector< double > Point_t; - typedef std::vector< Point_t > Point_Vector; - - typedef std::vector< Vertex_handle > typeVectorVertex; - typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; - typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; - - typedef int Witness_id; - typedef int Landmark_id; - typedef std::list< Vertex_handle > ActiveWitnessList; - -/** - * /brief Iterative construction of the witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks}. - * Landmarks are supposed to be in [0,nbL-1] - */ - - -template< typename KNearestNeighbours > -void witness_complex(KNearestNeighbours & knn) -//void witness_complex(std::vector< std::vector< Vertex_handle > > & knn) -{ - std::cout << "**Start the procedure witness_complex" << std::endl; - int k=2; /* current dimension in iterative construction */ - //Construction of the active witness list - int nbW = knn.size(); - int nbL = knn.at(0).size(); - //VertexHandle vh; - typeVectorVertex vv; - typeSimplex simplex; - typePairSimplexBool returnValue; - int counter = 0; - /* The list of still useful witnesses - * it will diminuish in the course of iterations - */ - ActiveWitnessList active_w;// = new ActiveWitnessList(); - for (int i=0; i != nbL; ++i) { - // initial fill of 0-dimensional simplices - // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore - //vh = (Vertex_handle)i; - counter++; - vv = {i}; - /* TODO Filtration */ - //simplex = std::make_pair(vv, Filtration_value(0.0)); - //returnValue = this->insert_simplex(simplex.first, simplex.second); - returnValue = insert_simplex(vv, Filtration_value(0.0)); - /* TODO Error if not inserted : normally no need here though*/ - } - //vv = {0}; - //returnValue = insert_simplex(vv,Filtration_value(0.0)); - //std::cout << "Successfully added landmarks" << std::endl; - // PRINT2 - //print_sc(root()); std::cout << std::endl; - int u,v; // two extremities of an edge - if (nbL > 1) // if the supposed dimension of the complex is >0 - { - for (int i=0; i != nbW; ++i) - { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - //Siblings * curr_sib = &root_; - //vh = (Vertex_handle)i; - vv = {u,v}; - returnValue = this->insert_simplex(vv,Filtration_value(0.0)); - //print_sc(root()); std::cout << std::endl; - //std::cout << "Added edges" << std::endl; - } - //print_sc(root()); - for (int i=0; i != nbW; ++i) - { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - if ( u > v) - { - u = v; - v = knn[i][0]; - knn[i][0] = knn[i][1]; - knn[i][1] = v; - } - Simplex_handle sh; - vv = {u,v}; - sh = (root()->find(u))->second.children()->find(v); - active_w.push_back(i); - } - } - //std::cout << "Successfully added edges" << std::endl; - while (!active_w.empty() && k < nbL ) - { - //std::cout << "Started the step k=" << k << std::endl; - typename ActiveWitnessList::iterator it = active_w.begin(); - while (it != active_w.end()) - { - typeVectorVertex simplex_vector; - /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/ - // First sort the first k landmarks - VertexHandle inserted_vertex = knn[*it][k]; - bool ok = all_faces_in(knn, *it, k, inserted_vertex); - if (ok) - { - for (int i = 0; i != k+1; ++i) - simplex_vector.push_back(knn[*it][i]); - returnValue = insert_simplex(simplex_vector,0.0); - it++; - } - else - active_w.erase(it++); //First increase the iterator and then erase the previous element - } - k++; - } - print_sc(root()); std::cout << std::endl; -} - - void witness_complex_from_file(Point_Vector point_vector, int nbL) - { - //READ THE FILE INTO A POINT VECTOR - //std::vector< std::vector< double > > point_vector; - //read_points(file_name, point_vector); - std::vector > WL; - furthestPoints(point_vector, point_vector.size(), nbL, WL); - witness_complex(WL); - } - -private: - - void print_sc(Siblings * sibl) - { - if (sibl == NULL) - std::cout << "&"; - else - print_children(sibl->members_); - } - - void print_children(Dictionary map) - { - std::cout << "("; - if (!map.empty()) - { - std::cout << map.begin()->first; - /*if (map.begin()->second.children() == root()) - std::cout << "Sweet potato"; */ - if (has_children(map.begin())) - print_sc(map.begin()->second.children()); - typename Dictionary::iterator it; - for (it = map.begin()+1; it != map.end(); ++it) - { - std::cout << "," << it->first; - /*if (map.begin()->second.children() == root()) - std::cout << "Sweet potato";*/ - if (has_children(it)) - print_sc(it->second.children()); - } - } - std::cout << ")"; - } - - template - bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) - { - //std::cout << "All face in with the landmark " << inserted_vertex << std::endl; - std::vector< VertexHandle > facet; - //VertexHandle curr_vh = curr_sh->first; - // CHECK ALL THE FACETS - for (int i = 0; i != k+1; ++i) - { - if (knn[witness_id][i] != inserted_vertex) - { - facet = {}; - for (int j = 0; j != k+1; ++j) - { - if (j != i) - { - facet.push_back(knn[witness_id][j]); - } - }//endfor - if (find(facet) == null_simplex()) - return false; - //std::cout << "++++ finished loop safely\n"; - }//endif - } //endfor - return true; - } - - template - void print_vector(std::vector v) - { - std::cout << "["; - if (!v.empty()) - { - std::cout << *(v.begin()); - for (auto it = v.begin()+1; it != v.end(); ++it) - { - std::cout << ","; - std::cout << *it; - } - } - std::cout << "]"; - } - - template - void print_vvector(std::vector< std::vector > vv) - { - std::cout << "["; - if (!vv.empty()) - { - print_vector(*(vv.begin())); - for (auto it = vv.begin()+1; it != vv.end(); ++it) - { - std::cout << ","; - print_vector(*it); - } - } - std::cout << "]\n"; - } - -/** - * \brief Permutes the vector in such a way that the landmarks appear first - * \arg W is the vector of points which will be the witnesses - * \arg nbP is the number of witnesses - * \arg nbL is the number of landmarks - * \arg WL is the matrix of the nearest landmarks with respect to witnesses (output) - */ - - template - void furthestPoints(Point_Vector &W, int nbP, int nbL, KNearestNeighbours &WL) - //void furthestPoints(Point_Vector &W, int nbP, int nbL, Point_Vector &L) - { - std::cout << "Enter furthestPoints "<< std::endl; - // What is density and why we need it. - // basically it is the stop indicator for "no more landmarks" - //std::cout << "W="; print_vvector(W); - //double density = 5.; - std::vector< std::vector > wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks - std::vector< int > chosen_landmarks; // landmark list - - WL = KNearestNeighbours(nbP,std::vector()); //nbP copies of empty vectors - int current_number_of_landmarks=0; - double curr_max_dist = 0; - double curr_dist; - double infty = std::numeric_limits::infinity(); - std::vector< double > dist_to_L(nbP,infty); - // double mindist = infty; - int curr_max_w=0; - int j; - int temp_swap_int; - double temp_swap_double; - - //CHOICE OF THE FIRST LANDMARK - //std::cout << "Enter the first landmark stage\n"; - srand(354698); - int rand_int = rand()% nbP; - curr_max_w = rand_int; - - for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) - { - chosen_landmarks.push_back(curr_max_w); - curr_max_dist = 0; - std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; - std::cout << "WL="; print_vvector(WL); - std::cout << "WLD="; print_vvector(wit_land_dist); - std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; - for (auto v: WL) - v.push_back(current_number_of_landmarks); - for (int i = 0; i < nbP; ++i) - { - std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; - //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; - if (i != chosen_landmarks[current_number_of_landmarks]) - curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); - else - curr_dist = 0; - //std::cout << "The problem is not in distance function\n"; - wit_land_dist[i].push_back(curr_dist); - WL[i].push_back(current_number_of_landmarks); - //std::cout << "Push't back\n"; - if (curr_dist < dist_to_L[i]) - dist_to_L[i] = curr_dist; - if (dist_to_L[i] > curr_max_dist) - { - curr_max_dist = curr_dist; - curr_max_w = i; - } - j = current_number_of_landmarks; - //std::cout << "First half complete\n"; - while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) - { - temp_swap_int = WL[i][j]; - WL[i][j] = WL[i][j-1]; - WL[i][j-1] = temp_swap_int; - temp_swap_double = wit_land_dist[i][j]; - wit_land_dist[i][j] = wit_land_dist[i][j-1]; - wit_land_dist[i][j-1] = temp_swap_double; - --j; - } - std::cout << "result WL="; print_vvector(WL); - std::cout << "result WLD="; print_vvector(wit_land_dist); - - std::cout << "End loop\n"; - } - } - /* - while (1) { - curr_w = 0; - curr_max_dist = -1; - for(Point_Vector::iterator itW = W.begin(); itW != W.end(); itW++) { - //compute distance from w and L - mindist = infty; - for(Point_Vector::iterator itL = L.begin(); itL != L.end(); itL++) { - //curr_dist = distPoints(*itW,*itL); - curr_dist = euclidean_distance(*itW,*itL); - if(curr_dist < mindist) { - mindist = curr_dist; - } - } - if(mindist > curr_max_dist) { - curr_max_w = curr_w; //??? - curr_max_dist = mindist; - } - curr_w++; - } - L.push_back(W[curr_max_w]); - current_number_of_landmarks++; - //density = sqrt(curr_max_dist); - //std::cout << "[" << current_number_of_landmarks << ":" << density <<"] "; - if(L.size() == nbL) break; - } - */ - //std::cout << endl; - //return L; - } - -}; //class Witness_complex - - -} // namespace Guhdi - -#endif -- cgit v1.2.3 From 8df595a525b21fdd49816f312411814b3b894c21 Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 31 Mar 2015 14:52:37 +0000 Subject: Fixed bug in landmark_choice_by_furthest_points. Stay tuned for one more bug git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@521 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e8f0a0b7122fd180b92fa3ba58e33dbec49f29ea --- src/Witness_complex/include/gudhi/Witness_complex.h | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index d5a35801..4b65e8a2 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -219,7 +219,7 @@ namespace Gudhi { void witness_complex_from_points(Point_Vector point_vector) { std::vector > WL; - landmark_choice_by_random_points(point_vector, point_vector.size(), WL); + landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); witness_complex(WL); } @@ -357,7 +357,6 @@ private: { //curr_max_w at this point is the next landmark chosen_landmarks.push_back(curr_max_w); - curr_max_dist = 0; //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; //std::cout << "WL="; print_vvector(WL); //std::cout << "WLD="; print_vvector(wit_land_dist); @@ -377,11 +376,6 @@ private: //std::cout << "Push't back\n"; if (curr_dist < dist_to_L[i]) dist_to_L[i] = curr_dist; - if (dist_to_L[i] > curr_max_dist) - { - curr_max_dist = curr_dist; - curr_max_w = i; - } j = current_number_of_landmarks; //std::cout << "First half complete\n"; while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) @@ -400,6 +394,17 @@ private: //std::cout << "result distL="; print_vector(dist_to_L); std::cout << std::endl; //std::cout << "End loop\n"; } + std::cout << "Distance to landmarks="; print_vector(dist_to_L); std::cout << std::endl; + curr_max_dist = 0; + for (int i = 0; i < nbP; ++i) { + if (dist_to_L[i] > curr_max_dist) + { + curr_max_dist = dist_to_L[i]; + curr_max_w = i; + std::cout << "hop curr_max_w is now " << curr_max_w << std::endl; + } + } + std::cout << "Chose " << curr_max_w << " as new landmark\n"; } //std::cout << endl; } -- cgit v1.2.3 From e6d3a9c57f80f65997183f4e08ecee31d4bcaae1 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 1 Apr 2015 08:21:06 +0000 Subject: Added landmark_strategy_by_random_points git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@525 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: dcf5d32465313860e4666a8e81128077e2cde1a5 --- src/Witness_complex/include/gudhi/Witness_complex.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 4b65e8a2..bcfe0f38 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -219,7 +219,7 @@ namespace Gudhi { void witness_complex_from_points(Point_Vector point_vector) { std::vector > WL; - landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); + landmark_choice_by_random_points(point_vector, point_vector.size(), WL); witness_complex(WL); } @@ -360,7 +360,7 @@ private: //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; //std::cout << "WL="; print_vvector(WL); //std::cout << "WLD="; print_vvector(wit_land_dist); - std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; + //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; for (auto v: WL) v.push_back(current_number_of_landmarks); for (int i = 0; i < nbP; ++i) @@ -394,17 +394,16 @@ private: //std::cout << "result distL="; print_vector(dist_to_L); std::cout << std::endl; //std::cout << "End loop\n"; } - std::cout << "Distance to landmarks="; print_vector(dist_to_L); std::cout << std::endl; + //std::cout << "Distance to landmarks="; print_vector(dist_to_L); std::cout << std::endl; curr_max_dist = 0; for (int i = 0; i < nbP; ++i) { if (dist_to_L[i] > curr_max_dist) { curr_max_dist = dist_to_L[i]; curr_max_w = i; - std::cout << "hop curr_max_w is now " << curr_max_w << std::endl; } } - std::cout << "Chose " << curr_max_w << " as new landmark\n"; + //std::cout << "Chose " << curr_max_w << " as new landmark\n"; } //std::cout << endl; } -- cgit v1.2.3 From 42ef28d73a05b84ad02193e4f3bf76b416ba9a02 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 1 Apr 2015 14:50:43 +0000 Subject: Test commit: potentionally fix witness_complex_from_file.cpp file git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@530 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e5a3fd713024eb8a117ce58a1810f61af90490d0 --- src/Witness_complex/example/simple_witness_complex.cpp | 2 +- src/Witness_complex/example/witness_complex_from_file.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/simple_witness_complex.cpp b/src/Witness_complex/example/simple_witness_complex.cpp index 7a46ffb3..43921c4e 100644 --- a/src/Witness_complex/example/simple_witness_complex.cpp +++ b/src/Witness_complex/example/simple_witness_complex.cpp @@ -23,7 +23,7 @@ #include #include //#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Witness_complex1.h" +#include "gudhi/Witness_complex.h" using namespace Gudhi; diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index a0e192f7..e2a80e92 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -2,9 +2,9 @@ * (Geometric Understanding in Higher Dimensions) is a generic C++ * library for computational topology. * - * Author(s): Vincent Rouvreau + * Author(s): Siargey Kachanovich * - * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France) + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 @@ -24,7 +24,7 @@ #include #include //#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Witness_complex1.h" +#include "gudhi/Witness_complex.h" using namespace Gudhi; @@ -81,7 +81,8 @@ int main (int argc, char * const argv[]) start = clock(); Point_Vector point_vector; read_points_cust(file_name, point_vector); - witnessComplex.witness_complex_from_file(point_vector, nbL); + witnessComplex.setNbL(nbL); + witnessComplex.witness_complex_from_points(point_vector); end = clock(); std::cout << "Howdy world! The process took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; -- cgit v1.2.3 From b76ee21ac17dbfc630bb16d66fec4b1c2ee4013a Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 2 Apr 2015 12:28:46 +0000 Subject: Added writing to file functions git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@538 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 429568c33608ad8f49508513379e33cd6a73b006 --- .../include/gudhi/Witness_complex.h | 40 +++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index bcfe0f38..1b50ca95 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -208,7 +208,7 @@ namespace Gudhi { } k++; } - print_sc(root()); std::cout << std::endl; + //print_sc(root()); std::cout << std::endl; } /** \brief Construction of witness complex from points given explicitly @@ -254,6 +254,44 @@ private: std::cout << ")"; } + public: + /** \brief Print functions + */ + + void st_to_file(std::ofstream& out_file) + { + sc_to_file(out_file, root()); + } + + private: + void sc_to_file(std::ofstream& out_file, Siblings * sibl) + { + if (sibl == NULL) + out_file << "&"; + else + children_to_file(out_file, sibl->members_); + } + + void children_to_file(std::ofstream& out_file, Dictionary map) + { + out_file << "("; + if (!map.empty()) + { + out_file << map.begin()->first; + if (has_children(map.begin())) + sc_to_file(out_file, map.begin()->second.children()); + typename Dictionary::iterator it; + for (it = map.begin()+1; it != map.end(); ++it) + { + out_file << "," << it->first; + if (has_children(it)) + sc_to_file(out_file, it->second.children()); + } + } + out_file << ")"; + } + + /** \brief Check if the facets of the k-dimensional simplex witnessed * by witness witness_id are already in the complex. * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id -- cgit v1.2.3 From 35c75c5d30236dd29ad8e4d4f12de8223e73b58e Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 2 Apr 2015 12:38:30 +0000 Subject: Added also changes in the cpp file git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@539 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e32f574c7cf93f67de3d08b43f9c6de5a4a8396d --- src/Witness_complex/example/witness_complex_from_file.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index e2a80e92..cec1d1b8 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -23,6 +23,9 @@ #include #include #include + +//#include + //#include "gudhi/graph_simplicial_complex.h" #include "gudhi/Witness_complex.h" @@ -86,5 +89,13 @@ int main (int argc, char * const argv[]) end = clock(); std::cout << "Howdy world! The process took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; - + char buffer[100]; + int i = sprintf(buffer,"%s_%s_result.txt",argv[1],argv[2]); + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } } -- cgit v1.2.3 From cc8adaf7524cb56b6616bd6f6041af2e534ee211 Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 2 Apr 2015 14:11:52 +0000 Subject: Added parallel file git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@540 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b56520af4bef97f99cae62924fc4860ce1e2f73e --- .../include/gudhi/Witness_complex-parallel.h | 553 +++++++++++++++++++++ 1 file changed, 553 insertions(+) create mode 100644 src/Witness_complex/include/gudhi/Witness_complex-parallel.h (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex-parallel.h b/src/Witness_complex/include/gudhi/Witness_complex-parallel.h new file mode 100644 index 00000000..ac5c8dd5 --- /dev/null +++ b/src/Witness_complex/include/gudhi/Witness_complex-parallel.h @@ -0,0 +1,553 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 . + */ + +#ifndef GUDHI_WITNESS_COMPLEX_H_ +#define GUDHI_WITNESS_COMPLEX_H_ + +#include +#include +#include +#include +#include "gudhi/reader_utils.h" +#include "gudhi/distance_functions.h" +#include "gudhi/Simplex_tree.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Gudhi { + + + /** \addtogroup simplex_tree + * Witness complex is a simplicial complex defined on two sets of points in \f$\mathbf{R}^D\f$: + * \f$W\f$ set of witnesses and \f$L \subseteq W\f$ set of landmarks. The simplices are based on points in \f$L\f$ + * and a simplex belongs to the witness complex if and only if it is witnessed (there exists a point \f$w \in W\f$ such that + * w is closer to the vertices of this simplex than others) and all of its faces are witnessed as well. + */ + template + class Witness_complex: public Simplex_tree<> { + + private: + + struct Active_witness { + int witness_id; + int landmark_id; + Simplex_handle simplex_handle; + + Active_witness(int witness_id_, int landmark_id_, Simplex_handle simplex_handle_) + : witness_id(witness_id_), + landmark_id(landmark_id_), + simplex_handle(simplex_handle_) + {} + }; + + + + + public: + + + /** \brief Type for the vertex handle. + * + * Must be a signed integer type. It admits a total order <. */ + typedef VertexHandle Vertex_handle; + + /* Type of node in the simplex tree. */ + typedef Simplex_tree_node_explicit_storage Node; + /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ + typedef typename boost::container::flat_map Dictionary; + typedef typename Dictionary::iterator Simplex_handle; + + typedef std::vector< double > Point_t; + typedef std::vector< Point_t > Point_Vector; + + typedef std::vector< Vertex_handle > typeVectorVertex; + typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; + typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + + typedef int Witness_id; + typedef int Landmark_id; + typedef std::list< Vertex_handle > ActiveWitnessList; + + private: + /** Number of landmarks + */ + int nbL; + /** Desired density + */ + double density; + + public: + + /** \brief Set number of landmarks to nbL_ + */ + void setNbL(int nbL_) + { + nbL = nbL_; + } + + /** \brief Set density to density_ + */ + void setDensity(double density_) + { + density = density_; + } + + /** + * /brief Iterative construction of the witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks}. + * Landmarks are supposed to be in [0,nbL-1] + */ + + template< typename KNearestNeighbours > + void witness_complex(KNearestNeighbours & knn) + //void witness_complex(std::vector< std::vector< Vertex_handle > > & knn) + { + std::cout << "**Start the procedure witness_complex" << std::endl; + int k=2; /* current dimension in iterative construction */ + //Construction of the active witness list + int nbW = knn.size(); + //int nbL = knn.at(0).size(); + typeVectorVertex vv; + typeSimplex simplex; + typePairSimplexBool returnValue; + int counter = 0; + /* The list of still useful witnesses + * it will diminuish in the course of iterations + */ + ActiveWitnessList active_w;// = new ActiveWitnessList(); + for (int i=0; i != nbL; ++i) { + // initial fill of 0-dimensional simplices + // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore + counter++; + vv = {i}; + /* TODO Filtration */ + returnValue = insert_simplex(vv, Filtration_value(0.0)); + /* TODO Error if not inserted : normally no need here though*/ + } + //std::cout << "Successfully added landmarks" << std::endl; + // PRINT2 + //print_sc(root()); std::cout << std::endl; + int u,v; // two extremities of an edge + if (nbL > 1) // if the supposed dimension of the complex is >0 + { + for (int i=0; i != nbW; ++i) + { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + vv = {u,v}; + returnValue = this->insert_simplex(vv,Filtration_value(0.0)); + //print_sc(root()); std::cout << std::endl; + //std::cout << "Added edges" << std::endl; + } + //print_sc(root()); + for (int i=0; i != nbW; ++i) + { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + if ( u > v) + { + u = v; + v = knn[i][0]; + knn[i][0] = knn[i][1]; + knn[i][1] = v; + } + Simplex_handle sh; + vv = {u,v}; + sh = (root()->find(u))->second.children()->find(v); + active_w.push_back(i); + } + } + //std::cout << "Successfully added edges" << std::endl; + while (!active_w.empty() && k < nbL ) + { + //std::cout << "Started the step k=" << k << std::endl; + typename ActiveWitnessList::iterator it = active_w.begin(); + while (it != active_w.end()) + { + typeVectorVertex simplex_vector; + /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/ + // First sort the first k landmarks + VertexHandle inserted_vertex = knn[*it][k]; + bool ok = all_faces_in(knn, *it, k, inserted_vertex); + if (ok) + { + for (int i = 0; i != k+1; ++i) + simplex_vector.push_back(knn[*it][i]); + returnValue = insert_simplex(simplex_vector,0.0); + it++; + } + else + active_w.erase(it++); //First increase the iterator and then erase the previous element + } + k++; + } + //print_sc(root()); std::cout << std::endl; + } + + /** \brief Construction of witness complex from points given explicitly + * nbL must be set to the right value of landmarks for strategies + * FURTHEST_POINT_STRATEGY and RANDOM_POINT_STRATEGY and + * density must be set to the right value for DENSITY_STRATEGY + */ + void witness_complex_from_points(Point_Vector point_vector) + { + std::vector > WL; + clock_t start,end; + start = clock(); + landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); + end = clock(); + std::cout << "Landmarks took " << (double)(end-start)/CLOCKS_PER_SEC << "s.\n"; + start = clock(); + witness_complex(WL); + end = clock(); + std::cout << "Complex construction took " << (double)(end-start)/CLOCKS_PER_SEC << "s.\n"; + } + +private: + + /** \brief Print functions + */ + void print_sc(Siblings * sibl) + { + if (sibl == NULL) + std::cout << "&"; + else + print_children(sibl->members_); + } + + void print_children(Dictionary map) + { + std::cout << "("; + if (!map.empty()) + { + std::cout << map.begin()->first; + if (has_children(map.begin())) + print_sc(map.begin()->second.children()); + typename Dictionary::iterator it; + for (it = map.begin()+1; it != map.end(); ++it) + { + std::cout << "," << it->first; + if (has_children(it)) + print_sc(it->second.children()); + } + } + std::cout << ")"; + } + + public: + /** \brief Print functions + */ + + void st_to_file(std::ofstream& out_file) + { + sc_to_file(out_file, root()); + } + + private: + void sc_to_file(std::ofstream& out_file, Siblings * sibl) + { + if (sibl == NULL) + out_file << "&"; + else + children_to_file(out_file, sibl->members_); + } + + void children_to_file(std::ofstream& out_file, Dictionary map) + { + out_file << "("; + if (!map.empty()) + { + out_file << map.begin()->first; + if (has_children(map.begin())) + sc_to_file(out_file, map.begin()->second.children()); + typename Dictionary::iterator it; + for (it = map.begin()+1; it != map.end(); ++it) + { + out_file << "," << it->first; + if (has_children(it)) + sc_to_file(out_file, it->second.children()); + } + } + out_file << ")"; + } + + + /** \brief Check if the facets of the k-dimensional simplex witnessed + * by witness witness_id are already in the complex. + * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id + */ + template + bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) + { + //std::cout << "All face in with the landmark " << inserted_vertex << std::endl; + std::vector< VertexHandle > facet; + //VertexHandle curr_vh = curr_sh->first; + // CHECK ALL THE FACETS + for (int i = 0; i != k+1; ++i) + { + if (knn[witness_id][i] != inserted_vertex) + { + facet = {}; + for (int j = 0; j != k+1; ++j) + { + if (j != i) + { + facet.push_back(knn[witness_id][j]); + } + }//endfor + if (find(facet) == null_simplex()) + return false; + //std::cout << "++++ finished loop safely\n"; + }//endif + } //endfor + return true; + } + + template + void print_vector(std::vector v) + { + std::cout << "["; + if (!v.empty()) + { + std::cout << *(v.begin()); + for (auto it = v.begin()+1; it != v.end(); ++it) + { + std::cout << ","; + std::cout << *it; + } + } + std::cout << "]"; + } + + template + void print_vvector(std::vector< std::vector > vv) + { + std::cout << "["; + if (!vv.empty()) + { + print_vector(*(vv.begin())); + for (auto it = vv.begin()+1; it != vv.end(); ++it) + { + std::cout << ","; + print_vector(*it); + } + } + std::cout << "]\n"; + } + +/** + * \brief Landmark choice strategy by iteratively adding the landmark the furthest from the + * current landmark set + * \arg W is the vector of points which will be the witnesses + * \arg nbP is the number of witnesses + * \arg nbL is the number of landmarks + * \arg WL is the matrix of the nearest landmarks with respect to witnesses (output) + */ + + template + void landmark_choice_by_furthest_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) + { + //std::cout << "Enter landmark_choice_by_furthest_points "<< std::endl; + //std::cout << "W="; print_vvector(W); + //double density = 5.; + Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks + typeVectorVertex chosen_landmarks; // landmark list + + WL = KNearestNeighbours(nbP,std::vector()); + int current_number_of_landmarks=0; // counter for landmarks + double curr_max_dist = 0; // used for defining the furhest point from L + double curr_dist; // used to stock the distance from the current point to L + double infty = std::numeric_limits::infinity(); // infinity (see next entry) + std::vector< double > dist_to_L(nbP,infty); // vector of current distances to L from points + // double mindist = infty; + int curr_max_w=0; // the point currently furthest from L + int j; + int temp_swap_int; + double temp_swap_double; + + //CHOICE OF THE FIRST LANDMARK + std::cout << "Enter the first landmark stage\n"; + srand(354698); + int rand_int = rand()% nbP; + curr_max_w = rand_int; //For testing purposes a pseudo-random number is used here + + for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + { + //curr_max_w at this point is the next landmark + chosen_landmarks.push_back(curr_max_w); + //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; + //std::cout << "WL="; print_vvector(WL); + //std::cout << "WLD="; print_vvector(wit_land_dist); + //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; + for (auto v: WL) + v.push_back(current_number_of_landmarks); + //#pragma omp parallel for + for (int i = 0; i < nbP; ++i) + { + // iteration on points in W. update of distance vectors + + //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; + //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; + curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); + //std::cout << "The problem is not in distance function\n"; + wit_land_dist[i].push_back(curr_dist); + WL[i].push_back(current_number_of_landmarks); + //std::cout << "Push't back\n"; + if (curr_dist < dist_to_L[i]) + dist_to_L[i] = curr_dist; + j = current_number_of_landmarks; + //std::cout << "First half complete\n"; + while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) + { + // sort the closest landmark vector for every witness + temp_swap_int = WL[i][j]; + WL[i][j] = WL[i][j-1]; + WL[i][j-1] = temp_swap_int; + temp_swap_double = wit_land_dist[i][j]; + wit_land_dist[i][j] = wit_land_dist[i][j-1]; + wit_land_dist[i][j-1] = temp_swap_double; + --j; + } + //std::cout << "result WL="; print_vvector(WL); + //std::cout << "result WLD="; print_vvector(wit_land_dist); + //std::cout << "result distL="; print_vector(dist_to_L); std::cout << std::endl; + //std::cout << "End loop\n"; + } + //std::cout << "Distance to landmarks="; print_vector(dist_to_L); std::cout << std::endl; + curr_max_dist = 0; + //omp_set_variable() + #pragma omp parallel for + for (int i = 0; i < nbP; ++i) { + if (dist_to_L[i] > curr_max_dist) + { + //#pragma omp ordered + { + curr_max_dist = dist_to_L[i]; + curr_max_w = i; + } + } + } + /* + for (int i = 0; i < nbP; ++i) { + if (dist_to_L[i] > curr_max_dist) + { + { + curr_max_dist = dist_to_L[i]; + curr_max_w = i; + } + } + } + */ + //std::cout << "Chose " << curr_max_w << " as new landmark\n"; + } + //std::cout << endl; + } + + /** \brief Landmark choice strategy by taking random vertices for landmarks. + * + */ + + template + void landmark_choice_by_random_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) + { + //std::cout << "Enter landmark_choice_by_random_points "<< std::endl; + //std::cout << "W="; print_vvector(W); + std::unordered_set< int > chosen_landmarks; // landmark set + + Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks + + WL = KNearestNeighbours(nbP,std::vector()); + int current_number_of_landmarks=0; // counter for landmarks + + srand(24660); + int chosen_landmark = rand()%nbP; + double curr_dist; + + int j; + int temp_swap_int; + double temp_swap_double; + + + for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + { + while (chosen_landmarks.find(chosen_landmark) != chosen_landmarks.end()) + { + srand((int)clock()); + chosen_landmark = rand()% nbP; + //std::cout << chosen_landmark << "\n"; + } + chosen_landmarks.insert(chosen_landmark); + //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; + //std::cout << "WL="; print_vvector(WL); + //std::cout << "WLD="; print_vvector(wit_land_dist); + //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; + for (auto v: WL) + v.push_back(current_number_of_landmarks); + for (int i = 0; i < nbP; ++i) + { + // iteration on points in W. update of distance vectors + + //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; + //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; + curr_dist = euclidean_distance(W[i],W[chosen_landmark]); + //std::cout << "The problem is not in distance function\n"; + wit_land_dist[i].push_back(curr_dist); + WL[i].push_back(current_number_of_landmarks); + //std::cout << "Push't back\n"; + j = current_number_of_landmarks; + //std::cout << "First half complete\n"; + while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) + { + // sort the closest landmark vector for every witness + temp_swap_int = WL[i][j]; + WL[i][j] = WL[i][j-1]; + WL[i][j-1] = temp_swap_int; + temp_swap_double = wit_land_dist[i][j]; + wit_land_dist[i][j] = wit_land_dist[i][j-1]; + wit_land_dist[i][j-1] = temp_swap_double; + --j; + } + //std::cout << "result WL="; print_vvector(WL); + //std::cout << "result WLD="; print_vvector(wit_land_dist); + //std::cout << "End loop\n"; + } + } + //std::cout << endl; + } + + +}; //class Witness_complex + + + +} // namespace Guhdi + +#endif -- cgit v1.2.3 From 30b0effaf86ff300c5519e0919b33f61fc4a14f8 Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 7 Apr 2015 10:25:17 +0000 Subject: Deleted the parallel attempt file git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@544 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a853bc4b2afe5bfdaa8e95065f928c7c48988610 --- .../include/gudhi/Witness_complex-parallel.h | 553 --------------------- 1 file changed, 553 deletions(-) delete mode 100644 src/Witness_complex/include/gudhi/Witness_complex-parallel.h (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex-parallel.h b/src/Witness_complex/include/gudhi/Witness_complex-parallel.h deleted file mode 100644 index ac5c8dd5..00000000 --- a/src/Witness_complex/include/gudhi/Witness_complex-parallel.h +++ /dev/null @@ -1,553 +0,0 @@ -/* 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): Siargey Kachanovich - * - * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 . - */ - -#ifndef GUDHI_WITNESS_COMPLEX_H_ -#define GUDHI_WITNESS_COMPLEX_H_ - -#include -#include -#include -#include -#include "gudhi/reader_utils.h" -#include "gudhi/distance_functions.h" -#include "gudhi/Simplex_tree.h" -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Gudhi { - - - /** \addtogroup simplex_tree - * Witness complex is a simplicial complex defined on two sets of points in \f$\mathbf{R}^D\f$: - * \f$W\f$ set of witnesses and \f$L \subseteq W\f$ set of landmarks. The simplices are based on points in \f$L\f$ - * and a simplex belongs to the witness complex if and only if it is witnessed (there exists a point \f$w \in W\f$ such that - * w is closer to the vertices of this simplex than others) and all of its faces are witnessed as well. - */ - template - class Witness_complex: public Simplex_tree<> { - - private: - - struct Active_witness { - int witness_id; - int landmark_id; - Simplex_handle simplex_handle; - - Active_witness(int witness_id_, int landmark_id_, Simplex_handle simplex_handle_) - : witness_id(witness_id_), - landmark_id(landmark_id_), - simplex_handle(simplex_handle_) - {} - }; - - - - - public: - - - /** \brief Type for the vertex handle. - * - * Must be a signed integer type. It admits a total order <. */ - typedef VertexHandle Vertex_handle; - - /* Type of node in the simplex tree. */ - typedef Simplex_tree_node_explicit_storage Node; - /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ - typedef typename boost::container::flat_map Dictionary; - typedef typename Dictionary::iterator Simplex_handle; - - typedef std::vector< double > Point_t; - typedef std::vector< Point_t > Point_Vector; - - typedef std::vector< Vertex_handle > typeVectorVertex; - typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; - typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; - - typedef int Witness_id; - typedef int Landmark_id; - typedef std::list< Vertex_handle > ActiveWitnessList; - - private: - /** Number of landmarks - */ - int nbL; - /** Desired density - */ - double density; - - public: - - /** \brief Set number of landmarks to nbL_ - */ - void setNbL(int nbL_) - { - nbL = nbL_; - } - - /** \brief Set density to density_ - */ - void setDensity(double density_) - { - density = density_; - } - - /** - * /brief Iterative construction of the witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks}. - * Landmarks are supposed to be in [0,nbL-1] - */ - - template< typename KNearestNeighbours > - void witness_complex(KNearestNeighbours & knn) - //void witness_complex(std::vector< std::vector< Vertex_handle > > & knn) - { - std::cout << "**Start the procedure witness_complex" << std::endl; - int k=2; /* current dimension in iterative construction */ - //Construction of the active witness list - int nbW = knn.size(); - //int nbL = knn.at(0).size(); - typeVectorVertex vv; - typeSimplex simplex; - typePairSimplexBool returnValue; - int counter = 0; - /* The list of still useful witnesses - * it will diminuish in the course of iterations - */ - ActiveWitnessList active_w;// = new ActiveWitnessList(); - for (int i=0; i != nbL; ++i) { - // initial fill of 0-dimensional simplices - // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore - counter++; - vv = {i}; - /* TODO Filtration */ - returnValue = insert_simplex(vv, Filtration_value(0.0)); - /* TODO Error if not inserted : normally no need here though*/ - } - //std::cout << "Successfully added landmarks" << std::endl; - // PRINT2 - //print_sc(root()); std::cout << std::endl; - int u,v; // two extremities of an edge - if (nbL > 1) // if the supposed dimension of the complex is >0 - { - for (int i=0; i != nbW; ++i) - { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - vv = {u,v}; - returnValue = this->insert_simplex(vv,Filtration_value(0.0)); - //print_sc(root()); std::cout << std::endl; - //std::cout << "Added edges" << std::endl; - } - //print_sc(root()); - for (int i=0; i != nbW; ++i) - { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - if ( u > v) - { - u = v; - v = knn[i][0]; - knn[i][0] = knn[i][1]; - knn[i][1] = v; - } - Simplex_handle sh; - vv = {u,v}; - sh = (root()->find(u))->second.children()->find(v); - active_w.push_back(i); - } - } - //std::cout << "Successfully added edges" << std::endl; - while (!active_w.empty() && k < nbL ) - { - //std::cout << "Started the step k=" << k << std::endl; - typename ActiveWitnessList::iterator it = active_w.begin(); - while (it != active_w.end()) - { - typeVectorVertex simplex_vector; - /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/ - // First sort the first k landmarks - VertexHandle inserted_vertex = knn[*it][k]; - bool ok = all_faces_in(knn, *it, k, inserted_vertex); - if (ok) - { - for (int i = 0; i != k+1; ++i) - simplex_vector.push_back(knn[*it][i]); - returnValue = insert_simplex(simplex_vector,0.0); - it++; - } - else - active_w.erase(it++); //First increase the iterator and then erase the previous element - } - k++; - } - //print_sc(root()); std::cout << std::endl; - } - - /** \brief Construction of witness complex from points given explicitly - * nbL must be set to the right value of landmarks for strategies - * FURTHEST_POINT_STRATEGY and RANDOM_POINT_STRATEGY and - * density must be set to the right value for DENSITY_STRATEGY - */ - void witness_complex_from_points(Point_Vector point_vector) - { - std::vector > WL; - clock_t start,end; - start = clock(); - landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); - end = clock(); - std::cout << "Landmarks took " << (double)(end-start)/CLOCKS_PER_SEC << "s.\n"; - start = clock(); - witness_complex(WL); - end = clock(); - std::cout << "Complex construction took " << (double)(end-start)/CLOCKS_PER_SEC << "s.\n"; - } - -private: - - /** \brief Print functions - */ - void print_sc(Siblings * sibl) - { - if (sibl == NULL) - std::cout << "&"; - else - print_children(sibl->members_); - } - - void print_children(Dictionary map) - { - std::cout << "("; - if (!map.empty()) - { - std::cout << map.begin()->first; - if (has_children(map.begin())) - print_sc(map.begin()->second.children()); - typename Dictionary::iterator it; - for (it = map.begin()+1; it != map.end(); ++it) - { - std::cout << "," << it->first; - if (has_children(it)) - print_sc(it->second.children()); - } - } - std::cout << ")"; - } - - public: - /** \brief Print functions - */ - - void st_to_file(std::ofstream& out_file) - { - sc_to_file(out_file, root()); - } - - private: - void sc_to_file(std::ofstream& out_file, Siblings * sibl) - { - if (sibl == NULL) - out_file << "&"; - else - children_to_file(out_file, sibl->members_); - } - - void children_to_file(std::ofstream& out_file, Dictionary map) - { - out_file << "("; - if (!map.empty()) - { - out_file << map.begin()->first; - if (has_children(map.begin())) - sc_to_file(out_file, map.begin()->second.children()); - typename Dictionary::iterator it; - for (it = map.begin()+1; it != map.end(); ++it) - { - out_file << "," << it->first; - if (has_children(it)) - sc_to_file(out_file, it->second.children()); - } - } - out_file << ")"; - } - - - /** \brief Check if the facets of the k-dimensional simplex witnessed - * by witness witness_id are already in the complex. - * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id - */ - template - bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) - { - //std::cout << "All face in with the landmark " << inserted_vertex << std::endl; - std::vector< VertexHandle > facet; - //VertexHandle curr_vh = curr_sh->first; - // CHECK ALL THE FACETS - for (int i = 0; i != k+1; ++i) - { - if (knn[witness_id][i] != inserted_vertex) - { - facet = {}; - for (int j = 0; j != k+1; ++j) - { - if (j != i) - { - facet.push_back(knn[witness_id][j]); - } - }//endfor - if (find(facet) == null_simplex()) - return false; - //std::cout << "++++ finished loop safely\n"; - }//endif - } //endfor - return true; - } - - template - void print_vector(std::vector v) - { - std::cout << "["; - if (!v.empty()) - { - std::cout << *(v.begin()); - for (auto it = v.begin()+1; it != v.end(); ++it) - { - std::cout << ","; - std::cout << *it; - } - } - std::cout << "]"; - } - - template - void print_vvector(std::vector< std::vector > vv) - { - std::cout << "["; - if (!vv.empty()) - { - print_vector(*(vv.begin())); - for (auto it = vv.begin()+1; it != vv.end(); ++it) - { - std::cout << ","; - print_vector(*it); - } - } - std::cout << "]\n"; - } - -/** - * \brief Landmark choice strategy by iteratively adding the landmark the furthest from the - * current landmark set - * \arg W is the vector of points which will be the witnesses - * \arg nbP is the number of witnesses - * \arg nbL is the number of landmarks - * \arg WL is the matrix of the nearest landmarks with respect to witnesses (output) - */ - - template - void landmark_choice_by_furthest_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) - { - //std::cout << "Enter landmark_choice_by_furthest_points "<< std::endl; - //std::cout << "W="; print_vvector(W); - //double density = 5.; - Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks - typeVectorVertex chosen_landmarks; // landmark list - - WL = KNearestNeighbours(nbP,std::vector()); - int current_number_of_landmarks=0; // counter for landmarks - double curr_max_dist = 0; // used for defining the furhest point from L - double curr_dist; // used to stock the distance from the current point to L - double infty = std::numeric_limits::infinity(); // infinity (see next entry) - std::vector< double > dist_to_L(nbP,infty); // vector of current distances to L from points - // double mindist = infty; - int curr_max_w=0; // the point currently furthest from L - int j; - int temp_swap_int; - double temp_swap_double; - - //CHOICE OF THE FIRST LANDMARK - std::cout << "Enter the first landmark stage\n"; - srand(354698); - int rand_int = rand()% nbP; - curr_max_w = rand_int; //For testing purposes a pseudo-random number is used here - - for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) - { - //curr_max_w at this point is the next landmark - chosen_landmarks.push_back(curr_max_w); - //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; - //std::cout << "WL="; print_vvector(WL); - //std::cout << "WLD="; print_vvector(wit_land_dist); - //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; - for (auto v: WL) - v.push_back(current_number_of_landmarks); - //#pragma omp parallel for - for (int i = 0; i < nbP; ++i) - { - // iteration on points in W. update of distance vectors - - //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; - //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; - curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); - //std::cout << "The problem is not in distance function\n"; - wit_land_dist[i].push_back(curr_dist); - WL[i].push_back(current_number_of_landmarks); - //std::cout << "Push't back\n"; - if (curr_dist < dist_to_L[i]) - dist_to_L[i] = curr_dist; - j = current_number_of_landmarks; - //std::cout << "First half complete\n"; - while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) - { - // sort the closest landmark vector for every witness - temp_swap_int = WL[i][j]; - WL[i][j] = WL[i][j-1]; - WL[i][j-1] = temp_swap_int; - temp_swap_double = wit_land_dist[i][j]; - wit_land_dist[i][j] = wit_land_dist[i][j-1]; - wit_land_dist[i][j-1] = temp_swap_double; - --j; - } - //std::cout << "result WL="; print_vvector(WL); - //std::cout << "result WLD="; print_vvector(wit_land_dist); - //std::cout << "result distL="; print_vector(dist_to_L); std::cout << std::endl; - //std::cout << "End loop\n"; - } - //std::cout << "Distance to landmarks="; print_vector(dist_to_L); std::cout << std::endl; - curr_max_dist = 0; - //omp_set_variable() - #pragma omp parallel for - for (int i = 0; i < nbP; ++i) { - if (dist_to_L[i] > curr_max_dist) - { - //#pragma omp ordered - { - curr_max_dist = dist_to_L[i]; - curr_max_w = i; - } - } - } - /* - for (int i = 0; i < nbP; ++i) { - if (dist_to_L[i] > curr_max_dist) - { - { - curr_max_dist = dist_to_L[i]; - curr_max_w = i; - } - } - } - */ - //std::cout << "Chose " << curr_max_w << " as new landmark\n"; - } - //std::cout << endl; - } - - /** \brief Landmark choice strategy by taking random vertices for landmarks. - * - */ - - template - void landmark_choice_by_random_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) - { - //std::cout << "Enter landmark_choice_by_random_points "<< std::endl; - //std::cout << "W="; print_vvector(W); - std::unordered_set< int > chosen_landmarks; // landmark set - - Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks - - WL = KNearestNeighbours(nbP,std::vector()); - int current_number_of_landmarks=0; // counter for landmarks - - srand(24660); - int chosen_landmark = rand()%nbP; - double curr_dist; - - int j; - int temp_swap_int; - double temp_swap_double; - - - for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) - { - while (chosen_landmarks.find(chosen_landmark) != chosen_landmarks.end()) - { - srand((int)clock()); - chosen_landmark = rand()% nbP; - //std::cout << chosen_landmark << "\n"; - } - chosen_landmarks.insert(chosen_landmark); - //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; - //std::cout << "WL="; print_vvector(WL); - //std::cout << "WLD="; print_vvector(wit_land_dist); - //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; - for (auto v: WL) - v.push_back(current_number_of_landmarks); - for (int i = 0; i < nbP; ++i) - { - // iteration on points in W. update of distance vectors - - //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; - //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; - curr_dist = euclidean_distance(W[i],W[chosen_landmark]); - //std::cout << "The problem is not in distance function\n"; - wit_land_dist[i].push_back(curr_dist); - WL[i].push_back(current_number_of_landmarks); - //std::cout << "Push't back\n"; - j = current_number_of_landmarks; - //std::cout << "First half complete\n"; - while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) - { - // sort the closest landmark vector for every witness - temp_swap_int = WL[i][j]; - WL[i][j] = WL[i][j-1]; - WL[i][j-1] = temp_swap_int; - temp_swap_double = wit_land_dist[i][j]; - wit_land_dist[i][j] = wit_land_dist[i][j-1]; - wit_land_dist[i][j-1] = temp_swap_double; - --j; - } - //std::cout << "result WL="; print_vvector(WL); - //std::cout << "result WLD="; print_vvector(wit_land_dist); - //std::cout << "End loop\n"; - } - } - //std::cout << endl; - } - - -}; //class Witness_complex - - - -} // namespace Guhdi - -#endif -- cgit v1.2.3 From 244d9ce5a5cb9050255cf519def9bdb273646f81 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 8 Apr 2015 14:50:03 +0000 Subject: Added rock-age style off reader git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@553 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 74462161c45893cfbfcc1875569b93b365445e35 --- CMakeLists.txt | 12 +++--- .../example/witness_complex_from_file.cpp | 43 +++++++++++++++++++++- .../include/gudhi/Witness_complex.h | 4 +- 3 files changed, 50 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/CMakeLists.txt b/CMakeLists.txt index fabba412..0684b18e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ if(MSVC) # Turn off some VC++ warnings SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4668 /wd4311 /wd4800 /wd4820 /wd4503 /wd4244 /wd4345 /wd4996 /wd4396 /wd4018") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -std=c++11 -Wall -Wpedantic -Wsign-compare") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -std=c++11 -Wall -Wsign-compare") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -O0") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") endif() @@ -24,12 +24,12 @@ set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost) -find_package(GMP) -if(GMP_FOUND) - find_package(GMPXX) -endif() +#find_package(GMP) +#if(GMP_FOUND) + #find_package(GMPXX) +#endif() -find_package(CGAL) +#find_package(CGAL) # Required programs for unitary tests purpose FIND_PROGRAM( LCOV_PATH lcov ) diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index cec1d1b8..b1d7575a 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -28,7 +28,7 @@ //#include "gudhi/graph_simplicial_complex.h" #include "gudhi/Witness_complex.h" - +#include "gudhi/reader_utils.h" using namespace Gudhi; @@ -65,6 +65,44 @@ read_points_cust ( std::string file_name , std::vector< std::vector< double > > in_file.close(); } +/** + * \brief Rock age method of reading off file + * + */ +inline void +off_reader_cust ( std::string file_name , std::vector< std::vector< double > > & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + // Line OFF. No need in it + if (!getline(in_file, line)) + { + std::cerr << "No line OFF\n"; + return; + } + // Line with 3 numbers. No need + if (!getline(in_file, line)) + { + std::cerr << "No line with 3 numbers\n"; + return; + } + // Reading points + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + points.push_back(point); + } + in_file.close(); +} + int main (int argc, char * const argv[]) { if (argc != 3) @@ -83,7 +121,8 @@ int main (int argc, char * const argv[]) std::cout << "Let the carnage begin!\n"; start = clock(); Point_Vector point_vector; - read_points_cust(file_name, point_vector); + off_reader_cust(file_name, point_vector); + std::cout << "Successfully read the points\n"; witnessComplex.setNbL(nbL); witnessComplex.witness_complex_from_points(point_vector); end = clock(); diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 1b50ca95..f4b1d62c 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -184,6 +184,7 @@ namespace Gudhi { active_w.push_back(i); } } + std::cout << "k=1, active witnesses: " << active_w.size() << std::endl; //std::cout << "Successfully added edges" << std::endl; while (!active_w.empty() && k < nbL ) { @@ -206,6 +207,7 @@ namespace Gudhi { else active_w.erase(it++); //First increase the iterator and then erase the previous element } + std::cout << "k=" << k << ", active witnesses: " << active_w.size() << std::endl; k++; } //print_sc(root()); std::cout << std::endl; @@ -453,7 +455,7 @@ private: template void landmark_choice_by_random_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) { - //std::cout << "Enter landmark_choice_by_random_points "<< std::endl; + std::cout << "Enter landmark_choice_by_random_points "<< std::endl; //std::cout << "W="; print_vvector(W); std::unordered_set< int > chosen_landmarks; // landmark set -- cgit v1.2.3 From 3f659091c2e941714cc3de101d8525c5ea28b2de Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 8 Apr 2015 14:56:13 +0000 Subject: Added witness_complex_from_off git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@554 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 36536d49be6f49f9f388d3e8e61bcf09ed7e1424 --- .../example/witness_complex_from_file.cpp | 40 +----- .../example/witness_complex_from_off.cpp | 140 +++++++++++++++++++++ 2 files changed, 141 insertions(+), 39 deletions(-) create mode 100644 src/Witness_complex/example/witness_complex_from_off.cpp (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index b1d7575a..7460652f 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -65,44 +65,6 @@ read_points_cust ( std::string file_name , std::vector< std::vector< double > > in_file.close(); } -/** - * \brief Rock age method of reading off file - * - */ -inline void -off_reader_cust ( std::string file_name , std::vector< std::vector< double > > & points) -{ - std::ifstream in_file (file_name.c_str(),std::ios::in); - if(!in_file.is_open()) - { - std::cerr << "Unable to open file " << file_name << std::endl; - return; - } - std::string line; - double x; - // Line OFF. No need in it - if (!getline(in_file, line)) - { - std::cerr << "No line OFF\n"; - return; - } - // Line with 3 numbers. No need - if (!getline(in_file, line)) - { - std::cerr << "No line with 3 numbers\n"; - return; - } - // Reading points - while( getline ( in_file , line ) ) - { - std::vector< double > point; - std::istringstream iss( line ); - while(iss >> x) { point.push_back(x); } - points.push_back(point); - } - in_file.close(); -} - int main (int argc, char * const argv[]) { if (argc != 3) @@ -121,7 +83,7 @@ int main (int argc, char * const argv[]) std::cout << "Let the carnage begin!\n"; start = clock(); Point_Vector point_vector; - off_reader_cust(file_name, point_vector); + read_points_cust(file_name, point_vector); std::cout << "Successfully read the points\n"; witnessComplex.setNbL(nbL); witnessComplex.witness_complex_from_points(point_vector); diff --git a/src/Witness_complex/example/witness_complex_from_off.cpp b/src/Witness_complex/example/witness_complex_from_off.cpp new file mode 100644 index 00000000..b1d7575a --- /dev/null +++ b/src/Witness_complex/example/witness_complex_from_off.cpp @@ -0,0 +1,140 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex.h" +#include "gudhi/reader_utils.h" + +using namespace Gudhi; + +typedef std::vector< Vertex_handle > typeVectorVertex; +typedef std::vector< std::vector > Point_Vector; +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , std::vector< std::vector< double > > & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + if (point.size() != 1) + points.push_back(point); + } + in_file.close(); +} + +/** + * \brief Rock age method of reading off file + * + */ +inline void +off_reader_cust ( std::string file_name , std::vector< std::vector< double > > & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + // Line OFF. No need in it + if (!getline(in_file, line)) + { + std::cerr << "No line OFF\n"; + return; + } + // Line with 3 numbers. No need + if (!getline(in_file, line)) + { + std::cerr << "No line with 3 numbers\n"; + return; + } + // Reading points + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + points.push_back(point); + } + in_file.close(); +} + +int main (int argc, char * const argv[]) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] + << " path_to_point_file nbL \n"; + return 0; + } + std::string file_name = argv[1]; + int nbL = atoi(argv[2]); + + clock_t start, end; + //Construct the Simplex Tree + Witness_complex<> witnessComplex; + + std::cout << "Let the carnage begin!\n"; + start = clock(); + Point_Vector point_vector; + off_reader_cust(file_name, point_vector); + std::cout << "Successfully read the points\n"; + witnessComplex.setNbL(nbL); + witnessComplex.witness_complex_from_points(point_vector); + end = clock(); + std::cout << "Howdy world! The process took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + char buffer[100]; + int i = sprintf(buffer,"%s_%s_result.txt",argv[1],argv[2]); + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } +} -- cgit v1.2.3 From 7e1913f458abc7f526459c775f4b6e0c4a6d9ac0 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 8 Apr 2015 16:46:42 +0000 Subject: witness_from_points now creates an output directory+WL matrix output git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@555 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b5f1886dcc06e606d21e5e20cb5f394cf3920ea4 --- .../example/witness_complex_from_file.cpp | 57 +++++++++++++++++++--- .../include/gudhi/Witness_complex.h | 3 +- 2 files changed, 52 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index 7460652f..be4869ea 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -24,13 +24,17 @@ #include #include +#include +#include //#include //#include "gudhi/graph_simplicial_complex.h" #include "gudhi/Witness_complex.h" #include "gudhi/reader_utils.h" +//#include using namespace Gudhi; +//using namespace boost::filesystem; typedef std::vector< Vertex_handle > typeVectorVertex; typedef std::vector< std::vector > Point_Vector; @@ -65,14 +69,32 @@ read_points_cust ( std::string file_name , std::vector< std::vector< double > > in_file.close(); } +void write_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto l: w) + ofs << l << " "; + ofs << "\n"; + } + ofs.close(); +} + int main (int argc, char * const argv[]) { - if (argc != 3) - { - std::cerr << "Usage: " << argv[0] - << " path_to_point_file nbL \n"; - return 0; - } + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] + << " path_to_point_file nbL \n"; + return 0; + } + /* + boost::filesystem::path p; + + for (; argc > 2; --argc, ++argv) + p /= argv[1]; + */ std::string file_name = argv[1]; int nbL = atoi(argv[2]); @@ -86,10 +108,24 @@ int main (int argc, char * const argv[]) read_points_cust(file_name, point_vector); std::cout << "Successfully read the points\n"; witnessComplex.setNbL(nbL); - witnessComplex.witness_complex_from_points(point_vector); + // witnessComplex.witness_complex_from_points(point_vector); + std::vector > WL; + witnessComplex.landmark_choice_by_random_points(point_vector, point_vector.size(), WL); + // Write the WL matrix in a file + mkdir("output", S_IRWXU); + const size_t last_slash_idx = file_name.find_last_of("/"); + if (std::string::npos != last_slash_idx) + { + file_name.erase(0, last_slash_idx + 1); + } + std::string out_file = "output/"+file_name+"_"+argv[2]+".wl"; + write_wl(out_file,WL); + witnessComplex.witness_complex(WL); + // end = clock(); std::cout << "Howdy world! The process took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + /* char buffer[100]; int i = sprintf(buffer,"%s_%s_result.txt",argv[1],argv[2]); if (i >= 0) @@ -99,4 +135,11 @@ int main (int argc, char * const argv[]) witnessComplex.st_to_file(ofs); ofs.close(); } + */ + + out_file = "output/"+file_name+"_"+argv[2]+".stree"; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index f4b1d62c..89abeb1f 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -356,7 +356,8 @@ private: } std::cout << "]\n"; } - + + public: /** * \brief Landmark choice strategy by iteratively adding the landmark the furthest from the * current landmark set -- cgit v1.2.3 From f3d75e50187c04d7be3f55fe9fbb77fb3ed90888 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 8 Apr 2015 16:51:33 +0000 Subject: added separate time for landmarks and complex construction git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@556 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 11f86285979963b9dd0cd65fcc1229bb8f5323b6 --- src/Witness_complex/example/witness_complex_from_file.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index be4869ea..35c00003 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -103,14 +103,17 @@ int main (int argc, char * const argv[]) Witness_complex<> witnessComplex; std::cout << "Let the carnage begin!\n"; - start = clock(); Point_Vector point_vector; read_points_cust(file_name, point_vector); - std::cout << "Successfully read the points\n"; + //std::cout << "Successfully read the points\n"; witnessComplex.setNbL(nbL); // witnessComplex.witness_complex_from_points(point_vector); std::vector > WL; + start = clock(); witnessComplex.landmark_choice_by_random_points(point_vector, point_vector.size(), WL); + end = clock(); + std::cout << "Landmark choice took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; // Write the WL matrix in a file mkdir("output", S_IRWXU); const size_t last_slash_idx = file_name.find_last_of("/"); @@ -120,6 +123,7 @@ int main (int argc, char * const argv[]) } std::string out_file = "output/"+file_name+"_"+argv[2]+".wl"; write_wl(out_file,WL); + start = clock(); witnessComplex.witness_complex(WL); // end = clock(); -- cgit v1.2.3 From f6bd8bf87d5033a6f9c4ce726bfb040ccb6b452f Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 9 Apr 2015 07:36:16 +0000 Subject: Added witness complex from wl matrix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@557 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 61865da9db4f3a4a42b1d4e9e60a33b7671e5df2 --- src/Witness_complex/example/CMakeLists.txt | 4 + .../example/witness_complex_from_wl_matrix.cpp | 160 +++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 src/Witness_complex/example/witness_complex_from_wl_matrix.cpp (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 74007c65..51f7976b 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -7,6 +7,10 @@ add_test(simple_witness_complex ${CMAKE_CURRENT_BINARY_DIR}/simple_witness_compl add_executable( witness_complex_from_file witness_complex_from_file.cpp ) add_test( witness_complex_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 ) +add_executable( witness_complex_from_off witness_complex_from_off.cpp ) + +add_executable( witness_complex_from_wl_matrix witness_complex_from_wl_matrix.cpp ) + # An example with Simplex-tree using CGAL alpha_shapes_3 #if(GMP_FOUND AND CGAL_FOUND) # message("CGAL_lib = ${CGAL_LIBRARIES_DIR}") diff --git a/src/Witness_complex/example/witness_complex_from_wl_matrix.cpp b/src/Witness_complex/example/witness_complex_from_wl_matrix.cpp new file mode 100644 index 00000000..2fec499c --- /dev/null +++ b/src/Witness_complex/example/witness_complex_from_wl_matrix.cpp @@ -0,0 +1,160 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 + +//#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex.h" +#include "gudhi/reader_utils.h" +//#include + +using namespace Gudhi; +//using namespace boost::filesystem; + +typedef std::vector< Vertex_handle > typeVectorVertex; +typedef std::vector< std::vector > Point_Vector; +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , std::vector< std::vector< double > > & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + if (point.size() != 1) + points.push_back(point); + } + in_file.close(); +} + +void write_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto l: w) + ofs << l << " "; + ofs << "\n"; + } + ofs.close(); +} + +void read_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + int x; + while( getline ( in_file , line ) ) + { + std::vector< int > witness; + std::istringstream iss( line ); + while(iss >> x) { witness.push_back(x); } + WL.push_back(witness); + } + in_file.close(); + +} + +int main (int argc, char * const argv[]) +{ + if (argc != 2) + { + std::cerr << "Usage: " << argv[0] + << " path_to_point_file \n"; + return 0; + } + /* + boost::filesystem::path p; + + for (; argc > 2; --argc, ++argv) + p /= argv[1]; + */ + std::string file_name = argv[1]; + //int nbL = atoi(argv[2]); + + clock_t start, end; + //Construct the Simplex Tree + Witness_complex<> witnessComplex; + + std::cout << "Let the carnage begin!\n"; + Point_Vector point_vector; + read_points_cust(file_name, point_vector); + //std::cout << "Successfully read the points\n"; + // witnessComplex.witness_complex_from_points(point_vector); + std::vector > WL; + read_wl(file_name,WL); + witnessComplex.setNbL(WL[0].size()); + // Write the WL matrix in a file + std::string out_file; + write_wl(out_file,WL); + start = clock(); + witnessComplex.witness_complex(WL); + // + end = clock(); + std::cout << "Howdy world! The process took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + /* + char buffer[100]; + int i = sprintf(buffer,"%s_%s_result.txt",argv[1],argv[2]); + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } + */ + + out_file = "output/"+file_name+"_"+argv[2]+".stree"; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + +} -- cgit v1.2.3 From ec1bdf0a6eae6708e9071c9f332c6c4782c2884c Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 9 Apr 2015 16:05:11 +0000 Subject: Added is_pseudomanifold & Co functions. It compiles. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@558 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e4569f2ef6e36cca22b4a3856b3631c324c506c8 --- .../example/witness_complex_from_wl_matrix.cpp | 12 -- .../include/gudhi/Witness_complex.h | 137 ++++++++++++++++++++- 2 files changed, 136 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_wl_matrix.cpp b/src/Witness_complex/example/witness_complex_from_wl_matrix.cpp index 2fec499c..614bb945 100644 --- a/src/Witness_complex/example/witness_complex_from_wl_matrix.cpp +++ b/src/Witness_complex/example/witness_complex_from_wl_matrix.cpp @@ -140,18 +140,6 @@ int main (int argc, char * const argv[]) end = clock(); std::cout << "Howdy world! The process took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; - /* - char buffer[100]; - int i = sprintf(buffer,"%s_%s_result.txt",argv[1],argv[2]); - if (i >= 0) - { - std::string out_file = (std::string)buffer; - std::ofstream ofs (out_file, std::ofstream::out); - witnessComplex.st_to_file(ofs); - ofs.close(); - } - */ - out_file = "output/"+file_name+"_"+argv[2]+".stree"; std::ofstream ofs (out_file, std::ofstream::out); witnessComplex.st_to_file(ofs); diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 89abeb1f..ef470589 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -38,6 +38,10 @@ #include #include +#include +#include +#include + namespace Gudhi { @@ -93,7 +97,7 @@ namespace Gudhi { typedef int Witness_id; typedef int Landmark_id; typedef std::list< Vertex_handle > ActiveWitnessList; - + private: /** Number of landmarks */ @@ -521,7 +525,138 @@ private: //std::cout << endl; } + void write_bad_links(std::ofstream& out_file) + { + out_file << "Bad links list\n"; + for (auto v: complex_vertex_range()) + { + std::vector< Vertex_handle > link_vertices; + // Fill link_vertices + for (auto u: complex_vertex_range()) + if (u != v && find({u,v}) != null_simplex()) + link_vertices.push_back(u); + // Find the dimension + int d = link_dim(link_vertices, link_vertices.begin(),root(),0); + //Siblings* curr_sibl = root(); + bool b = link_is_pseudomanifold(link_vertices,d); + } + } + + private: + int link_dim(std::vector< Vertex_handle >& link_vertices, + typename std::vector< Vertex_handle >::iterator& curr_v, + Siblings* curr_sibl, int curr_d) + { + Simplex_handle sh; + int final_d = curr_d; + typename std::vector< Vertex_handle >::iterator it; + for (it = curr_v; it != link_vertices.end(); ++it) + { + sh = curr_sibl->find(*it); + if (sh != null_simplex()) + { + int d = link_dim(link_vertices, it+1, self_siblings(sh), curr_d+1); + if (d > final_d) + final_d = d; + } + } + return final_d; + } + + // color is false is a (d-1)-dim face, true is a d-dim face + //typedef bool Color; + // graph is an adjacency list + typedef typename boost::adjacency_list Adj_graph; + // map that gives to a certain simplex its node in graph and its dimension + //typedef std::pair Reference; + typedef boost::container::flat_map Graph_map; + typedef boost::graph_traits::vertex_descriptor Vertex_t; + typedef boost::graph_traits::edge_descriptor Edge_t; + /* \brief Verifies if the simplices formed by vertices given by link_vertices + * form a pseudomanifold. + * The idea is to make a bipartite graph, where vertices are the d- and (d-1)-dimensional + * faces and edges represent adjacency between them. + */ + bool link_is_pseudomanifold(std::vector< Vertex_handle >& link_vertices, + int dimension) + { + Adj_graph adj_graph; + Graph_map d_map, f_map; // d_map = map for d-dimensional simplices, + // f_map = map for its facets + add_vertices_edges(link_vertices, + link_vertices.begin(), + adj_graph, + d_map, + f_map, + root(), + 0, dimension); + for (auto f_map_it : f_map) + if (boost::out_degree(f_map_it->second, adj_graph) != 2) + return false; + // At this point I know that all (d-1)-simplices are adjacent to exactly 2 d-simplices + // What is left is to check the connexity + std::vector components(boost::num_vertices(adj_graph)); + return (boost::connected_components(adj_graph, &components[0]) == 1); + } + + void add_vertices_edges(typeVectorVertex& link_vertices, + typename typeVectorVertex::iterator curr_v, + Adj_graph& adj_graph, + Graph_map& d_map, + Graph_map& f_map, + Siblings* curr_sibl, + int curr_d, + int dimension) + { + Simplex_handle sh; + Vertex_t vert; + typename typeVectorVertex::iterator it; + //Add vertices + for (it = curr_v; it != link_vertices.end(); ++it) + { + sh = curr_sibl->find(*it); + if (sh != null_simplex()) + { + if (curr_d == dimension) + { + vert = boost::add_vertex(adj_graph); + f_map.insert(sh,vert); + } + else + { + if (curr_d == dimension-1) + { + vert = boost::add_vertex(adj_graph); + d_map.insert(sh,vert); + } + add_vertices_edges(link_vertices, + it+1, + adj_graph, + d_map, + f_map, + self_siblings(sh), + curr_d+1, dimension); + } + } + } + // Add edges + typename Graph_map::iterator map_it; + for (auto d_map_it : d_map) + { + sh = d_map_it->first; + Vertex_t d_vert = d_map_it->second; + for (auto facet_sh : boundary_simplex_range(sh)) + //for (auto f_map_it : f_map) + { + map_it = f_map.find(facet_sh); + //We must have all the facets in the graph at this point + assert(map_it != f_map.end()); + Vertex_t f_vert = map_it->second; + boost::add_edge(d_vert,f_vert,adj_graph); + } + } + } }; //class Witness_complex -- cgit v1.2.3 From 33149cf3d76704d90526484f82c4d537a91ecd91 Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 9 Apr 2015 16:59:17 +0000 Subject: write_bad_links compiles. 信じんない MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@559 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fbd82029f52cf2ed2a8d7379f8b55777f0758a25 --- .../example/witness_complex_from_file.cpp | 6 ++++- .../include/gudhi/Witness_complex.h | 29 ++++++++++++++-------- 2 files changed, 23 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index 35c00003..3e853f67 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -122,7 +122,7 @@ int main (int argc, char * const argv[]) file_name.erase(0, last_slash_idx + 1); } std::string out_file = "output/"+file_name+"_"+argv[2]+".wl"; - write_wl(out_file,WL); + //write_wl(out_file,WL); start = clock(); witnessComplex.witness_complex(WL); // @@ -146,4 +146,8 @@ int main (int argc, char * const argv[]) witnessComplex.st_to_file(ofs); ofs.close(); + out_file = "output/"+file_name+"_"+argv[2]+".badlinks"; + std::ofstream ofs2(out_file, std::ofstream::out); + witnessComplex.write_bad_links(ofs2); + ofs2.close(); } diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index ef470589..174af950 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -533,18 +533,22 @@ private: std::vector< Vertex_handle > link_vertices; // Fill link_vertices for (auto u: complex_vertex_range()) - if (u != v && find({u,v}) != null_simplex()) - link_vertices.push_back(u); + { + typeVectorVertex edge = {u,v}; + if (u != v && find(edge) != null_simplex()) + link_vertices.push_back(u); + } // Find the dimension int d = link_dim(link_vertices, link_vertices.begin(),root(),0); //Siblings* curr_sibl = root(); - bool b = link_is_pseudomanifold(link_vertices,d); + if (! link_is_pseudomanifold(link_vertices,d)) + out_file << "Bad link at " << v << "\n"; } } private: int link_dim(std::vector< Vertex_handle >& link_vertices, - typename std::vector< Vertex_handle >::iterator& curr_v, + typename std::vector< Vertex_handle >::iterator curr_v, Siblings* curr_sibl, int curr_d) { Simplex_handle sh; @@ -569,9 +573,10 @@ private: typedef typename boost::adjacency_list Adj_graph; // map that gives to a certain simplex its node in graph and its dimension //typedef std::pair Reference; - typedef boost::container::flat_map Graph_map; typedef boost::graph_traits::vertex_descriptor Vertex_t; typedef boost::graph_traits::edge_descriptor Edge_t; + + typedef boost::container::flat_map Graph_map; /* \brief Verifies if the simplices formed by vertices given by link_vertices * form a pseudomanifold. @@ -592,7 +597,7 @@ private: root(), 0, dimension); for (auto f_map_it : f_map) - if (boost::out_degree(f_map_it->second, adj_graph) != 2) + if (boost::out_degree(f_map_it.second, adj_graph) != 2) return false; // At this point I know that all (d-1)-simplices are adjacent to exactly 2 d-simplices // What is left is to check the connexity @@ -612,6 +617,8 @@ private: Simplex_handle sh; Vertex_t vert; typename typeVectorVertex::iterator it; + std::pair resPair; + //typename Graph_map::iterator resPair; //Add vertices for (it = curr_v; it != link_vertices.end(); ++it) { @@ -621,14 +628,14 @@ private: if (curr_d == dimension) { vert = boost::add_vertex(adj_graph); - f_map.insert(sh,vert); + resPair = f_map.emplace(sh,vert); } else { if (curr_d == dimension-1) { vert = boost::add_vertex(adj_graph); - d_map.insert(sh,vert); + resPair = d_map.emplace(sh,vert); } add_vertices_edges(link_vertices, it+1, @@ -642,10 +649,10 @@ private: } // Add edges typename Graph_map::iterator map_it; - for (auto d_map_it : d_map) + for (auto d_map_pair : d_map) { - sh = d_map_it->first; - Vertex_t d_vert = d_map_it->second; + sh = d_map_pair.first; + Vertex_t d_vert = d_map_pair.second; for (auto facet_sh : boundary_simplex_range(sh)) //for (auto f_map_it : f_map) { -- cgit v1.2.3 From 001cb626d2ce452e6c258eb326f60544be7c1b3c Mon Sep 17 00:00:00 2001 From: skachano Date: Fri, 10 Apr 2015 15:58:47 +0000 Subject: write_bad_links works git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@562 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 70e8ec8512f15f990437b257beb3c67d55e1cb78 --- .../example/witness_complex_from_file.cpp | 2 +- .../include/gudhi/Witness_complex.h | 139 ++++++++++++++++----- 2 files changed, 108 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index 3e853f67..c0e062fd 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -110,7 +110,7 @@ int main (int argc, char * const argv[]) // witnessComplex.witness_complex_from_points(point_vector); std::vector > WL; start = clock(); - witnessComplex.landmark_choice_by_random_points(point_vector, point_vector.size(), WL); + witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); end = clock(); std::cout << "Landmark choice took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 174af950..c0199d92 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -528,8 +528,31 @@ private: void write_bad_links(std::ofstream& out_file) { out_file << "Bad links list\n"; + std::cout << "Entered write_bad_links\n"; + //typeVectorVertex testv = {9,15,17}; + /* + Mein lieber Gott! + Simplex_handle d1 = root()->members().find(9); + if (d1 != root()->members().end()) + { + Simplex_handle d2 = d1->second.children()->members().find(15); + if (d2 != d1->second.children()->members().end()) + { + Simplex_handle d3 = d2->second.children()->members().find(17); + if (d3 != d2->second.children()->members().end()) + std::cout << "{9,15,17} is there\n"; + else + std::cout << "Everything is jak maje być\n"; + } + else + std::cout << "{9,15} is not there\n"; + } + else + std::cout << "{9} is not there\n"; + */ for (auto v: complex_vertex_range()) { + //std::cout << "Vertex " << v << ":\n"; std::vector< Vertex_handle > link_vertices; // Fill link_vertices for (auto u: complex_vertex_range()) @@ -538,8 +561,14 @@ private: if (u != v && find(edge) != null_simplex()) link_vertices.push_back(u); } + /* + print_vector(link_vertices); + std::cout << "\n"; + */ // Find the dimension - int d = link_dim(link_vertices, link_vertices.begin(),root(),0); + typeVectorVertex empty_simplex = {}; + int d = link_dim(link_vertices, link_vertices.begin(),-1, empty_simplex); + //std::cout << " dim " << d << "\n"; //Siblings* curr_sibl = root(); if (! link_is_pseudomanifold(link_vertices,d)) out_file << "Bad link at " << v << "\n"; @@ -547,22 +576,37 @@ private: } private: + int link_dim(std::vector< Vertex_handle >& link_vertices, typename std::vector< Vertex_handle >::iterator curr_v, - Siblings* curr_sibl, int curr_d) + int curr_d, + typeVectorVertex& curr_simplex) { + //std::cout << "Entered link_dim for " << *(curr_v-1) << "\n"; Simplex_handle sh; int final_d = curr_d; typename std::vector< Vertex_handle >::iterator it; for (it = curr_v; it != link_vertices.end(); ++it) { - sh = curr_sibl->find(*it); + curr_simplex.push_back(*it); + /* + std::cout << "Searching for "; + print_vector(curr_simplex); + std::cout << " curr_dim " << curr_d << " final_dim " << final_d; + */ + sh = find(curr_simplex); if (sh != null_simplex()) { - int d = link_dim(link_vertices, it+1, self_siblings(sh), curr_d+1); + //std::cout << " -> " << *it << "\n"; + int d = link_dim(link_vertices, it+1, curr_d+1, curr_simplex); if (d > final_d) final_d = d; } + /* + else + std::cout << "\n"; + */ + curr_simplex.pop_back(); } return final_d; } @@ -587,32 +631,39 @@ private: int dimension) { Adj_graph adj_graph; - Graph_map d_map, f_map; // d_map = map for d-dimensional simplices, + Graph_map d_map, f_map; // d_map = map for d-dimensional simplices // f_map = map for its facets - add_vertices_edges(link_vertices, - link_vertices.begin(), - adj_graph, - d_map, - f_map, - root(), - 0, dimension); + typeVectorVertex empty_vector = {}; + add_vertices(link_vertices, + link_vertices.begin(), + adj_graph, + d_map, + f_map, + empty_vector, + 0, dimension); + //std::cout << "DMAP_SIZE: " << d_map.size() << "\n"; + //std::cout << "FMAP_SIZE: " << f_map.size() << "\n"; + add_edges(adj_graph, d_map, f_map); for (auto f_map_it : f_map) - if (boost::out_degree(f_map_it.second, adj_graph) != 2) - return false; + { + //std::cout << "Degree of " << f_map_it.first->first << " is " << boost::out_degree(f_map_it.second, adj_graph) << "\n"; + if (boost::out_degree(f_map_it.second, adj_graph) != 2) + return false; + } // At this point I know that all (d-1)-simplices are adjacent to exactly 2 d-simplices // What is left is to check the connexity std::vector components(boost::num_vertices(adj_graph)); return (boost::connected_components(adj_graph, &components[0]) == 1); } - void add_vertices_edges(typeVectorVertex& link_vertices, - typename typeVectorVertex::iterator curr_v, - Adj_graph& adj_graph, - Graph_map& d_map, - Graph_map& f_map, - Siblings* curr_sibl, - int curr_d, - int dimension) + void add_vertices(typeVectorVertex& link_vertices, + typename typeVectorVertex::iterator curr_v, + Adj_graph& adj_graph, + Graph_map& d_map, + Graph_map& f_map, + typeVectorVertex& curr_simplex, + int curr_d, + int dimension) { Simplex_handle sh; Vertex_t vert; @@ -620,46 +671,70 @@ private: std::pair resPair; //typename Graph_map::iterator resPair; //Add vertices + //std::cout << "Entered add vertices\n"; for (it = curr_v; it != link_vertices.end(); ++it) { - sh = curr_sibl->find(*it); + curr_simplex.push_back(*it); + /* + std::cout << "Searching for "; + print_vector(curr_simplex); + std::cout << " curr_dim " << curr_d << " d " << dimension << ""; + */ + sh = find(curr_simplex); if (sh != null_simplex()) { + //std::cout << " added\n"; if (curr_d == dimension) { vert = boost::add_vertex(adj_graph); - resPair = f_map.emplace(sh,vert); + resPair = d_map.emplace(sh,vert); } else { if (curr_d == dimension-1) { vert = boost::add_vertex(adj_graph); - resPair = d_map.emplace(sh,vert); + resPair = f_map.emplace(sh,vert); } - add_vertices_edges(link_vertices, - it+1, - adj_graph, - d_map, - f_map, - self_siblings(sh), - curr_d+1, dimension); + add_vertices(link_vertices, + it+1, + adj_graph, + d_map, + f_map, + curr_simplex, + curr_d+1, dimension); } } + /* + else + std::cout << "\n"; + */ + curr_simplex.pop_back(); } + } + + void add_edges(Adj_graph& adj_graph, + Graph_map& d_map, + Graph_map& f_map) + { + Simplex_handle sh; // Add edges + //std::cout << "Entered add edges:\n"; typename Graph_map::iterator map_it; for (auto d_map_pair : d_map) { + //std::cout << "*"; sh = d_map_pair.first; Vertex_t d_vert = d_map_pair.second; for (auto facet_sh : boundary_simplex_range(sh)) //for (auto f_map_it : f_map) { + //std::cout << "'"; map_it = f_map.find(facet_sh); //We must have all the facets in the graph at this point assert(map_it != f_map.end()); Vertex_t f_vert = map_it->second; + //std::cout << "Added edge " << sh->first << "-" << map_it->first->first << "\n"; boost::add_edge(d_vert,f_vert,adj_graph); } } -- cgit v1.2.3 From 2d0c9ac7759dde1b0d2e41a147ac1a82bbc0081d Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 14 Apr 2015 16:33:51 +0000 Subject: Ready for testing! git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@565 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4cce2055368e8d9ade18d522d16daeea32acb893 --- .../example/witness_complex_from_file.cpp | 3 +- .../example/witness_complex_from_off.cpp | 44 +++++++++++++++++++++- .../include/gudhi/Witness_complex.h | 26 +++---------- 3 files changed, 50 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index c0e062fd..cf09899b 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -110,7 +110,8 @@ int main (int argc, char * const argv[]) // witnessComplex.witness_complex_from_points(point_vector); std::vector > WL; start = clock(); - witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); + //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); + witnessComplex.landmark_choice_by_random_points(point_vector, point_vector.size(), WL); end = clock(); std::cout << "Landmark choice took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; diff --git a/src/Witness_complex/example/witness_complex_from_off.cpp b/src/Witness_complex/example/witness_complex_from_off.cpp index b1d7575a..04d4e601 100644 --- a/src/Witness_complex/example/witness_complex_from_off.cpp +++ b/src/Witness_complex/example/witness_complex_from_off.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include //#include @@ -117,7 +119,8 @@ int main (int argc, char * const argv[]) clock_t start, end; //Construct the Simplex Tree Witness_complex<> witnessComplex; - + + /* std::cout << "Let the carnage begin!\n"; start = clock(); Point_Vector point_vector; @@ -137,4 +140,43 @@ int main (int argc, char * const argv[]) witnessComplex.st_to_file(ofs); ofs.close(); } + */ + std::cout << "Let the carnage begin!\n"; + Point_Vector point_vector; + off_reader_cust(file_name, point_vector); + //std::cout << "Successfully read the points\n"; + witnessComplex.setNbL(nbL); + // witnessComplex.witness_complex_from_points(point_vector); + std::vector > WL; + start = clock(); + //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); + witnessComplex.landmark_choice_by_random_points(point_vector, point_vector.size(), WL); + end = clock(); + std::cout << "Landmark choice took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + // Write the WL matrix in a file + mkdir("output", S_IRWXU); + const size_t last_slash_idx = file_name.find_last_of("/"); + if (std::string::npos != last_slash_idx) + { + file_name.erase(0, last_slash_idx + 1); + } + std::string out_file = "output/"+file_name+"_"+argv[2]+".wl"; + //write_wl(out_file,WL); + start = clock(); + witnessComplex.witness_complex(WL); + // + end = clock(); + std::cout << "Howdy world! The process took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + + out_file = "output/"+file_name+"_"+argv[2]+".stree"; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + + out_file = "output/"+file_name+"_"+argv[2]+".badlinks"; + std::ofstream ofs2(out_file, std::ofstream::out); + witnessComplex.write_bad_links(ofs2); + ofs2.close(); } diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index c0199d92..f831ef44 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -530,26 +530,7 @@ private: out_file << "Bad links list\n"; std::cout << "Entered write_bad_links\n"; //typeVectorVertex testv = {9,15,17}; - /* - Mein lieber Gott! - Simplex_handle d1 = root()->members().find(9); - if (d1 != root()->members().end()) - { - Simplex_handle d2 = d1->second.children()->members().find(15); - if (d2 != d1->second.children()->members().end()) - { - Simplex_handle d3 = d2->second.children()->members().find(17); - if (d3 != d2->second.children()->members().end()) - std::cout << "{9,15,17} is there\n"; - else - std::cout << "Everything is jak maje być\n"; - } - else - std::cout << "{9,15} is not there\n"; - } - else - std::cout << "{9} is not there\n"; - */ + int count = 0; for (auto v: complex_vertex_range()) { //std::cout << "Vertex " << v << ":\n"; @@ -571,8 +552,11 @@ private: //std::cout << " dim " << d << "\n"; //Siblings* curr_sibl = root(); if (! link_is_pseudomanifold(link_vertices,d)) - out_file << "Bad link at " << v << "\n"; + count++; + //out_file << "Bad link at " << v << "\n"; } + out_file << "Number of bad links: " << count << "/" << root()->size(); + std::cout << "Number of bad links: " << count << "/" << root()->size() << std::endl; } private: -- cgit v1.2.3 From 5a60fe7321538379d0910166620c1b8c3655f53a Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 15 Apr 2015 13:22:25 +0000 Subject: Added more detailed output on bad links git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@566 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1c4a4b692f9ce68221ac3f104b10509ccb307231 --- .../include/gudhi/Witness_complex.h | 39 ++++++++++++++++++---- 1 file changed, 33 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index f831ef44..e2dcdf79 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -190,8 +190,12 @@ namespace Gudhi { } std::cout << "k=1, active witnesses: " << active_w.size() << std::endl; //std::cout << "Successfully added edges" << std::endl; + count_good = {0,0}; + count_bad = {0,0}; while (!active_w.empty() && k < nbL ) { + count_good.push_back(0); + count_bad.push_back(0); //std::cout << "Started the step k=" << k << std::endl; typename ActiveWitnessList::iterator it = active_w.begin(); while (it != active_w.end()) @@ -530,7 +534,7 @@ private: out_file << "Bad links list\n"; std::cout << "Entered write_bad_links\n"; //typeVectorVertex testv = {9,15,17}; - int count = 0; + //int count = 0; for (auto v: complex_vertex_range()) { //std::cout << "Vertex " << v << ":\n"; @@ -551,16 +555,36 @@ private: int d = link_dim(link_vertices, link_vertices.begin(),-1, empty_simplex); //std::cout << " dim " << d << "\n"; //Siblings* curr_sibl = root(); - if (! link_is_pseudomanifold(link_vertices,d)) - count++; + if (link_is_pseudomanifold(link_vertices,d)) + count_good[d]++; //out_file << "Bad link at " << v << "\n"; } - out_file << "Number of bad links: " << count << "/" << root()->size(); - std::cout << "Number of bad links: " << count << "/" << root()->size() << std::endl; + //out_file << "Number of bad links: " << count << "/" << root()->size(); + //std::cout << "Number of bad links: " << count << "/" << root()->size() << std::endl; + nc = nbL; + for (int i = 0; i != count_good.size(); i++) + { + out_file << "count_good[" << i << "] = " << count_good[i] << std::endl; + nc -= count_good[i]; + if (count_good[i] != 0) + std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; + } + for (int i = 0; i != count_bad.size(); i++) + { + out_file << "count_bad[" << i << "] = " << count_bad[i] << std::endl; + nc -= count_bad[i]; + if (count_bad[i] != 0) + std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; + } + std::cout << "not_connected = " << nc << std::endl; } private: + std::vector count_good; + std::vector count_bad; + int nc; + int link_dim(std::vector< Vertex_handle >& link_vertices, typename std::vector< Vertex_handle >::iterator curr_v, int curr_d, @@ -632,7 +656,10 @@ private: { //std::cout << "Degree of " << f_map_it.first->first << " is " << boost::out_degree(f_map_it.second, adj_graph) << "\n"; if (boost::out_degree(f_map_it.second, adj_graph) != 2) - return false; + { + count_bad[dimension]++; + return false; + } } // At this point I know that all (d-1)-simplices are adjacent to exactly 2 d-simplices // What is left is to check the connexity -- cgit v1.2.3 From d3cef9245dcff1ea585142ef0b711bb35b6f9338 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 15 Apr 2015 13:48:51 +0000 Subject: Landmark selection: now it's faster git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@567 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 24292a17b98074b7aff4693630829b636ba3d67a --- .../include/gudhi/Witness_complex.h | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index e2dcdf79..c633691b 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -510,22 +510,25 @@ private: //std::cout << "Push't back\n"; j = current_number_of_landmarks; //std::cout << "First half complete\n"; - while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) - { - // sort the closest landmark vector for every witness - temp_swap_int = WL[i][j]; - WL[i][j] = WL[i][j-1]; - WL[i][j-1] = temp_swap_int; - temp_swap_double = wit_land_dist[i][j]; - wit_land_dist[i][j] = wit_land_dist[i][j-1]; - wit_land_dist[i][j-1] = temp_swap_double; - --j; - } //std::cout << "result WL="; print_vvector(WL); //std::cout << "result WLD="; print_vvector(wit_land_dist); //std::cout << "End loop\n"; } } + for (int i = 0; i < nbP; i++) + { + // sort the closest landmark vector for every witness + sort(WL[i].begin(), WL[i].end(), [&](int j1, int j2){return wit_land_dist[i][j1] < wit_land_dist[i][j2];}); + /* + temp_swap_int = WL[i][j]; + WL[i][j] = WL[i][j-1]; + WL[i][j-1] = temp_swap_int; + temp_swap_double = wit_land_dist[i][j]; + wit_land_dist[i][j] = wit_land_dist[i][j-1]; + wit_land_dist[i][j-1] = temp_swap_double; + --j; + */ + } //std::cout << endl; } -- cgit v1.2.3 From eaedaf52122a397f35fb75df93f83ae9ffdceb7c Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 27 Apr 2015 10:24:05 +0000 Subject: Struggled with CMake... git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@579 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 38b558196806b226cba5e1ef30abb927619bbe33 --- CMakeLists.txt | 2 +- src/Witness_complex/example/CMakeLists.txt | 48 +++++++++++++++------- .../include/gudhi/Witness_complex.h | 42 +++++++++++-------- 3 files changed, 60 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/CMakeLists.txt b/CMakeLists.txt index 0684b18e..57cb14d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ find_package(Boost) #find_package(GMPXX) #endif() -#find_package(CGAL) +find_package(CGAL) # Required programs for unitary tests purpose FIND_PROGRAM( LCOV_PATH lcov ) diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 51f7976b..14d23551 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -1,23 +1,41 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIWitnessComplex) +#cmake -DCGAL_DIR=~/GitDrive/CGAL/ ../../.. -add_executable ( simple_witness_complex simple_witness_complex.cpp ) -add_test(simple_witness_complex ${CMAKE_CURRENT_BINARY_DIR}/simple_witness_complex) +#if (CGAL_FOUND) + #message(STATUS "CGAL version: ${CGAL_VERSION}.") + #include( ${CGAL_USE_FILE} ) -add_executable( witness_complex_from_file witness_complex_from_file.cpp ) -add_test( witness_complex_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 ) + #find_package(Eigen3 3.1.0) + #include( ${EIGEN3_USE_FILE} ) -add_executable( witness_complex_from_off witness_complex_from_off.cpp ) + #INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIR}) + #INCLUDE_DIRECTORIES(${CGAL_INCLUDE_DIRS}) + add_executable ( simple_witness_complex simple_witness_complex.cpp ) + add_test(simple_witness_complex ${CMAKE_CURRENT_BINARY_DIR}/simple_witness_complex) -add_executable( witness_complex_from_wl_matrix witness_complex_from_wl_matrix.cpp ) + #add_executable( witness_complex_from_file witness_complex_from_file.cpp ) + #target_link_libraries(witness_complex_from_file ${EIGEN3_LIBRARIES} ${CGAL_LIBRARY}) + #add_test( witness_complex_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + + add_executable( witness_complex_from_off witness_complex_from_off.cpp ) + + add_executable( witness_complex_from_wl_matrix witness_complex_from_wl_matrix.cpp ) +#endif() # An example with Simplex-tree using CGAL alpha_shapes_3 -#if(GMP_FOUND AND CGAL_FOUND) -# message("CGAL_lib = ${CGAL_LIBRARIES_DIR}") -# message("GMP_LIBRARIES = ${GMP_LIBRARIES}") -# INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) -# INCLUDE_DIRECTORIES(${CGAL_INCLUDE_DIRS}) -# add_executable ( simplex_tree_from_alpha_shapes_3 simplex_tree_from_alpha_shapes_3.cpp ) -# target_link_libraries(simplex_tree_from_alpha_shapes_3 ${GMP_LIBRARIES} ${CGAL_LIBRARY}) -# add_test(simplex_tree_from_alpha_shapes_3 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_alpha_shapes_3 ${CMAKE_SOURCE_DIR}/data/points/bunny_5000) -#endif() + +include( ${CGAL_USE_FILE} ) +find_package(Eigen3 3.1.0) +if(GMP_FOUND AND CGAL_FOUND) + message("CGAL_lib = ${CGAL_LIBRARIES_DIR}") + message("GMP_LIBRARIES = ${GMP_LIBRARIES}") + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + #message("EIGEN3_LIBRARIES = ${EIGEN3_LIBRARIES}") + INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIRS}) + INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) + INCLUDE_DIRECTORIES(${CGAL_INCLUDE_DIRS}) + add_executable (witness_complex_from_file witness_complex_from_file.cpp ) + target_link_libraries(witness_complex_from_file ${GMP_LIBRARIES} ${EIGEN3_LIBRARIES} ${CGAL_LIBRARY}) + add_test(witness_complex_from_file ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) +endif() diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index c633691b..3c030c45 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -38,6 +38,13 @@ #include #include +// Needed for nearest neighbours +//#include +#include +#include +#include + +// Needed for the adjacency graph in bad link search #include #include #include @@ -477,9 +484,9 @@ private: int chosen_landmark = rand()%nbP; double curr_dist; - int j; - int temp_swap_int; - double temp_swap_double; + //int j; + //int temp_swap_int; + //double temp_swap_double; for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) @@ -508,7 +515,7 @@ private: wit_land_dist[i].push_back(curr_dist); WL[i].push_back(current_number_of_landmarks); //std::cout << "Push't back\n"; - j = current_number_of_landmarks; + //j = current_number_of_landmarks; //std::cout << "First half complete\n"; //std::cout << "result WL="; print_vvector(WL); //std::cout << "result WLD="; print_vvector(wit_land_dist); @@ -517,21 +524,24 @@ private: } for (int i = 0; i < nbP; i++) { - // sort the closest landmark vector for every witness sort(WL[i].begin(), WL[i].end(), [&](int j1, int j2){return wit_land_dist[i][j1] < wit_land_dist[i][j2];}); - /* - temp_swap_int = WL[i][j]; - WL[i][j] = WL[i][j-1]; - WL[i][j-1] = temp_swap_int; - temp_swap_double = wit_land_dist[i][j]; - wit_land_dist[i][j] = wit_land_dist[i][j-1]; - wit_land_dist[i][j-1] = temp_swap_double; - --j; - */ } //std::cout << endl; } + /** \brief Construct the matrix |W|x(D+1) of D+1 closest landmarks + * where W is the set of witnesses and D is the ambient dimension + */ + template + void nearest_landmarks(Point_Vector &W, std::unordered_set &L, KNearestNeighbours &WL) + { + int D = W[0].size(); + + } + + /** \brief Search and output links around vertices that are not pseudomanifolds + * + */ void write_bad_links(std::ofstream& out_file) { out_file << "Bad links list\n"; @@ -565,14 +575,14 @@ private: //out_file << "Number of bad links: " << count << "/" << root()->size(); //std::cout << "Number of bad links: " << count << "/" << root()->size() << std::endl; nc = nbL; - for (int i = 0; i != count_good.size(); i++) + for (unsigned int i = 0; i != count_good.size(); i++) { out_file << "count_good[" << i << "] = " << count_good[i] << std::endl; nc -= count_good[i]; if (count_good[i] != 0) std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; } - for (int i = 0; i != count_bad.size(); i++) + for (unsigned int i = 0; i != count_bad.size(); i++) { out_file << "count_bad[" << i << "] = " << count_bad[i] << std::endl; nc -= count_bad[i]; -- cgit v1.2.3 From a99d289c4f37766bc262baa980284fa1a9816d42 Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 27 Apr 2015 16:23:54 +0000 Subject: Added the file for knn landmarks (no CGAL include yet). New algorithm for landmark selection: now 10 times faster! git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@580 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 9de270bd67ac33fd1079de7692dd8974441db606 --- src/Witness_complex/example/CMakeLists.txt | 10 +- .../example/witness_complex_from_file.cpp | 4 +- .../example/witness_complex_from_off.cpp | 4 +- .../example/witness_complex_knn_landmarks.cpp | 161 +++++++++++++++++++ .../include/gudhi/Witness_complex.h | 176 +++++++++++++++------ 5 files changed, 303 insertions(+), 52 deletions(-) create mode 100644 src/Witness_complex/example/witness_complex_knn_landmarks.cpp (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 14d23551..fa594de7 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -14,9 +14,9 @@ project(GUDHIWitnessComplex) add_executable ( simple_witness_complex simple_witness_complex.cpp ) add_test(simple_witness_complex ${CMAKE_CURRENT_BINARY_DIR}/simple_witness_complex) - #add_executable( witness_complex_from_file witness_complex_from_file.cpp ) + add_executable( witness_complex_from_file witness_complex_from_file.cpp ) #target_link_libraries(witness_complex_from_file ${EIGEN3_LIBRARIES} ${CGAL_LIBRARY}) - #add_test( witness_complex_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_test( witness_complex_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) add_executable( witness_complex_from_off witness_complex_from_off.cpp ) @@ -35,7 +35,7 @@ if(GMP_FOUND AND CGAL_FOUND) INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${CGAL_INCLUDE_DIRS}) - add_executable (witness_complex_from_file witness_complex_from_file.cpp ) - target_link_libraries(witness_complex_from_file ${GMP_LIBRARIES} ${EIGEN3_LIBRARIES} ${CGAL_LIBRARY}) - add_test(witness_complex_from_file ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_executable (witness_complex_knn_landmarks witness_complex_knn_landmarks.cpp ) + target_link_libraries(witness_complex_knn_landmarks ${EIGEN3_LIBRARIES} ${CGAL_LIBRARY}) + add_test(witness_complex_knn_landmarks ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_knn_landmarks ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) endif() diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index cf09899b..b842574b 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -109,9 +109,11 @@ int main (int argc, char * const argv[]) witnessComplex.setNbL(nbL); // witnessComplex.witness_complex_from_points(point_vector); std::vector > WL; + std::set L; start = clock(); //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); - witnessComplex.landmark_choice_by_random_points(point_vector, point_vector.size(), WL); + witnessComplex.landmark_choice_by_random_points(point_vector, point_vector.size(), L); + witnessComplex.nearest_landmarks(point_vector,L,WL); end = clock(); std::cout << "Landmark choice took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; diff --git a/src/Witness_complex/example/witness_complex_from_off.cpp b/src/Witness_complex/example/witness_complex_from_off.cpp index 04d4e601..948f09a8 100644 --- a/src/Witness_complex/example/witness_complex_from_off.cpp +++ b/src/Witness_complex/example/witness_complex_from_off.cpp @@ -148,9 +148,11 @@ int main (int argc, char * const argv[]) witnessComplex.setNbL(nbL); // witnessComplex.witness_complex_from_points(point_vector); std::vector > WL; + std::set L; start = clock(); //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); - witnessComplex.landmark_choice_by_random_points(point_vector, point_vector.size(), WL); + witnessComplex.landmark_choice_by_random_points(point_vector, point_vector.size(), L); + witnessComplex.nearest_landmarks(point_vector,L,WL); end = clock(); std::cout << "Landmark choice took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; diff --git a/src/Witness_complex/example/witness_complex_knn_landmarks.cpp b/src/Witness_complex/example/witness_complex_knn_landmarks.cpp new file mode 100644 index 00000000..2003f218 --- /dev/null +++ b/src/Witness_complex/example/witness_complex_knn_landmarks.cpp @@ -0,0 +1,161 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 + +//#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex.h" +#include "gudhi/reader_utils.h" +//#include + +//#include +//#include +#include + +using namespace Gudhi; +//using namespace boost::filesystem; + +typedef std::vector< Vertex_handle > typeVectorVertex; +typedef std::vector< std::vector > Point_Vector; +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , std::vector< std::vector< double > > & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + if (point.size() != 1) + points.push_back(point); + } + in_file.close(); +} + +void write_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto l: w) + ofs << l << " "; + ofs << "\n"; + } + ofs.close(); +} + +int main (int argc, char * const argv[]) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] + << " path_to_point_file nbL \n"; + return 0; + } + /* + boost::filesystem::path p; + + for (; argc > 2; --argc, ++argv) + p /= argv[1]; + */ + std::string file_name = argv[1]; + int nbL = atoi(argv[2]); + + clock_t start, end; + //Construct the Simplex Tree + Witness_complex<> witnessComplex; + + std::cout << "Let the carnage begin!\n"; + Point_Vector point_vector; + read_points_cust(file_name, point_vector); + //std::cout << "Successfully read the points\n"; + witnessComplex.setNbL(nbL); + // witnessComplex.witness_complex_from_points(point_vector); + std::vector > WL; + std::set L; + int nbP = point_vector.size(); + start = clock(); + //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); + witnessComplex.landmark_choice_by_random_points(point_vector, nbP, L); + witnessComplex.nearest_landmarks(point_vector,L,WL); + end = clock(); + std::cout << "Landmark choice took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + // Write the WL matrix in a file + mkdir("output", S_IRWXU); + const size_t last_slash_idx = file_name.find_last_of("/"); + if (std::string::npos != last_slash_idx) + { + file_name.erase(0, last_slash_idx + 1); + } + std::string out_file = "output/"+file_name+"_"+argv[2]+".wl"; + //write_wl(out_file,WL); + start = clock(); + witnessComplex.witness_complex(WL); + // + end = clock(); + std::cout << "Howdy world! The process took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + /* + char buffer[100]; + int i = sprintf(buffer,"%s_%s_result.txt",argv[1],argv[2]); + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } + */ + + out_file = "output/"+file_name+"_"+argv[2]+".stree"; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + + out_file = "output/"+file_name+"_"+argv[2]+".badlinks"; + std::ofstream ofs2(out_file, std::ofstream::out); + witnessComplex.write_bad_links(ofs2); + ofs2.close(); +} diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 3c030c45..2ccaa416 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -32,7 +32,8 @@ #include "gudhi/Simplex_tree.h" #include #include -#include +#include +#include #include #include #include @@ -40,9 +41,9 @@ // Needed for nearest neighbours //#include -#include -#include -#include +//#include +//#include +//#include // Needed for the adjacency graph in bad link search #include @@ -233,12 +234,12 @@ namespace Gudhi { * FURTHEST_POINT_STRATEGY and RANDOM_POINT_STRATEGY and * density must be set to the right value for DENSITY_STRATEGY */ - void witness_complex_from_points(Point_Vector point_vector) - { - std::vector > WL; - landmark_choice_by_random_points(point_vector, point_vector.size(), WL); - witness_complex(WL); - } + // void witness_complex_from_points(Point_Vector point_vector) + // { + // std::vector > WL; + // landmark_choice_by_random_points(point_vector, point_vector.size(), WL); + // witness_complex(WL); + // } private: @@ -468,75 +469,160 @@ private: * */ - template - void landmark_choice_by_random_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) + // template + // void landmark_choice_by_random_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) + // { + // std::cout << "Enter landmark_choice_by_random_points "<< std::endl; + // //std::cout << "W="; print_vvector(W); + // std::unordered_set< int > chosen_landmarks; // landmark set + + // Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks + + // WL = KNearestNeighbours(nbP,std::vector()); + // int current_number_of_landmarks=0; // counter for landmarks + + // srand(24660); + // int chosen_landmark = rand()%nbP; + // double curr_dist; + + // //int j; + // //int temp_swap_int; + // //double temp_swap_double; + + + // for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + // { + // while (chosen_landmarks.find(chosen_landmark) != chosen_landmarks.end()) + // { + // srand((int)clock()); + // chosen_landmark = rand()% nbP; + // //std::cout << chosen_landmark << "\n"; + // } + // chosen_landmarks.insert(chosen_landmark); + // //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; + // //std::cout << "WL="; print_vvector(WL); + // //std::cout << "WLD="; print_vvector(wit_land_dist); + // //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; + // for (auto v: WL) + // v.push_back(current_number_of_landmarks); + // for (int i = 0; i < nbP; ++i) + // { + // // iteration on points in W. update of distance vectors + + // //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; + // //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; + // curr_dist = euclidean_distance(W[i],W[chosen_landmark]); + // //std::cout << "The problem is not in distance function\n"; + // wit_land_dist[i].push_back(curr_dist); + // WL[i].push_back(current_number_of_landmarks); + // //std::cout << "Push't back\n"; + // //j = current_number_of_landmarks; + // //std::cout << "First half complete\n"; + // //std::cout << "result WL="; print_vvector(WL); + // //std::cout << "result WLD="; print_vvector(wit_land_dist); + // //std::cout << "End loop\n"; + // } + // } + // for (int i = 0; i < nbP; i++) + // { + // sort(WL[i].begin(), WL[i].end(), [&](int j1, int j2){return wit_land_dist[i][j1] < wit_land_dist[i][j2];}); + // } + // //std::cout << endl; + // } + + /** \brief Landmark choice strategy by taking random vertices for landmarks. + * + */ + + // template + void landmark_choice_by_random_points(Point_Vector &W, int nbP, std::set &L) { std::cout << "Enter landmark_choice_by_random_points "<< std::endl; //std::cout << "W="; print_vvector(W); - std::unordered_set< int > chosen_landmarks; // landmark set + //std::unordered_set< int > chosen_landmarks; // landmark set Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks - WL = KNearestNeighbours(nbP,std::vector()); + //WL = KNearestNeighbours(nbP,std::vector()); int current_number_of_landmarks=0; // counter for landmarks srand(24660); int chosen_landmark = rand()%nbP; - double curr_dist; - + //double curr_dist; //int j; //int temp_swap_int; - //double temp_swap_double; - - + //double temp_swap_double; for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) { - while (chosen_landmarks.find(chosen_landmark) != chosen_landmarks.end()) + while (L.find(chosen_landmark) != L.end()) { srand((int)clock()); chosen_landmark = rand()% nbP; //std::cout << chosen_landmark << "\n"; } - chosen_landmarks.insert(chosen_landmark); + L.insert(chosen_landmark); //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; //std::cout << "WL="; print_vvector(WL); //std::cout << "WLD="; print_vvector(wit_land_dist); //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; - for (auto v: WL) - v.push_back(current_number_of_landmarks); - for (int i = 0; i < nbP; ++i) - { - // iteration on points in W. update of distance vectors + // for (auto v: WL) + // v.push_back(current_number_of_landmarks); + // for (int i = 0; i < nbP; ++i) + // { + // // iteration on points in W. update of distance vectors - //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; - //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; - curr_dist = euclidean_distance(W[i],W[chosen_landmark]); - //std::cout << "The problem is not in distance function\n"; - wit_land_dist[i].push_back(curr_dist); - WL[i].push_back(current_number_of_landmarks); - //std::cout << "Push't back\n"; - //j = current_number_of_landmarks; - //std::cout << "First half complete\n"; - //std::cout << "result WL="; print_vvector(WL); - //std::cout << "result WLD="; print_vvector(wit_land_dist); - //std::cout << "End loop\n"; - } - } - for (int i = 0; i < nbP; i++) - { - sort(WL[i].begin(), WL[i].end(), [&](int j1, int j2){return wit_land_dist[i][j1] < wit_land_dist[i][j2];}); + // //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; + // //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; + // curr_dist = euclidean_distance(W[i],W[chosen_landmark]); + // //std::cout << "The problem is not in distance function\n"; + // wit_land_dist[i].push_back(curr_dist); + // WL[i].push_back(current_number_of_landmarks); + // //std::cout << "Push't back\n"; + // //j = current_number_of_landmarks; + // //std::cout << "First half complete\n"; + // //std::cout << "result WL="; print_vvector(WL); + // //std::cout << "result WLD="; print_vvector(wit_land_dist); + // //std::cout << "End loop\n"; + // } } + // for (int i = 0; i < nbP; i++) + // { + // sort(WL[i].begin(), WL[i].end(), [&](int j1, int j2){return wit_land_dist[i][j1] < wit_land_dist[i][j2];}); + // } //std::cout << endl; } + /** \brief Construct the matrix |W|x(D+1) of D+1 closest landmarks * where W is the set of witnesses and D is the ambient dimension */ template - void nearest_landmarks(Point_Vector &W, std::unordered_set &L, KNearestNeighbours &WL) + void nearest_landmarks(Point_Vector &W, std::set &L, KNearestNeighbours &WL) { int D = W[0].size(); - + int nbP = W.size(); + WL = KNearestNeighbours(nbP,std::vector()); + typedef std::pair dist_i; + typedef bool (*comp)(dist_i,dist_i); + for (int W_i = 0; W_i < nbP; W_i++) + { + //std::cout << "<<<<<<<<<<<<<<" << W_i <<"\n"; + std::priority_queue, comp> l_heap([&](dist_i j1, dist_i j2){return j1.first > j2.first;}); + std::set::iterator L_it; + int L_i; + for (L_it = L.begin(), L_i=0; L_it != L.end(); L_it++, L_i++) + { + dist_i dist = std::make_pair(euclidean_distance(W[W_i],W[*L_it]), L_i); + l_heap.push(dist); + } + for (int i = 0; i < D+1; i++) + { + dist_i dist = l_heap.top(); + WL[W_i].push_back(dist.second); + //std::cout << dist.first << " " << dist.second << std::endl; + l_heap.pop(); + } + } } /** \brief Search and output links around vertices that are not pseudomanifolds -- cgit v1.2.3 From 42be4074aa20b30c343867de156f3c6d7f96cf81 Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 27 Apr 2015 16:56:40 +0000 Subject: Added a CGAL include git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@581 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4f747215a4a6ac6bb0ca6f86b140f0bd8c4f0c14 --- src/Witness_complex/example/witness_complex_from_file.cpp | 2 +- src/Witness_complex/example/witness_complex_knn_landmarks.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index b842574b..01172fbe 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -115,7 +115,7 @@ int main (int argc, char * const argv[]) witnessComplex.landmark_choice_by_random_points(point_vector, point_vector.size(), L); witnessComplex.nearest_landmarks(point_vector,L,WL); end = clock(); - std::cout << "Landmark choice took " + std::cout << "Landmark choice for " << nbL << " landmarks took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; // Write the WL matrix in a file mkdir("output", S_IRWXU); diff --git a/src/Witness_complex/example/witness_complex_knn_landmarks.cpp b/src/Witness_complex/example/witness_complex_knn_landmarks.cpp index 2003f218..5580c0eb 100644 --- a/src/Witness_complex/example/witness_complex_knn_landmarks.cpp +++ b/src/Witness_complex/example/witness_complex_knn_landmarks.cpp @@ -34,7 +34,7 @@ //#include //#include -//#include +#include #include using namespace Gudhi; -- cgit v1.2.3 From e1caa847d6c0de60812a5246437e7702605cb7e8 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 28 Apr 2015 07:21:41 +0000 Subject: compile fixed git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@582 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fb750b7fb681685a59ddad6c3bbb66970379de3d --- src/Witness_complex/example/CMakeLists.txt | 52 ++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index fa594de7..315ffc36 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -25,17 +25,43 @@ project(GUDHIWitnessComplex) # An example with Simplex-tree using CGAL alpha_shapes_3 -include( ${CGAL_USE_FILE} ) -find_package(Eigen3 3.1.0) -if(GMP_FOUND AND CGAL_FOUND) - message("CGAL_lib = ${CGAL_LIBRARIES_DIR}") - message("GMP_LIBRARIES = ${GMP_LIBRARIES}") - message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") - #message("EIGEN3_LIBRARIES = ${EIGEN3_LIBRARIES}") - INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIRS}) - INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) - INCLUDE_DIRECTORIES(${CGAL_INCLUDE_DIRS}) - add_executable (witness_complex_knn_landmarks witness_complex_knn_landmarks.cpp ) - target_link_libraries(witness_complex_knn_landmarks ${EIGEN3_LIBRARIES} ${CGAL_LIBRARY}) - add_test(witness_complex_knn_landmarks ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_knn_landmarks ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) +#find_package(Eigen3 3.1.0) +#if(GMP_FOUND AND CGAL_FOUND) +# message("CGAL_lib = ${CGAL_LIBRARIES_DIR}") +# message("GMP_LIBRARIES = ${GMP_LIBRARIES}") +# message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") +# #message("EIGEN3_LIBRARIES = ${EIGEN3_LIBRARIES}") +# INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIRS}) +# INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) +# INCLUDE_DIRECTORIES(${CGAL_INCLUDE_DIRS}) +# add_executable (witness_complex_knn_landmarks witness_complex_knn_landmarks.cpp ) +# target_link_libraries(witness_complex_knn_landmarks ${EIGEN3_LIBRARIES} ${CGAL_LIBRARY}) +# add_test(witness_complex_knn_landmarks ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_knn_landmarks ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) +#endif() + +# need CGAL 4.6 +# cmake -DCGAL_DIR=~/workspace/CGAL-4.6-beta1 ../../.. +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) + include_directories (BEFORE "../../include") + + add_executable ( witness_complex_knn_landmarks witness_complex_knn_landmarks.cpp ) + target_link_libraries(witness_complex_knn_landmarks ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(witness_complex_knn_landmarks ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_knn_landmarks ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() + else() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () endif() + -- cgit v1.2.3 From d8984eab8b054dbdaa2d2ada040f6b1927594bef Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 6 May 2015 13:51:36 +0000 Subject: Kd tree landmark choice worked git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@586 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 59d672bab0c8d8bad0a39774a58a50c87d573604 --- .../example/witness_complex_from_file.cpp | 2 +- .../example/witness_complex_knn_landmarks.cpp | 132 +++++++++++++++++++-- .../include/gudhi/Witness_complex.h | 21 ++-- 3 files changed, 134 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index 01172fbe..70c81528 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -125,7 +125,7 @@ int main (int argc, char * const argv[]) file_name.erase(0, last_slash_idx + 1); } std::string out_file = "output/"+file_name+"_"+argv[2]+".wl"; - //write_wl(out_file,WL); + write_wl(out_file,WL); start = clock(); witnessComplex.witness_complex(WL); // diff --git a/src/Witness_complex/example/witness_complex_knn_landmarks.cpp b/src/Witness_complex/example/witness_complex_knn_landmarks.cpp index 5580c0eb..e4a1c324 100644 --- a/src/Witness_complex/example/witness_complex_knn_landmarks.cpp +++ b/src/Witness_complex/example/witness_complex_knn_landmarks.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -34,25 +35,51 @@ //#include //#include +#include +#include +#include +#include #include -#include +#include + +#include +#include +#include +#include using namespace Gudhi; //using namespace boost::filesystem; typedef std::vector< Vertex_handle > typeVectorVertex; -typedef std::vector< std::vector > Point_Vector; + //typedef std::pair typeSimplex; //typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; +typedef CGAL::Epick_d K; +typedef K::FT FT; +typedef K::Point_d Point_d; +typedef CGAL::Search_traits< + FT, Point_d, + typename K::Cartesian_const_iterator_d, + typename K::Construct_cartesian_const_iterator_d> Traits_base; +typedef CGAL::Search_traits_adapter< + std::ptrdiff_t, Point_d*, Traits_base> STraits; +//typedef K TreeTraits; +typedef CGAL::Orthogonal_k_neighbor_search K_neighbor_search; +typedef K_neighbor_search::Tree Tree; +typedef K_neighbor_search::Distance Distance; +typedef K_neighbor_search::iterator KNS_iterator; +typedef K_neighbor_search::iterator KNS_range; +typedef boost::container::flat_map Point_etiquette_map; +typedef std::vector Point_Vector; /** * \brief Customized version of read_points * which takes into account a possible nbP first line * */ inline void -read_points_cust ( std::string file_name , std::vector< std::vector< double > > & points) +read_points_cust ( std::string file_name , Point_Vector & points) { std::ifstream in_file (file_name.c_str(),std::ios::in); if(!in_file.is_open()) @@ -67,11 +94,96 @@ read_points_cust ( std::string file_name , std::vector< std::vector< double > > std::vector< double > point; std::istringstream iss( line ); while(iss >> x) { point.push_back(x); } + Point_d p(point.begin(), point.end()); if (point.size() != 1) - points.push_back(point); + points.push_back(p); + } + in_file.close(); +} + +/* +void read_points_to_tree (std::string file_name, Tree& tree) +{ + //I assume here that tree is empty + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector coords; + std::istringstream iss( line ); + while(iss >> x) { coords.push_back(x); } + if (coords.size() != 1) + { + Point_d point(coords.begin(), coords.end()); + tree.insert(point); + } } in_file.close(); } +*/ + +/** Function that chooses landmarks from W and place it in the kd-tree L. + * Note: nbL hould be removed if the code moves to Witness_complex + */ +void landmark_choice_to_tree(Point_Vector &W, int nbP, Point_etiquette_map &L_i, int nbL, std::vector< std::vector > &WL) +{ + std::cout << "Enter landmark choice to kd tree\n"; + std::vector landmarks; + int chosen_landmark; + //std::pair res = std::make_pair(L_i.begin(),false); + Point_d* p; + srand(24660); + for (int i = 0; i < nbL; i++) + { + // while (!res.second) + // { + chosen_landmark = rand()%nbP; + p = &W[chosen_landmark]; + //L_i.emplace(chosen_landmark,i); + // } + landmarks.push_back(*p); + //std::cout << "Added landmark " << chosen_landmark << std::endl; + } + Tree L(boost::counting_iterator(0), + boost::counting_iterator(nbL), + typename Tree::Splitter(), + STraits((Point_d*)&(landmarks[0]))); + /*} + + +void d_nearest_landmarks(Point_Vector &W, Tree &L, Point_etiquette_map &L_i, std::vector< std::vector > &WL) +{*/ + std::cout << "Enter (D+1) nearest landmarks\n"; + std::cout << "Size of the tree is " << L.size() << std::endl; +//int nbP = W.size(); + int D = W[0].size(); + for (int i = 0; i < nbP; i++) + { + //std::cout << "Entered witness number " << i << std::endl; + Point_d& w = W[i]; + //std::cout << "Safely constructed a point\n"; + //Search D+1 nearest neighbours from the tree of landmarks L + K_neighbor_search search(L, w, D+1, FT(0), true, + CGAL::Distance_adapter>((Point_d*)&(landmarks[0])) ); + //std::cout << "Safely found nearest landmarks\n"; + for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) + { + //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; + //Point_etiquette_map::iterator itm = L_i.find(it->first); + //assert(itm != L_i.end()); + //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; + WL[i].push_back(it->first); + //std::cout << i << " " << it->first << ": " << it->second << std::endl; + } + } +} + void write_wl( std::string file_name, std::vector< std::vector > & WL) { @@ -112,13 +224,15 @@ int main (int argc, char * const argv[]) //std::cout << "Successfully read the points\n"; witnessComplex.setNbL(nbL); // witnessComplex.witness_complex_from_points(point_vector); - std::vector > WL; - std::set L; int nbP = point_vector.size(); + std::vector > WL(nbP); + //std::set L; + Tree L; + Point_etiquette_map L_i; start = clock(); //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); - witnessComplex.landmark_choice_by_random_points(point_vector, nbP, L); - witnessComplex.nearest_landmarks(point_vector,L,WL); + landmark_choice_to_tree(point_vector, nbP, L_i, nbL, WL); + //d_nearest_landmarks(point_vector, L, L_i, WL); end = clock(); std::cout << "Landmark choice took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; @@ -130,7 +244,7 @@ int main (int argc, char * const argv[]) file_name.erase(0, last_slash_idx + 1); } std::string out_file = "output/"+file_name+"_"+argv[2]+".wl"; - //write_wl(out_file,WL); + write_wl(out_file,WL); start = clock(); witnessComplex.witness_complex(WL); // diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 2ccaa416..69521e6a 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -284,29 +284,27 @@ private: private: void sc_to_file(std::ofstream& out_file, Siblings * sibl) { - if (sibl == NULL) - out_file << "&"; - else - children_to_file(out_file, sibl->members_); + assert(sibl); + children_to_file(out_file, sibl->members_); } - void children_to_file(std::ofstream& out_file, Dictionary map) + void children_to_file(std::ofstream& out_file, Dictionary& map) { - out_file << "("; + out_file << "(" << std::flush; if (!map.empty()) { - out_file << map.begin()->first; + out_file << map.begin()->first << std::flush; if (has_children(map.begin())) sc_to_file(out_file, map.begin()->second.children()); typename Dictionary::iterator it; for (it = map.begin()+1; it != map.end(); ++it) { - out_file << "," << it->first; + out_file << "," << it->first << std::flush; if (has_children(it)) sc_to_file(out_file, it->second.children()); } } - out_file << ")"; + out_file << ")" << std::flush; } @@ -541,7 +539,7 @@ private: //std::cout << "W="; print_vvector(W); //std::unordered_set< int > chosen_landmarks; // landmark set - Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks + //Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks //WL = KNearestNeighbours(nbP,std::vector()); int current_number_of_landmarks=0; // counter for landmarks @@ -618,7 +616,8 @@ private: for (int i = 0; i < D+1; i++) { dist_i dist = l_heap.top(); - WL[W_i].push_back(dist.second); + WL[W_i].push_back(dist.second); + //WL[W_i].insert(WL[W_i].begin(),dist.second); //std::cout << dist.first << " " << dist.second << std::endl; l_heap.pop(); } -- cgit v1.2.3 From bc9d9bdaec5e4ca1604cca2a5251031f25c64b0f Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 20 May 2015 15:16:13 +0000 Subject: Added perturbation witness complex construction git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@590 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 5c478d127e0fefa8696be5ca72ab89efa2e2dfc6 --- src/Witness_complex/example/CMakeLists.txt | 29 +- .../example/witness_complex_perturbations.cpp | 377 +++++++++++++++++++++ .../include/gudhi/Witness_complex.h | 28 +- 3 files changed, 431 insertions(+), 3 deletions(-) create mode 100644 src/Witness_complex/example/witness_complex_perturbations.cpp (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 315ffc36..a3e7b3f5 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -56,12 +56,37 @@ if(CGAL_FOUND) add_executable ( witness_complex_knn_landmarks witness_complex_knn_landmarks.cpp ) target_link_libraries(witness_complex_knn_landmarks ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_test(witness_complex_knn_landmarks ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_knn_landmarks ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - + #add_executable ( witness_complex_perturbations witness_complex_perturbations.cpp ) + #target_link_libraries(witness_complex_perturbations ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + #add_test(witness_complex_perturbations ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_perturbations ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() else() message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") endif () endif() +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + include( ${CGAL_USE_FILE} ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) + include_directories (BEFORE "../../include") + add_executable ( witness_complex_perturbations witness_complex_perturbations.cpp ) + target_link_libraries(witness_complex_perturbations ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(witness_complex_perturbations ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_perturbations ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_executable ( range_queries range_queries.cpp ) + target_link_libraries(range_queries ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(range_queries ${CMAKE_CURRENT_BINARY_DIR}/range_queries ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() + else() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () +endif() diff --git a/src/Witness_complex/example/witness_complex_perturbations.cpp b/src/Witness_complex/example/witness_complex_perturbations.cpp new file mode 100644 index 00000000..afb42807 --- /dev/null +++ b/src/Witness_complex/example/witness_complex_perturbations.cpp @@ -0,0 +1,377 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 + +#include +#include +//#include + +//#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex.h" +#include "gudhi/reader_utils.h" +//#include + +//#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace Gudhi; +//using namespace boost::filesystem; + +typedef std::vector< Vertex_handle > typeVectorVertex; + +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + +typedef CGAL::Epick_d K; +typedef K::FT FT; +typedef K::Point_d Point_d; +typedef CGAL::Search_traits< + FT, Point_d, + typename K::Cartesian_const_iterator_d, + typename K::Construct_cartesian_const_iterator_d> Traits_base; +typedef CGAL::Search_traits_adapter< + std::ptrdiff_t, Point_d*, Traits_base> STraits; +//typedef K TreeTraits; +typedef CGAL::Orthogonal_k_neighbor_search K_neighbor_search; +typedef K_neighbor_search::Tree Tree; +typedef K_neighbor_search::Distance Distance; +typedef K_neighbor_search::iterator KNS_iterator; +typedef K_neighbor_search::iterator KNS_range; +typedef boost::container::flat_map Point_etiquette_map; +typedef CGAL::Kd_tree Tree2; + +typedef CGAL::Fuzzy_sphere Fuzzy_sphere; + +typedef std::vector Point_Vector; + +typedef CGAL::Euclidean_distance Euclidean_distance; +//typedef K::Equal_d Equal_d; +typedef CGAL::Random_points_in_ball_d Random_point_iterator; +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , Point_Vector & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + Point_d p(point.begin(), point.end()); + if (point.size() != 1) + points.push_back(p); + } + in_file.close(); +} + +/* +void read_points_to_tree (std::string file_name, Tree& tree) +{ + //I assume here that tree is empty + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector coords; + std::istringstream iss( line ); + while(iss >> x) { coords.push_back(x); } + if (coords.size() != 1) + { + Point_d point(coords.begin(), coords.end()); + tree.insert(point); + } + } + in_file.close(); +} +*/ + +void write_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto l: w) + ofs << l << " "; + ofs << "\n"; + } + ofs.close(); +} + + + +/** Function that chooses landmarks from W and place it in the kd-tree L. + * Note: nbL hould be removed if the code moves to Witness_complex + */ +void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + std::cout << "Enter landmark choice to kd tree\n"; + //std::vector landmarks; + int chosen_landmark; + //std::pair res = std::make_pair(L_i.begin(),false); + Point_d* p; + srand(24660); + for (int i = 0; i < nbL; i++) + { + // while (!res.second) + // { + chosen_landmark = rand()%nbP; + p = &W[chosen_landmark]; + //L_i.emplace(chosen_landmark,i); + // } + landmarks.push_back(*p); + landmarks_ind.push_back(chosen_landmark); + //std::cout << "Added landmark " << chosen_landmark << std::endl; + } + } + + +int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + //******************** Constructing a WL matrix + int nbP = W.size(); + int nbL = landmarks.size(); + //Point_Vector landmarks_ = landmarks; + Euclidean_distance ed; + //Equal_d ed; + FT lambda = ed.transformed_distance(landmarks[0],landmarks[1]); + //FT lambda = 0.1;//Euclidean_distance(); + std::vector< std::vector > WL(nbP); + Tree L(boost::counting_iterator(0), + boost::counting_iterator(nbL), + typename Tree::Splitter(), + STraits(&(landmarks[0]))); + /*Tree2 L2(boost::counting_iterator(0), + boost::counting_iterator(nbL), + typename Tree::Splitter(), + STraits(&(landmarks[0]))); + */ + std::cout << "Enter (D+1) nearest landmarks\n"; + //std::cout << "Size of the tree is " << L.size() << std::endl; + int D = W[0].size(); + for (int i = 0; i < nbP; i++) + { + //std::cout << "Entered witness number " << i << std::endl; + Point_d& w = W[i]; + //std::cout << "Safely constructed a point\n"; + ////Search D+1 nearest neighbours from the tree of landmarks L + K_neighbor_search search(L, w, D+1, FT(0), true, + CGAL::Distance_adapter>(&(landmarks[0])) ); + //std::cout << "Safely found nearest landmarks\n"; + for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) + { + //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; + //Point_etiquette_map::iterator itm = L_i.find(it->first); + //assert(itm != L_i.end()); + //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; + WL[i].push_back(it->first); + //std::cout << "ITFIRST " << it->first << std::endl; + //std::cout << i << " " << it->first << ": " << it->second << std::endl; + } + if (i == landmarks_ind[WL[i][0]]) + { + //std::cout << "'"; + FT dist = ed.transformed_distance(W[i], landmarks[WL[i][1]]); + if (dist < lambda) + lambda = dist; + } + } + //std::cout << "\n"; + /* + std::string out_file = "wl_result"; + write_wl(out_file,WL); + */ + //******************** Constructng a witness complex + std::cout << "Entered witness complex construction\n"; + Witness_complex<> witnessComplex; + witnessComplex.setNbL(nbL); + witnessComplex.witness_complex(WL); + //******************** Making a set of bad link landmarks + std::cout << "Entered bad links\n"; + std::set< int > perturbL; + int count_badlinks = 0; + std::cout << "Bad links around "; + for (auto u: witnessComplex.complex_vertex_range()) + if (!witnessComplex.has_good_link(u)) + { + //std::cout << "Landmark " << u << " start!" << std::endl; + //perturbL.insert(u); + count_badlinks++; + std::cout << u << " "; + Point_d& l = landmarks[u]; + Fuzzy_sphere fs(l, sqrt(lambda)*2, 0, STraits(&(landmarks[0]))); + L.search(std::insert_iterator>(perturbL,perturbL.begin()),fs); + //L.search(std::inserter(perturbL,perturbL.begin()),fs); + //L.search(std::ostream_iterator(std::cout,"\n"),fs); + //std::cout << "PerturbL size is " << perturbL.size() << std::endl; + } + std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; + //std::cout << "landmark[0][0] before" << landmarks[0][0] << std::endl; + //*********************** Perturb bad link landmarks + + for (auto u: perturbL) + { + Random_point_iterator rp(D,sqrt(lambda)/2); + //std::cout << landmarks[u] << std::endl; + + std::vector point; + for (int i = 0; i < D; i++) + { + point.push_back(W[landmarks_ind[u]][i] + (*rp)[i]); + } + landmarks[u] = Point_d(point); + //std::cout << landmarks[u] << std::endl; + } + + //std::cout << "landmark[0][0] after" << landmarks[0][0] << std::endl; + std::cout << "lambda=" << lambda << std::endl; + // Write the WL matrix in a file + /* + mkdir("output", S_IRWXU); + const size_t last_slash_idx = file_name.find_last_of("/"); + if (std::string::npos != last_slash_idx) + { + file_name.erase(0, last_slash_idx + 1); + } + + char buffer[100]; + int i = sprintf(buffer,"stree_result.txt"); + + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } + */ + return count_badlinks; +} + + +int main (int argc, char * const argv[]) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] + << " path_to_point_file nbL \n"; + return 0; + } + /* + boost::filesystem::path p; + + for (; argc > 2; --argc, ++argv) + p /= argv[1]; + */ + std::string file_name = argv[1]; + int nbL = atoi(argv[2]); + + //clock_t start, end; + //Construct the Simplex Tree + //Witness_complex<> witnessComplex; + + std::cout << "Let the carnage begin!\n"; + Point_Vector point_vector; + read_points_cust(file_name, point_vector); + //std::cout << "Successfully read the points\n"; + //witnessComplex.setNbL(nbL); + // witnessComplex.witness_complex_from_points(point_vector); + int nbP = point_vector.size(); + //std::vector > WL(nbP); + //std::set L; + Point_Vector L; + std::vector chosen_landmarks; + //Point_etiquette_map L_i; + //start = clock(); + //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); + landmark_choice(point_vector, nbP, nbL, L, chosen_landmarks); + int bl = 1; + for (int i = 0; bl != 0; i++) + { + std::cout << "========== Start iteration " << i << " ========\n"; + bl = landmark_perturbation(point_vector, L, chosen_landmarks); + } + //end = clock(); + + /* + std::cout << "Landmark choice took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + start = clock(); + witnessComplex.witness_complex(WL); + // + end = clock(); + std::cout << "Howdy world! The process took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + */ + + /* + out_file = "output/"+file_name+"_"+argv[2]+".stree"; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + + out_file = "output/"+file_name+"_"+argv[2]+".badlinks"; + std::ofstream ofs2(out_file, std::ofstream::out); + witnessComplex.write_bad_links(ofs2); + ofs2.close(); + */ +} diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 69521e6a..bb553347 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -192,6 +192,7 @@ namespace Gudhi { } Simplex_handle sh; vv = {u,v}; + //if (u==v) std::cout << "Bazzinga!\n"; sh = (root()->find(u))->second.children()->find(v); active_w.push_back(i); } @@ -200,7 +201,8 @@ namespace Gudhi { //std::cout << "Successfully added edges" << std::endl; count_good = {0,0}; count_bad = {0,0}; - while (!active_w.empty() && k < nbL ) + int D = knn[0].size(); + while (!active_w.empty() && k < D ) { count_good.push_back(0); count_bad.push_back(0); @@ -623,6 +625,30 @@ private: } } } + + /** \brief Returns true if the link is good + */ + bool has_good_link(Vertex_handle v) + { + std::vector< Vertex_handle > link_vertices; + // Fill link_vertices + for (auto u: complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u != v && find(edge) != null_simplex()) + link_vertices.push_back(u); + } + /* + print_vector(link_vertices); + std::cout << "\n"; + */ + // Find the dimension + typeVectorVertex empty_simplex = {}; + int d = link_dim(link_vertices, link_vertices.begin(),-1, empty_simplex); + //std::cout << " dim " << d << "\n"; + //Siblings* curr_sibl = root(); + return (link_is_pseudomanifold(link_vertices,d)); + } /** \brief Search and output links around vertices that are not pseudomanifolds * -- cgit v1.2.3 From c0795bfcb30428f57ce51e939ec7d9f345a39f1b Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 20 May 2015 15:24:42 +0000 Subject: Removed range_queries from cmakelists git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@591 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e2c78757c05ccc827e53f377449ae247edc79649 --- src/Witness_complex/example/CMakeLists.txt | 6 +- .../example/witness_complex_flat_torus.cpp | 377 +++++++++++++++++++++ 2 files changed, 380 insertions(+), 3 deletions(-) create mode 100644 src/Witness_complex/example/witness_complex_flat_torus.cpp (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index a3e7b3f5..49c8c0bb 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -80,9 +80,9 @@ if(CGAL_FOUND) add_executable ( witness_complex_perturbations witness_complex_perturbations.cpp ) target_link_libraries(witness_complex_perturbations ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_test(witness_complex_perturbations ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_perturbations ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - add_executable ( range_queries range_queries.cpp ) - target_link_libraries(range_queries ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(range_queries ${CMAKE_CURRENT_BINARY_DIR}/range_queries ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + #add_executable ( range_queries range_queries.cpp ) + #target_link_libraries(range_queries ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + #add_test(range_queries ${CMAKE_CURRENT_BINARY_DIR}/range_queries ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Witness_complex/example/witness_complex_flat_torus.cpp b/src/Witness_complex/example/witness_complex_flat_torus.cpp new file mode 100644 index 00000000..afb42807 --- /dev/null +++ b/src/Witness_complex/example/witness_complex_flat_torus.cpp @@ -0,0 +1,377 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 + +#include +#include +//#include + +//#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex.h" +#include "gudhi/reader_utils.h" +//#include + +//#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace Gudhi; +//using namespace boost::filesystem; + +typedef std::vector< Vertex_handle > typeVectorVertex; + +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + +typedef CGAL::Epick_d K; +typedef K::FT FT; +typedef K::Point_d Point_d; +typedef CGAL::Search_traits< + FT, Point_d, + typename K::Cartesian_const_iterator_d, + typename K::Construct_cartesian_const_iterator_d> Traits_base; +typedef CGAL::Search_traits_adapter< + std::ptrdiff_t, Point_d*, Traits_base> STraits; +//typedef K TreeTraits; +typedef CGAL::Orthogonal_k_neighbor_search K_neighbor_search; +typedef K_neighbor_search::Tree Tree; +typedef K_neighbor_search::Distance Distance; +typedef K_neighbor_search::iterator KNS_iterator; +typedef K_neighbor_search::iterator KNS_range; +typedef boost::container::flat_map Point_etiquette_map; +typedef CGAL::Kd_tree Tree2; + +typedef CGAL::Fuzzy_sphere Fuzzy_sphere; + +typedef std::vector Point_Vector; + +typedef CGAL::Euclidean_distance Euclidean_distance; +//typedef K::Equal_d Equal_d; +typedef CGAL::Random_points_in_ball_d Random_point_iterator; +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , Point_Vector & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + Point_d p(point.begin(), point.end()); + if (point.size() != 1) + points.push_back(p); + } + in_file.close(); +} + +/* +void read_points_to_tree (std::string file_name, Tree& tree) +{ + //I assume here that tree is empty + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector coords; + std::istringstream iss( line ); + while(iss >> x) { coords.push_back(x); } + if (coords.size() != 1) + { + Point_d point(coords.begin(), coords.end()); + tree.insert(point); + } + } + in_file.close(); +} +*/ + +void write_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto l: w) + ofs << l << " "; + ofs << "\n"; + } + ofs.close(); +} + + + +/** Function that chooses landmarks from W and place it in the kd-tree L. + * Note: nbL hould be removed if the code moves to Witness_complex + */ +void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + std::cout << "Enter landmark choice to kd tree\n"; + //std::vector landmarks; + int chosen_landmark; + //std::pair res = std::make_pair(L_i.begin(),false); + Point_d* p; + srand(24660); + for (int i = 0; i < nbL; i++) + { + // while (!res.second) + // { + chosen_landmark = rand()%nbP; + p = &W[chosen_landmark]; + //L_i.emplace(chosen_landmark,i); + // } + landmarks.push_back(*p); + landmarks_ind.push_back(chosen_landmark); + //std::cout << "Added landmark " << chosen_landmark << std::endl; + } + } + + +int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + //******************** Constructing a WL matrix + int nbP = W.size(); + int nbL = landmarks.size(); + //Point_Vector landmarks_ = landmarks; + Euclidean_distance ed; + //Equal_d ed; + FT lambda = ed.transformed_distance(landmarks[0],landmarks[1]); + //FT lambda = 0.1;//Euclidean_distance(); + std::vector< std::vector > WL(nbP); + Tree L(boost::counting_iterator(0), + boost::counting_iterator(nbL), + typename Tree::Splitter(), + STraits(&(landmarks[0]))); + /*Tree2 L2(boost::counting_iterator(0), + boost::counting_iterator(nbL), + typename Tree::Splitter(), + STraits(&(landmarks[0]))); + */ + std::cout << "Enter (D+1) nearest landmarks\n"; + //std::cout << "Size of the tree is " << L.size() << std::endl; + int D = W[0].size(); + for (int i = 0; i < nbP; i++) + { + //std::cout << "Entered witness number " << i << std::endl; + Point_d& w = W[i]; + //std::cout << "Safely constructed a point\n"; + ////Search D+1 nearest neighbours from the tree of landmarks L + K_neighbor_search search(L, w, D+1, FT(0), true, + CGAL::Distance_adapter>(&(landmarks[0])) ); + //std::cout << "Safely found nearest landmarks\n"; + for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) + { + //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; + //Point_etiquette_map::iterator itm = L_i.find(it->first); + //assert(itm != L_i.end()); + //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; + WL[i].push_back(it->first); + //std::cout << "ITFIRST " << it->first << std::endl; + //std::cout << i << " " << it->first << ": " << it->second << std::endl; + } + if (i == landmarks_ind[WL[i][0]]) + { + //std::cout << "'"; + FT dist = ed.transformed_distance(W[i], landmarks[WL[i][1]]); + if (dist < lambda) + lambda = dist; + } + } + //std::cout << "\n"; + /* + std::string out_file = "wl_result"; + write_wl(out_file,WL); + */ + //******************** Constructng a witness complex + std::cout << "Entered witness complex construction\n"; + Witness_complex<> witnessComplex; + witnessComplex.setNbL(nbL); + witnessComplex.witness_complex(WL); + //******************** Making a set of bad link landmarks + std::cout << "Entered bad links\n"; + std::set< int > perturbL; + int count_badlinks = 0; + std::cout << "Bad links around "; + for (auto u: witnessComplex.complex_vertex_range()) + if (!witnessComplex.has_good_link(u)) + { + //std::cout << "Landmark " << u << " start!" << std::endl; + //perturbL.insert(u); + count_badlinks++; + std::cout << u << " "; + Point_d& l = landmarks[u]; + Fuzzy_sphere fs(l, sqrt(lambda)*2, 0, STraits(&(landmarks[0]))); + L.search(std::insert_iterator>(perturbL,perturbL.begin()),fs); + //L.search(std::inserter(perturbL,perturbL.begin()),fs); + //L.search(std::ostream_iterator(std::cout,"\n"),fs); + //std::cout << "PerturbL size is " << perturbL.size() << std::endl; + } + std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; + //std::cout << "landmark[0][0] before" << landmarks[0][0] << std::endl; + //*********************** Perturb bad link landmarks + + for (auto u: perturbL) + { + Random_point_iterator rp(D,sqrt(lambda)/2); + //std::cout << landmarks[u] << std::endl; + + std::vector point; + for (int i = 0; i < D; i++) + { + point.push_back(W[landmarks_ind[u]][i] + (*rp)[i]); + } + landmarks[u] = Point_d(point); + //std::cout << landmarks[u] << std::endl; + } + + //std::cout << "landmark[0][0] after" << landmarks[0][0] << std::endl; + std::cout << "lambda=" << lambda << std::endl; + // Write the WL matrix in a file + /* + mkdir("output", S_IRWXU); + const size_t last_slash_idx = file_name.find_last_of("/"); + if (std::string::npos != last_slash_idx) + { + file_name.erase(0, last_slash_idx + 1); + } + + char buffer[100]; + int i = sprintf(buffer,"stree_result.txt"); + + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } + */ + return count_badlinks; +} + + +int main (int argc, char * const argv[]) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] + << " path_to_point_file nbL \n"; + return 0; + } + /* + boost::filesystem::path p; + + for (; argc > 2; --argc, ++argv) + p /= argv[1]; + */ + std::string file_name = argv[1]; + int nbL = atoi(argv[2]); + + //clock_t start, end; + //Construct the Simplex Tree + //Witness_complex<> witnessComplex; + + std::cout << "Let the carnage begin!\n"; + Point_Vector point_vector; + read_points_cust(file_name, point_vector); + //std::cout << "Successfully read the points\n"; + //witnessComplex.setNbL(nbL); + // witnessComplex.witness_complex_from_points(point_vector); + int nbP = point_vector.size(); + //std::vector > WL(nbP); + //std::set L; + Point_Vector L; + std::vector chosen_landmarks; + //Point_etiquette_map L_i; + //start = clock(); + //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); + landmark_choice(point_vector, nbP, nbL, L, chosen_landmarks); + int bl = 1; + for (int i = 0; bl != 0; i++) + { + std::cout << "========== Start iteration " << i << " ========\n"; + bl = landmark_perturbation(point_vector, L, chosen_landmarks); + } + //end = clock(); + + /* + std::cout << "Landmark choice took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + start = clock(); + witnessComplex.witness_complex(WL); + // + end = clock(); + std::cout << "Howdy world! The process took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + */ + + /* + out_file = "output/"+file_name+"_"+argv[2]+".stree"; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + + out_file = "output/"+file_name+"_"+argv[2]+".badlinks"; + std::ofstream ofs2(out_file, std::ofstream::out); + witnessComplex.write_bad_links(ofs2); + ofs2.close(); + */ +} -- cgit v1.2.3 From da5114d23e2a42e45805773f60520059c7f8cf22 Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 26 May 2015 08:51:43 +0000 Subject: witness complex in a torus git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@594 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: af4ef3a1233aec08d21f635bb3606cfc5d19c4d7 --- src/Witness_complex/example/CMakeLists.txt | 6 +- .../example/witness_complex_flat_torus.cpp | 303 ++++++++++++++++++--- .../example/witness_complex_perturbations.cpp | 4 +- 3 files changed, 270 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 49c8c0bb..e3768138 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -80,9 +80,9 @@ if(CGAL_FOUND) add_executable ( witness_complex_perturbations witness_complex_perturbations.cpp ) target_link_libraries(witness_complex_perturbations ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_test(witness_complex_perturbations ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_perturbations ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - #add_executable ( range_queries range_queries.cpp ) - #target_link_libraries(range_queries ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - #add_test(range_queries ${CMAKE_CURRENT_BINARY_DIR}/range_queries ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_executable ( witness_complex_flat_torus witness_complex_flat_torus.cpp ) + target_link_libraries(witness_complex_flat_torus ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(witness_complex_flat_torus ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_flat_torus ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Witness_complex/example/witness_complex_flat_torus.cpp b/src/Witness_complex/example/witness_complex_flat_torus.cpp index afb42807..c1fb5082 100644 --- a/src/Witness_complex/example/witness_complex_flat_torus.cpp +++ b/src/Witness_complex/example/witness_complex_flat_torus.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,8 @@ #include #include #include -#include +#include + #include #include @@ -60,11 +62,6 @@ using namespace Gudhi; //using namespace boost::filesystem; -typedef std::vector< Vertex_handle > typeVectorVertex; - -//typedef std::pair typeSimplex; -//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; - typedef CGAL::Epick_d K; typedef K::FT FT; typedef K::Point_d Point_d; @@ -72,10 +69,197 @@ typedef CGAL::Search_traits< FT, Point_d, typename K::Cartesian_const_iterator_d, typename K::Construct_cartesian_const_iterator_d> Traits_base; +typedef CGAL::Euclidean_distance Euclidean_distance; + +/** + * \brief Class of distance in a flat torus in dimaension D + * + */ +class Torus_distance : public Euclidean_distance { + +public: + typedef FT FT; + typedef Point_d Point_d; + typedef Point_d Query_item; + typedef typename CGAL::Dynamic_dimension_tag D; + + FT transformed_distance(Query_item q, Point_d p) const + { + FT distance = FT(0); + FT coord = FT(0); + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1), pit = construct_it(p); + for(; qit != qe; qit++, pit++) + { + coord = sqrt(((*qit)-(*pit))*((*qit)-(*pit))); + if (coord*coord <= (1-coord)*(1-coord)) + distance += coord*coord; + else + distance += (1-coord)*(1-coord); + } + return distance; + } + + FT min_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r) const { + FT distance = FT(0); + FT dist1, dist2; + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if((*qit) < r.min_coord(i)) + { + dist1 = (r.min_coord(i)-(*qit)); + dist2 = (1 - r.max_coord(i)+(*qit)); + if (dist1 < dist2) + distance += dist1*dist1; + else + distance += dist2*dist2; + } + else if ((*qit) > r.max_coord(i)) + { + dist1 = (1 - (*qit)+r.min_coord(i)); + dist2 = ((*qit) - r.max_coord(i)); + if (dist1 < dist2) + distance += dist1*dist1; + else + distance += dist2*dist2; + } + } + return distance; + } + + FT min_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r, + std::vector& dists) const { + FT distance = FT(0); + FT dist1, dist2; + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if((*qit) < r.min_coord(i)) + { + dist1 = (r.min_coord(i)-(*qit)); + dist2 = (1 - r.max_coord(i)+(*qit)); + if (dist1 < dist2) + { + dists[i] = dist1; + distance += dist1*dist1; + } + else + { + dists[i] = dist2; + distance += dist2*dist2; + } + } + else if ((*qit) > r.max_coord(i)) + { + dist1 = (1 - (*qit)+r.min_coord(i)); + dist2 = ((*qit) - r.max_coord(i)); + if (dist1 < dist2) + { + dists[i] = dist1; + distance += dist1*dist1; + } + else + { + dists[i] = dist2; + distance += dist2*dist2; + } + } + }; + return distance; + } + + FT max_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r) const { + FT distance=FT(0); + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if (FT(1) <= (r.min_coord(i)+r.max_coord(i))) + if ((r.max_coord(i)+r.min_coord(i)-FT(1))/FT(2.0) <= (*qit) && + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + else + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + else + if ((FT(1)-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + else + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + } + return distance; + } + + FT max_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r, + std::vector& dists) const { + FT distance=FT(0); + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if (FT(1) <= (r.min_coord(i)+r.max_coord(i))) + if ((r.max_coord(i)+r.min_coord(i)-FT(1))/FT(2.0) <= (*qit) && + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + { + dists[i] = r.max_coord(i)-(*qit); + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + } + else + { + dists[i] = sqrt(((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i))); + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + } + else + if ((FT(1)-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + { + dists[i] = sqrt((r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit))); + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + + } + else + { + dists[i] = (*qit)-r.min_coord(i); + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + } + } + return distance; + } + + inline FT transformed_distance(FT d) const { + return d*d; + } + + inline FT inverse_of_transformed_distance(FT d) const { + return sqrt(d); + } + +}; + + +typedef std::vector< Vertex_handle > typeVectorVertex; + +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + typedef CGAL::Search_traits_adapter< std::ptrdiff_t, Point_d*, Traits_base> STraits; //typedef K TreeTraits; -typedef CGAL::Orthogonal_k_neighbor_search K_neighbor_search; +//typedef CGAL::Distance_adapter Euclidean_adapter; +//typedef CGAL::Kd_tree Kd_tree; +typedef CGAL::Orthogonal_k_neighbor_search> K_neighbor_search; typedef K_neighbor_search::Tree Tree; typedef K_neighbor_search::Distance Distance; typedef K_neighbor_search::iterator KNS_iterator; @@ -87,9 +271,12 @@ typedef CGAL::Fuzzy_sphere Fuzzy_sphere; typedef std::vector Point_Vector; -typedef CGAL::Euclidean_distance Euclidean_distance; //typedef K::Equal_d Equal_d; +typedef CGAL::Random_points_in_cube_d Random_cube_iterator; typedef CGAL::Random_points_in_ball_d Random_point_iterator; + + + /** * \brief Customized version of read_points * which takes into account a possible nbP first line @@ -118,6 +305,20 @@ read_points_cust ( std::string file_name , Point_Vector & points) in_file.close(); } +void generate_points_grid(Point_Vector& W, int width, int D) +{ + +} + +void generate_points_random_box(Point_Vector& W, int nbP, int dim) +{ + Random_cube_iterator rp(dim, 1); + for (int i = 0; i < nbP; i++) + { + W.push_back(*rp++); + } +} + /* void read_points_to_tree (std::string file_name, Tree& tree) { @@ -169,12 +370,14 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, int chosen_landmark; //std::pair res = std::make_pair(L_i.begin(),false); Point_d* p; - srand(24660); + CGAL::Random rand; for (int i = 0; i < nbL; i++) { // while (!res.second) // { - chosen_landmark = rand()%nbP; + chosen_landmark = rand.get_int(0,nbP); + //rand++; + //std::cout << "Chose " << chosen_landmark << std::endl; p = &W[chosen_landmark]; //L_i.emplace(chosen_landmark,i); // } @@ -191,9 +394,11 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< int nbP = W.size(); int nbL = landmarks.size(); //Point_Vector landmarks_ = landmarks; - Euclidean_distance ed; + Torus_distance ed; //Equal_d ed; + //Point_d p1(std::vector({0.8,0.8})), p2(std::vector({0.1,0.1})); FT lambda = ed.transformed_distance(landmarks[0],landmarks[1]); + //std::cout << "Lambda=" << lambda << std::endl; //FT lambda = 0.1;//Euclidean_distance(); std::vector< std::vector > WL(nbP); Tree L(boost::counting_iterator(0), @@ -215,7 +420,8 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< //std::cout << "Safely constructed a point\n"; ////Search D+1 nearest neighbours from the tree of landmarks L K_neighbor_search search(L, w, D+1, FT(0), true, - CGAL::Distance_adapter>(&(landmarks[0])) ); + //CGAL::Distance_adapter(&(landmarks[0])) ); + CGAL::Distance_adapter(&(landmarks[0])) ); //std::cout << "Safely found nearest landmarks\n"; for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) { @@ -236,10 +442,10 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< } } //std::cout << "\n"; - /* + std::string out_file = "wl_result"; write_wl(out_file,WL); - */ + //******************** Constructng a witness complex std::cout << "Entered witness complex construction\n"; Witness_complex<> witnessComplex; @@ -249,16 +455,16 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< std::cout << "Entered bad links\n"; std::set< int > perturbL; int count_badlinks = 0; - std::cout << "Bad links around "; + //std::cout << "Bad links around "; for (auto u: witnessComplex.complex_vertex_range()) if (!witnessComplex.has_good_link(u)) { //std::cout << "Landmark " << u << " start!" << std::endl; //perturbL.insert(u); count_badlinks++; - std::cout << u << " "; + //std::cout << u << " "; Point_d& l = landmarks[u]; - Fuzzy_sphere fs(l, sqrt(lambda)*2, 0, STraits(&(landmarks[0]))); + Fuzzy_sphere fs(l, sqrt(lambda)*3, 0, STraits(&(landmarks[0]))); L.search(std::insert_iterator>(perturbL,perturbL.begin()),fs); //L.search(std::inserter(perturbL,perturbL.begin()),fs); //L.search(std::ostream_iterator(std::cout,"\n"),fs); @@ -270,13 +476,20 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< for (auto u: perturbL) { - Random_point_iterator rp(D,sqrt(lambda)/2); + Random_point_iterator rp(D,sqrt(lambda)/16); //std::cout << landmarks[u] << std::endl; std::vector point; for (int i = 0; i < D; i++) { - point.push_back(W[landmarks_ind[u]][i] + (*rp)[i]); + //FT coord = W[landmarks_ind[u]][i] + (*rp)[i]; + FT coord = landmarks[u][i] + (*rp)[i]; + if (coord > 1) + point.push_back(coord-1); + else if (coord < -1) + point.push_back(coord+1); + else + point.push_back(coord); } landmarks[u] = Point_d(point); //std::cout << landmarks[u] << std::endl; @@ -284,14 +497,13 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< //std::cout << "landmark[0][0] after" << landmarks[0][0] << std::endl; std::cout << "lambda=" << lambda << std::endl; - // Write the WL matrix in a file + + //std::cout << "WL size" << WL.size() << std::endl; /* - mkdir("output", S_IRWXU); - const size_t last_slash_idx = file_name.find_last_of("/"); - if (std::string::npos != last_slash_idx) - { - file_name.erase(0, last_slash_idx + 1); - } + std::cout << "L:" << std::endl; + for (int i = 0; i < landmarks.size(); i++) + std::cout << landmarks[i] << std::endl; + */ char buffer[100]; int i = sprintf(buffer,"stree_result.txt"); @@ -303,39 +515,47 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< witnessComplex.st_to_file(ofs); ofs.close(); } - */ + return count_badlinks; } int main (int argc, char * const argv[]) { - if (argc != 3) + + if (argc != 4) { std::cerr << "Usage: " << argv[0] - << " path_to_point_file nbL \n"; + << " nbP nbL dim\n"; return 0; } /* boost::filesystem::path p; - for (; argc > 2; --argc, ++argv) p /= argv[1]; */ - std::string file_name = argv[1]; - int nbL = atoi(argv[2]); + int nbP = atoi(argv[1]); + int nbL = atoi(argv[2]); + int dim = atoi(argv[3]); //clock_t start, end; //Construct the Simplex Tree //Witness_complex<> witnessComplex; std::cout << "Let the carnage begin!\n"; Point_Vector point_vector; - read_points_cust(file_name, point_vector); + //read_points_cust(file_name, point_vector); + generate_points_random_box(point_vector, nbP, dim); + /* + for (auto &p: point_vector) + { + assert(std::count(point_vector.begin(),point_vector.end(),p) == 1); + } + */ //std::cout << "Successfully read the points\n"; //witnessComplex.setNbL(nbL); // witnessComplex.witness_complex_from_points(point_vector); - int nbP = point_vector.size(); + //int nbP = point_vector.size(); //std::vector > WL(nbP); //std::set L; Point_Vector L; @@ -344,11 +564,18 @@ int main (int argc, char * const argv[]) //start = clock(); //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); landmark_choice(point_vector, nbP, nbL, L, chosen_landmarks); - int bl = 1; - for (int i = 0; bl != 0; i++) + for (auto i: chosen_landmarks) + { + assert(std::count(chosen_landmarks.begin(),chosen_landmarks.end(),i) == 1); + } + int bl = nbL, curr_min = bl; + + for (int i = 0; bl > 0; i++) { - std::cout << "========== Start iteration " << i << " ========\n"; - bl = landmark_perturbation(point_vector, L, chosen_landmarks); + std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; + bl=landmark_perturbation(point_vector, L, chosen_landmarks); + if (bl < curr_min) + curr_min=bl; } //end = clock(); diff --git a/src/Witness_complex/example/witness_complex_perturbations.cpp b/src/Witness_complex/example/witness_complex_perturbations.cpp index afb42807..514b115b 100644 --- a/src/Witness_complex/example/witness_complex_perturbations.cpp +++ b/src/Witness_complex/example/witness_complex_perturbations.cpp @@ -236,10 +236,10 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< } } //std::cout << "\n"; - /* + std::string out_file = "wl_result"; write_wl(out_file,WL); - */ + //******************** Constructng a witness complex std::cout << "Entered witness complex construction\n"; Witness_complex<> witnessComplex; -- cgit v1.2.3 From 9d49bd8d3fe2421016c02bf40cf4ac8e87e75cbe Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 26 May 2015 10:39:03 +0000 Subject: witness complex in a torus 2 git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@595 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f43a636b79ccbc926e1a5c77dc0876ba689038c5 --- .../example/witness_complex_flat_torus.cpp | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_flat_torus.cpp b/src/Witness_complex/example/witness_complex_flat_torus.cpp index c1fb5082..c3b2f910 100644 --- a/src/Witness_complex/example/witness_complex_flat_torus.cpp +++ b/src/Witness_complex/example/witness_complex_flat_torus.cpp @@ -390,6 +390,12 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector& landmarks_ind) { + //********************Preface: origin point + int D = W[0].size(); + std::vector orig_vector; + for (int i=0; i point; for (int i = 0; i < D; i++) { + while (K().squared_distance_d_object()(*rp,origin) < lambda/256) + rp++; //FT coord = W[landmarks_ind[u]][i] + (*rp)[i]; FT coord = landmarks[u][i] + (*rp)[i]; if (coord > 1) @@ -563,10 +570,18 @@ int main (int argc, char * const argv[]) //Point_etiquette_map L_i; //start = clock(); //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); - landmark_choice(point_vector, nbP, nbL, L, chosen_landmarks); - for (auto i: chosen_landmarks) + bool ok=false; + while (!ok) { - assert(std::count(chosen_landmarks.begin(),chosen_landmarks.end(),i) == 1); + ok = true; + L = {}; + chosen_landmarks = {}; + landmark_choice(point_vector, nbP, nbL, L, chosen_landmarks); + for (auto i: chosen_landmarks) + { + ok = ok && (std::count(chosen_landmarks.begin(),chosen_landmarks.end(),i) == 1); + if (!ok) break; + } } int bl = nbL, curr_min = bl; -- cgit v1.2.3 From 0844edcc9dcd8d507da462d84d120d4ad4724c83 Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 26 May 2015 11:00:08 +0000 Subject: Fixed random point choice in flat torus git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@596 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ae114c4dc58c3f7dd8a761c6407c2ad4ff8ef61e --- src/Witness_complex/example/witness_complex_flat_torus.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_flat_torus.cpp b/src/Witness_complex/example/witness_complex_flat_torus.cpp index c3b2f910..1ce17fde 100644 --- a/src/Witness_complex/example/witness_complex_flat_torus.cpp +++ b/src/Witness_complex/example/witness_complex_flat_torus.cpp @@ -375,7 +375,8 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, { // while (!res.second) // { - chosen_landmark = rand.get_int(0,nbP); + while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0) + chosen_landmark = rand.get_int(0,nbP); //rand++; //std::cout << "Chose " << chosen_landmark << std::endl; p = &W[chosen_landmark]; -- cgit v1.2.3 From 380c105e640335deb148feb80b81bbc6fdd39ff3 Mon Sep 17 00:00:00 2001 From: skachano Date: Fri, 29 May 2015 09:18:41 +0000 Subject: witness: Tweaking for the tests git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@597 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f357efa7f0967c337be027f37c236f3ad2864204 --- src/Witness_complex/example/CMakeLists.txt | 3 + .../example/witness_complex_flat_torus.cpp | 223 ++++++++++++++++++--- .../example/witness_complex_perturbations.cpp | 83 +++++++- .../include/gudhi/Witness_complex.h | 36 +++- 4 files changed, 294 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index e3768138..09167cbe 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -83,6 +83,9 @@ if(CGAL_FOUND) add_executable ( witness_complex_flat_torus witness_complex_flat_torus.cpp ) target_link_libraries(witness_complex_flat_torus ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_test(witness_complex_flat_torus ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_flat_torus ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_executable ( witness_complex_sphere witness_complex_sphere.cpp ) + target_link_libraries(witness_complex_sphere ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(witness_complex_sphere ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_sphere ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Witness_complex/example/witness_complex_flat_torus.cpp b/src/Witness_complex/example/witness_complex_flat_torus.cpp index 1ce17fde..ff995a4f 100644 --- a/src/Witness_complex/example/witness_complex_flat_torus.cpp +++ b/src/Witness_complex/example/witness_complex_flat_torus.cpp @@ -75,28 +75,33 @@ typedef CGAL::Euclidean_distance Euclidean_distance; * \brief Class of distance in a flat torus in dimaension D * */ -class Torus_distance : public Euclidean_distance { +//class Torus_distance : public Euclidean_distance { +/* + class Torus_distance { public: - typedef FT FT; - typedef Point_d Point_d; - typedef Point_d Query_item; - typedef typename CGAL::Dynamic_dimension_tag D; + typedef K::FT FT; + typedef K::Point_d Point_d; + typedef Point_d Query_item; + typedef typename CGAL::Dynamic_dimension_tag D; + + double box_length = 2; FT transformed_distance(Query_item q, Point_d p) const { FT distance = FT(0); FT coord = FT(0); + //std::cout << "Hello skitty!\n"; typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); typename K::Cartesian_const_iterator_d qit = construct_it(q), qe = construct_it(q,1), pit = construct_it(p); for(; qit != qe; qit++, pit++) { coord = sqrt(((*qit)-(*pit))*((*qit)-(*pit))); - if (coord*coord <= (1-coord)*(1-coord)) + if (coord*coord <= (box_length-coord)*(box_length-coord)) distance += coord*coord; else - distance += (1-coord)*(1-coord); + distance += (box_length-coord)*(box_length-coord); } return distance; } @@ -113,7 +118,7 @@ public: if((*qit) < r.min_coord(i)) { dist1 = (r.min_coord(i)-(*qit)); - dist2 = (1 - r.max_coord(i)+(*qit)); + dist2 = (box_length - r.max_coord(i)+(*qit)); if (dist1 < dist2) distance += dist1*dist1; else @@ -121,7 +126,7 @@ public: } else if ((*qit) > r.max_coord(i)) { - dist1 = (1 - (*qit)+r.min_coord(i)); + dist1 = (box_length - (*qit)+r.min_coord(i)); dist2 = ((*qit) - r.max_coord(i)); if (dist1 < dist2) distance += dist1*dist1; @@ -140,12 +145,13 @@ public: typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); typename K::Cartesian_const_iterator_d qit = construct_it(q), qe = construct_it(q,1); + //std::cout << r.max_coord(0) << std::endl; for(unsigned int i = 0;qit != qe; i++, qit++) { if((*qit) < r.min_coord(i)) { dist1 = (r.min_coord(i)-(*qit)); - dist2 = (1 - r.max_coord(i)+(*qit)); + dist2 = (box_length - r.max_coord(i)+(*qit)); if (dist1 < dist2) { dists[i] = dist1; @@ -155,16 +161,18 @@ public: { dists[i] = dist2; distance += dist2*dist2; + //std::cout << "Good stuff1\n"; } } else if ((*qit) > r.max_coord(i)) { - dist1 = (1 - (*qit)+r.min_coord(i)); + dist1 = (box_length - (*qit)+r.min_coord(i)); dist2 = ((*qit) - r.max_coord(i)); if (dist1 < dist2) { dists[i] = dist1; distance += dist1*dist1; + //std::cout << "Good stuff2\n"; } else { @@ -175,7 +183,7 @@ public: }; return distance; } - + FT max_distance_to_rectangle(const Query_item& q, const CGAL::Kd_tree_rectangle& r) const { FT distance=FT(0); @@ -184,14 +192,14 @@ public: qe = construct_it(q,1); for(unsigned int i = 0;qit != qe; i++, qit++) { - if (FT(1) <= (r.min_coord(i)+r.max_coord(i))) - if ((r.max_coord(i)+r.min_coord(i)-FT(1))/FT(2.0) <= (*qit) && + if (box_length <= (r.min_coord(i)+r.max_coord(i))) + if ((r.max_coord(i)+r.min_coord(i)-box_length)/FT(2.0) <= (*qit) && (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); else distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); else - if ((FT(1)-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || + if ((box_length-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); else @@ -200,6 +208,7 @@ public: return distance; } + FT max_distance_to_rectangle(const Query_item& q, const CGAL::Kd_tree_rectangle& r, std::vector& dists) const { @@ -209,8 +218,8 @@ public: qe = construct_it(q,1); for(unsigned int i = 0;qit != qe; i++, qit++) { - if (FT(1) <= (r.min_coord(i)+r.max_coord(i))) - if ((r.max_coord(i)+r.min_coord(i)-FT(1))/FT(2.0) <= (*qit) && + if (box_length <= (r.min_coord(i)+r.max_coord(i))) + if ((r.max_coord(i)+r.min_coord(i)-box_length)/FT(2.0) <= (*qit) && (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) { dists[i] = r.max_coord(i)-(*qit); @@ -222,7 +231,7 @@ public: distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); } else - if ((FT(1)-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || + if ((box_length-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) { dists[i] = sqrt((r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit))); @@ -237,7 +246,14 @@ public: } return distance; } - + + inline FT new_distance(FT dist, FT old_off, FT new_off, + int ) const { + + FT new_dist = dist + (new_off*new_off - old_off*old_off); + return new_dist; + } + inline FT transformed_distance(FT d) const { return d*d; } @@ -247,7 +263,7 @@ public: } }; - +*/ typedef std::vector< Vertex_handle > typeVectorVertex; @@ -259,7 +275,7 @@ typedef CGAL::Search_traits_adapter< //typedef K TreeTraits; //typedef CGAL::Distance_adapter Euclidean_adapter; //typedef CGAL::Kd_tree Kd_tree; -typedef CGAL::Orthogonal_k_neighbor_search> K_neighbor_search; +typedef CGAL::Orthogonal_k_neighbor_search> K_neighbor_search; typedef K_neighbor_search::Tree Tree; typedef K_neighbor_search::Distance Distance; typedef K_neighbor_search::iterator KNS_iterator; @@ -275,7 +291,7 @@ typedef std::vector Point_Vector; typedef CGAL::Random_points_in_cube_d Random_cube_iterator; typedef CGAL::Random_points_in_ball_d Random_point_iterator; - +bool toric=true; /** * \brief Customized version of read_points @@ -319,6 +335,14 @@ void generate_points_random_box(Point_Vector& W, int nbP, int dim) } } +/* NOT TORUS RELATED + */ +void generate_points_sphere(Point_Vector& W, int nbP, int dim) +{ + CGAL::Random_points_on_sphere_d rp(dim,1); + for (int i = 0; i < nbP; i++) + W.push_back(*rp++); +} /* void read_points_to_tree (std::string file_name, Tree& tree) { @@ -359,6 +383,97 @@ void write_wl( std::string file_name, std::vector< std::vector > & WL) } +std::vector convert_to_torus(std::vector< Point_d>& points) +{ + std::vector< Point_d > points_torus; + for (auto p: points) + { + FT theta = M_PI*p[0]; + FT phi = M_PI*p[1]; + std::vector p_torus; + p_torus.push_back((1+0.2*cos(theta))*cos(phi)); + p_torus.push_back((1+0.2*cos(theta))*sin(phi)); + p_torus.push_back(0.2*sin(theta)); + points_torus.push_back(Point_d(p_torus)); + } + return points_torus; +} + +void write_points_torus( std::string file_name, std::vector< Point_d > & points) +{ + std::ofstream ofs (file_name, std::ofstream::out); + std::vector points_torus = convert_to_torus(points); + for (auto w : points_torus) + { + for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + } + ofs.close(); +} + +void write_points( std::string file_name, std::vector< Point_d > & points) +{ + if (toric) write_points_torus(file_name, points); + else + { + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : points) + { + for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + } + ofs.close(); + } +} + + +void write_edges_torus(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) +{ + std::ofstream ofs (file_name, std::ofstream::out); + Point_Vector l_torus = convert_to_torus(landmarks); + for (auto u: witness_complex.complex_vertex_range()) + for (auto v: witness_complex.complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) + { + for (auto it = l_torus[u].cartesian_begin(); it != l_torus[u].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + for (auto it = l_torus[v].cartesian_begin(); it != l_torus[v].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n\n\n"; + } + } + ofs.close(); +} + +void write_edges(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) +{ + std::ofstream ofs (file_name, std::ofstream::out); + if (toric) write_edges_torus(file_name, witness_complex, landmarks); + else + { + for (auto u: witness_complex.complex_vertex_range()) + for (auto v: witness_complex.complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) + { + for (auto it = landmarks[u].cartesian_begin(); it != landmarks[u].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + for (auto it = landmarks[v].cartesian_begin(); it != landmarks[v].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n\n\n"; + } + } + ofs.close(); + } +} + /** Function that chooses landmarks from W and place it in the kd-tree L. * Note: nbL hould be removed if the code moves to Witness_complex @@ -397,21 +512,41 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< for (int i=0; i({0.8,0.8})), p2(std::vector({0.1,0.1})); FT lambda = ed.transformed_distance(landmarks[0],landmarks[1]); //std::cout << "Lambda=" << lambda << std::endl; //FT lambda = 0.1;//Euclidean_distance(); + std::vector landmarks_ext; + int nb_cells = 1; + for (int i = 0; i < D; ++i) + nb_cells *= 3; + for (int i = 0; i < nb_cells; ++i) + for (int k = 0; k < nbL; ++k) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(landmarks[k][l] + 2.0*((cell_i%3)-1)); + cell_i /= 3; + } + landmarks_ext.push_back(point); + } + write_points("landmarks/initial_landmarks",landmarks_ext); + STraits traits(&(landmarks_ext[0])); std::vector< std::vector > WL(nbP); Tree L(boost::counting_iterator(0), - boost::counting_iterator(nbL), + boost::counting_iterator(nb_cells*nbL), typename Tree::Splitter(), - STraits(&(landmarks[0]))); + traits); /*Tree2 L2(boost::counting_iterator(0), boost::counting_iterator(nbL), typename Tree::Splitter(), @@ -424,10 +559,14 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< //std::cout << "Entered witness number " << i << std::endl; Point_d& w = W[i]; //std::cout << "Safely constructed a point\n"; - ////Search D+1 nearest neighbours from the tree of landmarks L + ////Search D+1 nearest neighbours from the tree of landmarks L + /* + if (w[0]>0.95) + std::cout << i << std::endl; + */ K_neighbor_search search(L, w, D+1, FT(0), true, //CGAL::Distance_adapter(&(landmarks[0])) ); - CGAL::Distance_adapter(&(landmarks[0])) ); + CGAL::Distance_adapter(&(landmarks_ext[0])) ); //std::cout << "Safely found nearest landmarks\n"; for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) { @@ -435,7 +574,7 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< //Point_etiquette_map::iterator itm = L_i.find(it->first); //assert(itm != L_i.end()); //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; - WL[i].push_back(it->first); + WL[i].push_back((it->first)%nbL); //std::cout << "ITFIRST " << it->first << std::endl; //std::cout << i << " " << it->first << ": " << it->second << std::endl; } @@ -463,6 +602,8 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< int count_badlinks = 0; //std::cout << "Bad links around "; for (auto u: witnessComplex.complex_vertex_range()) + { + std::cout << "Vertex " << u << " "; if (!witnessComplex.has_good_link(u)) { //std::cout << "Landmark " << u << " start!" << std::endl; @@ -470,12 +611,16 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< count_badlinks++; //std::cout << u << " "; Point_d& l = landmarks[u]; - Fuzzy_sphere fs(l, sqrt(lambda)*3, 0, STraits(&(landmarks[0]))); - L.search(std::insert_iterator>(perturbL,perturbL.begin()),fs); + Fuzzy_sphere fs(l, sqrt(lambda)*3, 0, traits); + std::vector curr_perturb; + L.search(std::insert_iterator>(curr_perturb,curr_perturb.begin()),fs); + for (int i: curr_perturb) + perturbL.insert(i%nbL); //L.search(std::inserter(perturbL,perturbL.begin()),fs); //L.search(std::ostream_iterator(std::cout,"\n"),fs); //std::cout << "PerturbL size is " << perturbL.size() << std::endl; } + } std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; //std::cout << "landmark[0][0] before" << landmarks[0][0] << std::endl; //*********************** Perturb bad link landmarks @@ -523,7 +668,18 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< witnessComplex.st_to_file(ofs); ofs.close(); } - + /* + i = sprintf(buffer,"badlinks.txt"); + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.write_bad_links(ofs); + ofs.close(); + } + */ + write_edges("landmarks/edges", witnessComplex, landmarks); + //std::cout << Distance().transformed_distance(Point_d(std::vector({0.1,0.1})), Point_d(std::vector({1.9,1.9}))) << std::endl; return count_badlinks; } @@ -585,13 +741,16 @@ int main (int argc, char * const argv[]) } } int bl = nbL, curr_min = bl; + write_points("landmarks/initial_pointset",point_vector); + //write_points("landmarks/initial_landmarks",L); - for (int i = 0; bl > 0; i++) + for (int i = 0; i < 1; i++) { std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; bl=landmark_perturbation(point_vector, L, chosen_landmarks); if (bl < curr_min) curr_min=bl; + write_points("landmarks/landmarks0",L); } //end = clock(); diff --git a/src/Witness_complex/example/witness_complex_perturbations.cpp b/src/Witness_complex/example/witness_complex_perturbations.cpp index 514b115b..07b1eb8d 100644 --- a/src/Witness_complex/example/witness_complex_perturbations.cpp +++ b/src/Witness_complex/example/witness_complex_perturbations.cpp @@ -157,11 +157,44 @@ void write_wl( std::string file_name, std::vector< std::vector > & WL) ofs.close(); } +void write_points( std::string file_name, std::vector< Point_d > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + } + ofs.close(); +} + +void write_edges_gnuplot(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto u: witness_complex.complex_vertex_range()) + for (auto v: witness_complex.complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) + { + for (auto it = landmarks[u].cartesian_begin(); it != landmarks[u].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + for (auto it = landmarks[v].cartesian_begin(); it != landmarks[v].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n\n\n"; + } + } + ofs.close(); +} + /** Function that chooses landmarks from W and place it in the kd-tree L. * Note: nbL hould be removed if the code moves to Witness_complex */ + void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) { std::cout << "Enter landmark choice to kd tree\n"; @@ -183,7 +216,32 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, //std::cout << "Added landmark " << chosen_landmark << std::endl; } } - +/* +void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + std::cout << "Enter landmark choice to kd tree\n"; + //std::vector landmarks; + int chosen_landmark; + //std::pair res = std::make_pair(L_i.begin(),false); + Point_d* p; + CGAL::Random rand; + for (int i = 0; i < nbL; i++) + { + // while (!res.second) + // { + while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0) + chosen_landmark = rand.get_int(0,nbP); + //rand++; + //std::cout << "Chose " << chosen_landmark << std::endl; + p = &W[chosen_landmark]; + //L_i.emplace(chosen_landmark,i); + // } + landmarks.push_back(*p); + landmarks_ind.push_back(chosen_landmark); + //std::cout << "Added landmark " << chosen_landmark << std::endl; + } + } +*/ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector& landmarks_ind) { @@ -285,13 +343,7 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< //std::cout << "landmark[0][0] after" << landmarks[0][0] << std::endl; std::cout << "lambda=" << lambda << std::endl; // Write the WL matrix in a file - /* - mkdir("output", S_IRWXU); - const size_t last_slash_idx = file_name.find_last_of("/"); - if (std::string::npos != last_slash_idx) - { - file_name.erase(0, last_slash_idx + 1); - } + char buffer[100]; int i = sprintf(buffer,"stree_result.txt"); @@ -303,7 +355,8 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< witnessComplex.st_to_file(ofs); ofs.close(); } - */ + //witnessComplex.write_badlinks("badlinks"); + write_edges_gnuplot("landmarks/edges", witnessComplex, landmarks); return count_badlinks; } @@ -345,10 +398,22 @@ int main (int argc, char * const argv[]) //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); landmark_choice(point_vector, nbP, nbL, L, chosen_landmarks); int bl = 1; + + mkdir("landmarks", S_IRWXU); + const size_t last_slash_idx = file_name.find_last_of("/"); + if (std::string::npos != last_slash_idx) + { + file_name.erase(0, last_slash_idx + 1); + } + write_points("landmarks/initial_pointset",point_vector); + write_points("landmarks/initial_landmarks",L); for (int i = 0; bl != 0; i++) { std::cout << "========== Start iteration " << i << " ========\n"; bl = landmark_perturbation(point_vector, L, chosen_landmarks); + std::ostringstream os(std::ostringstream::ate);; + os << "landmarks/landmarks0"; + write_points(os.str(),L); } //end = clock(); diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index bb553347..c8eaa3ef 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -642,14 +642,16 @@ private: print_vector(link_vertices); std::cout << "\n"; */ + print_vector(link_vertices); std::cout << "\n"; // Find the dimension typeVectorVertex empty_simplex = {}; int d = link_dim(link_vertices, link_vertices.begin(),-1, empty_simplex); //std::cout << " dim " << d << "\n"; //Siblings* curr_sibl = root(); + //std::cout << "Currently at vertex " return (link_is_pseudomanifold(link_vertices,d)); } - + /** \brief Search and output links around vertices that are not pseudomanifolds * */ @@ -661,7 +663,7 @@ private: //int count = 0; for (auto v: complex_vertex_range()) { - //std::cout << "Vertex " << v << ":\n"; + std::cout << "Vertex " << v << ": "; std::vector< Vertex_handle > link_vertices; // Fill link_vertices for (auto u: complex_vertex_range()) @@ -670,10 +672,10 @@ private: if (u != v && find(edge) != null_simplex()) link_vertices.push_back(u); } - /* - print_vector(link_vertices); - std::cout << "\n"; - */ + + print_vector(link_vertices); + std::cout << "\n"; + // Find the dimension typeVectorVertex empty_simplex = {}; int d = link_dim(link_vertices, link_vertices.begin(),-1, empty_simplex); @@ -718,6 +720,7 @@ private: Simplex_handle sh; int final_d = curr_d; typename std::vector< Vertex_handle >::iterator it; + //std::cout << "Current vertex is " << for (it = curr_v; it != link_vertices.end(); ++it) { curr_simplex.push_back(*it); @@ -731,8 +734,13 @@ private: { //std::cout << " -> " << *it << "\n"; int d = link_dim(link_vertices, it+1, curr_d+1, curr_simplex); - if (d > final_d) - final_d = d; + if (d >= final_d) + { + final_d = d; + std::cout << d << " "; + print_vector(curr_simplex); + std::cout << std::endl; + } } /* else @@ -781,14 +789,22 @@ private: //std::cout << "Degree of " << f_map_it.first->first << " is " << boost::out_degree(f_map_it.second, adj_graph) << "\n"; if (boost::out_degree(f_map_it.second, adj_graph) != 2) { + if (boost::out_degree(f_map_it.second, adj_graph) == 3) + { + std::cout << "This simplex has 3 cofaces: "; + for(auto v : simplex_vertex_range(f_map_it.first)) + std::cout << v << " "; + std::cout << std::endl; + } count_bad[dimension]++; return false; } } // At this point I know that all (d-1)-simplices are adjacent to exactly 2 d-simplices // What is left is to check the connexity - std::vector components(boost::num_vertices(adj_graph)); - return (boost::connected_components(adj_graph, &components[0]) == 1); + //std::vector components(boost::num_vertices(adj_graph)); + return true; //Forget the connexity + //return (boost::connected_components(adj_graph, &components[0]) == 1); } void add_vertices(typeVectorVertex& link_vertices, -- cgit v1.2.3 From 5cae0e771c7d4603d25ccf06c782fe383f91e74a Mon Sep 17 00:00:00 2001 From: skachano Date: Fri, 29 May 2015 09:22:36 +0000 Subject: Added the test with spheres git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@598 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f35dd2d082e318b912f581ee86e1407fd39109eb --- .../example/witness_complex_sphere.cpp | 748 +++++++++++++++++++++ 1 file changed, 748 insertions(+) create mode 100644 src/Witness_complex/example/witness_complex_sphere.cpp (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp new file mode 100644 index 00000000..c9a9119a --- /dev/null +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -0,0 +1,748 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 +#include + +#include +#include +//#include + +//#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex.h" +#include "gudhi/reader_utils.h" +//#include + +//#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +using namespace Gudhi; +//using namespace boost::filesystem; + +typedef CGAL::Epick_d K; +typedef K::FT FT; +typedef K::Point_d Point_d; +typedef CGAL::Search_traits< + FT, Point_d, + typename K::Cartesian_const_iterator_d, + typename K::Construct_cartesian_const_iterator_d> Traits_base; +typedef CGAL::Euclidean_distance Euclidean_distance; + +/** + * \brief Class of distance in a flat torus in dimaension D + * + */ +//class Torus_distance : public Euclidean_distance { + class Torus_distance { + +public: + typedef K::FT FT; + typedef K::Point_d Point_d; + typedef Point_d Query_item; + typedef typename CGAL::Dynamic_dimension_tag D; + + double box_length = 2; + + FT transformed_distance(Query_item q, Point_d p) const + { + FT distance = FT(0); + FT coord = FT(0); + //std::cout << "Hello skitty!\n"; + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1), pit = construct_it(p); + for(; qit != qe; qit++, pit++) + { + coord = sqrt(((*qit)-(*pit))*((*qit)-(*pit))); + if (coord*coord <= (box_length-coord)*(box_length-coord)) + distance += coord*coord; + else + distance += (box_length-coord)*(box_length-coord); + } + return distance; + } + + FT min_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r) const { + FT distance = FT(0); + FT dist1, dist2; + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if((*qit) < r.min_coord(i)) + { + dist1 = (r.min_coord(i)-(*qit)); + dist2 = (box_length - r.max_coord(i)+(*qit)); + if (dist1 < dist2) + distance += dist1*dist1; + else + distance += dist2*dist2; + } + else if ((*qit) > r.max_coord(i)) + { + dist1 = (box_length - (*qit)+r.min_coord(i)); + dist2 = ((*qit) - r.max_coord(i)); + if (dist1 < dist2) + distance += dist1*dist1; + else + distance += dist2*dist2; + } + } + return distance; + } + + FT min_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r, + std::vector& dists) const { + FT distance = FT(0); + FT dist1, dist2; + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + //std::cout << r.max_coord(0) << std::endl; + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if((*qit) < r.min_coord(i)) + { + dist1 = (r.min_coord(i)-(*qit)); + dist2 = (box_length - r.max_coord(i)+(*qit)); + if (dist1 < dist2) + { + dists[i] = dist1; + distance += dist1*dist1; + } + else + { + dists[i] = dist2; + distance += dist2*dist2; + //std::cout << "Good stuff1\n"; + } + } + else if ((*qit) > r.max_coord(i)) + { + dist1 = (box_length - (*qit)+r.min_coord(i)); + dist2 = ((*qit) - r.max_coord(i)); + if (dist1 < dist2) + { + dists[i] = dist1; + distance += dist1*dist1; + //std::cout << "Good stuff2\n"; + } + else + { + dists[i] = dist2; + distance += dist2*dist2; + } + } + }; + return distance; + } + + FT max_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r) const { + FT distance=FT(0); + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if (box_length <= (r.min_coord(i)+r.max_coord(i))) + if ((r.max_coord(i)+r.min_coord(i)-box_length)/FT(2.0) <= (*qit) && + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + else + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + else + if ((box_length-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + else + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + } + return distance; + } + + + FT max_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r, + std::vector& dists) const { + FT distance=FT(0); + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if (box_length <= (r.min_coord(i)+r.max_coord(i))) + if ((r.max_coord(i)+r.min_coord(i)-box_length)/FT(2.0) <= (*qit) && + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + { + dists[i] = r.max_coord(i)-(*qit); + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + } + else + { + dists[i] = sqrt(((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i))); + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + } + else + if ((box_length-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + { + dists[i] = sqrt((r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit))); + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + + } + else + { + dists[i] = (*qit)-r.min_coord(i); + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + } + } + return distance; + } + + inline FT new_distance(FT dist, FT old_off, FT new_off, + int /* cutting_dimension */) const { + + FT new_dist = dist + (new_off*new_off - old_off*old_off); + return new_dist; + } + + inline FT transformed_distance(FT d) const { + return d*d; + } + + inline FT inverse_of_transformed_distance(FT d) const { + return sqrt(d); + } + +}; + + +typedef std::vector< Vertex_handle > typeVectorVertex; + +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + +typedef CGAL::Search_traits_adapter< + std::ptrdiff_t, Point_d*, Traits_base> STraits; +//typedef K TreeTraits; +//typedef CGAL::Distance_adapter Euclidean_adapter; +//typedef CGAL::Kd_tree Kd_tree; +typedef CGAL::Orthogonal_k_neighbor_search> K_neighbor_search; +typedef K_neighbor_search::Tree Tree; +typedef K_neighbor_search::Distance Distance; +typedef K_neighbor_search::iterator KNS_iterator; +typedef K_neighbor_search::iterator KNS_range; +typedef boost::container::flat_map Point_etiquette_map; +typedef CGAL::Kd_tree Tree2; + +typedef CGAL::Fuzzy_sphere Fuzzy_sphere; + +typedef std::vector Point_Vector; + +//typedef K::Equal_d Equal_d; +typedef CGAL::Random_points_in_cube_d Random_cube_iterator; +typedef CGAL::Random_points_in_ball_d Random_point_iterator; + +bool toric=false; + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , Point_Vector & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + Point_d p(point.begin(), point.end()); + if (point.size() != 1) + points.push_back(p); + } + in_file.close(); +} + +void generate_points_grid(Point_Vector& W, int width, int D) +{ + +} + +void generate_points_random_box(Point_Vector& W, int nbP, int dim) +{ + Random_cube_iterator rp(dim, 1); + for (int i = 0; i < nbP; i++) + { + W.push_back(*rp++); + } +} + +/* NOT TORUS RELATED + */ +void generate_points_sphere(Point_Vector& W, int nbP, int dim) +{ + CGAL::Random_points_on_sphere_d rp(dim,1); + for (int i = 0; i < nbP; i++) + W.push_back(*rp++); +} +/* +void read_points_to_tree (std::string file_name, Tree& tree) +{ + //I assume here that tree is empty + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector coords; + std::istringstream iss( line ); + while(iss >> x) { coords.push_back(x); } + if (coords.size() != 1) + { + Point_d point(coords.begin(), coords.end()); + tree.insert(point); + } + } + in_file.close(); +} +*/ + +void write_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto l: w) + ofs << l << " "; + ofs << "\n"; + } + ofs.close(); +} + + +std::vector convert_to_torus(std::vector< Point_d>& points) +{ + std::vector< Point_d > points_torus; + for (auto p: points) + { + FT theta = M_PI*p[0]; + FT phi = M_PI*p[1]; + std::vector p_torus; + p_torus.push_back((1+0.2*cos(theta))*cos(phi)); + p_torus.push_back((1+0.2*cos(theta))*sin(phi)); + p_torus.push_back(0.2*sin(theta)); + points_torus.push_back(Point_d(p_torus)); + } + return points_torus; +} + +void write_points_torus( std::string file_name, std::vector< Point_d > & points) +{ + std::ofstream ofs (file_name, std::ofstream::out); + std::vector points_torus = convert_to_torus(points); + for (auto w : points_torus) + { + for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + } + ofs.close(); +} + +void write_points( std::string file_name, std::vector< Point_d > & points) +{ + if (toric) write_points_torus(file_name, points); + else + { + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : points) + { + for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + } + ofs.close(); + } +} + + +void write_edges_torus(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) +{ + std::ofstream ofs (file_name, std::ofstream::out); + Point_Vector l_torus = convert_to_torus(landmarks); + for (auto u: witness_complex.complex_vertex_range()) + for (auto v: witness_complex.complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) + { + for (auto it = l_torus[u].cartesian_begin(); it != l_torus[u].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + for (auto it = l_torus[v].cartesian_begin(); it != l_torus[v].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n\n\n"; + } + } + ofs.close(); +} + +void write_edges(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) +{ + std::ofstream ofs (file_name, std::ofstream::out); + if (toric) write_edges_torus(file_name, witness_complex, landmarks); + else + { + for (auto u: witness_complex.complex_vertex_range()) + for (auto v: witness_complex.complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) + { + for (auto it = landmarks[u].cartesian_begin(); it != landmarks[u].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + for (auto it = landmarks[v].cartesian_begin(); it != landmarks[v].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n\n\n"; + } + } + ofs.close(); + } +} + + +/** Function that chooses landmarks from W and place it in the kd-tree L. + * Note: nbL hould be removed if the code moves to Witness_complex + */ +void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + std::cout << "Enter landmark choice to kd tree\n"; + //std::vector landmarks; + int chosen_landmark; + //std::pair res = std::make_pair(L_i.begin(),false); + Point_d* p; + CGAL::Random rand; + for (int i = 0; i < nbL; i++) + { + // while (!res.second) + // { + while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0) + chosen_landmark = rand.get_int(0,nbP); + //rand++; + //std::cout << "Chose " << chosen_landmark << std::endl; + p = &W[chosen_landmark]; + //L_i.emplace(chosen_landmark,i); + // } + landmarks.push_back(*p); + landmarks_ind.push_back(chosen_landmark); + //std::cout << "Added landmark " << chosen_landmark << std::endl; + } + } + + +int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + //********************Preface: origin point + int D = W[0].size(); + std::vector orig_vector; + for (int i=0; i({0.8,0.8})), p2(std::vector({0.1,0.1})); + FT lambda = ed.transformed_distance(landmarks[0],landmarks[1]); + //std::cout << "Lambda=" << lambda << std::endl; + //FT lambda = 0.1;//Euclidean_distance(); + STraits traits(&(landmarks[0])); + std::vector< std::vector > WL(nbP); + Tree L(boost::counting_iterator(0), + boost::counting_iterator(nbL), + typename Tree::Splitter(), + traits); + /*Tree2 L2(boost::counting_iterator(0), + boost::counting_iterator(nbL), + typename Tree::Splitter(), + STraits(&(landmarks[0]))); + */ + std::cout << "Enter (D+1) nearest landmarks\n"; + //std::cout << "Size of the tree is " << L.size() << std::endl; + for (int i = 0; i < nbP; i++) + { + //std::cout << "Entered witness number " << i << std::endl; + Point_d& w = W[i]; + //std::cout << "Safely constructed a point\n"; + ////Search D+1 nearest neighbours from the tree of landmarks L + /* + if (w[0]>0.95) + std::cout << i << std::endl; + */ + K_neighbor_search search(L, w, D+1, FT(0), true, + //CGAL::Distance_adapter(&(landmarks[0])) ); + CGAL::Distance_adapter(&(landmarks[0])) ); + //std::cout << "Safely found nearest landmarks\n"; + for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) + { + //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; + //Point_etiquette_map::iterator itm = L_i.find(it->first); + //assert(itm != L_i.end()); + //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; + WL[i].push_back(it->first); + //std::cout << "ITFIRST " << it->first << std::endl; + //std::cout << i << " " << it->first << ": " << it->second << std::endl; + } + if (i == landmarks_ind[WL[i][0]]) + { + //std::cout << "'"; + FT dist = ed.transformed_distance(W[i], landmarks[WL[i][1]]); + if (dist < lambda) + lambda = dist; + } + } + //std::cout << "\n"; + + std::string out_file = "wl_result"; + write_wl(out_file,WL); + + //******************** Constructng a witness complex + std::cout << "Entered witness complex construction\n"; + Witness_complex<> witnessComplex; + witnessComplex.setNbL(nbL); + witnessComplex.witness_complex(WL); + //******************** Making a set of bad link landmarks + std::cout << "Entered bad links\n"; + std::set< int > perturbL; + int count_badlinks = 0; + //std::cout << "Bad links around "; + for (auto u: witnessComplex.complex_vertex_range()) + if (!witnessComplex.has_good_link(u)) + { + //std::cout << "Landmark " << u << " start!" << std::endl; + //perturbL.insert(u); + count_badlinks++; + //std::cout << u << " "; + Point_d& l = landmarks[u]; + Fuzzy_sphere fs(l, sqrt(lambda)*3, 0, traits); + std::vector curr_perturb; + L.search(std::insert_iterator>(curr_perturb,curr_perturb.begin()),fs); + for (int i: curr_perturb) + perturbL.insert(i%nbL); + //L.search(std::inserter(perturbL,perturbL.begin()),fs); + //L.search(std::ostream_iterator(std::cout,"\n"),fs); + //std::cout << "PerturbL size is " << perturbL.size() << std::endl; + } + std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; + //std::cout << "landmark[0][0] before" << landmarks[0][0] << std::endl; + //*********************** Perturb bad link landmarks + + for (auto u: perturbL) + { + Random_point_iterator rp(D,sqrt(lambda)/8); + //std::cout << landmarks[u] << std::endl; + + std::vector point; + for (int i = 0; i < D; i++) + { + while (K().squared_distance_d_object()(*rp,origin) < lambda/256) + rp++; + //FT coord = W[landmarks_ind[u]][i] + (*rp)[i]; + FT coord = landmarks[u][i] + (*rp)[i]; + if (coord > 1) + point.push_back(coord-1); + else if (coord < -1) + point.push_back(coord+1); + else + point.push_back(coord); + } + landmarks[u] = Point_d(point); + //std::cout << landmarks[u] << std::endl; + } + + //std::cout << "landmark[0][0] after" << landmarks[0][0] << std::endl; + std::cout << "lambda=" << lambda << std::endl; + + //std::cout << "WL size" << WL.size() << std::endl; + /* + std::cout << "L:" << std::endl; + for (int i = 0; i < landmarks.size(); i++) + std::cout << landmarks[i] << std::endl; + */ + + char buffer[100]; + int i = sprintf(buffer,"stree_result.txt"); + + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } + write_edges("landmarks/edges", witnessComplex, landmarks); + std::cout << Distance().transformed_distance(Point_d(std::vector({0.1,0.1})), Point_d(std::vector({1.9,1.9}))) << std::endl; + return count_badlinks; +} + + +int main (int argc, char * const argv[]) +{ + + if (argc != 4) + { + std::cerr << "Usage: " << argv[0] + << " nbP nbL dim\n"; + return 0; + } + /* + boost::filesystem::path p; + for (; argc > 2; --argc, ++argv) + p /= argv[1]; + */ + + int nbP = atoi(argv[1]); + int nbL = atoi(argv[2]); + int dim = atoi(argv[3]); + //clock_t start, end; + //Construct the Simplex Tree + //Witness_complex<> witnessComplex; + + std::cout << "Let the carnage begin!\n"; + Point_Vector point_vector; + //read_points_cust(file_name, point_vector); + generate_points_sphere(point_vector, nbP, dim); + /* + for (auto &p: point_vector) + { + assert(std::count(point_vector.begin(),point_vector.end(),p) == 1); + } + */ + //std::cout << "Successfully read the points\n"; + //witnessComplex.setNbL(nbL); + // witnessComplex.witness_complex_from_points(point_vector); + //int nbP = point_vector.size(); + //std::vector > WL(nbP); + //std::set L; + Point_Vector L; + std::vector chosen_landmarks; + //Point_etiquette_map L_i; + //start = clock(); + //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); + bool ok=false; + while (!ok) + { + ok = true; + L = {}; + chosen_landmarks = {}; + landmark_choice(point_vector, nbP, nbL, L, chosen_landmarks); + for (auto i: chosen_landmarks) + { + ok = ok && (std::count(chosen_landmarks.begin(),chosen_landmarks.end(),i) == 1); + if (!ok) break; + } + } + int bl = nbL, curr_min = bl; + write_points("landmarks/initial_pointset",point_vector); + write_points("landmarks/initial_landmarks",L); + + for (int i = 0; bl > 0; i++) + { + std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; + bl=landmark_perturbation(point_vector, L, chosen_landmarks); + if (bl < curr_min) + curr_min=bl; + write_points("landmarks/landmarks0",L); + } + //end = clock(); + + /* + std::cout << "Landmark choice took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + start = clock(); + witnessComplex.witness_complex(WL); + // + end = clock(); + std::cout << "Howdy world! The process took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + */ + + /* + out_file = "output/"+file_name+"_"+argv[2]+".stree"; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + + out_file = "output/"+file_name+"_"+argv[2]+".badlinks"; + std::ofstream ofs2(out_file, std::ofstream::out); + witnessComplex.write_bad_links(ofs2); + ofs2.close(); + */ +} -- cgit v1.2.3 From 3efbb8c26aecc9f88dae4ec69d3149a4f5f1bd40 Mon Sep 17 00:00:00 2001 From: skachano Date: Sat, 30 May 2015 15:36:35 +0000 Subject: witness: Testing continues git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@600 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 57d8d66a90e9839887289e4efd7fbddabe009d94 --- .../example/witness_complex_perturbations.cpp | 2 +- .../example/witness_complex_sphere.cpp | 15 ++++++++-- .../include/gudhi/Witness_complex.h | 32 ++++++++++++++++------ 3 files changed, 37 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_perturbations.cpp b/src/Witness_complex/example/witness_complex_perturbations.cpp index 07b1eb8d..9d39906b 100644 --- a/src/Witness_complex/example/witness_complex_perturbations.cpp +++ b/src/Witness_complex/example/witness_complex_perturbations.cpp @@ -328,7 +328,7 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< for (auto u: perturbL) { - Random_point_iterator rp(D,sqrt(lambda)/2); + Random_point_iterator rp(D,sqrt(lambda)/4); //std::cout << landmarks[u] << std::endl; std::vector point; diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index c9a9119a..7ba1dd61 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -489,8 +489,9 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, { // while (!res.second) // { - while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0) + do chosen_landmark = rand.get_int(0,nbP); + while (std::find(landmarks_ind.begin(), landmarks_ind.end(), chosen_landmark) != landmarks_ind.end()); //rand++; //std::cout << "Chose " << chosen_landmark << std::endl; p = &W[chosen_landmark]; @@ -546,7 +547,7 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< if (w[0]>0.95) std::cout << i << std::endl; */ - K_neighbor_search search(L, w, D+1, FT(0), true, + K_neighbor_search search(L, w, D, FT(0), true, //CGAL::Distance_adapter(&(landmarks[0])) ); CGAL::Distance_adapter(&(landmarks[0])) ); //std::cout << "Safely found nearest landmarks\n"; @@ -583,8 +584,10 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< std::set< int > perturbL; int count_badlinks = 0; //std::cout << "Bad links around "; + std::vector< int > count_bad(D+3); + std::vector< int > count_good(D+3); for (auto u: witnessComplex.complex_vertex_range()) - if (!witnessComplex.has_good_link(u)) + if (!witnessComplex.has_good_link(u, count_bad, count_good)) { //std::cout << "Landmark " << u << " start!" << std::endl; //perturbL.insert(u); @@ -600,6 +603,12 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< //L.search(std::ostream_iterator(std::cout,"\n"),fs); //std::cout << "PerturbL size is " << perturbL.size() << std::endl; } + for (unsigned int i = 0; i != count_good.size(); i++) + if (count_good[i] != 0) + std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; + for (unsigned int i = 0; i != count_bad.size(); i++) + if (count_bad[i] != 0) + std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; //std::cout << "landmark[0][0] before" << landmarks[0][0] << std::endl; //*********************** Perturb bad link landmarks diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index c8eaa3ef..c45d144d 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -628,7 +628,7 @@ private: /** \brief Returns true if the link is good */ - bool has_good_link(Vertex_handle v) + bool has_good_link(Vertex_handle v, std::vector< int >& bad_count, std::vector< int >& good_count) { std::vector< Vertex_handle > link_vertices; // Fill link_vertices @@ -642,14 +642,28 @@ private: print_vector(link_vertices); std::cout << "\n"; */ - print_vector(link_vertices); std::cout << "\n"; + //print_vector(link_vertices); std::cout << "\n"; // Find the dimension typeVectorVertex empty_simplex = {}; int d = link_dim(link_vertices, link_vertices.begin(),-1, empty_simplex); + /* + if (d >= good_count.size()) + { + std::cout << "d=" << d << std::endl; + std::cout << "gc.size=" << good_count.size() << std::endl; + print_vector(link_vertices); + std::cout << std::endl; + } + */ + //assert(d < good_count.size()); + if (d == -1) bad_count[0]++; //std::cout << " dim " << d << "\n"; //Siblings* curr_sibl = root(); //std::cout << "Currently at vertex " - return (link_is_pseudomanifold(link_vertices,d)); + bool b= (link_is_pseudomanifold(link_vertices,d)); + if (d != -1) {if (b) good_count[d]++; else bad_count[d]++;} + return b; + } /** \brief Search and output links around vertices that are not pseudomanifolds @@ -737,9 +751,9 @@ private: if (d >= final_d) { final_d = d; - std::cout << d << " "; - print_vector(curr_simplex); - std::cout << std::endl; + //std::cout << d << " "; + //print_vector(curr_simplex); + // std::cout << std::endl; } } /* @@ -789,13 +803,15 @@ private: //std::cout << "Degree of " << f_map_it.first->first << " is " << boost::out_degree(f_map_it.second, adj_graph) << "\n"; if (boost::out_degree(f_map_it.second, adj_graph) != 2) { + /* if (boost::out_degree(f_map_it.second, adj_graph) == 3) - { + { std::cout << "This simplex has 3 cofaces: "; for(auto v : simplex_vertex_range(f_map_it.first)) std::cout << v << " "; std::cout << std::endl; - } + + }*/ count_bad[dimension]++; return false; } -- cgit v1.2.3 From 9e99b02fa2d91aced59c5fded3f1a2e07afe30aa Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 1 Jun 2015 09:00:41 +0000 Subject: Corrected bad-good links git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@601 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 004b949f2d74b803483535b126e76b84b27f4a7e --- .../example/witness_complex_flat_torus.cpp | 14 ++- .../example/witness_complex_sphere.cpp | 9 +- .../include/gudhi/Witness_complex.h | 110 ++++++++++----------- 3 files changed, 71 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_flat_torus.cpp b/src/Witness_complex/example/witness_complex_flat_torus.cpp index ff995a4f..14d6426d 100644 --- a/src/Witness_complex/example/witness_complex_flat_torus.cpp +++ b/src/Witness_complex/example/witness_complex_flat_torus.cpp @@ -601,10 +601,12 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< std::set< int > perturbL; int count_badlinks = 0; //std::cout << "Bad links around "; + std::vector< int > count_bad(D); + std::vector< int > count_good(D); for (auto u: witnessComplex.complex_vertex_range()) { - std::cout << "Vertex " << u << " "; - if (!witnessComplex.has_good_link(u)) + //std::cout << "Vertex " << u << " "; + if (!witnessComplex.has_good_link(u, count_bad, count_good)) { //std::cout << "Landmark " << u << " start!" << std::endl; //perturbL.insert(u); @@ -621,6 +623,12 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< //std::cout << "PerturbL size is " << perturbL.size() << std::endl; } } + for (unsigned int i = 0; i != count_good.size(); i++) + if (count_good[i] != 0) + std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; + for (unsigned int i = 0; i != count_bad.size(); i++) + if (count_bad[i] != 0) + std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; //std::cout << "landmark[0][0] before" << landmarks[0][0] << std::endl; //*********************** Perturb bad link landmarks @@ -744,7 +752,7 @@ int main (int argc, char * const argv[]) write_points("landmarks/initial_pointset",point_vector); //write_points("landmarks/initial_landmarks",L); - for (int i = 0; i < 1; i++) + for (int i = 0; bl > 0; i++) { std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; bl=landmark_perturbation(point_vector, L, chosen_landmarks); diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index 7ba1dd61..f6345411 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -584,8 +584,8 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< std::set< int > perturbL; int count_badlinks = 0; //std::cout << "Bad links around "; - std::vector< int > count_bad(D+3); - std::vector< int > count_good(D+3); + std::vector< int > count_bad(D); + std::vector< int > count_good(D); for (auto u: witnessComplex.complex_vertex_range()) if (!witnessComplex.has_good_link(u, count_bad, count_good)) { @@ -623,8 +623,8 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< { while (K().squared_distance_d_object()(*rp,origin) < lambda/256) rp++; - //FT coord = W[landmarks_ind[u]][i] + (*rp)[i]; - FT coord = landmarks[u][i] + (*rp)[i]; + FT coord = W[landmarks_ind[u]][i] + (*rp)[i]; + //FT coord = landmarks[u][i] + (*rp)[i]; if (coord > 1) point.push_back(coord-1); else if (coord < -1) @@ -723,6 +723,7 @@ int main (int argc, char * const argv[]) write_points("landmarks/initial_landmarks",L); for (int i = 0; bl > 0; i++) + //for (int i = 0; i < 1; i++) { std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; bl=landmark_perturbation(point_vector, L, chosen_landmarks); diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index c45d144d..0888c086 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -630,51 +630,41 @@ private: */ bool has_good_link(Vertex_handle v, std::vector< int >& bad_count, std::vector< int >& good_count) { - std::vector< Vertex_handle > link_vertices; - // Fill link_vertices + std::vector< Vertex_handle > star_vertices; + // Fill star_vertices + star_vertices.push_back(v); for (auto u: complex_vertex_range()) { typeVectorVertex edge = {u,v}; if (u != v && find(edge) != null_simplex()) - link_vertices.push_back(u); + star_vertices.push_back(u); } - /* - print_vector(link_vertices); - std::cout << "\n"; - */ - //print_vector(link_vertices); std::cout << "\n"; // Find the dimension - typeVectorVertex empty_simplex = {}; - int d = link_dim(link_vertices, link_vertices.begin(),-1, empty_simplex); + typeVectorVertex init_simplex = {star_vertices[0]}; + int d = star_dim(star_vertices, star_vertices.begin()+1, 0, init_simplex) - 1; //link_dim = star_dim - 1 + assert(init_simplex.size() == 1); /* - if (d >= good_count.size()) - { - std::cout << "d=" << d << std::endl; - std::cout << "gc.size=" << good_count.size() << std::endl; - print_vector(link_vertices); - std::cout << std::endl; - } - */ - //assert(d < good_count.size()); + if (d == count_good.size()) + { + std::cout << "Found a star of dimension " << (d+1) << " around " << v << "\nThe star is "; + print_vector(star_vertices); std::cout << std::endl; + } + */ if (d == -1) bad_count[0]++; - //std::cout << " dim " << d << "\n"; - //Siblings* curr_sibl = root(); - //std::cout << "Currently at vertex " - bool b= (link_is_pseudomanifold(link_vertices,d)); + bool b= (link_is_pseudomanifold(star_vertices,d)); if (d != -1) {if (b) good_count[d]++; else bad_count[d]++;} - return b; + return (d != -1 && b); } /** \brief Search and output links around vertices that are not pseudomanifolds * */ + /* void write_bad_links(std::ofstream& out_file) { out_file << "Bad links list\n"; std::cout << "Entered write_bad_links\n"; - //typeVectorVertex testv = {9,15,17}; - //int count = 0; for (auto v: complex_vertex_range()) { std::cout << "Vertex " << v << ": "; @@ -693,14 +683,9 @@ private: // Find the dimension typeVectorVertex empty_simplex = {}; int d = link_dim(link_vertices, link_vertices.begin(),-1, empty_simplex); - //std::cout << " dim " << d << "\n"; - //Siblings* curr_sibl = root(); if (link_is_pseudomanifold(link_vertices,d)) count_good[d]++; - //out_file << "Bad link at " << v << "\n"; } - //out_file << "Number of bad links: " << count << "/" << root()->size(); - //std::cout << "Number of bad links: " << count << "/" << root()->size() << std::endl; nc = nbL; for (unsigned int i = 0; i != count_good.size(); i++) { @@ -718,42 +703,43 @@ private: } std::cout << "not_connected = " << nc << std::endl; } - + */ private: std::vector count_good; std::vector count_bad; int nc; - int link_dim(std::vector< Vertex_handle >& link_vertices, + int star_dim(std::vector< Vertex_handle >& star_vertices, typename std::vector< Vertex_handle >::iterator curr_v, int curr_d, typeVectorVertex& curr_simplex) { - //std::cout << "Entered link_dim for " << *(curr_v-1) << "\n"; + //std::cout << "Entered star_dim for " << *(curr_v-1) << "\n"; Simplex_handle sh; int final_d = curr_d; typename std::vector< Vertex_handle >::iterator it; //std::cout << "Current vertex is " << - for (it = curr_v; it != link_vertices.end(); ++it) + for (it = curr_v; it != star_vertices.end(); ++it) { curr_simplex.push_back(*it); + typeVectorVertex curr_simplex_copy(curr_simplex); /* std::cout << "Searching for "; print_vector(curr_simplex); std::cout << " curr_dim " << curr_d << " final_dim " << final_d; */ - sh = find(curr_simplex); + sh = find(curr_simplex_copy); //Need a copy because find sorts the vector and I want star center to be the first if (sh != null_simplex()) { //std::cout << " -> " << *it << "\n"; - int d = link_dim(link_vertices, it+1, curr_d+1, curr_simplex); + int d = star_dim(star_vertices, it+1, curr_d+1, curr_simplex); if (d >= final_d) { final_d = d; //std::cout << d << " "; //print_vector(curr_simplex); - // std::cout << std::endl; + //std::cout << std::endl; } } /* @@ -781,19 +767,19 @@ private: * The idea is to make a bipartite graph, where vertices are the d- and (d-1)-dimensional * faces and edges represent adjacency between them. */ - bool link_is_pseudomanifold(std::vector< Vertex_handle >& link_vertices, + bool link_is_pseudomanifold(std::vector< Vertex_handle >& star_vertices, int dimension) { Adj_graph adj_graph; Graph_map d_map, f_map; // d_map = map for d-dimensional simplices // f_map = map for its facets - typeVectorVertex empty_vector = {}; - add_vertices(link_vertices, - link_vertices.begin(), + typeVectorVertex init_vector = {}; + add_vertices(star_vertices, + star_vertices.begin()+1, adj_graph, d_map, f_map, - empty_vector, + init_vector, 0, dimension); //std::cout << "DMAP_SIZE: " << d_map.size() << "\n"; //std::cout << "FMAP_SIZE: " << f_map.size() << "\n"; @@ -823,60 +809,74 @@ private: //return (boost::connected_components(adj_graph, &components[0]) == 1); } - void add_vertices(typeVectorVertex& link_vertices, + void add_vertices(typeVectorVertex& star_vertices, typename typeVectorVertex::iterator curr_v, Adj_graph& adj_graph, Graph_map& d_map, Graph_map& f_map, typeVectorVertex& curr_simplex, int curr_d, - int dimension) + int link_dimension) { Simplex_handle sh; Vertex_t vert; typename typeVectorVertex::iterator it; - std::pair resPair; + //std::pair resPair; //typename Graph_map::iterator resPair; //Add vertices //std::cout << "Entered add vertices\n"; - for (it = curr_v; it != link_vertices.end(); ++it) + for (it = curr_v; it != star_vertices.end(); ++it) { - curr_simplex.push_back(*it); + curr_simplex.push_back(*it); //push next vertex in question + curr_simplex.push_back(star_vertices[0]); //push the center of the star /* std::cout << "Searching for "; print_vector(curr_simplex); std::cout << " curr_dim " << curr_d << " d " << dimension << ""; */ - sh = find(curr_simplex); + typeVectorVertex curr_simplex_copy(curr_simplex); + sh = find(curr_simplex_copy); //a simplex of the star + curr_simplex.pop_back(); //pop the center of the star + curr_simplex_copy = typeVectorVertex(curr_simplex); if (sh != null_simplex()) { //std::cout << " added\n"; - if (curr_d == dimension) + if (curr_d == link_dimension) { + sh = find(curr_simplex_copy); //a simplex of the link + assert(sh != null_simplex()); //ASSERT! vert = boost::add_vertex(adj_graph); - resPair = d_map.emplace(sh,vert); + d_map.emplace(sh,vert); + for (Simplex_handle sh_b: boundary_simplex_range(sh)) + { + vert = boost::add_vertex(adj_graph); + f_map.emplace(sh_b,vert); + } } else { - if (curr_d == dimension-1) + /* + if (curr_d == link_dimension-1) { vert = boost::add_vertex(adj_graph); resPair = f_map.emplace(sh,vert); } - add_vertices(link_vertices, + */ + //delete (&curr_simplex_copy); //Just so it doesn't stack + add_vertices(star_vertices, it+1, adj_graph, d_map, f_map, curr_simplex, - curr_d+1, dimension); + curr_d+1, link_dimension); } } /* else std::cout << "\n"; */ - curr_simplex.pop_back(); + curr_simplex.pop_back(); //pop the vertex in question } } -- cgit v1.2.3 From 5f049ec0dbf0f756d8ecc5e55b00d2bd748cb927 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 3 Jun 2015 08:40:22 +0000 Subject: witness: Added good-bad link count to witness_complex_perturbations git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@602 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b4dbfbf4f8c59399b174574216b577075f08ede8 --- .../example/witness_complex_perturbations.cpp | 20 +++++++++++++++----- src/Witness_complex/include/gudhi/Witness_complex.h | 14 ++++++++++---- 2 files changed, 25 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_perturbations.cpp b/src/Witness_complex/example/witness_complex_perturbations.cpp index 9d39906b..ec7a5abe 100644 --- a/src/Witness_complex/example/witness_complex_perturbations.cpp +++ b/src/Witness_complex/example/witness_complex_perturbations.cpp @@ -292,6 +292,8 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< if (dist < lambda) lambda = dist; } + //std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; + } //std::cout << "\n"; @@ -307,14 +309,16 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< std::cout << "Entered bad links\n"; std::set< int > perturbL; int count_badlinks = 0; - std::cout << "Bad links around "; + std::vector< int > count_bad(D); + std::vector< int > count_good(D); + //std::cout << "Bad links around "; for (auto u: witnessComplex.complex_vertex_range()) - if (!witnessComplex.has_good_link(u)) + if (!witnessComplex.has_good_link(u, count_bad, count_good)) { //std::cout << "Landmark " << u << " start!" << std::endl; //perturbL.insert(u); count_badlinks++; - std::cout << u << " "; + //std::cout << u << " "; Point_d& l = landmarks[u]; Fuzzy_sphere fs(l, sqrt(lambda)*2, 0, STraits(&(landmarks[0]))); L.search(std::insert_iterator>(perturbL,perturbL.begin()),fs); @@ -322,7 +326,13 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< //L.search(std::ostream_iterator(std::cout,"\n"),fs); //std::cout << "PerturbL size is " << perturbL.size() << std::endl; } - std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; + for (unsigned int i = 0; i != count_good.size(); i++) + if (count_good[i] != 0) + std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; + for (unsigned int i = 0; i != count_bad.size(); i++) + if (count_bad[i] != 0) + std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; + std::cout << "Bad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; //std::cout << "landmark[0][0] before" << landmarks[0][0] << std::endl; //*********************** Perturb bad link landmarks @@ -405,7 +415,7 @@ int main (int argc, char * const argv[]) { file_name.erase(0, last_slash_idx + 1); } - write_points("landmarks/initial_pointset",point_vector); + //write_points("landmarks/initial_pointset",point_vector); write_points("landmarks/initial_landmarks",L); for (int i = 0; bl != 0; i++) { diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 0888c086..222e379c 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -641,8 +641,11 @@ private: } // Find the dimension typeVectorVertex init_simplex = {star_vertices[0]}; - int d = star_dim(star_vertices, star_vertices.begin()+1, 0, init_simplex) - 1; //link_dim = star_dim - 1 + bool is_pure = true; + int d = star_dim(star_vertices, star_vertices.begin()+1, 0, init_simplex, is_pure) - 1; //link_dim = star_dim - 1 assert(init_simplex.size() == 1); + if (!is_pure) + std::cout << "Found an impure star around " << v << "\n"; /* if (d == count_good.size()) { @@ -651,7 +654,7 @@ private: } */ if (d == -1) bad_count[0]++; - bool b= (link_is_pseudomanifold(star_vertices,d)); + bool b= (is_pure && link_is_pseudomanifold(star_vertices,d)); if (d != -1) {if (b) good_count[d]++; else bad_count[d]++;} return (d != -1 && b); @@ -713,7 +716,8 @@ private: int star_dim(std::vector< Vertex_handle >& star_vertices, typename std::vector< Vertex_handle >::iterator curr_v, int curr_d, - typeVectorVertex& curr_simplex) + typeVectorVertex& curr_simplex, + bool& is_pure) { //std::cout << "Entered star_dim for " << *(curr_v-1) << "\n"; Simplex_handle sh; @@ -733,7 +737,9 @@ private: if (sh != null_simplex()) { //std::cout << " -> " << *it << "\n"; - int d = star_dim(star_vertices, it+1, curr_d+1, curr_simplex); + int d = star_dim(star_vertices, it+1, curr_d+1, curr_simplex, is_pure); + if (it != curr_v && d != final_d) //If the dimension is known and differs from the one computed previously + is_pure = false; //the simplex is not pure if (d >= final_d) { final_d = d; -- cgit v1.2.3 From 2bfa55d843580497f00376ede3dddf5c106dc12f Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 3 Jun 2015 12:37:11 +0000 Subject: Fixed purity and landmark choice git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@604 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 42e8bc2c939605e73ceb554ecf68e1807d3efb85 --- .../include/gudhi/Witness_complex.h | 73 ++++++++++++---------- 1 file changed, 39 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 222e379c..8b87ae89 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -642,10 +642,13 @@ private: // Find the dimension typeVectorVertex init_simplex = {star_vertices[0]}; bool is_pure = true; - int d = star_dim(star_vertices, star_vertices.begin()+1, 0, init_simplex, is_pure) - 1; //link_dim = star_dim - 1 + std::vector dim_coface(star_vertices.size(), 1); + int d = star_dim(star_vertices, star_vertices.begin()+1, 0, init_simplex, dim_coface.begin()+1) - 1; //link_dim = star_dim - 1 assert(init_simplex.size() == 1); if (!is_pure) std::cout << "Found an impure star around " << v << "\n"; + for (int dc: dim_coface) + is_pure = (dc == dim_coface[0]); /* if (d == count_good.size()) { @@ -653,10 +656,11 @@ private: print_vector(star_vertices); std::cout << std::endl; } */ - if (d == -1) bad_count[0]++; + //if (d == -1) bad_count[0]++; bool b= (is_pure && link_is_pseudomanifold(star_vertices,d)); if (d != -1) {if (b) good_count[d]++; else bad_count[d]++;} - return (d != -1 && b); + if (!is_pure) bad_count[0]++; + return (d != -1 && b && is_pure); } @@ -717,14 +721,15 @@ private: typename std::vector< Vertex_handle >::iterator curr_v, int curr_d, typeVectorVertex& curr_simplex, - bool& is_pure) + typename std::vector< int >::iterator curr_dc) { //std::cout << "Entered star_dim for " << *(curr_v-1) << "\n"; Simplex_handle sh; int final_d = curr_d; typename std::vector< Vertex_handle >::iterator it; + typename std::vector< Vertex_handle >::iterator dc_it; //std::cout << "Current vertex is " << - for (it = curr_v; it != star_vertices.end(); ++it) + for (it = curr_v, dc_it = curr_dc; it != star_vertices.end(); ++it, ++dc_it) { curr_simplex.push_back(*it); typeVectorVertex curr_simplex_copy(curr_simplex); @@ -737,9 +742,7 @@ private: if (sh != null_simplex()) { //std::cout << " -> " << *it << "\n"; - int d = star_dim(star_vertices, it+1, curr_d+1, curr_simplex, is_pure); - if (it != curr_v && d != final_d) //If the dimension is known and differs from the one computed previously - is_pure = false; //the simplex is not pure + int d = star_dim(star_vertices, it+1, curr_d+1, curr_simplex, dc_it); if (d >= final_d) { final_d = d; @@ -747,6 +750,8 @@ private: //print_vector(curr_simplex); //std::cout << std::endl; } + if (d >= *dc_it) + *dc_it = d; } /* else @@ -780,16 +785,16 @@ private: Graph_map d_map, f_map; // d_map = map for d-dimensional simplices // f_map = map for its facets typeVectorVertex init_vector = {}; - add_vertices(star_vertices, - star_vertices.begin()+1, - adj_graph, - d_map, - f_map, - init_vector, - 0, dimension); + add_vertices_to_link_graph(star_vertices, + star_vertices.begin()+1, + adj_graph, + d_map, + f_map, + init_vector, + 0, dimension); //std::cout << "DMAP_SIZE: " << d_map.size() << "\n"; //std::cout << "FMAP_SIZE: " << f_map.size() << "\n"; - add_edges(adj_graph, d_map, f_map); + add_edges_to_link_graph(adj_graph, d_map, f_map); for (auto f_map_it : f_map) { //std::cout << "Degree of " << f_map_it.first->first << " is " << boost::out_degree(f_map_it.second, adj_graph) << "\n"; @@ -815,14 +820,14 @@ private: //return (boost::connected_components(adj_graph, &components[0]) == 1); } - void add_vertices(typeVectorVertex& star_vertices, - typename typeVectorVertex::iterator curr_v, - Adj_graph& adj_graph, - Graph_map& d_map, - Graph_map& f_map, - typeVectorVertex& curr_simplex, - int curr_d, - int link_dimension) + void add_vertices_to_link_graph(typeVectorVertex& star_vertices, + typename typeVectorVertex::iterator curr_v, + Adj_graph& adj_graph, + Graph_map& d_map, + Graph_map& f_map, + typeVectorVertex& curr_simplex, + int curr_d, + int link_dimension) { Simplex_handle sh; Vertex_t vert; @@ -869,13 +874,13 @@ private: } */ //delete (&curr_simplex_copy); //Just so it doesn't stack - add_vertices(star_vertices, - it+1, - adj_graph, - d_map, - f_map, - curr_simplex, - curr_d+1, link_dimension); + add_vertices_to_link_graph(star_vertices, + it+1, + adj_graph, + d_map, + f_map, + curr_simplex, + curr_d+1, link_dimension); } } /* @@ -886,9 +891,9 @@ private: } } - void add_edges(Adj_graph& adj_graph, - Graph_map& d_map, - Graph_map& f_map) + void add_edges_to_link_graph(Adj_graph& adj_graph, + Graph_map& d_map, + Graph_map& f_map) { Simplex_handle sh; // Add edges -- cgit v1.2.3 From 81d222a2222bb7a4e6304ed1ce708598a8e29dc6 Mon Sep 17 00:00:00 2001 From: skachano Date: Fri, 12 Jun 2015 09:44:31 +0000 Subject: Added grid witnesses for flat torus git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@610 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 34d0bfe869ee04bd0dfa832e0e36b245f33b062f --- src/Witness_complex/example/CMakeLists.txt | 3 + .../example/relaxed_witness_complex_sphere.cpp | 460 +++++++++++++++++++++ .../example/witness_complex_flat_torus.cpp | 23 +- .../example/witness_complex_perturbations.cpp | 18 +- .../example/witness_complex_sphere.cpp | 3 +- 5 files changed, 493 insertions(+), 14 deletions(-) create mode 100644 src/Witness_complex/example/relaxed_witness_complex_sphere.cpp (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 09167cbe..77f95c79 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -86,6 +86,9 @@ if(CGAL_FOUND) add_executable ( witness_complex_sphere witness_complex_sphere.cpp ) target_link_libraries(witness_complex_sphere ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_test(witness_complex_sphere ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_sphere ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_executable ( relaxed_witness_complex_sphere relaxed_witness_complex_sphere.cpp ) + target_link_libraries(relaxed_witness_complex_sphere ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(relaxed_witness_complex_sphere ${CMAKE_CURRENT_BINARY_DIR}/relaxed_witness_complex_sphere ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Witness_complex/example/relaxed_witness_complex_sphere.cpp b/src/Witness_complex/example/relaxed_witness_complex_sphere.cpp new file mode 100644 index 00000000..53380124 --- /dev/null +++ b/src/Witness_complex/example/relaxed_witness_complex_sphere.cpp @@ -0,0 +1,460 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 +#include +#include + +#include +#include +//#include + +//#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Relaxed_witness_complex.h" +#include "gudhi/reader_utils.h" +//#include + +//#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +using namespace Gudhi; +//using namespace boost::filesystem; + +typedef CGAL::Epick_d K; +typedef K::FT FT; +typedef K::Point_d Point_d; +typedef CGAL::Search_traits< + FT, Point_d, + typename K::Cartesian_const_iterator_d, + typename K::Construct_cartesian_const_iterator_d> Traits_base; +typedef CGAL::Euclidean_distance Euclidean_distance; + +typedef std::vector< Vertex_handle > typeVectorVertex; + +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + +typedef CGAL::Search_traits_adapter< + std::ptrdiff_t, Point_d*, Traits_base> STraits; +//typedef K TreeTraits; +//typedef CGAL::Distance_adapter Euclidean_adapter; +//typedef CGAL::Kd_tree Kd_tree; +typedef CGAL::Orthogonal_incremental_neighbor_search> Neighbor_search; +typedef Neighbor_search::Tree Tree; +typedef Neighbor_search::Distance Distance; +typedef Neighbor_search::iterator KNS_iterator; +typedef Neighbor_search::iterator KNS_range; +typedef boost::container::flat_map Point_etiquette_map; +typedef CGAL::Kd_tree Tree2; + +typedef CGAL::Fuzzy_sphere Fuzzy_sphere; + +typedef std::vector Point_Vector; + +//typedef K::Equal_d Equal_d; +typedef CGAL::Random_points_in_cube_d Random_cube_iterator; +typedef CGAL::Random_points_in_ball_d Random_point_iterator; + +bool toric=false; + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , Point_Vector & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + Point_d p(point.begin(), point.end()); + if (point.size() != 1) + points.push_back(p); + } + in_file.close(); +} + + +void generate_points_sphere(Point_Vector& W, int nbP, int dim) +{ + CGAL::Random_points_on_sphere_d rp(dim,1); + for (int i = 0; i < nbP; i++) + W.push_back(*rp++); +} + + +void write_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto l: w) + ofs << l << " "; + ofs << "\n"; + } + ofs.close(); +} + +void write_rl( std::string file_name, std::vector< std::vector ::iterator> > & rl) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : rl) + { + for (auto l: w) + ofs << *l << " "; + ofs << "\n"; + } + ofs.close(); +} + +std::vector convert_to_torus(std::vector< Point_d>& points) +{ + std::vector< Point_d > points_torus; + for (auto p: points) + { + FT theta = M_PI*p[0]; + FT phi = M_PI*p[1]; + std::vector p_torus; + p_torus.push_back((1+0.2*cos(theta))*cos(phi)); + p_torus.push_back((1+0.2*cos(theta))*sin(phi)); + p_torus.push_back(0.2*sin(theta)); + points_torus.push_back(Point_d(p_torus)); + } + return points_torus; +} + + +void write_points_torus( std::string file_name, std::vector< Point_d > & points) +{ + std::ofstream ofs (file_name, std::ofstream::out); + std::vector points_torus = convert_to_torus(points); + for (auto w : points_torus) + { + for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + } + ofs.close(); +} + + +void write_points( std::string file_name, std::vector< Point_d > & points) +{ + if (toric) write_points_torus(file_name, points); + else + { + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : points) + { + for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + } + ofs.close(); + } +} + + +void write_edges_torus(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) +{ + std::ofstream ofs (file_name, std::ofstream::out); + Point_Vector l_torus = convert_to_torus(landmarks); + for (auto u: witness_complex.complex_vertex_range()) + for (auto v: witness_complex.complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) + { + for (auto it = l_torus[u].cartesian_begin(); it != l_torus[u].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + for (auto it = l_torus[v].cartesian_begin(); it != l_torus[v].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n\n\n"; + } + } + ofs.close(); +} + +void write_edges(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) +{ + std::ofstream ofs (file_name, std::ofstream::out); + if (toric) write_edges_torus(file_name, witness_complex, landmarks); + else + { + for (auto u: witness_complex.complex_vertex_range()) + for (auto v: witness_complex.complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) + { + for (auto it = landmarks[u].cartesian_begin(); it != landmarks[u].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + for (auto it = landmarks[v].cartesian_begin(); it != landmarks[v].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n\n\n"; + } + } + ofs.close(); + } +} + + +/** Function that chooses landmarks from W and place it in the kd-tree L. + * Note: nbL hould be removed if the code moves to Witness_complex + */ +void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + std::cout << "Enter landmark choice to kd tree\n"; + //std::vector landmarks; + int chosen_landmark; + //std::pair res = std::make_pair(L_i.begin(),false); + Point_d* p; + CGAL::Random rand; + for (int i = 0; i < nbL; i++) + { + // while (!res.second) + // { + do chosen_landmark = rand.get_int(0,nbP); + while (std::find(landmarks_ind.begin(), landmarks_ind.end(), chosen_landmark) != landmarks_ind.end()); + //rand++; + //std::cout << "Chose " << chosen_landmark << std::endl; + p = &W[chosen_landmark]; + //L_i.emplace(chosen_landmark,i); + // } + landmarks.push_back(*p); + landmarks_ind.push_back(chosen_landmark); + //std::cout << "Added landmark " << chosen_landmark << std::endl; + } + } + + +void landmarks_to_witness_complex(Point_Vector &W, Point_Vector& landmarks, std::vector& landmarks_ind, FT alpha) +{ + //********************Preface: origin point + unsigned D = W[0].size(); + std::vector orig_vector; + for (unsigned i = 0; i < D; i++) + orig_vector.push_back(0); + Point_d origin(orig_vector); + //Distance dist; + //dist.transformed_distance(0,1); + //******************** Constructing a WL matrix + int nbP = W.size(); + int nbL = landmarks.size(); + STraits traits(&(landmarks[0])); + Euclidean_distance ed; + std::vector< std::vector > WL(nbP); + std::vector< std::vector< typename std::vector::iterator > > ope_limits(nbP); + Tree L(boost::counting_iterator(0), + boost::counting_iterator(nbL), + typename Tree::Splitter(), + traits); + + std::cout << "Enter (D+1) nearest landmarks\n"; + //std::cout << "Size of the tree is " << L.size() << std::endl; + for (int i = 0; i < nbP; i++) + { + //std::cout << "Entered witness number " << i << std::endl; + Point_d& w = W[i]; + std::queue< typename std::vector::iterator > ope_queue; // queue of points at (1+epsilon) distance to current landmark + Neighbor_search search(L, w, FT(0), true, CGAL::Distance_adapter(&(landmarks[0]))); + Neighbor_search::iterator search_it = search.begin(); + + //Incremental search and filling WL + while (WL[i].size() < D) + WL[i].push_back((search_it++)->first); + FT dtow = ed.transformed_distance(w, landmarks[WL[i][D-1]]); + while (search_it->second < dtow + alpha) + WL[i].push_back((search_it++)->first); + + //Filling the (1+epsilon)-limits table + for (std::vector::iterator wl_it = WL[i].begin(); wl_it != WL[i].end(); ++wl_it) + { + ope_queue.push(wl_it); + FT d_to_curr_l = ed.transformed_distance(w, landmarks[*wl_it]); + //std::cout << "d_to_curr_l=" << d_to_curr_l << std::endl; + //std::cout << "d_to_front+alpha=" << d_to_curr_l << std::endl; + while (d_to_curr_l > alpha + ed.transformed_distance(w, landmarks[*(ope_queue.front())])) + { + ope_limits[i].push_back(wl_it); + ope_queue.pop(); + } + } + while (ope_queue.size() > 0) + { + ope_limits[i].push_back(WL[i].end()); + ope_queue.pop(); + } + //std::cout << "Safely constructed a point\n"; + ////Search D+1 nearest neighbours from the tree of landmarks L + /* + if (w[0]>0.95) + std::cout << i << std::endl; + */ + //K_neighbor_search search(L, w, D, FT(0), true, + // CGAL::Distance_adapter(&(landmarks[0])) ); + //std::cout << "Safely found nearest landmarks\n"; + /* + for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) + { + //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; + //Point_etiquette_map::iterator itm = L_i.find(it->first); + //assert(itm != L_i.end()); + //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; + WL[i].push_back(it->first); + //std::cout << "ITFIRST " << it->first << std::endl; + //std::cout << i << " " << it->first << ": " << it->second << std::endl; + } + */ + } + //std::cout << "\n"; + + //std::string out_file = "wl_result"; + write_wl("wl_result",WL); + write_rl("rl_result",ope_limits); + + //******************** Constructng a witness complex + std::cout << "Entered witness complex construction\n"; + Witness_complex<> witnessComplex; + witnessComplex.setNbL(nbL); + witnessComplex.relaxed_witness_complex(WL, ope_limits); + char buffer[100]; + int i = sprintf(buffer,"stree_result.txt"); + + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } + write_edges("landmarks/edges", witnessComplex, landmarks); + std::cout << Distance().transformed_distance(Point_d(std::vector({0.1,0.1})), Point_d(std::vector({1.9,1.9}))) << std::endl; +} + + +int main (int argc, char * const argv[]) +{ + + if (argc != 5) + { + std::cerr << "Usage: " << argv[0] + << " nbP nbL dim alpha\n"; + return 0; + } + /* + boost::filesystem::path p; + for (; argc > 2; --argc, ++argv) + p /= argv[1]; + */ + + int nbP = atoi(argv[1]); + int nbL = atoi(argv[2]); + int dim = atoi(argv[3]); + double alpha = atof(argv[4]); + //clock_t start, end; + //Construct the Simplex Tree + Witness_complex<> witnessComplex; + + std::cout << "Let the carnage begin!\n"; + Point_Vector point_vector; + //read_points_cust(file_name, point_vector); + generate_points_sphere(point_vector, nbP, dim); + /* + for (auto &p: point_vector) + { + assert(std::count(point_vector.begin(),point_vector.end(),p) == 1); + } + */ + //std::cout << "Successfully read the points\n"; + //witnessComplex.setNbL(nbL); + Point_Vector L; + std::vector chosen_landmarks; + landmark_choice(point_vector, nbP, nbL, L, chosen_landmarks); + //start = clock(); + + write_points("landmarks/initial_pointset",point_vector); + write_points("landmarks/initial_landmarks",L); + + landmarks_to_witness_complex(point_vector, L, chosen_landmarks, alpha); + //end = clock(); + + /* + std::cout << "Landmark choice took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + start = clock(); + witnessComplex.witness_complex(WL); + // + end = clock(); + std::cout << "Howdy world! The process took " + << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; + */ + + /* + out_file = "output/"+file_name+"_"+argv[2]+".stree"; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + + out_file = "output/"+file_name+"_"+argv[2]+".badlinks"; + std::ofstream ofs2(out_file, std::ofstream::out); + witnessComplex.write_bad_links(ofs2); + ofs2.close(); + */ +} diff --git a/src/Witness_complex/example/witness_complex_flat_torus.cpp b/src/Witness_complex/example/witness_complex_flat_torus.cpp index 14d6426d..42bf5e7e 100644 --- a/src/Witness_complex/example/witness_complex_flat_torus.cpp +++ b/src/Witness_complex/example/witness_complex_flat_torus.cpp @@ -323,7 +323,20 @@ read_points_cust ( std::string file_name , Point_Vector & points) void generate_points_grid(Point_Vector& W, int width, int D) { - + int nb_points = 1; + for (int i = 0; i < D; ++i) + nb_points *= width; + for (int i = 0; i < nb_points; ++i) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(0.01*(cell_i%width)); + cell_i /= width; + } + W.push_back(point); + } } void generate_points_random_box(Point_Vector& W, int nbP, int dim) @@ -490,8 +503,8 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, { // while (!res.second) // { - while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0) - chosen_landmark = rand.get_int(0,nbP); + do chosen_landmark = rand.get_int(0,nbP); + while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); //rand++; //std::cout << "Chose " << chosen_landmark << std::endl; p = &W[chosen_landmark]; @@ -717,7 +730,9 @@ int main (int argc, char * const argv[]) std::cout << "Let the carnage begin!\n"; Point_Vector point_vector; //read_points_cust(file_name, point_vector); - generate_points_random_box(point_vector, nbP, dim); + //generate_points_random_box(point_vector, nbP, dim); + generate_points_grid(point_vector, (int)pow(nbP, 1.0/dim), dim); + nbP = (int)(pow((int)pow(nbP, 1.0/dim), dim)); /* for (auto &p: point_vector) { diff --git a/src/Witness_complex/example/witness_complex_perturbations.cpp b/src/Witness_complex/example/witness_complex_perturbations.cpp index ec7a5abe..88a7510a 100644 --- a/src/Witness_complex/example/witness_complex_perturbations.cpp +++ b/src/Witness_complex/example/witness_complex_perturbations.cpp @@ -194,7 +194,7 @@ void write_edges_gnuplot(std::string file_name, Witness_complex<>& witness_compl /** Function that chooses landmarks from W and place it in the kd-tree L. * Note: nbL hould be removed if the code moves to Witness_complex */ - +/* void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) { std::cout << "Enter landmark choice to kd tree\n"; @@ -216,12 +216,13 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, //std::cout << "Added landmark " << chosen_landmark << std::endl; } } -/* +*/ + void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) { std::cout << "Enter landmark choice to kd tree\n"; //std::vector landmarks; - int chosen_landmark; + int chosen_landmark = 0; //std::pair res = std::make_pair(L_i.begin(),false); Point_d* p; CGAL::Random rand; @@ -229,9 +230,9 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, { // while (!res.second) // { - while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0) - chosen_landmark = rand.get_int(0,nbP); - //rand++; + do chosen_landmark = rand.uniform_int(0,nbP); + while (std::find(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark) != landmarks_ind.end()); + //rand++; //std::cout << "Chose " << chosen_landmark << std::endl; p = &W[chosen_landmark]; //L_i.emplace(chosen_landmark,i); @@ -241,7 +242,7 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, //std::cout << "Added landmark " << chosen_landmark << std::endl; } } -*/ + int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector& landmarks_ind) { @@ -417,7 +418,8 @@ int main (int argc, char * const argv[]) } //write_points("landmarks/initial_pointset",point_vector); write_points("landmarks/initial_landmarks",L); - for (int i = 0; bl != 0; i++) + //for (int i = 0; bl != 0; i++) + for (int i = 0; i < 1; i++) { std::cout << "========== Start iteration " << i << " ========\n"; bl = landmark_perturbation(point_vector, L, chosen_landmarks); diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index f6345411..f2bb9819 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -489,8 +489,7 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, { // while (!res.second) // { - do - chosen_landmark = rand.get_int(0,nbP); + do chosen_landmark = rand.get_int(0,nbP); while (std::find(landmarks_ind.begin(), landmarks_ind.end(), chosen_landmark) != landmarks_ind.end()); //rand++; //std::cout << "Chose " << chosen_landmark << std::endl; -- cgit v1.2.3 From 36a355eb8756a8eb6bdc3e9cad4283d89da4f7f6 Mon Sep 17 00:00:00 2001 From: skachano Date: Sat, 13 Jun 2015 12:29:09 +0000 Subject: Tweaked a bit Witness_complex.h + simplex count git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@612 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 69c0f87a15a44e438750acfd158495713789feee --- .../include/gudhi/Witness_complex.h | 170 +++++++++++++++++++-- 1 file changed, 156 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 8b87ae89..04fcc98f 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -165,6 +165,7 @@ namespace Gudhi { // PRINT2 //print_sc(root()); std::cout << std::endl; int u,v; // two extremities of an edge + int count = 0; if (nbL > 1) // if the supposed dimension of the complex is >0 { for (int i=0; i != nbW; ++i) @@ -174,9 +175,13 @@ namespace Gudhi { v = knn[i][1]; vv = {u,v}; returnValue = this->insert_simplex(vv,Filtration_value(0.0)); + if (returnValue.second) + count++; //print_sc(root()); std::cout << std::endl; //std::cout << "Added edges" << std::endl; } + std::cout << "The number of edges = " << count << std::endl; + count = 0; //print_sc(root()); for (int i=0; i != nbW; ++i) { @@ -206,6 +211,7 @@ namespace Gudhi { { count_good.push_back(0); count_bad.push_back(0); + count++; //std::cout << "Started the step k=" << k << std::endl; typename ActiveWitnessList::iterator it = active_w.begin(); while (it != active_w.end()) @@ -220,12 +226,15 @@ namespace Gudhi { for (int i = 0; i != k+1; ++i) simplex_vector.push_back(knn[*it][i]); returnValue = insert_simplex(simplex_vector,0.0); + if (returnValue.second) + count++; it++; } else active_w.erase(it++); //First increase the iterator and then erase the previous element } std::cout << "k=" << k << ", active witnesses: " << active_w.size() << std::endl; + std::cout << "** k=" << k << ", num_simplices: " < Reference; typedef boost::graph_traits::vertex_descriptor Vertex_t; typedef boost::graph_traits::edge_descriptor Edge_t; + typedef boost::graph_traits::adjacency_iterator Adj_it; + typedef std::pair Out_edge_it; typedef boost::container::flat_map Graph_map; - + typedef boost::container::flat_map Inv_graph_map; + /* \brief Verifies if the simplices formed by vertices given by link_vertices * form a pseudomanifold. * The idea is to make a bipartite graph, where vertices are the d- and (d-1)-dimensional @@ -800,15 +812,75 @@ private: //std::cout << "Degree of " << f_map_it.first->first << " is " << boost::out_degree(f_map_it.second, adj_graph) << "\n"; if (boost::out_degree(f_map_it.second, adj_graph) != 2) { - /* - if (boost::out_degree(f_map_it.second, adj_graph) == 3) + /* + if (boost::out_degree(f_map_it.second, adj_graph) >= 3) + { + std::cout << "This simplex has 3+ cofaces: "; + for(auto v : simplex_vertex_range(f_map_it.first)) + std::cout << v << " "; + std::cout << std::endl; + Adj_it ai, ai_end; + for (std::tie(ai, ai_end) = boost::adjacent_vertices(f_map_it.second, adj_graph); ai != ai_end; ++ai) + { + + } + } + */ + count_bad[dimension]++; + return false; + } + } + // At this point I know that all (d-1)-simplices are adjacent to exactly 2 d-simplices + // What is left is to check the connexity + //std::vector components(boost::num_vertices(adj_graph)); + return true; //Forget the connexity + //return (boost::connected_components(adj_graph, &components[0]) == 1); + } + + public: +bool complex_is_pseudomanifold(int dimension) + { + Adj_graph adj_graph; + Graph_map d_map, f_map; // d_map = map for d-dimensional simplices + // f_map = map for its facets + Inv_graph_map inv_d_map; + typeVectorVertex init_vector = {}; + std::vector star_vertices; + for (int v: complex_vertex_range()) + star_vertices.push_back(v); + add_max_simplices_to_graph(star_vertices, + star_vertices.begin(), + adj_graph, + d_map, + f_map, + inv_d_map, + init_vector, + 0, dimension); + std::cout << "DMAP_SIZE: " << d_map.size() << "\n"; + std::cout << "FMAP_SIZE: " << f_map.size() << "\n"; + add_edges_to_link_graph(adj_graph, d_map, f_map); + for (auto f_map_it : f_map) + { + //std::cout << "Degree of " << f_map_it.first->first << " is " << boost::out_degree(f_map_it.second, adj_graph) << "\n"; + if (boost::out_degree(f_map_it.second, adj_graph) != 2) + { + if (boost::out_degree(f_map_it.second, adj_graph) >= 3) { - std::cout << "This simplex has 3 cofaces: "; + std::cout << "This simplex has 3+ cofaces: "; for(auto v : simplex_vertex_range(f_map_it.first)) std::cout << v << " "; std::cout << std::endl; - - }*/ + Adj_it ai, ai_end; + for (std::tie(ai, ai_end) = boost::adjacent_vertices(f_map_it.second, adj_graph); ai != ai_end; ++ai) + { + auto it = inv_d_map.find(*ai); + assert (it != inv_d_map.end()); + Simplex_handle sh = it->second; + for(auto v : simplex_vertex_range(sh)) + std::cout << v << " "; + std::cout << std::endl; + } + } count_bad[dimension]++; return false; } @@ -820,6 +892,7 @@ private: //return (boost::connected_components(adj_graph, &components[0]) == 1); } + private: void add_vertices_to_link_graph(typeVectorVertex& star_vertices, typename typeVectorVertex::iterator curr_v, Adj_graph& adj_graph, @@ -858,21 +931,18 @@ private: assert(sh != null_simplex()); //ASSERT! vert = boost::add_vertex(adj_graph); d_map.emplace(sh,vert); - for (Simplex_handle sh_b: boundary_simplex_range(sh)) - { - vert = boost::add_vertex(adj_graph); - f_map.emplace(sh_b,vert); - } } else { - /* + if (curr_d == link_dimension-1) { + sh = find(curr_simplex_copy); //a simplex of the link + assert(sh != null_simplex()); vert = boost::add_vertex(adj_graph); - resPair = f_map.emplace(sh,vert); + f_map.emplace(sh,vert); } - */ + //delete (&curr_simplex_copy); //Just so it doesn't stack add_vertices_to_link_graph(star_vertices, it+1, @@ -917,6 +987,78 @@ private: } } } + + void add_max_simplices_to_graph(typeVectorVertex& star_vertices, + typename typeVectorVertex::iterator curr_v, + Adj_graph& adj_graph, + Graph_map& d_map, + Graph_map& f_map, + Inv_graph_map& inv_d_map, + typeVectorVertex& curr_simplex, + int curr_d, + int link_dimension) + { + Simplex_handle sh; + Vertex_t vert; + typename typeVectorVertex::iterator it; + //std::pair resPair; + //typename Graph_map::iterator resPair; + //Add vertices + //std::cout << "Entered add vertices\n"; + for (it = curr_v; it != star_vertices.end(); ++it) + { + curr_simplex.push_back(*it); //push next vertex in question + //curr_simplex.push_back(star_vertices[0]); //push the center of the star + /* + std::cout << "Searching for "; + print_vector(curr_simplex); + std::cout << " curr_dim " << curr_d << " d " << dimension << ""; + */ + typeVectorVertex curr_simplex_copy(curr_simplex); + sh = find(curr_simplex_copy); //a simplex of the star + //curr_simplex.pop_back(); //pop the center of the star + curr_simplex_copy = typeVectorVertex(curr_simplex); + if (sh != null_simplex()) + { + //std::cout << " added\n"; + if (curr_d == link_dimension) + { + sh = find(curr_simplex_copy); //a simplex of the link + assert(sh != null_simplex()); //ASSERT! + vert = boost::add_vertex(adj_graph); + d_map.emplace(sh,vert); + inv_d_map.emplace(vert,sh); + } + else + { + + if (curr_d == link_dimension-1) + { + sh = find(curr_simplex_copy); //a simplex of the link + assert(sh != null_simplex()); + vert = boost::add_vertex(adj_graph); + f_map.emplace(sh,vert); + } + + //delete (&curr_simplex_copy); //Just so it doesn't stack + add_max_simplices_to_graph(star_vertices, + it+1, + adj_graph, + d_map, + f_map, + inv_d_map, + curr_simplex, + curr_d+1, link_dimension); + } + } + /* + else + std::cout << "\n"; + */ + curr_simplex.pop_back(); //pop the vertex in question + } + } + }; //class Witness_complex -- cgit v1.2.3 From c88e3b93de22be92cc7027f4c14ea4294f8c366f Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 16 Jun 2015 09:36:00 +0000 Subject: Fixed the changing WL matrix bug in witness complex. Added is_witness_complex test git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@615 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 60917e75766b53d08240b510c0508e7d781b56d6 --- .../example/relaxed_witness_complex_sphere.cpp | 1 + .../example/witness_complex_sphere.cpp | 10 +- .../include/gudhi/Relaxed_witness_complex.h | 886 +++++++++++++++++++++ .../include/gudhi/Witness_complex.h | 93 ++- 4 files changed, 962 insertions(+), 28 deletions(-) create mode 100644 src/Witness_complex/include/gudhi/Relaxed_witness_complex.h (limited to 'src') diff --git a/src/Witness_complex/example/relaxed_witness_complex_sphere.cpp b/src/Witness_complex/example/relaxed_witness_complex_sphere.cpp index 53380124..067321ce 100644 --- a/src/Witness_complex/example/relaxed_witness_complex_sphere.cpp +++ b/src/Witness_complex/example/relaxed_witness_complex_sphere.cpp @@ -36,6 +36,7 @@ //#include "gudhi/graph_simplicial_complex.h" #include "gudhi/Relaxed_witness_complex.h" #include "gudhi/reader_utils.h" +#include "gudhi/Collapse/Collapse.h" //#include //#include diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index f2bb9819..d08c763f 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -578,6 +578,10 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< Witness_complex<> witnessComplex; witnessComplex.setNbL(nbL); witnessComplex.witness_complex(WL); + if (witnessComplex.is_witness_complex(WL)) + std::cout << "!!YES. IT IS A WITNESS COMPLEX!!\n"; + else + std::cout << "??NO. IT IS NOT A WITNESS COMPLEX??\n"; //******************** Making a set of bad link landmarks std::cout << "Entered bad links\n"; std::set< int > perturbL; @@ -614,7 +618,7 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< for (auto u: perturbL) { - Random_point_iterator rp(D,sqrt(lambda)/8); + Random_point_iterator rp(D,sqrt(lambda)/8*nbL/count_badlinks); //std::cout << landmarks[u] << std::endl; std::vector point; @@ -721,8 +725,8 @@ int main (int argc, char * const argv[]) write_points("landmarks/initial_pointset",point_vector); write_points("landmarks/initial_landmarks",L); - for (int i = 0; bl > 0; i++) - //for (int i = 0; i < 1; i++) + //for (int i = 0; bl > 0; i++) + for (int i = 0; i < 1; i++) { std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; bl=landmark_perturbation(point_vector, L, chosen_landmarks); diff --git a/src/Witness_complex/include/gudhi/Relaxed_witness_complex.h b/src/Witness_complex/include/gudhi/Relaxed_witness_complex.h new file mode 100644 index 00000000..c869628f --- /dev/null +++ b/src/Witness_complex/include/gudhi/Relaxed_witness_complex.h @@ -0,0 +1,886 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 . + */ + +#ifndef GUDHI_RELAXED_WITNESS_COMPLEX_H_ +#define GUDHI_RELAXED_WITNESS_COMPLEX_H_ + +#include +#include +#include +#include +#include "gudhi/reader_utils.h" +#include "gudhi/distance_functions.h" +#include "gudhi/Simplex_tree.h" +#include +#include +#include +#include +#include +#include +#include +#include + +// Needed for nearest neighbours +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// Needed for the adjacency graph in bad link search +#include +#include +#include + +namespace Gudhi { + + + /** \addtogroup simplex_tree + * Witness complex is a simplicial complex defined on two sets of points in \f$\mathbf{R}^D\f$: + * \f$W\f$ set of witnesses and \f$L \subseteq W\f$ set of landmarks. The simplices are based on points in \f$L\f$ + * and a simplex belongs to the witness complex if and only if it is witnessed (there exists a point \f$w \in W\f$ such that + * w is closer to the vertices of this simplex than others) and all of its faces are witnessed as well. + */ + template + class Witness_complex: public Simplex_tree<> { + + private: + + struct Active_witness { + int witness_id; + int landmark_id; + Simplex_handle simplex_handle; + + Active_witness(int witness_id_, int landmark_id_, Simplex_handle simplex_handle_) + : witness_id(witness_id_), + landmark_id(landmark_id_), + simplex_handle(simplex_handle_) + {} + }; + + + + + public: + + + /** \brief Type for the vertex handle. + * + * Must be a signed integer type. It admits a total order <. */ + typedef VertexHandle Vertex_handle; + + /* Type of node in the simplex tree. */ + typedef Simplex_tree_node_explicit_storage Node; + /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ + typedef typename boost::container::flat_map Dictionary; + typedef typename Dictionary::iterator Simplex_handle; + + typedef std::vector< double > Point_t; + typedef std::vector< Point_t > Point_Vector; + + typedef std::vector< Vertex_handle > typeVectorVertex; + typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; + typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + + typedef int Witness_id; + typedef int Landmark_id; + typedef std::list< Vertex_handle > ActiveWitnessList; + + private: + /** Number of landmarks + */ + int nbL; + /** Desired density + */ + double density; + + public: + + /** \brief Set number of landmarks to nbL_ + */ + void setNbL(int nbL_) + { + nbL = nbL_; + } + + /** \brief Set density to density_ + */ + void setDensity(double density_) + { + density = density_; + } + + /** + * /brief Iterative construction of the relaxed witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks} and (1+epsilon)-limit table {witnesses}*{landmarks} consisting of iterators of k nearest neighbor matrix. + * The line lengths can differ, however both matrices have the same corresponding line lengths. + */ + + template< typename KNearestNeighbours, typename OPELimits > + void relaxed_witness_complex(KNearestNeighbours & knn, OPELimits & rl) + //void witness_complex(std::vector< std::vector< Vertex_handle > > & knn) + { + std::cout << "**Start the procedure witness_complex" << std::endl; + //Construction of the active witness list + int nbW = knn.size(); + //int nbL = knn.at(0).size(); + typeVectorVertex vv; + //typeSimplex simplex; + //typePairSimplexBool returnValue; + //int counter = 0; + /* The list of still useful witnesses + * it will diminuish in the course of iterations + */ + ActiveWitnessList active_w;// = new ActiveWitnessList(); + for (int i=0; i != nbL; ++i) { + // initial fill of 0-dimensional simplices + // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore + //counter++; + vv = {i}; + insert_simplex(vv, Filtration_value(0.0)); + /* TODO Error if not inserted : normally no need here though*/ + } + int k=1; /* current dimension in iterative construction */ + //std::cout << "Successfully added landmarks" << std::endl; + // PRINT2 + //print_sc(root()); std::cout << std::endl; + for (int i=0; i != nbW; ++i) + active_w.push_back(i); + /* + int u,v; // two extremities of an edge + if (nbL > 1) // if the supposed dimension of the complex is >0 + { + for (int i=0; i != nbW; ++i) + { + // initial fill of active witnesses list + u = knn[i][0]; + v = knn[i][1]; + vv = {u,v}; + this->insert_simplex(vv,Filtration_value(0.0)); + //print_sc(root()); std::cout << std::endl; + //std::cout << "Added edges" << std::endl; + } + //print_sc(root()); + + } + */ + std::cout << "k=0, active witnesses: " << active_w.size() << std::endl; + //std::cout << "Successfully added edges" << std::endl; + //count_good = {0,0}; + //count_bad = {0,0}; + while (!active_w.empty() && k < nbL ) + { + //count_good.push_back(0); + //count_bad.push_back(0); + //std::cout << "Started the step k=" << k << std::endl; + typename ActiveWitnessList::iterator aw_it = active_w.begin(); + while (aw_it != active_w.end()) + { + std::vector simplex; + bool ok = add_all_faces_of_dimension(k, knn[*aw_it].begin(), rl[*aw_it].begin(), simplex, knn[*aw_it].end(), knn[*aw_it].end()); + if (!ok) + active_w.erase(aw_it++); //First increase the iterator and then erase the previous element + else + aw_it++; + } + std::cout << "k=" << k << ", active witnesses: " << active_w.size() << std::endl; + k++; + } + //print_sc(root()); std::cout << std::endl; + } + + /* \brief Adds recursively all the faces of a certain dimension dim witnessed by the same witness + * Iterator is needed to know until how far we can take landmarks to form simplexes + * simplex is the prefix of the simplexes to insert + * The output value indicates if the witness rests active or not + */ + bool add_all_faces_of_dimension(int dim, std::vector::iterator curr_l, typename std::vector< std::vector::iterator >::iterator curr_until, std::vector& simplex, std::vector::iterator until, std::vector::iterator end) + { + /* + std::ofstream ofs ("stree_result.txt", std::ofstream::out); + st_to_file(ofs); + ofs.close(); + */ + //print_sc(root()); + bool will_be_active = false; + if (dim > 0) + for (std::vector::iterator it = curr_l; it != until && it != end; ++it, ++curr_until) + { + simplex.push_back(*it); + if (find(simplex) != null_simplex()) + will_be_active = will_be_active || add_all_faces_of_dimension(dim-1, it+1, curr_until+1, simplex, until, end); + simplex.pop_back(); + if (until == end) + until = *curr_until; + } + else if (dim == 0) + for (std::vector::iterator it = curr_l; it != until && it != end; ++it, ++curr_until) + { + simplex.push_back(*it); + if (all_faces_in(simplex)) + { + will_be_active = true; + insert_simplex(simplex, 0.0); + } + simplex.pop_back(); + if (until == end) + until = *curr_until; + } + return will_be_active; + } + + /** \brief Construction of witness complex from points given explicitly + * nbL must be set to the right value of landmarks for strategies + * FURTHEST_POINT_STRATEGY and RANDOM_POINT_STRATEGY and + * density must be set to the right value for DENSITY_STRATEGY + */ + // void witness_complex_from_points(Point_Vector point_vector) + // { + // std::vector > WL; + // landmark_choice_by_random_points(point_vector, point_vector.size(), WL); + // witness_complex(WL); + // } + +private: + + /** \brief Print functions + */ + void print_sc(Siblings * sibl) + { + if (sibl == NULL) + std::cout << "&"; + else + print_children(sibl->members_); + } + + void print_children(Dictionary map) + { + std::cout << "("; + if (!map.empty()) + { + std::cout << map.begin()->first; + if (has_children(map.begin())) + print_sc(map.begin()->second.children()); + typename Dictionary::iterator it; + for (it = map.begin()+1; it != map.end(); ++it) + { + std::cout << "," << it->first; + if (has_children(it)) + print_sc(it->second.children()); + } + } + std::cout << ")"; + } + + public: + /** \brief Print functions + */ + + void st_to_file(std::ofstream& out_file) + { + sc_to_file(out_file, root()); + } + + private: + void sc_to_file(std::ofstream& out_file, Siblings * sibl) + { + assert(sibl); + children_to_file(out_file, sibl->members_); + } + + void children_to_file(std::ofstream& out_file, Dictionary& map) + { + out_file << "(" << std::flush; + if (!map.empty()) + { + out_file << map.begin()->first << std::flush; + if (has_children(map.begin())) + sc_to_file(out_file, map.begin()->second.children()); + typename Dictionary::iterator it; + for (it = map.begin()+1; it != map.end(); ++it) + { + out_file << "," << it->first << std::flush; + if (has_children(it)) + sc_to_file(out_file, it->second.children()); + } + } + out_file << ")" << std::flush; + } + + + /** \brief Check if the facets of the k-dimensional simplex witnessed + * by witness witness_id are already in the complex. + * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id + */ + bool all_faces_in(std::vector& simplex) + { + //std::cout << "All face in with the landmark " << inserted_vertex << std::endl; + std::vector< VertexHandle > facet; + //VertexHandle curr_vh = curr_sh->first; + // CHECK ALL THE FACETS + for (std::vector::iterator not_it = simplex.begin(); not_it != simplex.end(); ++not_it) + { + facet.clear(); + //facet = {}; + for (std::vector::iterator it = simplex.begin(); it != simplex.end(); ++it) + if (it != not_it) + facet.push_back(*it); + if (find(facet) == null_simplex()) + return false; + } //endfor + return true; + } + + template + void print_vector(std::vector v) + { + std::cout << "["; + if (!v.empty()) + { + std::cout << *(v.begin()); + for (auto it = v.begin()+1; it != v.end(); ++it) + { + std::cout << ","; + std::cout << *it; + } + } + std::cout << "]"; + } + + template + void print_vvector(std::vector< std::vector > vv) + { + std::cout << "["; + if (!vv.empty()) + { + print_vector(*(vv.begin())); + for (auto it = vv.begin()+1; it != vv.end(); ++it) + { + std::cout << ","; + print_vector(*it); + } + } + std::cout << "]\n"; + } + + public: +/** + * \brief Landmark choice strategy by iteratively adding the landmark the furthest from the + * current landmark set + * \arg W is the vector of points which will be the witnesses + * \arg nbP is the number of witnesses + * \arg nbL is the number of landmarks + * \arg WL is the matrix of the nearest landmarks with respect to witnesses (output) + */ + + template + void landmark_choice_by_furthest_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) + { + //std::cout << "Enter landmark_choice_by_furthest_points "<< std::endl; + //std::cout << "W="; print_vvector(W); + //double density = 5.; + Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks + typeVectorVertex chosen_landmarks; // landmark list + + WL = KNearestNeighbours(nbP,std::vector()); + int current_number_of_landmarks=0; // counter for landmarks + double curr_max_dist = 0; // used for defining the furhest point from L + double curr_dist; // used to stock the distance from the current point to L + double infty = std::numeric_limits::infinity(); // infinity (see next entry) + std::vector< double > dist_to_L(nbP,infty); // vector of current distances to L from points + // double mindist = infty; + int curr_max_w=0; // the point currently furthest from L + int j; + int temp_swap_int; + double temp_swap_double; + + //CHOICE OF THE FIRST LANDMARK + std::cout << "Enter the first landmark stage\n"; + srand(354698); + int rand_int = rand()% nbP; + curr_max_w = rand_int; //For testing purposes a pseudo-random number is used here + + for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + { + //curr_max_w at this point is the next landmark + chosen_landmarks.push_back(curr_max_w); + //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; + //std::cout << "WL="; print_vvector(WL); + //std::cout << "WLD="; print_vvector(wit_land_dist); + //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; + for (auto v: WL) + v.push_back(current_number_of_landmarks); + for (int i = 0; i < nbP; ++i) + { + // iteration on points in W. update of distance vectors + + //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; + //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; + curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); + //std::cout << "The problem is not in distance function\n"; + wit_land_dist[i].push_back(curr_dist); + WL[i].push_back(current_number_of_landmarks); + //std::cout << "Push't back\n"; + if (curr_dist < dist_to_L[i]) + dist_to_L[i] = curr_dist; + j = current_number_of_landmarks; + //std::cout << "First half complete\n"; + while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) + { + // sort the closest landmark vector for every witness + temp_swap_int = WL[i][j]; + WL[i][j] = WL[i][j-1]; + WL[i][j-1] = temp_swap_int; + temp_swap_double = wit_land_dist[i][j]; + wit_land_dist[i][j] = wit_land_dist[i][j-1]; + wit_land_dist[i][j-1] = temp_swap_double; + --j; + } + //std::cout << "result WL="; print_vvector(WL); + //std::cout << "result WLD="; print_vvector(wit_land_dist); + //std::cout << "result distL="; print_vector(dist_to_L); std::cout << std::endl; + //std::cout << "End loop\n"; + } + //std::cout << "Distance to landmarks="; print_vector(dist_to_L); std::cout << std::endl; + curr_max_dist = 0; + for (int i = 0; i < nbP; ++i) { + if (dist_to_L[i] > curr_max_dist) + { + curr_max_dist = dist_to_L[i]; + curr_max_w = i; + } + } + //std::cout << "Chose " << curr_max_w << " as new landmark\n"; + } + //std::cout << endl; + } + + /** \brief Landmark choice strategy by taking random vertices for landmarks. + * + */ + + // template + // void landmark_choice_by_random_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) + // { + // std::cout << "Enter landmark_choice_by_random_points "<< std::endl; + // //std::cout << "W="; print_vvector(W); + // std::unordered_set< int > chosen_landmarks; // landmark set + + // Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks + + // WL = KNearestNeighbours(nbP,std::vector()); + // int current_number_of_landmarks=0; // counter for landmarks + + // srand(24660); + // int chosen_landmark = rand()%nbP; + // double curr_dist; + + // //int j; + // //int temp_swap_int; + // //double temp_swap_double; + + + // for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + // { + // while (chosen_landmarks.find(chosen_landmark) != chosen_landmarks.end()) + // { + // srand((int)clock()); + // chosen_landmark = rand()% nbP; + // //std::cout << chosen_landmark << "\n"; + // } + // chosen_landmarks.insert(chosen_landmark); + // //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; + // //std::cout << "WL="; print_vvector(WL); + // //std::cout << "WLD="; print_vvector(wit_land_dist); + // //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; + // for (auto v: WL) + // v.push_back(current_number_of_landmarks); + // for (int i = 0; i < nbP; ++i) + // { + // // iteration on points in W. update of distance vectors + + // //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; + // //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; + // curr_dist = euclidean_distance(W[i],W[chosen_landmark]); + // //std::cout << "The problem is not in distance function\n"; + // wit_land_dist[i].push_back(curr_dist); + // WL[i].push_back(current_number_of_landmarks); + // //std::cout << "Push't back\n"; + // //j = current_number_of_landmarks; + // //std::cout << "First half complete\n"; + // //std::cout << "result WL="; print_vvector(WL); + // //std::cout << "result WLD="; print_vvector(wit_land_dist); + // //std::cout << "End loop\n"; + // } + // } + // for (int i = 0; i < nbP; i++) + // { + // sort(WL[i].begin(), WL[i].end(), [&](int j1, int j2){return wit_land_dist[i][j1] < wit_land_dist[i][j2];}); + // } + // //std::cout << endl; + // } + + /** \brief Landmark choice strategy by taking random vertices for landmarks. + * + */ + + // template + void landmark_choice_by_random_points(Point_Vector &W, int nbP, std::set &L) + { + std::cout << "Enter landmark_choice_by_random_points "<< std::endl; + //std::cout << "W="; print_vvector(W); + //std::unordered_set< int > chosen_landmarks; // landmark set + + //Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks + + //WL = KNearestNeighbours(nbP,std::vector()); + int current_number_of_landmarks=0; // counter for landmarks + + srand(24660); + int chosen_landmark = rand()%nbP; + //double curr_dist; + //int j; + //int temp_swap_int; + //double temp_swap_double; + for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + { + while (L.find(chosen_landmark) != L.end()) + { + srand((int)clock()); + chosen_landmark = rand()% nbP; + //std::cout << chosen_landmark << "\n"; + } + L.insert(chosen_landmark); + //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; + //std::cout << "WL="; print_vvector(WL); + //std::cout << "WLD="; print_vvector(wit_land_dist); + //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; + // for (auto v: WL) + // v.push_back(current_number_of_landmarks); + // for (int i = 0; i < nbP; ++i) + // { + // // iteration on points in W. update of distance vectors + + // //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; + // //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; + // curr_dist = euclidean_distance(W[i],W[chosen_landmark]); + // //std::cout << "The problem is not in distance function\n"; + // wit_land_dist[i].push_back(curr_dist); + // WL[i].push_back(current_number_of_landmarks); + // //std::cout << "Push't back\n"; + // //j = current_number_of_landmarks; + // //std::cout << "First half complete\n"; + // //std::cout << "result WL="; print_vvector(WL); + // //std::cout << "result WLD="; print_vvector(wit_land_dist); + // //std::cout << "End loop\n"; + // } + } + // for (int i = 0; i < nbP; i++) + // { + // sort(WL[i].begin(), WL[i].end(), [&](int j1, int j2){return wit_land_dist[i][j1] < wit_land_dist[i][j2];}); + // } + //std::cout << endl; + } + + + /** \brief Construct the matrix |W|x(D+1) of D+1 closest landmarks + * where W is the set of witnesses and D is the ambient dimension + */ + template + void nearest_landmarks(Point_Vector &W, std::set &L, KNearestNeighbours &WL) + { + int D = W[0].size(); + int nbP = W.size(); + WL = KNearestNeighbours(nbP,std::vector()); + typedef std::pair dist_i; + typedef bool (*comp)(dist_i,dist_i); + for (int W_i = 0; W_i < nbP; W_i++) + { + //std::cout << "<<<<<<<<<<<<<<" << W_i <<"\n"; + std::priority_queue, comp> l_heap([&](dist_i j1, dist_i j2){return j1.first > j2.first;}); + std::set::iterator L_it; + int L_i; + for (L_it = L.begin(), L_i=0; L_it != L.end(); L_it++, L_i++) + { + dist_i dist = std::make_pair(euclidean_distance(W[W_i],W[*L_it]), L_i); + l_heap.push(dist); + } + for (int i = 0; i < D+1; i++) + { + dist_i dist = l_heap.top(); + WL[W_i].push_back(dist.second); + //WL[W_i].insert(WL[W_i].begin(),dist.second); + //std::cout << dist.first << " " << dist.second << std::endl; + l_heap.pop(); + } + } + } + + /** \brief Search and output links around vertices that are not pseudomanifolds + * + */ + void write_bad_links(std::ofstream& out_file) + { + out_file << "Bad links list\n"; + std::cout << "Entered write_bad_links\n"; + //typeVectorVertex testv = {9,15,17}; + //int count = 0; + for (auto v: complex_vertex_range()) + { + //std::cout << "Vertex " << v << ":\n"; + std::vector< Vertex_handle > link_vertices; + // Fill link_vertices + for (auto u: complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u != v && find(edge) != null_simplex()) + link_vertices.push_back(u); + } + /* + print_vector(link_vertices); + std::cout << "\n"; + */ + // Find the dimension + typeVectorVertex empty_simplex = {}; + int d = link_dim(link_vertices, link_vertices.begin(),-1, empty_simplex); + //std::cout << " dim " << d << "\n"; + //Siblings* curr_sibl = root(); + if (link_is_pseudomanifold(link_vertices,d)) + count_good[d]++; + //out_file << "Bad link at " << v << "\n"; + } + //out_file << "Number of bad links: " << count << "/" << root()->size(); + //std::cout << "Number of bad links: " << count << "/" << root()->size() << std::endl; + nc = nbL; + for (unsigned int i = 0; i != count_good.size(); i++) + { + out_file << "count_good[" << i << "] = " << count_good[i] << std::endl; + nc -= count_good[i]; + if (count_good[i] != 0) + std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; + } + for (unsigned int i = 0; i != count_bad.size(); i++) + { + out_file << "count_bad[" << i << "] = " << count_bad[i] << std::endl; + nc -= count_bad[i]; + if (count_bad[i] != 0) + std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; + } + std::cout << "not_connected = " << nc << std::endl; + } + + private: + + std::vector count_good; + std::vector count_bad; + int nc; + + int link_dim(std::vector< Vertex_handle >& link_vertices, + typename std::vector< Vertex_handle >::iterator curr_v, + int curr_d, + typeVectorVertex& curr_simplex) + { + //std::cout << "Entered link_dim for " << *(curr_v-1) << "\n"; + Simplex_handle sh; + int final_d = curr_d; + typename std::vector< Vertex_handle >::iterator it; + for (it = curr_v; it != link_vertices.end(); ++it) + { + curr_simplex.push_back(*it); + /* + std::cout << "Searching for "; + print_vector(curr_simplex); + std::cout << " curr_dim " << curr_d << " final_dim " << final_d; + */ + sh = find(curr_simplex); + if (sh != null_simplex()) + { + //std::cout << " -> " << *it << "\n"; + int d = link_dim(link_vertices, it+1, curr_d+1, curr_simplex); + if (d > final_d) + final_d = d; + } + /* + else + std::cout << "\n"; + */ + curr_simplex.pop_back(); + } + return final_d; + } + + // color is false is a (d-1)-dim face, true is a d-dim face + //typedef bool Color; + // graph is an adjacency list + typedef typename boost::adjacency_list Adj_graph; + // map that gives to a certain simplex its node in graph and its dimension + //typedef std::pair Reference; + typedef boost::graph_traits::vertex_descriptor Vertex_t; + typedef boost::graph_traits::edge_descriptor Edge_t; + + typedef boost::container::flat_map Graph_map; + + /* \brief Verifies if the simplices formed by vertices given by link_vertices + * form a pseudomanifold. + * The idea is to make a bipartite graph, where vertices are the d- and (d-1)-dimensional + * faces and edges represent adjacency between them. + */ + bool link_is_pseudomanifold(std::vector< Vertex_handle >& link_vertices, + int dimension) + { + Adj_graph adj_graph; + Graph_map d_map, f_map; // d_map = map for d-dimensional simplices + // f_map = map for its facets + typeVectorVertex empty_vector = {}; + add_vertices(link_vertices, + link_vertices.begin(), + adj_graph, + d_map, + f_map, + empty_vector, + 0, dimension); + //std::cout << "DMAP_SIZE: " << d_map.size() << "\n"; + //std::cout << "FMAP_SIZE: " << f_map.size() << "\n"; + add_edges(adj_graph, d_map, f_map); + for (auto f_map_it : f_map) + { + //std::cout << "Degree of " << f_map_it.first->first << " is " << boost::out_degree(f_map_it.second, adj_graph) << "\n"; + if (boost::out_degree(f_map_it.second, adj_graph) != 2) + { + count_bad[dimension]++; + return false; + } + } + // At this point I know that all (d-1)-simplices are adjacent to exactly 2 d-simplices + // What is left is to check the connexity + std::vector components(boost::num_vertices(adj_graph)); + return (boost::connected_components(adj_graph, &components[0]) == 1); + } + + void add_vertices(typeVectorVertex& link_vertices, + typename typeVectorVertex::iterator curr_v, + Adj_graph& adj_graph, + Graph_map& d_map, + Graph_map& f_map, + typeVectorVertex& curr_simplex, + int curr_d, + int dimension) + { + Simplex_handle sh; + Vertex_t vert; + typename typeVectorVertex::iterator it; + std::pair resPair; + //typename Graph_map::iterator resPair; + //Add vertices + //std::cout << "Entered add vertices\n"; + for (it = curr_v; it != link_vertices.end(); ++it) + { + curr_simplex.push_back(*it); + /* + std::cout << "Searching for "; + print_vector(curr_simplex); + std::cout << " curr_dim " << curr_d << " d " << dimension << ""; + */ + sh = find(curr_simplex); + if (sh != null_simplex()) + { + //std::cout << " added\n"; + if (curr_d == dimension) + { + vert = boost::add_vertex(adj_graph); + resPair = d_map.emplace(sh,vert); + } + else + { + if (curr_d == dimension-1) + { + vert = boost::add_vertex(adj_graph); + resPair = f_map.emplace(sh,vert); + } + add_vertices(link_vertices, + it+1, + adj_graph, + d_map, + f_map, + curr_simplex, + curr_d+1, dimension); + } + } + /* + else + std::cout << "\n"; + */ + curr_simplex.pop_back(); + } + } + + void add_edges(Adj_graph& adj_graph, + Graph_map& d_map, + Graph_map& f_map) + { + Simplex_handle sh; + // Add edges + //std::cout << "Entered add edges:\n"; + typename Graph_map::iterator map_it; + for (auto d_map_pair : d_map) + { + //std::cout << "*"; + sh = d_map_pair.first; + Vertex_t d_vert = d_map_pair.second; + for (auto facet_sh : boundary_simplex_range(sh)) + //for (auto f_map_it : f_map) + { + //std::cout << "'"; + map_it = f_map.find(facet_sh); + //We must have all the facets in the graph at this point + assert(map_it != f_map.end()); + Vertex_t f_vert = map_it->second; + //std::cout << "Added edge " << sh->first << "-" << map_it->first->first << "\n"; + boost::add_edge(d_vert,f_vert,adj_graph); + } + } + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + //***********COLLAPSES**************************************************************************// + ////////////////////////////////////////////////////////////////////////////////////////////////// + + + + + + + +}; //class Witness_complex + + + +} // namespace Guhdi + +#endif diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 04fcc98f..201d6525 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -140,7 +140,6 @@ namespace Gudhi { //void witness_complex(std::vector< std::vector< Vertex_handle > > & knn) { std::cout << "**Start the procedure witness_complex" << std::endl; - int k=2; /* current dimension in iterative construction */ //Construction of the active witness list int nbW = knn.size(); //int nbL = knn.at(0).size(); @@ -157,13 +156,14 @@ namespace Gudhi { // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore counter++; vv = {i}; - /* TODO Filtration */ returnValue = insert_simplex(vv, Filtration_value(0.0)); /* TODO Error if not inserted : normally no need here though*/ } + int k=1; /* current dimension in iterative construction */ //std::cout << "Successfully added landmarks" << std::endl; // PRINT2 //print_sc(root()); std::cout << std::endl; + /* int u,v; // two extremities of an edge int count = 0; if (nbL > 1) // if the supposed dimension of the complex is >0 @@ -202,39 +202,37 @@ namespace Gudhi { active_w.push_back(i); } } - std::cout << "k=1, active witnesses: " << active_w.size() << std::endl; + */ + for (int i=0; i != nbW; ++i) + active_w.push_back(i); + std::cout << "k=0, active witnesses: " << active_w.size() << std::endl; //std::cout << "Successfully added edges" << std::endl; - count_good = {0,0}; - count_bad = {0,0}; + count_good = {0}; + count_bad = {0}; int D = knn[0].size(); while (!active_w.empty() && k < D ) { count_good.push_back(0); count_bad.push_back(0); - count++; //std::cout << "Started the step k=" << k << std::endl; typename ActiveWitnessList::iterator it = active_w.begin(); while (it != active_w.end()) { typeVectorVertex simplex_vector; /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/ - // First sort the first k landmarks - VertexHandle inserted_vertex = knn[*it][k]; - bool ok = all_faces_in(knn, *it, k, inserted_vertex); + bool ok = all_faces_in(knn, *it, k); if (ok) { for (int i = 0; i != k+1; ++i) simplex_vector.push_back(knn[*it][i]); returnValue = insert_simplex(simplex_vector,0.0); - if (returnValue.second) - count++; it++; } else active_w.erase(it++); //First increase the iterator and then erase the previous element } std::cout << "k=" << k << ", active witnesses: " << active_w.size() << std::endl; - std::cout << "** k=" << k << ", num_simplices: " < - bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k, VertexHandle inserted_vertex) + bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k) { //std::cout << "All face in with the landmark " << inserted_vertex << std::endl; std::vector< VertexHandle > facet; @@ -332,20 +330,17 @@ private: // CHECK ALL THE FACETS for (int i = 0; i != k+1; ++i) { - if (knn[witness_id][i] != inserted_vertex) + facet = {}; + for (int j = 0; j != k+1; ++j) { - facet = {}; - for (int j = 0; j != k+1; ++j) + if (j != i) { - if (j != i) - { - facet.push_back(knn[witness_id][j]); - } - }//endfor - if (find(facet) == null_simplex()) - return false; - //std::cout << "++++ finished loop safely\n"; - }//endif + facet.push_back(knn[witness_id][j]); + } + }//endfor + if (find(facet) == null_simplex()) + return false; + //std::cout << "++++ finished loop safely\n"; } //endfor return true; } @@ -1059,6 +1054,54 @@ bool complex_is_pseudomanifold(int dimension) } } + public: + /** \brief Verification if every simplex in the complex is witnessed + */ + template< class KNearestNeighbors > + bool is_witness_complex(KNearestNeighbors WL) + { + //bool final_result = true; + for (Simplex_handle sh: complex_simplex_range()) + { + bool is_witnessed = false; + typeVectorVertex simplex; + int nbV = 0; //number of verticed in the simplex + for (int v: simplex_vertex_range(sh)) + simplex.push_back(v); + nbV = simplex.size(); + for (typeVectorVertex w: WL) + { + bool has_vertices = true; + for (int v: simplex) + if (std::find(w.begin(), w.begin()+nbV, v) == w.begin()+nbV) + { + has_vertices = false; + //break; + } + if (has_vertices) + { + is_witnessed = true; + std::cout << "The simplex "; + print_vector(simplex); + std::cout << " is witnessed by the witness "; + print_vector(w); + std::cout << std::endl; + break; + } + } + if (!is_witnessed) + { + std::cout << "The following simplex is not witnessed "; + print_vector(simplex); + std::cout << std::endl; + assert(is_witnessed); + return false; + } + } + return true; // Arrive here if the not_witnessed check failed all the time + } + + }; //class Witness_complex -- cgit v1.2.3 From d4c823dce7436f561c8cd545f5a4f80d2d301ca1 Mon Sep 17 00:00:00 2001 From: skachano Date: Sat, 4 Jul 2015 09:49:32 +0000 Subject: Added files for testing on didgeridoo git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@676 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6d8aeda398803d49ee9218b99939095098ceb92e --- src/Witness_complex/example/CMakeLists.txt | 15 +- src/Witness_complex/example/Torus_distance.h | 209 ++++++++ .../example/witness_complex_cube.cpp | 541 +++++++++++++++++++ .../example/witness_complex_cubic_systems.cpp | 547 +++++++++++++++++++ .../example/witness_complex_epsilon.cpp | 566 ++++++++++++++++++++ .../example/witness_complex_flat_torus.cpp | 73 ++- .../example/witness_complex_perturbations.cpp | 2 +- .../example/witness_complex_protected_delaunay.cpp | 594 +++++++++++++++++++++ .../example/witness_complex_sphere.cpp | 248 ++------- 9 files changed, 2582 insertions(+), 213 deletions(-) create mode 100644 src/Witness_complex/example/Torus_distance.h create mode 100644 src/Witness_complex/example/witness_complex_cube.cpp create mode 100644 src/Witness_complex/example/witness_complex_cubic_systems.cpp create mode 100644 src/Witness_complex/example/witness_complex_epsilon.cpp create mode 100644 src/Witness_complex/example/witness_complex_protected_delaunay.cpp (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 77f95c79..23919b4a 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -87,8 +87,19 @@ if(CGAL_FOUND) target_link_libraries(witness_complex_sphere ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_test(witness_complex_sphere ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_sphere ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) add_executable ( relaxed_witness_complex_sphere relaxed_witness_complex_sphere.cpp ) - target_link_libraries(relaxed_witness_complex_sphere ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(relaxed_witness_complex_sphere ${CMAKE_CURRENT_BINARY_DIR}/relaxed_witness_complex_sphere ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_test(witness_complex_sphere ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_sphere ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_executable ( witness_complex_protected_delaunay witness_complex_protected_delaunay.cpp ) + target_link_libraries(witness_complex_protected_delaunay ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(witness_complex_protected_delaunay ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_protected_delaunay ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_executable ( witness_complex_cubic_systems witness_complex_cubic_systems.cpp ) + target_link_libraries(witness_complex_cubic_systems ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(witness_complex_cubic_systems ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_cubic_systems ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_executable ( witness_complex_cube witness_complex_cube.cpp ) + target_link_libraries(witness_complex_cube ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(witness_complex_cube ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_cube ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_executable ( witness_complex_epsilon witness_complex_epsilon.cpp ) + target_link_libraries(witness_complex_epsilon ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(witness_complex_epsilon ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_epsilon ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Witness_complex/example/Torus_distance.h b/src/Witness_complex/example/Torus_distance.h new file mode 100644 index 00000000..5ae127df --- /dev/null +++ b/src/Witness_complex/example/Torus_distance.h @@ -0,0 +1,209 @@ +#ifndef GUDHI_TORUS_DISTANCE_H_ +#define GUDHI_TORUS_DISTANCE_H_ + +#include + +#include +#include +#include + +typedef CGAL::Epick_d K; +typedef K::Point_d Point_d; +typedef K::FT FT; +typedef CGAL::Search_traits< + FT, Point_d, + typename K::Cartesian_const_iterator_d, + typename K::Construct_cartesian_const_iterator_d> Traits_base; + +/** + * \brief Class of distance in a flat torus in dimension D + * + */ +class Torus_distance { + +public: + typedef K::FT FT; + typedef K::Point_d Point_d; + typedef Point_d Query_item; + typedef typename CGAL::Dynamic_dimension_tag D; + + double box_length = 2; + + FT transformed_distance(Query_item q, Point_d p) const + { + FT distance = FT(0); + FT coord = FT(0); + //std::cout << "Hello skitty!\n"; + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1), pit = construct_it(p); + for(; qit != qe; qit++, pit++) + { + coord = sqrt(((*qit)-(*pit))*((*qit)-(*pit))); + if (coord*coord <= (box_length-coord)*(box_length-coord)) + distance += coord*coord; + else + distance += (box_length-coord)*(box_length-coord); + } + return distance; + } + + FT min_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r) const { + FT distance = FT(0); + FT dist1, dist2; + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if((*qit) < r.min_coord(i)) + { + dist1 = (r.min_coord(i)-(*qit)); + dist2 = (box_length - r.max_coord(i)+(*qit)); + if (dist1 < dist2) + distance += dist1*dist1; + else + distance += dist2*dist2; + } + else if ((*qit) > r.max_coord(i)) + { + dist1 = (box_length - (*qit)+r.min_coord(i)); + dist2 = ((*qit) - r.max_coord(i)); + if (dist1 < dist2) + distance += dist1*dist1; + else + distance += dist2*dist2; + } + } + return distance; + } + + FT min_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r, + std::vector& dists) const { + FT distance = FT(0); + FT dist1, dist2; + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + //std::cout << r.max_coord(0) << std::endl; + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if((*qit) < r.min_coord(i)) + { + dist1 = (r.min_coord(i)-(*qit)); + dist2 = (box_length - r.max_coord(i)+(*qit)); + if (dist1 < dist2) + { + dists[i] = dist1; + distance += dist1*dist1; + } + else + { + dists[i] = dist2; + distance += dist2*dist2; + //std::cout << "Good stuff1\n"; + } + } + else if ((*qit) > r.max_coord(i)) + { + dist1 = (box_length - (*qit)+r.min_coord(i)); + dist2 = ((*qit) - r.max_coord(i)); + if (dist1 < dist2) + { + dists[i] = dist1; + distance += dist1*dist1; + //std::cout << "Good stuff2\n"; + } + else + { + dists[i] = dist2; + distance += dist2*dist2; + } + } + }; + return distance; + } + + FT max_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r) const { + FT distance=FT(0); + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if (box_length <= (r.min_coord(i)+r.max_coord(i))) + if ((r.max_coord(i)+r.min_coord(i)-box_length)/FT(2.0) <= (*qit) && + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + else + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + else + if ((box_length-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + else + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + } + return distance; + } + + + FT max_distance_to_rectangle(const Query_item& q, + const CGAL::Kd_tree_rectangle& r, + std::vector& dists) const { + FT distance=FT(0); + typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); + typename K::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q,1); + for(unsigned int i = 0;qit != qe; i++, qit++) + { + if (box_length <= (r.min_coord(i)+r.max_coord(i))) + if ((r.max_coord(i)+r.min_coord(i)-box_length)/FT(2.0) <= (*qit) && + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + { + dists[i] = r.max_coord(i)-(*qit); + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + } + else + { + dists[i] = sqrt(((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i))); + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + } + else + if ((box_length-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || + (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) + { + dists[i] = sqrt((r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit))); + distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); + + } + else + { + dists[i] = (*qit)-r.min_coord(i); + distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); + } + } + return distance; + } + + inline FT new_distance(FT dist, FT old_off, FT new_off, + int ) const { + + FT new_dist = dist + (new_off*new_off - old_off*old_off); + return new_dist; + } + + inline FT transformed_distance(FT d) const { + return d*d; + } + + inline FT inverse_of_transformed_distance(FT d) const { + return sqrt(d); + } + +}; + +#endif diff --git a/src/Witness_complex/example/witness_complex_cube.cpp b/src/Witness_complex/example/witness_complex_cube.cpp new file mode 100644 index 00000000..7545f156 --- /dev/null +++ b/src/Witness_complex/example/witness_complex_cube.cpp @@ -0,0 +1,541 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 +#include +#include + +#include +#include +//#include + +//#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex.h" +#include "gudhi/reader_utils.h" +#include "Torus_distance.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +using namespace Gudhi; +//using namespace boost::filesystem; + +typedef CGAL::Epick_d K; +typedef K::Point_d Point_d; +//typedef CGAL::Cartesian_d K; +//typedef CGAL::Point_d Point_d; +typedef K::FT FT; +typedef CGAL::Search_traits< + FT, Point_d, + typename K::Cartesian_const_iterator_d, + typename K::Construct_cartesian_const_iterator_d> Traits_base; +typedef CGAL::Euclidean_distance Euclidean_distance; + + +typedef std::vector< Vertex_handle > typeVectorVertex; + +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + +typedef CGAL::Search_traits_adapter< + std::ptrdiff_t, Point_d*, Traits_base> STraits; +//typedef K TreeTraits; +//typedef CGAL::Distance_adapter Euclidean_adapter; +//typedef CGAL::Kd_tree Kd_tree; +typedef CGAL::Orthogonal_k_neighbor_search> K_neighbor_search; +typedef K_neighbor_search::Tree Tree; +typedef K_neighbor_search::Distance Distance; +typedef K_neighbor_search::iterator KNS_iterator; +typedef K_neighbor_search::iterator KNS_range; +typedef boost::container::flat_map Point_etiquette_map; +typedef CGAL::Kd_tree Tree2; + +typedef CGAL::Fuzzy_sphere Fuzzy_sphere; + +typedef std::vector Point_Vector; + +//typedef K::Equal_d Equal_d; +//typedef CGAL::Random_points_in_cube_d > > Random_cube_iterator; +typedef CGAL::Random_points_in_cube_d Random_cube_iterator; +typedef CGAL::Random_points_in_ball_d Random_point_iterator; + +typedef CGAL::Delaunay_triangulation Delaunay_triangulation; +typedef Delaunay_triangulation::Facet Facet; +typedef CGAL::Sphere_d Sphere_d; + +bool toric=false; + + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , Point_Vector & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + Point_d p(point.begin(), point.end()); + if (point.size() != 1) + points.push_back(p); + } + in_file.close(); +} + +void generate_points_grid(Point_Vector& W, int width, int D) +{ + int nb_points = 1; + for (int i = 0; i < D; ++i) + nb_points *= width; + for (int i = 0; i < nb_points; ++i) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(0.01*(cell_i%width)); + cell_i /= width; + } + W.push_back(point); + } +} + +void generate_points_random_box(Point_Vector& W, int nbP, int dim) +{ + /* + Random_cube_iterator rp(dim, 1); + for (int i = 0; i < nbP; i++) + { + std::vector point; + for (auto it = rp->cartesian_begin(); it != rp->cartesian_end(); ++it) + point.push_back(*it); + W.push_back(Point_d(point)); + rp++; + } + */ + Random_cube_iterator rp(dim, 1.0); + for (int i = 0; i < nbP; i++) + { + W.push_back(*rp++); + } +} + + +void write_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto l: w) + ofs << l << " "; + ofs << "\n"; + } + ofs.close(); +} + + +void write_points( std::string file_name, std::vector< Point_d > & points) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : points) + { + for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + } + ofs.close(); +} + +void write_edges(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto u: witness_complex.complex_vertex_range()) + for (auto v: witness_complex.complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) + { + for (auto it = landmarks[u].cartesian_begin(); it != landmarks[u].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + for (auto it = landmarks[v].cartesian_begin(); it != landmarks[v].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n\n\n"; + } + } + ofs.close(); +} + + +void insert_delaunay_landmark_with_copies(Point_Vector& W, int chosen_landmark, std::vector& landmarks_ind, Delaunay_triangulation& delaunay, int& landmark_count) +{ + delaunay.insert(W[chosen_landmark]); + landmarks_ind.push_back(chosen_landmark); + landmark_count++; +} + +bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, int D, FT delta) +{ + Euclidean_distance ed; + Delaunay_triangulation::Vertex_handle v; + Delaunay_triangulation::Face f(t.current_dimension()); + Delaunay_triangulation::Facet ft; + Delaunay_triangulation::Full_cell_handle c; + Delaunay_triangulation::Locate_type lt; + c = t.locate(p, lt, f, ft, v); + for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) + if (!t.is_infinite(fc_it)) + { + std::vector vertices; + for (auto v_it = fc_it->vertices_begin(); v_it != fc_it->vertices_end(); ++v_it) + vertices.push_back((*v_it)->point()); + Sphere_d cs(D, vertices.begin(), vertices.end()); + Point_d center_cs = cs.center(); + FT r = sqrt(ed.transformed_distance(center_cs, fc_it->vertex(1)->point())); + FT dist2 = ed.transformed_distance(center_cs, p); + //if the new point is inside the protection ball of a non conflicting simplex + if (dist2 >= r*r && dist2 <= (r+delta)*(r+delta)) + return true; + } + return false; +} + +bool triangulation_is_protected(Delaunay_triangulation& t, FT delta) +{ + Euclidean_distance ed; + int D = t.current_dimension(); + for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) + if (!t.is_infinite(fc_it)) + for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) + { + //check if vertex belongs to the face + bool belongs = false; + for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) + if (v_it == *fc_v_it) + { + belongs = true; + break; + } + if (!belongs) + { + std::vector vertices; + for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) + vertices.push_back((*fc_v_it)->point()); + Sphere_d cs(D, vertices.begin(), vertices.end()); + Point_d center_cs = cs.center(); + FT r = sqrt(ed.transformed_distance(center_cs, fc_it->vertex(1)->point())); + FT dist2 = ed.transformed_distance(center_cs, v_it->point()); + //if the new point is inside the protection ball of a non conflicting simplex + if (dist2 <= (r+delta)*(r+delta)) + return false; + } + } + return true; +} + +void fill_landmarks(Point_Vector& W, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + for (int j = 0; j < landmarks_ind.size(); ++j) + landmarks.push_back(W[landmarks_ind[j]][l]); +} + +void landmark_choice_by_delaunay(Point_Vector& W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind, FT delta) +{ + int D = W[0].size(); + Delaunay_triangulation t(D); + CGAL::Random rand; + int chosen_landmark; + int landmark_count = 0; + for (int i = 0; i <= D+1; ++i) + { + do chosen_landmark = rand.get_int(0,nbP); + while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); + insert_delaunay_landmark_with_copies(W, chosen_landmark, landmarks_ind, t, landmark_count); + } + while (landmark_count < nbL) + { + do chosen_landmark = rand.get_int(0,nbP); + while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); + // If no conflicts then insert in every copy of T^3 + if (!is_violating_protection(W[chosen_landmark], t, D, delta)) + insert_delaunay_landmark_with_copies(W, chosen_landmark, landmarks_ind, t, landmark_count); + } +} + + +void landmark_choice_protected_delaunay(Point_Vector& W, int nbP, Point_Vector& landmarks, std::vector& landmarks_ind, FT delta) +{ + int D = W[0].size(); + Torus_distance td; + Euclidean_distance ed; + Delaunay_triangulation t(D); + CGAL::Random rand; + int landmark_count = 0; + std::list index_list; + // shuffle the list of indexes (via a vector) + { + std::vector temp_vector; + for (int i = 0; i < nbP; ++i) + temp_vector.push_back(i); + unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::shuffle(temp_vector.begin(), temp_vector.end(), std::default_random_engine(seed)); + for (std::vector::iterator it = temp_vector.begin(); it != temp_vector.end(); ++it) + index_list.push_front(*it); + } + // add the first D+1 vertices to form one non-empty cell + for (int i = 0; i <= D+1; ++i) + { + insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count); + index_list.pop_front(); + } + // add other vertices if they don't violate protection + std::list::iterator list_it = index_list.begin(); + while (list_it != index_list.end()) + if (!is_violating_protection(W[*list_it], t, D, delta)) + { + // If no conflicts then insert in every copy of T^3 + insert_delaunay_landmark_with_copies(W, *list_it, landmarks_ind, t, landmark_count); + index_list.erase(list_it); + list_it = index_list.begin(); + } + else + list_it++; + fill_landmark_copies(W, landmarks, landmarks_ind); +} + + +int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + //******************** Preface: origin point + int D = W[0].size(); + std::vector orig_vector; + for (int i=0; i landmarks_ext; + int nb_cells = 1; + for (int i = 0; i < D; ++i) + nb_cells *= 3; + for (int i = 0; i < nb_cells; ++i) + for (int k = 0; k < nbL; ++k) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(landmarks[k][l] + 2.0*((cell_i%3)-1.0)); + cell_i /= 3; + } + landmarks_ext.push_back(point); + } + write_points("landmarks/initial_landmarks",landmarks_ext); + STraits traits(&(landmarks_ext[0])); + std::vector< std::vector > WL(nbP); + + //********************** Neighbor search in a Kd tree + Tree L(boost::counting_iterator(0), + boost::counting_iterator(nb_cells*nbL), + typename Tree::Splitter(), + traits); + std::cout << "Enter (D+1) nearest landmarks\n"; + for (int i = 0; i < nbP; i++) + { + Point_d& w = W[i]; + ////Search D+1 nearest neighbours from the tree of landmarks L + K_neighbor_search search(L, w, D+1, FT(0), true, + CGAL::Distance_adapter(&(landmarks_ext[0])) ); + for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) + { + if (std::find(WL[i].begin(), WL[i].end(), (it->first)%nbL) == WL[i].end()) + WL[i].push_back((it->first)%nbL); + } + if (i == landmarks_ind[WL[i][0]]) + { + FT dist = ed.transformed_distance(W[i], landmarks[WL[i][1]]); + if (dist < lambda) + lambda = dist; + } + } + std::string out_file = "wl_result"; + write_wl(out_file,WL); + + //******************** Constructng a witness complex + std::cout << "Entered witness complex construction\n"; + Witness_complex<> witnessComplex; + witnessComplex.setNbL(nbL); + witnessComplex.witness_complex(WL); + + //******************** Making a set of bad link landmarks + std::cout << "Entered bad links\n"; + std::set< int > perturbL; + int count_badlinks = 0; + //std::cout << "Bad links around "; + std::vector< int > count_bad(D); + std::vector< int > count_good(D); + for (auto u: witnessComplex.complex_vertex_range()) + { + if (!witnessComplex.has_good_link(u, count_bad, count_good)) + { + count_badlinks++; + Point_d& l = landmarks[u]; + Fuzzy_sphere fs(l, sqrt(lambda)*3, 0, traits); + std::vector curr_perturb; + L.search(std::insert_iterator>(curr_perturb,curr_perturb.begin()),fs); + for (int i: curr_perturb) + perturbL.insert(i%nbL); + } + } + for (unsigned int i = 0; i != count_good.size(); i++) + if (count_good[i] != 0) + std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; + for (unsigned int i = 0; i != count_bad.size(); i++) + if (count_bad[i] != 0) + std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; + std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; + + //*********************** Perturb bad link landmarks + for (auto u: perturbL) + { + Random_point_iterator rp(D,sqrt(lambda)/8); + std::vector point; + for (int i = 0; i < D; i++) + { + while (K().squared_distance_d_object()(*rp,origin) < lambda/256) + rp++; + FT coord = landmarks[u][i] + (*rp)[i]; + if (coord > 1) + point.push_back(coord-1); + else if (coord < -1) + point.push_back(coord+1); + else + point.push_back(coord); + } + landmarks[u] = Point_d(point); + } + std::cout << "lambda=" << lambda << std::endl; + char buffer[100]; + int i = sprintf(buffer,"stree_result.txt"); + + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } + write_edges("landmarks/edges", witnessComplex, landmarks); + return count_badlinks; +} + + +int main (int argc, char * const argv[]) +{ + if (argc != 5) + { + std::cerr << "Usage: " << argv[0] + << " nbP nbL dim delta\n"; + return 0; + } + int nbP = atoi(argv[1]); + int nbL = atoi(argv[2]); + int dim = atoi(argv[3]); + FT delta = atof(argv[4]); + + std::cout << "Let the carnage begin!\n"; + Point_Vector point_vector; + generate_points_random_box(point_vector, nbP, dim); + Point_Vector L; + std::vector chosen_landmarks; + bool ok=false; + while (!ok) + { + ok = true; + L = {}; + chosen_landmarks = {}; + //landmark_choice_by_delaunay(point_vector, nbP, nbL, L, chosen_landmarks, delta); + landmark_choice_protected_delaunay(point_vector, nbP, L, chosen_landmarks, delta); + nbL = chosen_landmarks.size(); + std::cout << "Number of landmarks is " << nbL << std::endl; + //int width = (int)pow(nbL, 1.0/dim); landmark_choice_bcc(point_vector, nbP, width, L, chosen_landmarks); + for (auto i: chosen_landmarks) + { + ok = ok && (std::count(chosen_landmarks.begin(),chosen_landmarks.end(),i) == 1); + if (!ok) break; + } + + } + int bl = nbL, curr_min = bl; + write_points("landmarks/initial_pointset",point_vector); + //write_points("landmarks/initial_landmarks",L); + //for (int i = 0; i < 1; i++) + for (int i = 0; bl > 0; i++) + { + std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; + bl=landmark_perturbation(point_vector, nbL, L, chosen_landmarks); + if (bl < curr_min) + curr_min=bl; + write_points("landmarks/landmarks0",L); + } + +} diff --git a/src/Witness_complex/example/witness_complex_cubic_systems.cpp b/src/Witness_complex/example/witness_complex_cubic_systems.cpp new file mode 100644 index 00000000..2f4ee1cb --- /dev/null +++ b/src/Witness_complex/example/witness_complex_cubic_systems.cpp @@ -0,0 +1,547 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 +#include + +#include +#include +#include + +//#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex.h" +#include "gudhi/reader_utils.h" +#include "Torus_distance.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +using namespace Gudhi; +//using namespace boost::filesystem; + +typedef CGAL::Epick_d K; +typedef K::Point_d Point_d; +//typedef CGAL::Cartesian_d K; +//typedef CGAL::Point_d Point_d; +typedef K::FT FT; +typedef CGAL::Search_traits< + FT, Point_d, + typename K::Cartesian_const_iterator_d, + typename K::Construct_cartesian_const_iterator_d> Traits_base; +typedef CGAL::Euclidean_distance Euclidean_distance; + + +typedef std::vector< Vertex_handle > typeVectorVertex; + +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + +typedef CGAL::Search_traits_adapter< + std::ptrdiff_t, Point_d*, Traits_base> STraits; +//typedef K TreeTraits; +//typedef CGAL::Distance_adapter Euclidean_adapter; +//typedef CGAL::Kd_tree Kd_tree; +typedef CGAL::Orthogonal_k_neighbor_search> K_neighbor_search; +typedef K_neighbor_search::Tree Tree; +typedef K_neighbor_search::Distance Distance; +typedef K_neighbor_search::iterator KNS_iterator; +typedef K_neighbor_search::iterator KNS_range; +typedef boost::container::flat_map Point_etiquette_map; +typedef CGAL::Kd_tree Tree2; + +typedef CGAL::Fuzzy_sphere Fuzzy_sphere; + +typedef std::vector Point_Vector; + +//typedef K::Equal_d Equal_d; +//typedef CGAL::Random_points_in_cube_d > > Random_cube_iterator; +typedef CGAL::Random_points_in_cube_d Random_cube_iterator; +typedef CGAL::Random_points_in_ball_d Random_point_iterator; + +typedef CGAL::Delaunay_triangulation Delaunay_triangulation; +typedef Delaunay_triangulation::Facet Facet; +typedef CGAL::Sphere_d Sphere_d; + +bool toric=false; + + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , Point_Vector & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + Point_d p(point.begin(), point.end()); + if (point.size() != 1) + points.push_back(p); + } + in_file.close(); +} + +void generate_points_random_box(Point_Vector& W, int nbP, int dim) +{ + /* + Random_cube_iterator rp(dim, 1); + for (int i = 0; i < nbP; i++) + { + std::vector point; + for (auto it = rp->cartesian_begin(); it != rp->cartesian_end(); ++it) + point.push_back(*it); + W.push_back(Point_d(point)); + rp++; + } + */ + Random_cube_iterator rp(dim, 1.0); + for (int i = 0; i < nbP; i++) + { + W.push_back(*rp++); + } +} + + +void write_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto l: w) + ofs << l << " "; + ofs << "\n"; + } + ofs.close(); +} + + +void write_points( std::string file_name, std::vector< Point_d > & points) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : points) + { + for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + } + ofs.close(); +} + +void write_edges(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto u: witness_complex.complex_vertex_range()) + for (auto v: witness_complex.complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) + { + for (auto it = landmarks[u].cartesian_begin(); it != landmarks[u].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + for (auto it = landmarks[v].cartesian_begin(); it != landmarks[v].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n\n\n"; + } + } + ofs.close(); +} + + +/** Function that chooses landmarks from W and place it in the kd-tree L. + * Note: nbL hould be removed if the code moves to Witness_complex + */ +void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + std::cout << "Enter landmark choice to kd tree\n"; + int chosen_landmark; + Point_d* p; + CGAL::Random rand; + for (int i = 0; i < nbL; i++) + { + // while (!res.second) + // { + do chosen_landmark = rand.get_int(0,nbP); + while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); + //rand++; + //std::cout << "Chose " << chosen_landmark << std::endl; + p = &W[chosen_landmark]; + //L_i.emplace(chosen_landmark,i); + // } + landmarks.push_back(*p); + landmarks_ind.push_back(chosen_landmark); + //std::cout << "Added landmark " << chosen_landmark << std::endl; + } + } + +void aux_fill_grid(Point_Vector& W, int& width, Point_Vector& landmarks, std::vector& landmarks_ind, std::vector & curr_pattern) +{ + int D = W[0].size(); + int nb_points = 1; + for (int i = 0; i < D; ++i) + nb_points *= width; + for (int i = 0; i < nb_points; ++i) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + if (curr_pattern[l]) + point.push_back(-1.0+(2.0/width)*(cell_i%width)+(1.0/width)); + else + point.push_back(-1.0+(2.0/width)*(cell_i%width)); + cell_i /= width; + } + landmarks.push_back(Point_d(point)); + landmarks_ind.push_back(0);//landmarks_ind.push_back(W.size()); + //std::cout << "Added point " << W.size() << std::endl;; + //W.push_back(Point_d(point)); + } +} + +void aux_put_halves(Point_Vector& W, int& width, Point_Vector& landmarks, std::vector& landmarks_ind, std::vector& curr_pattern, std::vector::iterator curr_pattern_it, std::vector::iterator bool_it, std::vector::iterator bool_end) +{ + if (curr_pattern_it != curr_pattern.end()) + { + if (bool_it != bool_end) + { + *curr_pattern_it = false; + aux_put_halves(W, width, landmarks, landmarks_ind, curr_pattern, curr_pattern_it+1, bool_it, bool_end); + *curr_pattern_it = true; + aux_put_halves(W, width, landmarks, landmarks_ind, curr_pattern, curr_pattern_it+1, bool_it+1, bool_end); + } + } + else + if (*bool_it) + { + std::cout << "Filling the pattern "; + for (bool b: curr_pattern) + if (b) std::cout << '1'; + else std::cout << '0'; + std::cout << "\n"; + aux_fill_grid(W, width, landmarks, landmarks_ind, curr_pattern); + } +} + +void landmark_choice_cs(Point_Vector& W, int width, Point_Vector& landmarks, std::vector& landmarks_ind, std::vector& face_centers) +{ + std::cout << "Enter landmark choice to kd tree\n"; + //int chosen_landmark; + CGAL::Random rand; + //To speed things up check the last true in the code and put it as the finishing condition + unsigned last_true = face_centers.size()-1; + while (!face_centers[last_true] && last_true != 0) + last_true--; + //Recursive procedure to understand where we put +1/2 in centers' coordinates + std::vector curr_pattern(W[0].size(), false); + aux_put_halves(W, width, landmarks, landmarks_ind, curr_pattern, curr_pattern.begin(), face_centers.begin(), face_centers.begin()+(last_true+1)); + std::cout << "The number of landmarks is: " << landmarks.size() << std::endl; + + } + +int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + //******************** Preface: origin point + int D = W[0].size(); + std::vector orig_vector; + for (int i=0; i landmarks_ext; + int nb_cells = 1; + for (int i = 0; i < D; ++i) + nb_cells *= 3; + for (int i = 0; i < nb_cells; ++i) + for (int k = 0; k < nbL; ++k) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(landmarks[k][l] + 2.0*((cell_i%3)-1.0)); + cell_i /= 3; + } + landmarks_ext.push_back(point); + } + write_points("landmarks/initial_landmarks",landmarks_ext); + STraits traits(&(landmarks_ext[0])); + std::vector< std::vector > WL(nbP); + + //********************** Neighbor search in a Kd tree + Tree L(boost::counting_iterator(0), + boost::counting_iterator(nb_cells*nbL), + typename Tree::Splitter(), + traits); + std::cout << "Enter (D+1) nearest landmarks\n"; + for (int i = 0; i < nbP; i++) + { + Point_d& w = W[i]; + ////Search D+1 nearest neighbours from the tree of landmarks L + K_neighbor_search search(L, w, D+1, FT(0), true, + CGAL::Distance_adapter(&(landmarks_ext[0])) ); + for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) + { + if (std::find(WL[i].begin(), WL[i].end(), (it->first)%nbL) == WL[i].end()) + WL[i].push_back((it->first)%nbL); + } + if (i == landmarks_ind[WL[i][0]]) + { + FT dist = ed.transformed_distance(W[i], landmarks[WL[i][1]]); + if (dist < lambda) + lambda = dist; + } + } + std::string out_file = "wl_result"; + write_wl(out_file,WL); + + //******************** Constructng a witness complex + std::cout << "Entered witness complex construction\n"; + Witness_complex<> witnessComplex; + witnessComplex.setNbL(nbL); + witnessComplex.witness_complex(WL); + + //******************** Making a set of bad link landmarks + std::cout << "Entered bad links\n"; + std::set< int > perturbL; + int count_badlinks = 0; + //std::cout << "Bad links around "; + std::vector< int > count_bad(D); + std::vector< int > count_good(D); + for (auto u: witnessComplex.complex_vertex_range()) + { + if (!witnessComplex.has_good_link(u, count_bad, count_good, D)) + { + count_badlinks++; + Point_d& l = landmarks[u]; + Fuzzy_sphere fs(l, sqrt(lambda)*3, 0, traits); + std::vector curr_perturb; + L.search(std::insert_iterator>(curr_perturb,curr_perturb.begin()),fs); + for (int i: curr_perturb) + perturbL.insert(i%nbL); + } + } + for (unsigned int i = 0; i != count_good.size(); i++) + if (count_good[i] != 0) + std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; + for (unsigned int i = 0; i != count_bad.size(); i++) + if (count_bad[i] != 0) + std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; + std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; + + //*********************** Perturb bad link landmarks + for (auto u: perturbL) + { + Random_point_iterator rp(D,sqrt(lambda)/8); + std::vector point; + for (int i = 0; i < D; i++) + { + while (K().squared_distance_d_object()(*rp,origin) < lambda/256) + rp++; + FT coord = landmarks[u][i] + (*rp)[i]; + if (coord > 1) + point.push_back(coord-1); + else if (coord < -1) + point.push_back(coord+1); + else + point.push_back(coord); + } + landmarks[u] = Point_d(point); + } + std::cout << "lambda=" << lambda << std::endl; + char buffer[100]; + int i = sprintf(buffer,"stree_result.txt"); + + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } + write_edges("landmarks/edges", witnessComplex, landmarks); + return count_badlinks; +} + +void exaustive_search(Point_Vector& W, int width) +{ + int D = W[0].size()+1; + int nb_points = pow(2,D); + std::vector face_centers(D, false); + int bl = 0; //Bad links + std::vector> good_patterns; + for (int i = 0; i < nb_points; ++i) + { + int cell_i = i; + for (int l = 0; l < D; ++l) + { + if (cell_i%2 == 0) + face_centers[l] = false; + else + face_centers[l] = true; + cell_i /= 2; + } + std::cout << "**Current pattern "; + for (bool b: face_centers) + if (b) std::cout << '1'; + else std::cout << '0'; + std::cout << "\n"; + Point_Vector landmarks; + std::vector landmarks_ind; + Point_Vector W_copy(W); + landmark_choice_cs(W_copy, width, landmarks, landmarks_ind, face_centers); + if (landmarks.size() != 0) + { + bl = landmark_perturbation(W_copy, landmarks, landmarks_ind); + if ((1.0*bl)/landmarks.size() < 0.5) + good_patterns.push_back(face_centers); + } + } + std::cout << "The following patterns worked: "; + for (std::vector pattern : good_patterns) + { + std::cout << "["; + for (bool b: pattern) + if (b) std::cout << '1'; + else std::cout << '0'; + std::cout << "] "; + } + std::cout << "\n"; +} + +int main (int argc, char * const argv[]) +{ + unsigned nbP = atoi(argv[1]); + unsigned width = atoi(argv[2]); + unsigned dim = atoi(argv[3]); + std::string code = (std::string) argv[4]; + bool e_option = false; + int c; + if (argc != 5) + { + std::cerr << "Usage: " << argv[0] + << "witness_complex_cubic_systems nbP width dim code || witness_complex_systems -e nbP width dim\n" + << "where nbP stands for the number of witnesses, width for the width of the grid, dim for dimension " + << "and code is a sequence of (dim+1) symbols 0 and 1 representing if we take the centers of k-dimensional faces of the cubic system depending if it is 0 or 1." + << "-e stands for the 'exaustive' option"; + return 0; + } + while ((c = getopt (argc, argv, "e::")) != -1) + switch(c) + { + case 'e' : + e_option = true; + nbP = atoi(argv[2]); + width = atoi(argv[3]); + dim = atoi(argv[4]); + break; + default : + nbP = atoi(argv[1]); + width = atoi(argv[2]); + dim = atoi(argv[3]); + code = (std::string) argv[4]; + } + Point_Vector point_vector; + generate_points_random_box(point_vector, nbP, dim); + + // Exaustive search + if (e_option) + { + std::cout << "Start exaustive search!\n"; + exaustive_search(point_vector, width); + return 0; + } + // Search with a specific cubic system + std::vector face_centers; + if (code.size() != dim+1) + { + std::cerr << "The code should contain (dim+1) symbols"; + return 1; + } + for (char c: code) + if (c == '0') + face_centers.push_back(false); + else + face_centers.push_back(true); + std::cout << "Let the carnage begin!\n"; + Point_Vector L; + std::vector chosen_landmarks; + + landmark_choice_cs(point_vector, width, L, chosen_landmarks, face_centers); + + int nbL = width; //!!!!!!!!!!!!! + int bl = nbL, curr_min = bl; + write_points("landmarks/initial_pointset",point_vector); + //write_points("landmarks/initial_landmarks",L); + //for (int i = 0; i < 1; i++) + for (int i = 0; bl > 0; i++) + { + std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; + bl=landmark_perturbation(point_vector, L, chosen_landmarks); + if (bl < curr_min) + curr_min=bl; + write_points("landmarks/landmarks0",L); + } + +} diff --git a/src/Witness_complex/example/witness_complex_epsilon.cpp b/src/Witness_complex/example/witness_complex_epsilon.cpp new file mode 100644 index 00000000..d091bdb7 --- /dev/null +++ b/src/Witness_complex/example/witness_complex_epsilon.cpp @@ -0,0 +1,566 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 +#include +#include + +#include +#include +//#include + +//#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex.h" +#include "gudhi/reader_utils.h" +#include "Torus_distance.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +using namespace Gudhi; +//using namespace boost::filesystem; + +typedef CGAL::Epick_d K; +typedef K::Point_d Point_d; +//typedef CGAL::Cartesian_d K; +//typedef CGAL::Point_d Point_d; +typedef K::FT FT; +typedef CGAL::Search_traits< + FT, Point_d, + typename K::Cartesian_const_iterator_d, + typename K::Construct_cartesian_const_iterator_d> Traits_base; +typedef CGAL::Euclidean_distance Euclidean_distance; + + +typedef std::vector< Vertex_handle > typeVectorVertex; + +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + +typedef CGAL::Search_traits_adapter< + std::ptrdiff_t, Point_d*, Traits_base> STraits; +//typedef K TreeTraits; +//typedef CGAL::Distance_adapter Euclidean_adapter; +//typedef CGAL::Kd_tree Kd_tree; +typedef CGAL::Orthogonal_k_neighbor_search> K_neighbor_search; +typedef K_neighbor_search::Tree Tree; +typedef K_neighbor_search::Distance Distance; +typedef K_neighbor_search::iterator KNS_iterator; +typedef K_neighbor_search::iterator KNS_range; +typedef boost::container::flat_map Point_etiquette_map; +typedef CGAL::Kd_tree Tree2; + +typedef CGAL::Fuzzy_sphere Fuzzy_sphere; + +typedef std::vector Point_Vector; + +//typedef K::Equal_d Equal_d; +//typedef CGAL::Random_points_in_cube_d > > Random_cube_iterator; +typedef CGAL::Random_points_in_cube_d Random_cube_iterator; +typedef CGAL::Random_points_in_ball_d Random_point_iterator; + +typedef CGAL::Delaunay_triangulation Delaunay_triangulation; +typedef Delaunay_triangulation::Facet Facet; +typedef CGAL::Sphere_d Sphere_d; + +bool toric=false; + + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , Point_Vector & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + Point_d p(point.begin(), point.end()); + if (point.size() != 1) + points.push_back(p); + } + in_file.close(); +} + +void generate_points_grid(Point_Vector& W, int width, int D) +{ + int nb_points = 1; + for (int i = 0; i < D; ++i) + nb_points *= width; + for (int i = 0; i < nb_points; ++i) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(0.01*(cell_i%width)); + cell_i /= width; + } + W.push_back(point); + } +} + +void generate_points_random_box(Point_Vector& W, int nbP, int dim) +{ + /* + Random_cube_iterator rp(dim, 1); + for (int i = 0; i < nbP; i++) + { + std::vector point; + for (auto it = rp->cartesian_begin(); it != rp->cartesian_end(); ++it) + point.push_back(*it); + W.push_back(Point_d(point)); + rp++; + } + */ + Random_cube_iterator rp(dim, 1.0); + for (int i = 0; i < nbP; i++) + { + W.push_back(*rp++); + } +} + + +void write_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto l: w) + ofs << l << " "; + ofs << "\n"; + } + ofs.close(); +} + + +void write_points( std::string file_name, std::vector< Point_d > & points) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : points) + { + for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + } + ofs.close(); +} + +void write_edges(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto u: witness_complex.complex_vertex_range()) + for (auto v: witness_complex.complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) + { + for (auto it = landmarks[u].cartesian_begin(); it != landmarks[u].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + for (auto it = landmarks[v].cartesian_begin(); it != landmarks[v].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n\n\n"; + } + } + ofs.close(); +} + + +/** Function that chooses landmarks from W and place it in the kd-tree L. + * Note: nbL hould be removed if the code moves to Witness_complex + */ +void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + std::cout << "Enter landmark choice to kd tree\n"; + int chosen_landmark; + Point_d* p; + CGAL::Random rand; + for (int i = 0; i < nbL; i++) + { + // while (!res.second) + // { + do chosen_landmark = rand.get_int(0,nbP); + while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); + //rand++; + //std::cout << "Chose " << chosen_landmark << std::endl; + p = &W[chosen_landmark]; + //L_i.emplace(chosen_landmark,i); + // } + landmarks.push_back(*p); + landmarks_ind.push_back(chosen_landmark); + //std::cout << "Added landmark " << chosen_landmark << std::endl; + } + } + +void insert_delaunay_landmark_with_copies(Point_Vector& W, int chosen_landmark, std::vector& landmarks_ind, Delaunay_triangulation& delaunay, int& landmark_count) +{ + delaunay.insert(W[chosen_landmark]); + landmarks_ind.push_back(chosen_landmark); + landmark_count++; +} + +bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, int D, FT delta) +{ + Euclidean_distance ed; + Delaunay_triangulation::Vertex_handle v; + Delaunay_triangulation::Face f(t.current_dimension()); + Delaunay_triangulation::Facet ft; + Delaunay_triangulation::Full_cell_handle c; + Delaunay_triangulation::Locate_type lt; + c = t.locate(p, lt, f, ft, v); + for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) + if (!t.is_infinite(fc_it)) + { + std::vector vertices; + for (auto v_it = fc_it->vertices_begin(); v_it != fc_it->vertices_end(); ++v_it) + vertices.push_back((*v_it)->point()); + Sphere_d cs(D, vertices.begin(), vertices.end()); + Point_d center_cs = cs.center(); + FT r = sqrt(ed.transformed_distance(center_cs, fc_it->vertex(1)->point())); + FT dist2 = ed.transformed_distance(center_cs, p); + //if the new point is inside the protection ball of a non conflicting simplex + if (dist2 >= r*r && dist2 <= (r+delta)*(r+delta)) + return true; + } + return false; +} + +bool triangulation_is_protected(Delaunay_triangulation& t, FT delta) +{ + Euclidean_distance ed; + int D = t.current_dimension(); + for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) + if (!t.is_infinite(fc_it)) + for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) + { + //check if vertex belongs to the face + bool belongs = false; + for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) + if (v_it == *fc_v_it) + { + belongs = true; + break; + } + if (!belongs) + { + std::vector vertices; + for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) + vertices.push_back((*fc_v_it)->point()); + Sphere_d cs(D, vertices.begin(), vertices.end()); + Point_d center_cs = cs.center(); + FT r = sqrt(ed.transformed_distance(center_cs, fc_it->vertex(1)->point())); + FT dist2 = ed.transformed_distance(center_cs, v_it->point()); + //if the new point is inside the protection ball of a non conflicting simplex + if (dist2 <= (r+delta)*(r+delta)) + return false; + } + } + return true; +} + +FT sampling_radius(Delaunay_triangulation& t) +{ + int D = t.current_dimension(); + FT epsilon2 = 4.0; + for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) + { + Point_Vector vertices; + for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) + vertices.push_back((*fc_v_it)->point()); + Sphere_d cs(D, vertices.begin(), vertices.end()); + FT r2 = Euclidean_distance().transformed_distance(cs.center(), *(vertices.begin())); + if (epsilon2 > r2) + epsilon2 = r2; + } + return sqrt(epsilon2); +} + +FT point_sampling_radius_by_delaunay(Point_Vector& points) +{ + Delaunay_triangulation t(points[0].size()); + t.insert(points.begin(), points.end()); + return sampling_radius(t); +} + +void landmark_choice_protected_delaunay(Point_Vector& W, int nbP, Point_Vector& landmarks, std::vector& landmarks_ind, FT delta) +{ + int D = W[0].size(); + Torus_distance td; + Euclidean_distance ed; + Delaunay_triangulation t(D); + CGAL::Random rand; + int landmark_count = 0; + std::list index_list; + // shuffle the list of indexes (via a vector) + { + std::vector temp_vector; + for (int i = 0; i < nbP; ++i) + temp_vector.push_back(i); + unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::shuffle(temp_vector.begin(), temp_vector.end(), std::default_random_engine(seed)); + for (std::vector::iterator it = temp_vector.begin(); it != temp_vector.end(); ++it) + index_list.push_front(*it); + } + // add the first D+1 vertices to form one non-empty cell + for (int i = 0; i <= D+1; ++i) + { + insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count); + index_list.pop_front(); + } + // add other vertices if they don't violate protection + std::list::iterator list_it = index_list.begin(); + while (list_it != index_list.end()) + if (!is_violating_protection(W[*list_it], t, D, delta)) + { + // If no conflicts then insert in every copy of T^3 + insert_delaunay_landmark_with_copies(W, *list_it, landmarks_ind, t, landmark_count); + index_list.erase(list_it); + list_it = index_list.begin(); + } + else + list_it++; + for (std::vector::iterator it = landmarks_ind.begin(); it != landmarks_ind.end(); ++it) + landmarks.push_back(W[*it]); +} + + +int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + //******************** Preface: origin point + int D = W[0].size(); + std::vector orig_vector; + for (int i=0; i landmarks_ext; + int nb_cells = 1; + for (int i = 0; i < D; ++i) + nb_cells *= 3; + for (int i = 0; i < nb_cells; ++i) + for (int k = 0; k < nbL; ++k) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(landmarks[k][l] + 2.0*((cell_i%3)-1.0)); + cell_i /= 3; + } + landmarks_ext.push_back(point); + } + write_points("landmarks/initial_landmarks",landmarks_ext); + STraits traits(&(landmarks_ext[0])); + std::vector< std::vector > WL(nbP); + + //********************** Neighbor search in a Kd tree + Tree L(boost::counting_iterator(0), + boost::counting_iterator(nb_cells*nbL), + typename Tree::Splitter(), + traits); + std::cout << "Enter (D+1) nearest landmarks\n"; + for (int i = 0; i < nbP; i++) + { + Point_d& w = W[i]; + ////Search D+1 nearest neighbours from the tree of landmarks L + K_neighbor_search search(L, w, D+1, FT(0), true, + CGAL::Distance_adapter(&(landmarks_ext[0])) ); + for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) + { + if (std::find(WL[i].begin(), WL[i].end(), (it->first)%nbL) == WL[i].end()) + WL[i].push_back((it->first)%nbL); + } + if (i == landmarks_ind[WL[i][0]]) + { + FT dist = ed.transformed_distance(W[i], landmarks[WL[i][1]]); + if (dist < lambda) + lambda = dist; + } + } + std::string out_file = "wl_result"; + write_wl(out_file,WL); + + //******************** Constructng a witness complex + std::cout << "Entered witness complex construction\n"; + Witness_complex<> witnessComplex; + witnessComplex.setNbL(nbL); + witnessComplex.witness_complex(WL); + + //******************** Making a set of bad link landmarks + std::cout << "Entered bad links\n"; + std::set< int > perturbL; + int count_badlinks = 0; + //std::cout << "Bad links around "; + std::vector< int > count_bad(D); + std::vector< int > count_good(D); + for (auto u: witnessComplex.complex_vertex_range()) + { + if (!witnessComplex.has_good_link(u, count_bad, count_good)) + { + count_badlinks++; + Point_d& l = landmarks[u]; + Fuzzy_sphere fs(l, sqrt(lambda)*3, 0, traits); + std::vector curr_perturb; + L.search(std::insert_iterator>(curr_perturb,curr_perturb.begin()),fs); + for (int i: curr_perturb) + perturbL.insert(i%nbL); + } + } + for (unsigned int i = 0; i != count_good.size(); i++) + if (count_good[i] != 0) + std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; + for (unsigned int i = 0; i != count_bad.size(); i++) + if (count_bad[i] != 0) + std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; + std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; + + //*********************** Perturb bad link landmarks + for (auto u: perturbL) + { + Random_point_iterator rp(D,sqrt(lambda)/8); + std::vector point; + for (int i = 0; i < D; i++) + { + while (K().squared_distance_d_object()(*rp,origin) < lambda/256) + rp++; + FT coord = landmarks[u][i] + (*rp)[i]; + if (coord > 1) + point.push_back(coord-1); + else if (coord < -1) + point.push_back(coord+1); + else + point.push_back(coord); + } + landmarks[u] = Point_d(point); + } + std::cout << "lambda=" << lambda << std::endl; + char buffer[100]; + int i = sprintf(buffer,"stree_result.txt"); + + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } + write_edges("landmarks/edges", witnessComplex, landmarks); + return count_badlinks; +} + + +int main (int argc, char * const argv[]) +{ + if (argc != 5) + { + std::cerr << "Usage: " << argv[0] + << " nbP nbL dim delta\n"; + return 0; + } + int nbP = atoi(argv[1]); + int nbL = atoi(argv[2]); + int dim = atoi(argv[3]); + FT delta = atof(argv[4]); + + std::cout << "Let the carnage begin!\n"; + Point_Vector point_vector; + generate_points_random_box(point_vector, nbP, dim); + FT epsilon = point_sampling_radius_by_delaunay(point_vector); + std::cout << "Initial epsilon = " << epsilon << std::endl; + Point_Vector L; + std::vector chosen_landmarks; + bool ok=false; + while (!ok) + { + ok = true; + L = {}; + chosen_landmarks = {}; + //landmark_choice_by_delaunay(point_vector, nbP, nbL, L, chosen_landmarks, delta); + landmark_choice_protected_delaunay(point_vector, nbP, L, chosen_landmarks, delta); + nbL = chosen_landmarks.size(); + std::cout << "Number of landmarks is " << nbL << std::endl; + //int width = (int)pow(nbL, 1.0/dim); landmark_choice_bcc(point_vector, nbP, width, L, chosen_landmarks); + for (auto i: chosen_landmarks) + { + ok = ok && (std::count(chosen_landmarks.begin(),chosen_landmarks.end(),i) == 1); + if (!ok) break; + } + + } + FT epsilon2 = point_sampling_radius_by_delaunay(L); + std::cout << "Final epsilon = " << epsilon2 << ". Ratio = " << epsilon/epsilon2 << std::endl; + int bl = nbL, curr_min = bl; + write_points("landmarks/initial_pointset",point_vector); + //write_points("landmarks/initial_landmarks",L); + //for (int i = 0; i < 1; i++) + for (int i = 0; bl > 0; i++) + { + std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; + bl=landmark_perturbation(point_vector, nbL, L, chosen_landmarks); + if (bl < curr_min) + curr_min=bl; + write_points("landmarks/landmarks0",L); + } + +} diff --git a/src/Witness_complex/example/witness_complex_flat_torus.cpp b/src/Witness_complex/example/witness_complex_flat_torus.cpp index 42bf5e7e..06bf5a9f 100644 --- a/src/Witness_complex/example/witness_complex_flat_torus.cpp +++ b/src/Witness_complex/example/witness_complex_flat_torus.cpp @@ -63,8 +63,10 @@ using namespace Gudhi; //using namespace boost::filesystem; typedef CGAL::Epick_d K; -typedef K::FT FT; typedef K::Point_d Point_d; +//typedef CGAL::Cartesian_d K; +//typedef CGAL::Point_d Point_d; +typedef K::FT FT; typedef CGAL::Search_traits< FT, Point_d, typename K::Cartesian_const_iterator_d, @@ -72,7 +74,7 @@ typedef CGAL::Search_traits< typedef CGAL::Euclidean_distance Euclidean_distance; /** - * \brief Class of distance in a flat torus in dimaension D + * \brief Class of distance in a flat torus in dimension D * */ //class Torus_distance : public Euclidean_distance { @@ -288,10 +290,11 @@ typedef CGAL::Fuzzy_sphere Fuzzy_sphere; typedef std::vector Point_Vector; //typedef K::Equal_d Equal_d; +//typedef CGAL::Random_points_in_cube_d > > Random_cube_iterator; typedef CGAL::Random_points_in_cube_d Random_cube_iterator; typedef CGAL::Random_points_in_ball_d Random_point_iterator; -bool toric=true; +bool toric=false; /** * \brief Customized version of read_points @@ -341,7 +344,18 @@ void generate_points_grid(Point_Vector& W, int width, int D) void generate_points_random_box(Point_Vector& W, int nbP, int dim) { + /* Random_cube_iterator rp(dim, 1); + for (int i = 0; i < nbP; i++) + { + std::vector point; + for (auto it = rp->cartesian_begin(); it != rp->cartesian_end(); ++it) + point.push_back(*it); + W.push_back(Point_d(point)); + rp++; + } + */ + Random_cube_iterator rp(dim, 1.0); for (int i = 0; i < nbP; i++) { W.push_back(*rp++); @@ -494,9 +508,7 @@ void write_edges(std::string file_name, Witness_complex<>& witness_complex, Poin void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) { std::cout << "Enter landmark choice to kd tree\n"; - //std::vector landmarks; int chosen_landmark; - //std::pair res = std::make_pair(L_i.begin(),false); Point_d* p; CGAL::Random rand; for (int i = 0; i < nbL; i++) @@ -516,6 +528,33 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, } } +/** \brief Choose landmarks on a body-central cubic system + */ +void landmark_choice_bcc(Point_Vector &W, int nbP, int width, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + int D = W[0].size(); + int nb_points = 1; + for (int i = 0; i < D; ++i) + nb_points *= width; + for (int i = 0; i < nb_points; ++i) + { + std::vector point; + std::vector cpoint; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(-1.0+(2.0/width)*(cell_i%width)); + cpoint.push_back(-1.0+(2.0/width)*(cell_i%width)+(1.0/width)); + cell_i /= width; + } + landmarks.push_back(point); + landmarks.push_back(cpoint); + landmarks_ind.push_back(2*i); + landmarks_ind.push_back(2*i+1); + } + std::cout << "The number of landmarks is: " << landmarks.size() << std::endl; +} + int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector& landmarks_ind) { @@ -548,7 +587,7 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< int cell_i = i; for (int l = 0; l < D; ++l) { - point.push_back(landmarks[k][l] + 2.0*((cell_i%3)-1)); + point.push_back(landmarks[k][l] + 2.0*((cell_i%3)-1.0)); cell_i /= 3; } landmarks_ext.push_back(point); @@ -587,7 +626,8 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< //Point_etiquette_map::iterator itm = L_i.find(it->first); //assert(itm != L_i.end()); //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; - WL[i].push_back((it->first)%nbL); + if (std::find(WL[i].begin(), WL[i].end(), (it->first)%nbL) == WL[i].end()) + WL[i].push_back((it->first)%nbL); //std::cout << "ITFIRST " << it->first << std::endl; //std::cout << i << " " << it->first << ": " << it->second << std::endl; } @@ -609,6 +649,12 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< Witness_complex<> witnessComplex; witnessComplex.setNbL(nbL); witnessComplex.witness_complex(WL); + /* + if (witnessComplex.is_witness_complex(WL)) + std::cout << "!!YES. IT IS A WITNESS COMPLEX!!\n"; + else + std::cout << "??NO. IT IS NOT A WITNESS COMPLEX??\n"; + */ //******************** Making a set of bad link landmarks std::cout << "Entered bad links\n"; std::set< int > perturbL; @@ -730,9 +776,9 @@ int main (int argc, char * const argv[]) std::cout << "Let the carnage begin!\n"; Point_Vector point_vector; //read_points_cust(file_name, point_vector); - //generate_points_random_box(point_vector, nbP, dim); - generate_points_grid(point_vector, (int)pow(nbP, 1.0/dim), dim); - nbP = (int)(pow((int)pow(nbP, 1.0/dim), dim)); + generate_points_random_box(point_vector, nbP, dim); + //generate_points_grid(point_vector, (int)pow(nbP, 1.0/dim), dim); + //nbP = (int)(pow((int)pow(nbP, 1.0/dim), dim)); /* for (auto &p: point_vector) { @@ -757,17 +803,20 @@ int main (int argc, char * const argv[]) L = {}; chosen_landmarks = {}; landmark_choice(point_vector, nbP, nbL, L, chosen_landmarks); + + //int width = (int)pow(nbL, 1.0/dim); landmark_choice_bcc(point_vector, nbP, width, L, chosen_landmarks); for (auto i: chosen_landmarks) { ok = ok && (std::count(chosen_landmarks.begin(),chosen_landmarks.end(),i) == 1); if (!ok) break; } + } int bl = nbL, curr_min = bl; write_points("landmarks/initial_pointset",point_vector); //write_points("landmarks/initial_landmarks",L); - - for (int i = 0; bl > 0; i++) + for (int i = 0; i < 1; i++) + //for (int i = 0; bl > 0; i++) { std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; bl=landmark_perturbation(point_vector, L, chosen_landmarks); diff --git a/src/Witness_complex/example/witness_complex_perturbations.cpp b/src/Witness_complex/example/witness_complex_perturbations.cpp index 88a7510a..b3b84b1f 100644 --- a/src/Witness_complex/example/witness_complex_perturbations.cpp +++ b/src/Witness_complex/example/witness_complex_perturbations.cpp @@ -416,7 +416,7 @@ int main (int argc, char * const argv[]) { file_name.erase(0, last_slash_idx + 1); } - //write_points("landmarks/initial_pointset",point_vector); + write_points("landmarks/initial_pointset",point_vector); write_points("landmarks/initial_landmarks",L); //for (int i = 0; bl != 0; i++) for (int i = 0; i < 1; i++) diff --git a/src/Witness_complex/example/witness_complex_protected_delaunay.cpp b/src/Witness_complex/example/witness_complex_protected_delaunay.cpp new file mode 100644 index 00000000..2f795a5f --- /dev/null +++ b/src/Witness_complex/example/witness_complex_protected_delaunay.cpp @@ -0,0 +1,594 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 +#include +#include + +#include +#include +//#include + +//#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Witness_complex.h" +#include "gudhi/reader_utils.h" +#include "Torus_distance.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +using namespace Gudhi; +//using namespace boost::filesystem; + +typedef CGAL::Epick_d K; +typedef K::Point_d Point_d; +//typedef CGAL::Cartesian_d K; +//typedef CGAL::Point_d Point_d; +typedef K::FT FT; +typedef CGAL::Search_traits< + FT, Point_d, + typename K::Cartesian_const_iterator_d, + typename K::Construct_cartesian_const_iterator_d> Traits_base; +typedef CGAL::Euclidean_distance Euclidean_distance; + + +typedef std::vector< Vertex_handle > typeVectorVertex; + +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + +typedef CGAL::Search_traits_adapter< + std::ptrdiff_t, Point_d*, Traits_base> STraits; +//typedef K TreeTraits; +//typedef CGAL::Distance_adapter Euclidean_adapter; +//typedef CGAL::Kd_tree Kd_tree; +typedef CGAL::Orthogonal_k_neighbor_search> K_neighbor_search; +typedef K_neighbor_search::Tree Tree; +typedef K_neighbor_search::Distance Distance; +typedef K_neighbor_search::iterator KNS_iterator; +typedef K_neighbor_search::iterator KNS_range; +typedef boost::container::flat_map Point_etiquette_map; +typedef CGAL::Kd_tree Tree2; + +typedef CGAL::Fuzzy_sphere Fuzzy_sphere; + +typedef std::vector Point_Vector; + +//typedef K::Equal_d Equal_d; +//typedef CGAL::Random_points_in_cube_d > > Random_cube_iterator; +typedef CGAL::Random_points_in_cube_d Random_cube_iterator; +typedef CGAL::Random_points_in_ball_d Random_point_iterator; + +typedef CGAL::Delaunay_triangulation Delaunay_triangulation; +typedef Delaunay_triangulation::Facet Facet; +typedef CGAL::Sphere_d Sphere_d; + +bool toric=false; + + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , Point_Vector & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + Point_d p(point.begin(), point.end()); + if (point.size() != 1) + points.push_back(p); + } + in_file.close(); +} + +void generate_points_grid(Point_Vector& W, int width, int D) +{ + int nb_points = 1; + for (int i = 0; i < D; ++i) + nb_points *= width; + for (int i = 0; i < nb_points; ++i) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(0.01*(cell_i%width)); + cell_i /= width; + } + W.push_back(point); + } +} + +void generate_points_random_box(Point_Vector& W, int nbP, int dim) +{ + /* + Random_cube_iterator rp(dim, 1); + for (int i = 0; i < nbP; i++) + { + std::vector point; + for (auto it = rp->cartesian_begin(); it != rp->cartesian_end(); ++it) + point.push_back(*it); + W.push_back(Point_d(point)); + rp++; + } + */ + Random_cube_iterator rp(dim, 1.0); + for (int i = 0; i < nbP; i++) + { + W.push_back(*rp++); + } +} + + +void write_wl( std::string file_name, std::vector< std::vector > & WL) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : WL) + { + for (auto l: w) + ofs << l << " "; + ofs << "\n"; + } + ofs.close(); +} + + +void write_points( std::string file_name, std::vector< Point_d > & points) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto w : points) + { + for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + } + ofs.close(); +} + +void write_edges(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) +{ + std::ofstream ofs (file_name, std::ofstream::out); + for (auto u: witness_complex.complex_vertex_range()) + for (auto v: witness_complex.complex_vertex_range()) + { + typeVectorVertex edge = {u,v}; + if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) + { + for (auto it = landmarks[u].cartesian_begin(); it != landmarks[u].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n"; + for (auto it = landmarks[v].cartesian_begin(); it != landmarks[v].cartesian_end(); ++it) + ofs << *it << " "; + ofs << "\n\n\n"; + } + } + ofs.close(); +} + + +/** Function that chooses landmarks from W and place it in the kd-tree L. + * Note: nbL hould be removed if the code moves to Witness_complex + */ +void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + std::cout << "Enter landmark choice to kd tree\n"; + int chosen_landmark; + Point_d* p; + CGAL::Random rand; + for (int i = 0; i < nbL; i++) + { + // while (!res.second) + // { + do chosen_landmark = rand.get_int(0,nbP); + while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); + //rand++; + //std::cout << "Chose " << chosen_landmark << std::endl; + p = &W[chosen_landmark]; + //L_i.emplace(chosen_landmark,i); + // } + landmarks.push_back(*p); + landmarks_ind.push_back(chosen_landmark); + //std::cout << "Added landmark " << chosen_landmark << std::endl; + } + } + +void insert_delaunay_landmark_with_copies(Point_Vector& W, int chosen_landmark, std::vector& landmarks_ind, Delaunay_triangulation& delaunay, int& landmark_count) +{ + int D = W[0].size(); + int nb_cells = pow(3, D); + for (int i = 0; i < nb_cells; ++i) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(W[chosen_landmark][l] + 2.0*(cell_i%3-1)); + cell_i /= 3; + } + delaunay.insert(point); + } + landmarks_ind.push_back(chosen_landmark); + landmark_count++; +} + +bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, int D, FT delta) +{ + Euclidean_distance ed; + Delaunay_triangulation::Vertex_handle v; + Delaunay_triangulation::Face f(t.current_dimension()); + Delaunay_triangulation::Facet ft; + Delaunay_triangulation::Full_cell_handle c; + Delaunay_triangulation::Locate_type lt; + c = t.locate(p, lt, f, ft, v); + for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) + if (!t.is_infinite(fc_it)) + { + std::vector vertices; + for (auto v_it = fc_it->vertices_begin(); v_it != fc_it->vertices_end(); ++v_it) + vertices.push_back((*v_it)->point()); + Sphere_d cs(D, vertices.begin(), vertices.end()); + Point_d center_cs = cs.center(); + FT r = sqrt(ed.transformed_distance(center_cs, fc_it->vertex(1)->point())); + FT dist2 = ed.transformed_distance(center_cs, p); + //if the new point is inside the protection ball of a non conflicting simplex + if (dist2 >= r*r && dist2 <= (r+delta)*(r+delta)) + return true; + } + return false; +} + +bool triangulation_is_protected(Delaunay_triangulation& t, FT delta) +{ + Euclidean_distance ed; + int D = t.current_dimension(); + for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) + if (!t.is_infinite(fc_it)) + for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) + { + //check if vertex belongs to the face + bool belongs = false; + for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) + if (v_it == *fc_v_it) + { + belongs = true; + break; + } + if (!belongs) + { + std::vector vertices; + for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) + vertices.push_back((*fc_v_it)->point()); + Sphere_d cs(D, vertices.begin(), vertices.end()); + Point_d center_cs = cs.center(); + FT r = sqrt(ed.transformed_distance(center_cs, fc_it->vertex(1)->point())); + FT dist2 = ed.transformed_distance(center_cs, v_it->point()); + //if the new point is inside the protection ball of a non conflicting simplex + if (dist2 <= (r+delta)*(r+delta)) + return false; + } + } + return true; +} + +void fill_landmark_copies(Point_Vector& W, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + int D = W[0].size(); + int nb_cells = pow(3, D); + int nbL = landmarks_ind.size(); + // Fill landmarks + for (int i = 0; i < nb_cells-1; ++i) + for (int j = 0; j < nbL; ++j) + { + int cell_i = i; + Point_d point; + for (int l = 0; l < D; ++l) + { + point.push_back(W[landmarks_ind[j]][l] + 2.0*(cell_i-1)); + cell_i /= 3; + } + landmarks.push_back(point); + } +} + +void landmark_choice_by_delaunay(Point_Vector& W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind, FT delta) +{ + int D = W[0].size(); + Delaunay_triangulation t(D); + CGAL::Random rand; + int chosen_landmark; + int landmark_count = 0; + for (int i = 0; i <= D+1; ++i) + { + do chosen_landmark = rand.get_int(0,nbP); + while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); + insert_delaunay_landmark_with_copies(W, chosen_landmark, landmarks_ind, t, landmark_count); + } + while (landmark_count < nbL) + { + do chosen_landmark = rand.get_int(0,nbP); + while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); + // If no conflicts then insert in every copy of T^3 + if (!is_violating_protection(W[chosen_landmark], t, D, delta)) + insert_delaunay_landmark_with_copies(W, chosen_landmark, landmarks_ind, t, landmark_count); + } + fill_landmark_copies(W, landmarks, landmarks_ind); +} + + +void landmark_choice_protected_delaunay(Point_Vector& W, int nbP, Point_Vector& landmarks, std::vector& landmarks_ind, FT delta) +{ + int D = W[0].size(); + Torus_distance td; + Euclidean_distance ed; + Delaunay_triangulation t(D); + CGAL::Random rand; + int landmark_count = 0; + std::list index_list; + // shuffle the list of indexes (via a vector) + { + std::vector temp_vector; + for (int i = 0; i < nbP; ++i) + temp_vector.push_back(i); + unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::shuffle(temp_vector.begin(), temp_vector.end(), std::default_random_engine(seed)); + for (std::vector::iterator it = temp_vector.begin(); it != temp_vector.end(); ++it) + index_list.push_front(*it); + } + // add the first D+1 vertices to form one non-empty cell + for (int i = 0; i <= D+1; ++i) + { + insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count); + index_list.pop_front(); + } + // add other vertices if they don't violate protection + std::list::iterator list_it = index_list.begin(); + while (list_it != index_list.end()) + if (!is_violating_protection(W[*list_it], t, D, delta)) + { + // If no conflicts then insert in every copy of T^3 + insert_delaunay_landmark_with_copies(W, *list_it, landmarks_ind, t, landmark_count); + index_list.erase(list_it); + list_it = index_list.begin(); + } + else + list_it++; + fill_landmark_copies(W, landmarks, landmarks_ind); +} + + +int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + //******************** Preface: origin point + int D = W[0].size(); + std::vector orig_vector; + for (int i=0; i landmarks_ext; + int nb_cells = 1; + for (int i = 0; i < D; ++i) + nb_cells *= 3; + for (int i = 0; i < nb_cells; ++i) + for (int k = 0; k < nbL; ++k) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(landmarks[k][l] + 2.0*((cell_i%3)-1.0)); + cell_i /= 3; + } + landmarks_ext.push_back(point); + } + write_points("landmarks/initial_landmarks",landmarks_ext); + STraits traits(&(landmarks_ext[0])); + std::vector< std::vector > WL(nbP); + + //********************** Neighbor search in a Kd tree + Tree L(boost::counting_iterator(0), + boost::counting_iterator(nb_cells*nbL), + typename Tree::Splitter(), + traits); + std::cout << "Enter (D+1) nearest landmarks\n"; + for (int i = 0; i < nbP; i++) + { + Point_d& w = W[i]; + ////Search D+1 nearest neighbours from the tree of landmarks L + K_neighbor_search search(L, w, D+1, FT(0), true, + CGAL::Distance_adapter(&(landmarks_ext[0])) ); + for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) + { + if (std::find(WL[i].begin(), WL[i].end(), (it->first)%nbL) == WL[i].end()) + WL[i].push_back((it->first)%nbL); + } + if (i == landmarks_ind[WL[i][0]]) + { + FT dist = ed.transformed_distance(W[i], landmarks[WL[i][1]]); + if (dist < lambda) + lambda = dist; + } + } + std::string out_file = "wl_result"; + write_wl(out_file,WL); + + //******************** Constructng a witness complex + std::cout << "Entered witness complex construction\n"; + Witness_complex<> witnessComplex; + witnessComplex.setNbL(nbL); + witnessComplex.witness_complex(WL); + + //******************** Making a set of bad link landmarks + std::cout << "Entered bad links\n"; + std::set< int > perturbL; + int count_badlinks = 0; + //std::cout << "Bad links around "; + std::vector< int > count_bad(D); + std::vector< int > count_good(D); + for (auto u: witnessComplex.complex_vertex_range()) + { + if (!witnessComplex.has_good_link(u, count_bad, count_good)) + { + count_badlinks++; + Point_d& l = landmarks[u]; + Fuzzy_sphere fs(l, sqrt(lambda)*3, 0, traits); + std::vector curr_perturb; + L.search(std::insert_iterator>(curr_perturb,curr_perturb.begin()),fs); + for (int i: curr_perturb) + perturbL.insert(i%nbL); + } + } + for (unsigned int i = 0; i != count_good.size(); i++) + if (count_good[i] != 0) + std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; + for (unsigned int i = 0; i != count_bad.size(); i++) + if (count_bad[i] != 0) + std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; + std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; + + //*********************** Perturb bad link landmarks + for (auto u: perturbL) + { + Random_point_iterator rp(D,sqrt(lambda)/8); + std::vector point; + for (int i = 0; i < D; i++) + { + while (K().squared_distance_d_object()(*rp,origin) < lambda/256) + rp++; + FT coord = landmarks[u][i] + (*rp)[i]; + if (coord > 1) + point.push_back(coord-1); + else if (coord < -1) + point.push_back(coord+1); + else + point.push_back(coord); + } + landmarks[u] = Point_d(point); + } + std::cout << "lambda=" << lambda << std::endl; + char buffer[100]; + int i = sprintf(buffer,"stree_result.txt"); + + if (i >= 0) + { + std::string out_file = (std::string)buffer; + std::ofstream ofs (out_file, std::ofstream::out); + witnessComplex.st_to_file(ofs); + ofs.close(); + } + write_edges("landmarks/edges", witnessComplex, landmarks); + return count_badlinks; +} + + +int main (int argc, char * const argv[]) +{ + if (argc != 5) + { + std::cerr << "Usage: " << argv[0] + << " nbP nbL dim delta\n"; + return 0; + } + int nbP = atoi(argv[1]); + int nbL = atoi(argv[2]); + int dim = atoi(argv[3]); + FT delta = atof(argv[4]); + + std::cout << "Let the carnage begin!\n"; + Point_Vector point_vector; + generate_points_random_box(point_vector, nbP, dim); + Point_Vector L; + std::vector chosen_landmarks; + bool ok=false; + while (!ok) + { + ok = true; + L = {}; + chosen_landmarks = {}; + //landmark_choice_by_delaunay(point_vector, nbP, nbL, L, chosen_landmarks, delta); + landmark_choice_protected_delaunay(point_vector, nbP, L, chosen_landmarks, delta); + nbL = chosen_landmarks.size(); + std::cout << "Number of landmarks is " << nbL << std::endl; + //int width = (int)pow(nbL, 1.0/dim); landmark_choice_bcc(point_vector, nbP, width, L, chosen_landmarks); + for (auto i: chosen_landmarks) + { + ok = ok && (std::count(chosen_landmarks.begin(),chosen_landmarks.end(),i) == 1); + if (!ok) break; + } + + } + int bl = nbL, curr_min = bl; + write_points("landmarks/initial_pointset",point_vector); + //write_points("landmarks/initial_landmarks",L); + //for (int i = 0; i < 1; i++) + for (int i = 0; bl > 0; i++) + { + std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; + bl=landmark_perturbation(point_vector, nbL, L, chosen_landmarks); + if (bl < curr_min) + curr_min=bl; + write_points("landmarks/landmarks0",L); + } + +} diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index d08c763f..74aae875 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -71,199 +71,6 @@ typedef CGAL::Search_traits< typename K::Construct_cartesian_const_iterator_d> Traits_base; typedef CGAL::Euclidean_distance Euclidean_distance; -/** - * \brief Class of distance in a flat torus in dimaension D - * - */ -//class Torus_distance : public Euclidean_distance { - class Torus_distance { - -public: - typedef K::FT FT; - typedef K::Point_d Point_d; - typedef Point_d Query_item; - typedef typename CGAL::Dynamic_dimension_tag D; - - double box_length = 2; - - FT transformed_distance(Query_item q, Point_d p) const - { - FT distance = FT(0); - FT coord = FT(0); - //std::cout << "Hello skitty!\n"; - typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); - typename K::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q,1), pit = construct_it(p); - for(; qit != qe; qit++, pit++) - { - coord = sqrt(((*qit)-(*pit))*((*qit)-(*pit))); - if (coord*coord <= (box_length-coord)*(box_length-coord)) - distance += coord*coord; - else - distance += (box_length-coord)*(box_length-coord); - } - return distance; - } - - FT min_distance_to_rectangle(const Query_item& q, - const CGAL::Kd_tree_rectangle& r) const { - FT distance = FT(0); - FT dist1, dist2; - typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); - typename K::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q,1); - for(unsigned int i = 0;qit != qe; i++, qit++) - { - if((*qit) < r.min_coord(i)) - { - dist1 = (r.min_coord(i)-(*qit)); - dist2 = (box_length - r.max_coord(i)+(*qit)); - if (dist1 < dist2) - distance += dist1*dist1; - else - distance += dist2*dist2; - } - else if ((*qit) > r.max_coord(i)) - { - dist1 = (box_length - (*qit)+r.min_coord(i)); - dist2 = ((*qit) - r.max_coord(i)); - if (dist1 < dist2) - distance += dist1*dist1; - else - distance += dist2*dist2; - } - } - return distance; - } - - FT min_distance_to_rectangle(const Query_item& q, - const CGAL::Kd_tree_rectangle& r, - std::vector& dists) const { - FT distance = FT(0); - FT dist1, dist2; - typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); - typename K::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q,1); - //std::cout << r.max_coord(0) << std::endl; - for(unsigned int i = 0;qit != qe; i++, qit++) - { - if((*qit) < r.min_coord(i)) - { - dist1 = (r.min_coord(i)-(*qit)); - dist2 = (box_length - r.max_coord(i)+(*qit)); - if (dist1 < dist2) - { - dists[i] = dist1; - distance += dist1*dist1; - } - else - { - dists[i] = dist2; - distance += dist2*dist2; - //std::cout << "Good stuff1\n"; - } - } - else if ((*qit) > r.max_coord(i)) - { - dist1 = (box_length - (*qit)+r.min_coord(i)); - dist2 = ((*qit) - r.max_coord(i)); - if (dist1 < dist2) - { - dists[i] = dist1; - distance += dist1*dist1; - //std::cout << "Good stuff2\n"; - } - else - { - dists[i] = dist2; - distance += dist2*dist2; - } - } - }; - return distance; - } - - FT max_distance_to_rectangle(const Query_item& q, - const CGAL::Kd_tree_rectangle& r) const { - FT distance=FT(0); - typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); - typename K::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q,1); - for(unsigned int i = 0;qit != qe; i++, qit++) - { - if (box_length <= (r.min_coord(i)+r.max_coord(i))) - if ((r.max_coord(i)+r.min_coord(i)-box_length)/FT(2.0) <= (*qit) && - (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) - distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); - else - distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); - else - if ((box_length-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || - (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) - distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); - else - distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); - } - return distance; - } - - - FT max_distance_to_rectangle(const Query_item& q, - const CGAL::Kd_tree_rectangle& r, - std::vector& dists) const { - FT distance=FT(0); - typename K::Construct_cartesian_const_iterator_d construct_it=Traits_base().construct_cartesian_const_iterator_d_object(); - typename K::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q,1); - for(unsigned int i = 0;qit != qe; i++, qit++) - { - if (box_length <= (r.min_coord(i)+r.max_coord(i))) - if ((r.max_coord(i)+r.min_coord(i)-box_length)/FT(2.0) <= (*qit) && - (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) - { - dists[i] = r.max_coord(i)-(*qit); - distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); - } - else - { - dists[i] = sqrt(((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i))); - distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); - } - else - if ((box_length-r.max_coord(i)-r.min_coord(i))/FT(2.0) <= (*qit) || - (*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) - { - dists[i] = sqrt((r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit))); - distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); - - } - else - { - dists[i] = (*qit)-r.min_coord(i); - distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); - } - } - return distance; - } - - inline FT new_distance(FT dist, FT old_off, FT new_off, - int /* cutting_dimension */) const { - - FT new_dist = dist + (new_off*new_off - old_off*old_off); - return new_dist; - } - - inline FT transformed_distance(FT d) const { - return d*d; - } - - inline FT inverse_of_transformed_distance(FT d) const { - return sqrt(d); - } - -}; - - typedef std::vector< Vertex_handle > typeVectorVertex; //typedef std::pair typeSimplex; @@ -502,6 +309,49 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, } } +/** \brief A test with 600cell, the generalisation of icosaedre in 4d + */ +void landmark_choice_600cell(Point_Vector&W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +{ + assert(W[0].size() == 4); //4-dimensionality required + FT phi = (1+sqrt(5))/2; + FT phi_1 = FT(1)/phi; + std::vector p; + // 16 vertices + for (FT a = -0.5; a < 1; a += 1) + for (FT b = -0.5; b < 1; b += 1) + for (FT c = -0.5; c < 1; c += 1) + for (FT d = -0.5; d < 1; d += 1) + landmarks.push_back(Point_d(std::vector({a,b,c,d}))); + // 8 vertices + for (FT a = -0.5; a < 1; a += 1) + { + landmarks.push_back(Point_d(std::vector({a,0,0,0}))); + landmarks.push_back(Point_d(std::vector({0,a,0,0}))); + landmarks.push_back(Point_d(std::vector({0,0,a,0}))); + landmarks.push_back(Point_d(std::vector({0,0,0,a}))); + } + // 96 vertices + for (FT a = -phi/2; a < phi; a += phi) + for (FT b = -0.5; b < 1; b += 1) + for (FT c = -phi_1/2; c < phi_1; c += phi_1) + { + landmarks.push_back(Point_d(std::vector({a,b,c,0}))); + landmarks.push_back(Point_d(std::vector({b,a,0,c}))); + landmarks.push_back(Point_d(std::vector({c,0,a,b}))); + landmarks.push_back(Point_d(std::vector({0,c,b,a}))); + landmarks.push_back(Point_d(std::vector({a,c,0,b}))); + landmarks.push_back(Point_d(std::vector({a,0,b,c}))); + landmarks.push_back(Point_d(std::vector({c,b,0,a}))); + landmarks.push_back(Point_d(std::vector({0,b,a,c}))); + landmarks.push_back(Point_d(std::vector({b,0,c,a}))); + landmarks.push_back(Point_d(std::vector({0,a,c,b}))); + landmarks.push_back(Point_d(std::vector({b,c,a,0}))); + landmarks.push_back(Point_d(std::vector({c,a,b,0}))); + } + for (int i = 0; i < 120; ++i) + landmarks_ind.push_back(i); +} int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector& landmarks_ind) { @@ -516,10 +366,7 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< //******************** Constructing a WL matrix int nbP = W.size(); int nbL = landmarks.size(); - //Point_Vector landmarks_ = landmarks; - Torus_distance ed; - //Equal_d ed; - //Point_d p1(std::vector({0.8,0.8})), p2(std::vector({0.1,0.1})); + Euclidean_distance ed; FT lambda = ed.transformed_distance(landmarks[0],landmarks[1]); //std::cout << "Lambda=" << lambda << std::endl; //FT lambda = 0.1;//Euclidean_distance(); @@ -578,10 +425,12 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< Witness_complex<> witnessComplex; witnessComplex.setNbL(nbL); witnessComplex.witness_complex(WL); + /* if (witnessComplex.is_witness_complex(WL)) std::cout << "!!YES. IT IS A WITNESS COMPLEX!!\n"; else - std::cout << "??NO. IT IS NOT A WITNESS COMPLEX??\n"; + std::cout << "??NO. IT IS NOT A WITNESS COMPLEX??\n"; + */ //******************** Making a set of bad link landmarks std::cout << "Entered bad links\n"; std::set< int > perturbL; @@ -715,11 +564,14 @@ int main (int argc, char * const argv[]) L = {}; chosen_landmarks = {}; landmark_choice(point_vector, nbP, nbL, L, chosen_landmarks); + //landmark_choice_600cell(point_vector, nbP, nbL, L, chosen_landmarks); + /* for (auto i: chosen_landmarks) { ok = ok && (std::count(chosen_landmarks.begin(),chosen_landmarks.end(),i) == 1); if (!ok) break; } + */ } int bl = nbL, curr_min = bl; write_points("landmarks/initial_pointset",point_vector); -- cgit v1.2.3 From 1bcbd5e259d3c13211a9b71c66cacadaad35404c Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 6 Jul 2015 07:04:53 +0000 Subject: Corrected errors in witness_complex_cube git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@680 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e0a33544c992889344cdaaed947479a5bc458ce3 --- .../example/witness_complex_cube.cpp | 59 +++++++++------------- .../example/witness_complex_flat_torus.cpp | 6 +-- .../example/witness_complex_perturbations.cpp | 20 +++++--- .../example/witness_complex_sphere.cpp | 7 +-- 4 files changed, 44 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_cube.cpp b/src/Witness_complex/example/witness_complex_cube.cpp index 7545f156..b6051a5f 100644 --- a/src/Witness_complex/example/witness_complex_cube.cpp +++ b/src/Witness_complex/example/witness_complex_cube.cpp @@ -291,8 +291,8 @@ bool triangulation_is_protected(Delaunay_triangulation& t, FT delta) void fill_landmarks(Point_Vector& W, Point_Vector& landmarks, std::vector& landmarks_ind) { - for (int j = 0; j < landmarks_ind.size(); ++j) - landmarks.push_back(W[landmarks_ind[j]][l]); + for (unsigned j = 0; j < landmarks_ind.size(); ++j) + landmarks.push_back(W[landmarks_ind[j]]); } void landmark_choice_by_delaunay(Point_Vector& W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind, FT delta) @@ -356,7 +356,7 @@ void landmark_choice_protected_delaunay(Point_Vector& W, int nbP, Point_Vector& } else list_it++; - fill_landmark_copies(W, landmarks, landmarks_ind); + fill_landmarks(W, landmarks, landmarks_ind); } @@ -427,6 +427,7 @@ int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std witnessComplex.witness_complex(WL); //******************** Making a set of bad link landmarks + /* std::cout << "Entered bad links\n"; std::set< int > perturbL; int count_badlinks = 0; @@ -453,8 +454,9 @@ int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std if (count_bad[i] != 0) std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; - + */ //*********************** Perturb bad link landmarks + /* for (auto u: perturbL) { Random_point_iterator rp(D,sqrt(lambda)/8); @@ -486,56 +488,41 @@ int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std } write_edges("landmarks/edges", witnessComplex, landmarks); return count_badlinks; + */ + return 0; } int main (int argc, char * const argv[]) { - if (argc != 5) + if (argc != 3) { std::cerr << "Usage: " << argv[0] - << " nbP nbL dim delta\n"; + << " nbP dim\n"; return 0; } int nbP = atoi(argv[1]); - int nbL = atoi(argv[2]); - int dim = atoi(argv[3]); - FT delta = atof(argv[4]); + int dim = atoi(argv[2]); std::cout << "Let the carnage begin!\n"; Point_Vector point_vector; generate_points_random_box(point_vector, nbP, dim); Point_Vector L; std::vector chosen_landmarks; - bool ok=false; - while (!ok) - { - ok = true; - L = {}; - chosen_landmarks = {}; - //landmark_choice_by_delaunay(point_vector, nbP, nbL, L, chosen_landmarks, delta); - landmark_choice_protected_delaunay(point_vector, nbP, L, chosen_landmarks, delta); - nbL = chosen_landmarks.size(); - std::cout << "Number of landmarks is " << nbL << std::endl; - //int width = (int)pow(nbL, 1.0/dim); landmark_choice_bcc(point_vector, nbP, width, L, chosen_landmarks); - for (auto i: chosen_landmarks) - { - ok = ok && (std::count(chosen_landmarks.begin(),chosen_landmarks.end(),i) == 1); - if (!ok) break; - } - - } - int bl = nbL, curr_min = bl; - write_points("landmarks/initial_pointset",point_vector); + //write_points("landmarks/initial_pointset",point_vector); //write_points("landmarks/initial_landmarks",L); - //for (int i = 0; i < 1; i++) - for (int i = 0; bl > 0; i++) + for (int i = 0; i < 11; i++) + //for (int i = 0; bl > 0; i++) { - std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; - bl=landmark_perturbation(point_vector, nbL, L, chosen_landmarks); - if (bl < curr_min) - curr_min=bl; - write_points("landmarks/landmarks0",L); + //std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; + double delta = pow(10, -(1.0*i)/2); + std::cout << "delta = " << delta << std::endl; + L = {}; chosen_landmarks = {}; + landmark_choice_protected_delaunay(point_vector, nbP, L, chosen_landmarks, delta); + int nbL = chosen_landmarks.size(); + std::cout << "Number of landmarks = " << nbL << std::endl; + landmark_perturbation(point_vector, nbL, L, chosen_landmarks); + //write_points("landmarks/landmarks0",L); } } diff --git a/src/Witness_complex/example/witness_complex_flat_torus.cpp b/src/Witness_complex/example/witness_complex_flat_torus.cpp index 06bf5a9f..69ef5fbf 100644 --- a/src/Witness_complex/example/witness_complex_flat_torus.cpp +++ b/src/Witness_complex/example/witness_complex_flat_torus.cpp @@ -335,7 +335,7 @@ void generate_points_grid(Point_Vector& W, int width, int D) int cell_i = i; for (int l = 0; l < D; ++l) { - point.push_back(0.01*(cell_i%width)); + point.push_back((2.0/width)*(cell_i%width)); cell_i /= width; } W.push_back(point); @@ -516,7 +516,7 @@ void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, // while (!res.second) // { do chosen_landmark = rand.get_int(0,nbP); - while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); + while (std::find(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=landmarks_ind.end()); //rand++; //std::cout << "Chose " << chosen_landmark << std::endl; p = &W[chosen_landmark]; @@ -672,7 +672,7 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< count_badlinks++; //std::cout << u << " "; Point_d& l = landmarks[u]; - Fuzzy_sphere fs(l, sqrt(lambda)*3, 0, traits); + Fuzzy_sphere fs(l, sqrt(lambda), 0, traits); std::vector curr_perturb; L.search(std::insert_iterator>(curr_perturb,curr_perturb.begin()),fs); for (int i: curr_perturb) diff --git a/src/Witness_complex/example/witness_complex_perturbations.cpp b/src/Witness_complex/example/witness_complex_perturbations.cpp index b3b84b1f..f78bcdab 100644 --- a/src/Witness_complex/example/witness_complex_perturbations.cpp +++ b/src/Witness_complex/example/witness_complex_perturbations.cpp @@ -267,6 +267,8 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< std::cout << "Enter (D+1) nearest landmarks\n"; //std::cout << "Size of the tree is " << L.size() << std::endl; int D = W[0].size(); + clock_t start, end; + start = clock(); for (int i = 0; i < nbP; i++) { //std::cout << "Entered witness number " << i << std::endl; @@ -294,18 +296,23 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< lambda = dist; } //std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; - - } + } //std::cout << "\n"; + end = clock(); + std::cout << "WL matrix construction on " << nbL << " landmarks took " << (double)(end-start)/CLOCKS_PER_SEC << "s.\n"; + std::string out_file = "wl_result"; - write_wl(out_file,WL); + //write_wl(out_file,WL); //******************** Constructng a witness complex std::cout << "Entered witness complex construction\n"; Witness_complex<> witnessComplex; witnessComplex.setNbL(nbL); + start = clock(); witnessComplex.witness_complex(WL); + end = clock(); + std::cout << "Witness complex construction on " << nbL << " landmarks took " << (double)(end-start)/CLOCKS_PER_SEC << "s.\n"; //******************** Making a set of bad link landmarks std::cout << "Entered bad links\n"; std::set< int > perturbL; @@ -355,7 +362,7 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< std::cout << "lambda=" << lambda << std::endl; // Write the WL matrix in a file - + /* char buffer[100]; int i = sprintf(buffer,"stree_result.txt"); @@ -366,8 +373,9 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< witnessComplex.st_to_file(ofs); ofs.close(); } + */ //witnessComplex.write_badlinks("badlinks"); - write_edges_gnuplot("landmarks/edges", witnessComplex, landmarks); + //write_edges_gnuplot("landmarks/edges", witnessComplex, landmarks); return count_badlinks; } @@ -417,7 +425,7 @@ int main (int argc, char * const argv[]) file_name.erase(0, last_slash_idx + 1); } write_points("landmarks/initial_pointset",point_vector); - write_points("landmarks/initial_landmarks",L); + //write_points("landmarks/initial_landmarks",L); //for (int i = 0; bl != 0; i++) for (int i = 0; i < 1; i++) { diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index 74aae875..550c9392 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -431,6 +431,7 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< else std::cout << "??NO. IT IS NOT A WITNESS COMPLEX??\n"; */ + */ //******************** Making a set of bad link landmarks std::cout << "Entered bad links\n"; std::set< int > perturbL; @@ -446,7 +447,7 @@ int landmark_perturbation(Point_Vector &W, Point_Vector& landmarks, std::vector< count_badlinks++; //std::cout << u << " "; Point_d& l = landmarks[u]; - Fuzzy_sphere fs(l, sqrt(lambda)*3, 0, traits); + Fuzzy_sphere fs(l, sqrt(lambda), 0, traits); std::vector curr_perturb; L.search(std::insert_iterator>(curr_perturb,curr_perturb.begin()),fs); for (int i: curr_perturb) @@ -577,8 +578,8 @@ int main (int argc, char * const argv[]) write_points("landmarks/initial_pointset",point_vector); write_points("landmarks/initial_landmarks",L); - //for (int i = 0; bl > 0; i++) - for (int i = 0; i < 1; i++) + for (int i = 0; bl > 0; i++) + //for (int i = 0; i < 1; i++) { std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; bl=landmark_perturbation(point_vector, L, chosen_landmarks); -- cgit v1.2.3 From da39f7cd8a0db5d7fa13c9c87f8fc3e038c10d01 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 15 Jul 2015 12:56:11 +0000 Subject: The construction of a protected set worked! FY! git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@716 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c2fec169cc227d123c3386007ef4e5799e8e3209 --- .../example/witness_complex_cube.cpp | 484 ++++++++++++++++-- .../example/witness_complex_epsilon.cpp | 565 +-------------------- 2 files changed, 462 insertions(+), 587 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_cube.cpp b/src/Witness_complex/example/witness_complex_cube.cpp index b6051a5f..a9a2959b 100644 --- a/src/Witness_complex/example/witness_complex_cube.cpp +++ b/src/Witness_complex/example/witness_complex_cube.cpp @@ -47,12 +47,15 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include @@ -66,7 +69,10 @@ using namespace Gudhi; typedef CGAL::Epick_d K; typedef K::Point_d Point_d; -//typedef CGAL::Cartesian_d K; +typedef K::Vector_d Vector_d; +typedef K::Oriented_side_d Oriented_side_d; +typedef K::Has_on_positive_side_d Has_on_positive_side_d; + //typedef CGAL::Point_d Point_d; typedef K::FT FT; typedef CGAL::Search_traits< @@ -105,7 +111,12 @@ typedef CGAL::Random_points_in_ball_d Random_point_iterator; typedef CGAL::Delaunay_triangulation Delaunay_triangulation; typedef Delaunay_triangulation::Facet Facet; -typedef CGAL::Sphere_d Sphere_d; +typedef Delaunay_triangulation::Vertex_handle Delaunay_vertex; +typedef Delaunay_triangulation::Full_cell_handle Full_cell_handle; +//typedef CGAL::Sphere_d Sphere_d; +typedef K::Sphere_d Sphere_d; +typedef K::Hyperplane_d Hyperplane_d; + bool toric=false; @@ -230,7 +241,187 @@ void insert_delaunay_landmark_with_copies(Point_Vector& W, int chosen_landmark, landmark_count++; } +bool vertex_is_in_full_cell(Delaunay_triangulation::Vertex_handle v, Full_cell_handle fc) +{ + for (auto v_it = fc->vertices_begin(); v_it != fc->vertices_end(); ++v_it) + if (*v_it == v) + return true; + return false; +} + +bool new_cell_is_violated(Delaunay_triangulation& t, std::vector& vertices, bool is_infinite, const Point_d& p, FT delta) +{ + if (!is_infinite) + // FINITE CASE + { + Sphere_d cs(vertices.begin(), vertices.end()); + Point_d center_cs = cs.center(); + FT r = sqrt(Euclidean_distance().transformed_distance(center_cs, vertices[0])); + for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) + if (!t.is_infinite(v_it)) + { + //CGAL::Oriented_side side = Oriented_side_d()(cs, (v_it)->point()); + if (std::find(vertices.begin(), vertices.end(), v_it->point()) == vertices.end()) + { + FT dist2 = Euclidean_distance().transformed_distance(center_cs, (v_it)->point()); + //if (dist2 >= r*r && dist2 <= (r+delta)*(r+delta)) + if (dist2 >= r*r && dist2 <= r*r+delta*delta) + return true; + } + } + } + else + // INFINITE CASE + { + Delaunay_triangulation::Vertex_iterator v = t.vertices_begin(); + while (t.is_infinite(v) || std::find(vertices.begin(), vertices.end(), v->point()) == vertices.end()) + v++; + Hyperplane_d facet_plane(vertices.begin(), vertices.end(), v->point(), CGAL::ON_POSITIVE_SIDE); + Vector_d orth_v = facet_plane.orthogonal_vector(); + for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) + if (!t.is_infinite(v_it)) + if (std::find(vertices.begin(), vertices.end(), v_it->point()) == vertices.end()) + { + std::vector coords; + Point_d p = v_it->point(); + auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin(); + for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i) + coords.push_back((*p_i) - (*orth_i) * delta / sqrt(orth_v.squared_length())); + Point_d p_delta = Point_d(coords); + bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p); + bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta); + if (!p_is_inside && p_delta_is_inside) + return true; + } + } + return false; +} + + +bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, Full_cell_handle c, Full_cell_handle parent_cell, int index, int D, FT delta, std::vector& marked_cells) +{ + Euclidean_distance ed; + std::vector vertices; + if (!t.is_infinite(c)) + { + // if the cell is finite, we look if the protection is violated + for (auto v_it = c->vertices_begin(); v_it != c->vertices_end(); ++v_it) + vertices.push_back((*v_it)->point()); + Sphere_d cs( vertices.begin(), vertices.end()); + Point_d center_cs = cs.center(); + FT r = sqrt(ed.transformed_distance(center_cs, vertices[0])); + FT dist2 = ed.transformed_distance(center_cs, p); + // if the new point is inside the protection ball of a non conflicting simplex + //if (dist2 >= r*r && dist2 <= (r+delta)*(r+delta)) + if (dist2 >= r*r && dist2 <= r*r+delta*delta) + return true; + c->tds_data().mark_visited(); + marked_cells.push_back(c); + // if the new point is inside the circumscribing ball : continue violation searching on neughbours + if (dist2 < r*r) + for (int i = 0; i < D+1; ++i) + { + Full_cell_handle next_c = c->neighbor(i); + if (next_c->tds_data().is_clear() && + is_violating_protection(p, t, next_c, c, i, D, delta, marked_cells)) + return true; + } + // if the new point is outside the protection sphere + else + { + // facet f is on the border of the conflict zone : check protection of simplex {p,f} + // the new simplex is guaranteed to be finite + vertices.clear(); vertices.push_back(p); + for (int i = 0; i < D+1; ++i) + if (i != index) + vertices.push_back(parent_cell->vertex(i)->point()); + Delaunay_vertex vertex_to_check; + for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it) + if (!vertex_is_in_full_cell(*vh_it, parent_cell)) + { + vertex_to_check = *vh_it; break; + } + if (new_cell_is_violated(t, vertices, false, vertex_to_check->point(), delta)) + return true; + } + } + else + { + // Inside of the convex hull is + side. Outside is - side. + for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it) + if (!t.is_infinite(*vh_it)) + vertices.push_back((*vh_it)->point()); + Delaunay_triangulation::Vertex_iterator v_it = t.vertices_begin(); + while (t.is_infinite(v_it) || vertex_is_in_full_cell(v_it, c)) + v_it++; + Hyperplane_d facet_plane(vertices.begin(), vertices.end(), v_it->point(), CGAL::ON_POSITIVE_SIDE); + //CGAL::Oriented_side outside = Oriented_side_d()(facet_plane, v_it->point()); + Vector_d orth_v = facet_plane.orthogonal_vector(); + std::vector coords; + auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin(); + for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i) + coords.push_back((*p_i) - (*orth_i) * delta / sqrt(orth_v.squared_length())); + Point_d p_delta = Point_d(coords); + bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p); + bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta); + + if (!p_is_inside && p_delta_is_inside) + return true; + //if the cell is infinite we look at the neighbours regardless + c->tds_data().mark_visited(); + marked_cells.push_back(c); + if (p_is_inside) + for (int i = 0; i < D+1; ++i) + { + Full_cell_handle next_c = c->neighbor(i); + if (next_c->tds_data().is_clear() && + is_violating_protection(p, t, next_c, c, i, D, delta, marked_cells)) + return true; + } + else + { + // facet f is on the border of the conflict zone : check protection of simplex {p,f} + // the new simplex is finite if the parent cell is finite + vertices.clear(); vertices.push_back(p); + bool new_simplex_is_finite = false; + for (int i = 0; i < D+1; ++i) + if (i != index) + { + if (t.is_infinite(parent_cell->vertex(i))) + new_simplex_is_finite = true; + else + vertices.push_back(parent_cell->vertex(i)->point()); + } + Delaunay_vertex vertex_to_check; + for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it) + if (!vertex_is_in_full_cell(*vh_it, parent_cell)) + { + vertex_to_check = *vh_it; break; + } + if (new_cell_is_violated(t, vertices, new_simplex_is_finite, vertex_to_check->point(), delta)) + return true; + } + } + return false; +} + bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, int D, FT delta) +{ + Euclidean_distance ed; + Delaunay_triangulation::Vertex_handle v; + Delaunay_triangulation::Face f(t.current_dimension()); + Delaunay_triangulation::Facet ft; + Delaunay_triangulation::Full_cell_handle c; + Delaunay_triangulation::Locate_type lt; + std::vector marked_cells; + c = t.locate(p, lt, f, ft, v); + bool violation_existing_cells = is_violating_protection(p, t, c, c, 0, D, delta, marked_cells); + for (Full_cell_handle fc : marked_cells) + fc->tds_data().clear(); + return violation_existing_cells; +} + +bool old_is_violating_protection(Point_d& p, Delaunay_triangulation& t, int D, FT delta) { Euclidean_distance ed; Delaunay_triangulation::Vertex_handle v; @@ -245,7 +436,7 @@ bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, int D, FT de std::vector vertices; for (auto v_it = fc_it->vertices_begin(); v_it != fc_it->vertices_end(); ++v_it) vertices.push_back((*v_it)->point()); - Sphere_d cs(D, vertices.begin(), vertices.end()); + Sphere_d cs( vertices.begin(), vertices.end()); Point_d center_cs = cs.center(); FT r = sqrt(ed.transformed_distance(center_cs, fc_it->vertex(1)->point())); FT dist2 = ed.transformed_distance(center_cs, p); @@ -253,39 +444,88 @@ bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, int D, FT de if (dist2 >= r*r && dist2 <= (r+delta)*(r+delta)) return true; } + t.insert(p, c); return false; } +void write_delaunay_mesh(Delaunay_triangulation& t, const Point_d& p) +{ + std::ofstream ofs ("delaunay.mesh", std::ofstream::out); + int nbV = t.number_of_vertices()+1; + ofs << "MeshVersionFormatted 1\nDimension 2\n"; + ofs << "Vertices\n" << nbV << "\n"; + int ind = 1; //index of a vertex + std::map index_of_vertex; + for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) + { + if (t.is_infinite(v_it)) + continue; + for (auto coord = v_it->point().cartesian_begin(); coord != v_it->point().cartesian_end(); ++coord) + ofs << *coord << " "; + ofs << "508\n"; + index_of_vertex[v_it] = ind++; + } + for (auto coord = p.cartesian_begin(); coord != p.cartesian_end(); ++coord) + ofs << *coord << " "; + ofs << "208\n"; + /* + int nbFacets = 0; + for (auto ft_it = t.finite_facets_begin(); ft_it != t.finite_facets_end(); ++ft_it) + nbFacets++; + ofs << "\nEdges\n" << nbFacets << "\n\n"; + for (auto ft_it = t.facets_begin(); ft_it != t.facets_end(); ++ft_it) + { + if (t.is_infinite(ft_it)) + continue; + for (auto vh_it = ft_it->vertices_begin(); vh_it != ft_it->vertices_end(); ++vh_it) + ofs << index_of_vertex[*vh_it] << " "; + } + */ + ofs << "Triangles " << t.number_of_finite_full_cells()+1 << "\n"; + for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) + { + if (t.is_infinite(fc_it)) + continue; + for (auto vh_it = fc_it->vertices_begin(); vh_it != fc_it->vertices_end(); ++vh_it) + ofs << index_of_vertex[*vh_it] << " "; + ofs << "508\n"; + } + ofs << nbV << " " << nbV << " " << nbV << " " << 208 << "\n"; + ofs << "End\n"; + ofs.close(); +} + bool triangulation_is_protected(Delaunay_triangulation& t, FT delta) { + // Verification part Euclidean_distance ed; - int D = t.current_dimension(); for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) if (!t.is_infinite(fc_it)) for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) - { + if (!t.is_infinite(v_it)) //check if vertex belongs to the face - bool belongs = false; - for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) - if (v_it == *fc_v_it) - { - belongs = true; - break; - } - if (!belongs) + if (!vertex_is_in_full_cell(v_it, fc_it)) { std::vector vertices; for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) vertices.push_back((*fc_v_it)->point()); - Sphere_d cs(D, vertices.begin(), vertices.end()); + Sphere_d cs( vertices.begin(), vertices.end()); Point_d center_cs = cs.center(); - FT r = sqrt(ed.transformed_distance(center_cs, fc_it->vertex(1)->point())); + FT r = sqrt(ed.transformed_distance(center_cs, fc_it->vertex(0)->point())); FT dist2 = ed.transformed_distance(center_cs, v_it->point()); //if the new point is inside the protection ball of a non conflicting simplex - if (dist2 <= (r+delta)*(r+delta)) - return false; + //std::cout << "Dist^2 = " << dist2 << " (r+delta)*(r+delta) = " << (r+delta)*(r+delta) << " r^2 = " << r*r <<"\n"; + //if (dist2 <= (r+delta)*(r+delta) && dist2 >= r*r) + if (dist2 <= r*r+delta*delta && dist2 >= r*r) + { + write_delaunay_mesh(t, v_it->point()); + std::cout << "Problematic vertex " << *v_it << " "; + std::cout << "Problematic cell " << *fc_it << "\n"; + std::cout << "r^2 = " << r*r << ", d^2 = " << dist2 << ", r^2+delta^2 = " << r*r+delta*delta << "\n"; + return false; + } } - } + return true; } @@ -295,33 +535,65 @@ void fill_landmarks(Point_Vector& W, Point_Vector& landmarks, std::vector& landmarks.push_back(W[landmarks_ind[j]]); } -void landmark_choice_by_delaunay(Point_Vector& W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind, FT delta) +void fill_full_cell_vector(Delaunay_triangulation& t, std::vector>& full_cells) { - int D = W[0].size(); - Delaunay_triangulation t(D); - CGAL::Random rand; - int chosen_landmark; - int landmark_count = 0; - for (int i = 0; i <= D+1; ++i) + // Store vertex indices in a map + int ind = 0; //index of a vertex + std::map index_of_vertex; + for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) + if (t.is_infinite(v_it)) + continue; + else + index_of_vertex[v_it] = ind++; + // Write full cells as vectors in full_cells + for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) { - do chosen_landmark = rand.get_int(0,nbP); - while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); - insert_delaunay_landmark_with_copies(W, chosen_landmark, landmarks_ind, t, landmark_count); + if (t.is_infinite(fc_it)) + continue; + std::vector cell; + for (auto v_it = fc_it->vertices_begin(); v_it != fc_it->vertices_end(); ++v_it) + cell.push_back(index_of_vertex[*v_it]); + full_cells.push_back(cell); } - while (landmark_count < nbL) - { - do chosen_landmark = rand.get_int(0,nbP); - while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); - // If no conflicts then insert in every copy of T^3 - if (!is_violating_protection(W[chosen_landmark], t, D, delta)) - insert_delaunay_landmark_with_copies(W, chosen_landmark, landmarks_ind, t, landmark_count); +} + +FT sampling_radius(Delaunay_triangulation& t) +{ + FT epsilon2 = 4.0; + for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) + { + if (t.is_infinite(fc_it)) + continue; + Point_Vector vertices; + for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) + vertices.push_back((*fc_v_it)->point()); + Sphere_d cs( vertices.begin(), vertices.end()); + Point_d csc = cs.center(); + bool in_cube = true; + for (auto xi = csc.cartesian_begin(); xi != csc.cartesian_end(); ++xi) + if (*xi > 1.0 || *xi < -1.0) + { + in_cube = false; break; + } + if (!in_cube) + continue; + FT r2 = Euclidean_distance().transformed_distance(cs.center(), *(vertices.begin())); + if (epsilon2 > r2) + epsilon2 = r2; } + return sqrt(epsilon2); } +FT point_sampling_radius_by_delaunay(Point_Vector& points) +{ + Delaunay_triangulation t(points[0].size()); + t.insert(points.begin(), points.end()); + return sampling_radius(t); +} -void landmark_choice_protected_delaunay(Point_Vector& W, int nbP, Point_Vector& landmarks, std::vector& landmarks_ind, FT delta) +void landmark_choice_protected_delaunay(Point_Vector& W, int nbP, Point_Vector& landmarks, std::vector& landmarks_ind, FT delta, std::vector>& full_cells) { - int D = W[0].size(); + unsigned D = W[0].size(); Torus_distance td; Euclidean_distance ed; Delaunay_triangulation t(D); @@ -335,32 +607,106 @@ void landmark_choice_protected_delaunay(Point_Vector& W, int nbP, Point_Vector& temp_vector.push_back(i); unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); std::shuffle(temp_vector.begin(), temp_vector.end(), std::default_random_engine(seed)); + //CGAL::spatial_sort(temp_vector.begin(), temp_vector.end()); for (std::vector::iterator it = temp_vector.begin(); it != temp_vector.end(); ++it) index_list.push_front(*it); } - // add the first D+1 vertices to form one non-empty cell + for (unsigned pos1 = 0; pos1 < D+1; ++pos1) + { + std::vector point; + for (unsigned i = 0; i < pos1; ++i) + point.push_back(-1); + if (pos1 != D) + point.push_back(1); + for (unsigned i = pos1+1; i < D; ++i) + point.push_back(0); + assert(point.size() == D); + W[index_list.front()] = Point_d(point); + insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count); + index_list.pop_front(); + } + // add the first D+1 vertices to form one finite cell + /* for (int i = 0; i <= D+1; ++i) { + t.insert(W[index_list.front()]); insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count); index_list.pop_front(); } + */ + /* + { + std::vector coords; + for (int i = 0; i < D; ++i) + coords.push_back(-1); + W[index_list.front()] = Point_d(coords); + insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count); + index_list.pop_front(); + for (int i = 0; i < D; ++i) + { + coords.clear(); + for (int j = 0; j < D; ++j) + if (i == j) + coords.push_back(1); + else + coords.push_back(-1); + W[index_list.front()] = Point_d(coords); + insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count); + index_list.pop_front(); + } + } + */ + //std::cout << t; + //assert(t.number_of_vertices() == D+1); + //assert(landmarks_ind.size() == D+1); + //assert(W[landmarks_ind[0]][0] == 0); // add other vertices if they don't violate protection std::list::iterator list_it = index_list.begin(); while (list_it != index_list.end()) - if (!is_violating_protection(W[*list_it], t, D, delta)) - { + { + if (!is_violating_protection(W[*list_it], t, D, delta)) + { // If no conflicts then insert in every copy of T^3 + is_violating_protection(W[*list_it], t, D, delta); insert_delaunay_landmark_with_copies(W, *list_it, landmarks_ind, t, landmark_count); index_list.erase(list_it); list_it = index_list.begin(); + //std::cout << "index_list_size() = " << index_list.size() << "\n"; } - else - list_it++; + else + { + list_it++; + //std::cout << "!!!!!WARNING!!!!! A POINT HAS BEEN OMITTED!!!\n"; + } + //write_delaunay_mesh(t, W[*list_it]); + } fill_landmarks(W, landmarks, landmarks_ind); + fill_full_cell_vector(t, full_cells); + if (triangulation_is_protected(t, delta)) + std::cout << "Triangulation is ok\n"; + else + std::cout << "Triangulation is BAD!! T_T しくしく!\n"; + write_delaunay_mesh(t, Point_d(std::vector({0,0}))); + //std::cout << t << std::endl; } +template +void print_vector(std::vector v) +{ + std::cout << "["; + if (!v.empty()) + { + std::cout << *(v.begin()); + for (auto it = v.begin()+1; it != v.end(); ++it) + { + std::cout << ","; + std::cout << *it; + } + } + std::cout << "]"; +} -int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) +int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind, std::vector>& full_cells) { //******************** Preface: origin point int D = W[0].size(); @@ -426,6 +772,20 @@ int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std witnessComplex.setNbL(nbL); witnessComplex.witness_complex(WL); + //******************** Verifying if all full cells are in the complex + + int in=0, not_in=0; + for (auto cell : full_cells) + { + //print_vector(cell); + if (witnessComplex.find(cell) != witnessComplex.null_simplex()) + in++; + else + not_in++; + } + std::cout << "Out of all the cells in Delaunay triangulation:\n" << in << " are in the witness complex\n" << + not_in << " are not.\n"; + //******************** Making a set of bad link landmarks /* std::cout << "Entered bad links\n"; @@ -476,6 +836,7 @@ int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std landmarks[u] = Point_d(point); } std::cout << "lambda=" << lambda << std::endl; + */ char buffer[100]; int i = sprintf(buffer,"stree_result.txt"); @@ -486,7 +847,9 @@ int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std witnessComplex.st_to_file(ofs); ofs.close(); } + write_edges("landmarks/edges", witnessComplex, landmarks); + /* return count_badlinks; */ return 0; @@ -495,22 +858,27 @@ int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std int main (int argc, char * const argv[]) { - if (argc != 3) + if (argc != 4) { std::cerr << "Usage: " << argv[0] - << " nbP dim\n"; + << " nbP dim delta\n"; return 0; } int nbP = atoi(argv[1]); int dim = atoi(argv[2]); + double delta = atof(argv[3]); std::cout << "Let the carnage begin!\n"; Point_Vector point_vector; generate_points_random_box(point_vector, nbP, dim); + FT epsilon = point_sampling_radius_by_delaunay(point_vector); + std::cout << "Initial epsilon = " << epsilon << std::endl; Point_Vector L; std::vector chosen_landmarks; //write_points("landmarks/initial_pointset",point_vector); //write_points("landmarks/initial_landmarks",L); + CGAL::Timer timer; + /* for (int i = 0; i < 11; i++) //for (int i = 0; bl > 0; i++) { @@ -518,11 +886,29 @@ int main (int argc, char * const argv[]) double delta = pow(10, -(1.0*i)/2); std::cout << "delta = " << delta << std::endl; L = {}; chosen_landmarks = {}; - landmark_choice_protected_delaunay(point_vector, nbP, L, chosen_landmarks, delta); + std::vector> full_cells; + timer.start(); + landmark_choice_protected_delaunay(point_vector, nbP, L, chosen_landmarks, delta, full_cells); + timer.stop(); + FT epsilon2 = point_sampling_radius_by_delaunay(L); + std::cout << "Final epsilon = " << epsilon2 << ". Ratio = " << epsilon/epsilon2 << std::endl; + write_points("landmarks/initial_landmarks",L); int nbL = chosen_landmarks.size(); - std::cout << "Number of landmarks = " << nbL << std::endl; - landmark_perturbation(point_vector, nbL, L, chosen_landmarks); + std::cout << "Number of landmarks = " << nbL << ", time= " << timer.time() << "s"<< std::endl; + landmark_perturbation(point_vector, nbL, L, chosen_landmarks, full_cells); + timer.reset(); //write_points("landmarks/landmarks0",L); } - + */ + std::vector> full_cells; + timer.start(); + landmark_choice_protected_delaunay(point_vector, nbP, L, chosen_landmarks, delta, full_cells); + timer.stop(); + FT epsilon2 = point_sampling_radius_by_delaunay(L); + std::cout << "Final epsilon = " << epsilon2 << ". Ratio = " << epsilon/epsilon2 << std::endl; + write_points("landmarks/initial_landmarks",L); + int nbL = chosen_landmarks.size(); + std::cout << "Number of landmarks = " << nbL << ", time= " << timer.time() << "s"<< std::endl; + landmark_perturbation(point_vector, nbL, L, chosen_landmarks, full_cells); + timer.reset(); } diff --git a/src/Witness_complex/example/witness_complex_epsilon.cpp b/src/Witness_complex/example/witness_complex_epsilon.cpp index d091bdb7..7f8b985f 100644 --- a/src/Witness_complex/example/witness_complex_epsilon.cpp +++ b/src/Witness_complex/example/witness_complex_epsilon.cpp @@ -21,546 +21,35 @@ */ #include -#include -#include -#include -#include -#include -#include -#include +#include -#include -#include -//#include - -//#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Witness_complex.h" -#include "gudhi/reader_utils.h" -#include "Torus_distance.h" - -#include -#include -#include -#include #include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -#include -#include -#include -#include - -using namespace Gudhi; -//using namespace boost::filesystem; +#include typedef CGAL::Epick_d K; -typedef K::Point_d Point_d; -//typedef CGAL::Cartesian_d K; -//typedef CGAL::Point_d Point_d; -typedef K::FT FT; -typedef CGAL::Search_traits< - FT, Point_d, - typename K::Cartesian_const_iterator_d, - typename K::Construct_cartesian_const_iterator_d> Traits_base; -typedef CGAL::Euclidean_distance Euclidean_distance; - - -typedef std::vector< Vertex_handle > typeVectorVertex; - -//typedef std::pair typeSimplex; -//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; - -typedef CGAL::Search_traits_adapter< - std::ptrdiff_t, Point_d*, Traits_base> STraits; -//typedef K TreeTraits; -//typedef CGAL::Distance_adapter Euclidean_adapter; -//typedef CGAL::Kd_tree Kd_tree; -typedef CGAL::Orthogonal_k_neighbor_search> K_neighbor_search; -typedef K_neighbor_search::Tree Tree; -typedef K_neighbor_search::Distance Distance; -typedef K_neighbor_search::iterator KNS_iterator; -typedef K_neighbor_search::iterator KNS_range; -typedef boost::container::flat_map Point_etiquette_map; -typedef CGAL::Kd_tree Tree2; - -typedef CGAL::Fuzzy_sphere Fuzzy_sphere; - -typedef std::vector Point_Vector; - -//typedef K::Equal_d Equal_d; -//typedef CGAL::Random_points_in_cube_d > > Random_cube_iterator; -typedef CGAL::Random_points_in_cube_d Random_cube_iterator; -typedef CGAL::Random_points_in_ball_d Random_point_iterator; - -typedef CGAL::Delaunay_triangulation Delaunay_triangulation; -typedef Delaunay_triangulation::Facet Facet; -typedef CGAL::Sphere_d Sphere_d; - -bool toric=false; - - -/** - * \brief Customized version of read_points - * which takes into account a possible nbP first line - * - */ -inline void -read_points_cust ( std::string file_name , Point_Vector & points) -{ - std::ifstream in_file (file_name.c_str(),std::ios::in); - if(!in_file.is_open()) - { - std::cerr << "Unable to open file " << file_name << std::endl; - return; - } - std::string line; - double x; - while( getline ( in_file , line ) ) - { - std::vector< double > point; - std::istringstream iss( line ); - while(iss >> x) { point.push_back(x); } - Point_d p(point.begin(), point.end()); - if (point.size() != 1) - points.push_back(p); - } - in_file.close(); -} - -void generate_points_grid(Point_Vector& W, int width, int D) -{ - int nb_points = 1; - for (int i = 0; i < D; ++i) - nb_points *= width; - for (int i = 0; i < nb_points; ++i) - { - std::vector point; - int cell_i = i; - for (int l = 0; l < D; ++l) - { - point.push_back(0.01*(cell_i%width)); - cell_i /= width; - } - W.push_back(point); - } -} - -void generate_points_random_box(Point_Vector& W, int nbP, int dim) -{ - /* - Random_cube_iterator rp(dim, 1); - for (int i = 0; i < nbP; i++) - { - std::vector point; - for (auto it = rp->cartesian_begin(); it != rp->cartesian_end(); ++it) - point.push_back(*it); - W.push_back(Point_d(point)); - rp++; - } - */ - Random_cube_iterator rp(dim, 1.0); - for (int i = 0; i < nbP; i++) - { - W.push_back(*rp++); - } -} - - -void write_wl( std::string file_name, std::vector< std::vector > & WL) -{ - std::ofstream ofs (file_name, std::ofstream::out); - for (auto w : WL) - { - for (auto l: w) - ofs << l << " "; - ofs << "\n"; - } - ofs.close(); -} - - -void write_points( std::string file_name, std::vector< Point_d > & points) -{ - std::ofstream ofs (file_name, std::ofstream::out); - for (auto w : points) - { - for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) - ofs << *it << " "; - ofs << "\n"; - } - ofs.close(); -} - -void write_edges(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) -{ - std::ofstream ofs (file_name, std::ofstream::out); - for (auto u: witness_complex.complex_vertex_range()) - for (auto v: witness_complex.complex_vertex_range()) - { - typeVectorVertex edge = {u,v}; - if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) - { - for (auto it = landmarks[u].cartesian_begin(); it != landmarks[u].cartesian_end(); ++it) - ofs << *it << " "; - ofs << "\n"; - for (auto it = landmarks[v].cartesian_begin(); it != landmarks[v].cartesian_end(); ++it) - ofs << *it << " "; - ofs << "\n\n\n"; - } - } - ofs.close(); -} - - -/** Function that chooses landmarks from W and place it in the kd-tree L. - * Note: nbL hould be removed if the code moves to Witness_complex - */ -void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) -{ - std::cout << "Enter landmark choice to kd tree\n"; - int chosen_landmark; - Point_d* p; - CGAL::Random rand; - for (int i = 0; i < nbL; i++) - { - // while (!res.second) - // { - do chosen_landmark = rand.get_int(0,nbP); - while (std::count(landmarks_ind.begin(),landmarks_ind.end(),chosen_landmark)!=0); - //rand++; - //std::cout << "Chose " << chosen_landmark << std::endl; - p = &W[chosen_landmark]; - //L_i.emplace(chosen_landmark,i); - // } - landmarks.push_back(*p); - landmarks_ind.push_back(chosen_landmark); - //std::cout << "Added landmark " << chosen_landmark << std::endl; - } - } - -void insert_delaunay_landmark_with_copies(Point_Vector& W, int chosen_landmark, std::vector& landmarks_ind, Delaunay_triangulation& delaunay, int& landmark_count) -{ - delaunay.insert(W[chosen_landmark]); - landmarks_ind.push_back(chosen_landmark); - landmark_count++; -} - -bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, int D, FT delta) -{ - Euclidean_distance ed; - Delaunay_triangulation::Vertex_handle v; - Delaunay_triangulation::Face f(t.current_dimension()); - Delaunay_triangulation::Facet ft; - Delaunay_triangulation::Full_cell_handle c; - Delaunay_triangulation::Locate_type lt; - c = t.locate(p, lt, f, ft, v); - for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) - if (!t.is_infinite(fc_it)) - { - std::vector vertices; - for (auto v_it = fc_it->vertices_begin(); v_it != fc_it->vertices_end(); ++v_it) - vertices.push_back((*v_it)->point()); - Sphere_d cs(D, vertices.begin(), vertices.end()); - Point_d center_cs = cs.center(); - FT r = sqrt(ed.transformed_distance(center_cs, fc_it->vertex(1)->point())); - FT dist2 = ed.transformed_distance(center_cs, p); - //if the new point is inside the protection ball of a non conflicting simplex - if (dist2 >= r*r && dist2 <= (r+delta)*(r+delta)) - return true; - } - return false; -} - -bool triangulation_is_protected(Delaunay_triangulation& t, FT delta) -{ - Euclidean_distance ed; - int D = t.current_dimension(); - for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) - if (!t.is_infinite(fc_it)) - for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) - { - //check if vertex belongs to the face - bool belongs = false; - for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) - if (v_it == *fc_v_it) - { - belongs = true; - break; - } - if (!belongs) - { - std::vector vertices; - for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) - vertices.push_back((*fc_v_it)->point()); - Sphere_d cs(D, vertices.begin(), vertices.end()); - Point_d center_cs = cs.center(); - FT r = sqrt(ed.transformed_distance(center_cs, fc_it->vertex(1)->point())); - FT dist2 = ed.transformed_distance(center_cs, v_it->point()); - //if the new point is inside the protection ball of a non conflicting simplex - if (dist2 <= (r+delta)*(r+delta)) - return false; - } - } - return true; -} - -FT sampling_radius(Delaunay_triangulation& t) -{ - int D = t.current_dimension(); - FT epsilon2 = 4.0; - for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) - { - Point_Vector vertices; - for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) - vertices.push_back((*fc_v_it)->point()); - Sphere_d cs(D, vertices.begin(), vertices.end()); - FT r2 = Euclidean_distance().transformed_distance(cs.center(), *(vertices.begin())); - if (epsilon2 > r2) - epsilon2 = r2; - } - return sqrt(epsilon2); -} - -FT point_sampling_radius_by_delaunay(Point_Vector& points) -{ - Delaunay_triangulation t(points[0].size()); - t.insert(points.begin(), points.end()); - return sampling_radius(t); -} - -void landmark_choice_protected_delaunay(Point_Vector& W, int nbP, Point_Vector& landmarks, std::vector& landmarks_ind, FT delta) -{ - int D = W[0].size(); - Torus_distance td; - Euclidean_distance ed; - Delaunay_triangulation t(D); - CGAL::Random rand; - int landmark_count = 0; - std::list index_list; - // shuffle the list of indexes (via a vector) - { - std::vector temp_vector; - for (int i = 0; i < nbP; ++i) - temp_vector.push_back(i); - unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); - std::shuffle(temp_vector.begin(), temp_vector.end(), std::default_random_engine(seed)); - for (std::vector::iterator it = temp_vector.begin(); it != temp_vector.end(); ++it) - index_list.push_front(*it); - } - // add the first D+1 vertices to form one non-empty cell - for (int i = 0; i <= D+1; ++i) - { - insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count); - index_list.pop_front(); - } - // add other vertices if they don't violate protection - std::list::iterator list_it = index_list.begin(); - while (list_it != index_list.end()) - if (!is_violating_protection(W[*list_it], t, D, delta)) - { - // If no conflicts then insert in every copy of T^3 - insert_delaunay_landmark_with_copies(W, *list_it, landmarks_ind, t, landmark_count); - index_list.erase(list_it); - list_it = index_list.begin(); - } - else - list_it++; - for (std::vector::iterator it = landmarks_ind.begin(); it != landmarks_ind.end(); ++it) - landmarks.push_back(W[*it]); -} - - -int landmark_perturbation(Point_Vector &W, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) -{ - //******************** Preface: origin point - int D = W[0].size(); - std::vector orig_vector; - for (int i=0; i landmarks_ext; - int nb_cells = 1; - for (int i = 0; i < D; ++i) - nb_cells *= 3; - for (int i = 0; i < nb_cells; ++i) - for (int k = 0; k < nbL; ++k) - { - std::vector point; - int cell_i = i; - for (int l = 0; l < D; ++l) - { - point.push_back(landmarks[k][l] + 2.0*((cell_i%3)-1.0)); - cell_i /= 3; - } - landmarks_ext.push_back(point); - } - write_points("landmarks/initial_landmarks",landmarks_ext); - STraits traits(&(landmarks_ext[0])); - std::vector< std::vector > WL(nbP); - - //********************** Neighbor search in a Kd tree - Tree L(boost::counting_iterator(0), - boost::counting_iterator(nb_cells*nbL), - typename Tree::Splitter(), - traits); - std::cout << "Enter (D+1) nearest landmarks\n"; - for (int i = 0; i < nbP; i++) - { - Point_d& w = W[i]; - ////Search D+1 nearest neighbours from the tree of landmarks L - K_neighbor_search search(L, w, D+1, FT(0), true, - CGAL::Distance_adapter(&(landmarks_ext[0])) ); - for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) - { - if (std::find(WL[i].begin(), WL[i].end(), (it->first)%nbL) == WL[i].end()) - WL[i].push_back((it->first)%nbL); - } - if (i == landmarks_ind[WL[i][0]]) - { - FT dist = ed.transformed_distance(W[i], landmarks[WL[i][1]]); - if (dist < lambda) - lambda = dist; - } - } - std::string out_file = "wl_result"; - write_wl(out_file,WL); - - //******************** Constructng a witness complex - std::cout << "Entered witness complex construction\n"; - Witness_complex<> witnessComplex; - witnessComplex.setNbL(nbL); - witnessComplex.witness_complex(WL); - - //******************** Making a set of bad link landmarks - std::cout << "Entered bad links\n"; - std::set< int > perturbL; - int count_badlinks = 0; - //std::cout << "Bad links around "; - std::vector< int > count_bad(D); - std::vector< int > count_good(D); - for (auto u: witnessComplex.complex_vertex_range()) - { - if (!witnessComplex.has_good_link(u, count_bad, count_good)) - { - count_badlinks++; - Point_d& l = landmarks[u]; - Fuzzy_sphere fs(l, sqrt(lambda)*3, 0, traits); - std::vector curr_perturb; - L.search(std::insert_iterator>(curr_perturb,curr_perturb.begin()),fs); - for (int i: curr_perturb) - perturbL.insert(i%nbL); - } - } - for (unsigned int i = 0; i != count_good.size(); i++) - if (count_good[i] != 0) - std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; - for (unsigned int i = 0; i != count_bad.size(); i++) - if (count_bad[i] != 0) - std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; - std::cout << "\nBad links total: " << count_badlinks << " Points to perturb: " << perturbL.size() << std::endl; - - //*********************** Perturb bad link landmarks - for (auto u: perturbL) - { - Random_point_iterator rp(D,sqrt(lambda)/8); - std::vector point; - for (int i = 0; i < D; i++) - { - while (K().squared_distance_d_object()(*rp,origin) < lambda/256) - rp++; - FT coord = landmarks[u][i] + (*rp)[i]; - if (coord > 1) - point.push_back(coord-1); - else if (coord < -1) - point.push_back(coord+1); - else - point.push_back(coord); - } - landmarks[u] = Point_d(point); - } - std::cout << "lambda=" << lambda << std::endl; - char buffer[100]; - int i = sprintf(buffer,"stree_result.txt"); - - if (i >= 0) - { - std::string out_file = (std::string)buffer; - std::ofstream ofs (out_file, std::ofstream::out); - witnessComplex.st_to_file(ofs); - ofs.close(); - } - write_edges("landmarks/edges", witnessComplex, landmarks); - return count_badlinks; -} - - -int main (int argc, char * const argv[]) -{ - if (argc != 5) - { - std::cerr << "Usage: " << argv[0] - << " nbP nbL dim delta\n"; - return 0; - } - int nbP = atoi(argv[1]); - int nbL = atoi(argv[2]); - int dim = atoi(argv[3]); - FT delta = atof(argv[4]); - - std::cout << "Let the carnage begin!\n"; - Point_Vector point_vector; - generate_points_random_box(point_vector, nbP, dim); - FT epsilon = point_sampling_radius_by_delaunay(point_vector); - std::cout << "Initial epsilon = " << epsilon << std::endl; - Point_Vector L; - std::vector chosen_landmarks; - bool ok=false; - while (!ok) - { - ok = true; - L = {}; - chosen_landmarks = {}; - //landmark_choice_by_delaunay(point_vector, nbP, nbL, L, chosen_landmarks, delta); - landmark_choice_protected_delaunay(point_vector, nbP, L, chosen_landmarks, delta); - nbL = chosen_landmarks.size(); - std::cout << "Number of landmarks is " << nbL << std::endl; - //int width = (int)pow(nbL, 1.0/dim); landmark_choice_bcc(point_vector, nbP, width, L, chosen_landmarks); - for (auto i: chosen_landmarks) - { - ok = ok && (std::count(chosen_landmarks.begin(),chosen_landmarks.end(),i) == 1); - if (!ok) break; - } - - } - FT epsilon2 = point_sampling_radius_by_delaunay(L); - std::cout << "Final epsilon = " << epsilon2 << ". Ratio = " << epsilon/epsilon2 << std::endl; - int bl = nbL, curr_min = bl; - write_points("landmarks/initial_pointset",point_vector); - //write_points("landmarks/initial_landmarks",L); - //for (int i = 0; i < 1; i++) - for (int i = 0; bl > 0; i++) - { - std::cout << "========== Start iteration " << i << "== curr_min(" << curr_min << ")========\n"; - bl=landmark_perturbation(point_vector, nbL, L, chosen_landmarks); - if (bl < curr_min) - curr_min=bl; - write_points("landmarks/landmarks0",L); - } - +typedef K::Point_d Point_d; +typedef K::FT FT; +typedef K::Hyperplane_d Hyperplane_d; +typedef K::Has_on_positive_side_d Has_on_positive_side_d; + +int main () +{ + std::vector vertices; + Point_d v1(std::vector({-1,1})); + Point_d v2(std::vector({1,-1})); + vertices.push_back(v1); + vertices.push_back(v2); + Point_d p(std::vector({-1,-1})); + Hyperplane_d hp(vertices.begin(), vertices.end()); + //Hyperplane_d hp(vertices.begin(), vertices.end(), p, CGAL::ON_POSITIVE_SIDE); + if (Has_on_positive_side_d()(hp, p)) + std::cout << "OK\n"; + else + std::cout << "NOK\n"; + CGAL::Oriented_side side_p = K::Oriented_side_d()(hp, p); + if (side_p == CGAL::ZERO) + std::cout << "Point (-1,-1) is on the line passing through (-1,1) and (1,-1)"; + CGAL::Oriented_side side_v2 = K::Oriented_side_d()(hp, v2); + if (side_v2 != CGAL::ZERO) + std::cout << "Point (1,-1) is not on the line passing through (-1,1) and (1,-1)"; } -- cgit v1.2.3 From 62937147e40a7d2da7aa7a7a604808feeccaa75e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 25 Sep 2015 14:57:29 +0000 Subject: Add bitmap cubical complex git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@794 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 50d9b8eb80e0fe99f871afa5bdbb853add97e25e --- CMakeLists.txt | 3 + data/bitmap/CubicalOneSphere.txt | 12 + data/bitmap/CubicalTwoSphere.txt | 31 + .../example/Bitmap_cubical_complex.cpp | 69 ++ src/Bitmap_cubical_complex/example/CMakeLists.txt | 12 + .../example/Random_bitmap_cubical_complex.cpp | 85 +++ .../include/gudhi/Bitmap_cubical_complex.h | 706 +++++++++++++++++++++ .../include/gudhi/Bitmap_cubical_complex_base.h | 577 +++++++++++++++++ src/Bitmap_cubical_complex/include/gudhi/counter.h | 136 ++++ src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 623 ++++++++++++++++++ src/Bitmap_cubical_complex/test/CMakeLists.txt | 25 + src/CMakeLists.txt | 1 + 12 files changed, 2280 insertions(+) create mode 100644 data/bitmap/CubicalOneSphere.txt create mode 100644 data/bitmap/CubicalTwoSphere.txt create mode 100644 src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp create mode 100644 src/Bitmap_cubical_complex/example/CMakeLists.txt create mode 100644 src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp create mode 100644 src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/counter.h create mode 100644 src/Bitmap_cubical_complex/test/Bitmap_test.cpp create mode 100644 src/Bitmap_cubical_complex/test/CMakeLists.txt (limited to 'src') diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bea06e2..43e0558c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ else() message(STATUS "boost library dirs:" ${Boost_LIBRARY_DIRS}) include_directories(src/common/include/) + include_directories(src/Bitmap_cubical_complex/include/) include_directories(src/Bottleneck/include/) include_directories(src/Contraction/include/) include_directories(src/Hasse_complex/include/) @@ -74,6 +75,8 @@ else() add_subdirectory(src/Hasse_complex/example) add_subdirectory(src/Bottleneck/example) add_subdirectory(src/Bottleneck/test) + add_subdirectory(src/Bitmap_cubical_complex/example) + add_subdirectory(src/Bitmap_cubical_complex/test) # GudhUI add_subdirectory(src/GudhUI) diff --git a/data/bitmap/CubicalOneSphere.txt b/data/bitmap/CubicalOneSphere.txt new file mode 100644 index 00000000..4dec3fc6 --- /dev/null +++ b/data/bitmap/CubicalOneSphere.txt @@ -0,0 +1,12 @@ +2 +3 +3 +0 +0 +0 +0 +100 +0 +0 +0 +0 diff --git a/data/bitmap/CubicalTwoSphere.txt b/data/bitmap/CubicalTwoSphere.txt new file mode 100644 index 00000000..32f5d933 --- /dev/null +++ b/data/bitmap/CubicalTwoSphere.txt @@ -0,0 +1,31 @@ +3 +3 +3 +3 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +100 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp new file mode 100644 index 00000000..c0dbaf36 --- /dev/null +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -0,0 +1,69 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-Saclay (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 . + */ + +//for persistence algorithm +#include "gudhi/reader_utils.h" +#include "gudhi/Bitmap_cubical_complex.h" +#include "gudhi/Persistent_cohomology.h" + +#include + +using namespace Gudhi; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include + +using namespace std; + +int main(int argc, char** argv) { + cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbed in \ +the first line is a dimension D of a cubical complex. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if (argc != 2) { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style cubical complex at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex b(argv[1]); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + pcoh.init_coefficients(p); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology(min_persistence); + + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*) ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt new file mode 100644 index 00000000..05ef1319 --- /dev/null +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHISimplexTreeFromFile) + +add_executable ( Bitmap_cubical_complex Bitmap_cubical_complex.cpp ) +target_link_libraries(Bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) +add_test(Bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalOneSphere.txt) +add_test(Bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) + +add_executable ( Random_bitmap_cubical_complex Random_bitmap_cubical_complex.cpp ) +target_link_libraries(Random_bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) +add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap_cubical_complex 2 100 100) + diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp new file mode 100644 index 00000000..de9d96e0 --- /dev/null +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -0,0 +1,85 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 . + */ + + +//for persistence algorithm +#include "gudhi/reader_utils.h" +#include "gudhi/Bitmap_cubical_complex.h" +#include "gudhi/Persistent_cohomology.h" + +#include + +using namespace Gudhi; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include +#include +#include + +using namespace std; + +int main(int argc, char** argv) { + srand(time(0)); + + cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes. \ +The first parameter of the program is the dimension D of the cubical complex. The next D parameters are number of top dimensional cubes in each dimension of the cubical complex.\ +The program will create random cubical complex of that sizes and compute persistent homology of it." << endl; + + int p = 2; + double min_persistence = 0; + + size_t dimensionOfBitmap = (size_t) atoi(argv[1]); + std::vector< unsigned > sizes; + size_t multipliers = 1; + for (size_t dim = 0; dim != dimensionOfBitmap; ++dim) { + unsigned sizeInThisDimension = (unsigned) atoi(argv[2 + dim]); + sizes.push_back(sizeInThisDimension); + multipliers *= sizeInThisDimension; + } + + std::vector< double > data; + for (size_t i = 0; i != multipliers; ++i) { + data.push_back(rand() / (double) RAND_MAX); + } + + + + Bitmap_cubical_complex b(sizes, data); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + pcoh.init_coefficients(p); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology(min_persistence); + + + stringstream ss; + ss << "randomComplex_persistence"; + std::ofstream out((char*) ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h new file mode 100644 index 00000000..61ae8105 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -0,0 +1,706 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-Saclay (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 . + */ + +#ifndef BITMAP_CUBICAL_COMPLEX_H_ +#define BITMAP_CUBICAL_COMPLEX_H_ + +#include + +#include + +//global variable, was used just for debugging. +bool globalDbg = false; + +template +class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { + public: + //*********************************************************************************************************************************// + //Typedefs and typenames + //*********************************************************************************************************************************// + friend class Simplex_handle; + typedef size_t Simplex_key; + typedef T Filtration_value; + + + //*********************************************************************************************************************************// + //Simplex handle class + //*********************************************************************************************************************************// + + /** + * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. Elements of this class are: the pointer to the bitmap B in which the considered cell is + * together with a position of this cell in B. Given this data, one can get all the information about the considered cell. + **/ + class Simplex_handle { + public: + + Simplex_handle() { + if (globalDbg) { + cerr << "Simplex_handle()\n"; + } + this->b = 0; + this->position = 0; + } + + Simplex_handle(Bitmap_cubical_complex* b) { + if (globalDbg) { + cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; + } + this->b = b; + this->position = 0; + } + + Simplex_handle(const Simplex_handle& org) : b(org.b) { + if (globalDbg) { + cerr << "Simplex_handle( const Simplex_handle& org )\n"; + } + this->position = org.position; + } + + Simplex_handle& operator=(const Simplex_handle& rhs) { + if (globalDbg) { + cerr << "Simplex_handle operator = \n"; + } + this->position = rhs.position; + this->b = rhs.b; + return *this; + } + + Simplex_handle(Bitmap_cubical_complex* b, Simplex_key position) { + if (globalDbg) { + cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; + cerr << "Position : " << position << endl; + } + this->b = b; + this->position = position; + } + friend class Bitmap_cubical_complex; + private: + Bitmap_cubical_complex* b; + Simplex_key position; //Assumption -- this field always keep the REAL position of simplex in the bitmap, no matter what keys have been. + //to deal with the keys, the class Bitmap_cubical_complex have extra vectors: keyAssociatedToSimplex and simplexAssociatedToKey + //that allow to move between actual cell and the key assigned to it. + }; + + + //*********************************************************************************************************************************// + //Constructors + //*********************************************************************************************************************************// + //Over here we need to definie various input types. I am proposing the following ones: + //Perseus style + //H5 files? TODO + //binary files with little endiangs / big endians? TODO + //constructor from a vector of elements of a type T. TODO + + /** + * Constructor form a Perseus-style file. + **/ + Bitmap_cubical_complex(char* perseusStyleFile) : Bitmap_cubical_complex_base(perseusStyleFile) { + if (globalDbg) { + cerr << "Bitmap_cubical_complex( char* perseusStyleFile )\n"; + } + std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); + std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); + + for (size_t i = 0; i != this->totalNumberOfCells; ++i) { + keyAssociatedToSimplex[i] = simplexAssociatedToKey[i] = i; + } + this->keyAssociatedToSimplex = keyAssociatedToSimplex; + this->simplexAssociatedToKey = simplexAssociatedToKey; + //we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change some elements of the bitmap, then this procedure need + //to be called again. + this->initializeElementsOrderedAccordingToFiltration(); + } + + /** + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells in the following directions and vector of element of a type T + * with filtration on top dimensional cells. + **/ + Bitmap_cubical_complex(std::vector dimensions, std::vector topDimensionalCells) : Bitmap_cubical_complex_base(dimensions, topDimensionalCells) { + std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); + std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); + + for (size_t i = 0; i != this->totalNumberOfCells; ++i) { + keyAssociatedToSimplex[i] = simplexAssociatedToKey[i] = i; + } + this->keyAssociatedToSimplex = keyAssociatedToSimplex; + this->simplexAssociatedToKey = simplexAssociatedToKey; + //we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change some elements of the bitmap, then this procedure need + //to be called again. + this->initializeElementsOrderedAccordingToFiltration(); + } + + //*********************************************************************************************************************************// + //Other 'easy' functions + //*********************************************************************************************************************************// + + /** + * Returns number of all cubes in the complex. + **/ + size_t num_simplices()const { + return this->totalNumberOfCells; + } + + /** + * Returns a Simplex_handle to a cube that do not exist in this complex. + **/ + Simplex_handle null_simplex() { + return Simplex_handle(this, this->data.size()); + } + + /** + * Returns dimension of the complex. + **/ + size_t dimension() { + return this->sizes.size(); + } + + /** + * Return dimension of a cell pointed by the Simplex_handle. + **/ + size_t dimension(const Simplex_handle& sh) { + if (globalDbg) { + cerr << "int dimension(const Simplex_handle& sh)\n"; + } + if (sh.position != this->data.size()) return sh.b->get_dimension_of_a_cell(sh.position); + return std::numeric_limits::max(); + } + + /** + * Return the filtration of a cell pointed by the Simplex_handle. + **/ + T filtration(const Simplex_handle& sh) { + if (globalDbg) { + cerr << "T filtration(const Simplex_handle& sh)\n"; + } + //Returns the filtration value of a simplex. + if (sh.position != this->data.size()) return sh.b->data[ sh.position ]; + return INT_MAX; + } + + /** + * Return a key which is not a key of any cube in the considered data structure. + **/ + Simplex_key null_key() { + if (globalDbg) { + cerr << "Simplex_key null_key()\n"; + } + return this->data.size(); + } + + /** + * Return the key of a cube pointed by the Simplex_handle. + **/ + Simplex_key key(const Simplex_handle& sh) { + if (globalDbg) { + cerr << "Simplex_key key(const Simplex_handle& sh)\n"; + } + return sh.b->keyAssociatedToSimplex[ sh.position ]; + } + + /** + * Return the Simplex_handle given the key of the cube. + **/ + Simplex_handle simplex(Simplex_key key) { + if (globalDbg) { + cerr << "Simplex_handle simplex(Simplex_key key)\n"; + } + return Simplex_handle(this, this->simplexAssociatedToKey[ key ]); + } + + /** + * Assign key to a cube pointed by the Simplex_handle + **/ + void assign_key(Simplex_handle& sh, Simplex_key key) { + if (globalDbg) { + cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n"; + } + this->keyAssociatedToSimplex[sh.position] = key; + this->simplexAssociatedToKey[key] = sh.position; + } + + /** + * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. + **/ + void initializeElementsOrderedAccordingToFiltration(); + + + + //*********************************************************************************************************************************// + //Iterators + //*********************************************************************************************************************************// + + /** + * Boundary_simplex_iterator class allows iteration on boundary of each cube. + **/ + class Boundary_simplex_range; + + class Boundary_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { + //Iterator on the simplices belonging to the boundary of a simplex. + //value_type must be 'Simplex_handle'. + public: + + Boundary_simplex_iterator(Simplex_handle& sh) : sh(sh) { + if (globalDbg) { + cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n"; + } + this->position = 0; + this->boundaryElements = this->sh.b->get_boundary_of_a_cell(this->sh.position); + } + + Boundary_simplex_iterator operator++() { + if (globalDbg) { + cerr << "Boundary_simplex_iterator operator++()\n"; + } + ++this->position; + return *this; + } + + Boundary_simplex_iterator operator++(int) { + Boundary_simplex_iterator result = *this; + ++(*this); + return result; + } + + Boundary_simplex_iterator operator=(const Boundary_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "Boundary_simplex_iterator operator =\n"; + } + this->sh = rhs.sh; + this->boundaryElements.clear(); + this->boundaryElementsinsert(this->boundaryElements.end(), rhs.boundaryElements.begin(), rhs.boundaryElements.end()); + } + + bool operator==(const Boundary_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator ==\n"; + } + if (this->position == rhs.position) { + if (this->boundaryElements.size() != rhs.boundaryElements.size())return false; + for (size_t i = 0; i != this->boundaryElements.size(); ++i) { + if (this->boundaryElements[i] != rhs.boundaryElements[i])return false; + } + return true; + } + return false; + } + + bool operator!=(const Boundary_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator != \n"; + } + return !(*this == rhs); + } + + Simplex_handle operator*() { + if (globalDbg) { + cerr << "Simplex_handle operator*\n"; + } + return Simplex_handle(this->sh.b, this->boundaryElements[this->position]); + } + + friend class Boundary_simplex_range; + private: + Simplex_handle sh; + std::vector< size_t > boundaryElements; + size_t position; + }; + + /** + * Boundary_simplex_range class provides ranges for boundary iterators. + **/ + class Boundary_simplex_range { + //Range giving access to the simplices in the boundary of a simplex. + //.begin() and .end() return type Boundary_simplex_iterator. + public: + + Boundary_simplex_range(const Simplex_handle& sh) : sh(sh) { }; + + Boundary_simplex_iterator begin() { + if (globalDbg) { + cerr << "Boundary_simplex_iterator begin\n"; + } + Boundary_simplex_iterator it(this->sh); + return it; + } + + Boundary_simplex_iterator end() { + if (globalDbg) { + cerr << "Boundary_simplex_iterator end()\n"; + } + Boundary_simplex_iterator it(this->sh); + it.position = it.boundaryElements.size(); + return it; + } + private: + Simplex_handle sh; + }; + + + /** + * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. Secondary criteria for filtration are: + * (1) Dimension of a cube (lower dimensional comes first). + * (2) Position in the data structure (the ones that are earlies in the data structure comes first). + **/ + class Filtration_simplex_range; + + class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { + //Iterator over all simplices of the complex in the order of the indexing scheme. + //'value_type' must be 'Simplex_handle'. + public: + + Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { }; + + Filtration_simplex_iterator() : b(NULL) { }; + + Filtration_simplex_iterator operator++() { + if (globalDbg) { + cerr << "Filtration_simplex_iterator operator++\n"; + } + ++this->position; + return (*this); + } + + Filtration_simplex_iterator operator++(int) { + Filtration_simplex_iterator result = *this; + ++(*this); + return result; + } + + Filtration_simplex_iterator operator=(const Filtration_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "Filtration_simplex_iterator operator =\n"; + } + this->b = rhs.b; + this->position = rhs.position; + } + + bool operator==(const Filtration_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n"; + } + if (this->position == rhs.position) { + return true; + } + return false; + } + + bool operator!=(const Filtration_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n"; + } + return !(*this == rhs); + } + + Simplex_handle operator*() { + if (globalDbg) { + cerr << "Simplex_handle operator*()\n"; + } + return Simplex_handle(this->b, this->b->elementsOrderedAccordingToFiltration[ this->position ]); + } + + friend class Filtration_simplex_range; + private: + Bitmap_cubical_complex* b; + size_t position; + }; + + /** + * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. + **/ + class Filtration_simplex_range { + //Range over the simplices of the complex in the order of the filtration. + //.begin() and .end() return type Filtration_simplex_iterator. + public: + + Filtration_simplex_range(Bitmap_cubical_complex* b) : b(b) { }; + + Filtration_simplex_iterator begin() { + if (globalDbg) { + cerr << "Filtration_simplex_iterator begin() \n"; + } + return Filtration_simplex_iterator(this->b); + } + + Filtration_simplex_iterator end() { + if (globalDbg) { + cerr << "Filtration_simplex_iterator end()\n"; + } + Filtration_simplex_iterator it(this->b); + it.position = this->b->elementsOrderedAccordingToFiltration.size(); + return it; + } + private: + Bitmap_cubical_complex* b; + }; + + + + //*********************************************************************************************************************************// + //Methods to access iterators from the container: + + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class that provides ranges for the Boundary_simplex_iterator. + **/ + Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) { + if (globalDbg) { + cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n"; + } + //Returns a range giving access to all simplices of the boundary of a simplex, i.e. the set of codimension 1 subsimplices of the Simplex. + return Boundary_simplex_range(sh); + } + + /** + * filtration_simplex_range creates an object of a Filtration_simplex_range class that provides ranges for the Filtration_simplex_iterator. + **/ + Filtration_simplex_range filtration_simplex_range() { + if (globalDbg) { + cerr << "Filtration_simplex_range filtration_simplex_range()\n"; + } + //Returns a range over the simplices of the complex in the order of the filtration + return Filtration_simplex_range(this); + } + //*********************************************************************************************************************************// + + + + //*********************************************************************************************************************************// + //Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are there. + //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so I understand that this is something that was planned (for simplicial maps?) + //but was never finished. The only idea I have here is to use the same empty structure from IndexingTag.h file, but only if the compiler needs it. If the compiler + //do not need it, then I would rather not add here elements which I do not understand. + //typedef Indexing_tag + + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + std::pair endpoints(Simplex_handle sh) { + std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh.position); + if (globalDbg) { + cerr << "std::pair endpoints( Simplex_handle sh )\n"; + cerr << "bdry.size() : " << bdry.size() << endl; + } + //this method returns two first elements from the boundary of sh. + if (bdry.size() < 2)throw ("Error in endpoints in Bitmap_cubical_complex class. The cell for which this method was called have less than two elements in the boundary."); + return std::make_pair(Simplex_handle(this, bdry[0]), Simplex_handle(this, bdry[1])); + } + + + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range; + + class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { + //Iterator over all simplices of the complex in the order of the indexing scheme. + //'value_type' must be 'Simplex_handle'. + public: + + Skeleton_simplex_iterator(Bitmap_cubical_complex* b, size_t d) : b(b), dimension(d) { + if (globalDbg) { + cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n"; + } + //find the position of the first simplex of a dimension d + this->position = 0; + while ((this->position != b->data.size()) && (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { + ++this->position; + } + }; + + Skeleton_simplex_iterator() : b(NULL), dimension(0) { }; + + Skeleton_simplex_iterator operator++() { + if (globalDbg) { + cerr << "Skeleton_simplex_iterator operator++()\n"; + } + //increment the position as long as you did not get to the next element of the dimension dimension. + ++this->position; + while ((this->position != this->b->data.size()) && (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { + ++this->position; + } + return (*this); + } + + Skeleton_simplex_iterator operator++(int) { + Skeleton_simplex_iterator result = *this; + ++(*this); + return result; + } + + Skeleton_simplex_iterator operator=(const Skeleton_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "Skeleton_simplex_iterator operator =\n"; + } + this->b = rhs.b; + this->position = rhs.position; + } + + bool operator==(const Skeleton_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator ==\n"; + } + if (this->position == rhs.position) { + return true; + } + return false; + } + + bool operator!=(const Skeleton_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n"; + } + return !(*this == rhs); + } + + Simplex_handle operator*() { + if (globalDbg) { + cerr << "Simplex_handle operator*() \n"; + } + return Simplex_handle(this->b, this->position); + } + + friend class Skeleton_simplex_range; + private: + Bitmap_cubical_complex* b; + size_t position; + int dimension; + }; + + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range { + //Range over the simplices of the complex in the order of the filtration. + //.begin() and .end() return type Filtration_simplex_iterator. + public: + + Skeleton_simplex_range(Bitmap_cubical_complex* b, int dimension) : b(b), dimension(dimension) { }; + + Skeleton_simplex_iterator begin() { + if (globalDbg) { + cerr << "Skeleton_simplex_iterator begin()\n"; + } + return Skeleton_simplex_iterator(this->b, this->dimension); + } + + Skeleton_simplex_iterator end() { + if (globalDbg) { + cerr << "Skeleton_simplex_iterator end()\n"; + } + Skeleton_simplex_iterator it(this->b, this->dimension); + it.position = this->b->data.size(); + return it; + } + private: + Bitmap_cubical_complex* b; + int dimension; + }; + + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + Skeleton_simplex_range skeleton_simplex_range(int dimension) { + if (globalDbg) { + cerr << "Skeleton_simplex_range skeleton_simplex_range( int dimension )\n"; + } + return Skeleton_simplex_range(this, dimension); + } + + + + //*********************************************************************************************************************************// + //functions used for debugging: + + /** + * Function used for debugging purposes. + **/ + void printKeyAssociatedToSimplex() { + for (size_t i = 0; i != this->data.size(); ++i) { + cerr << i << " -> " << this->simplexAssociatedToKey[i] << endl; + } + } + + /** + * Function used for debugging purposes. + **/ + size_t printRealPosition(const Simplex_handle& sh) { + return sh.position; + } + + private: + std::vector< size_t > keyAssociatedToSimplex; + std::vector< size_t > simplexAssociatedToKey; + std::vector< size_t > elementsOrderedAccordingToFiltration; //needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. +}; //Bitmap_cubical_complex + +template +bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< size_t, std::pair< T, char > >& f, const std::pair< size_t, std::pair< T, char > >& s) { + if (globalDbg) { + cerr << "ompareElementsForElementsOrderedAccordingToFiltration\n"; + } + if (f.second.first < s.second.first) { + return true; + } else { + if (f.second.first > s.second.first) { + return false; + } else { + //in this case f.second.first == s.second.first, and we use dimension to compare: + if (f.second.second < s.second.second) { + return true; + } else { + if (f.second.second > s.second.second) { + return false; + } else { + //in this case, both the filtration value and the dimensions for those cells are the same. Since it may be nice to have a stable sorting procedure, in this case, we compare positions in the bitmap: + return ( f.first < s.first); + } + } + } + } +} + +template +void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() { + if (globalDbg) { + cerr << "void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() \n"; + } + //( position , (filtration , dimension) ) + std::vector< std::pair< size_t, std::pair< T, char > > > dataOfElementsFromBitmap(this->data.size()); + for (size_t i = 0; i != this->data.size(); ++i) { + //TODO -- this can be optimized by having a counter here. We do not need to re-compute the dimension for every cell from scratch + dataOfElementsFromBitmap[i] = std::make_pair(i, std::make_pair(this->data[i], this->get_dimension_of_a_cell(i))); + } + std::sort(dataOfElementsFromBitmap.begin(), dataOfElementsFromBitmap.end(), compareElementsForElementsOrderedAccordingToFiltration); + + std::vector< size_t > elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap(this->data.size()); + for (size_t i = 0; i != dataOfElementsFromBitmap.size(); ++i) { + elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap[i] = dataOfElementsFromBitmap[i].first; + } + this->elementsOrderedAccordingToFiltration = elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap; +} + + +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// + +#endif // BITMAP_CUBICAL_COMPLEX_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h new file mode 100644 index 00000000..26c97872 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -0,0 +1,577 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-Saclay (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 . + */ + +#ifndef BITMAP_CUBICAL_COMPLEX_BASE_H_ +#define BITMAP_CUBICAL_COMPLEX_BASE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +/** + * This is a class implementing a basic bitmap data structure to store cubical complexes. It implements only the most basic subroutines. + * The idea of the bitmap is the following. Our aim is to have a memory efficient data structure to store d-dimensional cubical complex C being a cubical decomposition + * of a rectangular region of a space. This is achieved by storing C as a vector of bits (this is where the name 'bitmap' came from). Each cell is represented by a single + * bit (in case of black and white bitmaps, or by a single element of a type T (here T is a filtration type of a bitmap, typically a double). All the informations needed for homology and + * persistent homology computations (like dimension of a cell, boundary and coboundary elements of a cell, are then obtained from the position of the element in C. + */ +template +class Bitmap_cubical_complex_base { + public: + /** + * There are a few constructors of a Bitmap_cubical_complex_base class. First one, that takes vector, creates an empty bitmap of a dimension equal to the number of elements in the + * input vector and size in the i-th dimension equal the number in the position i-of the input vector. + */ + Bitmap_cubical_complex_base(std::vector sizes_); + /** + * The second constructor takes as a input a Perseus style file. For more details, please consult the documentations of Perseus software as well as examples attached to this + * implementation. + **/ + Bitmap_cubical_complex_base(char* perseusStyleFile_); + /** + * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) together with vector of filtration values of top dimensional cells. + **/ + Bitmap_cubical_complex_base(std::vector dimensions_, std::vector topDimensionalCells_); + + /** + * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell and get_cell_data are the basic functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a non-negative integer, indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to the positions of (co)boundary element of the input cell. + */ + inline std::vector< size_t > get_boundary_of_a_cell(size_t cell_); + /** + * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell and get_cell_data are the basic functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a non-negative integer, indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to the positions of (co)boundary element of the input cell. + **/ + inline std::vector< size_t > get_coboundary_of_a_cell(size_t cell_); + /** + * In the case of get_dimension_of_a_cell function, the output is a non-negative integer indicating the dimension of a cell. + **/ + inline unsigned get_dimension_of_a_cell(size_t cell_); + /** + * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. + **/ + inline T& get_cell_data(size_t cell_); + + + /** + * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. Then, there are a few ways one can pick the filtration of lower dimensional + * cells. The most typical one is by so called lower star filtration. This function is always called by any constructor which takes the top dimensional cells. If you use such a constructor, + * then there is no need to call this function. Call it only if you are putting the filtration of the cells by your own (for instance by using topDimensionalCellsIterator). + **/ + void impose_lower_star_filtration(); //assume that top dimensional cells are already set. + + /** + * Returns dimension of a complex. + **/ + inline unsigned dimension() { + return sizes.size(); + } + + /** + * Returns number of all cubes in the data structure. + **/ + inline unsigned size_of_bitmap() { + return this->data.size(); + } + + /** + * Writing to stream operator. + **/ + template + friend ostream& operator<<(ostream & os_, const Bitmap_cubical_complex_base& b_); + + //ITERATORS + + /** + * Iterator through all cells in the complex (in order they appear in the structure -- i.e. in lexicographical order). + **/ + typedef typename std::vector< T >::iterator all_cells_iterator; + + all_cells_iterator all_cells_begin()const { + return this->data.begin(); + } + + all_cells_iterator all_cells_end()const { + return this->data.end(); + } + + + typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + + all_cells_const_iterator all_cells_const_begin()const { + return this->data.begin(); + } + + all_cells_const_iterator all_cells_const_end()const { + return this->data.end(); + } + + /** + * Iterator through top dimensional cells of the complex. The cells appear in order they are stored in the structure (i.e. in lexicographical order) + **/ + class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > { + public: + + Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b_) : b(b_) { + for (size_t i = 0; i != b_.dimension(); ++i) { + this->counter.push_back(0); + } + } + + Top_dimensional_cells_iterator operator++() { + //first find first element of the counter that can be increased: + size_t dim = 0; + while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1))++dim; + + if (dim != this->b.dimension()) { + ++this->counter[dim]; + for (size_t i = 0; i != dim; ++i) { + this->counter[i] = 0; + } + } else { + ++this->counter[0]; + } + return *this; + } + + Top_dimensional_cells_iterator operator++(int) { + Top_dimensional_cells_iterator result = *this; + ++(*this); + return result; + } + + Top_dimensional_cells_iterator operator=(const Top_dimensional_cells_iterator& rhs_) { + this->counter = rhs_.counter; + this->b = rhs_.b; + return *this; + } + + bool operator==(const Top_dimensional_cells_iterator& rhs_) { + if (&this->b != &rhs_.b)return false; + if (this->counter.size() != rhs_.counter.size())return false; + for (size_t i = 0; i != this->counter.size(); ++i) { + if (this->counter[i] != rhs_.counter[i])return false; + } + return true; + } + + bool operator!=(const Top_dimensional_cells_iterator& rhs_) { + return !(*this == rhs_); + } + + T& operator*() { + //given the counter, compute the index in the array and return this element. + unsigned index = 0; + for (size_t i = 0; i != this->counter.size(); ++i) { + index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; + } + return this->b.data[index]; + } + + size_t computeIndexInBitmap() { + size_t index = 0; + for (size_t i = 0; i != this->counter.size(); ++i) { + index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; + } + return index; + } + + void printCounter() { + for (size_t i = 0; i != this->counter.size(); ++i) { + cout << this->counter[i] << " "; + } + } + friend class Bitmap_cubical_complex_base; + protected: + std::vector< unsigned > counter; + Bitmap_cubical_complex_base& b; + }; + + Top_dimensional_cells_iterator top_dimensional_cells_begin() { + Top_dimensional_cells_iterator a(*this); + return a; + } + + Top_dimensional_cells_iterator top_dimensional_cells_end() { + Top_dimensional_cells_iterator a(*this); + for (size_t i = 0; i != this->dimension(); ++i) { + a.counter[i] = this->sizes[i] - 1; + } + a.counter[0]++; + return a; + } + + + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + + + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + + protected: + std::vector sizes; + std::vector multipliers; + std::vector data; + size_t totalNumberOfCells; + + void set_up_containers(std::vector sizes_) { + unsigned multiplier = 1; + for (size_t i = 0; i != sizes_.size(); ++i) { + this->sizes.push_back(sizes_[i]); + this->multipliers.push_back(multiplier); + //multiplier *= 2*(sizes[i]+1)+1; + multiplier *= 2 * sizes_[i] + 1; + } + //std::reverse( this->sizes.begin() , this->sizes.end() ); + std::vector data(multiplier); + std::fill(data.begin(), data.end(), INT_MAX); + this->totalNumberOfCells = multiplier; + this->data = data; + } + + size_t compute_position_in_bitmap(std::vector< int > counter_) { + size_t position = 0; + for (size_t i = 0; i != this->multipliers.size(); ++i) { + position += this->multipliers[i] * counter_[i]; + } + return position; + } + + std::vector compute_counter_for_given_cell(size_t cell_) { + std::vector counter; + for (size_t dim = this->sizes.size(); dim != 0; --dim) { + counter.push_back(cell_ / this->multipliers[dim - 1]); + cell_ = cell_ % this->multipliers[dim - 1]; + } + std::reverse(counter.begin(), counter.end()); + return counter; + } + + std::vector< size_t > generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_); +}; + +template +ostream& operator<<(ostream & out_, const Bitmap_cubical_complex_base& b_) { + //for ( typename bitmap::all_cells_const_iterator it = b.all_cells_const_begin() ; it != b.all_cells_const_end() ; ++it ) + for (typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b_.all_cells_const_begin(); it != b_.all_cells_const_end(); ++it) { + out_ << *it << " "; + } + return out_; +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizes_) { + this->set_up_containers(sizes_); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizesInFollowingDirections_, std::vector topDimensionalCells_) { + this->set_up_containers(sizesInFollowingDirections_); + + size_t numberOfTopDimensionalElements = 1; + for (size_t i = 0; i != sizesInFollowingDirections_.size(); ++i) { + numberOfTopDimensionalElements *= sizesInFollowingDirections_[i]; + } + if (numberOfTopDimensionalElements != topDimensionalCells_.size()) { + cerr << "Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from sizesInFollowingDirections vector is different than the size of topDimensionalCells vector." << endl; + throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from sizesInFollowingDirections vector is different than the size of topDimensionalCells vector."); + } + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + size_t index = 0; + for (it = this->top_dimensional_cells_begin(); it != this->top_dimensional_cells_end(); ++it) { + (*it) = topDimensionalCells_[index]; + ++index; + } + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFile_) { + bool dbg = false; + ifstream inFiltration, inIds; + inFiltration.open(perseusStyleFile_); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + if (dbg) { + cerr << "dimensionOfData : " << dimensionOfData << endl; + } + + std::vector sizes; + for (size_t i = 0; i != dimensionOfData; ++i) { + int sizeInThisDimension; + inFiltration >> sizeInThisDimension; + sizeInThisDimension = abs(sizeInThisDimension); + sizes.push_back(sizeInThisDimension); + if (dbg) { + cerr << "sizeInThisDimension : " << sizeInThisDimension << endl; + } + } + this->set_up_containers(sizes); + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_begin(); + + //TODO -- over here we also need to read id's of cell and put them to bitmapElement structure! + while (!inFiltration.eof()) { + double filtrationLevel; + inFiltration >> filtrationLevel; + if (dbg) { + cerr << "Cell of an index : " << it.computeIndexInBitmap() << " and dimension: " << this->get_dimension_of_a_cell(it.computeIndexInBitmap()) << " get the value : " << filtrationLevel << endl; + } + *it = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); +} + +template +std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(size_t cell_) { + bool bdg = false; + //first of all, we need to take the list of coordinates in which the cell has nonzero length. We do it by using modified version to compute dimension of a cell: + std::vector< unsigned > dimensionsInWhichCellHasNonzeroLength; + unsigned dimension = 0; + size_t cell1 = cell_; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / multipliers[i - 1]; + if (position % 2 == 1) { + dimensionsInWhichCellHasNonzeroLength.push_back(i - 1); + dimension++; + } + cell1 = cell1 % multipliers[i - 1]; + } + + if (bdg) { + cerr << "dimensionsInWhichCellHasNonzeroLength : \n"; + for (size_t i = 0; i != dimensionsInWhichCellHasNonzeroLength.size(); ++i) { + cerr << dimensionsInWhichCellHasNonzeroLength[i] << endl; + } + getchar(); + } + + std::vector< size_t > boundaryElements; + if (dimensionsInWhichCellHasNonzeroLength.size() == 0)return boundaryElements; + for (size_t i = 0; i != dimensionsInWhichCellHasNonzeroLength.size(); ++i) { + boundaryElements.push_back(cell_ - multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); + boundaryElements.push_back(cell_ + multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); + + if (bdg) cerr << "multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; + if (bdg) cerr << "cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; + if (bdg) cerr << "cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; + } + return boundaryElements; +} + +template +std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(size_t cell_) { + bool bdg = false; + //first of all, we need to take the list of coordinates in which the cell has nonzero length. We do it by using modified version to compute dimension of a cell: + std::vector< unsigned > dimensionsInWhichCellHasZeroLength; + unsigned dimension = 0; + size_t cell1 = cell_; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / multipliers[i - 1]; + if (position % 2 == 0) { + dimensionsInWhichCellHasZeroLength.push_back(i - 1); + dimension++; + } + cell1 = cell1 % multipliers[i - 1]; + } + + std::vector counter = this->compute_counter_for_given_cell(cell_); + //reverse(counter.begin() , counter.end()); + + if (bdg) { + cerr << "dimensionsInWhichCellHasZeroLength : \n"; + for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { + cerr << dimensionsInWhichCellHasZeroLength[i] << endl; + } + cerr << "\n counter : " << endl; + for (size_t i = 0; i != counter.size(); ++i) { + cerr << counter[i] << endl; + } + getchar(); + } + + std::vector< size_t > coboundaryElements; + if (dimensionsInWhichCellHasZeroLength.size() == 0)return coboundaryElements; + for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { + if (bdg) { + cerr << "Dimension : " << i << endl; + if (counter[dimensionsInWhichCellHasZeroLength[i]] == 0) { + cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + } + if (counter[dimensionsInWhichCellHasZeroLength[i]] == 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]]) { + cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + } + } + + + if ((cell_ > multipliers[dimensionsInWhichCellHasZeroLength[i]]) && (counter[dimensionsInWhichCellHasZeroLength[i]] != 0)) + //if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 0 ) + { + if (bdg)cerr << "Subtracting : " << cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]] << endl; + coboundaryElements.push_back(cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]]); + } + if ((cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] < this->data.size()) && (counter[dimensionsInWhichCellHasZeroLength[i]] != 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]])) + //if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 2*this->sizes[dimensionsInWhichCellHasZeroLength[i]] ) + { + coboundaryElements.push_back(cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]]); + if (bdg)cerr << "Adding : " << cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] << endl; + } + } + return coboundaryElements; +} + +template +unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell(size_t cell_) { + bool dbg = false; + if (dbg)cerr << "\n\n\n Computing position o a cell of an index : " << cell_ << endl; + unsigned dimension = 0; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell_ / multipliers[i - 1]; + + if (dbg)cerr << "i-1 :" << i - 1 << endl; + if (dbg)cerr << "cell_ : " << cell_ << endl; + if (dbg)cerr << "position : " << position << endl; + if (dbg)cerr << "multipliers[" << i - 1 << "] = " << multipliers[i - 1] << endl; + if (dbg)getchar(); + + if (position % 2 == 1) { + if (dbg)cerr << "Nonzero length in this direction \n"; + dimension++; + } + cell_ = cell_ % multipliers[i - 1]; + } + return dimension; +} + +template +T& Bitmap_cubical_complex_base::get_cell_data(size_t cell_) { + return this->data[cell_]; +} + +template +void Bitmap_cubical_complex_base::impose_lower_star_filtration() { + bool dbg = false; + + //this vector will be used to check which elements have already been taken care of in imposing lower star filtration: + std::vector isThisCellConsidered(this->data.size(), false); + + std::vector indicesToConsider; + //we assume here that we already have a filtration on the top dimensional cells and we have to extend it to lower ones. + typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + for (it = this->top_dimensional_cells_begin(); it != this->top_dimensional_cells_end(); ++it) { + indicesToConsider.push_back(it.computeIndexInBitmap()); + } + + while (indicesToConsider.size()) { + if (dbg) { + cerr << "indicesToConsider in this iteration \n"; + for (size_t i = 0; i != indicesToConsider.size(); ++i) { + cout << indicesToConsider[i] << " "; + } + getchar(); + } + std::vector newIndicesToConsider; + for (size_t i = 0; i != indicesToConsider.size(); ++i) { + std::vector bd = this->get_boundary_of_a_cell(indicesToConsider[i]); + for (size_t boundaryIt = 0; boundaryIt != bd.size(); ++boundaryIt) { + if (this->data[ bd[boundaryIt] ] > this->data[ indicesToConsider[i] ]) { + this->data[ bd[boundaryIt] ] = this->data[ indicesToConsider[i] ]; + } + if (isThisCellConsidered[ bd[boundaryIt] ] == false) { + newIndicesToConsider.push_back(bd[boundaryIt]); + isThisCellConsidered[ bd[boundaryIt] ] = true; + } + } + } + indicesToConsider.swap(newIndicesToConsider); + } +} + +template +std::vector< size_t > Bitmap_cubical_complex_base::generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_) { + bool dbg = false; + if (this->sizes.size() != directionsForPeriodicBCond_.size())throw "directionsForPeriodicBCond_ vector size is different from the size of the bitmap. The program will now terminate \n"; + + std::vector sizes(this->sizes.size()); + for (size_t i = 0; i != this->sizes.size(); ++i)sizes[i] = 2 * this->sizes[i]; + + counter c(sizes); + + std::vector< size_t > result; + + for (size_t i = 0; i != this->data.size(); ++i) { + size_t position; + if (!c.isFinal()) { + position = i; + //result.push_back( i ); + } else { + std::vector< bool > finals = c.directionsOfFinals(); + bool jumpInPosition = false; + for (size_t dir = 0; dir != finals.size(); ++dir) { + if (finals[dir] == false)continue; + if (directionsForPeriodicBCond_[dir]) { + jumpInPosition = true; + } + } + if (jumpInPosition == true) { + //in this case this guy is final, so we need to find 'the opposite one' + position = compute_position_in_bitmap(c.findOpposite(directionsForPeriodicBCond_)); + } else { + position = i; + } + } + result.push_back(position); + if (dbg) { + cerr << " position : " << position << endl; + cerr << c << endl; + getchar(); + } + + c.increment(); + } + + return result; +} + +#endif // BITMAP_CUBICAL_COMPLEX_BASE_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/counter.h b/src/Bitmap_cubical_complex/include/gudhi/counter.h new file mode 100644 index 00000000..9df819b2 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/counter.h @@ -0,0 +1,136 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-Saclay (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 . + */ + +#ifndef COUNTER_H_ +#define COUNTER_H_ + +#include +#include + +using namespace std; + +/** + * This is an implementation of a simple counter. It is needed for the implementation of a bitmapCubicalComplex. + **/ + +class counter { + public: + + /** + * Constructor of a counter class. It takes only the parameter which is the end value of the counter. The default beginning value is a vector of the same length as the endd, filled-in with zeros. + **/ + counter(std::vector< int > endd) { + for (size_t i = 0; i != endd.size(); ++i) { + this->current.push_back(0); + this->begin.push_back(0); + this->end.push_back(endd[i]); + } + } + + /** + * Constructor of a counter class. It takes as the input beginn and end vector. It assumes that begin vector is lexicographically below the end vector. + **/ + counter(std::vector< int > beginn, std::vector< int > endd) { + if (beginn.size() != endd.size())throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; + for (size_t i = 0; i != endd.size(); ++i) { + this->current.push_back(0); + this->begin.push_back(0); + this->end.push_back(endd[i]); + } + } + + /** + * Function to increment the counter. If the value returned by the function is true, then the incrementation process was successful. + * If the value of the function is false, that means, that the counter have reached its end-value. + **/ + bool increment() { + size_t i = 0; + while ((i != this->end.size()) && (this->current[i] == this->end[i])) { + ++i; + } + + if (i == this->end.size())return false; + ++this->current[i]; + for (size_t j = 0; j != i; ++j) { + this->current[j] = this->begin[j]; + } + return true; + } + + /** + * Function to check if we are at the end of counter. + **/ + bool isFinal() { + for (size_t i = 0; i != this->current.size(); ++i) { + if (this->current[i] == this->end[i])return true; + } + return false; + } + + /** + * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. Its aim is to find an counter corresponding to the element the following + * boundary element is identified with when periodic boundary conditions are imposed. + **/ + std::vector< int > findOpposite(std::vector< bool > directionsForPeriodicBCond) { + std::vector< int > result; + for (size_t i = 0; i != this->current.size(); ++i) { + if ((this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true)) { + result.push_back(this->begin[i]); + } else { + result.push_back(this->current[i]); + } + } + return result; + } + + /** + * Function checking at which positions the current value of a counter is the final value of the counter. + **/ + std::vector< bool > directionsOfFinals() { + std::vector< bool > result; + for (size_t i = 0; i != this->current.size(); ++i) { + if (this->current[i] == this->end[i]) { + result.push_back(true); + } else { + result.push_back(false); + } + } + return result; + } + + /** + * Function to write counter to the stream. + **/ + friend std::ostream& operator<<(std::ostream& out, const counter& c) { + //cerr << "c.current.size() : " << c.current.size() << endl; + for (size_t i = 0; i != c.current.size(); ++i) { + out << c.current[i] << " "; + } + return out; + } + private: + std::vector< int > begin; + std::vector< int > end; + std::vector< int > current; +}; + +#endif // COUNTER_H_ diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp new file mode 100644 index 00000000..1c204bae --- /dev/null +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -0,0 +1,623 @@ +#include "gudhi/Bitmap_cubical_complex.h" + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "cubical_complex" +#include + +using namespace std; + +BOOST_AUTO_TEST_CASE(check_dimension) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + BOOST_CHECK(increasing.dimension() == 2); +} + +BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { + std::vector< double > expectedFiltrationValues1; + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(100); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + + std::vector< double > expectedFiltrationValues2; + expectedFiltrationValues2.push_back(1); + expectedFiltrationValues2.push_back(2); + expectedFiltrationValues2.push_back(3); + expectedFiltrationValues2.push_back(4); + expectedFiltrationValues2.push_back(5); + expectedFiltrationValues2.push_back(6); + expectedFiltrationValues2.push_back(7); + expectedFiltrationValues2.push_back(8); + expectedFiltrationValues2.push_back(9); + + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector< double > oneDimensionalCycle; + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(100); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle); + + + int i = 0; + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { + BOOST_CHECK(*it == expectedFiltrationValues2[i]); + ++i; + } + i = 0; + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { + BOOST_CHECK(*it == expectedFiltrationValues1[i]); + ++i; + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { + + std::vector boundary0; + std::vector boundary1; + boundary1.push_back(0); + boundary1.push_back(2); + std::vector boundary2; + std::vector boundary3; + boundary3.push_back(2); + boundary3.push_back(4); + std::vector boundary4; + std::vector boundary5; + boundary5.push_back(4); + boundary5.push_back(6); + std::vector boundary6; + std::vector boundary7; + boundary7.push_back(0); + boundary7.push_back(14); + std::vector boundary8; + boundary8.push_back(1); + boundary8.push_back(15); + boundary8.push_back(7); + boundary8.push_back(9); + std::vector boundary9; + boundary9.push_back(2); + boundary9.push_back(16); + std::vector boundary10; + boundary10.push_back(3); + boundary10.push_back(17); + boundary10.push_back(9); + boundary10.push_back(11); + std::vector boundary11; + boundary11.push_back(4); + boundary11.push_back(18); + std::vector boundary12; + boundary12.push_back(5); + boundary12.push_back(19); + boundary12.push_back(11); + boundary12.push_back(13); + std::vector boundary13; + boundary13.push_back(6); + boundary13.push_back(20); + std::vector boundary14; + std::vector boundary15; + boundary15.push_back(14); + boundary15.push_back(16); + std::vector boundary16; + std::vector boundary17; + boundary17.push_back(16); + boundary17.push_back(18); + std::vector boundary18; + std::vector boundary19; + boundary19.push_back(18); + boundary19.push_back(20); + std::vector boundary20; + std::vector boundary21; + boundary21.push_back(14); + boundary21.push_back(28); + std::vector boundary22; + boundary22.push_back(15); + boundary22.push_back(29); + boundary22.push_back(21); + boundary22.push_back(23); + std::vector boundary23; + boundary23.push_back(16); + boundary23.push_back(30); + std::vector boundary24; + boundary24.push_back(17); + boundary24.push_back(31); + boundary24.push_back(23); + boundary24.push_back(25); + std::vector boundary25; + boundary25.push_back(18); + boundary25.push_back(32); + std::vector boundary26; + boundary26.push_back(19); + boundary26.push_back(33); + boundary26.push_back(25); + boundary26.push_back(27); + std::vector boundary27; + boundary27.push_back(20); + boundary27.push_back(34); + std::vector boundary28; + std::vector boundary29; + boundary29.push_back(28); + boundary29.push_back(30); + std::vector boundary30; + std::vector boundary31; + boundary31.push_back(30); + boundary31.push_back(32); + std::vector boundary32; + std::vector boundary33; + boundary33.push_back(32); + boundary33.push_back(34); + std::vector boundary34; + std::vector boundary35; + boundary35.push_back(28); + boundary35.push_back(42); + std::vector boundary36; + boundary36.push_back(29); + boundary36.push_back(43); + boundary36.push_back(35); + boundary36.push_back(37); + std::vector boundary37; + boundary37.push_back(30); + boundary37.push_back(44); + std::vector boundary38; + boundary38.push_back(31); + boundary38.push_back(45); + boundary38.push_back(37); + boundary38.push_back(39); + std::vector boundary39; + boundary39.push_back(32); + boundary39.push_back(46); + std::vector boundary40; + boundary40.push_back(33); + boundary40.push_back(47); + boundary40.push_back(39); + boundary40.push_back(41); + std::vector boundary41; + boundary41.push_back(34); + boundary41.push_back(48); + std::vector boundary42; + std::vector boundary43; + boundary43.push_back(42); + boundary43.push_back(44); + std::vector boundary44; + std::vector boundary45; + boundary45.push_back(44); + boundary45.push_back(46); + std::vector boundary46; + std::vector boundary47; + boundary47.push_back(46); + boundary47.push_back(48); + std::vector boundary48; + std::vector< std::vector > boundaries; + boundaries.push_back(boundary0); + boundaries.push_back(boundary1); + boundaries.push_back(boundary2); + boundaries.push_back(boundary3); + boundaries.push_back(boundary4); + boundaries.push_back(boundary5); + boundaries.push_back(boundary6); + boundaries.push_back(boundary7); + boundaries.push_back(boundary8); + boundaries.push_back(boundary9); + boundaries.push_back(boundary10); + boundaries.push_back(boundary11); + boundaries.push_back(boundary12); + boundaries.push_back(boundary13); + boundaries.push_back(boundary14); + boundaries.push_back(boundary15); + boundaries.push_back(boundary16); + boundaries.push_back(boundary17); + boundaries.push_back(boundary18); + boundaries.push_back(boundary19); + boundaries.push_back(boundary20); + boundaries.push_back(boundary21); + boundaries.push_back(boundary22); + boundaries.push_back(boundary23); + boundaries.push_back(boundary24); + boundaries.push_back(boundary25); + boundaries.push_back(boundary26); + boundaries.push_back(boundary27); + boundaries.push_back(boundary28); + boundaries.push_back(boundary29); + boundaries.push_back(boundary30); + boundaries.push_back(boundary31); + boundaries.push_back(boundary32); + boundaries.push_back(boundary33); + boundaries.push_back(boundary34); + boundaries.push_back(boundary35); + boundaries.push_back(boundary36); + boundaries.push_back(boundary37); + boundaries.push_back(boundary38); + boundaries.push_back(boundary39); + boundaries.push_back(boundary40); + boundaries.push_back(boundary41); + boundaries.push_back(boundary42); + boundaries.push_back(boundary43); + boundaries.push_back(boundary44); + boundaries.push_back(boundary45); + boundaries.push_back(boundary46); + boundaries.push_back(boundary47); + boundaries.push_back(boundary48); + + + + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); + for (size_t j = 0; j != bd.size(); ++j) { + BOOST_CHECK(boundaries[i][j] == bd[j]); + } + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + + std::vector coboundaryElements; + coboundaryElements.push_back(7); + coboundaryElements.push_back(1); + coboundaryElements.push_back(8); + coboundaryElements.push_back(9); + coboundaryElements.push_back(1); + coboundaryElements.push_back(3); + coboundaryElements.push_back(10); + coboundaryElements.push_back(11); + coboundaryElements.push_back(3); + coboundaryElements.push_back(5); + coboundaryElements.push_back(12); + coboundaryElements.push_back(13); + coboundaryElements.push_back(5); + coboundaryElements.push_back(8); + coboundaryElements.push_back(8); + coboundaryElements.push_back(10); + coboundaryElements.push_back(10); + coboundaryElements.push_back(12); + coboundaryElements.push_back(12); + coboundaryElements.push_back(7); + coboundaryElements.push_back(21); + coboundaryElements.push_back(15); + coboundaryElements.push_back(8); + coboundaryElements.push_back(22); + coboundaryElements.push_back(9); + coboundaryElements.push_back(23); + coboundaryElements.push_back(15); + coboundaryElements.push_back(17); + coboundaryElements.push_back(10); + coboundaryElements.push_back(24); + coboundaryElements.push_back(11); + coboundaryElements.push_back(25); + coboundaryElements.push_back(17); + coboundaryElements.push_back(19); + coboundaryElements.push_back(12); + coboundaryElements.push_back(26); + coboundaryElements.push_back(13); + coboundaryElements.push_back(27); + coboundaryElements.push_back(19); + coboundaryElements.push_back(22); + coboundaryElements.push_back(22); + coboundaryElements.push_back(24); + coboundaryElements.push_back(24); + coboundaryElements.push_back(26); + coboundaryElements.push_back(26); + coboundaryElements.push_back(21); + coboundaryElements.push_back(35); + coboundaryElements.push_back(29); + coboundaryElements.push_back(22); + coboundaryElements.push_back(36); + coboundaryElements.push_back(23); + coboundaryElements.push_back(37); + coboundaryElements.push_back(29); + coboundaryElements.push_back(31); + coboundaryElements.push_back(24); + coboundaryElements.push_back(38); + coboundaryElements.push_back(25); + coboundaryElements.push_back(39); + coboundaryElements.push_back(31); + coboundaryElements.push_back(33); + coboundaryElements.push_back(26); + coboundaryElements.push_back(40); + coboundaryElements.push_back(27); + coboundaryElements.push_back(41); + coboundaryElements.push_back(33); + coboundaryElements.push_back(36); + coboundaryElements.push_back(36); + coboundaryElements.push_back(38); + coboundaryElements.push_back(38); + coboundaryElements.push_back(40); + coboundaryElements.push_back(40); + coboundaryElements.push_back(35); + coboundaryElements.push_back(43); + coboundaryElements.push_back(36); + coboundaryElements.push_back(37); + coboundaryElements.push_back(43); + coboundaryElements.push_back(45); + coboundaryElements.push_back(38); + coboundaryElements.push_back(39); + coboundaryElements.push_back(45); + coboundaryElements.push_back(47); + coboundaryElements.push_back(40); + coboundaryElements.push_back(41); + coboundaryElements.push_back(47); + size_t number = 0; + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + std::vector< size_t > bd = increasing.get_coboundary_of_a_cell(i); + for (size_t j = 0; j != bd.size(); ++j) { + BOOST_CHECK(coboundaryElements[number] == bd[j]); + ++number; + } + + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + std::vector dim; + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + BOOST_CHECK(increasing.get_dimension_of_a_cell(i) == dim[i]); + } +} + +BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + std::vector< unsigned > dim; + dim.push_back(0); + dim.push_back(0); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + + std::vector fil; + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(5); + fil.push_back(5); + fil.push_back(5); + fil.push_back(5); + fil.push_back(6); + fil.push_back(6); + fil.push_back(6); + fil.push_back(6); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(8); + fil.push_back(8); + fil.push_back(8); + fil.push_back(8); + fil.push_back(9); + fil.push_back(9); + fil.push_back(9); + fil.push_back(9); + + + Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range(); + size_t position = 0; + for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { + BOOST_CHECK(increasing.dimension(*it) == dim[position]); + BOOST_CHECK(increasing.filtration(*it) == fil[position]); + ++position; + } +} diff --git a/src/Bitmap_cubical_complex/test/CMakeLists.txt b/src/Bitmap_cubical_complex/test/CMakeLists.txt new file mode 100644 index 00000000..97c374e6 --- /dev/null +++ b/src/Bitmap_cubical_complex/test/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHIBitmapCCUT) + +if (GCOVR_PATH) + # for gcovr to make coverage reports - Corbera Jenkins plugin + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fprofile-arcs -ftest-coverage") +endif() +if (GPROF_PATH) + # for gprof to make coverage reports - Jenkins + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pg") +endif() + +add_executable ( BitmapCCUT Bitmap_test.cpp ) +target_link_libraries(BitmapCCUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + +# Unitary tests +add_test(NAME BitmapCCUT + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/BitmapCCUT + # XML format for Jenkins xUnit plugin + --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/BitmapCCUT.xml --log_level=test_suite --report_level=no) + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 545b0b58..576ba353 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,6 +44,7 @@ else() add_subdirectory(example/Contraction) add_subdirectory(example/Hasse_complex) add_subdirectory(example/Bottleneck) + add_subdirectory(example/Bitmap_cubical_complex) # GudhUI add_subdirectory(GudhUI) -- cgit v1.2.3 From dd2a15d1a8d2607848527513210330baebce9e8e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 25 Sep 2015 16:07:20 +0000 Subject: cpplint fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@795 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 94efebf169656da3179640ce9c02e8416cc75a18 --- .../example/Bitmap_cubical_complex.cpp | 30 ++- .../example/Random_bitmap_cubical_complex.cpp | 28 +- .../include/gudhi/Bitmap_cubical_complex.h | 294 +++++++++++---------- .../include/gudhi/Bitmap_cubical_complex_base.h | 144 +++++----- src/Bitmap_cubical_complex/include/gudhi/counter.h | 23 +- 5 files changed, 277 insertions(+), 242 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index c0dbaf36..37c16618 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -20,33 +20,35 @@ * along with this program. If not, see . */ -//for persistence algorithm -#include "gudhi/reader_utils.h" -#include "gudhi/Bitmap_cubical_complex.h" -#include "gudhi/Persistent_cohomology.h" +// for persistence algorithm +#include +#include +#include #include -using namespace Gudhi; -using namespace Gudhi::persistent_cohomology; - -//standard stuff +// standard stuff #include #include +using namespace Gudhi; +using namespace Gudhi::persistent_cohomology; using namespace std; int main(int argc, char** argv) { - cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbed in \ -the first line is a dimension D of a cubical complex. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes " + "provided in text files in Perseus style (the only numbed in the first line is a dimension D of a cubical " + "complex. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N " + "denote product of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of " + "top dimensional cells. We assume that the cells are in the lexicographical order. See CubicalOneSphere.txt or " + "CubicalTwoSphere.txt for example." << endl; int p = 2; double min_persistence = 0; if (argc != 2) { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style cubical complex at the input. The program will now terminate.\n"; + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style cubical complex at the " + "input. The program will now terminate.\n"; return 1; } @@ -55,7 +57,7 @@ lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for exam // Compute the persistence diagram of the complex persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); - pcoh.init_coefficients(p); //initilizes the coefficient field for homology + pcoh.init_coefficients(p); // initializes the coefficient field for homology pcoh.compute_persistent_cohomology(min_persistence); diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index de9d96e0..ac7557ce 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -21,31 +21,31 @@ */ -//for persistence algorithm -#include "gudhi/reader_utils.h" -#include "gudhi/Bitmap_cubical_complex.h" -#include "gudhi/Persistent_cohomology.h" +// for persistence algorithm +#include +#include +#include #include -using namespace Gudhi; -using namespace Gudhi::persistent_cohomology; - -//standard stuff +// standard stuff #include #include #include #include #include +using namespace Gudhi; +using namespace Gudhi::persistent_cohomology; using namespace std; int main(int argc, char** argv) { srand(time(0)); - cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes. \ -The first parameter of the program is the dimension D of the cubical complex. The next D parameters are number of top dimensional cubes in each dimension of the cubical complex.\ -The program will create random cubical complex of that sizes and compute persistent homology of it." << endl; + cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes. " + "The first parameter of the program is the dimension D of the cubical complex. The next D parameters are number " + "of top dimensional cubes in each dimension of the cubical complex. The program will create random cubical " + "complex of that sizes and compute persistent homology of it." << endl; int p = 2; double min_persistence = 0; @@ -64,17 +64,13 @@ The program will create random cubical complex of that sizes and compute persist data.push_back(rand() / (double) RAND_MAX); } - - Bitmap_cubical_complex b(sizes, data); - // Compute the persistence diagram of the complex persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); - pcoh.init_coefficients(p); //initilizes the coefficient field for homology + pcoh.init_coefficients(p); // initializes the coefficient field for homology pcoh.compute_persistent_cohomology(min_persistence); - stringstream ss; ss << "randomComplex_persistence"; std::ofstream out((char*) ss.str().c_str()); diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 61ae8105..2f8cb0a3 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -23,38 +23,41 @@ #ifndef BITMAP_CUBICAL_COMPLEX_H_ #define BITMAP_CUBICAL_COMPLEX_H_ -#include - #include -//global variable, was used just for debugging. +#include +#include // for pair +#include // for sort +#include // for vector + +// global variable, was used just for debugging. bool globalDbg = false; template class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { public: - //*********************************************************************************************************************************// - //Typedefs and typenames - //*********************************************************************************************************************************// + //******************************************************************************************************************// + // Typedefs and typenames + //******************************************************************************************************************// friend class Simplex_handle; typedef size_t Simplex_key; typedef T Filtration_value; - //*********************************************************************************************************************************// - //Simplex handle class - //*********************************************************************************************************************************// + //******************************************************************************************************************// + // Simplex handle class + //******************************************************************************************************************// /** - * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. Elements of this class are: the pointer to the bitmap B in which the considered cell is - * together with a position of this cell in B. Given this data, one can get all the information about the considered cell. + * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. Elements of this + * class are: the pointer to the bitmap B in which the considered cell is together with a position of this cell in B. + * Given this data, one can get all the information about the considered cell. **/ class Simplex_handle { public: - Simplex_handle() { if (globalDbg) { - cerr << "Simplex_handle()\n"; + std::cerr << "Simplex_handle()\n"; } this->b = 0; this->position = 0; @@ -62,7 +65,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Simplex_handle(Bitmap_cubical_complex* b) { if (globalDbg) { - cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; + std::cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; } this->b = b; this->position = 0; @@ -70,14 +73,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Simplex_handle(const Simplex_handle& org) : b(org.b) { if (globalDbg) { - cerr << "Simplex_handle( const Simplex_handle& org )\n"; + std::cerr << "Simplex_handle( const Simplex_handle& org )\n"; } this->position = org.position; } Simplex_handle& operator=(const Simplex_handle& rhs) { if (globalDbg) { - cerr << "Simplex_handle operator = \n"; + std::cerr << "Simplex_handle operator = \n"; } this->position = rhs.position; this->b = rhs.b; @@ -86,8 +89,8 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Simplex_handle(Bitmap_cubical_complex* b, Simplex_key position) { if (globalDbg) { - cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; - cerr << "Position : " << position << endl; + std::cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; + std::cerr << "Position : " << position << std::endl; } this->b = b; this->position = position; @@ -95,27 +98,28 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { friend class Bitmap_cubical_complex; private: Bitmap_cubical_complex* b; - Simplex_key position; //Assumption -- this field always keep the REAL position of simplex in the bitmap, no matter what keys have been. - //to deal with the keys, the class Bitmap_cubical_complex have extra vectors: keyAssociatedToSimplex and simplexAssociatedToKey - //that allow to move between actual cell and the key assigned to it. + Simplex_key position; + // Assumption -- this field always keep the REAL position of simplex in the bitmap, no matter what keys have been. + // to deal with the keys, the class Bitmap_cubical_complex have extra vectors: keyAssociatedToSimplex and + // simplexAssociatedToKey that allow to move between actual cell and the key assigned to it. }; - //*********************************************************************************************************************************// - //Constructors - //*********************************************************************************************************************************// - //Over here we need to definie various input types. I am proposing the following ones: - //Perseus style - //H5 files? TODO - //binary files with little endiangs / big endians? TODO - //constructor from a vector of elements of a type T. TODO + //******************************************************************************************************************// + // Constructors + //******************************************************************************************************************// + // Over here we need to definie various input types. I am proposing the following ones: + // Perseus style + // TODO(Pawel Dlotko): H5 files? + // TODO(Pawel Dlotko): binary files with little endiangs / big endians? + // TODO(Pawel Dlotko): constructor from a vector of elements of a type T. /** * Constructor form a Perseus-style file. **/ Bitmap_cubical_complex(char* perseusStyleFile) : Bitmap_cubical_complex_base(perseusStyleFile) { if (globalDbg) { - cerr << "Bitmap_cubical_complex( char* perseusStyleFile )\n"; + std::cerr << "Bitmap_cubical_complex( char* perseusStyleFile )\n"; } std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); @@ -125,16 +129,17 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { } this->keyAssociatedToSimplex = keyAssociatedToSimplex; this->simplexAssociatedToKey = simplexAssociatedToKey; - //we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change some elements of the bitmap, then this procedure need - //to be called again. + // we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change + // some elements of the bitmap, then this procedure need to be called again. this->initializeElementsOrderedAccordingToFiltration(); } /** - * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells in the following directions and vector of element of a type T - * with filtration on top dimensional cells. + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells in the + * following directions and vector of element of a type T with filtration on top dimensional cells. **/ - Bitmap_cubical_complex(std::vector dimensions, std::vector topDimensionalCells) : Bitmap_cubical_complex_base(dimensions, topDimensionalCells) { + Bitmap_cubical_complex(std::vector dimensions, std::vector topDimensionalCells) + : Bitmap_cubical_complex_base(dimensions, topDimensionalCells) { std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); @@ -143,14 +148,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { } this->keyAssociatedToSimplex = keyAssociatedToSimplex; this->simplexAssociatedToKey = simplexAssociatedToKey; - //we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change some elements of the bitmap, then this procedure need - //to be called again. + // we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change + // some elements of the bitmap, then this procedure need to be called again. this->initializeElementsOrderedAccordingToFiltration(); } - //*********************************************************************************************************************************// - //Other 'easy' functions - //*********************************************************************************************************************************// + //******************************************************************************************************************// + // Other 'easy' functions + //******************************************************************************************************************// /** * Returns number of all cubes in the complex. @@ -178,7 +183,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ size_t dimension(const Simplex_handle& sh) { if (globalDbg) { - cerr << "int dimension(const Simplex_handle& sh)\n"; + std::cerr << "int dimension(const Simplex_handle& sh)\n"; } if (sh.position != this->data.size()) return sh.b->get_dimension_of_a_cell(sh.position); return std::numeric_limits::max(); @@ -189,9 +194,9 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ T filtration(const Simplex_handle& sh) { if (globalDbg) { - cerr << "T filtration(const Simplex_handle& sh)\n"; + std::cerr << "T filtration(const Simplex_handle& sh)\n"; } - //Returns the filtration value of a simplex. + // Returns the filtration value of a simplex. if (sh.position != this->data.size()) return sh.b->data[ sh.position ]; return INT_MAX; } @@ -201,7 +206,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ Simplex_key null_key() { if (globalDbg) { - cerr << "Simplex_key null_key()\n"; + std::cerr << "Simplex_key null_key()\n"; } return this->data.size(); } @@ -211,7 +216,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ Simplex_key key(const Simplex_handle& sh) { if (globalDbg) { - cerr << "Simplex_key key(const Simplex_handle& sh)\n"; + std::cerr << "Simplex_key key(const Simplex_handle& sh)\n"; } return sh.b->keyAssociatedToSimplex[ sh.position ]; } @@ -221,7 +226,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ Simplex_handle simplex(Simplex_key key) { if (globalDbg) { - cerr << "Simplex_handle simplex(Simplex_key key)\n"; + std::cerr << "Simplex_handle simplex(Simplex_key key)\n"; } return Simplex_handle(this, this->simplexAssociatedToKey[ key ]); } @@ -231,7 +236,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ void assign_key(Simplex_handle& sh, Simplex_key key) { if (globalDbg) { - cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n"; + std::cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n"; } this->keyAssociatedToSimplex[sh.position] = key; this->simplexAssociatedToKey[key] = sh.position; @@ -244,9 +249,9 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { - //*********************************************************************************************************************************// - //Iterators - //*********************************************************************************************************************************// + //******************************************************************************************************************// + // Iterators + //******************************************************************************************************************// /** * Boundary_simplex_iterator class allows iteration on boundary of each cube. @@ -254,13 +259,12 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { class Boundary_simplex_range; class Boundary_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - //Iterator on the simplices belonging to the boundary of a simplex. - //value_type must be 'Simplex_handle'. + // Iterator on the simplices belonging to the boundary of a simplex. + // value_type must be 'Simplex_handle'. public: - Boundary_simplex_iterator(Simplex_handle& sh) : sh(sh) { if (globalDbg) { - cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n"; + std::cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n"; } this->position = 0; this->boundaryElements = this->sh.b->get_boundary_of_a_cell(this->sh.position); @@ -268,7 +272,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Boundary_simplex_iterator operator++() { if (globalDbg) { - cerr << "Boundary_simplex_iterator operator++()\n"; + std::cerr << "Boundary_simplex_iterator operator++()\n"; } ++this->position; return *this; @@ -282,16 +286,17 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Boundary_simplex_iterator operator=(const Boundary_simplex_iterator& rhs) { if (globalDbg) { - cerr << "Boundary_simplex_iterator operator =\n"; + std::cerr << "Boundary_simplex_iterator operator =\n"; } this->sh = rhs.sh; this->boundaryElements.clear(); - this->boundaryElementsinsert(this->boundaryElements.end(), rhs.boundaryElements.begin(), rhs.boundaryElements.end()); + this->boundaryElementsinsert(this->boundaryElements.end(), + rhs.boundaryElements.begin(), rhs.boundaryElements.end()); } bool operator==(const Boundary_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator ==\n"; + std::cerr << "bool operator ==\n"; } if (this->position == rhs.position) { if (this->boundaryElements.size() != rhs.boundaryElements.size())return false; @@ -305,14 +310,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { bool operator!=(const Boundary_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator != \n"; + std::cerr << "bool operator != \n"; } return !(*this == rhs); } Simplex_handle operator*() { if (globalDbg) { - cerr << "Simplex_handle operator*\n"; + std::cerr << "Simplex_handle operator*\n"; } return Simplex_handle(this->sh.b, this->boundaryElements[this->position]); } @@ -328,15 +333,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { * Boundary_simplex_range class provides ranges for boundary iterators. **/ class Boundary_simplex_range { - //Range giving access to the simplices in the boundary of a simplex. - //.begin() and .end() return type Boundary_simplex_iterator. + // Range giving access to the simplices in the boundary of a simplex. + // .begin() and .end() return type Boundary_simplex_iterator. public: - - Boundary_simplex_range(const Simplex_handle& sh) : sh(sh) { }; + Boundary_simplex_range(const Simplex_handle& sh) : sh(sh) { } Boundary_simplex_iterator begin() { if (globalDbg) { - cerr << "Boundary_simplex_iterator begin\n"; + std::cerr << "Boundary_simplex_iterator begin\n"; } Boundary_simplex_iterator it(this->sh); return it; @@ -344,12 +348,13 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Boundary_simplex_iterator end() { if (globalDbg) { - cerr << "Boundary_simplex_iterator end()\n"; + std::cerr << "Boundary_simplex_iterator end()\n"; } Boundary_simplex_iterator it(this->sh); it.position = it.boundaryElements.size(); return it; } + private: Simplex_handle sh; }; @@ -363,17 +368,16 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { class Filtration_simplex_range; class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - //Iterator over all simplices of the complex in the order of the indexing scheme. - //'value_type' must be 'Simplex_handle'. + // Iterator over all simplices of the complex in the order of the indexing scheme. + // 'value_type' must be 'Simplex_handle'. public: + Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { } - Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { }; - - Filtration_simplex_iterator() : b(NULL) { }; + Filtration_simplex_iterator() : b(NULL) { } Filtration_simplex_iterator operator++() { if (globalDbg) { - cerr << "Filtration_simplex_iterator operator++\n"; + std::cerr << "Filtration_simplex_iterator operator++\n"; } ++this->position; return (*this); @@ -387,7 +391,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Filtration_simplex_iterator operator=(const Filtration_simplex_iterator& rhs) { if (globalDbg) { - cerr << "Filtration_simplex_iterator operator =\n"; + std::cerr << "Filtration_simplex_iterator operator =\n"; } this->b = rhs.b; this->position = rhs.position; @@ -395,7 +399,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { bool operator==(const Filtration_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n"; + std::cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n"; } if (this->position == rhs.position) { return true; @@ -405,14 +409,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { bool operator!=(const Filtration_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n"; + std::cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n"; } return !(*this == rhs); } Simplex_handle operator*() { if (globalDbg) { - cerr << "Simplex_handle operator*()\n"; + std::cerr << "Simplex_handle operator*()\n"; } return Simplex_handle(this->b, this->b->elementsOrderedAccordingToFiltration[ this->position ]); } @@ -427,22 +431,21 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. **/ class Filtration_simplex_range { - //Range over the simplices of the complex in the order of the filtration. - //.begin() and .end() return type Filtration_simplex_iterator. + // Range over the simplices of the complex in the order of the filtration. + // .begin() and .end() return type Filtration_simplex_iterator. public: - - Filtration_simplex_range(Bitmap_cubical_complex* b) : b(b) { }; + Filtration_simplex_range(Bitmap_cubical_complex* b) : b(b) { } Filtration_simplex_iterator begin() { if (globalDbg) { - cerr << "Filtration_simplex_iterator begin() \n"; + std::cerr << "Filtration_simplex_iterator begin() \n"; } return Filtration_simplex_iterator(this->b); } Filtration_simplex_iterator end() { if (globalDbg) { - cerr << "Filtration_simplex_iterator end()\n"; + std::cerr << "Filtration_simplex_iterator end()\n"; } Filtration_simplex_iterator it(this->b); it.position = this->b->elementsOrderedAccordingToFiltration.size(); @@ -454,40 +457,44 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { - //*********************************************************************************************************************************// - //Methods to access iterators from the container: + //******************************************************************************************************************// + // Methods to access iterators from the container: /** * boundary_simplex_range creates an object of a Boundary_simplex_range class that provides ranges for the Boundary_simplex_iterator. **/ Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) { if (globalDbg) { - cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n"; + std::cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n"; } - //Returns a range giving access to all simplices of the boundary of a simplex, i.e. the set of codimension 1 subsimplices of the Simplex. + // Returns a range giving access to all simplices of the boundary of a simplex, i.e. the set of + // codimension 1 subsimplices of the Simplex. return Boundary_simplex_range(sh); } /** - * filtration_simplex_range creates an object of a Filtration_simplex_range class that provides ranges for the Filtration_simplex_iterator. + * filtration_simplex_range creates an object of a Filtration_simplex_range class that provides ranges for the + * Filtration_simplex_iterator. **/ Filtration_simplex_range filtration_simplex_range() { if (globalDbg) { - cerr << "Filtration_simplex_range filtration_simplex_range()\n"; + std::cerr << "Filtration_simplex_range filtration_simplex_range()\n"; } - //Returns a range over the simplices of the complex in the order of the filtration + // Returns a range over the simplices of the complex in the order of the filtration return Filtration_simplex_range(this); } - //*********************************************************************************************************************************// + //******************************************************************************************************************// - //*********************************************************************************************************************************// - //Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are there. - //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so I understand that this is something that was planned (for simplicial maps?) - //but was never finished. The only idea I have here is to use the same empty structure from IndexingTag.h file, but only if the compiler needs it. If the compiler - //do not need it, then I would rather not add here elements which I do not understand. - //typedef Indexing_tag + //******************************************************************************************************************// + // Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are + // there. + // TODO(Pawel Dlotko): The file IndexingTag.h in the Gudhi library contains an empty structure, so I understand that + // this is something that was planned (for simplicial maps?) but was never finished. The only idea I have here is + // to use the same empty structure from IndexingTag.h file, but only if the compiler needs it. If the compiler + // do not need it, then I would rather not add here elements which I do not understand. + // typedef Indexing_tag /** * Function needed for compatibility with Gudhi. Not useful for other purposes. @@ -495,11 +502,13 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { std::pair endpoints(Simplex_handle sh) { std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh.position); if (globalDbg) { - cerr << "std::pair endpoints( Simplex_handle sh )\n"; - cerr << "bdry.size() : " << bdry.size() << endl; + std::cerr << "std::pair endpoints( Simplex_handle sh )\n"; + std::cerr << "bdry.size() : " << bdry.size() << std::endl; } - //this method returns two first elements from the boundary of sh. - if (bdry.size() < 2)throw ("Error in endpoints in Bitmap_cubical_complex class. The cell for which this method was called have less than two elements in the boundary."); + // this method returns two first elements from the boundary of sh. + if (bdry.size() < 2) + throw("Error in endpoints in Bitmap_cubical_complex class. " + "The cell for which this method was called have less than two elements in the boundary."); return std::make_pair(Simplex_handle(this, bdry[0]), Simplex_handle(this, bdry[1])); } @@ -510,30 +519,31 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { class Skeleton_simplex_range; class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - //Iterator over all simplices of the complex in the order of the indexing scheme. - //'value_type' must be 'Simplex_handle'. + // Iterator over all simplices of the complex in the order of the indexing scheme. + // 'value_type' must be 'Simplex_handle'. public: - Skeleton_simplex_iterator(Bitmap_cubical_complex* b, size_t d) : b(b), dimension(d) { if (globalDbg) { - cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n"; + std::cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n"; } - //find the position of the first simplex of a dimension d + // find the position of the first simplex of a dimension d this->position = 0; - while ((this->position != b->data.size()) && (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { + while ((this->position != b->data.size()) && + (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { ++this->position; } - }; + } - Skeleton_simplex_iterator() : b(NULL), dimension(0) { }; + Skeleton_simplex_iterator() : b(NULL), dimension(0) { } Skeleton_simplex_iterator operator++() { if (globalDbg) { - cerr << "Skeleton_simplex_iterator operator++()\n"; + std::cerr << "Skeleton_simplex_iterator operator++()\n"; } - //increment the position as long as you did not get to the next element of the dimension dimension. + // increment the position as long as you did not get to the next element of the dimension dimension. ++this->position; - while ((this->position != this->b->data.size()) && (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { + while ((this->position != this->b->data.size()) && + (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { ++this->position; } return (*this); @@ -547,7 +557,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Skeleton_simplex_iterator operator=(const Skeleton_simplex_iterator& rhs) { if (globalDbg) { - cerr << "Skeleton_simplex_iterator operator =\n"; + std::cerr << "Skeleton_simplex_iterator operator =\n"; } this->b = rhs.b; this->position = rhs.position; @@ -555,7 +565,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { bool operator==(const Skeleton_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator ==\n"; + std::cerr << "bool operator ==\n"; } if (this->position == rhs.position) { return true; @@ -565,14 +575,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { bool operator!=(const Skeleton_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n"; + std::cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n"; } return !(*this == rhs); } Simplex_handle operator*() { if (globalDbg) { - cerr << "Simplex_handle operator*() \n"; + std::cerr << "Simplex_handle operator*() \n"; } return Simplex_handle(this->b, this->position); } @@ -588,27 +598,27 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { * Class needed for compatibility with Gudhi. Not useful for other purposes. **/ class Skeleton_simplex_range { - //Range over the simplices of the complex in the order of the filtration. - //.begin() and .end() return type Filtration_simplex_iterator. + // Range over the simplices of the complex in the order of the filtration. + // .begin() and .end() return type Filtration_simplex_iterator. public: - - Skeleton_simplex_range(Bitmap_cubical_complex* b, int dimension) : b(b), dimension(dimension) { }; + Skeleton_simplex_range(Bitmap_cubical_complex* b, int dimension) : b(b), dimension(dimension) { } Skeleton_simplex_iterator begin() { if (globalDbg) { - cerr << "Skeleton_simplex_iterator begin()\n"; + std::cerr << "Skeleton_simplex_iterator begin()\n"; } return Skeleton_simplex_iterator(this->b, this->dimension); } Skeleton_simplex_iterator end() { if (globalDbg) { - cerr << "Skeleton_simplex_iterator end()\n"; + std::cerr << "Skeleton_simplex_iterator end()\n"; } Skeleton_simplex_iterator it(this->b, this->dimension); it.position = this->b->data.size(); return it; } + private: Bitmap_cubical_complex* b; int dimension; @@ -619,22 +629,22 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ Skeleton_simplex_range skeleton_simplex_range(int dimension) { if (globalDbg) { - cerr << "Skeleton_simplex_range skeleton_simplex_range( int dimension )\n"; + std::cerr << "Skeleton_simplex_range skeleton_simplex_range( int dimension )\n"; } return Skeleton_simplex_range(this, dimension); } - //*********************************************************************************************************************************// - //functions used for debugging: + //******************************************************************************************************************// + // functions used for debugging: /** * Function used for debugging purposes. **/ void printKeyAssociatedToSimplex() { for (size_t i = 0; i != this->data.size(); ++i) { - cerr << i << " -> " << this->simplexAssociatedToKey[i] << endl; + std::cerr << i << " -> " << this->simplexAssociatedToKey[i] << std::endl; } } @@ -648,13 +658,17 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { private: std::vector< size_t > keyAssociatedToSimplex; std::vector< size_t > simplexAssociatedToKey; - std::vector< size_t > elementsOrderedAccordingToFiltration; //needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. -}; //Bitmap_cubical_complex + // needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. + std::vector< size_t > elementsOrderedAccordingToFiltration; +}; template -bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< size_t, std::pair< T, char > >& f, const std::pair< size_t, std::pair< T, char > >& s) { +bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< size_t, + std::pair< T, char > >& f, + const std::pair< size_t, + std::pair< T, char > >& s) { if (globalDbg) { - cerr << "ompareElementsForElementsOrderedAccordingToFiltration\n"; + std::cerr << "ompareElementsForElementsOrderedAccordingToFiltration\n"; } if (f.second.first < s.second.first) { return true; @@ -662,14 +676,15 @@ bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< siz if (f.second.first > s.second.first) { return false; } else { - //in this case f.second.first == s.second.first, and we use dimension to compare: + // in this case f.second.first == s.second.first, and we use dimension to compare: if (f.second.second < s.second.second) { return true; } else { if (f.second.second > s.second.second) { return false; } else { - //in this case, both the filtration value and the dimensions for those cells are the same. Since it may be nice to have a stable sorting procedure, in this case, we compare positions in the bitmap: + // in this case, both the filtration value and the dimensions for those cells are the same. + // Since it may be nice to have a stable sorting procedure, in this case, we compare positions in the bitmap: return ( f.first < s.first); } } @@ -680,21 +695,24 @@ bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< siz template void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() { if (globalDbg) { - cerr << "void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() \n"; + std::cerr << "void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() \n"; } - //( position , (filtration , dimension) ) + // ( position , (filtration , dimension) ) std::vector< std::pair< size_t, std::pair< T, char > > > dataOfElementsFromBitmap(this->data.size()); for (size_t i = 0; i != this->data.size(); ++i) { - //TODO -- this can be optimized by having a counter here. We do not need to re-compute the dimension for every cell from scratch + // TODO(Pawel Dlotko): This can be optimized by having a counter here. We do not need to re-compute the dimension + // for every cell from scratch dataOfElementsFromBitmap[i] = std::make_pair(i, std::make_pair(this->data[i], this->get_dimension_of_a_cell(i))); } - std::sort(dataOfElementsFromBitmap.begin(), dataOfElementsFromBitmap.end(), compareElementsForElementsOrderedAccordingToFiltration); + std::sort(dataOfElementsFromBitmap.begin(), dataOfElementsFromBitmap.end(), + compareElementsForElementsOrderedAccordingToFiltration); - std::vector< size_t > elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap(this->data.size()); + // Elements of bitmap ordered according to filtration then according to dimension then according to position in bitmap + std::vector< size_t > elements_of_bitmap_ordered(this->data.size()); for (size_t i = 0; i != dataOfElementsFromBitmap.size(); ++i) { - elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap[i] = dataOfElementsFromBitmap[i].first; + elements_of_bitmap_ordered[i] = dataOfElementsFromBitmap[i].first; } - this->elementsOrderedAccordingToFiltration = elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap; + this->elementsOrderedAccordingToFiltration = elements_of_bitmap_ordered; } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 26c97872..d9c91832 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -23,20 +23,17 @@ #ifndef BITMAP_CUBICAL_COMPLEX_BASE_H_ #define BITMAP_CUBICAL_COMPLEX_BASE_H_ +#include + #include #include #include -#include #include #include #include #include #include -#include - -using namespace std; - /** * This is a class implementing a basic bitmap data structure to store cubical complexes. It implements only the most basic subroutines. * The idea of the bitmap is the following. Our aim is to have a memory efficient data structure to store d-dimensional cubical complex C being a cubical decomposition @@ -89,7 +86,7 @@ class Bitmap_cubical_complex_base { * cells. The most typical one is by so called lower star filtration. This function is always called by any constructor which takes the top dimensional cells. If you use such a constructor, * then there is no need to call this function. Call it only if you are putting the filtration of the cells by your own (for instance by using topDimensionalCellsIterator). **/ - void impose_lower_star_filtration(); //assume that top dimensional cells are already set. + void impose_lower_star_filtration(); // assume that top dimensional cells are already set. /** * Returns dimension of a complex. @@ -109,9 +106,9 @@ class Bitmap_cubical_complex_base { * Writing to stream operator. **/ template - friend ostream& operator<<(ostream & os_, const Bitmap_cubical_complex_base& b_); + friend std::ostream& operator<<(std::ostream & os_, const Bitmap_cubical_complex_base& b_); - //ITERATORS + // ITERATORS /** * Iterator through all cells in the complex (in order they appear in the structure -- i.e. in lexicographical order). @@ -142,7 +139,6 @@ class Bitmap_cubical_complex_base { **/ class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > { public: - Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b_) : b(b_) { for (size_t i = 0; i != b_.dimension(); ++i) { this->counter.push_back(0); @@ -150,7 +146,7 @@ class Bitmap_cubical_complex_base { } Top_dimensional_cells_iterator operator++() { - //first find first element of the counter that can be increased: + // first find first element of the counter that can be increased: size_t dim = 0; while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1))++dim; @@ -191,7 +187,7 @@ class Bitmap_cubical_complex_base { } T& operator*() { - //given the counter, compute the index in the array and return this element. + // given the counter, compute the index in the array and return this element. unsigned index = 0; for (size_t i = 0; i != this->counter.size(); ++i) { index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; @@ -209,7 +205,7 @@ class Bitmap_cubical_complex_base { void printCounter() { for (size_t i = 0; i != this->counter.size(); ++i) { - cout << this->counter[i] << " "; + std::cout << this->counter[i] << " "; } } friend class Bitmap_cubical_complex_base; @@ -255,10 +251,10 @@ class Bitmap_cubical_complex_base { for (size_t i = 0; i != sizes_.size(); ++i) { this->sizes.push_back(sizes_[i]); this->multipliers.push_back(multiplier); - //multiplier *= 2*(sizes[i]+1)+1; + // multiplier *= 2*(sizes[i]+1)+1; multiplier *= 2 * sizes_[i] + 1; } - //std::reverse( this->sizes.begin() , this->sizes.end() ); + // std::reverse( this->sizes.begin() , this->sizes.end() ); std::vector data(multiplier); std::fill(data.begin(), data.end(), INT_MAX); this->totalNumberOfCells = multiplier; @@ -287,9 +283,11 @@ class Bitmap_cubical_complex_base { }; template -ostream& operator<<(ostream & out_, const Bitmap_cubical_complex_base& b_) { - //for ( typename bitmap::all_cells_const_iterator it = b.all_cells_const_begin() ; it != b.all_cells_const_end() ; ++it ) - for (typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b_.all_cells_const_begin(); it != b_.all_cells_const_end(); ++it) { +std::ostream& operator<<(std::ostream & out_, const Bitmap_cubical_complex_base& b_) { + // for ( typename bitmap::all_cells_const_iterator it = b.all_cells_const_begin() ; + // it != b.all_cells_const_end() ; ++it ) + for (typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b_.all_cells_const_begin(); + it != b_.all_cells_const_end(); ++it) { out_ << *it << " "; } return out_; @@ -301,7 +299,8 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizesInFollowingDirections_, std::vector topDimensionalCells_) { +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizesInFollowingDirections_, + std::vector topDimensionalCells_) { this->set_up_containers(sizesInFollowingDirections_); size_t numberOfTopDimensionalElements = 1; @@ -309,8 +308,12 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizesInFollowingDirections_ , std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from sizesInFollowingDirections vector is different than the size of topDimensionalCells vector." << endl; - throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from sizesInFollowingDirections vector is different than the size of topDimensionalCells vector."); + std::cerr << "Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , " + "std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from " + "sizesInFollowingDirections vector is different than the size of topDimensionalCells vector." << std::endl; + throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , " + "std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from " + "sizesInFollowingDirections vector is different than the size of topDimensionalCells vector."); } Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); @@ -325,13 +328,13 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFile_) { bool dbg = false; - ifstream inFiltration, inIds; + std::ifstream inFiltration, inIds; inFiltration.open(perseusStyleFile_); unsigned dimensionOfData; inFiltration >> dimensionOfData; if (dbg) { - cerr << "dimensionOfData : " << dimensionOfData << endl; + std::cerr << "dimensionOfData : " << dimensionOfData << std::endl; } std::vector sizes; @@ -341,7 +344,7 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFi sizeInThisDimension = abs(sizeInThisDimension); sizes.push_back(sizeInThisDimension); if (dbg) { - cerr << "sizeInThisDimension : " << sizeInThisDimension << endl; + std::cerr << "sizeInThisDimension : " << sizeInThisDimension << std::endl; } } this->set_up_containers(sizes); @@ -349,12 +352,14 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFi Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); it = this->top_dimensional_cells_begin(); - //TODO -- over here we also need to read id's of cell and put them to bitmapElement structure! + // TODO(Pawel Dlotko): Over here we also need to read id's of cell and put them to bitmapElement structure! while (!inFiltration.eof()) { double filtrationLevel; inFiltration >> filtrationLevel; if (dbg) { - cerr << "Cell of an index : " << it.computeIndexInBitmap() << " and dimension: " << this->get_dimension_of_a_cell(it.computeIndexInBitmap()) << " get the value : " << filtrationLevel << endl; + std::cerr << "Cell of an index : " << it.computeIndexInBitmap() << " and dimension: " << + this->get_dimension_of_a_cell(it.computeIndexInBitmap()) << " get the value : " << + filtrationLevel << std::endl; } *it = filtrationLevel; ++it; @@ -366,7 +371,8 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFi template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(size_t cell_) { bool bdg = false; - //first of all, we need to take the list of coordinates in which the cell has nonzero length. We do it by using modified version to compute dimension of a cell: + // First of all, we need to take the list of coordinates in which the cell has nonzero length. + // We do it by using modified version to compute dimension of a cell: std::vector< unsigned > dimensionsInWhichCellHasNonzeroLength; unsigned dimension = 0; size_t cell1 = cell_; @@ -380,9 +386,9 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(siz } if (bdg) { - cerr << "dimensionsInWhichCellHasNonzeroLength : \n"; + std::cerr << "dimensionsInWhichCellHasNonzeroLength : \n"; for (size_t i = 0; i != dimensionsInWhichCellHasNonzeroLength.size(); ++i) { - cerr << dimensionsInWhichCellHasNonzeroLength[i] << endl; + std::cerr << dimensionsInWhichCellHasNonzeroLength[i] << std::endl; } getchar(); } @@ -393,9 +399,12 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(siz boundaryElements.push_back(cell_ - multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); boundaryElements.push_back(cell_ + multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); - if (bdg) cerr << "multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; - if (bdg) cerr << "cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; - if (bdg) cerr << "cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; + if (bdg) std::cerr << "multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; + if (bdg) std::cerr << "cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << + cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; + if (bdg) std::cerr << "cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << + cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; } return boundaryElements; } @@ -403,7 +412,8 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(siz template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(size_t cell_) { bool bdg = false; - //first of all, we need to take the list of coordinates in which the cell has nonzero length. We do it by using modified version to compute dimension of a cell: + // First of all, we need to take the list of coordinates in which the cell has nonzero length. + // We do it by using modified version to compute dimension of a cell: std::vector< unsigned > dimensionsInWhichCellHasZeroLength; unsigned dimension = 0; size_t cell1 = cell_; @@ -417,16 +427,16 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(s } std::vector counter = this->compute_counter_for_given_cell(cell_); - //reverse(counter.begin() , counter.end()); + // reverse(counter.begin() , counter.end()); if (bdg) { - cerr << "dimensionsInWhichCellHasZeroLength : \n"; + std::cerr << "dimensionsInWhichCellHasZeroLength : \n"; for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { - cerr << dimensionsInWhichCellHasZeroLength[i] << endl; + std::cerr << dimensionsInWhichCellHasZeroLength[i] << std::endl; } - cerr << "\n counter : " << endl; + std::cerr << "\n counter : " << std::endl; for (size_t i = 0; i != counter.size(); ++i) { - cerr << counter[i] << endl; + std::cerr << counter[i] << std::endl; } getchar(); } @@ -435,27 +445,29 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(s if (dimensionsInWhichCellHasZeroLength.size() == 0)return coboundaryElements; for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { if (bdg) { - cerr << "Dimension : " << i << endl; + std::cerr << "Dimension : " << i << std::endl; if (counter[dimensionsInWhichCellHasZeroLength[i]] == 0) { - cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + std::cerr << "In dimension : " << i << + " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; } if (counter[dimensionsInWhichCellHasZeroLength[i]] == 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]]) { - cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + std::cerr << "In dimension : " << i << + " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; } } - if ((cell_ > multipliers[dimensionsInWhichCellHasZeroLength[i]]) && (counter[dimensionsInWhichCellHasZeroLength[i]] != 0)) - //if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 0 ) - { - if (bdg)cerr << "Subtracting : " << cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]] << endl; + if ((cell_ > multipliers[dimensionsInWhichCellHasZeroLength[i]]) && + (counter[dimensionsInWhichCellHasZeroLength[i]] != 0)) { + // if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 0 ) + if (bdg)std::cerr << "Subtracting : " << cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]] << std::endl; coboundaryElements.push_back(cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]]); } - if ((cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] < this->data.size()) && (counter[dimensionsInWhichCellHasZeroLength[i]] != 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]])) - //if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 2*this->sizes[dimensionsInWhichCellHasZeroLength[i]] ) - { + if ((cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] < this->data.size()) && + (counter[dimensionsInWhichCellHasZeroLength[i]] != 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]])) { + // if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 2*this->sizes[dimensionsInWhichCellHasZeroLength[i]] ) coboundaryElements.push_back(cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]]); - if (bdg)cerr << "Adding : " << cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] << endl; + if (bdg)std::cerr << "Adding : " << cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] << std::endl; } } return coboundaryElements; @@ -464,19 +476,19 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(s template unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell(size_t cell_) { bool dbg = false; - if (dbg)cerr << "\n\n\n Computing position o a cell of an index : " << cell_ << endl; + if (dbg)std::cerr << "\n\n\n Computing position o a cell of an index : " << cell_ << std::endl; unsigned dimension = 0; for (size_t i = this->multipliers.size(); i != 0; --i) { unsigned position = cell_ / multipliers[i - 1]; - if (dbg)cerr << "i-1 :" << i - 1 << endl; - if (dbg)cerr << "cell_ : " << cell_ << endl; - if (dbg)cerr << "position : " << position << endl; - if (dbg)cerr << "multipliers[" << i - 1 << "] = " << multipliers[i - 1] << endl; + if (dbg)std::cerr << "i-1 :" << i - 1 << std::endl; + if (dbg)std::cerr << "cell_ : " << cell_ << std::endl; + if (dbg)std::cerr << "position : " << position << std::endl; + if (dbg)std::cerr << "multipliers[" << i - 1 << "] = " << multipliers[i - 1] << std::endl; if (dbg)getchar(); if (position % 2 == 1) { - if (dbg)cerr << "Nonzero length in this direction \n"; + if (dbg)std::cerr << "Nonzero length in this direction \n"; dimension++; } cell_ = cell_ % multipliers[i - 1]; @@ -493,11 +505,12 @@ template void Bitmap_cubical_complex_base::impose_lower_star_filtration() { bool dbg = false; - //this vector will be used to check which elements have already been taken care of in imposing lower star filtration: + // this vector will be used to check which elements have already been taken care of in imposing lower star filtration: std::vector isThisCellConsidered(this->data.size(), false); std::vector indicesToConsider; - //we assume here that we already have a filtration on the top dimensional cells and we have to extend it to lower ones. + // we assume here that we already have a filtration on the top dimensional cells + // and we have to extend it to lower ones. typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); for (it = this->top_dimensional_cells_begin(); it != this->top_dimensional_cells_end(); ++it) { indicesToConsider.push_back(it.computeIndexInBitmap()); @@ -505,9 +518,9 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { while (indicesToConsider.size()) { if (dbg) { - cerr << "indicesToConsider in this iteration \n"; + std::cerr << "indicesToConsider in this iteration \n"; for (size_t i = 0; i != indicesToConsider.size(); ++i) { - cout << indicesToConsider[i] << " "; + std::cout << indicesToConsider[i] << " "; } getchar(); } @@ -529,9 +542,12 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { } template -std::vector< size_t > Bitmap_cubical_complex_base::generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_) { +std::vector< size_t > +Bitmap_cubical_complex_base::generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_) { bool dbg = false; - if (this->sizes.size() != directionsForPeriodicBCond_.size())throw "directionsForPeriodicBCond_ vector size is different from the size of the bitmap. The program will now terminate \n"; + if (this->sizes.size() != directionsForPeriodicBCond_.size()) + throw ("directionsForPeriodicBCond_ vector size is different from the size of the bitmap. " + "The program will now terminate \n"); std::vector sizes(this->sizes.size()); for (size_t i = 0; i != this->sizes.size(); ++i)sizes[i] = 2 * this->sizes[i]; @@ -544,7 +560,7 @@ std::vector< size_t > Bitmap_cubical_complex_base::generate_vector_of_shifts_ size_t position; if (!c.isFinal()) { position = i; - //result.push_back( i ); + // result.push_back( i ); } else { std::vector< bool > finals = c.directionsOfFinals(); bool jumpInPosition = false; @@ -555,7 +571,7 @@ std::vector< size_t > Bitmap_cubical_complex_base::generate_vector_of_shifts_ } } if (jumpInPosition == true) { - //in this case this guy is final, so we need to find 'the opposite one' + // in this case this guy is final, so we need to find 'the opposite one' position = compute_position_in_bitmap(c.findOpposite(directionsForPeriodicBCond_)); } else { position = i; @@ -563,8 +579,8 @@ std::vector< size_t > Bitmap_cubical_complex_base::generate_vector_of_shifts_ } result.push_back(position); if (dbg) { - cerr << " position : " << position << endl; - cerr << c << endl; + std::cerr << " position : " << position << std::endl; + std::cerr << c << std::endl; getchar(); } diff --git a/src/Bitmap_cubical_complex/include/gudhi/counter.h b/src/Bitmap_cubical_complex/include/gudhi/counter.h index 9df819b2..9445a422 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/counter.h +++ b/src/Bitmap_cubical_complex/include/gudhi/counter.h @@ -26,17 +26,15 @@ #include #include -using namespace std; - /** * This is an implementation of a simple counter. It is needed for the implementation of a bitmapCubicalComplex. **/ class counter { public: - /** - * Constructor of a counter class. It takes only the parameter which is the end value of the counter. The default beginning value is a vector of the same length as the endd, filled-in with zeros. + * Constructor of a counter class. It takes only the parameter which is the end value of the counter. + * The default beginning value is a vector of the same length as the end, filled-in with zeros. **/ counter(std::vector< int > endd) { for (size_t i = 0; i != endd.size(); ++i) { @@ -47,10 +45,12 @@ class counter { } /** - * Constructor of a counter class. It takes as the input beginn and end vector. It assumes that begin vector is lexicographically below the end vector. + * Constructor of a counter class. It takes as the input beginn and endd vector. It assumes that begin vector is + * lexicographically below the end vector. **/ counter(std::vector< int > beginn, std::vector< int > endd) { - if (beginn.size() != endd.size())throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; + if (beginn.size() != endd.size()) + throw("In constructor of a counter, begin and end vectors do not have the same size. Program terminate"); for (size_t i = 0; i != endd.size(); ++i) { this->current.push_back(0); this->begin.push_back(0); @@ -59,7 +59,8 @@ class counter { } /** - * Function to increment the counter. If the value returned by the function is true, then the incrementation process was successful. + * Function to increment the counter. If the value returned by the function is true, then the incrementation process + * was successful. * If the value of the function is false, that means, that the counter have reached its end-value. **/ bool increment() { @@ -87,8 +88,9 @@ class counter { } /** - * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. Its aim is to find an counter corresponding to the element the following - * boundary element is identified with when periodic boundary conditions are imposed. + * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. + * Its aim is to find an counter corresponding to the element the following boundary element is identified with + * when periodic boundary conditions are imposed. **/ std::vector< int > findOpposite(std::vector< bool > directionsForPeriodicBCond) { std::vector< int > result; @@ -121,12 +123,13 @@ class counter { * Function to write counter to the stream. **/ friend std::ostream& operator<<(std::ostream& out, const counter& c) { - //cerr << "c.current.size() : " << c.current.size() << endl; + // std::cerr << "c.current.size() : " << c.current.size() << std::endl; for (size_t i = 0; i != c.current.size(); ++i) { out << c.current[i] << " "; } return out; } + private: std::vector< int > begin; std::vector< int > end; -- cgit v1.2.3 From 39ffc7af64543f0b2ce17487771afbd010a97349 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 27 Nov 2015 14:16:44 +0000 Subject: Adding changes to the cubcial complex class according to Marc and Vincent's comments. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@930 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: cb9134a5c18fae3e2e63bbaf8329dd168d08d3b3 --- .../example/Bitmap_cubical_complex.cpp | 147 +- src/Bitmap_cubical_complex/example/CMakeLists.txt | 2 +- .../example/Random_bitmap_cubical_complex.cpp | 174 +-- .../include/gudhi/Bitmap_cubical_complex.h | 1443 ++++++++++---------- .../include/gudhi/Bitmap_cubical_complex_base.h | 1352 ++++++++++-------- src/Bitmap_cubical_complex/include/gudhi/counter.h | 316 +++-- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 1261 ++++++++--------- src/CMakeLists.txt | 8 +- 8 files changed, 2467 insertions(+), 2236 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index 37c16618..31da3609 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -1,71 +1,76 @@ -/* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-Saclay (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 . - */ - -// for persistence algorithm -#include -#include -#include - -#include - -// standard stuff -#include -#include - -using namespace Gudhi; -using namespace Gudhi::persistent_cohomology; -using namespace std; - -int main(int argc, char** argv) { - cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes " - "provided in text files in Perseus style (the only numbed in the first line is a dimension D of a cubical " - "complex. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N " - "denote product of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of " - "top dimensional cells. We assume that the cells are in the lexicographical order. See CubicalOneSphere.txt or " - "CubicalTwoSphere.txt for example." << endl; - - int p = 2; - double min_persistence = 0; - - if (argc != 2) { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style cubical complex at the " - "input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex b(argv[1]); - - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); - pcoh.init_coefficients(p); // initializes the coefficient field for homology - pcoh.compute_persistent_cohomology(min_persistence); - - - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out((char*) ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 0; -} + /* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 . + */ + + +//for persistence algorithm +#include +#include +#include + + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include + +using namespace std; + +int main( int argc , char** argv ) +{ + cout << "This program computes persistent homology, by using bitmap_cubical_complex class,\ + of cubical complexes provided in text files in Perseus style (the only numbered in \ +the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are\ + numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are\ + filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a\ + Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex b( argv[1] ); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology( min_persistence ); + + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index 05ef1319..dd252a79 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 2.6) -project(GUDHISimplexTreeFromFile) +project(GUDHIBitmap) add_executable ( Bitmap_cubical_complex Bitmap_cubical_complex.cpp ) target_link_libraries(Bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index ac7557ce..60cfc113 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -1,81 +1,93 @@ -/* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Saclay (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 . - */ - - -// for persistence algorithm -#include -#include -#include - -#include - -// standard stuff -#include -#include -#include -#include -#include - -using namespace Gudhi; -using namespace Gudhi::persistent_cohomology; -using namespace std; - -int main(int argc, char** argv) { - srand(time(0)); - - cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes. " - "The first parameter of the program is the dimension D of the cubical complex. The next D parameters are number " - "of top dimensional cubes in each dimension of the cubical complex. The program will create random cubical " - "complex of that sizes and compute persistent homology of it." << endl; - - int p = 2; - double min_persistence = 0; - - size_t dimensionOfBitmap = (size_t) atoi(argv[1]); - std::vector< unsigned > sizes; - size_t multipliers = 1; - for (size_t dim = 0; dim != dimensionOfBitmap; ++dim) { - unsigned sizeInThisDimension = (unsigned) atoi(argv[2 + dim]); - sizes.push_back(sizeInThisDimension); - multipliers *= sizeInThisDimension; - } - - std::vector< double > data; - for (size_t i = 0; i != multipliers; ++i) { - data.push_back(rand() / (double) RAND_MAX); - } - - Bitmap_cubical_complex b(sizes, data); - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); - pcoh.init_coefficients(p); // initializes the coefficient field for homology - pcoh.compute_persistent_cohomology(min_persistence); - - stringstream ss; - ss << "randomComplex_persistence"; - std::ofstream out((char*) ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 0; -} + /* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 . + */ + + +//for persistence algorithm +#include +#include +#include + + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include + +using namespace std; + +int main( int argc , char** argv ) +{ + srand( time(0) ); + + cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes. \ +The first parameter of the program is the dimension D of the bitmap. \ +The next D parameters are number of top dimensional cubes in each dimension of the bitmap.\ +The program will create random cubical complex of that sizes and compute persistent homology of it." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc < 3 ) + { + cerr << "Wrong number of parameters, the program will now terminate\n"; + return 1; + } + + size_t dimensionOfBitmap = (size_t)atoi( argv[1] ); + std::vector< unsigned > sizes; + size_t multipliers = 1; + for ( size_t dim = 0 ; dim != dimensionOfBitmap ; ++dim ) + { + unsigned sizeInThisDimension = (unsigned)atoi( argv[2+dim] ); + sizes.push_back( sizeInThisDimension ); + multipliers *= sizeInThisDimension; + } + + std::vector< double > data; + for ( size_t i = 0 ; i != multipliers ; ++i ) + { + data.push_back( rand()/(double)RAND_MAX ); + } + + + + Bitmap_cubical_complex b( sizes , data ); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology( min_persistence ); + + + stringstream ss; + ss << "randomComplex_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 2f8cb0a3..f2c753d9 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -1,724 +1,719 @@ -/* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-Saclay (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 . - */ - -#ifndef BITMAP_CUBICAL_COMPLEX_H_ -#define BITMAP_CUBICAL_COMPLEX_H_ - -#include - -#include -#include // for pair -#include // for sort -#include // for vector - -// global variable, was used just for debugging. -bool globalDbg = false; - -template -class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { - public: - //******************************************************************************************************************// - // Typedefs and typenames - //******************************************************************************************************************// - friend class Simplex_handle; - typedef size_t Simplex_key; - typedef T Filtration_value; - - - //******************************************************************************************************************// - // Simplex handle class - //******************************************************************************************************************// - - /** - * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. Elements of this - * class are: the pointer to the bitmap B in which the considered cell is together with a position of this cell in B. - * Given this data, one can get all the information about the considered cell. - **/ - class Simplex_handle { - public: - Simplex_handle() { - if (globalDbg) { - std::cerr << "Simplex_handle()\n"; - } - this->b = 0; - this->position = 0; - } - - Simplex_handle(Bitmap_cubical_complex* b) { - if (globalDbg) { - std::cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; - } - this->b = b; - this->position = 0; - } - - Simplex_handle(const Simplex_handle& org) : b(org.b) { - if (globalDbg) { - std::cerr << "Simplex_handle( const Simplex_handle& org )\n"; - } - this->position = org.position; - } - - Simplex_handle& operator=(const Simplex_handle& rhs) { - if (globalDbg) { - std::cerr << "Simplex_handle operator = \n"; - } - this->position = rhs.position; - this->b = rhs.b; - return *this; - } - - Simplex_handle(Bitmap_cubical_complex* b, Simplex_key position) { - if (globalDbg) { - std::cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; - std::cerr << "Position : " << position << std::endl; - } - this->b = b; - this->position = position; - } - friend class Bitmap_cubical_complex; - private: - Bitmap_cubical_complex* b; - Simplex_key position; - // Assumption -- this field always keep the REAL position of simplex in the bitmap, no matter what keys have been. - // to deal with the keys, the class Bitmap_cubical_complex have extra vectors: keyAssociatedToSimplex and - // simplexAssociatedToKey that allow to move between actual cell and the key assigned to it. - }; - - - //******************************************************************************************************************// - // Constructors - //******************************************************************************************************************// - // Over here we need to definie various input types. I am proposing the following ones: - // Perseus style - // TODO(Pawel Dlotko): H5 files? - // TODO(Pawel Dlotko): binary files with little endiangs / big endians? - // TODO(Pawel Dlotko): constructor from a vector of elements of a type T. - - /** - * Constructor form a Perseus-style file. - **/ - Bitmap_cubical_complex(char* perseusStyleFile) : Bitmap_cubical_complex_base(perseusStyleFile) { - if (globalDbg) { - std::cerr << "Bitmap_cubical_complex( char* perseusStyleFile )\n"; - } - std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); - std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); - - for (size_t i = 0; i != this->totalNumberOfCells; ++i) { - keyAssociatedToSimplex[i] = simplexAssociatedToKey[i] = i; - } - this->keyAssociatedToSimplex = keyAssociatedToSimplex; - this->simplexAssociatedToKey = simplexAssociatedToKey; - // we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change - // some elements of the bitmap, then this procedure need to be called again. - this->initializeElementsOrderedAccordingToFiltration(); - } - - /** - * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells in the - * following directions and vector of element of a type T with filtration on top dimensional cells. - **/ - Bitmap_cubical_complex(std::vector dimensions, std::vector topDimensionalCells) - : Bitmap_cubical_complex_base(dimensions, topDimensionalCells) { - std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); - std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); - - for (size_t i = 0; i != this->totalNumberOfCells; ++i) { - keyAssociatedToSimplex[i] = simplexAssociatedToKey[i] = i; - } - this->keyAssociatedToSimplex = keyAssociatedToSimplex; - this->simplexAssociatedToKey = simplexAssociatedToKey; - // we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change - // some elements of the bitmap, then this procedure need to be called again. - this->initializeElementsOrderedAccordingToFiltration(); - } - - //******************************************************************************************************************// - // Other 'easy' functions - //******************************************************************************************************************// - - /** - * Returns number of all cubes in the complex. - **/ - size_t num_simplices()const { - return this->totalNumberOfCells; - } - - /** - * Returns a Simplex_handle to a cube that do not exist in this complex. - **/ - Simplex_handle null_simplex() { - return Simplex_handle(this, this->data.size()); - } - - /** - * Returns dimension of the complex. - **/ - size_t dimension() { - return this->sizes.size(); - } - - /** - * Return dimension of a cell pointed by the Simplex_handle. - **/ - size_t dimension(const Simplex_handle& sh) { - if (globalDbg) { - std::cerr << "int dimension(const Simplex_handle& sh)\n"; - } - if (sh.position != this->data.size()) return sh.b->get_dimension_of_a_cell(sh.position); - return std::numeric_limits::max(); - } - - /** - * Return the filtration of a cell pointed by the Simplex_handle. - **/ - T filtration(const Simplex_handle& sh) { - if (globalDbg) { - std::cerr << "T filtration(const Simplex_handle& sh)\n"; - } - // Returns the filtration value of a simplex. - if (sh.position != this->data.size()) return sh.b->data[ sh.position ]; - return INT_MAX; - } - - /** - * Return a key which is not a key of any cube in the considered data structure. - **/ - Simplex_key null_key() { - if (globalDbg) { - std::cerr << "Simplex_key null_key()\n"; - } - return this->data.size(); - } - - /** - * Return the key of a cube pointed by the Simplex_handle. - **/ - Simplex_key key(const Simplex_handle& sh) { - if (globalDbg) { - std::cerr << "Simplex_key key(const Simplex_handle& sh)\n"; - } - return sh.b->keyAssociatedToSimplex[ sh.position ]; - } - - /** - * Return the Simplex_handle given the key of the cube. - **/ - Simplex_handle simplex(Simplex_key key) { - if (globalDbg) { - std::cerr << "Simplex_handle simplex(Simplex_key key)\n"; - } - return Simplex_handle(this, this->simplexAssociatedToKey[ key ]); - } - - /** - * Assign key to a cube pointed by the Simplex_handle - **/ - void assign_key(Simplex_handle& sh, Simplex_key key) { - if (globalDbg) { - std::cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n"; - } - this->keyAssociatedToSimplex[sh.position] = key; - this->simplexAssociatedToKey[key] = sh.position; - } - - /** - * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. - **/ - void initializeElementsOrderedAccordingToFiltration(); - - - - //******************************************************************************************************************// - // Iterators - //******************************************************************************************************************// - - /** - * Boundary_simplex_iterator class allows iteration on boundary of each cube. - **/ - class Boundary_simplex_range; - - class Boundary_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - // Iterator on the simplices belonging to the boundary of a simplex. - // value_type must be 'Simplex_handle'. - public: - Boundary_simplex_iterator(Simplex_handle& sh) : sh(sh) { - if (globalDbg) { - std::cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n"; - } - this->position = 0; - this->boundaryElements = this->sh.b->get_boundary_of_a_cell(this->sh.position); - } - - Boundary_simplex_iterator operator++() { - if (globalDbg) { - std::cerr << "Boundary_simplex_iterator operator++()\n"; - } - ++this->position; - return *this; - } - - Boundary_simplex_iterator operator++(int) { - Boundary_simplex_iterator result = *this; - ++(*this); - return result; - } - - Boundary_simplex_iterator operator=(const Boundary_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "Boundary_simplex_iterator operator =\n"; - } - this->sh = rhs.sh; - this->boundaryElements.clear(); - this->boundaryElementsinsert(this->boundaryElements.end(), - rhs.boundaryElements.begin(), rhs.boundaryElements.end()); - } - - bool operator==(const Boundary_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator ==\n"; - } - if (this->position == rhs.position) { - if (this->boundaryElements.size() != rhs.boundaryElements.size())return false; - for (size_t i = 0; i != this->boundaryElements.size(); ++i) { - if (this->boundaryElements[i] != rhs.boundaryElements[i])return false; - } - return true; - } - return false; - } - - bool operator!=(const Boundary_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator != \n"; - } - return !(*this == rhs); - } - - Simplex_handle operator*() { - if (globalDbg) { - std::cerr << "Simplex_handle operator*\n"; - } - return Simplex_handle(this->sh.b, this->boundaryElements[this->position]); - } - - friend class Boundary_simplex_range; - private: - Simplex_handle sh; - std::vector< size_t > boundaryElements; - size_t position; - }; - - /** - * Boundary_simplex_range class provides ranges for boundary iterators. - **/ - class Boundary_simplex_range { - // Range giving access to the simplices in the boundary of a simplex. - // .begin() and .end() return type Boundary_simplex_iterator. - public: - Boundary_simplex_range(const Simplex_handle& sh) : sh(sh) { } - - Boundary_simplex_iterator begin() { - if (globalDbg) { - std::cerr << "Boundary_simplex_iterator begin\n"; - } - Boundary_simplex_iterator it(this->sh); - return it; - } - - Boundary_simplex_iterator end() { - if (globalDbg) { - std::cerr << "Boundary_simplex_iterator end()\n"; - } - Boundary_simplex_iterator it(this->sh); - it.position = it.boundaryElements.size(); - return it; - } - - private: - Simplex_handle sh; - }; - - - /** - * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. Secondary criteria for filtration are: - * (1) Dimension of a cube (lower dimensional comes first). - * (2) Position in the data structure (the ones that are earlies in the data structure comes first). - **/ - class Filtration_simplex_range; - - class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - // Iterator over all simplices of the complex in the order of the indexing scheme. - // 'value_type' must be 'Simplex_handle'. - public: - Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { } - - Filtration_simplex_iterator() : b(NULL) { } - - Filtration_simplex_iterator operator++() { - if (globalDbg) { - std::cerr << "Filtration_simplex_iterator operator++\n"; - } - ++this->position; - return (*this); - } - - Filtration_simplex_iterator operator++(int) { - Filtration_simplex_iterator result = *this; - ++(*this); - return result; - } - - Filtration_simplex_iterator operator=(const Filtration_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "Filtration_simplex_iterator operator =\n"; - } - this->b = rhs.b; - this->position = rhs.position; - } - - bool operator==(const Filtration_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n"; - } - if (this->position == rhs.position) { - return true; - } - return false; - } - - bool operator!=(const Filtration_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n"; - } - return !(*this == rhs); - } - - Simplex_handle operator*() { - if (globalDbg) { - std::cerr << "Simplex_handle operator*()\n"; - } - return Simplex_handle(this->b, this->b->elementsOrderedAccordingToFiltration[ this->position ]); - } - - friend class Filtration_simplex_range; - private: - Bitmap_cubical_complex* b; - size_t position; - }; - - /** - * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. - **/ - class Filtration_simplex_range { - // Range over the simplices of the complex in the order of the filtration. - // .begin() and .end() return type Filtration_simplex_iterator. - public: - Filtration_simplex_range(Bitmap_cubical_complex* b) : b(b) { } - - Filtration_simplex_iterator begin() { - if (globalDbg) { - std::cerr << "Filtration_simplex_iterator begin() \n"; - } - return Filtration_simplex_iterator(this->b); - } - - Filtration_simplex_iterator end() { - if (globalDbg) { - std::cerr << "Filtration_simplex_iterator end()\n"; - } - Filtration_simplex_iterator it(this->b); - it.position = this->b->elementsOrderedAccordingToFiltration.size(); - return it; - } - private: - Bitmap_cubical_complex* b; - }; - - - - //******************************************************************************************************************// - // Methods to access iterators from the container: - - /** - * boundary_simplex_range creates an object of a Boundary_simplex_range class that provides ranges for the Boundary_simplex_iterator. - **/ - Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) { - if (globalDbg) { - std::cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n"; - } - // Returns a range giving access to all simplices of the boundary of a simplex, i.e. the set of - // codimension 1 subsimplices of the Simplex. - return Boundary_simplex_range(sh); - } - - /** - * filtration_simplex_range creates an object of a Filtration_simplex_range class that provides ranges for the - * Filtration_simplex_iterator. - **/ - Filtration_simplex_range filtration_simplex_range() { - if (globalDbg) { - std::cerr << "Filtration_simplex_range filtration_simplex_range()\n"; - } - // Returns a range over the simplices of the complex in the order of the filtration - return Filtration_simplex_range(this); - } - //******************************************************************************************************************// - - - - //******************************************************************************************************************// - // Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are - // there. - // TODO(Pawel Dlotko): The file IndexingTag.h in the Gudhi library contains an empty structure, so I understand that - // this is something that was planned (for simplicial maps?) but was never finished. The only idea I have here is - // to use the same empty structure from IndexingTag.h file, but only if the compiler needs it. If the compiler - // do not need it, then I would rather not add here elements which I do not understand. - // typedef Indexing_tag - - /** - * Function needed for compatibility with Gudhi. Not useful for other purposes. - **/ - std::pair endpoints(Simplex_handle sh) { - std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh.position); - if (globalDbg) { - std::cerr << "std::pair endpoints( Simplex_handle sh )\n"; - std::cerr << "bdry.size() : " << bdry.size() << std::endl; - } - // this method returns two first elements from the boundary of sh. - if (bdry.size() < 2) - throw("Error in endpoints in Bitmap_cubical_complex class. " - "The cell for which this method was called have less than two elements in the boundary."); - return std::make_pair(Simplex_handle(this, bdry[0]), Simplex_handle(this, bdry[1])); - } - - - /** - * Class needed for compatibility with Gudhi. Not useful for other purposes. - **/ - class Skeleton_simplex_range; - - class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - // Iterator over all simplices of the complex in the order of the indexing scheme. - // 'value_type' must be 'Simplex_handle'. - public: - Skeleton_simplex_iterator(Bitmap_cubical_complex* b, size_t d) : b(b), dimension(d) { - if (globalDbg) { - std::cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n"; - } - // find the position of the first simplex of a dimension d - this->position = 0; - while ((this->position != b->data.size()) && - (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { - ++this->position; - } - } - - Skeleton_simplex_iterator() : b(NULL), dimension(0) { } - - Skeleton_simplex_iterator operator++() { - if (globalDbg) { - std::cerr << "Skeleton_simplex_iterator operator++()\n"; - } - // increment the position as long as you did not get to the next element of the dimension dimension. - ++this->position; - while ((this->position != this->b->data.size()) && - (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { - ++this->position; - } - return (*this); - } - - Skeleton_simplex_iterator operator++(int) { - Skeleton_simplex_iterator result = *this; - ++(*this); - return result; - } - - Skeleton_simplex_iterator operator=(const Skeleton_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "Skeleton_simplex_iterator operator =\n"; - } - this->b = rhs.b; - this->position = rhs.position; - } - - bool operator==(const Skeleton_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator ==\n"; - } - if (this->position == rhs.position) { - return true; - } - return false; - } - - bool operator!=(const Skeleton_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n"; - } - return !(*this == rhs); - } - - Simplex_handle operator*() { - if (globalDbg) { - std::cerr << "Simplex_handle operator*() \n"; - } - return Simplex_handle(this->b, this->position); - } - - friend class Skeleton_simplex_range; - private: - Bitmap_cubical_complex* b; - size_t position; - int dimension; - }; - - /** - * Class needed for compatibility with Gudhi. Not useful for other purposes. - **/ - class Skeleton_simplex_range { - // Range over the simplices of the complex in the order of the filtration. - // .begin() and .end() return type Filtration_simplex_iterator. - public: - Skeleton_simplex_range(Bitmap_cubical_complex* b, int dimension) : b(b), dimension(dimension) { } - - Skeleton_simplex_iterator begin() { - if (globalDbg) { - std::cerr << "Skeleton_simplex_iterator begin()\n"; - } - return Skeleton_simplex_iterator(this->b, this->dimension); - } - - Skeleton_simplex_iterator end() { - if (globalDbg) { - std::cerr << "Skeleton_simplex_iterator end()\n"; - } - Skeleton_simplex_iterator it(this->b, this->dimension); - it.position = this->b->data.size(); - return it; - } - - private: - Bitmap_cubical_complex* b; - int dimension; - }; - - /** - * Function needed for compatibility with Gudhi. Not useful for other purposes. - **/ - Skeleton_simplex_range skeleton_simplex_range(int dimension) { - if (globalDbg) { - std::cerr << "Skeleton_simplex_range skeleton_simplex_range( int dimension )\n"; - } - return Skeleton_simplex_range(this, dimension); - } - - - - //******************************************************************************************************************// - // functions used for debugging: - - /** - * Function used for debugging purposes. - **/ - void printKeyAssociatedToSimplex() { - for (size_t i = 0; i != this->data.size(); ++i) { - std::cerr << i << " -> " << this->simplexAssociatedToKey[i] << std::endl; - } - } - - /** - * Function used for debugging purposes. - **/ - size_t printRealPosition(const Simplex_handle& sh) { - return sh.position; - } - - private: - std::vector< size_t > keyAssociatedToSimplex; - std::vector< size_t > simplexAssociatedToKey; - // needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. - std::vector< size_t > elementsOrderedAccordingToFiltration; -}; - -template -bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< size_t, - std::pair< T, char > >& f, - const std::pair< size_t, - std::pair< T, char > >& s) { - if (globalDbg) { - std::cerr << "ompareElementsForElementsOrderedAccordingToFiltration\n"; - } - if (f.second.first < s.second.first) { - return true; - } else { - if (f.second.first > s.second.first) { - return false; - } else { - // in this case f.second.first == s.second.first, and we use dimension to compare: - if (f.second.second < s.second.second) { - return true; - } else { - if (f.second.second > s.second.second) { - return false; - } else { - // in this case, both the filtration value and the dimensions for those cells are the same. - // Since it may be nice to have a stable sorting procedure, in this case, we compare positions in the bitmap: - return ( f.first < s.first); - } - } - } - } -} - -template -void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() { - if (globalDbg) { - std::cerr << "void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() \n"; - } - // ( position , (filtration , dimension) ) - std::vector< std::pair< size_t, std::pair< T, char > > > dataOfElementsFromBitmap(this->data.size()); - for (size_t i = 0; i != this->data.size(); ++i) { - // TODO(Pawel Dlotko): This can be optimized by having a counter here. We do not need to re-compute the dimension - // for every cell from scratch - dataOfElementsFromBitmap[i] = std::make_pair(i, std::make_pair(this->data[i], this->get_dimension_of_a_cell(i))); - } - std::sort(dataOfElementsFromBitmap.begin(), dataOfElementsFromBitmap.end(), - compareElementsForElementsOrderedAccordingToFiltration); - - // Elements of bitmap ordered according to filtration then according to dimension then according to position in bitmap - std::vector< size_t > elements_of_bitmap_ordered(this->data.size()); - for (size_t i = 0; i != dataOfElementsFromBitmap.size(); ++i) { - elements_of_bitmap_ordered[i] = dataOfElementsFromBitmap[i].first; - } - this->elementsOrderedAccordingToFiltration = elements_of_bitmap_ordered; -} - - -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// - -#endif // BITMAP_CUBICAL_COMPLEX_H_ + /* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-Saclay (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 . + */ + + +#pragma once +#include +#include "Bitmap_cubical_complex_base.h" + + + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +//global variable, was used just for debugging. +const bool globalDbg = false; + +template +class Bitmap_cubical_complex : public Bitmap_cubical_complex_base +{ +public: +//*********************************************// +//Typedefs and typenames +//*********************************************// + friend class Simplex_handle; + typedef size_t Simplex_key; + typedef T Filtration_value; + + +//*********************************************// +//Simplex handle class +//*********************************************// + /** + * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. + * Elements of this class are: the pointer to the bitmap B in which the considered cell is + * together with a position of this cell in B. Given this data, + * one can get all the information about the considered cell. + **/ + class Simplex_handle + { + public: + Simplex_handle() + { + if ( globalDbg ){cerr << "Simplex_handle()\n";} + this->b = 0; + this->position = 0; + } + + Simplex_handle(Bitmap_cubical_complex* b) + { + if ( globalDbg ) + { + cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; + } + this->b = b; + this->position = 0; + } + + //Simplex_handle( const Simplex_handle& org ):b(org.b) + //{ + // if ( globalDbg ){cerr << "Simplex_handle( const Simplex_handle& org )\n";} + // this->position = org.position; + //} + + Simplex_handle operator = ( const Simplex_handle& rhs ) + { + if ( globalDbg ){cerr << "Simplex_handle operator = \n";} + this->position = rhs.position; + this->b = rhs.b; + return *this; + } + + Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position) + { + if ( globalDbg ) + { + cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; + cerr << "Position : " << position << endl; + } + this->b = b; + this->position = position; + } + friend class Bitmap_cubical_complex; + private: + Bitmap_cubical_complex* b; + Simplex_key position; + //Assumption -- field above always keep the REAL position of simplex in the bitmap, + //no matter what keys have been. + //to deal with the keys, the class Bitmap_cubical_complex have extra vectors: key_associated_to_simplex and + //simplex_associated_to_key that allow to move between actual cell and the key assigned to it. + }; + + +//*********************************************// +//Constructors +//*********************************************// + //Over here we need to definie various input types. I am proposing the following ones: + //Perseus style + //H5 files? TODO + //binary files with little endiangs / big endians? TODO + //constructor from a vector of elements of a type T. TODO + + /** + * Constructor form a Perseus-style file. + **/ + Bitmap_cubical_complex( const char* perseus_style_file ): + Bitmap_cubical_complex_base(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1), + simplex_associated_to_key(this->total_number_of_cells+1) + { + if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} + for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) + { + this->key_associated_to_simplex[i] = this->simplex_associated_to_key[i] = i; + } + //we initialize this only once, in each constructor, when the bitmap is constructed. + //If the user decide to change some elements of the bitmap, then this procedure need + //to be called again. + this->initialize_elements_ordered_according_to_filtration(); + } + + + /** + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells + * in the following directions and vector of element of a type T + * with filtration on top dimensional cells. + **/ + Bitmap_cubical_complex( std::vector& dimensions , std::vector& top_dimensional_cells ): + Bitmap_cubical_complex_base(dimensions,top_dimensional_cells), + key_associated_to_simplex(this->total_number_of_cells+1), + simplex_associated_to_key(this->total_number_of_cells+1) + { + for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) + { + this->key_associated_to_simplex[i] = this->simplex_associated_to_key[i] = i; + } + //we initialize this only once, in each constructor, when the bitmap is constructed. + //If the user decide to change some elements of the bitmap, then this procedure need + //to be called again. + this->initialize_elements_ordered_according_to_filtration(); + } + +//*********************************************// +//Other 'easy' functions +//*********************************************// + /** + * Returns number of all cubes in the complex. + **/ + size_t num_simplices()const + { + return this->total_number_of_cells; + } + + /** + * Returns a Simplex_handle to a cube that do not exist in this complex. + **/ + Simplex_handle null_simplex() + { + return Simplex_handle(this,this->data.size()); + } + + /** + * Returns dimension of the complex. + **/ + size_t dimension() + { + return this->sizes.size(); + } + + /** + * Return dimension of a cell pointed by the Simplex_handle. + **/ + unsigned dimension(const Simplex_handle& sh) + { + if ( globalDbg ){cerr << "unsigned dimension(const Simplex_handle& sh)\n";} + if ( sh.position != this->data.size() ) return sh.b->get_dimension_of_a_cell( sh.position ); + return -1; + } + + /** + * Return the filtration of a cell pointed by the Simplex_handle. + **/ + T filtration(const Simplex_handle& sh) + { + if ( globalDbg ){cerr << "T filtration(const Simplex_handle& sh)\n";} + //Returns the filtration value of a simplex. + if ( sh.position != this->data.size() ) return sh.b->data[ sh.position ]; + return std::numeric_limits::max(); + } + + /** + * Return a key which is not a key of any cube in the considered data structure. + **/ + Simplex_key null_key() + { + if ( globalDbg ){cerr << "Simplex_key null_key()\n";} + return this->data.size(); + } + + /** + * Return the key of a cube pointed by the Simplex_handle. + **/ + Simplex_key key(const Simplex_handle& sh) + { + if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} + return sh.b->key_associated_to_simplex[ sh.position ]; + } + + /** + * Return the Simplex_handle given the key of the cube. + **/ + Simplex_handle simplex(Simplex_key key) + { + if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} + return Simplex_handle( this , this->simplex_associated_to_key[ key ] ); + } + + /** + * Assign key to a cube pointed by the Simplex_handle + **/ + void assign_key(Simplex_handle& sh, Simplex_key key) + { + if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} + this->key_associated_to_simplex[sh.position] = key; + this->simplex_associated_to_key[key] = sh.position; + } + + /** + * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. + **/ + void initialize_elements_ordered_according_to_filtration(); + + + +//*********************************************// +//Iterators +//*********************************************// + + /** + * Boundary_simplex_iterator class allows iteration on boundary of each cube. + **/ + class Boundary_simplex_range; + class Boundary_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > + { + //Iterator on the simplices belonging to the boundary of a simplex. + //value_type must be 'Simplex_handle'. + public: + Boundary_simplex_iterator( Simplex_handle& sh ):sh(sh) + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n";} + this->position = 0; + this->boundary_elements = this->sh.b->get_boundary_of_a_cell( this->sh.position ); + } + Boundary_simplex_iterator operator++() + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator operator++()\n";} + ++this->position; + return *this; + } + Boundary_simplex_iterator operator++(int) + { + Boundary_simplex_iterator result = *this; + ++(*this); + return result; + } + Boundary_simplex_iterator operator =( const Boundary_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator operator =\n";} + this->sh = rhs.sh; + this->boundary_elements.clear(); + this->boundary_elementsinsert + (this->boundary_elements.end(), rhs.boundary_elements.begin(), rhs.boundary_elements.end()); + } + bool operator == ( const Boundary_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator ==\n";} + if ( this->position == rhs.position ) + { + if ( this->boundary_elements.size() != rhs.boundary_elements.size() )return false; + for ( size_t i = 0 ; i != this->boundary_elements.size() ; ++i ) + { + if ( this->boundary_elements[i] != rhs.boundary_elements[i] )return false; + } + return true; + } + return false; + } + + bool operator != ( const Boundary_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator != \n";} + return !(*this == rhs); + } + Simplex_handle operator*() + { + if ( globalDbg ){cerr << "Simplex_handle operator*\n";} + return Simplex_handle( this->sh.b , this->boundary_elements[this->position] ); + } + + friend class Boundary_simplex_range; + private: + Simplex_handle sh; + std::vector< size_t > boundary_elements; + size_t position; + }; + + + /** + * Boundary_simplex_range class provides ranges for boundary iterators. + **/ + class Boundary_simplex_range + { + //Range giving access to the simplices in the boundary of a simplex. + //.begin() and .end() return type Boundary_simplex_iterator. + public: + Boundary_simplex_range(const Simplex_handle& sh):sh(sh){}; + Boundary_simplex_iterator begin() + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator begin\n";} + Boundary_simplex_iterator it( this->sh ); + return it; + } + Boundary_simplex_iterator end() + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator end()\n";} + Boundary_simplex_iterator it( this->sh ); + it.position = it.boundary_elements.size(); + return it; + } + private: + Simplex_handle sh; + }; + + + /** + * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. + * Secondary criteria for filtration are: + * (1) Dimension of a cube (lower dimensional comes first). + * (2) Position in the data structure (the ones that are earlies in the data structure comes first). + **/ + class Filtration_simplex_range; + class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > + { + //Iterator over all simplices of the complex in the order of the indexing scheme. + //'value_type' must be 'Simplex_handle'. + public: + Filtration_simplex_iterator( Bitmap_cubical_complex* b ):b(b),position(0){}; + Filtration_simplex_iterator():b(NULL){}; + + Filtration_simplex_iterator operator++() + { + if ( globalDbg ){cerr << "Filtration_simplex_iterator operator++\n";} + ++this->position; + return (*this); + } + Filtration_simplex_iterator operator++(int) + { + Filtration_simplex_iterator result = *this; + ++(*this); + return result; + } + Filtration_simplex_iterator operator =( const Filtration_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "Filtration_simplex_iterator operator =\n";} + this->b = rhs.b; + this->position = rhs.position; + } + bool operator == ( const Filtration_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n";} + if ( this->position == rhs.position ) + { + return true; + } + return false; + } + + bool operator != ( const Filtration_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n";} + return !(*this == rhs); + } + Simplex_handle operator*() + { + if ( globalDbg ){cerr << "Simplex_handle operator*()\n";} + return Simplex_handle( this->b , this->b->elements_ordered_according_to_filtration[ this->position ] ); + } + + friend class Filtration_simplex_range; + private: + Bitmap_cubical_complex* b; + size_t position; + }; + + + /** + * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. + **/ + class Filtration_simplex_range + { + //Range over the simplices of the complex in the order of the filtration. + //.begin() and .end() return type Filtration_simplex_iterator. + public: + Filtration_simplex_range(Bitmap_cubical_complex* b):b(b){}; + Filtration_simplex_iterator begin() + { + if ( globalDbg ){cerr << "Filtration_simplex_iterator begin() \n";} + return Filtration_simplex_iterator( this->b ); + } + Filtration_simplex_iterator end() + { + if ( globalDbg ){cerr << "Filtration_simplex_iterator end()\n";} + Filtration_simplex_iterator it( this->b ); + it.position = this->b->elements_ordered_according_to_filtration.size(); + return it; + } + private: + Bitmap_cubical_complex* b; + }; + + + +//*********************************************// +//Methods to access iterators from the container: + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. + **/ + Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) + { + if ( globalDbg ){cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n";} + //Returns a range giving access to all simplices of the boundary of a simplex, + //i.e. the set of codimension 1 subsimplices of the Simplex. + return Boundary_simplex_range(sh); + } + + /** + * filtration_simplex_range creates an object of a Filtration_simplex_range class + * that provides ranges for the Filtration_simplex_iterator. + **/ + Filtration_simplex_range filtration_simplex_range() + { + if ( globalDbg ){cerr << "Filtration_simplex_range filtration_simplex_range()\n";} + //Returns a range over the simplices of the complex in the order of the filtration + return Filtration_simplex_range(this); + } +//*********************************************// + + + +//*********************************************// +//Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are there. + //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so + //I understand that this is something that was planned (for simplicial maps?) + //but was never finished. The only idea I have here is to use the same empty structure from + //IndexingTag.h file, but only if the compiler needs it. If the compiler + //do not need it, then I would rather not add here elements which I do not understand. + //typedef Indexing_tag + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + std::pair endpoints( Simplex_handle sh ) + { + std::vector< size_t > bdry = this->get_boundary_of_a_cell( sh.position ); + if ( globalDbg ) + { + cerr << "std::pair endpoints( Simplex_handle sh )\n"; + cerr << "bdry.size() : " << bdry.size() << endl; + } + //this method returns two first elements from the boundary of sh. + if ( bdry.size() < 2 ) + throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the boundary."); + return std::make_pair( Simplex_handle(this,bdry[0]) , Simplex_handle(this,bdry[1]) ); + } + + + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range; + class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > + { + //Iterator over all simplices of the complex in the order of the indexing scheme. + //'value_type' must be 'Simplex_handle'. + public: + Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d ):b(b),dimension(d) + { + if ( globalDbg ){cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n";} + //find the position of the first simplex of a dimension d + this->position = 0; + while ( + (this->position != b->data.size()) && + ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) + ) + { + ++this->position; + } + }; + Skeleton_simplex_iterator ():b(NULL),dimension(0){}; + + Skeleton_simplex_iterator operator++() + { + if ( globalDbg ){cerr << "Skeleton_simplex_iterator operator++()\n";} + //increment the position as long as you did not get to the next element of the dimension dimension. + ++this->position; + while ( + (this->position != this->b->data.size()) && + ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) + ) + { + ++this->position; + } + return (*this); + } + Skeleton_simplex_iterator operator++(int) + { + Skeleton_simplex_iterator result = *this; + ++(*this); + return result; + } + Skeleton_simplex_iterator operator =( const Skeleton_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "Skeleton_simplex_iterator operator =\n";} + this->b = rhs.b; + this->position = rhs.position; + } + bool operator == ( const Skeleton_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator ==\n";} + if ( this->position == rhs.position ) + { + return true; + } + return false; + } + + bool operator != ( const Skeleton_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n";} + return !(*this == rhs); + } + Simplex_handle operator*() + { + if ( globalDbg ){cerr << "Simplex_handle operator*() \n";} + return Simplex_handle( this->b , this->position ); + } + + friend class Skeleton_simplex_range; + private: + Bitmap_cubical_complex* b; + size_t position; + unsigned dimension; + }; + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range + { + //Range over the simplices of the complex in the order of the filtration. + //.begin() and .end() return type Filtration_simplex_iterator. + public: + Skeleton_simplex_range(Bitmap_cubical_complex* b , unsigned dimension):b(b),dimension(dimension){}; + Skeleton_simplex_iterator begin() + { + if ( globalDbg ){cerr << "Skeleton_simplex_iterator begin()\n";} + return Skeleton_simplex_iterator( this->b , this->dimension ); + } + Skeleton_simplex_iterator end() + { + if ( globalDbg ){cerr << "Skeleton_simplex_iterator end()\n";} + Skeleton_simplex_iterator it( this->b , this->dimension ); + it.position = this->b->data.size(); + return it; + } + private: + Bitmap_cubical_complex* b; + unsigned dimension; + }; + + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + Skeleton_simplex_range skeleton_simplex_range( unsigned dimension ) + { + if ( globalDbg ){cerr << "Skeleton_simplex_range skeleton_simplex_range( unsigned dimension )\n";} + return Skeleton_simplex_range( this , dimension ); + } + + + +//*********************************************// +//functions used for debugging: + /** + * Function used for debugging purposes. + **/ + //void printkey_associated_to_simplex() + //{ + // for ( size_t i = 0 ; i != this->data.size() ; ++i ) + // { + // cerr << i << " -> " << this->simplex_associated_to_key[i] << endl; + // } + //} + + /** + * Function used for debugging purposes. + **/ + size_t printRealPosition( const Simplex_handle& sh ) + { + return sh.position; + } + +private: + std::vector< size_t > key_associated_to_simplex; + std::vector< size_t > simplex_associated_to_key; + std::vector< size_t > elements_ordered_according_to_filtration; + //filed above is needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. +};//Bitmap_cubical_complex + +template +bool compare_elements_for_elements_ordered_according_to_filtration +( const std::pair< size_t , std::pair< T , char > >& f , const std::pair< size_t , std::pair< T , char > >& s ) +{ + if ( globalDbg ){cerr << "compare_elements_for_elements_ordered_according_to_filtration\n";} + if ( f.second.first < s.second.first ) + { + return true; + } + else + { + if ( f.second.first > s.second.first ) + { + return false; + } + else + { + //in this case f.second.first == s.second.first, and we use dimension to compare: + if ( f.second.second < s.second.second ) + { + return true; + } + else + { + if ( f.second.second > s.second.second ) + { + return false; + } + else + { + //in this case, both the filtration value and the dimensions for those cells are the same. + //Since it may be nice to have a stable sorting procedure, in this case, + //we compare positions in the bitmap: + return ( f.first < s.first ); + } + } + } + } +} + +template +void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() +{ + if ( globalDbg ) + { + cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; + } + //( position , (filtration , dimension) ) + std::vector< std::pair< size_t , std::pair< T , char > > > data_of_elements_from_bitmap( this->data.size() ); + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + //TODO -- this can be optimized by having a counter here. + //We do not need to re-compute the dimension for every cell from scratch + data_of_elements_from_bitmap[i] = + std::make_pair( i , std::make_pair( this->data[i] , this->get_dimension_of_a_cell(i) ) ); + } + std::sort( data_of_elements_from_bitmap.begin() , + data_of_elements_from_bitmap.end() , + compare_elements_for_elements_ordered_according_to_filtration ); + + std::vector< size_t > + elements_ordered_according_to_filtration_then_to_dimension_then_to_position + ( this->data.size() ); + for ( size_t i = 0 ; i != data_of_elements_from_bitmap.size() ; ++i ) + { + elements_ordered_according_to_filtration_then_to_dimension_then_to_position[i] + = data_of_elements_from_bitmap[i].first; + } + this->elements_ordered_according_to_filtration = + elements_ordered_according_to_filtration_then_to_dimension_then_to_position; +} + + +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// + + +} +} \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index d9c91832..2c2bd481 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -1,593 +1,759 @@ -/* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-Saclay (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 . - */ - -#ifndef BITMAP_CUBICAL_COMPLEX_BASE_H_ -#define BITMAP_CUBICAL_COMPLEX_BASE_H_ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * This is a class implementing a basic bitmap data structure to store cubical complexes. It implements only the most basic subroutines. - * The idea of the bitmap is the following. Our aim is to have a memory efficient data structure to store d-dimensional cubical complex C being a cubical decomposition - * of a rectangular region of a space. This is achieved by storing C as a vector of bits (this is where the name 'bitmap' came from). Each cell is represented by a single - * bit (in case of black and white bitmaps, or by a single element of a type T (here T is a filtration type of a bitmap, typically a double). All the informations needed for homology and - * persistent homology computations (like dimension of a cell, boundary and coboundary elements of a cell, are then obtained from the position of the element in C. - */ -template -class Bitmap_cubical_complex_base { - public: - /** - * There are a few constructors of a Bitmap_cubical_complex_base class. First one, that takes vector, creates an empty bitmap of a dimension equal to the number of elements in the - * input vector and size in the i-th dimension equal the number in the position i-of the input vector. - */ - Bitmap_cubical_complex_base(std::vector sizes_); - /** - * The second constructor takes as a input a Perseus style file. For more details, please consult the documentations of Perseus software as well as examples attached to this - * implementation. - **/ - Bitmap_cubical_complex_base(char* perseusStyleFile_); - /** - * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) together with vector of filtration values of top dimensional cells. - **/ - Bitmap_cubical_complex_base(std::vector dimensions_, std::vector topDimensionalCells_); - - /** - * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell and get_cell_data are the basic functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a non-negative integer, indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to the positions of (co)boundary element of the input cell. - */ - inline std::vector< size_t > get_boundary_of_a_cell(size_t cell_); - /** - * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell and get_cell_data are the basic functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a non-negative integer, indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to the positions of (co)boundary element of the input cell. - **/ - inline std::vector< size_t > get_coboundary_of_a_cell(size_t cell_); - /** - * In the case of get_dimension_of_a_cell function, the output is a non-negative integer indicating the dimension of a cell. - **/ - inline unsigned get_dimension_of_a_cell(size_t cell_); - /** - * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. - **/ - inline T& get_cell_data(size_t cell_); - - - /** - * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. Then, there are a few ways one can pick the filtration of lower dimensional - * cells. The most typical one is by so called lower star filtration. This function is always called by any constructor which takes the top dimensional cells. If you use such a constructor, - * then there is no need to call this function. Call it only if you are putting the filtration of the cells by your own (for instance by using topDimensionalCellsIterator). - **/ - void impose_lower_star_filtration(); // assume that top dimensional cells are already set. - - /** - * Returns dimension of a complex. - **/ - inline unsigned dimension() { - return sizes.size(); - } - - /** - * Returns number of all cubes in the data structure. - **/ - inline unsigned size_of_bitmap() { - return this->data.size(); - } - - /** - * Writing to stream operator. - **/ - template - friend std::ostream& operator<<(std::ostream & os_, const Bitmap_cubical_complex_base& b_); - - // ITERATORS - - /** - * Iterator through all cells in the complex (in order they appear in the structure -- i.e. in lexicographical order). - **/ - typedef typename std::vector< T >::iterator all_cells_iterator; - - all_cells_iterator all_cells_begin()const { - return this->data.begin(); - } - - all_cells_iterator all_cells_end()const { - return this->data.end(); - } - - - typedef typename std::vector< T >::const_iterator all_cells_const_iterator; - - all_cells_const_iterator all_cells_const_begin()const { - return this->data.begin(); - } - - all_cells_const_iterator all_cells_const_end()const { - return this->data.end(); - } - - /** - * Iterator through top dimensional cells of the complex. The cells appear in order they are stored in the structure (i.e. in lexicographical order) - **/ - class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > { - public: - Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b_) : b(b_) { - for (size_t i = 0; i != b_.dimension(); ++i) { - this->counter.push_back(0); - } - } - - Top_dimensional_cells_iterator operator++() { - // first find first element of the counter that can be increased: - size_t dim = 0; - while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1))++dim; - - if (dim != this->b.dimension()) { - ++this->counter[dim]; - for (size_t i = 0; i != dim; ++i) { - this->counter[i] = 0; - } - } else { - ++this->counter[0]; - } - return *this; - } - - Top_dimensional_cells_iterator operator++(int) { - Top_dimensional_cells_iterator result = *this; - ++(*this); - return result; - } - - Top_dimensional_cells_iterator operator=(const Top_dimensional_cells_iterator& rhs_) { - this->counter = rhs_.counter; - this->b = rhs_.b; - return *this; - } - - bool operator==(const Top_dimensional_cells_iterator& rhs_) { - if (&this->b != &rhs_.b)return false; - if (this->counter.size() != rhs_.counter.size())return false; - for (size_t i = 0; i != this->counter.size(); ++i) { - if (this->counter[i] != rhs_.counter[i])return false; - } - return true; - } - - bool operator!=(const Top_dimensional_cells_iterator& rhs_) { - return !(*this == rhs_); - } - - T& operator*() { - // given the counter, compute the index in the array and return this element. - unsigned index = 0; - for (size_t i = 0; i != this->counter.size(); ++i) { - index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; - } - return this->b.data[index]; - } - - size_t computeIndexInBitmap() { - size_t index = 0; - for (size_t i = 0; i != this->counter.size(); ++i) { - index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; - } - return index; - } - - void printCounter() { - for (size_t i = 0; i != this->counter.size(); ++i) { - std::cout << this->counter[i] << " "; - } - } - friend class Bitmap_cubical_complex_base; - protected: - std::vector< unsigned > counter; - Bitmap_cubical_complex_base& b; - }; - - Top_dimensional_cells_iterator top_dimensional_cells_begin() { - Top_dimensional_cells_iterator a(*this); - return a; - } - - Top_dimensional_cells_iterator top_dimensional_cells_end() { - Top_dimensional_cells_iterator a(*this); - for (size_t i = 0; i != this->dimension(); ++i) { - a.counter[i] = this->sizes[i] - 1; - } - a.counter[0]++; - return a; - } - - - //****************************************************************************************************************// - //****************************************************************************************************************// - //****************************************************************************************************************// - //****************************************************************************************************************// - - - //****************************************************************************************************************// - //****************************************************************************************************************// - //****************************************************************************************************************// - //****************************************************************************************************************// - - protected: - std::vector sizes; - std::vector multipliers; - std::vector data; - size_t totalNumberOfCells; - - void set_up_containers(std::vector sizes_) { - unsigned multiplier = 1; - for (size_t i = 0; i != sizes_.size(); ++i) { - this->sizes.push_back(sizes_[i]); - this->multipliers.push_back(multiplier); - // multiplier *= 2*(sizes[i]+1)+1; - multiplier *= 2 * sizes_[i] + 1; - } - // std::reverse( this->sizes.begin() , this->sizes.end() ); - std::vector data(multiplier); - std::fill(data.begin(), data.end(), INT_MAX); - this->totalNumberOfCells = multiplier; - this->data = data; - } - - size_t compute_position_in_bitmap(std::vector< int > counter_) { - size_t position = 0; - for (size_t i = 0; i != this->multipliers.size(); ++i) { - position += this->multipliers[i] * counter_[i]; - } - return position; - } - - std::vector compute_counter_for_given_cell(size_t cell_) { - std::vector counter; - for (size_t dim = this->sizes.size(); dim != 0; --dim) { - counter.push_back(cell_ / this->multipliers[dim - 1]); - cell_ = cell_ % this->multipliers[dim - 1]; - } - std::reverse(counter.begin(), counter.end()); - return counter; - } - - std::vector< size_t > generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_); -}; - -template -std::ostream& operator<<(std::ostream & out_, const Bitmap_cubical_complex_base& b_) { - // for ( typename bitmap::all_cells_const_iterator it = b.all_cells_const_begin() ; - // it != b.all_cells_const_end() ; ++it ) - for (typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b_.all_cells_const_begin(); - it != b_.all_cells_const_end(); ++it) { - out_ << *it << " "; - } - return out_; -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizes_) { - this->set_up_containers(sizes_); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizesInFollowingDirections_, - std::vector topDimensionalCells_) { - this->set_up_containers(sizesInFollowingDirections_); - - size_t numberOfTopDimensionalElements = 1; - for (size_t i = 0; i != sizesInFollowingDirections_.size(); ++i) { - numberOfTopDimensionalElements *= sizesInFollowingDirections_[i]; - } - if (numberOfTopDimensionalElements != topDimensionalCells_.size()) { - std::cerr << "Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , " - "std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from " - "sizesInFollowingDirections vector is different than the size of topDimensionalCells vector." << std::endl; - throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , " - "std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from " - "sizesInFollowingDirections vector is different than the size of topDimensionalCells vector."); - } - - Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - size_t index = 0; - for (it = this->top_dimensional_cells_begin(); it != this->top_dimensional_cells_end(); ++it) { - (*it) = topDimensionalCells_[index]; - ++index; - } - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFile_) { - bool dbg = false; - std::ifstream inFiltration, inIds; - inFiltration.open(perseusStyleFile_); - unsigned dimensionOfData; - inFiltration >> dimensionOfData; - - if (dbg) { - std::cerr << "dimensionOfData : " << dimensionOfData << std::endl; - } - - std::vector sizes; - for (size_t i = 0; i != dimensionOfData; ++i) { - int sizeInThisDimension; - inFiltration >> sizeInThisDimension; - sizeInThisDimension = abs(sizeInThisDimension); - sizes.push_back(sizeInThisDimension); - if (dbg) { - std::cerr << "sizeInThisDimension : " << sizeInThisDimension << std::endl; - } - } - this->set_up_containers(sizes); - - Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_begin(); - - // TODO(Pawel Dlotko): Over here we also need to read id's of cell and put them to bitmapElement structure! - while (!inFiltration.eof()) { - double filtrationLevel; - inFiltration >> filtrationLevel; - if (dbg) { - std::cerr << "Cell of an index : " << it.computeIndexInBitmap() << " and dimension: " << - this->get_dimension_of_a_cell(it.computeIndexInBitmap()) << " get the value : " << - filtrationLevel << std::endl; - } - *it = filtrationLevel; - ++it; - } - inFiltration.close(); - this->impose_lower_star_filtration(); -} - -template -std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(size_t cell_) { - bool bdg = false; - // First of all, we need to take the list of coordinates in which the cell has nonzero length. - // We do it by using modified version to compute dimension of a cell: - std::vector< unsigned > dimensionsInWhichCellHasNonzeroLength; - unsigned dimension = 0; - size_t cell1 = cell_; - for (size_t i = this->multipliers.size(); i != 0; --i) { - unsigned position = cell1 / multipliers[i - 1]; - if (position % 2 == 1) { - dimensionsInWhichCellHasNonzeroLength.push_back(i - 1); - dimension++; - } - cell1 = cell1 % multipliers[i - 1]; - } - - if (bdg) { - std::cerr << "dimensionsInWhichCellHasNonzeroLength : \n"; - for (size_t i = 0; i != dimensionsInWhichCellHasNonzeroLength.size(); ++i) { - std::cerr << dimensionsInWhichCellHasNonzeroLength[i] << std::endl; - } - getchar(); - } - - std::vector< size_t > boundaryElements; - if (dimensionsInWhichCellHasNonzeroLength.size() == 0)return boundaryElements; - for (size_t i = 0; i != dimensionsInWhichCellHasNonzeroLength.size(); ++i) { - boundaryElements.push_back(cell_ - multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); - boundaryElements.push_back(cell_ + multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); - - if (bdg) std::cerr << "multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; - if (bdg) std::cerr << "cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << - cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; - if (bdg) std::cerr << "cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << - cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; - } - return boundaryElements; -} - -template -std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(size_t cell_) { - bool bdg = false; - // First of all, we need to take the list of coordinates in which the cell has nonzero length. - // We do it by using modified version to compute dimension of a cell: - std::vector< unsigned > dimensionsInWhichCellHasZeroLength; - unsigned dimension = 0; - size_t cell1 = cell_; - for (size_t i = this->multipliers.size(); i != 0; --i) { - unsigned position = cell1 / multipliers[i - 1]; - if (position % 2 == 0) { - dimensionsInWhichCellHasZeroLength.push_back(i - 1); - dimension++; - } - cell1 = cell1 % multipliers[i - 1]; - } - - std::vector counter = this->compute_counter_for_given_cell(cell_); - // reverse(counter.begin() , counter.end()); - - if (bdg) { - std::cerr << "dimensionsInWhichCellHasZeroLength : \n"; - for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { - std::cerr << dimensionsInWhichCellHasZeroLength[i] << std::endl; - } - std::cerr << "\n counter : " << std::endl; - for (size_t i = 0; i != counter.size(); ++i) { - std::cerr << counter[i] << std::endl; - } - getchar(); - } - - std::vector< size_t > coboundaryElements; - if (dimensionsInWhichCellHasZeroLength.size() == 0)return coboundaryElements; - for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { - if (bdg) { - std::cerr << "Dimension : " << i << std::endl; - if (counter[dimensionsInWhichCellHasZeroLength[i]] == 0) { - std::cerr << "In dimension : " << i << - " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; - } - if (counter[dimensionsInWhichCellHasZeroLength[i]] == 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]]) { - std::cerr << "In dimension : " << i << - " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; - } - } - - - if ((cell_ > multipliers[dimensionsInWhichCellHasZeroLength[i]]) && - (counter[dimensionsInWhichCellHasZeroLength[i]] != 0)) { - // if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 0 ) - if (bdg)std::cerr << "Subtracting : " << cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]] << std::endl; - coboundaryElements.push_back(cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]]); - } - if ((cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] < this->data.size()) && - (counter[dimensionsInWhichCellHasZeroLength[i]] != 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]])) { - // if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 2*this->sizes[dimensionsInWhichCellHasZeroLength[i]] ) - coboundaryElements.push_back(cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]]); - if (bdg)std::cerr << "Adding : " << cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] << std::endl; - } - } - return coboundaryElements; -} - -template -unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell(size_t cell_) { - bool dbg = false; - if (dbg)std::cerr << "\n\n\n Computing position o a cell of an index : " << cell_ << std::endl; - unsigned dimension = 0; - for (size_t i = this->multipliers.size(); i != 0; --i) { - unsigned position = cell_ / multipliers[i - 1]; - - if (dbg)std::cerr << "i-1 :" << i - 1 << std::endl; - if (dbg)std::cerr << "cell_ : " << cell_ << std::endl; - if (dbg)std::cerr << "position : " << position << std::endl; - if (dbg)std::cerr << "multipliers[" << i - 1 << "] = " << multipliers[i - 1] << std::endl; - if (dbg)getchar(); - - if (position % 2 == 1) { - if (dbg)std::cerr << "Nonzero length in this direction \n"; - dimension++; - } - cell_ = cell_ % multipliers[i - 1]; - } - return dimension; -} - -template -T& Bitmap_cubical_complex_base::get_cell_data(size_t cell_) { - return this->data[cell_]; -} - -template -void Bitmap_cubical_complex_base::impose_lower_star_filtration() { - bool dbg = false; - - // this vector will be used to check which elements have already been taken care of in imposing lower star filtration: - std::vector isThisCellConsidered(this->data.size(), false); - - std::vector indicesToConsider; - // we assume here that we already have a filtration on the top dimensional cells - // and we have to extend it to lower ones. - typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - for (it = this->top_dimensional_cells_begin(); it != this->top_dimensional_cells_end(); ++it) { - indicesToConsider.push_back(it.computeIndexInBitmap()); - } - - while (indicesToConsider.size()) { - if (dbg) { - std::cerr << "indicesToConsider in this iteration \n"; - for (size_t i = 0; i != indicesToConsider.size(); ++i) { - std::cout << indicesToConsider[i] << " "; - } - getchar(); - } - std::vector newIndicesToConsider; - for (size_t i = 0; i != indicesToConsider.size(); ++i) { - std::vector bd = this->get_boundary_of_a_cell(indicesToConsider[i]); - for (size_t boundaryIt = 0; boundaryIt != bd.size(); ++boundaryIt) { - if (this->data[ bd[boundaryIt] ] > this->data[ indicesToConsider[i] ]) { - this->data[ bd[boundaryIt] ] = this->data[ indicesToConsider[i] ]; - } - if (isThisCellConsidered[ bd[boundaryIt] ] == false) { - newIndicesToConsider.push_back(bd[boundaryIt]); - isThisCellConsidered[ bd[boundaryIt] ] = true; - } - } - } - indicesToConsider.swap(newIndicesToConsider); - } -} - -template -std::vector< size_t > -Bitmap_cubical_complex_base::generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_) { - bool dbg = false; - if (this->sizes.size() != directionsForPeriodicBCond_.size()) - throw ("directionsForPeriodicBCond_ vector size is different from the size of the bitmap. " - "The program will now terminate \n"); - - std::vector sizes(this->sizes.size()); - for (size_t i = 0; i != this->sizes.size(); ++i)sizes[i] = 2 * this->sizes[i]; - - counter c(sizes); - - std::vector< size_t > result; - - for (size_t i = 0; i != this->data.size(); ++i) { - size_t position; - if (!c.isFinal()) { - position = i; - // result.push_back( i ); - } else { - std::vector< bool > finals = c.directionsOfFinals(); - bool jumpInPosition = false; - for (size_t dir = 0; dir != finals.size(); ++dir) { - if (finals[dir] == false)continue; - if (directionsForPeriodicBCond_[dir]) { - jumpInPosition = true; - } - } - if (jumpInPosition == true) { - // in this case this guy is final, so we need to find 'the opposite one' - position = compute_position_in_bitmap(c.findOpposite(directionsForPeriodicBCond_)); - } else { - position = i; - } - } - result.push_back(position); - if (dbg) { - std::cerr << " position : " << position << std::endl; - std::cerr << c << std::endl; - getchar(); - } - - c.increment(); - } - - return result; -} - -#endif // BITMAP_CUBICAL_COMPLEX_BASE_H_ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-Saclay (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 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include "counter.h" + + +using namespace std; + +namespace Gudhi +{ + +namespace Cubical_complex +{ + + + +/** + * This is a class implementing a basic bitmap data structure to store cubical complexes. + * It implements only the most basic subroutines. + * The idea of the bitmap is the following. Our aim is to have a memory efficient + * data structure to store d-dimensional cubical complex + * C being a cubical decomposition + * of a rectangular region of a space. This is achieved by storing C as a + * vector of bits (this is where the name 'bitmap' came from). + * Each cell is represented by a single + * bit (in case of black and white bitmaps, or by a single element of a type T + * (here T is a filtration type of a bitmap, typically a double). + * All the informations needed for homology and + * persistent homology computations (like dimension of a cell, boundary and + * coboundary elements of a cell, are then obtained from the + * position of the element in C. + * The default filtration used in this implementation is the lower star filtration. + */ +template +class Bitmap_cubical_complex_base +{ +public: + /** + * There are a few constructors of a Bitmap_cubical_complex_base class. + * First one, that takes vector, creates an empty bitmap of a dimension equal + * the number of elements in the + * input vector and size in the i-th dimension equal the number in the position i-of the input vector. + */ + Bitmap_cubical_complex_base( std::vector& sizes ); + /** + * The second constructor takes as a input a Perseus style file. For more details, + * please consult the documentations of + * Perseus software as well as examples attached to this + * implementation. + **/ + Bitmap_cubical_complex_base( const char* perseus_style_file ); + /** + * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) + * together with vector of filtration values of top dimensional cells. + **/ + Bitmap_cubical_complex_base( std::vector& dimensions , const std::vector& top_dimensional_cells ); + + /** + * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell + * and get_cell_data are the basic + * functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a + * non-negative integer, indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to + * the positions of (co)boundary element of the input cell. + */ + inline std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; + /** + * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, + * get_dimension_of_a_cell and get_cell_data are the basic + * functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. + * The input parameter of all of those function is a non-negative integer, + * indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if + * non-negative integers pointing to the + * positions of (co)boundary element of the input cell. + **/ + inline std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + /** + * In the case of get_dimension_of_a_cell function, the output is a non-negative integer + * indicating the dimension of a cell. + **/ + inline unsigned get_dimension_of_a_cell( size_t cell )const; + /** + * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. + **/ + inline T& get_cell_data( size_t cell ); + + + /** + * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. + * Then, there are a few ways one can pick the filtration of lower dimensional + * cells. The most typical one is by so called lower star filtration. This function is always called by any + * constructor which takes the top dimensional cells. If you use such a constructor, + * then there is no need to call this function. Call it only if you are putting the filtration + * of the cells by your own (for instance by using Top_dimensional_cells_iterator). + **/ + void impose_lower_star_filtration();//assume that top dimensional cells are already set. + + /** + * Returns dimension of a complex. + **/ + inline unsigned dimension()const{ return sizes.size(); } + + /** + * Returns number of all cubes in the data structure. + **/ + inline unsigned size_of_bitmap()const + { + return this->data.size(); + } + + /** + * Writing to stream operator. + **/ + template + friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); + + //ITERATORS + + /** + * Iterator through all cells in the complex (in order they appear in the structure -- i.e. + * in lexicographical order). + **/ + typedef typename std::vector< T >::iterator all_cells_iterator; + all_cells_iterator all_cells_begin()const + { + return this->data.begin(); + } + all_cells_iterator all_cells_end()const + { + return this->data.end(); + } + + + typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + all_cells_const_iterator all_cells_const_begin()const + { + return this->data.begin(); + } + all_cells_const_iterator all_cells_const_end()const + { + return this->data.end(); + } + + /** + * Iterator through top dimensional cells of the complex. The cells appear in order they are stored + * in the structure (i.e. in lexicographical order) + **/ + class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > + { + public: + Top_dimensional_cells_iterator( Bitmap_cubical_complex_base& b ):b(b) + { + for ( size_t i = 0 ; i != b.dimension() ; ++i ) + { + this->counter.push_back(0); + } + } + Top_dimensional_cells_iterator operator++() + { + //first find first element of the counter that can be increased: + size_t dim = 0; + while ( ( dim != this->b.dimension() ) && ( this->counter[dim] == this->b.sizes[dim]-1 ) )++dim; + + if ( dim != this->b.dimension() ) + { + ++this->counter[dim]; + for ( size_t i = 0 ; i != dim ; ++i ) + { + this->counter[i] = 0; + } + } + else + { + ++this->counter[0]; + } + return *this; + } + Top_dimensional_cells_iterator operator++(int) + { + Top_dimensional_cells_iterator result = *this; + ++(*this); + return result; + } + Top_dimensional_cells_iterator operator =( const Top_dimensional_cells_iterator& rhs ) + { + this->counter = rhs.counter; + this->b = rhs.b; + return *this; + } + bool operator == ( const Top_dimensional_cells_iterator& rhs )const + { + if ( &this->b != &rhs.b )return false; + if ( this->counter.size() != rhs.counter.size() )return false; + for ( size_t i = 0 ; i != this->counter.size() ; ++i ) + { + if ( this->counter[i] != rhs.counter[i] )return false; + } + return true; + } + bool operator != ( const Top_dimensional_cells_iterator& rhs )const + { + return !(*this == rhs); + } + + T& operator*() + { + //given the counter, compute the index in the array and return this element. + unsigned index = 0; + for ( size_t i = 0 ; i != this->counter.size() ; ++i ) + { + index += (2*this->counter[i]+1)*this->b.multipliers[i]; + } + return this->b.data[index]; + } + + size_t compute_index_in_bitmap()const + { + size_t index = 0; + for ( size_t i = 0 ; i != this->counter.size() ; ++i ) + { + index += (2*this->counter[i]+1)*this->b.multipliers[i]; + } + return index; + } + + void print_counter()const + { + for ( size_t i = 0 ; i != this->counter.size() ; ++i ) + { + cout << this->counter[i] << " "; + } + } + friend class Bitmap_cubical_complex_base; + protected: + std::vector< unsigned > counter; + Bitmap_cubical_complex_base& b; + }; + Top_dimensional_cells_iterator top_dimensional_cells_begin() + { + Top_dimensional_cells_iterator a(*this); + return a; + } + Top_dimensional_cells_iterator top_dimensional_cells_end() + { + Top_dimensional_cells_iterator a(*this); + for ( size_t i = 0 ; i != this->dimension() ; ++i ) + { + a.counter[i] = this->sizes[i]-1; + } + a.counter[0]++; + return a; + } + + +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// + + +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// + +protected: + std::vector sizes; + std::vector multipliers; + std::vector data; + size_t total_number_of_cells; + void set_up_containers( std::vector& sizes ) + { + unsigned multiplier = 1; + for ( size_t i = 0 ; i != sizes.size() ; ++i ) + { + this->sizes.push_back(sizes[i]); + this->multipliers.push_back(multiplier); + //multiplier *= 2*(sizes[i]+1)+1; + multiplier *= 2*sizes[i]+1; + } + //std::reverse( this->sizes.begin() , this->sizes.end() ); + std::vector data(multiplier); + std::fill( data.begin() , data.end() , std::numeric_limits::max() ); + this->total_number_of_cells = multiplier; + this->data = data; + } + + size_t compute_position_in_bitmap( std::vector< unsigned >& counter ) + { + size_t position = 0; + for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) + { + position += this->multipliers[i]*counter[i]; + } + return position; + } + + std::vector compute_counter_for_given_cell( size_t cell )const + { + std::vector counter; + for ( size_t dim = this->sizes.size() ; dim != 0 ; --dim ) + { + counter.push_back(cell/this->multipliers[dim-1]); + cell = cell%this->multipliers[dim-1]; + } + std::reverse( counter.begin() , counter.end() ); + return counter; + } + + std::vector< size_t > + generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions + ( std::vector< bool >& directions_for_periodic_b_cond ); +}; + + + + +template +ostream& operator << ( ostream & out , const Bitmap_cubical_complex_base& b ) +{ + for ( typename Bitmap_cubical_complex_base::all_cells_const_iterator + it = b.all_cells_const_begin() ; it != b.all_cells_const_end() ; ++it ) + { + out << *it << " "; + } + return out; +} + + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base +( std::vector& sizes ) +{ + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base +( std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) +{ + this->set_up_containers( sizes_in_following_directions ); + + size_t number_of_top_dimensional_elements = 1; + for ( size_t i = 0 ; i != sizes_in_following_directions.size() ; ++i ) + { + number_of_top_dimensional_elements *= sizes_in_following_directions[i]; + } + if ( number_of_top_dimensional_elements != top_dimensional_cells.size() ) + { + cerr << + "Error in constructor\ + Bitmap_cubical_complex_base\ + ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ + Number of top dimensional elements that follow from sizes_in_following_directions vector is different\ + than the size of top_dimensional_cells vector." << endl; + throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions,\ + std::vector top_dimensional_cells )\ + . Number of top dimensional elements that follow from sizes_in_following_directions vector is different than the\ + size of top_dimensional_cells vector."); + } + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + size_t index = 0; + for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + (*it) = top_dimensional_cells[index]; + ++index; + } + this->impose_lower_star_filtration(); +} + + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file ) +{ + bool dbg = false; + ifstream inFiltration, inIds; + inFiltration.open( perseus_style_file ); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;} + + std::vector sizes; + for ( size_t i = 0 ; i != dimensionOfData ; ++i ) + { + unsigned size_in_this_dimension; + inFiltration >> size_in_this_dimension; + size_in_this_dimension = abs(size_in_this_dimension); + sizes.push_back( size_in_this_dimension ); + if (dbg){cerr << "size_in_this_dimension : " << size_in_this_dimension << endl;} + } + this->set_up_containers( sizes ); + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_begin(); + + //TODO -- over here we also need to read id's of cell and put them to bitmapElement structure! + while ( !inFiltration.eof() ) + { + double filtrationLevel; + inFiltration >> filtrationLevel; + if ( dbg ) + { + cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + << " get the value : " << filtrationLevel << endl; + } + *it = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); +} + + +template +std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const +{ + bool bdg = false; + //first of all, we need to take the list of coordinates in which the cell has nonzero length. + //We do it by using modified version to compute dimension of a cell: + std::vector< unsigned > dimensions_in_which_cell_has_nonzero_length; + unsigned dimension = 0; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/multipliers[i-1]; + if ( position%2 == 1 ) + { + dimensions_in_which_cell_has_nonzero_length.push_back(i-1); + dimension++; + } + cell1 = cell1%multipliers[i-1]; + } + + if (bdg) + { + cerr << "dimensions_in_which_cell_has_nonzero_length : \n"; + for ( size_t i = 0 ; i != dimensions_in_which_cell_has_nonzero_length.size() ; ++i ) + { + cerr << dimensions_in_which_cell_has_nonzero_length[i] << endl; + } + getchar(); + } + + std::vector< size_t > boundary_elements; + if ( dimensions_in_which_cell_has_nonzero_length.size() == 0 )return boundary_elements; + for ( size_t i = 0 ; i != dimensions_in_which_cell_has_nonzero_length.size() ; ++i ) + { + boundary_elements.push_back( cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); + boundary_elements.push_back( cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); + + if (bdg) cerr << "multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " + << multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; + if (bdg) cerr << "cell - multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " + << cell - multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; + if (bdg) cerr << "cell + multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " + << cell + multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; + } + return boundary_elements; +} + + + + +template +std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const +{ + bool bdg = false; + //first of all, we need to take the list of coordinates in which the cell has nonzero length. + //We do it by using modified version to compute dimension of a cell: + std::vector< unsigned > dimensions_in_which_cell_has_zero_length; + unsigned dimension = 0; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/multipliers[i-1]; + if ( position%2 == 0 ) + { + dimensions_in_which_cell_has_zero_length.push_back(i-1); + dimension++; + } + cell1 = cell1%multipliers[i-1]; + } + + std::vector counter = this->compute_counter_for_given_cell( cell ); + //reverse(counter.begin() , counter.end()); + + if (bdg) + { + cerr << "dimensions_in_which_cell_has_zero_length : \n"; + for ( size_t i = 0 ; i != dimensions_in_which_cell_has_zero_length.size() ; ++i ) + { + cerr << dimensions_in_which_cell_has_zero_length[i] << endl; + } + cerr << "\n counter : " << endl; + for ( size_t i = 0 ; i != counter.size() ; ++i ) + { + cerr << counter[i] << endl; + } + getchar(); + } + + std::vector< size_t > coboundary_elements; + if ( dimensions_in_which_cell_has_zero_length.size() == 0 )return coboundary_elements; + for ( size_t i = 0 ; i != dimensions_in_which_cell_has_zero_length.size() ; ++i ) + { + if ( bdg ) + { + cerr << "Dimension : " << i << endl; + if (counter[dimensions_in_which_cell_has_zero_length[i]] == 0) + { + cerr << "In dimension : " << i + << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + } + if ( counter[dimensions_in_which_cell_has_zero_length[i]] + == + 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) + { + cerr << "In dimension : " << i + << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + } + } + + + if ( (cell > multipliers[dimensions_in_which_cell_has_zero_length[i]]) + && (counter[dimensions_in_which_cell_has_zero_length[i]] != 0) ) + //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != 0 ) + { + if ( bdg ) + { + cerr << "Subtracting : " << cell - multipliers[dimensions_in_which_cell_has_zero_length[i]] << endl; + } + coboundary_elements.push_back( cell - multipliers[dimensions_in_which_cell_has_zero_length[i]] ); + } + if ( + (cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && + (counter[dimensions_in_which_cell_has_zero_length[i]] + != + 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]]) + ) + //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != + //2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) + { + coboundary_elements.push_back( cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] ); + if ( bdg )cerr << "Adding : " << cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] << endl; + } + } + return coboundary_elements; +} + + + + + + +template +unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell( size_t cell )const +{ + bool dbg = false; + if (dbg)cerr << "\n\n\n Computing position o a cell of an index : " << cell << endl; + unsigned dimension = 0; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell/multipliers[i-1]; + + if (dbg)cerr << "i-1 :" << i-1 << endl; + if (dbg)cerr << "cell : " << cell << endl; + if (dbg)cerr << "position : " << position << endl; + if (dbg)cerr << "multipliers["< +T& Bitmap_cubical_complex_base::get_cell_data( size_t cell ) +{ + return this->data[cell]; +} + + +template +void Bitmap_cubical_complex_base::impose_lower_star_filtration() +{ + bool dbg = false; + + //this vector will be used to check which elements have already been taken care of + //in imposing lower star filtration: + std::vector is_this_cell_considered( this->data.size() , false ); + + std::vector indices_to_consider; + //we assume here that we already have a filtration on the top dimensional cells and + //we have to extend it to lower ones. + typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + indices_to_consider.push_back( it.compute_index_in_bitmap() ); + } + + while ( indices_to_consider.size() ) + { + if ( dbg ) + { + cerr << "indices_to_consider in this iteration \n"; + for ( size_t i = 0 ; i != indices_to_consider.size() ; ++i ) + { + cout << indices_to_consider[i] << " "; + } + getchar(); + } + std::vector new_indices_to_consider; + for ( size_t i = 0 ; i != indices_to_consider.size() ; ++i ) + { + std::vector bd = this->get_boundary_of_a_cell( indices_to_consider[i] ); + for ( size_t boundaryIt = 0 ; boundaryIt != bd.size() ; ++boundaryIt ) + { + if ( this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ] ) + { + this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + } + if ( is_this_cell_considered[ bd[boundaryIt] ] == false ) + { + new_indices_to_consider.push_back( bd[boundaryIt] ); + is_this_cell_considered[ bd[boundaryIt] ] = true; + } + } + } + indices_to_consider.swap(new_indices_to_consider); + } +} + + +template +bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , char >& first , + const std::pair< std::pair< T , size_t > , char >& second ) +{ + if ( first.first.first < second.first.first ) + { + return true; + } + else + { + if ( first.first.first > second.first.first ) + { + return false; + } + //in this case first.first.first == second.first.first, so we need to compare dimensions + return first.second < second.second; + } +} + + + +template +std::vector< size_t > Bitmap_cubical_complex_base:: +generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions +( std::vector< bool >& directions_for_periodic_b_cond ) +{ + bool dbg = false; + if ( this->sizes.size() != directions_for_periodic_b_cond.size() ) + throw "directions_for_periodic_b_cond vector size is different from the size of the bitmap. Program terminate \n"; + + std::vector sizes( this->sizes.size() ); + for ( size_t i = 0 ; i != this->sizes.size() ; ++i )sizes[i] = 2*this->sizes[i]; + + counter c( sizes ); + + std::vector< size_t > result; + + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + size_t position; + if ( !c.isFinal() ) + { + position = i; + //result.push_back( i ); + } + else + { + std::vector< bool > finals = c.directions_of_finals(); + bool jump_in_position = false; + for ( size_t dir = 0 ; dir != finals.size() ; ++dir ) + { + if ( finals[dir] == false )continue; + if ( directions_for_periodic_b_cond[dir] ) + { + jump_in_position = true; + } + } + if ( jump_in_position == true ) + { + //in this case this guy is final, so we need to find 'the opposite one' + position = compute_position_in_bitmap( c.find_opposite( directions_for_periodic_b_cond ) ); + } + else + { + position = i; + } + } + result.push_back( position ); + if ( dbg ) + { + cerr << " position : " << position << endl; + cerr << c << endl; + getchar(); + } + + c.increment(); + } + + return result; +} + +} + +} \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/include/gudhi/counter.h b/src/Bitmap_cubical_complex/include/gudhi/counter.h index 9445a422..a5fda36f 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/counter.h +++ b/src/Bitmap_cubical_complex/include/gudhi/counter.h @@ -1,139 +1,177 @@ -/* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-Saclay (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 . - */ - -#ifndef COUNTER_H_ -#define COUNTER_H_ - -#include -#include - -/** - * This is an implementation of a simple counter. It is needed for the implementation of a bitmapCubicalComplex. - **/ - -class counter { - public: - /** - * Constructor of a counter class. It takes only the parameter which is the end value of the counter. - * The default beginning value is a vector of the same length as the end, filled-in with zeros. - **/ - counter(std::vector< int > endd) { - for (size_t i = 0; i != endd.size(); ++i) { - this->current.push_back(0); - this->begin.push_back(0); - this->end.push_back(endd[i]); - } - } - - /** - * Constructor of a counter class. It takes as the input beginn and endd vector. It assumes that begin vector is - * lexicographically below the end vector. - **/ - counter(std::vector< int > beginn, std::vector< int > endd) { - if (beginn.size() != endd.size()) - throw("In constructor of a counter, begin and end vectors do not have the same size. Program terminate"); - for (size_t i = 0; i != endd.size(); ++i) { - this->current.push_back(0); - this->begin.push_back(0); - this->end.push_back(endd[i]); - } - } - - /** - * Function to increment the counter. If the value returned by the function is true, then the incrementation process - * was successful. - * If the value of the function is false, that means, that the counter have reached its end-value. - **/ - bool increment() { - size_t i = 0; - while ((i != this->end.size()) && (this->current[i] == this->end[i])) { - ++i; - } - - if (i == this->end.size())return false; - ++this->current[i]; - for (size_t j = 0; j != i; ++j) { - this->current[j] = this->begin[j]; - } - return true; - } - - /** - * Function to check if we are at the end of counter. - **/ - bool isFinal() { - for (size_t i = 0; i != this->current.size(); ++i) { - if (this->current[i] == this->end[i])return true; - } - return false; - } - - /** - * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. - * Its aim is to find an counter corresponding to the element the following boundary element is identified with - * when periodic boundary conditions are imposed. - **/ - std::vector< int > findOpposite(std::vector< bool > directionsForPeriodicBCond) { - std::vector< int > result; - for (size_t i = 0; i != this->current.size(); ++i) { - if ((this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true)) { - result.push_back(this->begin[i]); - } else { - result.push_back(this->current[i]); - } - } - return result; - } - - /** - * Function checking at which positions the current value of a counter is the final value of the counter. - **/ - std::vector< bool > directionsOfFinals() { - std::vector< bool > result; - for (size_t i = 0; i != this->current.size(); ++i) { - if (this->current[i] == this->end[i]) { - result.push_back(true); - } else { - result.push_back(false); - } - } - return result; - } - - /** - * Function to write counter to the stream. - **/ - friend std::ostream& operator<<(std::ostream& out, const counter& c) { - // std::cerr << "c.current.size() : " << c.current.size() << std::endl; - for (size_t i = 0; i != c.current.size(); ++i) { - out << c.current[i] << " "; - } - return out; - } - - private: - std::vector< int > begin; - std::vector< int > end; - std::vector< int > current; -}; - -#endif // COUNTER_H_ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-Saclay (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 . + */ + +#pragma once + +#include +#include + +using namespace std; + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +/** +* This is an implementation of a counter being a vector of integers. +* The constructor of the class takes as an input two vectors W and V. +* It assumes that W < V coordinatewise. +* If the initial counter W is not specified, it is assumed to be vector of zeros. +* The class allows to iterate between W and V by using increment() function. +* The increment() function returns a bool value. +* The current counter reach the end counter V if the value returned by the increment function is FALSE. +* This class is needed for the implementation of a bitmapCubicalComplex. +**/ + +class counter +{ +public: + /** + * Constructor of a counter class. It takes only the parameter which is the end value of the counter. + * The default beginning value is a vector of the same length as the endd, filled-in with zeros. + **/ + counter(std::vector const& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} + //counter(std::vector< int >& endd) + //{ + // for ( size_t i = 0 ; i != endd.size() ; ++i ) + // { + // this->current.push_back(0); + // this->begin.push_back(0); + // this->end.push_back( endd[i] ); + // } + //} + + + /** + * Constructor of a counter class. It takes as the input beginn and end vector. + * It assumes that begin vector is lexicographically below the end vector. + **/ + counter(std::vector< unsigned >& beginn , std::vector< unsigned >& endd) + { + if ( beginn.size() != endd.size() ) + throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; + for ( size_t i = 0 ; i != endd.size() ; ++i ) + { + this->current.push_back(0); + this->begin.push_back(0); + this->end.push_back( endd[i] ); + } + } + + /** + * Function to increment the counter. If the value returned by the function is true, + * then the incrementation process was successful. + * If the value of the function is false, that means, that the counter have reached its end-value. + **/ + bool increment() + { + size_t i = 0; + while( (i != this->end.size()) && (this->current[i] == this->end[i]) ) + { + ++i; + } + + if ( i == this->end.size() )return false; + ++this->current[i]; + for ( size_t j = 0 ; j != i ; ++j ) + { + this->current[j] = this->begin[j]; + } + return true; + } + + /** + * Function to check if we are at the end of counter. + **/ + bool isFinal() + { + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( this->current[i] == this->end[i] )return true; + } + return false; + } + + /** + * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. + * Its aim is to find an counter corresponding to the element the following + * boundary element is identified with when periodic boundary conditions are imposed. + **/ + std::vector< unsigned > find_opposite( std::vector< bool >& directionsForPeriodicBCond ) + { + std::vector< unsigned > result; + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( (this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true) ) + { + result.push_back( this->begin[i] ); + } + else + { + result.push_back( this->current[i] ); + } + } + return result; + } + + /** + * Function checking at which positions the current value of a counter is the final value of the counter. + **/ + std::vector< bool > directions_of_finals() + { + std::vector< bool > result; + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( this->current[i] == this->end[i] ) + { + result.push_back( true ); + } + else + { + result.push_back( false ); + } + } + return result; + } + + /** + * Function to write counter to the stream. + **/ + friend std::ostream& operator<<(std::ostream& out , const counter& c ) + { + //cerr << "c.current.size() : " << c.current.size() << endl; + for ( size_t i = 0 ; i != c.current.size() ; ++i ) + { + out << c.current[i] << " "; + } + return out; + } +private: + std::vector< unsigned > begin; + std::vector< unsigned > end; + std::vector< unsigned > current; +}; + +} +} \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index 1c204bae..183b856a 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -1,623 +1,638 @@ -#include "gudhi/Bitmap_cubical_complex.h" - -#define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE "cubical_complex" -#include - -using namespace std; - -BOOST_AUTO_TEST_CASE(check_dimension) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - BOOST_CHECK(increasing.dimension() == 2); -} - -BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { - std::vector< double > expectedFiltrationValues1; - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(100); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - - std::vector< double > expectedFiltrationValues2; - expectedFiltrationValues2.push_back(1); - expectedFiltrationValues2.push_back(2); - expectedFiltrationValues2.push_back(3); - expectedFiltrationValues2.push_back(4); - expectedFiltrationValues2.push_back(5); - expectedFiltrationValues2.push_back(6); - expectedFiltrationValues2.push_back(7); - expectedFiltrationValues2.push_back(8); - expectedFiltrationValues2.push_back(9); - - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector< double > oneDimensionalCycle; - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(100); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle); - - - int i = 0; - for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { - BOOST_CHECK(*it == expectedFiltrationValues2[i]); - ++i; - } - i = 0; - for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { - BOOST_CHECK(*it == expectedFiltrationValues1[i]); - ++i; - } -} - -BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { - - std::vector boundary0; - std::vector boundary1; - boundary1.push_back(0); - boundary1.push_back(2); - std::vector boundary2; - std::vector boundary3; - boundary3.push_back(2); - boundary3.push_back(4); - std::vector boundary4; - std::vector boundary5; - boundary5.push_back(4); - boundary5.push_back(6); - std::vector boundary6; - std::vector boundary7; - boundary7.push_back(0); - boundary7.push_back(14); - std::vector boundary8; - boundary8.push_back(1); - boundary8.push_back(15); - boundary8.push_back(7); - boundary8.push_back(9); - std::vector boundary9; - boundary9.push_back(2); - boundary9.push_back(16); - std::vector boundary10; - boundary10.push_back(3); - boundary10.push_back(17); - boundary10.push_back(9); - boundary10.push_back(11); - std::vector boundary11; - boundary11.push_back(4); - boundary11.push_back(18); - std::vector boundary12; - boundary12.push_back(5); - boundary12.push_back(19); - boundary12.push_back(11); - boundary12.push_back(13); - std::vector boundary13; - boundary13.push_back(6); - boundary13.push_back(20); - std::vector boundary14; - std::vector boundary15; - boundary15.push_back(14); - boundary15.push_back(16); - std::vector boundary16; - std::vector boundary17; - boundary17.push_back(16); - boundary17.push_back(18); - std::vector boundary18; - std::vector boundary19; - boundary19.push_back(18); - boundary19.push_back(20); - std::vector boundary20; - std::vector boundary21; - boundary21.push_back(14); - boundary21.push_back(28); - std::vector boundary22; - boundary22.push_back(15); - boundary22.push_back(29); - boundary22.push_back(21); - boundary22.push_back(23); - std::vector boundary23; - boundary23.push_back(16); - boundary23.push_back(30); - std::vector boundary24; - boundary24.push_back(17); - boundary24.push_back(31); - boundary24.push_back(23); - boundary24.push_back(25); - std::vector boundary25; - boundary25.push_back(18); - boundary25.push_back(32); - std::vector boundary26; - boundary26.push_back(19); - boundary26.push_back(33); - boundary26.push_back(25); - boundary26.push_back(27); - std::vector boundary27; - boundary27.push_back(20); - boundary27.push_back(34); - std::vector boundary28; - std::vector boundary29; - boundary29.push_back(28); - boundary29.push_back(30); - std::vector boundary30; - std::vector boundary31; - boundary31.push_back(30); - boundary31.push_back(32); - std::vector boundary32; - std::vector boundary33; - boundary33.push_back(32); - boundary33.push_back(34); - std::vector boundary34; - std::vector boundary35; - boundary35.push_back(28); - boundary35.push_back(42); - std::vector boundary36; - boundary36.push_back(29); - boundary36.push_back(43); - boundary36.push_back(35); - boundary36.push_back(37); - std::vector boundary37; - boundary37.push_back(30); - boundary37.push_back(44); - std::vector boundary38; - boundary38.push_back(31); - boundary38.push_back(45); - boundary38.push_back(37); - boundary38.push_back(39); - std::vector boundary39; - boundary39.push_back(32); - boundary39.push_back(46); - std::vector boundary40; - boundary40.push_back(33); - boundary40.push_back(47); - boundary40.push_back(39); - boundary40.push_back(41); - std::vector boundary41; - boundary41.push_back(34); - boundary41.push_back(48); - std::vector boundary42; - std::vector boundary43; - boundary43.push_back(42); - boundary43.push_back(44); - std::vector boundary44; - std::vector boundary45; - boundary45.push_back(44); - boundary45.push_back(46); - std::vector boundary46; - std::vector boundary47; - boundary47.push_back(46); - boundary47.push_back(48); - std::vector boundary48; - std::vector< std::vector > boundaries; - boundaries.push_back(boundary0); - boundaries.push_back(boundary1); - boundaries.push_back(boundary2); - boundaries.push_back(boundary3); - boundaries.push_back(boundary4); - boundaries.push_back(boundary5); - boundaries.push_back(boundary6); - boundaries.push_back(boundary7); - boundaries.push_back(boundary8); - boundaries.push_back(boundary9); - boundaries.push_back(boundary10); - boundaries.push_back(boundary11); - boundaries.push_back(boundary12); - boundaries.push_back(boundary13); - boundaries.push_back(boundary14); - boundaries.push_back(boundary15); - boundaries.push_back(boundary16); - boundaries.push_back(boundary17); - boundaries.push_back(boundary18); - boundaries.push_back(boundary19); - boundaries.push_back(boundary20); - boundaries.push_back(boundary21); - boundaries.push_back(boundary22); - boundaries.push_back(boundary23); - boundaries.push_back(boundary24); - boundaries.push_back(boundary25); - boundaries.push_back(boundary26); - boundaries.push_back(boundary27); - boundaries.push_back(boundary28); - boundaries.push_back(boundary29); - boundaries.push_back(boundary30); - boundaries.push_back(boundary31); - boundaries.push_back(boundary32); - boundaries.push_back(boundary33); - boundaries.push_back(boundary34); - boundaries.push_back(boundary35); - boundaries.push_back(boundary36); - boundaries.push_back(boundary37); - boundaries.push_back(boundary38); - boundaries.push_back(boundary39); - boundaries.push_back(boundary40); - boundaries.push_back(boundary41); - boundaries.push_back(boundary42); - boundaries.push_back(boundary43); - boundaries.push_back(boundary44); - boundaries.push_back(boundary45); - boundaries.push_back(boundary46); - boundaries.push_back(boundary47); - boundaries.push_back(boundary48); - - - - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { - std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); - for (size_t j = 0; j != bd.size(); ++j) { - BOOST_CHECK(boundaries[i][j] == bd[j]); - } - } -} - -BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - - - std::vector coboundaryElements; - coboundaryElements.push_back(7); - coboundaryElements.push_back(1); - coboundaryElements.push_back(8); - coboundaryElements.push_back(9); - coboundaryElements.push_back(1); - coboundaryElements.push_back(3); - coboundaryElements.push_back(10); - coboundaryElements.push_back(11); - coboundaryElements.push_back(3); - coboundaryElements.push_back(5); - coboundaryElements.push_back(12); - coboundaryElements.push_back(13); - coboundaryElements.push_back(5); - coboundaryElements.push_back(8); - coboundaryElements.push_back(8); - coboundaryElements.push_back(10); - coboundaryElements.push_back(10); - coboundaryElements.push_back(12); - coboundaryElements.push_back(12); - coboundaryElements.push_back(7); - coboundaryElements.push_back(21); - coboundaryElements.push_back(15); - coboundaryElements.push_back(8); - coboundaryElements.push_back(22); - coboundaryElements.push_back(9); - coboundaryElements.push_back(23); - coboundaryElements.push_back(15); - coboundaryElements.push_back(17); - coboundaryElements.push_back(10); - coboundaryElements.push_back(24); - coboundaryElements.push_back(11); - coboundaryElements.push_back(25); - coboundaryElements.push_back(17); - coboundaryElements.push_back(19); - coboundaryElements.push_back(12); - coboundaryElements.push_back(26); - coboundaryElements.push_back(13); - coboundaryElements.push_back(27); - coboundaryElements.push_back(19); - coboundaryElements.push_back(22); - coboundaryElements.push_back(22); - coboundaryElements.push_back(24); - coboundaryElements.push_back(24); - coboundaryElements.push_back(26); - coboundaryElements.push_back(26); - coboundaryElements.push_back(21); - coboundaryElements.push_back(35); - coboundaryElements.push_back(29); - coboundaryElements.push_back(22); - coboundaryElements.push_back(36); - coboundaryElements.push_back(23); - coboundaryElements.push_back(37); - coboundaryElements.push_back(29); - coboundaryElements.push_back(31); - coboundaryElements.push_back(24); - coboundaryElements.push_back(38); - coboundaryElements.push_back(25); - coboundaryElements.push_back(39); - coboundaryElements.push_back(31); - coboundaryElements.push_back(33); - coboundaryElements.push_back(26); - coboundaryElements.push_back(40); - coboundaryElements.push_back(27); - coboundaryElements.push_back(41); - coboundaryElements.push_back(33); - coboundaryElements.push_back(36); - coboundaryElements.push_back(36); - coboundaryElements.push_back(38); - coboundaryElements.push_back(38); - coboundaryElements.push_back(40); - coboundaryElements.push_back(40); - coboundaryElements.push_back(35); - coboundaryElements.push_back(43); - coboundaryElements.push_back(36); - coboundaryElements.push_back(37); - coboundaryElements.push_back(43); - coboundaryElements.push_back(45); - coboundaryElements.push_back(38); - coboundaryElements.push_back(39); - coboundaryElements.push_back(45); - coboundaryElements.push_back(47); - coboundaryElements.push_back(40); - coboundaryElements.push_back(41); - coboundaryElements.push_back(47); - size_t number = 0; - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { - std::vector< size_t > bd = increasing.get_coboundary_of_a_cell(i); - for (size_t j = 0; j != bd.size(); ++j) { - BOOST_CHECK(coboundaryElements[number] == bd[j]); - ++number; - } - - } -} - -BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - - std::vector dim; - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { - BOOST_CHECK(increasing.get_dimension_of_a_cell(i) == dim[i]); - } -} - -BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - - std::vector< unsigned > dim; - dim.push_back(0); - dim.push_back(0); - dim.push_back(0); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - - std::vector fil; - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(2); - fil.push_back(2); - fil.push_back(2); - fil.push_back(2); - fil.push_back(2); - fil.push_back(2); - fil.push_back(3); - fil.push_back(3); - fil.push_back(3); - fil.push_back(3); - fil.push_back(3); - fil.push_back(3); - fil.push_back(4); - fil.push_back(4); - fil.push_back(4); - fil.push_back(4); - fil.push_back(4); - fil.push_back(4); - fil.push_back(5); - fil.push_back(5); - fil.push_back(5); - fil.push_back(5); - fil.push_back(6); - fil.push_back(6); - fil.push_back(6); - fil.push_back(6); - fil.push_back(7); - fil.push_back(7); - fil.push_back(7); - fil.push_back(7); - fil.push_back(7); - fil.push_back(7); - fil.push_back(8); - fil.push_back(8); - fil.push_back(8); - fil.push_back(8); - fil.push_back(9); - fil.push_back(9); - fil.push_back(9); - fil.push_back(9); - - - Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range(); - size_t position = 0; - for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { - BOOST_CHECK(increasing.dimension(*it) == dim[position]); - BOOST_CHECK(increasing.filtration(*it) == fil[position]); - ++position; - } -} +#include +#include +#include +#include + +// standard stuff +#include +#include + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "cubical_complex" +#include + + +using namespace std; +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + + + +BOOST_AUTO_TEST_CASE(check_dimension) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + BOOST_CHECK(increasing.dimension() == 2); +} + +BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { + std::vector< double > expectedFiltrationValues1; + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(100); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + + std::vector< double > expectedFiltrationValues2; + expectedFiltrationValues2.push_back(1); + expectedFiltrationValues2.push_back(2); + expectedFiltrationValues2.push_back(3); + expectedFiltrationValues2.push_back(4); + expectedFiltrationValues2.push_back(5); + expectedFiltrationValues2.push_back(6); + expectedFiltrationValues2.push_back(7); + expectedFiltrationValues2.push_back(8); + expectedFiltrationValues2.push_back(9); + + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector< double > oneDimensionalCycle; + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(100); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle); + + + int i = 0; + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator + it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { + BOOST_CHECK(*it == expectedFiltrationValues2[i]); + ++i; + } + i = 0; + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator + it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { + BOOST_CHECK(*it == expectedFiltrationValues1[i]); + ++i; + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { + + std::vector boundary0; + std::vector boundary1; + boundary1.push_back(0); + boundary1.push_back(2); + std::vector boundary2; + std::vector boundary3; + boundary3.push_back(2); + boundary3.push_back(4); + std::vector boundary4; + std::vector boundary5; + boundary5.push_back(4); + boundary5.push_back(6); + std::vector boundary6; + std::vector boundary7; + boundary7.push_back(0); + boundary7.push_back(14); + std::vector boundary8; + boundary8.push_back(1); + boundary8.push_back(15); + boundary8.push_back(7); + boundary8.push_back(9); + std::vector boundary9; + boundary9.push_back(2); + boundary9.push_back(16); + std::vector boundary10; + boundary10.push_back(3); + boundary10.push_back(17); + boundary10.push_back(9); + boundary10.push_back(11); + std::vector boundary11; + boundary11.push_back(4); + boundary11.push_back(18); + std::vector boundary12; + boundary12.push_back(5); + boundary12.push_back(19); + boundary12.push_back(11); + boundary12.push_back(13); + std::vector boundary13; + boundary13.push_back(6); + boundary13.push_back(20); + std::vector boundary14; + std::vector boundary15; + boundary15.push_back(14); + boundary15.push_back(16); + std::vector boundary16; + std::vector boundary17; + boundary17.push_back(16); + boundary17.push_back(18); + std::vector boundary18; + std::vector boundary19; + boundary19.push_back(18); + boundary19.push_back(20); + std::vector boundary20; + std::vector boundary21; + boundary21.push_back(14); + boundary21.push_back(28); + std::vector boundary22; + boundary22.push_back(15); + boundary22.push_back(29); + boundary22.push_back(21); + boundary22.push_back(23); + std::vector boundary23; + boundary23.push_back(16); + boundary23.push_back(30); + std::vector boundary24; + boundary24.push_back(17); + boundary24.push_back(31); + boundary24.push_back(23); + boundary24.push_back(25); + std::vector boundary25; + boundary25.push_back(18); + boundary25.push_back(32); + std::vector boundary26; + boundary26.push_back(19); + boundary26.push_back(33); + boundary26.push_back(25); + boundary26.push_back(27); + std::vector boundary27; + boundary27.push_back(20); + boundary27.push_back(34); + std::vector boundary28; + std::vector boundary29; + boundary29.push_back(28); + boundary29.push_back(30); + std::vector boundary30; + std::vector boundary31; + boundary31.push_back(30); + boundary31.push_back(32); + std::vector boundary32; + std::vector boundary33; + boundary33.push_back(32); + boundary33.push_back(34); + std::vector boundary34; + std::vector boundary35; + boundary35.push_back(28); + boundary35.push_back(42); + std::vector boundary36; + boundary36.push_back(29); + boundary36.push_back(43); + boundary36.push_back(35); + boundary36.push_back(37); + std::vector boundary37; + boundary37.push_back(30); + boundary37.push_back(44); + std::vector boundary38; + boundary38.push_back(31); + boundary38.push_back(45); + boundary38.push_back(37); + boundary38.push_back(39); + std::vector boundary39; + boundary39.push_back(32); + boundary39.push_back(46); + std::vector boundary40; + boundary40.push_back(33); + boundary40.push_back(47); + boundary40.push_back(39); + boundary40.push_back(41); + std::vector boundary41; + boundary41.push_back(34); + boundary41.push_back(48); + std::vector boundary42; + std::vector boundary43; + boundary43.push_back(42); + boundary43.push_back(44); + std::vector boundary44; + std::vector boundary45; + boundary45.push_back(44); + boundary45.push_back(46); + std::vector boundary46; + std::vector boundary47; + boundary47.push_back(46); + boundary47.push_back(48); + std::vector boundary48; + std::vector< std::vector > boundaries; + boundaries.push_back(boundary0); + boundaries.push_back(boundary1); + boundaries.push_back(boundary2); + boundaries.push_back(boundary3); + boundaries.push_back(boundary4); + boundaries.push_back(boundary5); + boundaries.push_back(boundary6); + boundaries.push_back(boundary7); + boundaries.push_back(boundary8); + boundaries.push_back(boundary9); + boundaries.push_back(boundary10); + boundaries.push_back(boundary11); + boundaries.push_back(boundary12); + boundaries.push_back(boundary13); + boundaries.push_back(boundary14); + boundaries.push_back(boundary15); + boundaries.push_back(boundary16); + boundaries.push_back(boundary17); + boundaries.push_back(boundary18); + boundaries.push_back(boundary19); + boundaries.push_back(boundary20); + boundaries.push_back(boundary21); + boundaries.push_back(boundary22); + boundaries.push_back(boundary23); + boundaries.push_back(boundary24); + boundaries.push_back(boundary25); + boundaries.push_back(boundary26); + boundaries.push_back(boundary27); + boundaries.push_back(boundary28); + boundaries.push_back(boundary29); + boundaries.push_back(boundary30); + boundaries.push_back(boundary31); + boundaries.push_back(boundary32); + boundaries.push_back(boundary33); + boundaries.push_back(boundary34); + boundaries.push_back(boundary35); + boundaries.push_back(boundary36); + boundaries.push_back(boundary37); + boundaries.push_back(boundary38); + boundaries.push_back(boundary39); + boundaries.push_back(boundary40); + boundaries.push_back(boundary41); + boundaries.push_back(boundary42); + boundaries.push_back(boundary43); + boundaries.push_back(boundary44); + boundaries.push_back(boundary45); + boundaries.push_back(boundary46); + boundaries.push_back(boundary47); + boundaries.push_back(boundary48); + + + + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); + for (size_t j = 0; j != bd.size(); ++j) { + BOOST_CHECK(boundaries[i][j] == bd[j]); + } + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + + std::vector coboundaryElements; + coboundaryElements.push_back(7); + coboundaryElements.push_back(1); + coboundaryElements.push_back(8); + coboundaryElements.push_back(9); + coboundaryElements.push_back(1); + coboundaryElements.push_back(3); + coboundaryElements.push_back(10); + coboundaryElements.push_back(11); + coboundaryElements.push_back(3); + coboundaryElements.push_back(5); + coboundaryElements.push_back(12); + coboundaryElements.push_back(13); + coboundaryElements.push_back(5); + coboundaryElements.push_back(8); + coboundaryElements.push_back(8); + coboundaryElements.push_back(10); + coboundaryElements.push_back(10); + coboundaryElements.push_back(12); + coboundaryElements.push_back(12); + coboundaryElements.push_back(7); + coboundaryElements.push_back(21); + coboundaryElements.push_back(15); + coboundaryElements.push_back(8); + coboundaryElements.push_back(22); + coboundaryElements.push_back(9); + coboundaryElements.push_back(23); + coboundaryElements.push_back(15); + coboundaryElements.push_back(17); + coboundaryElements.push_back(10); + coboundaryElements.push_back(24); + coboundaryElements.push_back(11); + coboundaryElements.push_back(25); + coboundaryElements.push_back(17); + coboundaryElements.push_back(19); + coboundaryElements.push_back(12); + coboundaryElements.push_back(26); + coboundaryElements.push_back(13); + coboundaryElements.push_back(27); + coboundaryElements.push_back(19); + coboundaryElements.push_back(22); + coboundaryElements.push_back(22); + coboundaryElements.push_back(24); + coboundaryElements.push_back(24); + coboundaryElements.push_back(26); + coboundaryElements.push_back(26); + coboundaryElements.push_back(21); + coboundaryElements.push_back(35); + coboundaryElements.push_back(29); + coboundaryElements.push_back(22); + coboundaryElements.push_back(36); + coboundaryElements.push_back(23); + coboundaryElements.push_back(37); + coboundaryElements.push_back(29); + coboundaryElements.push_back(31); + coboundaryElements.push_back(24); + coboundaryElements.push_back(38); + coboundaryElements.push_back(25); + coboundaryElements.push_back(39); + coboundaryElements.push_back(31); + coboundaryElements.push_back(33); + coboundaryElements.push_back(26); + coboundaryElements.push_back(40); + coboundaryElements.push_back(27); + coboundaryElements.push_back(41); + coboundaryElements.push_back(33); + coboundaryElements.push_back(36); + coboundaryElements.push_back(36); + coboundaryElements.push_back(38); + coboundaryElements.push_back(38); + coboundaryElements.push_back(40); + coboundaryElements.push_back(40); + coboundaryElements.push_back(35); + coboundaryElements.push_back(43); + coboundaryElements.push_back(36); + coboundaryElements.push_back(37); + coboundaryElements.push_back(43); + coboundaryElements.push_back(45); + coboundaryElements.push_back(38); + coboundaryElements.push_back(39); + coboundaryElements.push_back(45); + coboundaryElements.push_back(47); + coboundaryElements.push_back(40); + coboundaryElements.push_back(41); + coboundaryElements.push_back(47); + size_t number = 0; + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + std::vector< size_t > bd = increasing.get_coboundary_of_a_cell(i); + for (size_t j = 0; j != bd.size(); ++j) { + BOOST_CHECK(coboundaryElements[number] == bd[j]); + ++number; + } + + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + std::vector dim; + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + BOOST_CHECK(increasing.get_dimension_of_a_cell(i) == dim[i]); + } +} + +BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + std::vector< unsigned > dim; + dim.push_back(0); + dim.push_back(0); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + + std::vector fil; + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(5); + fil.push_back(5); + fil.push_back(5); + fil.push_back(5); + fil.push_back(6); + fil.push_back(6); + fil.push_back(6); + fil.push_back(6); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(8); + fil.push_back(8); + fil.push_back(8); + fil.push_back(8); + fil.push_back(9); + fil.push_back(9); + fil.push_back(9); + fil.push_back(9); + + + Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range(); + size_t position = 0; + for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { + BOOST_CHECK(increasing.dimension(*it) == dim[position]); + BOOST_CHECK(increasing.filtration(*it) == fil[position]); + ++position; + } +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a66d90b6..2ef89f84 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,10 +44,10 @@ else() # Gudhi compilation part include_directories(include) - add_subdirectory(example/Simplex_tree) - add_subdirectory(example/Persistent_cohomology) - add_subdirectory(example/Skeleton_blocker) - add_subdirectory(example/Contraction) + #add_subdirectory(example/Simplex_tree) + #add_subdirectory(example/Persistent_cohomology) + #add_subdirectory(example/Skeleton_blocker) + #add_subdirectory(example/Contraction) add_subdirectory(example/Bitmap_cubical_complex) # data points generator -- cgit v1.2.3 From f70e386fc98f1dbd8287d1cb7cc715710a8f751b Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 7 Dec 2015 14:35:31 +0000 Subject: Merged with trunk and removed stuff git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@933 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d417402ca5874b490f3a28f3c9b6deb4565f55fe --- src/Witness_complex/example/CMakeLists.txt | 90 ---------------------- .../example/simple_witness_complex.cpp | 2 - 2 files changed, 92 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index ff372d16..83f9c71c 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -9,93 +9,3 @@ project(GUDHIWitnessComplex) #target_link_libraries(witness_complex_from_file ${EIGEN3_LIBRARIES} ${CGAL_LIBRARY}) add_test( witness_complex_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - add_executable( witness_complex_from_off witness_complex_from_off.cpp ) - - add_executable( witness_complex_from_wl_matrix witness_complex_from_wl_matrix.cpp ) - - -# An example with Simplex-tree using CGAL alpha_shapes_3 - -#find_package(Eigen3 3.1.0) -#if(GMP_FOUND AND CGAL_FOUND) -# message("CGAL_lib = ${CGAL_LIBRARIES_DIR}") -# message("GMP_LIBRARIES = ${GMP_LIBRARIES}") -# message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") -# #message("EIGEN3_LIBRARIES = ${EIGEN3_LIBRARIES}") -# INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIRS}) -# INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) -# INCLUDE_DIRECTORIES(${CGAL_INCLUDE_DIRS}) -# add_executable (witness_complex_knn_landmarks witness_complex_knn_landmarks.cpp ) -# target_link_libraries(witness_complex_knn_landmarks ${EIGEN3_LIBRARIES} ${CGAL_LIBRARY}) -# add_test(witness_complex_knn_landmarks ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_knn_landmarks ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) -#endif() - -# need CGAL 4.6 -# cmake -DCGAL_DIR=~/workspace/CGAL-4.6-beta1 ../../.. -if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.6.0) - message(STATUS "CGAL version: ${CGAL_VERSION}.") - - include( ${CGAL_USE_FILE} ) - - find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) - message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") - include( ${EIGEN3_USE_FILE} ) - message(STATUS "Eigen3 use file: ${EIGEN3_USE_FILE}.") - include_directories (BEFORE "../../include") - - add_executable ( witness_complex_knn_landmarks witness_complex_knn_landmarks.cpp ) - target_link_libraries(witness_complex_knn_landmarks ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(witness_complex_knn_landmarks ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_knn_landmarks ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - #add_executable ( witness_complex_perturbations witness_complex_perturbations.cpp ) - #target_link_libraries(witness_complex_perturbations ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - #add_test(witness_complex_perturbations ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_perturbations ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") - endif() - else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") - endif () -endif() -if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.6.0) - message(STATUS "CGAL version: ${CGAL_VERSION}.") - - include( ${CGAL_USE_FILE} ) - - find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) - message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") - include( ${EIGEN3_USE_FILE} ) - include_directories (BEFORE "../../include") - add_executable ( witness_complex_perturbations witness_complex_perturbations.cpp ) - target_link_libraries(witness_complex_perturbations ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(witness_complex_perturbations ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_perturbations ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - add_executable ( witness_complex_flat_torus witness_complex_flat_torus.cpp ) - target_link_libraries(witness_complex_flat_torus ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(witness_complex_flat_torus ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_flat_torus ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - add_executable ( witness_complex_sphere witness_complex_sphere.cpp ) - target_link_libraries(witness_complex_sphere ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(witness_complex_sphere ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_sphere ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - add_executable ( relaxed_witness_complex_sphere relaxed_witness_complex_sphere.cpp ) - add_test(witness_complex_sphere ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_sphere ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - add_executable ( witness_complex_protected_delaunay witness_complex_protected_delaunay.cpp ) - target_link_libraries(witness_complex_protected_delaunay ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(witness_complex_protected_delaunay ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_protected_delaunay ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - add_executable ( witness_complex_cubic_systems witness_complex_cubic_systems.cpp ) - target_link_libraries(witness_complex_cubic_systems ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(witness_complex_cubic_systems ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_cubic_systems ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - add_executable ( witness_complex_cube witness_complex_cube.cpp ) - target_link_libraries(witness_complex_cube ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(witness_complex_cube ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_cube ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - add_executable ( witness_complex_epsilon witness_complex_epsilon.cpp ) - target_link_libraries(witness_complex_epsilon ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(witness_complex_epsilon ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_epsilon ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") - endif() - else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") - endif () -endif() diff --git a/src/Witness_complex/example/simple_witness_complex.cpp b/src/Witness_complex/example/simple_witness_complex.cpp index 43921c4e..e95f67a8 100644 --- a/src/Witness_complex/example/simple_witness_complex.cpp +++ b/src/Witness_complex/example/simple_witness_complex.cpp @@ -48,7 +48,5 @@ int main (int argc, char * const argv[]) typeVectorVertex witness10 = {5,0,1,3,6,2,4}; KNN.push_back(witness10); typeVectorVertex witness11 = {5,6,1,0,2,3,4}; KNN.push_back(witness11); typeVectorVertex witness12 = {1,6,0,5,2,3,4}; KNN.push_back(witness12); - std::cout << "Let the carnage begin!\n"; witnessComplex.witness_complex(KNN); - std::cout << "Howdy world!\n"; } -- cgit v1.2.3 From 9325765e94b1bd43600fe345a033216bce55873f Mon Sep 17 00:00:00 2001 From: skachano Date: Mon, 7 Dec 2015 15:00:41 +0000 Subject: Removed things from Witness_complex.h git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@935 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 00450ae8c849a35d5adc9baa3f35ef8fae1b664a --- .../include/gudhi/Witness_complex.h | 632 +-------------------- 1 file changed, 3 insertions(+), 629 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 201d6525..8316fe3e 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -39,12 +39,6 @@ #include #include -// Needed for nearest neighbours -//#include -//#include -//#include -//#include - // Needed for the adjacency graph in bad link search #include #include @@ -53,8 +47,7 @@ namespace Gudhi { - /** \addtogroup simplex_tree - * Witness complex is a simplicial complex defined on two sets of points in \f$\mathbf{R}^D\f$: + /** Witness complex is a simplicial complex defined on two sets of points in \f$\mathbf{R}^D\f$: * \f$W\f$ set of witnesses and \f$L \subseteq W\f$ set of landmarks. The simplices are based on points in \f$L\f$ * and a simplex belongs to the witness complex if and only if it is witnessed (there exists a point \f$w \in W\f$ such that * w is closer to the vertices of this simplex than others) and all of its faces are witnessed as well. @@ -107,12 +100,8 @@ namespace Gudhi { typedef std::list< Vertex_handle > ActiveWitnessList; private: - /** Number of landmarks - */ - int nbL; - /** Desired density - */ - double density; + int nbL; // Number of landmarks + double density; // Desired density public: @@ -142,7 +131,6 @@ namespace Gudhi { std::cout << "**Start the procedure witness_complex" << std::endl; //Construction of the active witness list int nbW = knn.size(); - //int nbL = knn.at(0).size(); typeVectorVertex vv; typeSimplex simplex; typePairSimplexBool returnValue; @@ -160,60 +148,13 @@ namespace Gudhi { /* TODO Error if not inserted : normally no need here though*/ } int k=1; /* current dimension in iterative construction */ - //std::cout << "Successfully added landmarks" << std::endl; - // PRINT2 - //print_sc(root()); std::cout << std::endl; - /* - int u,v; // two extremities of an edge - int count = 0; - if (nbL > 1) // if the supposed dimension of the complex is >0 - { - for (int i=0; i != nbW; ++i) - { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - vv = {u,v}; - returnValue = this->insert_simplex(vv,Filtration_value(0.0)); - if (returnValue.second) - count++; - //print_sc(root()); std::cout << std::endl; - //std::cout << "Added edges" << std::endl; - } - std::cout << "The number of edges = " << count << std::endl; - count = 0; - //print_sc(root()); - for (int i=0; i != nbW; ++i) - { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - if ( u > v) - { - u = v; - v = knn[i][0]; - knn[i][0] = knn[i][1]; - knn[i][1] = v; - } - Simplex_handle sh; - vv = {u,v}; - //if (u==v) std::cout << "Bazzinga!\n"; - sh = (root()->find(u))->second.children()->find(v); - active_w.push_back(i); - } - } - */ for (int i=0; i != nbW; ++i) active_w.push_back(i); std::cout << "k=0, active witnesses: " << active_w.size() << std::endl; //std::cout << "Successfully added edges" << std::endl; - count_good = {0}; - count_bad = {0}; int D = knn[0].size(); while (!active_w.empty() && k < D ) { - count_good.push_back(0); - count_bad.push_back(0); //std::cout << "Started the step k=" << k << std::endl; typename ActiveWitnessList::iterator it = active_w.begin(); while (it != active_w.end()) @@ -232,23 +173,9 @@ namespace Gudhi { active_w.erase(it++); //First increase the iterator and then erase the previous element } std::cout << "k=" << k << ", active witnesses: " << active_w.size() << std::endl; - //std::cout << "** k=" << k << ", num_simplices: " < > WL; - // landmark_choice_by_random_points(point_vector, point_vector.size(), WL); - // witness_complex(WL); - // } private: @@ -390,9 +317,6 @@ private: template void landmark_choice_by_furthest_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) { - //std::cout << "Enter landmark_choice_by_furthest_points "<< std::endl; - //std::cout << "W="; print_vvector(W); - //double density = 5.; Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks typeVectorVertex chosen_landmarks; // landmark list @@ -402,7 +326,6 @@ private: double curr_dist; // used to stock the distance from the current point to L double infty = std::numeric_limits::infinity(); // infinity (see next entry) std::vector< double > dist_to_L(nbP,infty); // vector of current distances to L from points - // double mindist = infty; int curr_max_w=0; // the point currently furthest from L int j; int temp_swap_int; @@ -418,30 +341,18 @@ private: { //curr_max_w at this point is the next landmark chosen_landmarks.push_back(curr_max_w); - //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; - //std::cout << "WL="; print_vvector(WL); - //std::cout << "WLD="; print_vvector(wit_land_dist); - //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; for (auto v: WL) v.push_back(current_number_of_landmarks); for (int i = 0; i < nbP; ++i) { - // iteration on points in W. update of distance vectors - - //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; - //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); - //std::cout << "The problem is not in distance function\n"; wit_land_dist[i].push_back(curr_dist); WL[i].push_back(current_number_of_landmarks); - //std::cout << "Push't back\n"; if (curr_dist < dist_to_L[i]) dist_to_L[i] = curr_dist; j = current_number_of_landmarks; - //std::cout << "First half complete\n"; while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) { - // sort the closest landmark vector for every witness temp_swap_int = WL[i][j]; WL[i][j] = WL[i][j-1]; WL[i][j-1] = temp_swap_int; @@ -450,12 +361,7 @@ private: wit_land_dist[i][j-1] = temp_swap_double; --j; } - //std::cout << "result WL="; print_vvector(WL); - //std::cout << "result WLD="; print_vvector(wit_land_dist); - //std::cout << "result distL="; print_vector(dist_to_L); std::cout << std::endl; - //std::cout << "End loop\n"; } - //std::cout << "Distance to landmarks="; print_vector(dist_to_L); std::cout << std::endl; curr_max_dist = 0; for (int i = 0; i < nbP; ++i) { if (dist_to_L[i] > curr_max_dist) @@ -464,76 +370,9 @@ private: curr_max_w = i; } } - //std::cout << "Chose " << curr_max_w << " as new landmark\n"; } - //std::cout << endl; } - /** \brief Landmark choice strategy by taking random vertices for landmarks. - * - */ - - // template - // void landmark_choice_by_random_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) - // { - // std::cout << "Enter landmark_choice_by_random_points "<< std::endl; - // //std::cout << "W="; print_vvector(W); - // std::unordered_set< int > chosen_landmarks; // landmark set - - // Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks - - // WL = KNearestNeighbours(nbP,std::vector()); - // int current_number_of_landmarks=0; // counter for landmarks - - // srand(24660); - // int chosen_landmark = rand()%nbP; - // double curr_dist; - - // //int j; - // //int temp_swap_int; - // //double temp_swap_double; - - - // for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) - // { - // while (chosen_landmarks.find(chosen_landmark) != chosen_landmarks.end()) - // { - // srand((int)clock()); - // chosen_landmark = rand()% nbP; - // //std::cout << chosen_landmark << "\n"; - // } - // chosen_landmarks.insert(chosen_landmark); - // //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; - // //std::cout << "WL="; print_vvector(WL); - // //std::cout << "WLD="; print_vvector(wit_land_dist); - // //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; - // for (auto v: WL) - // v.push_back(current_number_of_landmarks); - // for (int i = 0; i < nbP; ++i) - // { - // // iteration on points in W. update of distance vectors - - // //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; - // //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; - // curr_dist = euclidean_distance(W[i],W[chosen_landmark]); - // //std::cout << "The problem is not in distance function\n"; - // wit_land_dist[i].push_back(curr_dist); - // WL[i].push_back(current_number_of_landmarks); - // //std::cout << "Push't back\n"; - // //j = current_number_of_landmarks; - // //std::cout << "First half complete\n"; - // //std::cout << "result WL="; print_vvector(WL); - // //std::cout << "result WLD="; print_vvector(wit_land_dist); - // //std::cout << "End loop\n"; - // } - // } - // for (int i = 0; i < nbP; i++) - // { - // sort(WL[i].begin(), WL[i].end(), [&](int j1, int j2){return wit_land_dist[i][j1] < wit_land_dist[i][j2];}); - // } - // //std::cout << endl; - // } - /** \brief Landmark choice strategy by taking random vertices for landmarks. * */ @@ -541,59 +380,19 @@ private: // template void landmark_choice_by_random_points(Point_Vector &W, int nbP, std::set &L) { - std::cout << "Enter landmark_choice_by_random_points "<< std::endl; - //std::cout << "W="; print_vvector(W); - //std::unordered_set< int > chosen_landmarks; // landmark set - - //Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks - - //WL = KNearestNeighbours(nbP,std::vector()); int current_number_of_landmarks=0; // counter for landmarks srand(24660); int chosen_landmark = rand()%nbP; - //double curr_dist; - //int j; - //int temp_swap_int; - //double temp_swap_double; for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) { while (L.find(chosen_landmark) != L.end()) { srand((int)clock()); chosen_landmark = rand()% nbP; - //std::cout << chosen_landmark << "\n"; } L.insert(chosen_landmark); - //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; - //std::cout << "WL="; print_vvector(WL); - //std::cout << "WLD="; print_vvector(wit_land_dist); - //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; - // for (auto v: WL) - // v.push_back(current_number_of_landmarks); - // for (int i = 0; i < nbP; ++i) - // { - // // iteration on points in W. update of distance vectors - - // //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; - // //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; - // curr_dist = euclidean_distance(W[i],W[chosen_landmark]); - // //std::cout << "The problem is not in distance function\n"; - // wit_land_dist[i].push_back(curr_dist); - // WL[i].push_back(current_number_of_landmarks); - // //std::cout << "Push't back\n"; - // //j = current_number_of_landmarks; - // //std::cout << "First half complete\n"; - // //std::cout << "result WL="; print_vvector(WL); - // //std::cout << "result WLD="; print_vvector(wit_land_dist); - // //std::cout << "End loop\n"; - // } } - // for (int i = 0; i < nbP; i++) - // { - // sort(WL[i].begin(), WL[i].end(), [&](int j1, int j2){return wit_land_dist[i][j1] < wit_land_dist[i][j2];}); - // } - //std::cout << endl; } @@ -610,7 +409,6 @@ private: typedef bool (*comp)(dist_i,dist_i); for (int W_i = 0; W_i < nbP; W_i++) { - //std::cout << "<<<<<<<<<<<<<<" << W_i <<"\n"; std::priority_queue, comp> l_heap([&](dist_i j1, dist_i j2){return j1.first > j2.first;}); std::set::iterator L_it; int L_i; @@ -623,437 +421,13 @@ private: { dist_i dist = l_heap.top(); WL[W_i].push_back(dist.second); - //WL[W_i].insert(WL[W_i].begin(),dist.second); - //std::cout << dist.first << " " << dist.second << std::endl; l_heap.pop(); } } } - /** \brief Returns true if the link is good - */ - bool has_good_link(Vertex_handle v, std::vector< int >& bad_count, std::vector< int >& good_count) - { - std::vector< Vertex_handle > star_vertices; - // Fill star_vertices - star_vertices.push_back(v); - for (auto u: complex_vertex_range()) - { - typeVectorVertex edge = {u,v}; - if (u != v && find(edge) != null_simplex()) - star_vertices.push_back(u); - } - // Find the dimension - typeVectorVertex init_simplex = {star_vertices[0]}; - bool is_pure = true; - std::vector dim_coface(star_vertices.size(), 1); - int d = star_dim(star_vertices, star_vertices.begin()+1, 0, init_simplex, dim_coface.begin()+1) - 1; //link_dim = star_dim - 1 - assert(init_simplex.size() == 1); - if (!is_pure) - std::cout << "Found an impure star around " << v << "\n"; - for (int dc: dim_coface) - is_pure = (dc == dim_coface[0]); - /* - if (d == count_good.size()) - { - std::cout << "Found a star of dimension " << (d+1) << " around " << v << "\nThe star is "; - print_vector(star_vertices); std::cout << std::endl; - } - */ - //if (d == -1) bad_count[0]++; - bool b= (is_pure && link_is_pseudomanifold(star_vertices,d)); - if (d != -1) {if (b) good_count[d]++; else bad_count[d]++;} - if (!is_pure) bad_count[0]++; - return (d != -1 && b && is_pure); - - } - - /** \brief Search and output links around vertices that are not pseudomanifolds - * - */ - /* - void write_bad_links(std::ofstream& out_file) - { - out_file << "Bad links list\n"; - std::cout << "Entered write_bad_links\n"; - for (auto v: complex_vertex_range()) - { - std::cout << "Vertex " << v << ": "; - std::vector< Vertex_handle > link_vertices; - // Fill link_vertices - for (auto u: complex_vertex_range()) - { - typeVectorVertex edge = {u,v}; - if (u != v && find(edge) != null_simplex()) - link_vertices.push_back(u); - } - - print_vector(link_vertices); - std::cout << "\n"; - - // Find the dimension - typeVectorVertex empty_simplex = {}; - int d = link_dim(link_vertices, link_vertices.begin(),-1, empty_simplex); - if (link_is_pseudomanifold(link_vertices,d)) - count_good[d]++; - } - nc = nbL; - for (unsigned int i = 0; i != count_good.size(); i++) - { - out_file << "count_good[" << i << "] = " << count_good[i] << std::endl; - nc -= count_good[i]; - if (count_good[i] != 0) - std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; - } - for (unsigned int i = 0; i != count_bad.size(); i++) - { - out_file << "count_bad[" << i << "] = " << count_bad[i] << std::endl; - nc -= count_bad[i]; - if (count_bad[i] != 0) - std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; - } - std::cout << "not_connected = " << nc << std::endl; - } - */ - private: - - std::vector count_good; - std::vector count_bad; - int nc; - - int star_dim(std::vector< Vertex_handle >& star_vertices, - typename std::vector< Vertex_handle >::iterator curr_v, - int curr_d, - typeVectorVertex& curr_simplex, - typename std::vector< int >::iterator curr_dc) - { - //std::cout << "Entered star_dim for " << *(curr_v-1) << "\n"; - Simplex_handle sh; - int final_d = curr_d; - typename std::vector< Vertex_handle >::iterator it; - typename std::vector< Vertex_handle >::iterator dc_it; - //std::cout << "Current vertex is " << - for (it = curr_v, dc_it = curr_dc; it != star_vertices.end(); ++it, ++dc_it) - { - curr_simplex.push_back(*it); - typeVectorVertex curr_simplex_copy(curr_simplex); - /* - std::cout << "Searching for "; - print_vector(curr_simplex); - std::cout << " curr_dim " << curr_d << " final_dim " << final_d; - */ - sh = find(curr_simplex_copy); //Need a copy because find sorts the vector and I want star center to be the first - if (sh != null_simplex()) - { - //std::cout << " -> " << *it << "\n"; - int d = star_dim(star_vertices, it+1, curr_d+1, curr_simplex, dc_it); - if (d >= final_d) - { - final_d = d; - //std::cout << d << " "; - //print_vector(curr_simplex); - //std::cout << std::endl; - } - if (d >= *dc_it) - *dc_it = d; - } - /* - else - std::cout << "\n"; - */ - curr_simplex.pop_back(); - } - return final_d; - } - - // color is false is a (d-1)-dim face, true is a d-dim face - //typedef bool Color; - // graph is an adjacency list - typedef typename boost::adjacency_list Adj_graph; - // map that gives to a certain simplex its node in graph and its dimension - //typedef std::pair Reference; - typedef boost::graph_traits::vertex_descriptor Vertex_t; - typedef boost::graph_traits::edge_descriptor Edge_t; - typedef boost::graph_traits::adjacency_iterator Adj_it; - typedef std::pair Out_edge_it; - - typedef boost::container::flat_map Graph_map; - typedef boost::container::flat_map Inv_graph_map; - - /* \brief Verifies if the simplices formed by vertices given by link_vertices - * form a pseudomanifold. - * The idea is to make a bipartite graph, where vertices are the d- and (d-1)-dimensional - * faces and edges represent adjacency between them. - */ - bool link_is_pseudomanifold(std::vector< Vertex_handle >& star_vertices, - int dimension) - { - Adj_graph adj_graph; - Graph_map d_map, f_map; // d_map = map for d-dimensional simplices - // f_map = map for its facets - typeVectorVertex init_vector = {}; - add_vertices_to_link_graph(star_vertices, - star_vertices.begin()+1, - adj_graph, - d_map, - f_map, - init_vector, - 0, dimension); - //std::cout << "DMAP_SIZE: " << d_map.size() << "\n"; - //std::cout << "FMAP_SIZE: " << f_map.size() << "\n"; - add_edges_to_link_graph(adj_graph, d_map, f_map); - for (auto f_map_it : f_map) - { - //std::cout << "Degree of " << f_map_it.first->first << " is " << boost::out_degree(f_map_it.second, adj_graph) << "\n"; - if (boost::out_degree(f_map_it.second, adj_graph) != 2) - { - /* - if (boost::out_degree(f_map_it.second, adj_graph) >= 3) - { - std::cout << "This simplex has 3+ cofaces: "; - for(auto v : simplex_vertex_range(f_map_it.first)) - std::cout << v << " "; - std::cout << std::endl; - Adj_it ai, ai_end; - for (std::tie(ai, ai_end) = boost::adjacent_vertices(f_map_it.second, adj_graph); ai != ai_end; ++ai) - { - - } - } - */ - count_bad[dimension]++; - return false; - } - } - // At this point I know that all (d-1)-simplices are adjacent to exactly 2 d-simplices - // What is left is to check the connexity - //std::vector components(boost::num_vertices(adj_graph)); - return true; //Forget the connexity - //return (boost::connected_components(adj_graph, &components[0]) == 1); - } - - public: -bool complex_is_pseudomanifold(int dimension) - { - Adj_graph adj_graph; - Graph_map d_map, f_map; // d_map = map for d-dimensional simplices - // f_map = map for its facets - Inv_graph_map inv_d_map; - typeVectorVertex init_vector = {}; - std::vector star_vertices; - for (int v: complex_vertex_range()) - star_vertices.push_back(v); - add_max_simplices_to_graph(star_vertices, - star_vertices.begin(), - adj_graph, - d_map, - f_map, - inv_d_map, - init_vector, - 0, dimension); - std::cout << "DMAP_SIZE: " << d_map.size() << "\n"; - std::cout << "FMAP_SIZE: " << f_map.size() << "\n"; - add_edges_to_link_graph(adj_graph, d_map, f_map); - for (auto f_map_it : f_map) - { - //std::cout << "Degree of " << f_map_it.first->first << " is " << boost::out_degree(f_map_it.second, adj_graph) << "\n"; - if (boost::out_degree(f_map_it.second, adj_graph) != 2) - { - if (boost::out_degree(f_map_it.second, adj_graph) >= 3) - { - std::cout << "This simplex has 3+ cofaces: "; - for(auto v : simplex_vertex_range(f_map_it.first)) - std::cout << v << " "; - std::cout << std::endl; - Adj_it ai, ai_end; - for (std::tie(ai, ai_end) = boost::adjacent_vertices(f_map_it.second, adj_graph); ai != ai_end; ++ai) - { - auto it = inv_d_map.find(*ai); - assert (it != inv_d_map.end()); - Simplex_handle sh = it->second; - for(auto v : simplex_vertex_range(sh)) - std::cout << v << " "; - std::cout << std::endl; - } - } - count_bad[dimension]++; - return false; - } - } - // At this point I know that all (d-1)-simplices are adjacent to exactly 2 d-simplices - // What is left is to check the connexity - //std::vector components(boost::num_vertices(adj_graph)); - return true; //Forget the connexity - //return (boost::connected_components(adj_graph, &components[0]) == 1); - } - private: - void add_vertices_to_link_graph(typeVectorVertex& star_vertices, - typename typeVectorVertex::iterator curr_v, - Adj_graph& adj_graph, - Graph_map& d_map, - Graph_map& f_map, - typeVectorVertex& curr_simplex, - int curr_d, - int link_dimension) - { - Simplex_handle sh; - Vertex_t vert; - typename typeVectorVertex::iterator it; - //std::pair resPair; - //typename Graph_map::iterator resPair; - //Add vertices - //std::cout << "Entered add vertices\n"; - for (it = curr_v; it != star_vertices.end(); ++it) - { - curr_simplex.push_back(*it); //push next vertex in question - curr_simplex.push_back(star_vertices[0]); //push the center of the star - /* - std::cout << "Searching for "; - print_vector(curr_simplex); - std::cout << " curr_dim " << curr_d << " d " << dimension << ""; - */ - typeVectorVertex curr_simplex_copy(curr_simplex); - sh = find(curr_simplex_copy); //a simplex of the star - curr_simplex.pop_back(); //pop the center of the star - curr_simplex_copy = typeVectorVertex(curr_simplex); - if (sh != null_simplex()) - { - //std::cout << " added\n"; - if (curr_d == link_dimension) - { - sh = find(curr_simplex_copy); //a simplex of the link - assert(sh != null_simplex()); //ASSERT! - vert = boost::add_vertex(adj_graph); - d_map.emplace(sh,vert); - } - else - { - - if (curr_d == link_dimension-1) - { - sh = find(curr_simplex_copy); //a simplex of the link - assert(sh != null_simplex()); - vert = boost::add_vertex(adj_graph); - f_map.emplace(sh,vert); - } - - //delete (&curr_simplex_copy); //Just so it doesn't stack - add_vertices_to_link_graph(star_vertices, - it+1, - adj_graph, - d_map, - f_map, - curr_simplex, - curr_d+1, link_dimension); - } - } - /* - else - std::cout << "\n"; - */ - curr_simplex.pop_back(); //pop the vertex in question - } - } - void add_edges_to_link_graph(Adj_graph& adj_graph, - Graph_map& d_map, - Graph_map& f_map) - { - Simplex_handle sh; - // Add edges - //std::cout << "Entered add edges:\n"; - typename Graph_map::iterator map_it; - for (auto d_map_pair : d_map) - { - //std::cout << "*"; - sh = d_map_pair.first; - Vertex_t d_vert = d_map_pair.second; - for (auto facet_sh : boundary_simplex_range(sh)) - //for (auto f_map_it : f_map) - { - //std::cout << "'"; - map_it = f_map.find(facet_sh); - //We must have all the facets in the graph at this point - assert(map_it != f_map.end()); - Vertex_t f_vert = map_it->second; - //std::cout << "Added edge " << sh->first << "-" << map_it->first->first << "\n"; - boost::add_edge(d_vert,f_vert,adj_graph); - } - } - } - - void add_max_simplices_to_graph(typeVectorVertex& star_vertices, - typename typeVectorVertex::iterator curr_v, - Adj_graph& adj_graph, - Graph_map& d_map, - Graph_map& f_map, - Inv_graph_map& inv_d_map, - typeVectorVertex& curr_simplex, - int curr_d, - int link_dimension) - { - Simplex_handle sh; - Vertex_t vert; - typename typeVectorVertex::iterator it; - //std::pair resPair; - //typename Graph_map::iterator resPair; - //Add vertices - //std::cout << "Entered add vertices\n"; - for (it = curr_v; it != star_vertices.end(); ++it) - { - curr_simplex.push_back(*it); //push next vertex in question - //curr_simplex.push_back(star_vertices[0]); //push the center of the star - /* - std::cout << "Searching for "; - print_vector(curr_simplex); - std::cout << " curr_dim " << curr_d << " d " << dimension << ""; - */ - typeVectorVertex curr_simplex_copy(curr_simplex); - sh = find(curr_simplex_copy); //a simplex of the star - //curr_simplex.pop_back(); //pop the center of the star - curr_simplex_copy = typeVectorVertex(curr_simplex); - if (sh != null_simplex()) - { - //std::cout << " added\n"; - if (curr_d == link_dimension) - { - sh = find(curr_simplex_copy); //a simplex of the link - assert(sh != null_simplex()); //ASSERT! - vert = boost::add_vertex(adj_graph); - d_map.emplace(sh,vert); - inv_d_map.emplace(vert,sh); - } - else - { - - if (curr_d == link_dimension-1) - { - sh = find(curr_simplex_copy); //a simplex of the link - assert(sh != null_simplex()); - vert = boost::add_vertex(adj_graph); - f_map.emplace(sh,vert); - } - - //delete (&curr_simplex_copy); //Just so it doesn't stack - add_max_simplices_to_graph(star_vertices, - it+1, - adj_graph, - d_map, - f_map, - inv_d_map, - curr_simplex, - curr_d+1, link_dimension); - } - } - /* - else - std::cout << "\n"; - */ - curr_simplex.pop_back(); //pop the vertex in question - } - } - public: /** \brief Verification if every simplex in the complex is witnessed */ -- cgit v1.2.3 From 8f54c437e0b895368c6151584811ce7df1575ea0 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 9 Dec 2015 13:03:03 +0000 Subject: Modified Witness_complex.h + more doc git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@936 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 771e0a9cbfd0035738aee1a07b5f7c1f56bf13fc --- .../example/simple_witness_complex.cpp | 38 +- .../gudhi/Landmark_choice_by_furthest_point.h | 98 +++ .../gudhi/Landmark_choice_by_random_point.h | 82 ++ .../include/gudhi/Relaxed_witness_complex.h | 886 --------------------- .../include/gudhi/Witness_complex.h | 312 +------- .../include/gudhi/Witness_complex_doc.h | 37 + 6 files changed, 283 insertions(+), 1170 deletions(-) create mode 100644 src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h create mode 100644 src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h delete mode 100644 src/Witness_complex/include/gudhi/Relaxed_witness_complex.h create mode 100644 src/Witness_complex/include/gudhi/Witness_complex_doc.h (limited to 'src') diff --git a/src/Witness_complex/example/simple_witness_complex.cpp b/src/Witness_complex/example/simple_witness_complex.cpp index e95f67a8..6731f135 100644 --- a/src/Witness_complex/example/simple_witness_complex.cpp +++ b/src/Witness_complex/example/simple_witness_complex.cpp @@ -23,30 +23,36 @@ #include #include //#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Simplex_tree.h" #include "gudhi/Witness_complex.h" using namespace Gudhi; typedef std::vector< Vertex_handle > typeVectorVertex; +typedef Witness_complex> WitnessComplex; //typedef std::pair typeSimplex; //typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; int main (int argc, char * const argv[]) { - Witness_complex<> witnessComplex = Witness_complex<>(); - std::vector< typeVectorVertex > KNN; - typeVectorVertex witness0 = {1,0,5,2,6,3,4}; KNN.push_back(witness0 ); - typeVectorVertex witness1 = {2,6,4,5,0,1,3}; KNN.push_back(witness1 ); - typeVectorVertex witness2 = {3,4,2,1,5,6,0}; KNN.push_back(witness2 ); - typeVectorVertex witness3 = {4,2,1,3,5,6,0}; KNN.push_back(witness3 ); - typeVectorVertex witness4 = {5,1,6,0,2,3,4}; KNN.push_back(witness4 ); - typeVectorVertex witness5 = {6,0,5,2,1,3,4}; KNN.push_back(witness5 ); - typeVectorVertex witness6 = {0,5,6,1,2,3,4}; KNN.push_back(witness6 ); - typeVectorVertex witness7 = {2,6,4,5,3,1,0}; KNN.push_back(witness7 ); - typeVectorVertex witness8 = {1,2,5,4,3,6,0}; KNN.push_back(witness8 ); - typeVectorVertex witness9 = {3,4,0,6,5,1,2}; KNN.push_back(witness9 ); - typeVectorVertex witness10 = {5,0,1,3,6,2,4}; KNN.push_back(witness10); - typeVectorVertex witness11 = {5,6,1,0,2,3,4}; KNN.push_back(witness11); - typeVectorVertex witness12 = {1,6,0,5,2,3,4}; KNN.push_back(witness12); - witnessComplex.witness_complex(KNN); + Simplex_tree<> complex; + std::vector< typeVectorVertex > knn; + typeVectorVertex witness0 = {1,0,5,2,6,3,4}; knn.push_back(witness0 ); + typeVectorVertex witness1 = {2,6,4,5,0,1,3}; knn.push_back(witness1 ); + typeVectorVertex witness2 = {3,4,2,1,5,6,0}; knn.push_back(witness2 ); + typeVectorVertex witness3 = {4,2,1,3,5,6,0}; knn.push_back(witness3 ); + typeVectorVertex witness4 = {5,1,6,0,2,3,4}; knn.push_back(witness4 ); + typeVectorVertex witness5 = {6,0,5,2,1,3,4}; knn.push_back(witness5 ); + typeVectorVertex witness6 = {0,5,6,1,2,3,4}; knn.push_back(witness6 ); + typeVectorVertex witness7 = {2,6,4,5,3,1,0}; knn.push_back(witness7 ); + typeVectorVertex witness8 = {1,2,5,4,3,6,0}; knn.push_back(witness8 ); + typeVectorVertex witness9 = {3,4,0,6,5,1,2}; knn.push_back(witness9 ); + typeVectorVertex witness10 = {5,0,1,3,6,2,4}; knn.push_back(witness10); + typeVectorVertex witness11 = {5,6,1,0,2,3,4}; knn.push_back(witness11); + typeVectorVertex witness12 = {1,6,0,5,2,3,4}; knn.push_back(witness12); + WitnessComplex witnessComplex(knn, complex, 7); + if (witnessComplex.is_witness_complex(knn)) + std::cout << "Witness complex is good\n"; + else + std::cout << "Witness complex is bad\n"; } diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h new file mode 100644 index 00000000..44bf9dbb --- /dev/null +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -0,0 +1,98 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 . + */ + +#ifndef GUDHI_LANDMARK_CHOICE_BY_FURTHEST_POINT_H_ +#define GUDHI_LANDMARK_CHOICE_BY_FURTHEST_POINT_H_ + +/** + * \class Landmark_choice_by_furthest_point + * \brief The class `Landmark_choice_by_furthest_point` allows to construct the matrix + * of closest landmarks per witness by iteratively choosing the furthest witness + * from the set of already chosen landmarks as the new landmark. + * \ingroup witness_complex + */ + +class Landmark_choice_by_random_point { + +/** + * \brief Landmark choice strategy by iteratively adding the furthest witness from the + * current landmark set as the new landmark. It takes a random access range `points` and + * writes {witness}*{closest landmarks} matrix in `knn`. + */ + + template + Landmark_choice_by_furthest_points(Point_random_access_range &points, + KNearestNeighbours &knn) + { + int nb_points = points.end() - points.begin(); + std::vector> wit_land_dist(nb_points, std::vector()); // distance matrix witness x landmarks + typeVectorVertex chosen_landmarks; // landmark list + + knn = KNearestNeighbours(nb_points, std::vector()); + int current_number_of_landmarks=0; // counter for landmarks + double curr_max_dist = 0; // used for defining the furhest point from L + const double infty = std::numeric_limits::infinity(); // infinity (see next entry) + std::vector< double > dist_to_L(nb_points,infty); // vector of current distances to L from points + + //CHOICE OF THE FIRST LANDMARK + int rand_int = rand() % nb_points; + int curr_max_w = rand_int; //For testing purposes a pseudo-random number is used here + + for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + { + //curr_max_w at this point is the next landmark + chosen_landmarks.push_back(curr_max_w); + for (auto v: knn) + v.push_back(current_number_of_landmarks); + int i = 0; + for (const auto& p: points) + { + // used to stock the distance from the current point to L + double curr_dist = euclidean_distance(p, points.begin() + chosen_landmarks[current_number_of_landmarks]); + wit_land_dist[i].push_back(curr_dist); + knn[i].push_back(current_number_of_landmarks); + if (curr_dist < dist_to_L[i]) + dist_to_L[i] = curr_dist; + int j = current_number_of_landmarks; + while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) + { + std::swap(knn[i][j], knn[i][j-1]); + std::swap(wit_land_dist[i][j-1], wit_land_dist[i][j-1]); + --j; + } + ++i; + } + curr_max_dist = 0; + for (auto dist: dist_to_L) { + if (dist > curr_max_dist) + { + curr_max_dist = dist; + curr_max_w = i; + } + } + } + } + +}; + +#endif diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h new file mode 100644 index 00000000..bc3e72d9 --- /dev/null +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h @@ -0,0 +1,82 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 . + */ + +#ifndef GUDHI_LANDMARK_CHOICE_BY_RANDOM_POINT_H_ +#define GUDHI_LANDMARK_CHOICE_BY_RANDOM_POINT_H_ + +/** + * \class Landmark_choice_by_random_point + * \brief The class `Landmark_choice_by_random_point` allows to construct the matrix + * of closest landmarks per witness by iteratively choosing a random non-chosen witness + * as a new landmark. + * \ingroup witness_complex + */ + +class Landmark_choice_by_random_point { + + + /** \brief Landmark choice strategy by taking random vertices for landmarks. + * It takes a random access range points and outputs a matrix {witness}*{closest landmarks} + * in knn. + */ + + template + void landmark_choice_by_random_points(Point_random_access_range &points, KNearestNeighbours &knn) + { + int nbP = points.end() - points.begin(); + std::set &landmarks; + int current_number_of_landmarks=0; // counter for landmarks + + int chosen_landmark = rand()%nbP; + for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + { + while (landmarks.find(chosen_landmark) != landmarks.end()) + chosen_landmark = rand()% nbP; + landmarks.insert(chosen_landmark); + } + + int D = points.begin().size(); + typedef std::pair dist_i; + typedef bool (*comp)(dist_i,dist_i); + for (int points_i = 0; points_i < nbP; points_i++) + { + std::priority_queue, comp> l_heap([&](dist_i j1, dist_i j2){return j1.first > j2.first;}); + std::set::iterator landmarks_it; + int landmarks_i = 0; + for (landmarks_it = landmarks.begin(), landmarks_i=0; landmarks_it != landmarks.end(); landmarks_it++, landmarks_i++) + { + dist_i dist = std::make_pair(euclidean_distance(points[points_i],points[*landmarks_it]), landmarks_i); + l_heap.push(dist); + } + for (int i = 0; i < D+1; i++) + { + dist_i dist = l_heap.top(); + knn[points_i].push_back(dist.second); + l_heap.pop(); + } + } + } + +}; + +#endif diff --git a/src/Witness_complex/include/gudhi/Relaxed_witness_complex.h b/src/Witness_complex/include/gudhi/Relaxed_witness_complex.h deleted file mode 100644 index c869628f..00000000 --- a/src/Witness_complex/include/gudhi/Relaxed_witness_complex.h +++ /dev/null @@ -1,886 +0,0 @@ -/* 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): Siargey Kachanovich - * - * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 . - */ - -#ifndef GUDHI_RELAXED_WITNESS_COMPLEX_H_ -#define GUDHI_RELAXED_WITNESS_COMPLEX_H_ - -#include -#include -#include -#include -#include "gudhi/reader_utils.h" -#include "gudhi/distance_functions.h" -#include "gudhi/Simplex_tree.h" -#include -#include -#include -#include -#include -#include -#include -#include - -// Needed for nearest neighbours -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -// Needed for the adjacency graph in bad link search -#include -#include -#include - -namespace Gudhi { - - - /** \addtogroup simplex_tree - * Witness complex is a simplicial complex defined on two sets of points in \f$\mathbf{R}^D\f$: - * \f$W\f$ set of witnesses and \f$L \subseteq W\f$ set of landmarks. The simplices are based on points in \f$L\f$ - * and a simplex belongs to the witness complex if and only if it is witnessed (there exists a point \f$w \in W\f$ such that - * w is closer to the vertices of this simplex than others) and all of its faces are witnessed as well. - */ - template - class Witness_complex: public Simplex_tree<> { - - private: - - struct Active_witness { - int witness_id; - int landmark_id; - Simplex_handle simplex_handle; - - Active_witness(int witness_id_, int landmark_id_, Simplex_handle simplex_handle_) - : witness_id(witness_id_), - landmark_id(landmark_id_), - simplex_handle(simplex_handle_) - {} - }; - - - - - public: - - - /** \brief Type for the vertex handle. - * - * Must be a signed integer type. It admits a total order <. */ - typedef VertexHandle Vertex_handle; - - /* Type of node in the simplex tree. */ - typedef Simplex_tree_node_explicit_storage Node; - /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ - typedef typename boost::container::flat_map Dictionary; - typedef typename Dictionary::iterator Simplex_handle; - - typedef std::vector< double > Point_t; - typedef std::vector< Point_t > Point_Vector; - - typedef std::vector< Vertex_handle > typeVectorVertex; - typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; - typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; - - typedef int Witness_id; - typedef int Landmark_id; - typedef std::list< Vertex_handle > ActiveWitnessList; - - private: - /** Number of landmarks - */ - int nbL; - /** Desired density - */ - double density; - - public: - - /** \brief Set number of landmarks to nbL_ - */ - void setNbL(int nbL_) - { - nbL = nbL_; - } - - /** \brief Set density to density_ - */ - void setDensity(double density_) - { - density = density_; - } - - /** - * /brief Iterative construction of the relaxed witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks} and (1+epsilon)-limit table {witnesses}*{landmarks} consisting of iterators of k nearest neighbor matrix. - * The line lengths can differ, however both matrices have the same corresponding line lengths. - */ - - template< typename KNearestNeighbours, typename OPELimits > - void relaxed_witness_complex(KNearestNeighbours & knn, OPELimits & rl) - //void witness_complex(std::vector< std::vector< Vertex_handle > > & knn) - { - std::cout << "**Start the procedure witness_complex" << std::endl; - //Construction of the active witness list - int nbW = knn.size(); - //int nbL = knn.at(0).size(); - typeVectorVertex vv; - //typeSimplex simplex; - //typePairSimplexBool returnValue; - //int counter = 0; - /* The list of still useful witnesses - * it will diminuish in the course of iterations - */ - ActiveWitnessList active_w;// = new ActiveWitnessList(); - for (int i=0; i != nbL; ++i) { - // initial fill of 0-dimensional simplices - // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore - //counter++; - vv = {i}; - insert_simplex(vv, Filtration_value(0.0)); - /* TODO Error if not inserted : normally no need here though*/ - } - int k=1; /* current dimension in iterative construction */ - //std::cout << "Successfully added landmarks" << std::endl; - // PRINT2 - //print_sc(root()); std::cout << std::endl; - for (int i=0; i != nbW; ++i) - active_w.push_back(i); - /* - int u,v; // two extremities of an edge - if (nbL > 1) // if the supposed dimension of the complex is >0 - { - for (int i=0; i != nbW; ++i) - { - // initial fill of active witnesses list - u = knn[i][0]; - v = knn[i][1]; - vv = {u,v}; - this->insert_simplex(vv,Filtration_value(0.0)); - //print_sc(root()); std::cout << std::endl; - //std::cout << "Added edges" << std::endl; - } - //print_sc(root()); - - } - */ - std::cout << "k=0, active witnesses: " << active_w.size() << std::endl; - //std::cout << "Successfully added edges" << std::endl; - //count_good = {0,0}; - //count_bad = {0,0}; - while (!active_w.empty() && k < nbL ) - { - //count_good.push_back(0); - //count_bad.push_back(0); - //std::cout << "Started the step k=" << k << std::endl; - typename ActiveWitnessList::iterator aw_it = active_w.begin(); - while (aw_it != active_w.end()) - { - std::vector simplex; - bool ok = add_all_faces_of_dimension(k, knn[*aw_it].begin(), rl[*aw_it].begin(), simplex, knn[*aw_it].end(), knn[*aw_it].end()); - if (!ok) - active_w.erase(aw_it++); //First increase the iterator and then erase the previous element - else - aw_it++; - } - std::cout << "k=" << k << ", active witnesses: " << active_w.size() << std::endl; - k++; - } - //print_sc(root()); std::cout << std::endl; - } - - /* \brief Adds recursively all the faces of a certain dimension dim witnessed by the same witness - * Iterator is needed to know until how far we can take landmarks to form simplexes - * simplex is the prefix of the simplexes to insert - * The output value indicates if the witness rests active or not - */ - bool add_all_faces_of_dimension(int dim, std::vector::iterator curr_l, typename std::vector< std::vector::iterator >::iterator curr_until, std::vector& simplex, std::vector::iterator until, std::vector::iterator end) - { - /* - std::ofstream ofs ("stree_result.txt", std::ofstream::out); - st_to_file(ofs); - ofs.close(); - */ - //print_sc(root()); - bool will_be_active = false; - if (dim > 0) - for (std::vector::iterator it = curr_l; it != until && it != end; ++it, ++curr_until) - { - simplex.push_back(*it); - if (find(simplex) != null_simplex()) - will_be_active = will_be_active || add_all_faces_of_dimension(dim-1, it+1, curr_until+1, simplex, until, end); - simplex.pop_back(); - if (until == end) - until = *curr_until; - } - else if (dim == 0) - for (std::vector::iterator it = curr_l; it != until && it != end; ++it, ++curr_until) - { - simplex.push_back(*it); - if (all_faces_in(simplex)) - { - will_be_active = true; - insert_simplex(simplex, 0.0); - } - simplex.pop_back(); - if (until == end) - until = *curr_until; - } - return will_be_active; - } - - /** \brief Construction of witness complex from points given explicitly - * nbL must be set to the right value of landmarks for strategies - * FURTHEST_POINT_STRATEGY and RANDOM_POINT_STRATEGY and - * density must be set to the right value for DENSITY_STRATEGY - */ - // void witness_complex_from_points(Point_Vector point_vector) - // { - // std::vector > WL; - // landmark_choice_by_random_points(point_vector, point_vector.size(), WL); - // witness_complex(WL); - // } - -private: - - /** \brief Print functions - */ - void print_sc(Siblings * sibl) - { - if (sibl == NULL) - std::cout << "&"; - else - print_children(sibl->members_); - } - - void print_children(Dictionary map) - { - std::cout << "("; - if (!map.empty()) - { - std::cout << map.begin()->first; - if (has_children(map.begin())) - print_sc(map.begin()->second.children()); - typename Dictionary::iterator it; - for (it = map.begin()+1; it != map.end(); ++it) - { - std::cout << "," << it->first; - if (has_children(it)) - print_sc(it->second.children()); - } - } - std::cout << ")"; - } - - public: - /** \brief Print functions - */ - - void st_to_file(std::ofstream& out_file) - { - sc_to_file(out_file, root()); - } - - private: - void sc_to_file(std::ofstream& out_file, Siblings * sibl) - { - assert(sibl); - children_to_file(out_file, sibl->members_); - } - - void children_to_file(std::ofstream& out_file, Dictionary& map) - { - out_file << "(" << std::flush; - if (!map.empty()) - { - out_file << map.begin()->first << std::flush; - if (has_children(map.begin())) - sc_to_file(out_file, map.begin()->second.children()); - typename Dictionary::iterator it; - for (it = map.begin()+1; it != map.end(); ++it) - { - out_file << "," << it->first << std::flush; - if (has_children(it)) - sc_to_file(out_file, it->second.children()); - } - } - out_file << ")" << std::flush; - } - - - /** \brief Check if the facets of the k-dimensional simplex witnessed - * by witness witness_id are already in the complex. - * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id - */ - bool all_faces_in(std::vector& simplex) - { - //std::cout << "All face in with the landmark " << inserted_vertex << std::endl; - std::vector< VertexHandle > facet; - //VertexHandle curr_vh = curr_sh->first; - // CHECK ALL THE FACETS - for (std::vector::iterator not_it = simplex.begin(); not_it != simplex.end(); ++not_it) - { - facet.clear(); - //facet = {}; - for (std::vector::iterator it = simplex.begin(); it != simplex.end(); ++it) - if (it != not_it) - facet.push_back(*it); - if (find(facet) == null_simplex()) - return false; - } //endfor - return true; - } - - template - void print_vector(std::vector v) - { - std::cout << "["; - if (!v.empty()) - { - std::cout << *(v.begin()); - for (auto it = v.begin()+1; it != v.end(); ++it) - { - std::cout << ","; - std::cout << *it; - } - } - std::cout << "]"; - } - - template - void print_vvector(std::vector< std::vector > vv) - { - std::cout << "["; - if (!vv.empty()) - { - print_vector(*(vv.begin())); - for (auto it = vv.begin()+1; it != vv.end(); ++it) - { - std::cout << ","; - print_vector(*it); - } - } - std::cout << "]\n"; - } - - public: -/** - * \brief Landmark choice strategy by iteratively adding the landmark the furthest from the - * current landmark set - * \arg W is the vector of points which will be the witnesses - * \arg nbP is the number of witnesses - * \arg nbL is the number of landmarks - * \arg WL is the matrix of the nearest landmarks with respect to witnesses (output) - */ - - template - void landmark_choice_by_furthest_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) - { - //std::cout << "Enter landmark_choice_by_furthest_points "<< std::endl; - //std::cout << "W="; print_vvector(W); - //double density = 5.; - Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks - typeVectorVertex chosen_landmarks; // landmark list - - WL = KNearestNeighbours(nbP,std::vector()); - int current_number_of_landmarks=0; // counter for landmarks - double curr_max_dist = 0; // used for defining the furhest point from L - double curr_dist; // used to stock the distance from the current point to L - double infty = std::numeric_limits::infinity(); // infinity (see next entry) - std::vector< double > dist_to_L(nbP,infty); // vector of current distances to L from points - // double mindist = infty; - int curr_max_w=0; // the point currently furthest from L - int j; - int temp_swap_int; - double temp_swap_double; - - //CHOICE OF THE FIRST LANDMARK - std::cout << "Enter the first landmark stage\n"; - srand(354698); - int rand_int = rand()% nbP; - curr_max_w = rand_int; //For testing purposes a pseudo-random number is used here - - for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) - { - //curr_max_w at this point is the next landmark - chosen_landmarks.push_back(curr_max_w); - //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; - //std::cout << "WL="; print_vvector(WL); - //std::cout << "WLD="; print_vvector(wit_land_dist); - //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; - for (auto v: WL) - v.push_back(current_number_of_landmarks); - for (int i = 0; i < nbP; ++i) - { - // iteration on points in W. update of distance vectors - - //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; - //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; - curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); - //std::cout << "The problem is not in distance function\n"; - wit_land_dist[i].push_back(curr_dist); - WL[i].push_back(current_number_of_landmarks); - //std::cout << "Push't back\n"; - if (curr_dist < dist_to_L[i]) - dist_to_L[i] = curr_dist; - j = current_number_of_landmarks; - //std::cout << "First half complete\n"; - while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) - { - // sort the closest landmark vector for every witness - temp_swap_int = WL[i][j]; - WL[i][j] = WL[i][j-1]; - WL[i][j-1] = temp_swap_int; - temp_swap_double = wit_land_dist[i][j]; - wit_land_dist[i][j] = wit_land_dist[i][j-1]; - wit_land_dist[i][j-1] = temp_swap_double; - --j; - } - //std::cout << "result WL="; print_vvector(WL); - //std::cout << "result WLD="; print_vvector(wit_land_dist); - //std::cout << "result distL="; print_vector(dist_to_L); std::cout << std::endl; - //std::cout << "End loop\n"; - } - //std::cout << "Distance to landmarks="; print_vector(dist_to_L); std::cout << std::endl; - curr_max_dist = 0; - for (int i = 0; i < nbP; ++i) { - if (dist_to_L[i] > curr_max_dist) - { - curr_max_dist = dist_to_L[i]; - curr_max_w = i; - } - } - //std::cout << "Chose " << curr_max_w << " as new landmark\n"; - } - //std::cout << endl; - } - - /** \brief Landmark choice strategy by taking random vertices for landmarks. - * - */ - - // template - // void landmark_choice_by_random_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) - // { - // std::cout << "Enter landmark_choice_by_random_points "<< std::endl; - // //std::cout << "W="; print_vvector(W); - // std::unordered_set< int > chosen_landmarks; // landmark set - - // Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks - - // WL = KNearestNeighbours(nbP,std::vector()); - // int current_number_of_landmarks=0; // counter for landmarks - - // srand(24660); - // int chosen_landmark = rand()%nbP; - // double curr_dist; - - // //int j; - // //int temp_swap_int; - // //double temp_swap_double; - - - // for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) - // { - // while (chosen_landmarks.find(chosen_landmark) != chosen_landmarks.end()) - // { - // srand((int)clock()); - // chosen_landmark = rand()% nbP; - // //std::cout << chosen_landmark << "\n"; - // } - // chosen_landmarks.insert(chosen_landmark); - // //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; - // //std::cout << "WL="; print_vvector(WL); - // //std::cout << "WLD="; print_vvector(wit_land_dist); - // //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; - // for (auto v: WL) - // v.push_back(current_number_of_landmarks); - // for (int i = 0; i < nbP; ++i) - // { - // // iteration on points in W. update of distance vectors - - // //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; - // //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; - // curr_dist = euclidean_distance(W[i],W[chosen_landmark]); - // //std::cout << "The problem is not in distance function\n"; - // wit_land_dist[i].push_back(curr_dist); - // WL[i].push_back(current_number_of_landmarks); - // //std::cout << "Push't back\n"; - // //j = current_number_of_landmarks; - // //std::cout << "First half complete\n"; - // //std::cout << "result WL="; print_vvector(WL); - // //std::cout << "result WLD="; print_vvector(wit_land_dist); - // //std::cout << "End loop\n"; - // } - // } - // for (int i = 0; i < nbP; i++) - // { - // sort(WL[i].begin(), WL[i].end(), [&](int j1, int j2){return wit_land_dist[i][j1] < wit_land_dist[i][j2];}); - // } - // //std::cout << endl; - // } - - /** \brief Landmark choice strategy by taking random vertices for landmarks. - * - */ - - // template - void landmark_choice_by_random_points(Point_Vector &W, int nbP, std::set &L) - { - std::cout << "Enter landmark_choice_by_random_points "<< std::endl; - //std::cout << "W="; print_vvector(W); - //std::unordered_set< int > chosen_landmarks; // landmark set - - //Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks - - //WL = KNearestNeighbours(nbP,std::vector()); - int current_number_of_landmarks=0; // counter for landmarks - - srand(24660); - int chosen_landmark = rand()%nbP; - //double curr_dist; - //int j; - //int temp_swap_int; - //double temp_swap_double; - for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) - { - while (L.find(chosen_landmark) != L.end()) - { - srand((int)clock()); - chosen_landmark = rand()% nbP; - //std::cout << chosen_landmark << "\n"; - } - L.insert(chosen_landmark); - //std::cout << "**********Entered loop with current number of landmarks = " << current_number_of_landmarks << std::endl; - //std::cout << "WL="; print_vvector(WL); - //std::cout << "WLD="; print_vvector(wit_land_dist); - //std::cout << "landmarks="; print_vector(chosen_landmarks); std::cout << std::endl; - // for (auto v: WL) - // v.push_back(current_number_of_landmarks); - // for (int i = 0; i < nbP; ++i) - // { - // // iteration on points in W. update of distance vectors - - // //std::cout << "In the loop with i=" << i << " and landmark=" << chosen_landmarks[current_number_of_landmarks] << std::endl; - // //std::cout << "W[i]="; print_vector(W[i]); std::cout << " W[landmark]="; print_vector(W[chosen_landmarks[current_number_of_landmarks]]); std::cout << std::endl; - // curr_dist = euclidean_distance(W[i],W[chosen_landmark]); - // //std::cout << "The problem is not in distance function\n"; - // wit_land_dist[i].push_back(curr_dist); - // WL[i].push_back(current_number_of_landmarks); - // //std::cout << "Push't back\n"; - // //j = current_number_of_landmarks; - // //std::cout << "First half complete\n"; - // //std::cout << "result WL="; print_vvector(WL); - // //std::cout << "result WLD="; print_vvector(wit_land_dist); - // //std::cout << "End loop\n"; - // } - } - // for (int i = 0; i < nbP; i++) - // { - // sort(WL[i].begin(), WL[i].end(), [&](int j1, int j2){return wit_land_dist[i][j1] < wit_land_dist[i][j2];}); - // } - //std::cout << endl; - } - - - /** \brief Construct the matrix |W|x(D+1) of D+1 closest landmarks - * where W is the set of witnesses and D is the ambient dimension - */ - template - void nearest_landmarks(Point_Vector &W, std::set &L, KNearestNeighbours &WL) - { - int D = W[0].size(); - int nbP = W.size(); - WL = KNearestNeighbours(nbP,std::vector()); - typedef std::pair dist_i; - typedef bool (*comp)(dist_i,dist_i); - for (int W_i = 0; W_i < nbP; W_i++) - { - //std::cout << "<<<<<<<<<<<<<<" << W_i <<"\n"; - std::priority_queue, comp> l_heap([&](dist_i j1, dist_i j2){return j1.first > j2.first;}); - std::set::iterator L_it; - int L_i; - for (L_it = L.begin(), L_i=0; L_it != L.end(); L_it++, L_i++) - { - dist_i dist = std::make_pair(euclidean_distance(W[W_i],W[*L_it]), L_i); - l_heap.push(dist); - } - for (int i = 0; i < D+1; i++) - { - dist_i dist = l_heap.top(); - WL[W_i].push_back(dist.second); - //WL[W_i].insert(WL[W_i].begin(),dist.second); - //std::cout << dist.first << " " << dist.second << std::endl; - l_heap.pop(); - } - } - } - - /** \brief Search and output links around vertices that are not pseudomanifolds - * - */ - void write_bad_links(std::ofstream& out_file) - { - out_file << "Bad links list\n"; - std::cout << "Entered write_bad_links\n"; - //typeVectorVertex testv = {9,15,17}; - //int count = 0; - for (auto v: complex_vertex_range()) - { - //std::cout << "Vertex " << v << ":\n"; - std::vector< Vertex_handle > link_vertices; - // Fill link_vertices - for (auto u: complex_vertex_range()) - { - typeVectorVertex edge = {u,v}; - if (u != v && find(edge) != null_simplex()) - link_vertices.push_back(u); - } - /* - print_vector(link_vertices); - std::cout << "\n"; - */ - // Find the dimension - typeVectorVertex empty_simplex = {}; - int d = link_dim(link_vertices, link_vertices.begin(),-1, empty_simplex); - //std::cout << " dim " << d << "\n"; - //Siblings* curr_sibl = root(); - if (link_is_pseudomanifold(link_vertices,d)) - count_good[d]++; - //out_file << "Bad link at " << v << "\n"; - } - //out_file << "Number of bad links: " << count << "/" << root()->size(); - //std::cout << "Number of bad links: " << count << "/" << root()->size() << std::endl; - nc = nbL; - for (unsigned int i = 0; i != count_good.size(); i++) - { - out_file << "count_good[" << i << "] = " << count_good[i] << std::endl; - nc -= count_good[i]; - if (count_good[i] != 0) - std::cout << "count_good[" << i << "] = " << count_good[i] << std::endl; - } - for (unsigned int i = 0; i != count_bad.size(); i++) - { - out_file << "count_bad[" << i << "] = " << count_bad[i] << std::endl; - nc -= count_bad[i]; - if (count_bad[i] != 0) - std::cout << "count_bad[" << i << "] = " << count_bad[i] << std::endl; - } - std::cout << "not_connected = " << nc << std::endl; - } - - private: - - std::vector count_good; - std::vector count_bad; - int nc; - - int link_dim(std::vector< Vertex_handle >& link_vertices, - typename std::vector< Vertex_handle >::iterator curr_v, - int curr_d, - typeVectorVertex& curr_simplex) - { - //std::cout << "Entered link_dim for " << *(curr_v-1) << "\n"; - Simplex_handle sh; - int final_d = curr_d; - typename std::vector< Vertex_handle >::iterator it; - for (it = curr_v; it != link_vertices.end(); ++it) - { - curr_simplex.push_back(*it); - /* - std::cout << "Searching for "; - print_vector(curr_simplex); - std::cout << " curr_dim " << curr_d << " final_dim " << final_d; - */ - sh = find(curr_simplex); - if (sh != null_simplex()) - { - //std::cout << " -> " << *it << "\n"; - int d = link_dim(link_vertices, it+1, curr_d+1, curr_simplex); - if (d > final_d) - final_d = d; - } - /* - else - std::cout << "\n"; - */ - curr_simplex.pop_back(); - } - return final_d; - } - - // color is false is a (d-1)-dim face, true is a d-dim face - //typedef bool Color; - // graph is an adjacency list - typedef typename boost::adjacency_list Adj_graph; - // map that gives to a certain simplex its node in graph and its dimension - //typedef std::pair Reference; - typedef boost::graph_traits::vertex_descriptor Vertex_t; - typedef boost::graph_traits::edge_descriptor Edge_t; - - typedef boost::container::flat_map Graph_map; - - /* \brief Verifies if the simplices formed by vertices given by link_vertices - * form a pseudomanifold. - * The idea is to make a bipartite graph, where vertices are the d- and (d-1)-dimensional - * faces and edges represent adjacency between them. - */ - bool link_is_pseudomanifold(std::vector< Vertex_handle >& link_vertices, - int dimension) - { - Adj_graph adj_graph; - Graph_map d_map, f_map; // d_map = map for d-dimensional simplices - // f_map = map for its facets - typeVectorVertex empty_vector = {}; - add_vertices(link_vertices, - link_vertices.begin(), - adj_graph, - d_map, - f_map, - empty_vector, - 0, dimension); - //std::cout << "DMAP_SIZE: " << d_map.size() << "\n"; - //std::cout << "FMAP_SIZE: " << f_map.size() << "\n"; - add_edges(adj_graph, d_map, f_map); - for (auto f_map_it : f_map) - { - //std::cout << "Degree of " << f_map_it.first->first << " is " << boost::out_degree(f_map_it.second, adj_graph) << "\n"; - if (boost::out_degree(f_map_it.second, adj_graph) != 2) - { - count_bad[dimension]++; - return false; - } - } - // At this point I know that all (d-1)-simplices are adjacent to exactly 2 d-simplices - // What is left is to check the connexity - std::vector components(boost::num_vertices(adj_graph)); - return (boost::connected_components(adj_graph, &components[0]) == 1); - } - - void add_vertices(typeVectorVertex& link_vertices, - typename typeVectorVertex::iterator curr_v, - Adj_graph& adj_graph, - Graph_map& d_map, - Graph_map& f_map, - typeVectorVertex& curr_simplex, - int curr_d, - int dimension) - { - Simplex_handle sh; - Vertex_t vert; - typename typeVectorVertex::iterator it; - std::pair resPair; - //typename Graph_map::iterator resPair; - //Add vertices - //std::cout << "Entered add vertices\n"; - for (it = curr_v; it != link_vertices.end(); ++it) - { - curr_simplex.push_back(*it); - /* - std::cout << "Searching for "; - print_vector(curr_simplex); - std::cout << " curr_dim " << curr_d << " d " << dimension << ""; - */ - sh = find(curr_simplex); - if (sh != null_simplex()) - { - //std::cout << " added\n"; - if (curr_d == dimension) - { - vert = boost::add_vertex(adj_graph); - resPair = d_map.emplace(sh,vert); - } - else - { - if (curr_d == dimension-1) - { - vert = boost::add_vertex(adj_graph); - resPair = f_map.emplace(sh,vert); - } - add_vertices(link_vertices, - it+1, - adj_graph, - d_map, - f_map, - curr_simplex, - curr_d+1, dimension); - } - } - /* - else - std::cout << "\n"; - */ - curr_simplex.pop_back(); - } - } - - void add_edges(Adj_graph& adj_graph, - Graph_map& d_map, - Graph_map& f_map) - { - Simplex_handle sh; - // Add edges - //std::cout << "Entered add edges:\n"; - typename Graph_map::iterator map_it; - for (auto d_map_pair : d_map) - { - //std::cout << "*"; - sh = d_map_pair.first; - Vertex_t d_vert = d_map_pair.second; - for (auto facet_sh : boundary_simplex_range(sh)) - //for (auto f_map_it : f_map) - { - //std::cout << "'"; - map_it = f_map.find(facet_sh); - //We must have all the facets in the graph at this point - assert(map_it != f_map.end()); - Vertex_t f_vert = map_it->second; - //std::cout << "Added edge " << sh->first << "-" << map_it->first->first << "\n"; - boost::add_edge(d_vert,f_vert,adj_graph); - } - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - //***********COLLAPSES**************************************************************************// - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - - - - - -}; //class Witness_complex - - - -} // namespace Guhdi - -#endif diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 8316fe3e..b218611b 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -27,9 +27,7 @@ #include #include #include -#include "gudhi/reader_utils.h" #include "gudhi/distance_functions.h" -#include "gudhi/Simplex_tree.h" #include #include #include @@ -47,47 +45,32 @@ namespace Gudhi { - /** Witness complex is a simplicial complex defined on two sets of points in \f$\mathbf{R}^D\f$: - * \f$W\f$ set of witnesses and \f$L \subseteq W\f$ set of landmarks. The simplices are based on points in \f$L\f$ - * and a simplex belongs to the witness complex if and only if it is witnessed (there exists a point \f$w \in W\f$ such that - * w is closer to the vertices of this simplex than others) and all of its faces are witnessed as well. + /** + \class Witness_complex + \brief Constructs the witness complex for the given set of witnesses and landmarks. + \ingroup witness_complex */ - template - class Witness_complex: public Simplex_tree<> { - + template< class Simplicial_complex> + class Witness_complex { + private: struct Active_witness { int witness_id; int landmark_id; - Simplex_handle simplex_handle; - Active_witness(int witness_id_, int landmark_id_, Simplex_handle simplex_handle_) + Active_witness(int witness_id_, int landmark_id_) : witness_id(witness_id_), - landmark_id(landmark_id_), - simplex_handle(simplex_handle_) + landmark_id(landmark_id_) {} }; - - - public: - - - /** \brief Type for the vertex handle. - * - * Must be a signed integer type. It admits a total order <. */ - typedef VertexHandle Vertex_handle; - - /* Type of node in the simplex tree. */ - typedef Simplex_tree_node_explicit_storage Node; - /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ - typedef typename boost::container::flat_map Dictionary; - typedef typename Dictionary::iterator Simplex_handle; + private: + typedef typename Simplicial_complex::Simplex_handle Simplex_handle; + typedef typename Simplicial_complex::Vertex_handle Vertex_handle; + typedef std::vector< double > Point_t; typedef std::vector< Point_t > Point_Vector; @@ -102,33 +85,29 @@ namespace Gudhi { private: int nbL; // Number of landmarks double density; // Desired density - + Simplicial_complex& sc; // Simplicial complex + public: - /** \brief Set number of landmarks to nbL_ + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** @name Constructor */ - void setNbL(int nbL_) - { - nbL = nbL_; - } - /** \brief Set density to density_ - */ - void setDensity(double density_) - { - density = density_; - } + //@{ /** - * /brief Iterative construction of the witness complex basing on a matrix of k nearest neighbours of the form {witnesses}x{landmarks}. - * Landmarks are supposed to be in [0,nbL-1] - */ - + * \brief Iterative construction of the witness complex. + * \details The witness complex is written in sc_ basing on a matrix knn of + * nearest neighbours of the form {witnesses}x{landmarks}. + * Parameter dim serves as the limit for the number of closest landmarks to consider. + * Landmarks are supposed to be in [0,nbL_-1] + */ template< typename KNearestNeighbours > - void witness_complex(KNearestNeighbours & knn) - //void witness_complex(std::vector< std::vector< Vertex_handle > > & knn) + Witness_complex(KNearestNeighbours & knn, + Simplicial_complex & sc_, + int nbL_, + int dim ): nbL(nbL_), sc(sc_) { - std::cout << "**Start the procedure witness_complex" << std::endl; //Construction of the active witness list int nbW = knn.size(); typeVectorVertex vv; @@ -144,16 +123,14 @@ namespace Gudhi { // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore counter++; vv = {i}; - returnValue = insert_simplex(vv, Filtration_value(0.0)); + returnValue = sc.insert_simplex(vv, Filtration_value(0.0)); /* TODO Error if not inserted : normally no need here though*/ } int k=1; /* current dimension in iterative construction */ for (int i=0; i != nbW; ++i) active_w.push_back(i); - std::cout << "k=0, active witnesses: " << active_w.size() << std::endl; //std::cout << "Successfully added edges" << std::endl; - int D = knn[0].size(); - while (!active_w.empty() && k < D ) + while (!active_w.empty() && k < dim ) { //std::cout << "Started the step k=" << k << std::endl; typename ActiveWitnessList::iterator it = active_w.begin(); @@ -166,84 +143,20 @@ namespace Gudhi { { for (int i = 0; i != k+1; ++i) simplex_vector.push_back(knn[*it][i]); - returnValue = insert_simplex(simplex_vector,0.0); + returnValue = sc.insert_simplex(simplex_vector,0.0); it++; } else active_w.erase(it++); //First increase the iterator and then erase the previous element } - std::cout << "k=" << k << ", active witnesses: " << active_w.size() << std::endl; k++; } } - -private: - /** \brief Print functions - */ - void print_sc(Siblings * sibl) - { - if (sibl == NULL) - std::cout << "&"; - else - print_children(sibl->members_); - } + //@} - void print_children(Dictionary map) - { - std::cout << "("; - if (!map.empty()) - { - std::cout << map.begin()->first; - if (has_children(map.begin())) - print_sc(map.begin()->second.children()); - typename Dictionary::iterator it; - for (it = map.begin()+1; it != map.end(); ++it) - { - std::cout << "," << it->first; - if (has_children(it)) - print_sc(it->second.children()); - } - } - std::cout << ")"; - } - - public: - /** \brief Print functions - */ - - void st_to_file(std::ofstream& out_file) - { - sc_to_file(out_file, root()); - } - private: - void sc_to_file(std::ofstream& out_file, Siblings * sibl) - { - assert(sibl); - children_to_file(out_file, sibl->members_); - } - void children_to_file(std::ofstream& out_file, Dictionary& map) - { - out_file << "(" << std::flush; - if (!map.empty()) - { - out_file << map.begin()->first << std::flush; - if (has_children(map.begin())) - sc_to_file(out_file, map.begin()->second.children()); - typename Dictionary::iterator it; - for (it = map.begin()+1; it != map.end(); ++it) - { - out_file << "," << it->first << std::flush; - if (has_children(it)) - sc_to_file(out_file, it->second.children()); - } - } - out_file << ")" << std::flush; - } - - /** \brief Check if the facets of the k-dimensional simplex witnessed * by witness witness_id are already in the complex. * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id @@ -252,8 +165,8 @@ private: bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k) { //std::cout << "All face in with the landmark " << inserted_vertex << std::endl; - std::vector< VertexHandle > facet; - //VertexHandle curr_vh = curr_sh->first; + std::vector< Vertex_handle > facet; + //Vertex_handle curr_vh = curr_sh->first; // CHECK ALL THE FACETS for (int i = 0; i != k+1; ++i) { @@ -265,14 +178,14 @@ private: facet.push_back(knn[witness_id][j]); } }//endfor - if (find(facet) == null_simplex()) + if (sc.find(facet) == sc.null_simplex()) return false; //std::cout << "++++ finished loop safely\n"; } //endfor return true; } - - template + + template void print_vector(std::vector v) { std::cout << "["; @@ -288,162 +201,25 @@ private: std::cout << "]"; } - template - void print_vvector(std::vector< std::vector > vv) - { - std::cout << "["; - if (!vv.empty()) - { - print_vector(*(vv.begin())); - for (auto it = vv.begin()+1; it != vv.end(); ++it) - { - std::cout << ","; - print_vector(*it); - } - } - std::cout << "]\n"; - } - public: -/** - * \brief Landmark choice strategy by iteratively adding the landmark the furthest from the - * current landmark set - * \arg W is the vector of points which will be the witnesses - * \arg nbP is the number of witnesses - * \arg nbL is the number of landmarks - * \arg WL is the matrix of the nearest landmarks with respect to witnesses (output) - */ - - template - void landmark_choice_by_furthest_points(Point_Vector &W, int nbP, KNearestNeighbours &WL) - { - Point_Vector wit_land_dist(nbP,std::vector()); // distance matrix witness x landmarks - typeVectorVertex chosen_landmarks; // landmark list - - WL = KNearestNeighbours(nbP,std::vector()); - int current_number_of_landmarks=0; // counter for landmarks - double curr_max_dist = 0; // used for defining the furhest point from L - double curr_dist; // used to stock the distance from the current point to L - double infty = std::numeric_limits::infinity(); // infinity (see next entry) - std::vector< double > dist_to_L(nbP,infty); // vector of current distances to L from points - int curr_max_w=0; // the point currently furthest from L - int j; - int temp_swap_int; - double temp_swap_double; - - //CHOICE OF THE FIRST LANDMARK - std::cout << "Enter the first landmark stage\n"; - srand(354698); - int rand_int = rand()% nbP; - curr_max_w = rand_int; //For testing purposes a pseudo-random number is used here - - for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) - { - //curr_max_w at this point is the next landmark - chosen_landmarks.push_back(curr_max_w); - for (auto v: WL) - v.push_back(current_number_of_landmarks); - for (int i = 0; i < nbP; ++i) - { - curr_dist = euclidean_distance(W[i],W[chosen_landmarks[current_number_of_landmarks]]); - wit_land_dist[i].push_back(curr_dist); - WL[i].push_back(current_number_of_landmarks); - if (curr_dist < dist_to_L[i]) - dist_to_L[i] = curr_dist; - j = current_number_of_landmarks; - while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) - { - temp_swap_int = WL[i][j]; - WL[i][j] = WL[i][j-1]; - WL[i][j-1] = temp_swap_int; - temp_swap_double = wit_land_dist[i][j]; - wit_land_dist[i][j] = wit_land_dist[i][j-1]; - wit_land_dist[i][j-1] = temp_swap_double; - --j; - } - } - curr_max_dist = 0; - for (int i = 0; i < nbP; ++i) { - if (dist_to_L[i] > curr_max_dist) - { - curr_max_dist = dist_to_L[i]; - curr_max_w = i; - } - } - } - } - - /** \brief Landmark choice strategy by taking random vertices for landmarks. - * - */ - - // template - void landmark_choice_by_random_points(Point_Vector &W, int nbP, std::set &L) - { - int current_number_of_landmarks=0; // counter for landmarks - - srand(24660); - int chosen_landmark = rand()%nbP; - for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) - { - while (L.find(chosen_landmark) != L.end()) - { - srand((int)clock()); - chosen_landmark = rand()% nbP; - } - L.insert(chosen_landmark); - } - } - - - /** \brief Construct the matrix |W|x(D+1) of D+1 closest landmarks - * where W is the set of witnesses and D is the ambient dimension - */ - template - void nearest_landmarks(Point_Vector &W, std::set &L, KNearestNeighbours &WL) - { - int D = W[0].size(); - int nbP = W.size(); - WL = KNearestNeighbours(nbP,std::vector()); - typedef std::pair dist_i; - typedef bool (*comp)(dist_i,dist_i); - for (int W_i = 0; W_i < nbP; W_i++) - { - std::priority_queue, comp> l_heap([&](dist_i j1, dist_i j2){return j1.first > j2.first;}); - std::set::iterator L_it; - int L_i; - for (L_it = L.begin(), L_i=0; L_it != L.end(); L_it++, L_i++) - { - dist_i dist = std::make_pair(euclidean_distance(W[W_i],W[*L_it]), L_i); - l_heap.push(dist); - } - for (int i = 0; i < D+1; i++) - { - dist_i dist = l_heap.top(); - WL[W_i].push_back(dist.second); - l_heap.pop(); - } - } - } - - - public: - /** \brief Verification if every simplex in the complex is witnessed + /** + * \brief Verification if every simplex in the complex is witnessed. + * \remark Added for debugging purposes. */ template< class KNearestNeighbors > - bool is_witness_complex(KNearestNeighbors WL) + bool is_witness_complex(KNearestNeighbors & knn) { //bool final_result = true; - for (Simplex_handle sh: complex_simplex_range()) + for (Simplex_handle sh: sc.complex_simplex_range()) { bool is_witnessed = false; typeVectorVertex simplex; int nbV = 0; //number of verticed in the simplex - for (int v: simplex_vertex_range(sh)) + for (int v: sc.simplex_vertex_range(sh)) simplex.push_back(v); nbV = simplex.size(); - for (typeVectorVertex w: WL) + for (typeVectorVertex w: knn) { bool has_vertices = true; for (int v: simplex) diff --git a/src/Witness_complex/include/gudhi/Witness_complex_doc.h b/src/Witness_complex/include/gudhi/Witness_complex_doc.h new file mode 100644 index 00000000..22cfe992 --- /dev/null +++ b/src/Witness_complex/include/gudhi/Witness_complex_doc.h @@ -0,0 +1,37 @@ +#ifndef WITNESS_COMPLEX_DOC_ +#define WITNESS_COMPLEX_DOC_ + +/** + \defgroup witness_complex Witness complex + + \author Siargey Kachanovich + + \section Definitions + + Witness complex \f$ Wit(W,L) \f$ is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$: + + \li \f$W\f$ set of **witnesses** and + \li \f$L \subseteq W\f$ set of **landmarks**. + + The simplices are based on landmarks + and a simplex belongs to the witness complex if and only if it is witnessed, that is: + + \f$ \sigma \subset L \f$ is witnessed if there exists a point \f$w \in W\f$ such that + w is closer to the vertices of \f$ \sigma \f$ than other points in \f$ L \f$ and all of its faces are witnessed as well. + + \section Implementation + + Two classes are implemented in this module: Gudhi::Witness_complex and Gudhi::Relaxed_witness_complex. + + While Gudhi::Witness_complex represents the classical witness complex, Gudhi::Relaxed_witness_complex takes an additional positive real parameter \f$ \alpha \f$ and constructs simplices \f$ \sigma \f$, for which + there exists \f$ w \in W \f$, such that \f$ d(p,w) < d(q,w) + \alpha \f$ for all \f$ p \in \sigma, q \in L\setminus \sigma \f$. + + In both cases, the constructors take a {witness}x{closest_landmarks} table, + which can be constructed by two additional classes Landmark_choice_by_furthest_point and Landmark_choice_by_random_point also included in the module. + + \copyright GNU General Public License v3. + + + */ + +#endif -- cgit v1.2.3 From f3fa597138156c3b925ac970555f8482e964c968 Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 10 Dec 2015 09:29:52 +0000 Subject: Added things git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@937 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4f0ae39ee1f68d8cce565ad0855edb3bff1e7f3f --- src/Doxyfile | 4 +- src/Witness_complex/doc/bench_Cy8.png | Bin 0 -> 15254 bytes src/Witness_complex/doc/bench_sphere.png | Bin 0 -> 16614 bytes src/Witness_complex/example/CMakeLists.txt | 26 +++++- .../example/simple_witness_complex.cpp | 4 +- .../example/witness_complex_from_file.cpp | 90 ++++++--------------- .../gudhi/Landmark_choice_by_furthest_point.h | 12 ++- .../gudhi/Landmark_choice_by_random_point.h | 16 ++-- .../include/gudhi/Witness_complex.h | 32 +++++--- .../include/gudhi/Witness_complex_doc.h | 11 +-- 10 files changed, 98 insertions(+), 97 deletions(-) create mode 100644 src/Witness_complex/doc/bench_Cy8.png create mode 100644 src/Witness_complex/doc/bench_sphere.png (limited to 'src') diff --git a/src/Doxyfile b/src/Doxyfile index faa0d3fe..6585e50c 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -834,8 +834,8 @@ EXAMPLE_RECURSIVE = NO IMAGE_PATH = doc/Skeleton_blocker/ \ doc/common/ \ - doc/Contraction/ - + doc/Contraction/ \ + doc/Witness_complex/ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program diff --git a/src/Witness_complex/doc/bench_Cy8.png b/src/Witness_complex/doc/bench_Cy8.png new file mode 100644 index 00000000..d9045294 Binary files /dev/null and b/src/Witness_complex/doc/bench_Cy8.png differ diff --git a/src/Witness_complex/doc/bench_sphere.png b/src/Witness_complex/doc/bench_sphere.png new file mode 100644 index 00000000..ba6bb381 Binary files /dev/null and b/src/Witness_complex/doc/bench_sphere.png differ diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 83f9c71c..4f5e33d4 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -6,6 +6,30 @@ project(GUDHIWitnessComplex) add_test(simple_witness_complex ${CMAKE_CURRENT_BINARY_DIR}/simple_witness_complex) add_executable( witness_complex_from_file witness_complex_from_file.cpp ) - #target_link_libraries(witness_complex_from_file ${EIGEN3_LIBRARIES} ${CGAL_LIBRARY}) add_test( witness_complex_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_executable( witness_complex_bench witness_complex_bench.cpp ) + add_test( witness_complex_bench_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_bench ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) + message(STATUS "Eigen3 use file: ${EIGEN3_USE_FILE}.") + include_directories (BEFORE "../../include") + + add_executable ( witness_complex_bench2 witness_complex_bench2.cpp ) + target_link_libraries(witness_complex_bench2 ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() + else() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () +endif() diff --git a/src/Witness_complex/example/simple_witness_complex.cpp b/src/Witness_complex/example/simple_witness_complex.cpp index 6731f135..bcbf2362 100644 --- a/src/Witness_complex/example/simple_witness_complex.cpp +++ b/src/Witness_complex/example/simple_witness_complex.cpp @@ -50,8 +50,8 @@ int main (int argc, char * const argv[]) typeVectorVertex witness10 = {5,0,1,3,6,2,4}; knn.push_back(witness10); typeVectorVertex witness11 = {5,6,1,0,2,3,4}; knn.push_back(witness11); typeVectorVertex witness12 = {1,6,0,5,2,3,4}; knn.push_back(witness12); - WitnessComplex witnessComplex(knn, complex, 7); - if (witnessComplex.is_witness_complex(knn)) + WitnessComplex witnessComplex(knn, complex, 7, 7); + if (witnessComplex.is_witness_complex(knn, true)) std::cout << "Witness complex is good\n"; else std::cout << "Witness complex is bad\n"; diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index 70c81528..6add4e0a 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -26,21 +26,18 @@ #include #include -//#include -//#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Simplex_tree.h" #include "gudhi/Witness_complex.h" +#include "gudhi/Landmark_choice_by_random_point.h" #include "gudhi/reader_utils.h" -//#include using namespace Gudhi; -//using namespace boost::filesystem; typedef std::vector< Vertex_handle > typeVectorVertex; typedef std::vector< std::vector > Point_Vector; -//typedef std::pair typeSimplex; -//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; +typedef Witness_complex< Simplex_tree<> > WitnessComplex; /** * \brief Customized version of read_points @@ -69,15 +66,15 @@ read_points_cust ( std::string file_name , std::vector< std::vector< double > > in_file.close(); } -void write_wl( std::string file_name, std::vector< std::vector > & WL) +/** Write a gnuplot readable file. + * Data range is a random access range of pairs (arg, value) + */ +template < typename Data_range > +void write_data( Data_range & data, std::string filename ) { - std::ofstream ofs (file_name, std::ofstream::out); - for (auto w : WL) - { - for (auto l: w) - ofs << l << " "; - ofs << "\n"; - } + std::ofstream ofs(filename, std::ofstream::out); + for (auto entry: data) + ofs << entry.first << ", " << entry.second << "\n"; ofs.close(); } @@ -89,68 +86,33 @@ int main (int argc, char * const argv[]) << " path_to_point_file nbL \n"; return 0; } - /* - boost::filesystem::path p; - for (; argc > 2; --argc, ++argv) - p /= argv[1]; - */ std::string file_name = argv[1]; int nbL = atoi(argv[2]); - clock_t start, end; - //Construct the Simplex Tree - Witness_complex<> witnessComplex; - - std::cout << "Let the carnage begin!\n"; + + // Construct the Simplex Tree + Simplex_tree<> simplex_tree; + + // Read the point file Point_Vector point_vector; read_points_cust(file_name, point_vector); - //std::cout << "Successfully read the points\n"; - witnessComplex.setNbL(nbL); - // witnessComplex.witness_complex_from_points(point_vector); - std::vector > WL; - std::set L; + std::cout << "Successfully read " << point_vector.size() << " points.\n"; + std::cout << "Ambient dimension is " << point_vector[0].size() << ".\n"; + + // Choose landmarks start = clock(); - //witnessComplex.landmark_choice_by_furthest_points(point_vector, point_vector.size(), WL); - witnessComplex.landmark_choice_by_random_points(point_vector, point_vector.size(), L); - witnessComplex.nearest_landmarks(point_vector,L,WL); + std::vector > knn; + Landmark_choice_by_random_point(point_vector, nbL, knn); end = clock(); std::cout << "Landmark choice for " << nbL << " landmarks took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; - // Write the WL matrix in a file - mkdir("output", S_IRWXU); - const size_t last_slash_idx = file_name.find_last_of("/"); - if (std::string::npos != last_slash_idx) - { - file_name.erase(0, last_slash_idx + 1); - } - std::string out_file = "output/"+file_name+"_"+argv[2]+".wl"; - write_wl(out_file,WL); + + // Compute witness complex start = clock(); - witnessComplex.witness_complex(WL); - // + WitnessComplex(knn, simplex_tree, nbL, point_vector[0].size()); end = clock(); - std::cout << "Howdy world! The process took " + std::cout << "Witness complex took " << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; - /* - char buffer[100]; - int i = sprintf(buffer,"%s_%s_result.txt",argv[1],argv[2]); - if (i >= 0) - { - std::string out_file = (std::string)buffer; - std::ofstream ofs (out_file, std::ofstream::out); - witnessComplex.st_to_file(ofs); - ofs.close(); - } - */ - - out_file = "output/"+file_name+"_"+argv[2]+".stree"; - std::ofstream ofs (out_file, std::ofstream::out); - witnessComplex.st_to_file(ofs); - ofs.close(); - out_file = "output/"+file_name+"_"+argv[2]+".badlinks"; - std::ofstream ofs2(out_file, std::ofstream::out); - witnessComplex.write_bad_links(ofs2); - ofs2.close(); } diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h index 44bf9dbb..0b196f18 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -31,18 +31,22 @@ * \ingroup witness_complex */ -class Landmark_choice_by_random_point { +class Landmark_choice_by_furthest_point { +public: + /** * \brief Landmark choice strategy by iteratively adding the furthest witness from the - * current landmark set as the new landmark. It takes a random access range `points` and + * current landmark set as the new landmark. + * \details It chooses nbL landmarks from a random access range `points` and * writes {witness}*{closest landmarks} matrix in `knn`. */ template - Landmark_choice_by_furthest_points(Point_random_access_range &points, - KNearestNeighbours &knn) + Landmark_choice_by_furthest_point(Point_random_access_range &points, + int nbL, + KNearestNeighbours &knn) { int nb_points = points.end() - points.begin(); std::vector> wit_land_dist(nb_points, std::vector()); // distance matrix witness x landmarks diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h index bc3e72d9..fa822591 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h @@ -33,18 +33,19 @@ class Landmark_choice_by_random_point { - +public: + /** \brief Landmark choice strategy by taking random vertices for landmarks. - * It takes a random access range points and outputs a matrix {witness}*{closest landmarks} - * in knn. + * \details It chooses nbL distinct landmarks from a random access range `points` + * and outputs a matrix {witness}*{closest landmarks} in knn. */ template - void landmark_choice_by_random_points(Point_random_access_range &points, KNearestNeighbours &knn) + Landmark_choice_by_random_point(Point_random_access_range &points, int nbL, KNearestNeighbours &knn) { int nbP = points.end() - points.begin(); - std::set &landmarks; + std::set landmarks; int current_number_of_landmarks=0; // counter for landmarks int chosen_landmark = rand()%nbP; @@ -55,9 +56,10 @@ class Landmark_choice_by_random_point { landmarks.insert(chosen_landmark); } - int D = points.begin().size(); + int dim = points.begin()->size(); typedef std::pair dist_i; typedef bool (*comp)(dist_i,dist_i); + knn = KNearestNeighbours(nbP); for (int points_i = 0; points_i < nbP; points_i++) { std::priority_queue, comp> l_heap([&](dist_i j1, dist_i j2){return j1.first > j2.first;}); @@ -68,7 +70,7 @@ class Landmark_choice_by_random_point { dist_i dist = std::make_pair(euclidean_distance(points[points_i],points[*landmarks_it]), landmarks_i); l_heap.push(dist); } - for (int i = 0; i < D+1; i++) + for (int i = 0; i < dim+1; i++) { dist_i dist = l_heap.top(); knn[points_i].push_back(dist.second); diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index b218611b..791d0e45 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -73,10 +73,11 @@ namespace Gudhi { typedef std::vector< double > Point_t; typedef std::vector< Point_t > Point_Vector; - + + typedef typename Simplicial_complex::Filtration_value Filtration_value; typedef std::vector< Vertex_handle > typeVectorVertex; typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; - typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + typedef std::pair< Simplex_handle, bool > typePairSimplexBool; typedef int Witness_id; typedef int Landmark_id; @@ -204,11 +205,12 @@ namespace Gudhi { public: /** - * \brief Verification if every simplex in the complex is witnessed. + * \brief Verification if every simplex in the complex is witnessed by witnesses in knn. + * \param print_output =true will print the witnesses for each simplex * \remark Added for debugging purposes. */ template< class KNearestNeighbors > - bool is_witness_complex(KNearestNeighbors & knn) + bool is_witness_complex(KNearestNeighbors & knn, bool print_output) { //bool final_result = true; for (Simplex_handle sh: sc.complex_simplex_range()) @@ -231,19 +233,25 @@ namespace Gudhi { if (has_vertices) { is_witnessed = true; - std::cout << "The simplex "; - print_vector(simplex); - std::cout << " is witnessed by the witness "; - print_vector(w); - std::cout << std::endl; + if (print_output) + { + std::cout << "The simplex "; + print_vector(simplex); + std::cout << " is witnessed by the witness "; + print_vector(w); + std::cout << std::endl; + } break; } } if (!is_witnessed) { - std::cout << "The following simplex is not witnessed "; - print_vector(simplex); - std::cout << std::endl; + if (print_output) + { + std::cout << "The following simplex is not witnessed "; + print_vector(simplex); + std::cout << std::endl; + } assert(is_witnessed); return false; } diff --git a/src/Witness_complex/include/gudhi/Witness_complex_doc.h b/src/Witness_complex/include/gudhi/Witness_complex_doc.h index 22cfe992..446f0d11 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex_doc.h +++ b/src/Witness_complex/include/gudhi/Witness_complex_doc.h @@ -21,14 +21,15 @@ \section Implementation - Two classes are implemented in this module: Gudhi::Witness_complex and Gudhi::Relaxed_witness_complex. + The principal class of this module is Gudhi::Witness_complex. - While Gudhi::Witness_complex represents the classical witness complex, Gudhi::Relaxed_witness_complex takes an additional positive real parameter \f$ \alpha \f$ and constructs simplices \f$ \sigma \f$, for which - there exists \f$ w \in W \f$, such that \f$ d(p,w) < d(q,w) + \alpha \f$ for all \f$ p \in \sigma, q \in L\setminus \sigma \f$. - - In both cases, the constructors take a {witness}x{closest_landmarks} table, + In both cases, the constructor for this class takes a {witness}x{closest_landmarks} table, which can be constructed by two additional classes Landmark_choice_by_furthest_point and Landmark_choice_by_random_point also included in the module. + *\image html "bench_Cy8.png" "Running time as function on number of landmarks" width=10cm + *\image html "bench_sphere.png" "Running time as function on number of witnesses for |L|=300" width=10cm + + \copyright GNU General Public License v3. -- cgit v1.2.3 From 6775c601c9c9f7a1f0679dbb1fecb3bd5181eb6a Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 10 Dec 2015 09:38:37 +0000 Subject: Changed a phrase in doc git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@938 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 407e6784210123fbd00b71efad0659f2d7c9263b --- src/Witness_complex/include/gudhi/Witness_complex_doc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex_doc.h b/src/Witness_complex/include/gudhi/Witness_complex_doc.h index 446f0d11..71c8776b 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex_doc.h +++ b/src/Witness_complex/include/gudhi/Witness_complex_doc.h @@ -23,8 +23,8 @@ The principal class of this module is Gudhi::Witness_complex. - In both cases, the constructor for this class takes a {witness}x{closest_landmarks} table, - which can be constructed by two additional classes Landmark_choice_by_furthest_point and Landmark_choice_by_random_point also included in the module. + In both cases, the constructor for this class takes a {witness}x{closest_landmarks} table, where each row represents a witness and consists of landmarks sorted by distance to this witness. + This table can be constructed by two additional classes Landmark_choice_by_furthest_point and Landmark_choice_by_random_point also included in the module. *\image html "bench_Cy8.png" "Running time as function on number of landmarks" width=10cm *\image html "bench_sphere.png" "Running time as function on number of witnesses for |L|=300" width=10cm -- cgit v1.2.3 From d9f8f2d006c1c57c05eeb6eddbc625e44ebd8831 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 11 Dec 2015 10:11:32 +0000 Subject: Adding corecntions suggested by the Editorial Board to the Bitmap_cubical_complex class. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@942 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 81338409d0c6dc3435474f08f499dd5b72812ad6 --- .../doc/Gudhi_Cubical_Complex_doc.h | 106 +++++ src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf | Bin 0 -> 13940 bytes src/Bitmap_cubical_complex/doc/exampleBitmap.pdf | Bin 0 -> 11122 bytes .../example/Bitmap_cubical_complex.cpp | 5 +- .../include/gudhi/Bitmap_cubical_complex.h | 455 +++++++-------------- .../include/gudhi/Bitmap_cubical_complex/counter.h | 171 ++++++++ .../include/gudhi/Bitmap_cubical_complex_base.h | 22 +- src/Bitmap_cubical_complex/include/gudhi/counter.h | 177 -------- 8 files changed, 440 insertions(+), 496 deletions(-) create mode 100644 src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h create mode 100644 src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf create mode 100644 src/Bitmap_cubical_complex/doc/exampleBitmap.pdf create mode 100644 src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/counter.h (limited to 'src') diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h new file mode 100644 index 00000000..4acf2b3a --- /dev/null +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -0,0 +1,106 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-Saclay (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 . + */ + + +#pragma once + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +/** \defgroup cubical_complex Cubical complex +* +* \author Pawel Dlotko +* +* @{ +* + +*Cubical complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. +* +* An \emph{elementary interval} is an interval of a form $[n,n+1]$, or $[n,n]$, for $n \in \mathcal{Z}$. The first one is called \emph{non-degenerated}, while the second one is \emph{degenerated} interval. A \emph{boundary of a elementary +*interval} is a chain $\partial [n,n+1] = [n+1,n+1]-[n,n]$ in case of non-degenerated elementary interval and $\partial [n,n] = 0$ in case of degenerated elementary interval. An \emph{elementary cube} $C$ is a +*product of elementary intervals, $C=I_1 \times \ldots \times I_n$. \emph{Embedding dimension} of a cube is n, the number of elementary intervals (degenerated or not) in the product. A \emph{dimension of a cube} $C=I_1 \times ... \times I_n$ is the +*number of non degenerated elementary intervals in the product. A \emph{boundary of a cube} $C=I_1 \times \ldots \times I_n$ is a chain obtained in the following way: +*\[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\] +*A \emph{cubical complex} $\mathcal{K}$ is a collection of cubes closed under operation of taking boundary (i.e. boundary of every cube from the collection is in the collection). A cube $C$ in cubical complex $\mathcal{K}$ is \emph{maximal} if it is not in +*a boundary of any other cube in $\mathcal{K}$. A \emph{support} of a cube $C$ is the set in $\mathbb{R}^n$ occupied by $C$ ($n$ is the embedding dimension of $C$). +* +*Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may be a set of two elements). +* +*For further details and theory of cubical complexes, please consult a book:\\ +*Computational homology, by Tomasz Kaczynski, Konstantin Mischaikow, and Marion Mrozek, Appl. Math. Sci., vol. 157, Springer-Verlag, New York, 2004 +* +*as well as the paper: +*Efficient computation of persistent homology for cubical data by Hubert Wagner, Chao Chen, Erald Vuini (published in the proceedings of Workshop on Topology-based Methods in Data +*Analysis and Visualization) +* +*\section{Data structure.} +* +*The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in $\mathbb{R}^n$. This extra +*assumption allows for a memory efficient way of storing cubical complexes in a form of so called bitmaps. Let $R = [b_1,e_1] \times \ldots \times [b_n,e_n]$, for $b_1,...b_n,e_1,...,e_n \in \mathbb{Z}$ +*, $b_i \leq d_i$ be the considered rectangular region and let $\mathcal{K}$ be a filtered cubical complex having the rectangle $R$ as its support. Note that the structure of the coordinate system gives a way +*a lexicographical ordering of cells of $\mathcal{K}$. This ordering is a base of the presented bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector +*of the values of filtration. This, together with dimension of $\mathcal{K}$ and the sizes of $\mathcal{K}$ in all directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube $C \in \mathcal{K}$. +* +*\image html "bitmapAllCubes.pdf" "Cubical complex in $\mathbb{R}^2". +* +*Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical complexes in $\mathbb{R}$. The number of all cubes in each direction is +*equal $2n+1$, where $n$ is the number of maximal cubes in the considered direction. Let us consider a cube at the position $k$ in the bitmap. Knowing the sizes of the bitmap, +*by a series of modulo operation, we can determine which elementary intervals are present in the product that gives the cube $C$. In a similar way, we can compute boundary +*and the coboundary of each cube. Further details can be found in the literature. +* +*\section{Input Format.} +* +*In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star filtration to all cubes. There are a number of constructors +*that can be used to construct cubical complex by users who want to use the code directly. They can be found in the \emph{Bitmap\_cubical\_complex} class. +*Currently one input from a text file is used. It uses a format used already in Perseus software $(http://www.sas.upenn.edu/~vnanda/perseus/)$ by Vidit Nanda. +*Below we are providing a description of the format. +* +*\begin{enumerate} +*\item The first line of the file is $d$, the embedding dimension of a complex. +*\item The next $d$ lines consist of positive numbers being the numbers of top dimensional cubes in the given direction. Let us call those numbers $n_1,\ldots,n_d$. +*\item Later there is a sequence of $n_1 \dot \ldots \dot n_d$ numbers in a lexicographical ordering. Those numbers are filtrations of top dimensional cubes. +*\end{enumerate} +* +*\image html "exampleBitmap.pdf" "Example of a input data." +* +*The input file for the following complex is: +*\begin{verbatim} +*2 +*3 +*3 +*1 +*2 +*3 +*8 +*20 +*4 +*7 +*6 +*5 +*\end{verbatim} +* +* +} +} diff --git a/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf new file mode 100644 index 00000000..694105e4 Binary files /dev/null and b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf differ diff --git a/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf b/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf new file mode 100644 index 00000000..ef930c0c Binary files /dev/null and b/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf differ diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index 31da3609..e56428b6 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -59,16 +59,13 @@ lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for exam Bitmap_cubical_complex b( argv[1] ); - // Compute the persistence diagram of the complex persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); pcoh.init_coefficients( p ); //initilizes the coefficient field for homology pcoh.compute_persistent_cohomology( min_persistence ); - - stringstream ss; ss << argv[1] << "_persistence"; - std::ofstream out((char*)ss.str().c_str()); + std::ofstream out(ss.str().c_str()); pcoh.output_diagram(out); out.close(); diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index f2c753d9..b8887e71 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -34,7 +34,9 @@ namespace Cubical_complex { //global variable, was used just for debugging. -const bool globalDbg = false; +const bool globalDbg = false; + +template class is_before_in_filtration; template class Bitmap_cubical_complex : public Bitmap_cubical_complex_base @@ -45,71 +47,8 @@ public: //*********************************************// friend class Simplex_handle; typedef size_t Simplex_key; - typedef T Filtration_value; - - -//*********************************************// -//Simplex handle class -//*********************************************// - /** - * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. - * Elements of this class are: the pointer to the bitmap B in which the considered cell is - * together with a position of this cell in B. Given this data, - * one can get all the information about the considered cell. - **/ - class Simplex_handle - { - public: - Simplex_handle() - { - if ( globalDbg ){cerr << "Simplex_handle()\n";} - this->b = 0; - this->position = 0; - } - - Simplex_handle(Bitmap_cubical_complex* b) - { - if ( globalDbg ) - { - cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; - } - this->b = b; - this->position = 0; - } - - //Simplex_handle( const Simplex_handle& org ):b(org.b) - //{ - // if ( globalDbg ){cerr << "Simplex_handle( const Simplex_handle& org )\n";} - // this->position = org.position; - //} - - Simplex_handle operator = ( const Simplex_handle& rhs ) - { - if ( globalDbg ){cerr << "Simplex_handle operator = \n";} - this->position = rhs.position; - this->b = rhs.b; - return *this; - } - - Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position) - { - if ( globalDbg ) - { - cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; - cerr << "Position : " << position << endl; - } - this->b = b; - this->position = position; - } - friend class Bitmap_cubical_complex; - private: - Bitmap_cubical_complex* b; - Simplex_key position; - //Assumption -- field above always keep the REAL position of simplex in the bitmap, - //no matter what keys have been. - //to deal with the keys, the class Bitmap_cubical_complex have extra vectors: key_associated_to_simplex and - //simplex_associated_to_key that allow to move between actual cell and the key assigned to it. - }; + typedef T Filtration_value; + typedef Simplex_key Simplex_handle; //*********************************************// @@ -125,39 +64,37 @@ public: * Constructor form a Perseus-style file. **/ Bitmap_cubical_complex( const char* perseus_style_file ): - Bitmap_cubical_complex_base(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1), - simplex_associated_to_key(this->total_number_of_cells+1) + Bitmap_cubical_complex_base(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) { if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) { - this->key_associated_to_simplex[i] = this->simplex_associated_to_key[i] = i; + this->key_associated_to_simplex[i] = i; } - //we initialize this only once, in each constructor, when the bitmap is constructed. + //we initialize this only once, in each constructor, when the bitmap is constructed. //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. - this->initialize_elements_ordered_according_to_filtration(); + this->initialize_simplex_associated_to_key(); } /** - * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells * in the following directions and vector of element of a type T * with filtration on top dimensional cells. **/ Bitmap_cubical_complex( std::vector& dimensions , std::vector& top_dimensional_cells ): Bitmap_cubical_complex_base(dimensions,top_dimensional_cells), - key_associated_to_simplex(this->total_number_of_cells+1), - simplex_associated_to_key(this->total_number_of_cells+1) + key_associated_to_simplex(this->total_number_of_cells+1) { for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) { - this->key_associated_to_simplex[i] = this->simplex_associated_to_key[i] = i; + this->key_associated_to_simplex[i] = i; } - //we initialize this only once, in each constructor, when the bitmap is constructed. + //we initialize this only once, in each constructor, when the bitmap is constructed. //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. - this->initialize_elements_ordered_according_to_filtration(); + this->initialize_simplex_associated_to_key(); } //*********************************************// @@ -174,15 +111,17 @@ public: /** * Returns a Simplex_handle to a cube that do not exist in this complex. **/ - Simplex_handle null_simplex() - { - return Simplex_handle(this,this->data.size()); - } + static Simplex_handle null_simplex() + { + if ( globalDbg ){cerr << "Simplex_handle null_simplex()\n";} + return std::numeric_limits::max(); + } + /** * Returns dimension of the complex. **/ - size_t dimension() + inline size_t dimension()const { return this->sizes.size(); } @@ -190,10 +129,10 @@ public: /** * Return dimension of a cell pointed by the Simplex_handle. **/ - unsigned dimension(const Simplex_handle& sh) + inline unsigned dimension(const Simplex_handle& sh)const { if ( globalDbg ){cerr << "unsigned dimension(const Simplex_handle& sh)\n";} - if ( sh.position != this->data.size() ) return sh.b->get_dimension_of_a_cell( sh.position ); + if ( sh != std::numeric_limits::max() ) return this->get_dimension_of_a_cell( sh ); return -1; } @@ -204,26 +143,30 @@ public: { if ( globalDbg ){cerr << "T filtration(const Simplex_handle& sh)\n";} //Returns the filtration value of a simplex. - if ( sh.position != this->data.size() ) return sh.b->data[ sh.position ]; + if ( sh != std::numeric_limits::max() ) return this->data[sh]; return std::numeric_limits::max(); } /** * Return a key which is not a key of any cube in the considered data structure. **/ - Simplex_key null_key() + static Simplex_key null_key() { if ( globalDbg ){cerr << "Simplex_key null_key()\n";} - return this->data.size(); + return std::numeric_limits::max(); } /** * Return the key of a cube pointed by the Simplex_handle. **/ - Simplex_key key(const Simplex_handle& sh) + Simplex_key key(const Simplex_handle& sh)const { - if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} - return sh.b->key_associated_to_simplex[ sh.position ]; + if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} + if ( sh != std::numeric_limits::max() ) + { + return this->key_associated_to_simplex[sh]; + } + return this->null_key(); } /** @@ -231,8 +174,12 @@ public: **/ Simplex_handle simplex(Simplex_key key) { - if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} - return Simplex_handle( this , this->simplex_associated_to_key[ key ] ); + if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} + if ( key != std::numeric_limits::max() ) + { + return this->simplex_associated_to_key[ key ]; + } + return null_simplex(); } /** @@ -240,15 +187,29 @@ public: **/ void assign_key(Simplex_handle& sh, Simplex_key key) { - if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} - this->key_associated_to_simplex[sh.position] = key; - this->simplex_associated_to_key[key] = sh.position; + if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} + + + + + + + + +if ( key == std::numeric_limits::max() ) return;//TODO FAKE!!! CHEATING!!! + + + + + + this->key_associated_to_simplex[sh] = key; + this->simplex_associated_to_key[key] = sh; } /** * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. **/ - void initialize_elements_ordered_according_to_filtration(); + void initialize_simplex_associated_to_key(); @@ -256,104 +217,42 @@ public: //Iterators //*********************************************// - /** - * Boundary_simplex_iterator class allows iteration on boundary of each cube. - **/ - class Boundary_simplex_range; - class Boundary_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > - { - //Iterator on the simplices belonging to the boundary of a simplex. - //value_type must be 'Simplex_handle'. - public: - Boundary_simplex_iterator( Simplex_handle& sh ):sh(sh) - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n";} - this->position = 0; - this->boundary_elements = this->sh.b->get_boundary_of_a_cell( this->sh.position ); - } - Boundary_simplex_iterator operator++() - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator operator++()\n";} - ++this->position; - return *this; - } - Boundary_simplex_iterator operator++(int) - { - Boundary_simplex_iterator result = *this; - ++(*this); - return result; - } - Boundary_simplex_iterator operator =( const Boundary_simplex_iterator& rhs ) - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator operator =\n";} - this->sh = rhs.sh; - this->boundary_elements.clear(); - this->boundary_elementsinsert - (this->boundary_elements.end(), rhs.boundary_elements.begin(), rhs.boundary_elements.end()); - } - bool operator == ( const Boundary_simplex_iterator& rhs ) - { - if ( globalDbg ){cerr << "bool operator ==\n";} - if ( this->position == rhs.position ) - { - if ( this->boundary_elements.size() != rhs.boundary_elements.size() )return false; - for ( size_t i = 0 ; i != this->boundary_elements.size() ; ++i ) - { - if ( this->boundary_elements[i] != rhs.boundary_elements[i] )return false; - } - return true; - } - return false; - } - - bool operator != ( const Boundary_simplex_iterator& rhs ) - { - if ( globalDbg ){cerr << "bool operator != \n";} - return !(*this == rhs); - } - Simplex_handle operator*() - { - if ( globalDbg ){cerr << "Simplex_handle operator*\n";} - return Simplex_handle( this->sh.b , this->boundary_elements[this->position] ); - } - - friend class Boundary_simplex_range; - private: - Simplex_handle sh; - std::vector< size_t > boundary_elements; - size_t position; - }; /** * Boundary_simplex_range class provides ranges for boundary iterators. - **/ + **/ + typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; class Boundary_simplex_range { //Range giving access to the simplices in the boundary of a simplex. //.begin() and .end() return type Boundary_simplex_iterator. - public: - Boundary_simplex_range(const Simplex_handle& sh):sh(sh){}; - Boundary_simplex_iterator begin() - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator begin\n";} - Boundary_simplex_iterator it( this->sh ); - return it; - } - Boundary_simplex_iterator end() - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator end()\n";} - Boundary_simplex_iterator it( this->sh ); - it.position = it.boundary_elements.size(); - return it; - } - private: - Simplex_handle sh; - }; + public: + typedef Boundary_simplex_iterator const_iterator; + Boundary_simplex_range(const Simplex_handle& sh , Bitmap_cubical_complex* CC_):sh(sh),CC(CC_) + { + this->boundary_elements = this->CC->get_boundary_of_a_cell( sh ); + } + Boundary_simplex_iterator begin() + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator begin\n";} + return this->boundary_elements.begin(); + + } + Boundary_simplex_iterator end() + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator end()\n";} + return this->boundary_elements.end(); + } + private: + Simplex_handle sh; + Bitmap_cubical_complex* CC; + std::vector< Simplex_handle > boundary_elements; + }; /** - * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. + * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. * Secondary criteria for filtration are: * (1) Dimension of a cube (lower dimensional comes first). * (2) Position in the data structure (the ones that are earlies in the data structure comes first). @@ -385,17 +284,13 @@ public: this->b = rhs.b; this->position = rhs.position; } - bool operator == ( const Filtration_simplex_iterator& rhs ) + bool operator == ( const Filtration_simplex_iterator& rhs )const { if ( globalDbg ){cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n";} - if ( this->position == rhs.position ) - { - return true; - } - return false; + return ( this->position == rhs.position ); } - bool operator != ( const Filtration_simplex_iterator& rhs ) + bool operator != ( const Filtration_simplex_iterator& rhs )const { if ( globalDbg ){cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n";} return !(*this == rhs); @@ -403,7 +298,7 @@ public: Simplex_handle operator*() { if ( globalDbg ){cerr << "Simplex_handle operator*()\n";} - return Simplex_handle( this->b , this->b->elements_ordered_according_to_filtration[ this->position ] ); + return this->b->simplex_associated_to_key[ this->position ]; } friend class Filtration_simplex_range; @@ -420,7 +315,8 @@ public: { //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. - public: + public: + typedef Filtration_simplex_iterator const_iterator; Filtration_simplex_range(Bitmap_cubical_complex* b):b(b){}; Filtration_simplex_iterator begin() { @@ -431,7 +327,7 @@ public: { if ( globalDbg ){cerr << "Filtration_simplex_iterator end()\n";} Filtration_simplex_iterator it( this->b ); - it.position = this->b->elements_ordered_according_to_filtration.size(); + it.position = this->b->simplex_associated_to_key.size(); return it; } private: @@ -443,19 +339,19 @@ public: //*********************************************// //Methods to access iterators from the container: /** - * boundary_simplex_range creates an object of a Boundary_simplex_range class + * boundary_simplex_range creates an object of a Boundary_simplex_range class * that provides ranges for the Boundary_simplex_iterator. **/ Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) { if ( globalDbg ){cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n";} - //Returns a range giving access to all simplices of the boundary of a simplex, + //Returns a range giving access to all simplices of the boundary of a simplex, //i.e. the set of codimension 1 subsimplices of the Simplex. - return Boundary_simplex_range(sh); + return Boundary_simplex_range(sh,this); } /** - * filtration_simplex_range creates an object of a Filtration_simplex_range class + * filtration_simplex_range creates an object of a Filtration_simplex_range class * that provides ranges for the Filtration_simplex_iterator. **/ Filtration_simplex_range filtration_simplex_range() @@ -470,9 +366,9 @@ public: //*********************************************// //Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are there. - //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so + //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so //I understand that this is something that was planned (for simplicial maps?) - //but was never finished. The only idea I have here is to use the same empty structure from + //but was never finished. The only idea I have here is to use the same empty structure from //IndexingTag.h file, but only if the compiler needs it. If the compiler //do not need it, then I would rather not add here elements which I do not understand. //typedef Indexing_tag @@ -481,7 +377,7 @@ public: **/ std::pair endpoints( Simplex_handle sh ) { - std::vector< size_t > bdry = this->get_boundary_of_a_cell( sh.position ); + std::vector< size_t > bdry = this->get_boundary_of_a_cell( sh ); if ( globalDbg ) { cerr << "std::pair endpoints( Simplex_handle sh )\n"; @@ -490,7 +386,7 @@ public: //this method returns two first elements from the boundary of sh. if ( bdry.size() < 2 ) throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the boundary."); - return std::make_pair( Simplex_handle(this,bdry[0]) , Simplex_handle(this,bdry[1]) ); + return std::make_pair( bdry[0] , bdry[1] ); } @@ -508,9 +404,9 @@ public: if ( globalDbg ){cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n";} //find the position of the first simplex of a dimension d this->position = 0; - while ( - (this->position != b->data.size()) && - ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) + while ( + (this->position != b->data.size()) && + ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) ) { ++this->position; @@ -523,9 +419,9 @@ public: if ( globalDbg ){cerr << "Skeleton_simplex_iterator operator++()\n";} //increment the position as long as you did not get to the next element of the dimension dimension. ++this->position; - while ( - (this->position != this->b->data.size()) && - ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) + while ( + (this->position != this->b->data.size()) && + ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) ) { ++this->position; @@ -544,17 +440,13 @@ public: this->b = rhs.b; this->position = rhs.position; } - bool operator == ( const Skeleton_simplex_iterator& rhs ) + bool operator == ( const Skeleton_simplex_iterator& rhs )const { if ( globalDbg ){cerr << "bool operator ==\n";} - if ( this->position == rhs.position ) - { - return true; - } - return false; + return ( this->position == rhs.position ); } - bool operator != ( const Skeleton_simplex_iterator& rhs ) + bool operator != ( const Skeleton_simplex_iterator& rhs )const { if ( globalDbg ){cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n";} return !(*this == rhs); @@ -562,7 +454,7 @@ public: Simplex_handle operator*() { if ( globalDbg ){cerr << "Simplex_handle operator*() \n";} - return Simplex_handle( this->b , this->position ); + return this->position; } friend class Skeleton_simplex_range; @@ -578,7 +470,8 @@ public: { //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. - public: + public: + typedef Skeleton_simplex_iterator const_iterator; Skeleton_simplex_range(Bitmap_cubical_complex* b , unsigned dimension):b(b),dimension(dimension){}; Skeleton_simplex_iterator begin() { @@ -606,107 +499,59 @@ public: return Skeleton_simplex_range( this , dimension ); } + friend class is_before_in_filtration; -//*********************************************// -//functions used for debugging: - /** - * Function used for debugging purposes. - **/ - //void printkey_associated_to_simplex() - //{ - // for ( size_t i = 0 ; i != this->data.size() ; ++i ) - // { - // cerr << i << " -> " << this->simplex_associated_to_key[i] << endl; - // } - //} - - /** - * Function used for debugging purposes. - **/ - size_t printRealPosition( const Simplex_handle& sh ) - { - return sh.position; - } - -private: +protected: std::vector< size_t > key_associated_to_simplex; std::vector< size_t > simplex_associated_to_key; - std::vector< size_t > elements_ordered_according_to_filtration; - //filed above is needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. };//Bitmap_cubical_complex - + template -bool compare_elements_for_elements_ordered_according_to_filtration -( const std::pair< size_t , std::pair< T , char > >& f , const std::pair< size_t , std::pair< T , char > >& s ) +void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { - if ( globalDbg ){cerr << "compare_elements_for_elements_ordered_according_to_filtration\n";} - if ( f.second.first < s.second.first ) - { - return true; - } - else + if ( globalDbg ) { - if ( f.second.first > s.second.first ) - { - return false; - } - else - { - //in this case f.second.first == s.second.first, and we use dimension to compare: - if ( f.second.second < s.second.second ) - { - return true; - } - else - { - if ( f.second.second > s.second.second ) - { - return false; - } - else - { - //in this case, both the filtration value and the dimensions for those cells are the same. - //Since it may be nice to have a stable sorting procedure, in this case, - //we compare positions in the bitmap: - return ( f.first < s.first ); - } - } - } + cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; } + std::vector data_of_elements_from_bitmap( this->data.size() ); + std::iota (std::begin(data_of_elements_from_bitmap), std::end(data_of_elements_from_bitmap), 0); + std::sort( data_of_elements_from_bitmap.begin() , + data_of_elements_from_bitmap.end() , + is_before_in_filtration(this) ); + this->simplex_associated_to_key = data_of_elements_from_bitmap; } - + + template -void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() +class is_before_in_filtration { - if ( globalDbg ) - { - cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; - } - //( position , (filtration , dimension) ) - std::vector< std::pair< size_t , std::pair< T , char > > > data_of_elements_from_bitmap( this->data.size() ); - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - //TODO -- this can be optimized by having a counter here. - //We do not need to re-compute the dimension for every cell from scratch - data_of_elements_from_bitmap[i] = - std::make_pair( i , std::make_pair( this->data[i] , this->get_dimension_of_a_cell(i) ) ); - } - std::sort( data_of_elements_from_bitmap.begin() , - data_of_elements_from_bitmap.end() , - compare_elements_for_elements_ordered_according_to_filtration ); - - std::vector< size_t > - elements_ordered_according_to_filtration_then_to_dimension_then_to_position - ( this->data.size() ); - for ( size_t i = 0 ; i != data_of_elements_from_bitmap.size() ; ++i ) +public: + explicit is_before_in_filtration(Bitmap_cubical_complex * CC) + : CC_(CC) { } + + bool operator()( const typename Bitmap_cubical_complex::Simplex_handle sh1, const typename Bitmap_cubical_complex::Simplex_handle sh2) const { - elements_ordered_according_to_filtration_then_to_dimension_then_to_position[i] - = data_of_elements_from_bitmap[i].first; - } - this->elements_ordered_according_to_filtration = - elements_ordered_according_to_filtration_then_to_dimension_then_to_position; -} + // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. + T fil1 = CC_->data[sh1]; + T fil2 = CC_->data[sh2]; + if ( fil1 != fil2 ) + { + return fil1 < fil2; + } + //in this case they are on the same filtration level, so the dimension decide. + size_t dim1 = CC_->get_dimension_of_a_cell(sh1); + size_t dim2 = CC_->get_dimension_of_a_cell(sh2); + if ( dim1 != dim2 ) + { + return dim1 < dim2; + } + //in this case both filtration and dimensions of the considered cubes are the same. To have stable sort, we simply compare their positions in the bitmap: + return sh1 < sh2; + } +protected: + Bitmap_cubical_complex* CC_; + }; //****************************************************************************************************************// @@ -716,4 +561,4 @@ void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtrat } -} \ No newline at end of file +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h new file mode 100644 index 00000000..3a17b4a0 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h @@ -0,0 +1,171 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-Saclay (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 . + */ + +#pragma once + +#include +#include + +using namespace std; + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +/** +* This is an implementation of a counter being a vector of integers. +* The constructor of the class takes as an input two vectors W and V. +* It assumes that W < V coordinatewise. +* If the initial counter W is not specified, it is assumed to be vector of zeros. +* The class allows to iterate between W and V by using increment() function. +* The increment() function returns a bool value. +* The current counter reach the end counter V if the value returned by the increment function is FALSE. +* This class is needed for the implementation of a bitmapCubicalComplex. +**/ + +class counter +{ +public: + /** + * Constructor of a counter class. It takes only the parameter which is the end value of the counter. + * The default beginning value is a vector of the same length as the endd, filled-in with zeros. + **/ + counter(std::vector const& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} + //counter(std::vector< int >& endd) + //{ + // for ( size_t i = 0 ; i != endd.size() ; ++i ) + // { + // this->current.push_back(0); + // this->begin.push_back(0); + // this->end.push_back( endd[i] ); + // } + //} + + + /** + * Constructor of a counter class. It takes as the input beginn and end vector. + * It assumes that begin vector is lexicographically below the end vector. + **/ + counter(std::vector< unsigned >& beginn , std::vector< unsigned >& endd):begin(beginn),end(endd),current(endd.size(),0) + { + if ( beginn.size() != endd.size() ) + throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; + } + + /** + * Function to increment the counter. If the value returned by the function is true, + * then the incrementation process was successful. + * If the value of the function is false, that means, that the counter have reached its end-value. + **/ + bool increment() + { + size_t i = 0; + while( (i != this->end.size()) && (this->current[i] == this->end[i]) ) + { + ++i; + } + + if ( i == this->end.size() )return false; + ++this->current[i]; + for ( size_t j = 0 ; j != i ; ++j ) + { + this->current[j] = this->begin[j]; + } + return true; + } + + /** + * Function to check if we are at the end of counter. + **/ + bool isFinal() + { + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( this->current[i] == this->end[i] )return true; + } + return false; + } + + /** + * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. + * Its aim is to find an counter corresponding to the element the following + * boundary element is identified with when periodic boundary conditions are imposed. + **/ + std::vector< unsigned > find_opposite( std::vector< bool >& directionsForPeriodicBCond ) + { + std::vector< unsigned > result; + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( (this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true) ) + { + result.push_back( this->begin[i] ); + } + else + { + result.push_back( this->current[i] ); + } + } + return result; + } + + /** + * Function checking at which positions the current value of a counter is the final value of the counter. + **/ + std::vector< bool > directions_of_finals() + { + std::vector< bool > result; + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( this->current[i] == this->end[i] ) + { + result.push_back( true ); + } + else + { + result.push_back( false ); + } + } + return result; + } + + /** + * Function to write counter to the stream. + **/ + friend std::ostream& operator<<(std::ostream& out , const counter& c ) + { + //cerr << "c.current.size() : " << c.current.size() << endl; + for ( size_t i = 0 ; i != c.current.size() ; ++i ) + { + out << c.current[i] << " "; + } + return out; + } +private: + std::vector< unsigned > begin; + std::vector< unsigned > end; + std::vector< unsigned > current; +}; + +} +} \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 2c2bd481..4e63b9c3 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -30,7 +30,7 @@ #include #include #include -#include "counter.h" +#include "Bitmap_cubical_complex/counter.h" using namespace std; @@ -182,11 +182,9 @@ public: public: Top_dimensional_cells_iterator( Bitmap_cubical_complex_base& b ):b(b) { - for ( size_t i = 0 ; i != b.dimension() ; ++i ) - { - this->counter.push_back(0); - } - } + this->counter = std::vector(b.dimension()); + std::fill( this->counter.begin() , this->counter.end() , 0 ); + } Top_dimensional_cells_iterator operator++() { //first find first element of the counter that can be increased: @@ -264,7 +262,7 @@ public: } friend class Bitmap_cubical_complex_base; protected: - std::vector< unsigned > counter; + std::vector< size_t > counter; Bitmap_cubical_complex_base& b; }; Top_dimensional_cells_iterator top_dimensional_cells_begin() @@ -478,12 +476,16 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( si getchar(); } - std::vector< size_t > boundary_elements; + std::vector< size_t > boundary_elements( 2*dimensions_in_which_cell_has_nonzero_length.size() ); if ( dimensions_in_which_cell_has_nonzero_length.size() == 0 )return boundary_elements; for ( size_t i = 0 ; i != dimensions_in_which_cell_has_nonzero_length.size() ; ++i ) { - boundary_elements.push_back( cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); - boundary_elements.push_back( cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); + //boundary_elements.push_back( cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); + //boundary_elements.push_back( cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); + boundary_elements[2*i] = cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ]; + boundary_elements[2*i+1] = cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ]; + + if (bdg) cerr << "multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " << multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; diff --git a/src/Bitmap_cubical_complex/include/gudhi/counter.h b/src/Bitmap_cubical_complex/include/gudhi/counter.h deleted file mode 100644 index a5fda36f..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/counter.h +++ /dev/null @@ -1,177 +0,0 @@ -/* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-Saclay (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 . - */ - -#pragma once - -#include -#include - -using namespace std; - -namespace Gudhi -{ - -namespace Cubical_complex -{ - -/** -* This is an implementation of a counter being a vector of integers. -* The constructor of the class takes as an input two vectors W and V. -* It assumes that W < V coordinatewise. -* If the initial counter W is not specified, it is assumed to be vector of zeros. -* The class allows to iterate between W and V by using increment() function. -* The increment() function returns a bool value. -* The current counter reach the end counter V if the value returned by the increment function is FALSE. -* This class is needed for the implementation of a bitmapCubicalComplex. -**/ - -class counter -{ -public: - /** - * Constructor of a counter class. It takes only the parameter which is the end value of the counter. - * The default beginning value is a vector of the same length as the endd, filled-in with zeros. - **/ - counter(std::vector const& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} - //counter(std::vector< int >& endd) - //{ - // for ( size_t i = 0 ; i != endd.size() ; ++i ) - // { - // this->current.push_back(0); - // this->begin.push_back(0); - // this->end.push_back( endd[i] ); - // } - //} - - - /** - * Constructor of a counter class. It takes as the input beginn and end vector. - * It assumes that begin vector is lexicographically below the end vector. - **/ - counter(std::vector< unsigned >& beginn , std::vector< unsigned >& endd) - { - if ( beginn.size() != endd.size() ) - throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; - for ( size_t i = 0 ; i != endd.size() ; ++i ) - { - this->current.push_back(0); - this->begin.push_back(0); - this->end.push_back( endd[i] ); - } - } - - /** - * Function to increment the counter. If the value returned by the function is true, - * then the incrementation process was successful. - * If the value of the function is false, that means, that the counter have reached its end-value. - **/ - bool increment() - { - size_t i = 0; - while( (i != this->end.size()) && (this->current[i] == this->end[i]) ) - { - ++i; - } - - if ( i == this->end.size() )return false; - ++this->current[i]; - for ( size_t j = 0 ; j != i ; ++j ) - { - this->current[j] = this->begin[j]; - } - return true; - } - - /** - * Function to check if we are at the end of counter. - **/ - bool isFinal() - { - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( this->current[i] == this->end[i] )return true; - } - return false; - } - - /** - * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. - * Its aim is to find an counter corresponding to the element the following - * boundary element is identified with when periodic boundary conditions are imposed. - **/ - std::vector< unsigned > find_opposite( std::vector< bool >& directionsForPeriodicBCond ) - { - std::vector< unsigned > result; - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( (this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true) ) - { - result.push_back( this->begin[i] ); - } - else - { - result.push_back( this->current[i] ); - } - } - return result; - } - - /** - * Function checking at which positions the current value of a counter is the final value of the counter. - **/ - std::vector< bool > directions_of_finals() - { - std::vector< bool > result; - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( this->current[i] == this->end[i] ) - { - result.push_back( true ); - } - else - { - result.push_back( false ); - } - } - return result; - } - - /** - * Function to write counter to the stream. - **/ - friend std::ostream& operator<<(std::ostream& out , const counter& c ) - { - //cerr << "c.current.size() : " << c.current.size() << endl; - for ( size_t i = 0 ; i != c.current.size() ; ++i ) - { - out << c.current[i] << " "; - } - return out; - } -private: - std::vector< unsigned > begin; - std::vector< unsigned > end; - std::vector< unsigned > current; -}; - -} -} \ No newline at end of file -- cgit v1.2.3 From f0ca2ba2080c8f2b01a7cd459560980dfcb964f8 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 11 Dec 2015 12:44:20 +0000 Subject: Pictures in png format git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@943 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 470f82a103e17ffbda2b784fa829e5b0b11458e6 --- .../doc/Gudhi_Cubical_Complex_doc.h | 1 + src/Bitmap_cubical_complex/doc/bitmapAllCubes.png | Bin 0 -> 38944 bytes src/Bitmap_cubical_complex/doc/exampleBitmap.png | Bin 0 -> 9594 bytes 3 files changed, 1 insertion(+) create mode 100644 src/Bitmap_cubical_complex/doc/bitmapAllCubes.png create mode 100644 src/Bitmap_cubical_complex/doc/exampleBitmap.png (limited to 'src') diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index 4acf2b3a..6e821ce4 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -102,5 +102,6 @@ namespace Cubical_complex *\end{verbatim} * * +*@}//end of the group } } diff --git a/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png new file mode 100644 index 00000000..77167b13 Binary files /dev/null and b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png differ diff --git a/src/Bitmap_cubical_complex/doc/exampleBitmap.png b/src/Bitmap_cubical_complex/doc/exampleBitmap.png new file mode 100644 index 00000000..f8207473 Binary files /dev/null and b/src/Bitmap_cubical_complex/doc/exampleBitmap.png differ -- cgit v1.2.3 From fd41fbbb321b36c143129b5a311e015bf7c44a6f Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 11 Dec 2015 13:04:06 +0000 Subject: Removed pdf to use png Biblio issue git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@944 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 68e93aa53ebadcde4b44eec881b72080e6ceaa70 --- biblio/bibliography.bib | 27 +++++++ .../doc/Gudhi_Cubical_Complex_doc.h | 89 ++++++++++----------- src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf | Bin 13940 -> 0 bytes src/Bitmap_cubical_complex/doc/exampleBitmap.pdf | Bin 11122 -> 0 bytes src/Doxyfile | 3 +- 5 files changed, 71 insertions(+), 48 deletions(-) delete mode 100644 src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf delete mode 100644 src/Bitmap_cubical_complex/doc/exampleBitmap.pdf (limited to 'src') diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index 3fd1c10a..9fc01a5d 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -927,3 +927,30 @@ misc{jplex_cite, year = "2009", note = "http://comptop.stanford.edu/programs/jplex/" } + +@book{kaczynski2004computational, + title={Computational Homology}, + author={Kaczynski, T. and Mischaikow, K. and Mrozek, M.}, + isbn={9780387408538}, + lccn={03061109}, + series={Applied Mathematical Sciences}, + url={https://books.google.fr/books?id=AShKtpi3GecC}, + year={2004}, + publisher={Springer New York} +} + +@ARTICLE{peikert2012topological, +year={2012}, +isbn={978-3-642-23174-2}, +booktitle={Topological Methods in Data Analysis and Visualization II}, +series={Mathematics and Visualization}, +editor={Peikert, Ronald and Hauser, Helwig and Carr, Hamish and Fuchs, Raphael}, +doi={10.1007/978-3-642-23175-9_7}, +title={Efficient Computation of Persistent Homology for Cubical Data}, +url={http://dx.doi.org/10.1007/978-3-642-23175-9_7}, +publisher={Springer Berlin Heidelberg}, +author={Wagner, Hubert and Chen, Chao and Vucini, Erald}, +pages={91-106}, +language={English} +} + diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index 6e821ce4..1a6310fb 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -38,70 +38,65 @@ namespace Cubical_complex *Cubical complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. * -* An \emph{elementary interval} is an interval of a form $[n,n+1]$, or $[n,n]$, for $n \in \mathcal{Z}$. The first one is called \emph{non-degenerated}, while the second one is \emph{degenerated} interval. A \emph{boundary of a elementary -*interval} is a chain $\partial [n,n+1] = [n+1,n+1]-[n,n]$ in case of non-degenerated elementary interval and $\partial [n,n] = 0$ in case of degenerated elementary interval. An \emph{elementary cube} $C$ is a -*product of elementary intervals, $C=I_1 \times \ldots \times I_n$. \emph{Embedding dimension} of a cube is n, the number of elementary intervals (degenerated or not) in the product. A \emph{dimension of a cube} $C=I_1 \times ... \times I_n$ is the -*number of non degenerated elementary intervals in the product. A \emph{boundary of a cube} $C=I_1 \times \ldots \times I_n$ is a chain obtained in the following way: -*\[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\] -*A \emph{cubical complex} $\mathcal{K}$ is a collection of cubes closed under operation of taking boundary (i.e. boundary of every cube from the collection is in the collection). A cube $C$ in cubical complex $\mathcal{K}$ is \emph{maximal} if it is not in -*a boundary of any other cube in $\mathcal{K}$. A \emph{support} of a cube $C$ is the set in $\mathbb{R}^n$ occupied by $C$ ($n$ is the embedding dimension of $C$). +* An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} \f$. The first one is called non-degenerated, while the second one is \a degenerated interval. A boundary of a elementary +*interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of non-degenerated elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerated elementary interval. An elementary cube \f$ C \f$ is a + +*product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$. Embedding dimension of a cube is n, the number of elementary intervals (degenerated or not) in the product. A dimension of a cube \f$C=I_1 \times ... \times I_n\f$ is the +*number of non degenerated elementary intervals in the product. A boundary of a cube \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained in the following way: +*\f[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\f] +*A cubical complex \f$\mathcal{K}\f$ is a collection of cubes closed under operation of taking boundary (i.e. boundary of every cube from the collection is in the collection). A cube \f$C\f$ in cubical complex \f$\mathcal{K}\f$ is maximal if it is not in +*a boundary of any other cube in \f$\mathcal{K}\f$. A \a support of a cube \f$C\f$ is the set in \f$\mathbb{R}^n\f$ occupied by \f$C\f$ (\f$n\f$ is the embedding dimension of \f$C\f$). * *Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may be a set of two elements). * -*For further details and theory of cubical complexes, please consult a book:\\ -*Computational homology, by Tomasz Kaczynski, Konstantin Mischaikow, and Marion Mrozek, Appl. Math. Sci., vol. 157, Springer-Verlag, New York, 2004 +*For further details and theory of cubical complexes, please consult \cite kaczynski2004computational . * -*as well as the paper: -*Efficient computation of persistent homology for cubical data by Hubert Wagner, Chao Chen, Erald Vuini (published in the proceedings of Workshop on Topology-based Methods in Data -*Analysis and Visualization) +*as well as the following paper \cite peikert2012topological . * -*\section{Data structure.} +*\section datastructure Data structure. * -*The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in $\mathbb{R}^n$. This extra -*assumption allows for a memory efficient way of storing cubical complexes in a form of so called bitmaps. Let $R = [b_1,e_1] \times \ldots \times [b_n,e_n]$, for $b_1,...b_n,e_1,...,e_n \in \mathbb{Z}$ -*, $b_i \leq d_i$ be the considered rectangular region and let $\mathcal{K}$ be a filtered cubical complex having the rectangle $R$ as its support. Note that the structure of the coordinate system gives a way -*a lexicographical ordering of cells of $\mathcal{K}$. This ordering is a base of the presented bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector -*of the values of filtration. This, together with dimension of $\mathcal{K}$ and the sizes of $\mathcal{K}$ in all directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube $C \in \mathcal{K}$. +*The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in \f$\mathbb{R}^n\f$. This extra +*assumption allows for a memory efficient way of storing cubical complexes in a form of so called bitmaps. Let \f$R = [b_1,e_1] \times \ldots \times [b_n,e_n]\f$, for \f$b_1,...b_n,e_1,...,e_n \in \mathbb{Z}\f$ +*, \f$b_i \leq d_i\f$ be the considered rectangular region and let \f$\mathcal{K}\f$ be a filtered cubical complex having the rectangle \f$R\f$ as its support. Note that the structure of the coordinate system gives a way +*a lexicographical ordering of cells of \f$\mathcal{K}\f$. This ordering is a base of the presented bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector +*of the values of filtration. This, together with dimension of \f$\mathcal{K}\f$ and the sizes of \f$\mathcal{K}\f$ in all directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube \f$C \in \mathcal{K}\f$. * -*\image html "bitmapAllCubes.pdf" "Cubical complex in $\mathbb{R}^2". +*\image html "bitmapAllCubes.png" "Cubical complex. * -*Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical complexes in $\mathbb{R}$. The number of all cubes in each direction is -*equal $2n+1$, where $n$ is the number of maximal cubes in the considered direction. Let us consider a cube at the position $k$ in the bitmap. Knowing the sizes of the bitmap, -*by a series of modulo operation, we can determine which elementary intervals are present in the product that gives the cube $C$. In a similar way, we can compute boundary +*Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical complexes in \f$\mathbb{R}\f$. The number of all cubes in each direction is +*equal \f$2n+1\f$, where \f$n\f$ is the number of maximal cubes in the considered direction. Let us consider a cube at the position \f$k\f$ in the bitmap. Knowing the sizes of the bitmap, +*by a series of modulo operation, we can determine which elementary intervals are present in the product that gives the cube \f$C\f$. In a similar way, we can compute boundary *and the coboundary of each cube. Further details can be found in the literature. * -*\section{Input Format.} +*\section inputformat Input Format. * *In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star filtration to all cubes. There are a number of constructors -*that can be used to construct cubical complex by users who want to use the code directly. They can be found in the \emph{Bitmap\_cubical\_complex} class. -*Currently one input from a text file is used. It uses a format used already in Perseus software $(http://www.sas.upenn.edu/~vnanda/perseus/)$ by Vidit Nanda. +*that can be used to construct cubical complex by users who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class. +*Currently one input from a text file is used. It uses a format used already in Perseus software (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. *Below we are providing a description of the format. * -*\begin{enumerate} -*\item The first line of the file is $d$, the embedding dimension of a complex. -*\item The next $d$ lines consist of positive numbers being the numbers of top dimensional cubes in the given direction. Let us call those numbers $n_1,\ldots,n_d$. -*\item Later there is a sequence of $n_1 \dot \ldots \dot n_d$ numbers in a lexicographical ordering. Those numbers are filtrations of top dimensional cubes. -*\end{enumerate} * -*\image html "exampleBitmap.pdf" "Example of a input data." +*\image html "exampleBitmap.png" "Example of a input data." * *The input file for the following complex is: -*\begin{verbatim} -*2 -*3 -*3 -*1 -*2 -*3 -*8 -*20 -*4 -*7 -*6 -*5 -*\end{verbatim} -* -* +*\verbatim +2 +3 +3 +1 +2 +3 +8 +20 +4 +7 +6 +5 +\endverbatim + +*/ +/** @} */ // end defgroup cubical_complex + *@}//end of the group } } diff --git a/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf deleted file mode 100644 index 694105e4..00000000 Binary files a/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf and /dev/null differ diff --git a/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf b/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf deleted file mode 100644 index ef930c0c..00000000 Binary files a/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf and /dev/null differ diff --git a/src/Doxyfile b/src/Doxyfile index faa0d3fe..7a21c254 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -834,7 +834,8 @@ EXAMPLE_RECURSIVE = NO IMAGE_PATH = doc/Skeleton_blocker/ \ doc/common/ \ - doc/Contraction/ + doc/Contraction/ \ + doc/Bitmap_cubical_complex # The INPUT_FILTER tag can be used to specify a program that doxygen should -- cgit v1.2.3 From 5eae3bbe5c06a3b601b885ea9f2561743f4aeb1a Mon Sep 17 00:00:00 2001 From: pdlotko Date: Tue, 22 Dec 2015 07:57:35 +0000 Subject: Changes according to Marc's comments from 18 December. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@947 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3afdd0423f3b36d8103360ef11fbb5f1c9a348a5 --- .../example/Random_bitmap_cubical_complex.cpp | 2 +- .../include/gudhi/Bitmap_cubical_complex.h | 90 +++--------- .../include/gudhi/Bitmap_cubical_complex/counter.h | 6 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 163 ++++++++------------- 4 files changed, 93 insertions(+), 168 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index 60cfc113..36c22344 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -85,7 +85,7 @@ The program will create random cubical complex of that sizes and compute persist stringstream ss; ss << "randomComplex_persistence"; - std::ofstream out((char*)ss.str().c_str()); + std::ofstream out(ss.str().c_str()); pcoh.output_diagram(out); out.close(); diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index b8887e71..c082caba 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -45,7 +45,6 @@ public: //*********************************************// //Typedefs and typenames //*********************************************// - friend class Simplex_handle; typedef size_t Simplex_key; typedef T Filtration_value; typedef Simplex_key Simplex_handle; @@ -83,7 +82,7 @@ public: * in the following directions and vector of element of a type T * with filtration on top dimensional cells. **/ - Bitmap_cubical_complex( std::vector& dimensions , std::vector& top_dimensional_cells ): + Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells ): Bitmap_cubical_complex_base(dimensions,top_dimensional_cells), key_associated_to_simplex(this->total_number_of_cells+1) { @@ -114,7 +113,7 @@ public: static Simplex_handle null_simplex() { if ( globalDbg ){cerr << "Simplex_handle null_simplex()\n";} - return std::numeric_limits::max(); + return std::numeric_limits::max(); } @@ -129,22 +128,22 @@ public: /** * Return dimension of a cell pointed by the Simplex_handle. **/ - inline unsigned dimension(const Simplex_handle& sh)const + inline unsigned dimension(Simplex_handle sh)const { if ( globalDbg ){cerr << "unsigned dimension(const Simplex_handle& sh)\n";} - if ( sh != std::numeric_limits::max() ) return this->get_dimension_of_a_cell( sh ); + if ( sh != std::numeric_limits::max() ) return this->get_dimension_of_a_cell( sh ); return -1; } /** * Return the filtration of a cell pointed by the Simplex_handle. **/ - T filtration(const Simplex_handle& sh) + T filtration(Simplex_handle sh) { if ( globalDbg ){cerr << "T filtration(const Simplex_handle& sh)\n";} //Returns the filtration value of a simplex. - if ( sh != std::numeric_limits::max() ) return this->data[sh]; - return std::numeric_limits::max(); + if ( sh != std::numeric_limits::max() ) return this->data[sh]; + return std::numeric_limits::max(); } /** @@ -153,16 +152,16 @@ public: static Simplex_key null_key() { if ( globalDbg ){cerr << "Simplex_key null_key()\n";} - return std::numeric_limits::max(); + return std::numeric_limits::max(); } /** * Return the key of a cube pointed by the Simplex_handle. **/ - Simplex_key key(const Simplex_handle& sh)const + Simplex_key key(Simplex_handle sh)const { if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} - if ( sh != std::numeric_limits::max() ) + if ( sh != std::numeric_limits::max() ) { return this->key_associated_to_simplex[sh]; } @@ -175,7 +174,7 @@ public: Simplex_handle simplex(Simplex_key key) { if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} - if ( key != std::numeric_limits::max() ) + if ( key != std::numeric_limits::max() ) { return this->simplex_associated_to_key[ key ]; } @@ -185,23 +184,10 @@ public: /** * Assign key to a cube pointed by the Simplex_handle **/ - void assign_key(Simplex_handle& sh, Simplex_key key) + void assign_key(Simplex_handle sh, Simplex_key key) { if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} - - - - - - - - -if ( key == std::numeric_limits::max() ) return;//TODO FAKE!!! CHEATING!!! - - - - - + if ( key == std::numeric_limits::max() ) return; this->key_associated_to_simplex[sh] = key; this->simplex_associated_to_key[key] = sh; } @@ -222,33 +208,9 @@ if ( key == std::numeric_limits::max() ) return;//TODO FAKE!!! CHEATING!!! /** * Boundary_simplex_range class provides ranges for boundary iterators. **/ - typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; - class Boundary_simplex_range - { - //Range giving access to the simplices in the boundary of a simplex. - //.begin() and .end() return type Boundary_simplex_iterator. - public: - typedef Boundary_simplex_iterator const_iterator; - Boundary_simplex_range(const Simplex_handle& sh , Bitmap_cubical_complex* CC_):sh(sh),CC(CC_) - { - this->boundary_elements = this->CC->get_boundary_of_a_cell( sh ); - } - Boundary_simplex_iterator begin() - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator begin\n";} - return this->boundary_elements.begin(); + typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; + typedef typename std::vector< Simplex_handle > Boundary_simplex_range; - } - Boundary_simplex_iterator end() - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator end()\n";} - return this->boundary_elements.end(); - } - private: - Simplex_handle sh; - Bitmap_cubical_complex* CC; - std::vector< Simplex_handle > boundary_elements; - }; /** @@ -341,13 +303,10 @@ if ( key == std::numeric_limits::max() ) return;//TODO FAKE!!! CHEATING!!! /** * boundary_simplex_range creates an object of a Boundary_simplex_range class * that provides ranges for the Boundary_simplex_iterator. - **/ - Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) - { - if ( globalDbg ){cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n";} - //Returns a range giving access to all simplices of the boundary of a simplex, - //i.e. the set of codimension 1 subsimplices of the Simplex. - return Boundary_simplex_range(sh,this); + **/ + Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) + { + return this->get_boundary_of_a_cell(sh); } /** @@ -513,13 +472,12 @@ void Bitmap_cubical_complex::initialize_simplex_associated_to_key() if ( globalDbg ) { cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; - } - std::vector data_of_elements_from_bitmap( this->data.size() ); - std::iota (std::begin(data_of_elements_from_bitmap), std::end(data_of_elements_from_bitmap), 0); - std::sort( data_of_elements_from_bitmap.begin() , - data_of_elements_from_bitmap.end() , + } + this->simplex_associated_to_key = std::vector( this->data.size() ); + std::iota (std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); + std::sort( simplex_associated_to_key.begin() , + simplex_associated_to_key.end() , is_before_in_filtration(this) ); - this->simplex_associated_to_key = data_of_elements_from_bitmap; } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h index 3a17b4a0..c13d96e1 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h @@ -51,7 +51,7 @@ public: * Constructor of a counter class. It takes only the parameter which is the end value of the counter. * The default beginning value is a vector of the same length as the endd, filled-in with zeros. **/ - counter(std::vector const& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} + counter(const std::vector& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} //counter(std::vector< int >& endd) //{ // for ( size_t i = 0 ; i != endd.size() ; ++i ) @@ -67,7 +67,7 @@ public: * Constructor of a counter class. It takes as the input beginn and end vector. * It assumes that begin vector is lexicographically below the end vector. **/ - counter(std::vector< unsigned >& beginn , std::vector< unsigned >& endd):begin(beginn),end(endd),current(endd.size(),0) + counter(const std::vector< unsigned >& beginn , const std::vector< unsigned >& endd):begin(beginn),end(endd),current(endd.size(),0) { if ( beginn.size() != endd.size() ) throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; @@ -112,7 +112,7 @@ public: * Its aim is to find an counter corresponding to the element the following * boundary element is identified with when periodic boundary conditions are imposed. **/ - std::vector< unsigned > find_opposite( std::vector< bool >& directionsForPeriodicBCond ) + std::vector< unsigned > find_opposite( const std::vector< bool >& directionsForPeriodicBCond ) { std::vector< unsigned > result; for ( size_t i = 0 ; i != this->current.size() ; ++i ) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 4e63b9c3..fdc8511c 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -44,19 +44,19 @@ namespace Cubical_complex /** - * This is a class implementing a basic bitmap data structure to store cubical complexes. + * This is a class implementing a basic bitmap data structure to store cubical complexes. * It implements only the most basic subroutines. - * The idea of the bitmap is the following. Our aim is to have a memory efficient - * data structure to store d-dimensional cubical complex + * The idea of the bitmap is the following. Our aim is to have a memory efficient + * data structure to store d-dimensional cubical complex * C being a cubical decomposition - * of a rectangular region of a space. This is achieved by storing C as a - * vector of bits (this is where the name 'bitmap' came from). + * of a rectangular region of a space. This is achieved by storing C as a + * vector of bits (this is where the name 'bitmap' came from). * Each cell is represented by a single - * bit (in case of black and white bitmaps, or by a single element of a type T - * (here T is a filtration type of a bitmap, typically a double). + * bit (in case of black and white bitmaps, or by a single element of a type T + * (here T is a filtration type of a bitmap, typically a double). * All the informations needed for homology and - * persistent homology computations (like dimension of a cell, boundary and - * coboundary elements of a cell, are then obtained from the + * persistent homology computations (like dimension of a cell, boundary and + * coboundary elements of a cell, are then obtained from the * position of the element in C. * The default filtration used in this implementation is the lower star filtration. */ @@ -65,49 +65,49 @@ class Bitmap_cubical_complex_base { public: /** - * There are a few constructors of a Bitmap_cubical_complex_base class. - * First one, that takes vector, creates an empty bitmap of a dimension equal + * There are a few constructors of a Bitmap_cubical_complex_base class. + * First one, that takes vector, creates an empty bitmap of a dimension equal * the number of elements in the * input vector and size in the i-th dimension equal the number in the position i-of the input vector. */ - Bitmap_cubical_complex_base( std::vector& sizes ); + Bitmap_cubical_complex_base( const std::vector& sizes ); /** - * The second constructor takes as a input a Perseus style file. For more details, - * please consult the documentations of + * The second constructor takes as a input a Perseus style file. For more details, + * please consult the documentations of * Perseus software as well as examples attached to this * implementation. **/ Bitmap_cubical_complex_base( const char* perseus_style_file ); /** - * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) + * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) * together with vector of filtration values of top dimensional cells. **/ - Bitmap_cubical_complex_base( std::vector& dimensions , const std::vector& top_dimensional_cells ); + Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells ); /** - * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell - * and get_cell_data are the basic + * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell + * and get_cell_data are the basic * functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a + * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a * non-negative integer, indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to + * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to * the positions of (co)boundary element of the input cell. */ inline std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; /** - * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, - * get_dimension_of_a_cell and get_cell_data are the basic + * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, + * get_dimension_of_a_cell and get_cell_data are the basic * functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. - * The input parameter of all of those function is a non-negative integer, + * value form a position of a cell in the structure of a bitmap. + * The input parameter of all of those function is a non-negative integer, * indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if - * non-negative integers pointing to the + * In the case of functions that compute (co)boundary, the output is a vector if + * non-negative integers pointing to the * positions of (co)boundary element of the input cell. **/ inline std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; /** - * In the case of get_dimension_of_a_cell function, the output is a non-negative integer + * In the case of get_dimension_of_a_cell function, the output is a non-negative integer * indicating the dimension of a cell. **/ inline unsigned get_dimension_of_a_cell( size_t cell )const; @@ -118,11 +118,11 @@ public: /** - * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. + * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. * Then, there are a few ways one can pick the filtration of lower dimensional - * cells. The most typical one is by so called lower star filtration. This function is always called by any + * cells. The most typical one is by so called lower star filtration. This function is always called by any * constructor which takes the top dimensional cells. If you use such a constructor, - * then there is no need to call this function. Call it only if you are putting the filtration + * then there is no need to call this function. Call it only if you are putting the filtration * of the cells by your own (for instance by using Top_dimensional_cells_iterator). **/ void impose_lower_star_filtration();//assume that top dimensional cells are already set. @@ -149,7 +149,7 @@ public: //ITERATORS /** - * Iterator through all cells in the complex (in order they appear in the structure -- i.e. + * Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ typedef typename std::vector< T >::iterator all_cells_iterator; @@ -174,7 +174,7 @@ public: } /** - * Iterator through top dimensional cells of the complex. The cells appear in order they are stored + * Iterator through top dimensional cells of the complex. The cells appear in order they are stored * in the structure (i.e. in lexicographical order) **/ class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > @@ -184,7 +184,7 @@ public: { this->counter = std::vector(b.dimension()); std::fill( this->counter.begin() , this->counter.end() , 0 ); - } + } Top_dimensional_cells_iterator operator++() { //first find first element of the counter that can be increased: @@ -298,7 +298,7 @@ protected: std::vector multipliers; std::vector data; size_t total_number_of_cells; - void set_up_containers( std::vector& sizes ) + void set_up_containers( const std::vector& sizes ) { unsigned multiplier = 1; for ( size_t i = 0 ; i != sizes.size() ; ++i ) @@ -315,7 +315,7 @@ protected: this->data = data; } - size_t compute_position_in_bitmap( std::vector< unsigned >& counter ) + size_t compute_position_in_bitmap( const std::vector< unsigned >& counter ) { size_t position = 0; for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) @@ -337,9 +337,9 @@ protected: return counter; } - std::vector< size_t > + std::vector< size_t > generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions - ( std::vector< bool >& directions_for_periodic_b_cond ); + ( const std::vector< bool >& directions_for_periodic_b_cond ); }; @@ -348,7 +348,7 @@ protected: template ostream& operator << ( ostream & out , const Bitmap_cubical_complex_base& b ) { - for ( typename Bitmap_cubical_complex_base::all_cells_const_iterator + for ( typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b.all_cells_const_begin() ; it != b.all_cells_const_end() ; ++it ) { out << *it << " "; @@ -359,14 +359,14 @@ ostream& operator << ( ostream & out , const Bitmap_cubical_complex_base& b ) template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base -( std::vector& sizes ) +( const std::vector& sizes ) { this->set_up_containers( sizes ); } template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base -( std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) +( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) { this->set_up_containers( sizes_in_following_directions ); @@ -377,7 +377,7 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base } if ( number_of_top_dimensional_elements != top_dimensional_cells.size() ) { - cerr << + cerr << "Error in constructor\ Bitmap_cubical_complex_base\ ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ @@ -432,10 +432,10 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus inFiltration >> filtrationLevel; if ( dbg ) { - cerr << "Cell of an index : " - << it.compute_index_in_bitmap() - << " and dimension: " - << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) << " get the value : " << filtrationLevel << endl; } *it = filtrationLevel; @@ -449,51 +449,18 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const { - bool bdg = false; - //first of all, we need to take the list of coordinates in which the cell has nonzero length. - //We do it by using modified version to compute dimension of a cell: - std::vector< unsigned > dimensions_in_which_cell_has_nonzero_length; - unsigned dimension = 0; + std::vector< size_t > boundary_elements; size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { unsigned position = cell1/multipliers[i-1]; if ( position%2 == 1 ) - { - dimensions_in_which_cell_has_nonzero_length.push_back(i-1); - dimension++; + { + boundary_elements.push_back( cell - multipliers[ i-1 ] ); + boundary_elements.push_back( cell + multipliers[ i-1 ] ); } cell1 = cell1%multipliers[i-1]; } - - if (bdg) - { - cerr << "dimensions_in_which_cell_has_nonzero_length : \n"; - for ( size_t i = 0 ; i != dimensions_in_which_cell_has_nonzero_length.size() ; ++i ) - { - cerr << dimensions_in_which_cell_has_nonzero_length[i] << endl; - } - getchar(); - } - - std::vector< size_t > boundary_elements( 2*dimensions_in_which_cell_has_nonzero_length.size() ); - if ( dimensions_in_which_cell_has_nonzero_length.size() == 0 )return boundary_elements; - for ( size_t i = 0 ; i != dimensions_in_which_cell_has_nonzero_length.size() ; ++i ) - { - //boundary_elements.push_back( cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); - //boundary_elements.push_back( cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); - boundary_elements[2*i] = cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ]; - boundary_elements[2*i+1] = cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ]; - - - - if (bdg) cerr << "multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " - << multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; - if (bdg) cerr << "cell - multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " - << cell - multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; - if (bdg) cerr << "cell + multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " - << cell + multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; - } return boundary_elements; } @@ -504,7 +471,7 @@ template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const { bool bdg = false; - //first of all, we need to take the list of coordinates in which the cell has nonzero length. + //first of all, we need to take the list of coordinates in which the cell has nonzero length. //We do it by using modified version to compute dimension of a cell: std::vector< unsigned > dimensions_in_which_cell_has_zero_length; unsigned dimension = 0; @@ -547,20 +514,20 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( cerr << "Dimension : " << i << endl; if (counter[dimensions_in_which_cell_has_zero_length[i]] == 0) { - cerr << "In dimension : " << i + cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; } - if ( counter[dimensions_in_which_cell_has_zero_length[i]] - == + if ( counter[dimensions_in_which_cell_has_zero_length[i]] + == 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) { - cerr << "In dimension : " << i + cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; } } - if ( (cell > multipliers[dimensions_in_which_cell_has_zero_length[i]]) + if ( (cell > multipliers[dimensions_in_which_cell_has_zero_length[i]]) && (counter[dimensions_in_which_cell_has_zero_length[i]] != 0) ) //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != 0 ) { @@ -570,13 +537,13 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( } coboundary_elements.push_back( cell - multipliers[dimensions_in_which_cell_has_zero_length[i]] ); } - if ( - (cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && - (counter[dimensions_in_which_cell_has_zero_length[i]] - != - 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]]) + if ( + (cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && + (counter[dimensions_in_which_cell_has_zero_length[i]] + != + 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]]) ) - //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != + //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != //2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) { coboundary_elements.push_back( cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] ); @@ -629,12 +596,12 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { bool dbg = false; - //this vector will be used to check which elements have already been taken care of + //this vector will be used to check which elements have already been taken care of //in imposing lower star filtration: std::vector is_this_cell_considered( this->data.size() , false ); std::vector indices_to_consider; - //we assume here that we already have a filtration on the top dimensional cells and + //we assume here that we already have a filtration on the top dimensional cells and //we have to extend it to lower ones. typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) @@ -699,7 +666,7 @@ bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , ch template std::vector< size_t > Bitmap_cubical_complex_base:: generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions -( std::vector< bool >& directions_for_periodic_b_cond ) +( const std::vector< bool >& directions_for_periodic_b_cond ) { bool dbg = false; if ( this->sizes.size() != directions_for_periodic_b_cond.size() ) @@ -758,4 +725,4 @@ generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions } -} \ No newline at end of file +} -- cgit v1.2.3 From 1884df27964e344ac0004964c633ba01d4a6ae29 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Sun, 27 Dec 2015 09:25:07 +0000 Subject: COrrestions suggested by Marc just before Chrismas. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@948 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b5391c6584d8042646fea5ca17e250fcfc3dd85f --- .../include/gudhi/Bitmap_cubical_complex.h | 6 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 121 +++++++++------------ 2 files changed, 55 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index c082caba..b324d272 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -278,7 +278,8 @@ public: //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. public: - typedef Filtration_simplex_iterator const_iterator; + typedef Filtration_simplex_iterator const_iterator; + typedef Filtration_simplex_iterator iterator; Filtration_simplex_range(Bitmap_cubical_complex* b):b(b){}; Filtration_simplex_iterator begin() { @@ -430,7 +431,8 @@ public: //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. public: - typedef Skeleton_simplex_iterator const_iterator; + typedef Skeleton_simplex_iterator const_iterator; + typedef Skeleton_simplex_iterator iterator; Skeleton_simplex_range(Bitmap_cubical_complex* b , unsigned dimension):b(b),dimension(dimension){}; Skeleton_simplex_iterator begin() { diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index fdc8511c..54d60325 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -183,7 +183,7 @@ public: Top_dimensional_cells_iterator( Bitmap_cubical_complex_base& b ):b(b) { this->counter = std::vector(b.dimension()); - std::fill( this->counter.begin() , this->counter.end() , 0 ); + //std::fill( this->counter.begin() , this->counter.end() , 0 ); } Top_dimensional_cells_iterator operator++() { @@ -327,7 +327,8 @@ protected: std::vector compute_counter_for_given_cell( size_t cell )const { - std::vector counter; + std::vector counter; + counter.reserve( this->sizes.size() ); for ( size_t dim = this->sizes.size() ; dim != 0 ; --dim ) { counter.push_back(cell/this->multipliers[dim-1]); @@ -380,11 +381,11 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base cerr << "Error in constructor\ Bitmap_cubical_complex_base\ - ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ + ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ Number of top dimensional elements that follow from sizes_in_following_directions vector is different\ than the size of top_dimensional_cells vector." << endl; throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions,\ - std::vector top_dimensional_cells )\ + std::vector top_dimensional_cells )\ . Number of top dimensional elements that follow from sizes_in_following_directions vector is different than the\ size of top_dimensional_cells vector."); } @@ -411,7 +412,8 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;} - std::vector sizes; + std::vector sizes; + sizes.reserve( dimensionOfData ); for ( size_t i = 0 ; i != dimensionOfData ; ++i ) { unsigned size_in_this_dimension; @@ -449,17 +451,21 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const { - std::vector< size_t > boundary_elements; + std::vector< size_t > boundary_elements; + + //Speed traded of for memory. Check if it is better in practice. + boundary_elements.reserve( this->dimension()*2 ); + size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { - unsigned position = cell1/multipliers[i-1]; + unsigned position = cell1/this->multipliers[i-1]; if ( position%2 == 1 ) { - boundary_elements.push_back( cell - multipliers[ i-1 ] ); - boundary_elements.push_back( cell + multipliers[ i-1 ] ); + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); } - cell1 = cell1%multipliers[i-1]; + cell1 = cell1%this->multipliers[i-1]; } return boundary_elements; } @@ -470,84 +476,48 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( si template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const { - bool bdg = false; //first of all, we need to take the list of coordinates in which the cell has nonzero length. //We do it by using modified version to compute dimension of a cell: - std::vector< unsigned > dimensions_in_which_cell_has_zero_length; + std::vector< unsigned > dimensions_in_which_cell_has_zero_length; + + //Speed traded of for memory. Check if it is better in practice. + dimensions_in_which_cell_has_zero_length.reserve( this->dimension()*2 ); + unsigned dimension = 0; size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { - unsigned position = cell1/multipliers[i-1]; + unsigned position = cell1/this->multipliers[i-1]; if ( position%2 == 0 ) { dimensions_in_which_cell_has_zero_length.push_back(i-1); dimension++; } - cell1 = cell1%multipliers[i-1]; + cell1 = cell1%this->multipliers[i-1]; } std::vector counter = this->compute_counter_for_given_cell( cell ); - //reverse(counter.begin() , counter.end()); + std::vector< size_t > coboundary_elements; + + //Speed traded of for memory. Check if it is better in practice. + coboundary_elements.reserve ( dimensions_in_which_cell_has_zero_length.size()*2 ); - if (bdg) - { - cerr << "dimensions_in_which_cell_has_zero_length : \n"; - for ( size_t i = 0 ; i != dimensions_in_which_cell_has_zero_length.size() ; ++i ) - { - cerr << dimensions_in_which_cell_has_zero_length[i] << endl; - } - cerr << "\n counter : " << endl; - for ( size_t i = 0 ; i != counter.size() ; ++i ) - { - cerr << counter[i] << endl; - } - getchar(); - } - - std::vector< size_t > coboundary_elements; if ( dimensions_in_which_cell_has_zero_length.size() == 0 )return coboundary_elements; for ( size_t i = 0 ; i != dimensions_in_which_cell_has_zero_length.size() ; ++i ) { - if ( bdg ) - { - cerr << "Dimension : " << i << endl; - if (counter[dimensions_in_which_cell_has_zero_length[i]] == 0) - { - cerr << "In dimension : " << i - << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; - } - if ( counter[dimensions_in_which_cell_has_zero_length[i]] - == - 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) - { - cerr << "In dimension : " << i - << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; - } - } - - - if ( (cell > multipliers[dimensions_in_which_cell_has_zero_length[i]]) + if ( (cell > this->multipliers[dimensions_in_which_cell_has_zero_length[i]]) && (counter[dimensions_in_which_cell_has_zero_length[i]] != 0) ) - //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != 0 ) { - if ( bdg ) - { - cerr << "Subtracting : " << cell - multipliers[dimensions_in_which_cell_has_zero_length[i]] << endl; - } - coboundary_elements.push_back( cell - multipliers[dimensions_in_which_cell_has_zero_length[i]] ); + coboundary_elements.push_back( cell - this->multipliers[dimensions_in_which_cell_has_zero_length[i]] ); } if ( - (cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && + (cell + this->multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && (counter[dimensions_in_which_cell_has_zero_length[i]] != 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]]) ) - //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != - //2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) { - coboundary_elements.push_back( cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] ); - if ( bdg )cerr << "Adding : " << cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] << endl; + coboundary_elements.push_back( cell + this->multipliers[dimensions_in_which_cell_has_zero_length[i]] ); } } return coboundary_elements; @@ -566,12 +536,12 @@ unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell( size_t cell )c unsigned dimension = 0; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { - unsigned position = cell/multipliers[i-1]; + unsigned position = cell/this->multipliers[i-1]; if (dbg)cerr << "i-1 :" << i-1 << endl; if (dbg)cerr << "cell : " << cell << endl; if (dbg)cerr << "position : " << position << endl; - if (dbg)cerr << "multipliers["<multipliers[i-1]; } return dimension; } @@ -599,8 +569,15 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() //this vector will be used to check which elements have already been taken care of //in imposing lower star filtration: std::vector is_this_cell_considered( this->data.size() , false ); - - std::vector indices_to_consider; + + size_t size_to_reserve = 1; + for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) + { + size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); + } + + std::vector indices_to_consider; + indices_to_consider.reserve( size_to_reserve ); //we assume here that we already have a filtration on the top dimensional cells and //we have to extend it to lower ones. typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); @@ -672,12 +649,17 @@ generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions if ( this->sizes.size() != directions_for_periodic_b_cond.size() ) throw "directions_for_periodic_b_cond vector size is different from the size of the bitmap. Program terminate \n"; - std::vector sizes( this->sizes.size() ); - for ( size_t i = 0 ; i != this->sizes.size() ; ++i )sizes[i] = 2*this->sizes[i]; + std::vector sizes; + sizes.reserve( this->sizes.size() ); + for ( size_t i = 0 ; i != this->sizes.size() ; ++i ) + { + sizes.push_back(2*this->sizes[i]); + } counter c( sizes ); - std::vector< size_t > result; + std::vector< size_t > result; + result.reserve( this->data.size() ); for ( size_t i = 0 ; i != this->data.size() ; ++i ) { @@ -685,7 +667,6 @@ generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions if ( !c.isFinal() ) { position = i; - //result.push_back( i ); } else { -- cgit v1.2.3 From 28d0848f733f0dc6a019b3328c80168d10e0a5ae Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 8 Jan 2016 13:26:27 +0000 Subject: Adding a first vesion of a functionality that provide periodic boundary codnitions. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@955 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ae60d98a6b2c15c2f7152663c3b05d40f0a56e86 --- .../example/Bitmap_cubical_complex.cpp | 146 ++++++++++----------- ...ubical_complex_periodic_boundary_conditions.cpp | 72 ++++++++++ src/Bitmap_cubical_complex/example/CMakeLists.txt | 3 + 3 files changed, 148 insertions(+), 73 deletions(-) create mode 100644 src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp (limited to 'src') diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index e56428b6..ed141ed9 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -1,73 +1,73 @@ - /* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Saclay (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 . - */ - - -//for persistence algorithm -#include -#include -#include - - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff -#include -#include - -using namespace std; - -int main( int argc , char** argv ) -{ - cout << "This program computes persistent homology, by using bitmap_cubical_complex class,\ - of cubical complexes provided in text files in Perseus style (the only numbered in \ -the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are\ - numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are\ - filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; - - int p = 2; - double min_persistence = 0; - - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a\ - Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex b( argv[1] ); - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology - pcoh.compute_persistent_cohomology( min_persistence ); - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out(ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 0; -} + /* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 + + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include + +using namespace std; + + +int main( int argc , char** argv ) +{ + cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbered in \ +the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex b( argv[1] ); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology( min_persistence ); + + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp new file mode 100644 index 00000000..fa60d4f3 --- /dev/null +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp @@ -0,0 +1,72 @@ + /* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 + + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include + +using namespace std; + +int main( int argc , char** argv ) +{ + cout << "This program computes persistent homology, by using Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in Perseus style (the only numbered in \ +the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex_periodic_boundary_conditions b( argv[1] ); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex_periodic_boundary_conditions, Field_Zp > pcoh(b,true); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology( min_persistence ); + + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index dd252a79..26796e9d 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -10,3 +10,6 @@ add_executable ( Random_bitmap_cubical_complex Random_bitmap_cubical_complex.cpp target_link_libraries(Random_bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap_cubical_complex 2 100 100) +add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubical_complex_periodic_boundary_conditions.cpp ) +target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) + -- cgit v1.2.3 From 0181c1f8c6122c50f991abea1ec8c4ec6bf392b4 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Wed, 13 Jan 2016 07:39:34 +0000 Subject: First version of a code changed so that it computes persistence of cubical complexes with or without periodic boundary conditions, but do not require duplication of code that link it to Gudhi persistence engine. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@961 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 506db0edd18818287fe110dcd04c15e369b28171 --- src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp | 4 ++-- .../Bitmap_cubical_complex_periodic_boundary_conditions.cpp | 11 +++++++---- .../example/Random_bitmap_cubical_complex.cpp | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index ed141ed9..39a55f24 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -54,11 +54,11 @@ lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for exam return 1; } - Bitmap_cubical_complex b( argv[1] ); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); pcoh.init_coefficients( p ); //initilizes the coefficient field for homology pcoh.compute_persistent_cohomology( min_persistence ); diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp index fa60d4f3..3d80c96d 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp @@ -22,10 +22,10 @@ #include -#include +#include +#include #include - using namespace Gudhi; using namespace Gudhi::Cubical_complex; using namespace Gudhi::persistent_cohomology; @@ -53,11 +53,14 @@ lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for exam return 1; } - Bitmap_cubical_complex_periodic_boundary_conditions b( argv[1] ); + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > b( argv[1] ); // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex_periodic_boundary_conditions, Field_Zp > pcoh(b,true); + persistent_cohomology::Persistent_cohomology< + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > + , Field_Zp + > pcoh(b,true); pcoh.init_coefficients( p ); //initilizes the coefficient field for homology pcoh.compute_persistent_cohomology( min_persistence ); diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index 36c22344..97347162 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -74,11 +74,11 @@ The program will create random cubical complex of that sizes and compute persist - Bitmap_cubical_complex b( sizes , data ); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( sizes , data ); // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); pcoh.init_coefficients( p ); //initilizes the coefficient field for homology pcoh.compute_persistent_cohomology( min_persistence ); -- cgit v1.2.3 From 12226486b5bf3f1d867f46aed5dc6d2c9727a03c Mon Sep 17 00:00:00 2001 From: pdlotko Date: Wed, 13 Jan 2016 08:41:26 +0000 Subject: Added tests for periodic boubnadry oconditions bitmap. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@962 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 49f059cdf9e0c8e20ff727564da13be14ebc2c04 --- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 270 +++++++++++++++++++++++- 1 file changed, 259 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index 183b856a..4235761f 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -35,7 +35,7 @@ BOOST_AUTO_TEST_CASE(check_dimension) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); BOOST_CHECK(increasing.dimension() == 2); } @@ -88,18 +88,18 @@ BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > hole(dimensions, oneDimensionalCycle); int i = 0; - for (Bitmap_cubical_complex::Top_dimensional_cells_iterator + for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { BOOST_CHECK(*it == expectedFiltrationValues2[i]); ++i; } i = 0; - for (Bitmap_cubical_complex::Top_dimensional_cells_iterator + for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { BOOST_CHECK(*it == expectedFiltrationValues1[i]); ++i; @@ -309,7 +309,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { @@ -334,7 +334,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector coboundaryElements; @@ -449,7 +449,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector dim; dim.push_back(0); @@ -523,7 +523,7 @@ BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector< unsigned > dim; dim.push_back(0); @@ -628,11 +628,259 @@ BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { fil.push_back(9); - Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range(); + Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Filtration_simplex_range range = increasing.filtration_simplex_range(); size_t position = 0; - for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { + for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { BOOST_CHECK(increasing.dimension(*it) == dim[position]); BOOST_CHECK(increasing.filtration(*it) == fil[position]); ++position; } } + + + +BOOST_AUTO_TEST_CASE(boudary_operator_2d_bitmap_with_periodic_bcond) { + std::vector< double > filtration; + filtration.push_back(0); + filtration.push_back(0); + filtration.push_back(0); + filtration.push_back(0); + + + std::vector dimensions; + dimensions.push_back(2); + dimensions.push_back(2); + + std::vector periodic_directions; + periodic_directions.push_back(true); + periodic_directions.push_back(true); + + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtration,periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + + std::vector boundary0; + std::vector boundary1; + boundary1.push_back(0); + boundary1.push_back(2); + std::vector boundary2; + std::vector boundary3; + boundary3.push_back(2); + boundary3.push_back(0); + std::vector boundary4; + boundary4.push_back(0); + boundary4.push_back(8); + std::vector boundary5; + boundary5.push_back(1); + boundary5.push_back(9); + boundary5.push_back(4); + boundary5.push_back(6); + std::vector boundary6; + boundary6.push_back(2); + boundary6.push_back(10); + std::vector boundary7; + boundary7.push_back(3); + boundary7.push_back(11); + boundary7.push_back(6); + boundary7.push_back(4); + std::vector boundary8; + std::vector boundary9; + boundary9.push_back(8); + boundary9.push_back(10); + std::vector boundary10; + std::vector boundary11; + boundary11.push_back(10); + boundary11.push_back(8); + std::vector boundary12; + boundary12.push_back(8); + boundary12.push_back(0); + std::vector boundary13; + boundary13.push_back(9); + boundary13.push_back(1); + boundary13.push_back(12); + boundary13.push_back(14); + std::vector boundary14; + boundary14.push_back(10); + boundary14.push_back(2); + std::vector boundary15; + boundary15.push_back(11); + boundary15.push_back(3); + boundary15.push_back(14); + boundary15.push_back(12); + + std::vector< std::vector > boundaries; + boundaries.push_back( boundary0 ); + boundaries.push_back( boundary1 ); + boundaries.push_back( boundary2 ); + boundaries.push_back( boundary3 ); + boundaries.push_back( boundary4 ); + boundaries.push_back( boundary5 ); + boundaries.push_back( boundary6 ); + boundaries.push_back( boundary7 ); + boundaries.push_back( boundary8 ); + boundaries.push_back( boundary9 ); + boundaries.push_back( boundary10 ); + boundaries.push_back( boundary11 ); + boundaries.push_back( boundary12 ); + boundaries.push_back( boundary13 ); + boundaries.push_back( boundary14 ); + boundaries.push_back( boundary15 ); + + for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) { + std::vector< size_t > bd = cmplx.get_boundary_of_a_cell(i); + for (size_t j = 0; j != bd.size(); ++j) { + BOOST_CHECK(boundaries[i][j] == bd[j]); + } + } +} + + + + + + +BOOST_AUTO_TEST_CASE(coboudary_operator_2d_bitmap_with_periodic_bcond) { + std::vector< double > filtration; + filtration.push_back(0); + filtration.push_back(0); + filtration.push_back(0); + filtration.push_back(0); + + + std::vector dimensions; + dimensions.push_back(2); + dimensions.push_back(2); + + std::vector periodic_directions; + periodic_directions.push_back(true); + periodic_directions.push_back(true); + + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtration,periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + + std::vector coboundary0; + coboundary0.push_back(4); + coboundary0.push_back(12); + coboundary0.push_back(1); + coboundary0.push_back(3); + std::vector coboundary1; + coboundary1.push_back(5); + coboundary1.push_back(13); + std::vector coboundary2; + coboundary2.push_back(6); + coboundary2.push_back(14); + coboundary2.push_back(1); + coboundary2.push_back(3); + std::vector coboundary3; + coboundary3.push_back(7); + coboundary3.push_back(15); + std::vector coboundary4; + coboundary4.push_back(5); + coboundary4.push_back(7); + std::vector coboundary5; + std::vector coboundary6; + coboundary6.push_back(5); + coboundary6.push_back(7); + std::vector coboundary7; + std::vector coboundary8; + coboundary8.push_back(4); + coboundary8.push_back(12); + coboundary8.push_back(9); + coboundary8.push_back(11); + std::vector coboundary9; + coboundary9.push_back(5); + coboundary9.push_back(13); + std::vector coboundary10; + coboundary10.push_back(6); + coboundary10.push_back(14); + coboundary10.push_back(9); + coboundary10.push_back(11); + std::vector coboundary11; + coboundary11.push_back(7); + coboundary11.push_back(15); + std::vector coboundary12; + coboundary12.push_back(13); + coboundary12.push_back(15); + std::vector coboundary13; + std::vector coboundary14; + coboundary14.push_back(13); + coboundary14.push_back(15); + std::vector coboundary15; + + std::vector< std::vector > coboundaries; + coboundaries.push_back( coboundary0 ); + coboundaries.push_back( coboundary1 ); + coboundaries.push_back( coboundary2 ); + coboundaries.push_back( coboundary3 ); + coboundaries.push_back( coboundary4 ); + coboundaries.push_back( coboundary5 ); + coboundaries.push_back( coboundary6 ); + coboundaries.push_back( coboundary7 ); + coboundaries.push_back( coboundary8 ); + coboundaries.push_back( coboundary9 ); + coboundaries.push_back( coboundary10 ); + coboundaries.push_back( coboundary11 ); + coboundaries.push_back( coboundary12 ); + coboundaries.push_back( coboundary13 ); + coboundaries.push_back( coboundary14 ); + coboundaries.push_back( coboundary15 ); + + for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) { + std::vector< size_t > cbd = cmplx.get_coboundary_of_a_cell(i); + for (size_t j = 0; j != cbd.size(); ++j) { + BOOST_CHECK(coboundaries[i][j] == cbd[j]); + } + } +} + + + + + + + +BOOST_AUTO_TEST_CASE(bitmap_2d_with_periodic_bcond_filtration) { + std::vector< double > filtrationOrg; + filtrationOrg.push_back(0); + filtrationOrg.push_back(1); + filtrationOrg.push_back(2); + filtrationOrg.push_back(3); + + + std::vector dimensions; + dimensions.push_back(2); + dimensions.push_back(2); + + std::vector periodic_directions; + periodic_directions.push_back(true); + periodic_directions.push_back(true); + + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtrationOrg,periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + + std::vector filtration; + filtration.push_back(0);//0 + filtration.push_back(0);//1 + filtration.push_back(0);//2 + filtration.push_back(1);//3 + filtration.push_back(0);//4 + filtration.push_back(0);//5 + filtration.push_back(0);//6 + filtration.push_back(1);//7 + filtration.push_back(0);//8 + filtration.push_back(0);//9 + filtration.push_back(0);//10 + filtration.push_back(1);//11 + filtration.push_back(2);//12 + filtration.push_back(2);//13 + filtration.push_back(2);//14 + filtration.push_back(3);//15 + + + for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) + { + BOOST_CHECK( filtration[i] == cmplx.get_cell_data(i) ); + } +} -- cgit v1.2.3 From 35143d2a24e7a601a4629a7cfe43ea6b8ea35f1a Mon Sep 17 00:00:00 2001 From: pdlotko Date: Wed, 13 Jan 2016 10:14:41 +0000 Subject: Adding documentation of the class. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@963 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6eec3b7216880475ed667660275c2314bf0feb0c --- .../include/gudhi/Bitmap_cubical_complex.h | 43 ++- .../include/gudhi/Bitmap_cubical_complex_base.h | 226 +++++++--------- ...cal_complex_periodic_boundary_conditions_base.h | 298 +++++++++++++++++++++ 3 files changed, 427 insertions(+), 140 deletions(-) create mode 100644 src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h (limited to 'src') diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index b324d272..63edcadd 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -23,7 +23,8 @@ #pragma once #include -#include "Bitmap_cubical_complex_base.h" +#include "Bitmap_cubical_complex_base.h" +#include "Bitmap_cubical_complex_periodic_boundary_conditions_base.h" @@ -38,15 +39,15 @@ const bool globalDbg = false; template class is_before_in_filtration; -template -class Bitmap_cubical_complex : public Bitmap_cubical_complex_base +template +class Bitmap_cubical_complex : public T { public: //*********************************************// //Typedefs and typenames //*********************************************// typedef size_t Simplex_key; - typedef T Filtration_value; + typedef typename T::filtration_type Filtration_value; typedef Simplex_key Simplex_handle; @@ -63,7 +64,7 @@ public: * Constructor form a Perseus-style file. **/ Bitmap_cubical_complex( const char* perseus_style_file ): - Bitmap_cubical_complex_base(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) + T(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) { if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) @@ -82,8 +83,28 @@ public: * in the following directions and vector of element of a type T * with filtration on top dimensional cells. **/ - Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells ): - Bitmap_cubical_complex_base(dimensions,top_dimensional_cells), + Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells ): + T(dimensions,top_dimensional_cells), + key_associated_to_simplex(this->total_number_of_cells+1) + { + for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) + { + this->key_associated_to_simplex[i] = i; + } + //we initialize this only once, in each constructor, when the bitmap is constructed. + //If the user decide to change some elements of the bitmap, then this procedure need + //to be called again. + this->initialize_simplex_associated_to_key(); + } + + /** + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells + * in the following directions and vector of element of a type T::filtration_type + * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. + * If the position i on this vector is true, then we impose periodic boundary conditions in this direction. + **/ + Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ): + T(dimensions,top_dimensional_cells,directions_in_which_periodic_b_cond_are_to_be_imposed), key_associated_to_simplex(this->total_number_of_cells+1) { for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) @@ -138,9 +159,9 @@ public: /** * Return the filtration of a cell pointed by the Simplex_handle. **/ - T filtration(Simplex_handle sh) + typename T::filtration_type filtration(Simplex_handle sh) { - if ( globalDbg ){cerr << "T filtration(const Simplex_handle& sh)\n";} + if ( globalDbg ){cerr << "T::filtration_type filtration(const Simplex_handle& sh)\n";} //Returns the filtration value of a simplex. if ( sh != std::numeric_limits::max() ) return this->data[sh]; return std::numeric_limits::max(); @@ -493,8 +514,8 @@ public: bool operator()( const typename Bitmap_cubical_complex::Simplex_handle sh1, const typename Bitmap_cubical_complex::Simplex_handle sh2) const { // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. - T fil1 = CC_->data[sh1]; - T fil2 = CC_->data[sh2]; + typename T::filtration_type fil1 = CC_->data[sh1]; + typename T::filtration_type fil2 = CC_->data[sh2]; if ( fil1 != fil2 ) { return fil1 < fil2; diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 54d60325..600f250d 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -63,7 +63,12 @@ namespace Cubical_complex template class Bitmap_cubical_complex_base { -public: +public: + typedef T filtration_type; + /** + *Default constructor + **/ + Bitmap_cubical_complex_base(){} /** * There are a few constructors of a Bitmap_cubical_complex_base class. * First one, that takes vector, creates an empty bitmap of a dimension equal @@ -93,7 +98,7 @@ public: * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to * the positions of (co)boundary element of the input cell. */ - inline std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; + virtual inline std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; /** * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, * get_dimension_of_a_cell and get_cell_data are the basic @@ -286,7 +291,12 @@ public: //****************************************************************************************************************// //****************************************************************************************************************// //****************************************************************************************************************// - + + +inline size_t number_cells()const +{ + return this->total_number_of_cells; +} //****************************************************************************************************************// //****************************************************************************************************************// @@ -305,14 +315,10 @@ protected: { this->sizes.push_back(sizes[i]); this->multipliers.push_back(multiplier); - //multiplier *= 2*(sizes[i]+1)+1; multiplier *= 2*sizes[i]+1; } - //std::reverse( this->sizes.begin() , this->sizes.end() ); - std::vector data(multiplier); - std::fill( data.begin() , data.end() , std::numeric_limits::max() ); + this->data = std::vector(multiplier, std::numeric_limits::max()); this->total_number_of_cells = multiplier; - this->data = data; } size_t compute_position_in_bitmap( const std::vector< unsigned >& counter ) @@ -336,11 +342,12 @@ protected: } std::reverse( counter.begin() , counter.end() ); return counter; - } - - std::vector< size_t > - generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions - ( const std::vector< bool >& directions_for_periodic_b_cond ); + } + void read_perseus_style_file( const char* perseus_style_file ); + void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); + Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); + Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); + Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ); }; @@ -364,11 +371,10 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base { this->set_up_containers( sizes ); } - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base -( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) -{ + +template +void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) +{ this->set_up_containers( sizes_in_following_directions ); size_t number_of_top_dimensional_elements = 1; @@ -397,13 +403,19 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base (*it) = top_dimensional_cells[index]; ++index; } - this->impose_lower_star_filtration(); -} - + this->impose_lower_star_filtration(); +} template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file ) +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base +( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) { + this->setup_bitmap_based_on_top_dimensional_cells_list( sizes_in_following_directions , top_dimensional_cells ); +} + +template +void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) +{ bool dbg = false; ifstream inFiltration, inIds; inFiltration.open( perseus_style_file ); @@ -418,7 +430,7 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus { unsigned size_in_this_dimension; inFiltration >> size_in_this_dimension; - size_in_this_dimension = abs(size_in_this_dimension); + size_in_this_dimension = size_in_this_dimension; sizes.push_back( size_in_this_dimension ); if (dbg){cerr << "size_in_this_dimension : " << size_in_this_dimension << endl;} } @@ -427,7 +439,6 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); it = this->top_dimensional_cells_begin(); - //TODO -- over here we also need to read id's of cell and put them to bitmapElement structure! while ( !inFiltration.eof() ) { double filtrationLevel; @@ -444,7 +455,37 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus ++it; } inFiltration.close(); - this->impose_lower_star_filtration(); + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->read_perseus_style_file( perseus_style_file ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file ) +{ + this->read_perseus_style_file( perseus_style_file ); } @@ -468,60 +509,39 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( si cell1 = cell1%this->multipliers[i-1]; } return boundary_elements; -} - - +} + + + template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const { - //first of all, we need to take the list of coordinates in which the cell has nonzero length. - //We do it by using modified version to compute dimension of a cell: - std::vector< unsigned > dimensions_in_which_cell_has_zero_length; - - //Speed traded of for memory. Check if it is better in practice. - dimensions_in_which_cell_has_zero_length.reserve( this->dimension()*2 ); - - unsigned dimension = 0; + std::vector counter = this->compute_counter_for_given_cell( cell ); + std::vector< size_t > coboundary_elements; size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { unsigned position = cell1/this->multipliers[i-1]; if ( position%2 == 0 ) { - dimensions_in_which_cell_has_zero_length.push_back(i-1); - dimension++; + if ( (cell > this->multipliers[i-1]) && (counter[i-1] != 0) ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + } + if ( + (cell + this->multipliers[i-1] < this->data.size()) && (counter[i-1] != 2*this->sizes[i-1]) ) + { + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } } cell1 = cell1%this->multipliers[i-1]; } - - std::vector counter = this->compute_counter_for_given_cell( cell ); - std::vector< size_t > coboundary_elements; + return coboundary_elements; +} - //Speed traded of for memory. Check if it is better in practice. - coboundary_elements.reserve ( dimensions_in_which_cell_has_zero_length.size()*2 ); - if ( dimensions_in_which_cell_has_zero_length.size() == 0 )return coboundary_elements; - for ( size_t i = 0 ; i != dimensions_in_which_cell_has_zero_length.size() ; ++i ) - { - if ( (cell > this->multipliers[dimensions_in_which_cell_has_zero_length[i]]) - && (counter[dimensions_in_which_cell_has_zero_length[i]] != 0) ) - { - coboundary_elements.push_back( cell - this->multipliers[dimensions_in_which_cell_has_zero_length[i]] ); - } - if ( - (cell + this->multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && - (counter[dimensions_in_which_cell_has_zero_length[i]] - != - 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]]) - ) - { - coboundary_elements.push_back( cell + this->multipliers[dimensions_in_which_cell_has_zero_length[i]] ); - } - } - return coboundary_elements; -} @@ -555,7 +575,7 @@ unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell( size_t cell )c } template -T& Bitmap_cubical_complex_base::get_cell_data( size_t cell ) +inline T& Bitmap_cubical_complex_base::get_cell_data( size_t cell ) { return this->data[cell]; } @@ -602,10 +622,21 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { std::vector bd = this->get_boundary_of_a_cell( indices_to_consider[i] ); for ( size_t boundaryIt = 0 ; boundaryIt != bd.size() ; ++boundaryIt ) - { + { + if ( dbg ) + { + cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; + getchar(); + + } if ( this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ] ) { - this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + if ( dbg ) + { + cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; + getchar(); + } } if ( is_this_cell_considered[ bd[boundaryIt] ] == false ) { @@ -640,69 +671,6 @@ bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , ch -template -std::vector< size_t > Bitmap_cubical_complex_base:: -generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions -( const std::vector< bool >& directions_for_periodic_b_cond ) -{ - bool dbg = false; - if ( this->sizes.size() != directions_for_periodic_b_cond.size() ) - throw "directions_for_periodic_b_cond vector size is different from the size of the bitmap. Program terminate \n"; - - std::vector sizes; - sizes.reserve( this->sizes.size() ); - for ( size_t i = 0 ; i != this->sizes.size() ; ++i ) - { - sizes.push_back(2*this->sizes[i]); - } - - counter c( sizes ); - - std::vector< size_t > result; - result.reserve( this->data.size() ); - - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - size_t position; - if ( !c.isFinal() ) - { - position = i; - } - else - { - std::vector< bool > finals = c.directions_of_finals(); - bool jump_in_position = false; - for ( size_t dir = 0 ; dir != finals.size() ; ++dir ) - { - if ( finals[dir] == false )continue; - if ( directions_for_periodic_b_cond[dir] ) - { - jump_in_position = true; - } - } - if ( jump_in_position == true ) - { - //in this case this guy is final, so we need to find 'the opposite one' - position = compute_position_in_bitmap( c.find_opposite( directions_for_periodic_b_cond ) ); - } - else - { - position = i; - } - } - result.push_back( position ); - if ( dbg ) - { - cerr << " position : " << position << endl; - cerr << c << endl; - getchar(); - } - - c.increment(); - } - - return result; -} } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h new file mode 100644 index 00000000..28911ea8 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -0,0 +1,298 @@ +#pragma once +#include +#include "Bitmap_cubical_complex_base.h" + +using namespace std; + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures +//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the +//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base + +template +class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base +{ +public: + //constructors that take an extra parameter: + Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); + + //overwritten methods co compute boundary and coboundary + virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; + std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + //inline unsigned get_dimension_of_a_cell( size_t cell )const; + +protected: + std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; + void set_up_containers( const std::vector& sizes ) + { + + unsigned multiplier = 1; + for ( size_t i = 0 ; i != sizes.size() ; ++i ) + { + this->sizes.push_back(sizes[i]); + this->multipliers.push_back(multiplier); + + if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) + { + multiplier *= 2*sizes[i]; + } + else + { + multiplier *= 2*sizes[i]+1; + } + } + //std::reverse( this->sizes.begin() , this->sizes.end() ); + this->data = std::vector(multiplier,std::numeric_limits::max()); + this->total_number_of_cells = multiplier; + } + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ); + void construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); +}; + +template +void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers( dimensions ); + + size_t i = 0; + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + *it = topDimensionalCells[i]; + ++i; + } + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) +{ + //for Perseus style files: + bool dbg = false; + + ifstream inFiltration; + inFiltration.open( perseus_style_file ); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); + + std::vector sizes; + sizes.reserve( dimensionOfData ); + for ( size_t i = 0 ; i != dimensionOfData ; ++i ) + { + int size_in_this_dimension; + inFiltration >> size_in_this_dimension; + if ( size_in_this_dimension < 0 ) + { + this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; + } + sizes.push_back( abs(size_in_this_dimension) ); + } + this->set_up_containers( sizes ); + + typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_begin(); + + while ( !inFiltration.eof() ) + { + double filtrationLevel; + inFiltration >> filtrationLevel; + if ( inFiltration.eof() )break; + + if ( dbg ) + { + cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + << " get the value : " << filtrationLevel << endl; + } + *it = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); + + /* + char* filename = (char*)perseus_style_file; + //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; + ifstream file( filename , ios::binary | ios::ate ); + unsigned realSizeOfFile = file.tellg(); + file.close(); + realSizeOfFile = realSizeOfFile/sizeof(T); + + unsigned w, h, d; + + w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); + + T* slice = new T[w*h*d]; + if (slice == NULL) + { + cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; + exit(EXIT_FAILURE); + } + + FILE* fp; + if ((fp=fopen( filename, "rb" )) == NULL ) + { + cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; + exit(1); + } + fread( slice,4,w*h*d,fp ); + fclose(fp); + std::vector data(slice,slice+w*h*d); + delete[] slice; + std::vector< unsigned > sizes; + sizes.push_back(w); + sizes.push_back(w); + sizes.push_back(w); + + std::vector< bool > directions; + directions.push_back( true ); + directions.push_back( true ); + directions.push_back( true ); + Bitmap_cubical_complex_periodic_boundary_conditions_base b( sizes, data, directions ); + *this = b; + */ +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ) +{ + std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + + + + + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + +//***********************Methods************************// + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const +{ + bool dbg = false; + if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} + + std::vector< size_t > boundary_elements; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/this->multipliers[i-1]; + //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. + + if ( position%2 == 1 ) + { + //if there are no periodic boundary conditions in this direction, we do not have to do anything. + if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { + //cerr << "A\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. + if ( position != 2*this->sizes[ i-1 ]-1 ) + { + //cerr << "B\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //cerr << "C\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} + } + } + } + cell1 = cell1%this->multipliers[i-1]; + } + return boundary_elements; +} + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell( size_t cell )const +{ + std::vector counter = this->compute_counter_for_given_cell( cell ); + std::vector< size_t > coboundary_elements; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/this->multipliers[i-1]; + //if the cell has zero length in this direction, then it will have cbd in this direction. + if ( position%2 == 0 ) + { + if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { + //no periodic boundary conditions in this direction + if ( (counter[i-1] != 0) && (cell > this->multipliers[i-1]) ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + } + if ( (counter[i-1] != 2*this->sizes[i-1]) && (cell + this->multipliers[i-1] < this->data.size()) ) + { + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } + } + else + { + //we want to have periodic boundary conditions in this direction + if ( counter[i-1] != 0 ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } + else + { + //in this case counter[i-1] == 0. + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); + } + } + } + + cell1 = cell1%this->multipliers[i-1]; + } + return coboundary_elements; +} + + + +}//Cubical_complex +}//namespace Gudhi -- cgit v1.2.3 From 7e40efa04f1cc528f49da82df1502af85feb78d1 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 13 Jan 2016 19:08:03 +0000 Subject: Added a test, moved the old test from example git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@964 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 5744fdd3d30735cebdbd7442f023585a70bf0fca --- src/Witness_complex/example/CMakeLists.txt | 3 - .../example/simple_witness_complex.cpp | 58 ------------------ .../gudhi/Landmark_choice_by_furthest_point.h | 71 +++++++++++----------- .../test/simple_witness_complex.cpp | 55 +++++++++++++++++ .../test/witness_complex_points.cpp | 64 +++++++++++++++++++ 5 files changed, 155 insertions(+), 96 deletions(-) delete mode 100644 src/Witness_complex/example/simple_witness_complex.cpp create mode 100644 src/Witness_complex/test/simple_witness_complex.cpp create mode 100644 src/Witness_complex/test/witness_complex_points.cpp (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 4f5e33d4..4473078a 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIWitnessComplex) # A simple example - add_executable ( simple_witness_complex simple_witness_complex.cpp ) - add_test(simple_witness_complex ${CMAKE_CURRENT_BINARY_DIR}/simple_witness_complex) - add_executable( witness_complex_from_file witness_complex_from_file.cpp ) add_test( witness_complex_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) diff --git a/src/Witness_complex/example/simple_witness_complex.cpp b/src/Witness_complex/example/simple_witness_complex.cpp deleted file mode 100644 index bcbf2362..00000000 --- a/src/Witness_complex/example/simple_witness_complex.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* 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): Vincent Rouvreau - * - * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (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 "gudhi/graph_simplicial_complex.h" -#include "gudhi/Simplex_tree.h" -#include "gudhi/Witness_complex.h" - -using namespace Gudhi; - -typedef std::vector< Vertex_handle > typeVectorVertex; -typedef Witness_complex> WitnessComplex; -//typedef std::pair typeSimplex; -//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; - -int main (int argc, char * const argv[]) -{ - Simplex_tree<> complex; - std::vector< typeVectorVertex > knn; - typeVectorVertex witness0 = {1,0,5,2,6,3,4}; knn.push_back(witness0 ); - typeVectorVertex witness1 = {2,6,4,5,0,1,3}; knn.push_back(witness1 ); - typeVectorVertex witness2 = {3,4,2,1,5,6,0}; knn.push_back(witness2 ); - typeVectorVertex witness3 = {4,2,1,3,5,6,0}; knn.push_back(witness3 ); - typeVectorVertex witness4 = {5,1,6,0,2,3,4}; knn.push_back(witness4 ); - typeVectorVertex witness5 = {6,0,5,2,1,3,4}; knn.push_back(witness5 ); - typeVectorVertex witness6 = {0,5,6,1,2,3,4}; knn.push_back(witness6 ); - typeVectorVertex witness7 = {2,6,4,5,3,1,0}; knn.push_back(witness7 ); - typeVectorVertex witness8 = {1,2,5,4,3,6,0}; knn.push_back(witness8 ); - typeVectorVertex witness9 = {3,4,0,6,5,1,2}; knn.push_back(witness9 ); - typeVectorVertex witness10 = {5,0,1,3,6,2,4}; knn.push_back(witness10); - typeVectorVertex witness11 = {5,6,1,0,2,3,4}; knn.push_back(witness11); - typeVectorVertex witness12 = {1,6,0,5,2,3,4}; knn.push_back(witness12); - WitnessComplex witnessComplex(knn, complex, 7, 7); - if (witnessComplex.is_witness_complex(knn, true)) - std::cout << "Witness complex is good\n"; - else - std::cout << "Witness complex is bad\n"; -} diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h index 0b196f18..ebee96ad 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -33,6 +33,9 @@ class Landmark_choice_by_furthest_point { +private: + typedef std::vector typeVectorVertex; + public: /** @@ -57,45 +60,43 @@ public: double curr_max_dist = 0; // used for defining the furhest point from L const double infty = std::numeric_limits::infinity(); // infinity (see next entry) std::vector< double > dist_to_L(nb_points,infty); // vector of current distances to L from points + int dim = points.begin()->size(); - //CHOICE OF THE FIRST LANDMARK - int rand_int = rand() % nb_points; - int curr_max_w = rand_int; //For testing purposes a pseudo-random number is used here - - for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) - { - //curr_max_w at this point is the next landmark - chosen_landmarks.push_back(curr_max_w); - for (auto v: knn) - v.push_back(current_number_of_landmarks); - int i = 0; - for (const auto& p: points) - { - // used to stock the distance from the current point to L - double curr_dist = euclidean_distance(p, points.begin() + chosen_landmarks[current_number_of_landmarks]); - wit_land_dist[i].push_back(curr_dist); - knn[i].push_back(current_number_of_landmarks); - if (curr_dist < dist_to_L[i]) - dist_to_L[i] = curr_dist; - int j = current_number_of_landmarks; - while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) - { - std::swap(knn[i][j], knn[i][j-1]); - std::swap(wit_land_dist[i][j-1], wit_land_dist[i][j-1]); - --j; - } - ++i; - } - curr_max_dist = 0; - for (auto dist: dist_to_L) { - if (dist > curr_max_dist) + int rand_int = rand() % nb_points; + int curr_max_w = rand_int; //For testing purposes a pseudo-random number is used here + + for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) + { + //curr_max_w at this point is the next landmark + chosen_landmarks.push_back(curr_max_w); + for (auto& v: knn) + v.push_back(current_number_of_landmarks); + unsigned i = 0; + for (auto& p: points) { - curr_max_dist = dist; - curr_max_w = i; + double curr_dist = euclidean_distance(p, *(points.begin() + chosen_landmarks[current_number_of_landmarks])); + wit_land_dist[i].push_back(curr_dist); + knn[i].push_back(current_number_of_landmarks); + if (curr_dist < dist_to_L[i]) + dist_to_L[i] = curr_dist; + int j = current_number_of_landmarks; + while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) + { + std::swap(knn[i][j], knn[i][j-1]); + std::swap(wit_land_dist[i][j-1], wit_land_dist[i][j-1]); + --j; + } + ++i; } + curr_max_dist = 0; + for (i = 0; i < dist_to_L.size(); i++) + if (dist_to_L[i] > curr_max_dist) + { + curr_max_dist = dist_to_L[i]; + curr_max_w = i; + } } - } - } + } }; diff --git a/src/Witness_complex/test/simple_witness_complex.cpp b/src/Witness_complex/test/simple_witness_complex.cpp new file mode 100644 index 00000000..c7d85a4d --- /dev/null +++ b/src/Witness_complex/test/simple_witness_complex.cpp @@ -0,0 +1,55 @@ +/* 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): Vincent Rouvreau + * + * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (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 "gudhi/graph_simplicial_complex.h" +#include "gudhi/Simplex_tree.h" +#include "gudhi/Witness_complex.h" + +using namespace Gudhi; + +typedef std::vector< Vertex_handle > typeVectorVertex; +typedef Witness_complex> WitnessComplex; +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + +int main (int argc, char * const argv[]) +{ + Simplex_tree<> complex; + std::vector< typeVectorVertex > knn; + typeVectorVertex witness0 = {1,0,5,2,6,3,4}; knn.push_back(witness0 ); + typeVectorVertex witness1 = {2,6,4,5,0,1,3}; knn.push_back(witness1 ); + typeVectorVertex witness2 = {3,4,2,1,5,6,0}; knn.push_back(witness2 ); + typeVectorVertex witness3 = {4,2,1,3,5,6,0}; knn.push_back(witness3 ); + typeVectorVertex witness4 = {5,1,6,0,2,3,4}; knn.push_back(witness4 ); + typeVectorVertex witness5 = {6,0,5,2,1,3,4}; knn.push_back(witness5 ); + typeVectorVertex witness6 = {0,5,6,1,2,3,4}; knn.push_back(witness6 ); + typeVectorVertex witness7 = {2,6,4,5,3,1,0}; knn.push_back(witness7 ); + typeVectorVertex witness8 = {1,2,5,4,3,6,0}; knn.push_back(witness8 ); + typeVectorVertex witness9 = {3,4,0,6,5,1,2}; knn.push_back(witness9 ); + typeVectorVertex witness10 = {5,0,1,3,6,2,4}; knn.push_back(witness10); + typeVectorVertex witness11 = {5,6,1,0,2,3,4}; knn.push_back(witness11); + typeVectorVertex witness12 = {1,6,0,5,2,3,4}; knn.push_back(witness12); + WitnessComplex witnessComplex(knn, complex, 7, 7); + assert(witnessComplex.is_witness_complex(knn, true)); +} diff --git a/src/Witness_complex/test/witness_complex_points.cpp b/src/Witness_complex/test/witness_complex_points.cpp new file mode 100644 index 00000000..f9680874 --- /dev/null +++ b/src/Witness_complex/test/witness_complex_points.cpp @@ -0,0 +1,64 @@ +/* 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): Vincent Rouvreau + * + * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (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 "gudhi/graph_simplicial_complex.h" +#include "gudhi/Simplex_tree.h" +#include "gudhi/Witness_complex.h" +#include "gudhi/Landmark_choice_by_random_point.h" +#include "gudhi/Landmark_choice_by_furthest_point.h" + + +using namespace Gudhi; + +typedef std::vector< Vertex_handle > typeVectorVertex; +typedef Witness_complex> WitnessComplex; +typedef std::vector Point; +//typedef std::pair typeSimplex; +//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; + +int main (int argc, char * const argv[]) +{ + std::vector< typeVectorVertex > knn; + std::vector< Point > points; + // Add grid points as witnesses + for (double i = 0; i < 10; i += 1.0) + for (double j = 0; j < 10; j += 1.0) + for (double k = 0; k < 10; k += 1.0) + points.push_back(Point({i,j,k})); + + bool b_print_output = true; + // First test: random choice + Simplex_tree<> complex1; + Landmark_choice_by_random_point lcrp(points, 100, knn); + assert(!knn.empty()); + WitnessComplex witnessComplex1(knn, complex1, 100, 3); + assert(witnessComplex1.is_witness_complex(knn, b_print_output)); + + // Second test: furthest choice + knn.clear(); + Simplex_tree<> complex2; + Landmark_choice_by_furthest_point lcfp(points, 100, knn); + WitnessComplex witnessComplex2(knn, complex2, 100, 3); + assert(witnessComplex2.is_witness_complex(knn, b_print_output)); +} -- cgit v1.2.3 From e9f91fe2787f41dd7791c055592ade552ce8df8a Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 13 Jan 2016 19:08:48 +0000 Subject: Oh, forgot the CMakeList in test folder git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@965 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d4a5301e5a48a27050bec9a43c35980a98d8837b --- src/Witness_complex/test/CMakeLists.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/Witness_complex/test/CMakeLists.txt (limited to 'src') diff --git a/src/Witness_complex/test/CMakeLists.txt b/src/Witness_complex/test/CMakeLists.txt new file mode 100644 index 00000000..a13fd94a --- /dev/null +++ b/src/Witness_complex/test/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHITestWitnessComplex) + +#if(NOT MSVC) +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") +# set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} --coverage") +# set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} --coverage") +#endif() + +add_executable ( simple_witness_complex simple_witness_complex.cpp ) +add_test(test ${CMAKE_CURRENT_BINARY_DIR}/simple_witness_complex) + +add_executable ( witness_complex_points witness_complex_points.cpp ) +add_test(test ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_points) + +#cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/Simplex_tree/include/gudhi") -- cgit v1.2.3 From 309699bf1dfd0582e671c730aee6bdf0f5031a1a Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 14 Jan 2016 10:37:35 +0000 Subject: Fixed the bug in Landmark_selection_by_furthest_point git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@966 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: cbda37a8c267348800fe04e82c58c4021744292e --- .../include/gudhi/Landmark_choice_by_furthest_point.h | 16 ++++++---------- src/Witness_complex/test/witness_complex_points.cpp | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h index ebee96ad..6ac59ae9 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -60,7 +60,7 @@ public: double curr_max_dist = 0; // used for defining the furhest point from L const double infty = std::numeric_limits::infinity(); // infinity (see next entry) std::vector< double > dist_to_L(nb_points,infty); // vector of current distances to L from points - int dim = points.begin()->size(); + //int dim = points.begin()->size(); int rand_int = rand() % nb_points; int curr_max_w = rand_int; //For testing purposes a pseudo-random number is used here @@ -69,8 +69,6 @@ public: { //curr_max_w at this point is the next landmark chosen_landmarks.push_back(curr_max_w); - for (auto& v: knn) - v.push_back(current_number_of_landmarks); unsigned i = 0; for (auto& p: points) { @@ -79,13 +77,6 @@ public: knn[i].push_back(current_number_of_landmarks); if (curr_dist < dist_to_L[i]) dist_to_L[i] = curr_dist; - int j = current_number_of_landmarks; - while (j > 0 && wit_land_dist[i][j-1] > wit_land_dist[i][j]) - { - std::swap(knn[i][j], knn[i][j-1]); - std::swap(wit_land_dist[i][j-1], wit_land_dist[i][j-1]); - --j; - } ++i; } curr_max_dist = 0; @@ -96,6 +87,11 @@ public: curr_max_w = i; } } + for (unsigned i = 0; i < points.size(); ++i) + std::sort(knn[i].begin(), + knn[i].end(), + [&wit_land_dist, i](int a, int b) + { return wit_land_dist[i][a] < wit_land_dist[i][b]; }); } }; diff --git a/src/Witness_complex/test/witness_complex_points.cpp b/src/Witness_complex/test/witness_complex_points.cpp index f9680874..a86bf493 100644 --- a/src/Witness_complex/test/witness_complex_points.cpp +++ b/src/Witness_complex/test/witness_complex_points.cpp @@ -47,7 +47,7 @@ int main (int argc, char * const argv[]) for (double k = 0; k < 10; k += 1.0) points.push_back(Point({i,j,k})); - bool b_print_output = true; + bool b_print_output = false; // First test: random choice Simplex_tree<> complex1; Landmark_choice_by_random_point lcrp(points, 100, knn); -- cgit v1.2.3 From f44d72644fc31bc863d0c81d0ae80630ebc506e5 Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 14 Jan 2016 16:17:51 +0000 Subject: Added example stuff git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@968 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a769b41f7d2d784a2740c149da08dac8124e3df9 --- src/Witness_complex/example/CMakeLists.txt | 11 +- src/Witness_complex/example/generators.h | 134 +++++++++++++++++++++ .../example/witness_complex_sphere.cpp | 126 +++++++++++++++++++ .../include/gudhi/Witness_complex.h | 2 +- .../test/simple_witness_complex.cpp | 5 +- .../test/witness_complex_points.cpp | 9 +- 6 files changed, 271 insertions(+), 16 deletions(-) create mode 100644 src/Witness_complex/example/generators.h create mode 100644 src/Witness_complex/example/witness_complex_sphere.cpp (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 4473078a..b5770ba6 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -4,9 +4,6 @@ project(GUDHIWitnessComplex) # A simple example add_executable( witness_complex_from_file witness_complex_from_file.cpp ) add_test( witness_complex_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) - - add_executable( witness_complex_bench witness_complex_bench.cpp ) - add_test( witness_complex_bench_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_bench ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) if(CGAL_FOUND) if (NOT CGAL_VERSION VERSION_LESS 4.6.0) @@ -21,12 +18,12 @@ if(CGAL_FOUND) message(STATUS "Eigen3 use file: ${EIGEN3_USE_FILE}.") include_directories (BEFORE "../../include") - add_executable ( witness_complex_bench2 witness_complex_bench2.cpp ) - target_link_libraries(witness_complex_bench2 ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_executable ( witness_complex_sphere witness_complex_sphere.cpp ) + target_link_libraries(witness_complex_sphere ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + message(WARNING "Eigen3 not found. Version 3.1.0 is required for witness_complex_sphere example.") endif() else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile witness_complex_sphere example. Version 4.6.0 is required.") endif () endif() diff --git a/src/Witness_complex/example/generators.h b/src/Witness_complex/example/generators.h new file mode 100644 index 00000000..0d42cda2 --- /dev/null +++ b/src/Witness_complex/example/generators.h @@ -0,0 +1,134 @@ +#ifndef GENERATORS_H +#define GENERATORS_H + +#include + +#include +#include + +typedef CGAL::Epick_d K; +typedef K::FT FT; +typedef K::Point_d Point_d; +typedef std::vector Point_Vector; +typedef CGAL::Random_points_in_cube_d Random_cube_iterator; +typedef CGAL::Random_points_in_ball_d Random_point_iterator; + +/** + * \brief Rock age method of reading off file + * + */ +inline void +off_reader_cust ( std::string file_name , std::vector & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + // Line OFF. No need in it + if (!getline(in_file, line)) + { + std::cerr << "No line OFF\n"; + return; + } + // Line with 3 numbers. No need + if (!getline(in_file, line)) + { + std::cerr << "No line with 3 numbers\n"; + return; + } + // Reading points + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + points.push_back(Point_d(point)); + } + in_file.close(); +} + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , Point_Vector & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + Point_d p(point.begin(), point.end()); + if (point.size() != 1) + points.push_back(p); + } + in_file.close(); +} + +/** \brief Generate points on a grid in a cube of side 2 + * having {+-1}^D as vertices and insert them in W. + * The grid has "width" points on each side. + * If torus is true then it is supposed that the cube represents + * a flat torus, hence the opposite borders are associated. + * The points on border in this case are not placed twice. + */ +void generate_points_grid(Point_Vector& W, int width, int D, bool torus) +{ + int nb_points = 1; + for (int i = 0; i < D; ++i) + nb_points *= width; + for (int i = 0; i < nb_points; ++i) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + if (torus) + point.push_back(-1+(2.0/(width-1))*(cell_i%width)); + else + point.push_back(-1+(2.0/width)*(cell_i%width)); + //attention: the bottom and the right are covered too! + cell_i /= width; + } + W.push_back(point); + } +} + +/** \brief Generate nbP points uniformly in a cube of side 2 + * having {+-1}^dim as its vertices and insert them in W. + */ +void generate_points_random_box(Point_Vector& W, int nbP, int dim) +{ + Random_cube_iterator rp(dim, 1.0); + for (int i = 0; i < nbP; i++) + { + W.push_back(*rp++); + } +} + +/** \brief Generate nbP points uniformly on a (dim-1)-sphere + * and insert them in W. + */ +void generate_points_sphere(Point_Vector& W, int nbP, int dim) +{ + CGAL::Random_points_on_sphere_d rp(dim,1); + for (int i = 0; i < nbP; i++) + W.push_back(*rp++); +} + + +#endif diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp new file mode 100644 index 00000000..1fa0fc42 --- /dev/null +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -0,0 +1,126 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 . + */ +#define BOOST_PARAMETER_MAX_ARITY 12 + + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "generators.h" + +using namespace Gudhi; + +typedef std::vector< Vertex_handle > typeVectorVertex; +//typedef std::vector< std::vector > Point_Vector; + +typedef Witness_complex< Simplex_tree<> > WitnessComplex; + +/** + * \brief Customized version of read_points + * which takes into account a possible nbP first line + * + */ +inline void +read_points_cust ( std::string file_name , std::vector< std::vector< double > > & points) +{ + std::ifstream in_file (file_name.c_str(),std::ios::in); + if(!in_file.is_open()) + { + std::cerr << "Unable to open file " << file_name << std::endl; + return; + } + std::string line; + double x; + while( getline ( in_file , line ) ) + { + std::vector< double > point; + std::istringstream iss( line ); + while(iss >> x) { point.push_back(x); } + if (point.size() != 1) + points.push_back(point); + } + in_file.close(); +} + +/** Write a gnuplot readable file. + * Data range is a random access range of pairs (arg, value) + */ +template < typename Data_range > +void write_data( Data_range & data, std::string filename ) +{ + std::ofstream ofs(filename, std::ofstream::out); + for (auto entry: data) + ofs << entry.first << ", " << entry.second << "\n"; + ofs.close(); +} + +int main (int argc, char * const argv[]) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] + << " path_to_point_file nbL \n"; + return 0; + } + + std::string file_name = argv[1]; + int nbL = atoi(argv[2]); + clock_t start, end; + + // Construct the Simplex Tree + Simplex_tree<> simplex_tree; + + std::vector< std::pair > l_time; + + // Read the point file + for (int nbP = 500; nbP < 10000; nbP += 500) + { + Point_Vector point_vector; + generate_points_sphere(point_vector, nbP, 4); + std::cout << "Successfully generated " << point_vector.size() << " points.\n"; + std::cout << "Ambient dimension is " << point_vector[0].size() << ".\n"; + + // Choose landmarks + start = clock(); + std::vector > knn; + Landmark_choice_by_random_point(point_vector, nbL, knn); + + // Compute witness complex + WitnessComplex(knn, simplex_tree, nbL, point_vector[0].size()); + end = clock(); + double time = (double)(end-start)/CLOCKS_PER_SEC; + std::cout << "Witness complex for " << nbL << " landmarks took " + << time << " s. \n"; + l_time.push_back(std::make_pair(nbP,time)); + } + write_data(l_time, "w_time.dat"); +} diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 791d0e45..915e445c 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -27,7 +27,7 @@ #include #include #include -#include "gudhi/distance_functions.h" +#include #include #include #include diff --git a/src/Witness_complex/test/simple_witness_complex.cpp b/src/Witness_complex/test/simple_witness_complex.cpp index c7d85a4d..ea38b5c0 100644 --- a/src/Witness_complex/test/simple_witness_complex.cpp +++ b/src/Witness_complex/test/simple_witness_complex.cpp @@ -22,9 +22,8 @@ #include #include -//#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Simplex_tree.h" -#include "gudhi/Witness_complex.h" +#include +#include using namespace Gudhi; diff --git a/src/Witness_complex/test/witness_complex_points.cpp b/src/Witness_complex/test/witness_complex_points.cpp index a86bf493..0a50101d 100644 --- a/src/Witness_complex/test/witness_complex_points.cpp +++ b/src/Witness_complex/test/witness_complex_points.cpp @@ -22,11 +22,10 @@ #include #include -//#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Simplex_tree.h" -#include "gudhi/Witness_complex.h" -#include "gudhi/Landmark_choice_by_random_point.h" -#include "gudhi/Landmark_choice_by_furthest_point.h" +#include +#include +#include +#include using namespace Gudhi; -- cgit v1.2.3 From 500d18704bc26166983ea005278bd187e2d3020c Mon Sep 17 00:00:00 2001 From: skachano Date: Fri, 15 Jan 2016 08:53:03 +0000 Subject: Fixed namespaces git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@970 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f71d4840583611d3829d8c4f1049e5d2b01ce71d --- src/Witness_complex/example/witness_complex_from_file.cpp | 1 + src/Witness_complex/example/witness_complex_sphere.cpp | 1 + .../include/gudhi/Landmark_choice_by_furthest_point.h | 8 ++++++++ .../include/gudhi/Landmark_choice_by_random_point.h | 8 ++++++++ src/Witness_complex/include/gudhi/Witness_complex.h | 9 +++++---- src/Witness_complex/test/simple_witness_complex.cpp | 5 ++--- src/Witness_complex/test/witness_complex_points.cpp | 1 + 7 files changed, 26 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index 6add4e0a..72caf30b 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -33,6 +33,7 @@ #include "gudhi/reader_utils.h" using namespace Gudhi; +using namespace Gudhi::witness_complex; typedef std::vector< Vertex_handle > typeVectorVertex; typedef std::vector< std::vector > Point_Vector; diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index 1fa0fc42..d73445b9 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -38,6 +38,7 @@ #include "generators.h" using namespace Gudhi; +using namespace Gudhi::witness_complex; typedef std::vector< Vertex_handle > typeVectorVertex; //typedef std::vector< std::vector > Point_Vector; diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h index 6ac59ae9..050286f2 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -23,6 +23,10 @@ #ifndef GUDHI_LANDMARK_CHOICE_BY_FURTHEST_POINT_H_ #define GUDHI_LANDMARK_CHOICE_BY_FURTHEST_POINT_H_ +namespace Gudhi { + +namespace witness_complex { + /** * \class Landmark_choice_by_furthest_point * \brief The class `Landmark_choice_by_furthest_point` allows to construct the matrix @@ -96,4 +100,8 @@ public: }; +} + +} + #endif diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h index fa822591..038deff6 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h @@ -23,6 +23,10 @@ #ifndef GUDHI_LANDMARK_CHOICE_BY_RANDOM_POINT_H_ #define GUDHI_LANDMARK_CHOICE_BY_RANDOM_POINT_H_ +namespace Gudhi { + +namespace witness_complex { + /** * \class Landmark_choice_by_random_point * \brief The class `Landmark_choice_by_random_point` allows to construct the matrix @@ -81,4 +85,8 @@ public: }; +} + +} + #endif diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 915e445c..8938e59d 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -44,7 +44,8 @@ namespace Gudhi { - + namespace witness_complex { + /** \class Witness_complex \brief Constructs the witness complex for the given set of witnesses and landmarks. @@ -256,13 +257,13 @@ namespace Gudhi { return false; } } - return true; // Arrive here if the not_witnessed check failed all the time + return true; } -}; //class Witness_complex - + }; //class Witness_complex + } //namespace witness_complex } // namespace Guhdi diff --git a/src/Witness_complex/test/simple_witness_complex.cpp b/src/Witness_complex/test/simple_witness_complex.cpp index ea38b5c0..86f5bcd1 100644 --- a/src/Witness_complex/test/simple_witness_complex.cpp +++ b/src/Witness_complex/test/simple_witness_complex.cpp @@ -26,11 +26,10 @@ #include using namespace Gudhi; +using namespace Gudhi::witness_complex; typedef std::vector< Vertex_handle > typeVectorVertex; typedef Witness_complex> WitnessComplex; -//typedef std::pair typeSimplex; -//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; int main (int argc, char * const argv[]) { @@ -50,5 +49,5 @@ int main (int argc, char * const argv[]) typeVectorVertex witness11 = {5,6,1,0,2,3,4}; knn.push_back(witness11); typeVectorVertex witness12 = {1,6,0,5,2,3,4}; knn.push_back(witness12); WitnessComplex witnessComplex(knn, complex, 7, 7); - assert(witnessComplex.is_witness_complex(knn, true)); + assert(witnessComplex.is_witness_complex(knn, false)); } diff --git a/src/Witness_complex/test/witness_complex_points.cpp b/src/Witness_complex/test/witness_complex_points.cpp index 0a50101d..e9fac9b8 100644 --- a/src/Witness_complex/test/witness_complex_points.cpp +++ b/src/Witness_complex/test/witness_complex_points.cpp @@ -29,6 +29,7 @@ using namespace Gudhi; +using namespace Gudhi::witness_complex; typedef std::vector< Vertex_handle > typeVectorVertex; typedef Witness_complex> WitnessComplex; -- cgit v1.2.3 From 377b59e5e7fa6a92bd21b0cb9b9b86e33632e4ed Mon Sep 17 00:00:00 2001 From: skachano Date: Fri, 15 Jan 2016 08:57:23 +0000 Subject: Removed relaxed_witness_complex_sphere from repository git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@971 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 886ea9c52839e6cb21872da5097a55037b027ca7 --- .../example/relaxed_witness_complex_sphere.cpp | 461 --------------------- 1 file changed, 461 deletions(-) delete mode 100644 src/Witness_complex/example/relaxed_witness_complex_sphere.cpp (limited to 'src') diff --git a/src/Witness_complex/example/relaxed_witness_complex_sphere.cpp b/src/Witness_complex/example/relaxed_witness_complex_sphere.cpp deleted file mode 100644 index 067321ce..00000000 --- a/src/Witness_complex/example/relaxed_witness_complex_sphere.cpp +++ /dev/null @@ -1,461 +0,0 @@ -/* 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): Siargey Kachanovich - * - * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (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 -#include -#include - -#include -#include -//#include - -//#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Relaxed_witness_complex.h" -#include "gudhi/reader_utils.h" -#include "gudhi/Collapse/Collapse.h" -//#include - -//#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -#include -#include -#include -#include - -using namespace Gudhi; -//using namespace boost::filesystem; - -typedef CGAL::Epick_d K; -typedef K::FT FT; -typedef K::Point_d Point_d; -typedef CGAL::Search_traits< - FT, Point_d, - typename K::Cartesian_const_iterator_d, - typename K::Construct_cartesian_const_iterator_d> Traits_base; -typedef CGAL::Euclidean_distance Euclidean_distance; - -typedef std::vector< Vertex_handle > typeVectorVertex; - -//typedef std::pair typeSimplex; -//typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool; - -typedef CGAL::Search_traits_adapter< - std::ptrdiff_t, Point_d*, Traits_base> STraits; -//typedef K TreeTraits; -//typedef CGAL::Distance_adapter Euclidean_adapter; -//typedef CGAL::Kd_tree Kd_tree; -typedef CGAL::Orthogonal_incremental_neighbor_search> Neighbor_search; -typedef Neighbor_search::Tree Tree; -typedef Neighbor_search::Distance Distance; -typedef Neighbor_search::iterator KNS_iterator; -typedef Neighbor_search::iterator KNS_range; -typedef boost::container::flat_map Point_etiquette_map; -typedef CGAL::Kd_tree Tree2; - -typedef CGAL::Fuzzy_sphere Fuzzy_sphere; - -typedef std::vector Point_Vector; - -//typedef K::Equal_d Equal_d; -typedef CGAL::Random_points_in_cube_d Random_cube_iterator; -typedef CGAL::Random_points_in_ball_d Random_point_iterator; - -bool toric=false; - -/** - * \brief Customized version of read_points - * which takes into account a possible nbP first line - * - */ -inline void -read_points_cust ( std::string file_name , Point_Vector & points) -{ - std::ifstream in_file (file_name.c_str(),std::ios::in); - if(!in_file.is_open()) - { - std::cerr << "Unable to open file " << file_name << std::endl; - return; - } - std::string line; - double x; - while( getline ( in_file , line ) ) - { - std::vector< double > point; - std::istringstream iss( line ); - while(iss >> x) { point.push_back(x); } - Point_d p(point.begin(), point.end()); - if (point.size() != 1) - points.push_back(p); - } - in_file.close(); -} - - -void generate_points_sphere(Point_Vector& W, int nbP, int dim) -{ - CGAL::Random_points_on_sphere_d rp(dim,1); - for (int i = 0; i < nbP; i++) - W.push_back(*rp++); -} - - -void write_wl( std::string file_name, std::vector< std::vector > & WL) -{ - std::ofstream ofs (file_name, std::ofstream::out); - for (auto w : WL) - { - for (auto l: w) - ofs << l << " "; - ofs << "\n"; - } - ofs.close(); -} - -void write_rl( std::string file_name, std::vector< std::vector ::iterator> > & rl) -{ - std::ofstream ofs (file_name, std::ofstream::out); - for (auto w : rl) - { - for (auto l: w) - ofs << *l << " "; - ofs << "\n"; - } - ofs.close(); -} - -std::vector convert_to_torus(std::vector< Point_d>& points) -{ - std::vector< Point_d > points_torus; - for (auto p: points) - { - FT theta = M_PI*p[0]; - FT phi = M_PI*p[1]; - std::vector p_torus; - p_torus.push_back((1+0.2*cos(theta))*cos(phi)); - p_torus.push_back((1+0.2*cos(theta))*sin(phi)); - p_torus.push_back(0.2*sin(theta)); - points_torus.push_back(Point_d(p_torus)); - } - return points_torus; -} - - -void write_points_torus( std::string file_name, std::vector< Point_d > & points) -{ - std::ofstream ofs (file_name, std::ofstream::out); - std::vector points_torus = convert_to_torus(points); - for (auto w : points_torus) - { - for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) - ofs << *it << " "; - ofs << "\n"; - } - ofs.close(); -} - - -void write_points( std::string file_name, std::vector< Point_d > & points) -{ - if (toric) write_points_torus(file_name, points); - else - { - std::ofstream ofs (file_name, std::ofstream::out); - for (auto w : points) - { - for (auto it = w.cartesian_begin(); it != w.cartesian_end(); ++it) - ofs << *it << " "; - ofs << "\n"; - } - ofs.close(); - } -} - - -void write_edges_torus(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) -{ - std::ofstream ofs (file_name, std::ofstream::out); - Point_Vector l_torus = convert_to_torus(landmarks); - for (auto u: witness_complex.complex_vertex_range()) - for (auto v: witness_complex.complex_vertex_range()) - { - typeVectorVertex edge = {u,v}; - if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) - { - for (auto it = l_torus[u].cartesian_begin(); it != l_torus[u].cartesian_end(); ++it) - ofs << *it << " "; - ofs << "\n"; - for (auto it = l_torus[v].cartesian_begin(); it != l_torus[v].cartesian_end(); ++it) - ofs << *it << " "; - ofs << "\n\n\n"; - } - } - ofs.close(); -} - -void write_edges(std::string file_name, Witness_complex<>& witness_complex, Point_Vector& landmarks) -{ - std::ofstream ofs (file_name, std::ofstream::out); - if (toric) write_edges_torus(file_name, witness_complex, landmarks); - else - { - for (auto u: witness_complex.complex_vertex_range()) - for (auto v: witness_complex.complex_vertex_range()) - { - typeVectorVertex edge = {u,v}; - if (u < v && witness_complex.find(edge) != witness_complex.null_simplex()) - { - for (auto it = landmarks[u].cartesian_begin(); it != landmarks[u].cartesian_end(); ++it) - ofs << *it << " "; - ofs << "\n"; - for (auto it = landmarks[v].cartesian_begin(); it != landmarks[v].cartesian_end(); ++it) - ofs << *it << " "; - ofs << "\n\n\n"; - } - } - ofs.close(); - } -} - - -/** Function that chooses landmarks from W and place it in the kd-tree L. - * Note: nbL hould be removed if the code moves to Witness_complex - */ -void landmark_choice(Point_Vector &W, int nbP, int nbL, Point_Vector& landmarks, std::vector& landmarks_ind) -{ - std::cout << "Enter landmark choice to kd tree\n"; - //std::vector landmarks; - int chosen_landmark; - //std::pair res = std::make_pair(L_i.begin(),false); - Point_d* p; - CGAL::Random rand; - for (int i = 0; i < nbL; i++) - { - // while (!res.second) - // { - do chosen_landmark = rand.get_int(0,nbP); - while (std::find(landmarks_ind.begin(), landmarks_ind.end(), chosen_landmark) != landmarks_ind.end()); - //rand++; - //std::cout << "Chose " << chosen_landmark << std::endl; - p = &W[chosen_landmark]; - //L_i.emplace(chosen_landmark,i); - // } - landmarks.push_back(*p); - landmarks_ind.push_back(chosen_landmark); - //std::cout << "Added landmark " << chosen_landmark << std::endl; - } - } - - -void landmarks_to_witness_complex(Point_Vector &W, Point_Vector& landmarks, std::vector& landmarks_ind, FT alpha) -{ - //********************Preface: origin point - unsigned D = W[0].size(); - std::vector orig_vector; - for (unsigned i = 0; i < D; i++) - orig_vector.push_back(0); - Point_d origin(orig_vector); - //Distance dist; - //dist.transformed_distance(0,1); - //******************** Constructing a WL matrix - int nbP = W.size(); - int nbL = landmarks.size(); - STraits traits(&(landmarks[0])); - Euclidean_distance ed; - std::vector< std::vector > WL(nbP); - std::vector< std::vector< typename std::vector::iterator > > ope_limits(nbP); - Tree L(boost::counting_iterator(0), - boost::counting_iterator(nbL), - typename Tree::Splitter(), - traits); - - std::cout << "Enter (D+1) nearest landmarks\n"; - //std::cout << "Size of the tree is " << L.size() << std::endl; - for (int i = 0; i < nbP; i++) - { - //std::cout << "Entered witness number " << i << std::endl; - Point_d& w = W[i]; - std::queue< typename std::vector::iterator > ope_queue; // queue of points at (1+epsilon) distance to current landmark - Neighbor_search search(L, w, FT(0), true, CGAL::Distance_adapter(&(landmarks[0]))); - Neighbor_search::iterator search_it = search.begin(); - - //Incremental search and filling WL - while (WL[i].size() < D) - WL[i].push_back((search_it++)->first); - FT dtow = ed.transformed_distance(w, landmarks[WL[i][D-1]]); - while (search_it->second < dtow + alpha) - WL[i].push_back((search_it++)->first); - - //Filling the (1+epsilon)-limits table - for (std::vector::iterator wl_it = WL[i].begin(); wl_it != WL[i].end(); ++wl_it) - { - ope_queue.push(wl_it); - FT d_to_curr_l = ed.transformed_distance(w, landmarks[*wl_it]); - //std::cout << "d_to_curr_l=" << d_to_curr_l << std::endl; - //std::cout << "d_to_front+alpha=" << d_to_curr_l << std::endl; - while (d_to_curr_l > alpha + ed.transformed_distance(w, landmarks[*(ope_queue.front())])) - { - ope_limits[i].push_back(wl_it); - ope_queue.pop(); - } - } - while (ope_queue.size() > 0) - { - ope_limits[i].push_back(WL[i].end()); - ope_queue.pop(); - } - //std::cout << "Safely constructed a point\n"; - ////Search D+1 nearest neighbours from the tree of landmarks L - /* - if (w[0]>0.95) - std::cout << i << std::endl; - */ - //K_neighbor_search search(L, w, D, FT(0), true, - // CGAL::Distance_adapter(&(landmarks[0])) ); - //std::cout << "Safely found nearest landmarks\n"; - /* - for(K_neighbor_search::iterator it = search.begin(); it != search.end(); ++it) - { - //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; - //Point_etiquette_map::iterator itm = L_i.find(it->first); - //assert(itm != L_i.end()); - //std::cout << "Entered KNN_it with point at distance " << it->second << "\n"; - WL[i].push_back(it->first); - //std::cout << "ITFIRST " << it->first << std::endl; - //std::cout << i << " " << it->first << ": " << it->second << std::endl; - } - */ - } - //std::cout << "\n"; - - //std::string out_file = "wl_result"; - write_wl("wl_result",WL); - write_rl("rl_result",ope_limits); - - //******************** Constructng a witness complex - std::cout << "Entered witness complex construction\n"; - Witness_complex<> witnessComplex; - witnessComplex.setNbL(nbL); - witnessComplex.relaxed_witness_complex(WL, ope_limits); - char buffer[100]; - int i = sprintf(buffer,"stree_result.txt"); - - if (i >= 0) - { - std::string out_file = (std::string)buffer; - std::ofstream ofs (out_file, std::ofstream::out); - witnessComplex.st_to_file(ofs); - ofs.close(); - } - write_edges("landmarks/edges", witnessComplex, landmarks); - std::cout << Distance().transformed_distance(Point_d(std::vector({0.1,0.1})), Point_d(std::vector({1.9,1.9}))) << std::endl; -} - - -int main (int argc, char * const argv[]) -{ - - if (argc != 5) - { - std::cerr << "Usage: " << argv[0] - << " nbP nbL dim alpha\n"; - return 0; - } - /* - boost::filesystem::path p; - for (; argc > 2; --argc, ++argv) - p /= argv[1]; - */ - - int nbP = atoi(argv[1]); - int nbL = atoi(argv[2]); - int dim = atoi(argv[3]); - double alpha = atof(argv[4]); - //clock_t start, end; - //Construct the Simplex Tree - Witness_complex<> witnessComplex; - - std::cout << "Let the carnage begin!\n"; - Point_Vector point_vector; - //read_points_cust(file_name, point_vector); - generate_points_sphere(point_vector, nbP, dim); - /* - for (auto &p: point_vector) - { - assert(std::count(point_vector.begin(),point_vector.end(),p) == 1); - } - */ - //std::cout << "Successfully read the points\n"; - //witnessComplex.setNbL(nbL); - Point_Vector L; - std::vector chosen_landmarks; - landmark_choice(point_vector, nbP, nbL, L, chosen_landmarks); - //start = clock(); - - write_points("landmarks/initial_pointset",point_vector); - write_points("landmarks/initial_landmarks",L); - - landmarks_to_witness_complex(point_vector, L, chosen_landmarks, alpha); - //end = clock(); - - /* - std::cout << "Landmark choice took " - << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; - start = clock(); - witnessComplex.witness_complex(WL); - // - end = clock(); - std::cout << "Howdy world! The process took " - << (double)(end-start)/CLOCKS_PER_SEC << " s. \n"; - */ - - /* - out_file = "output/"+file_name+"_"+argv[2]+".stree"; - std::ofstream ofs (out_file, std::ofstream::out); - witnessComplex.st_to_file(ofs); - ofs.close(); - - out_file = "output/"+file_name+"_"+argv[2]+".badlinks"; - std::ofstream ofs2(out_file, std::ofstream::out); - witnessComplex.write_bad_links(ofs2); - ofs2.close(); - */ -} -- cgit v1.2.3 From cccb605bb3beca6eeae7d7368a4c3cb48bda98c7 Mon Sep 17 00:00:00 2001 From: skachano Date: Fri, 15 Jan 2016 14:16:34 +0000 Subject: Added consts where needed git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@973 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 57ca40cd8dcda5125e4412c196862e14ff073744 --- .../include/gudhi/Landmark_choice_by_furthest_point.h | 2 +- .../include/gudhi/Landmark_choice_by_random_point.h | 4 +++- src/Witness_complex/include/gudhi/Witness_complex.h | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h index 050286f2..163975c9 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -51,7 +51,7 @@ public: template - Landmark_choice_by_furthest_point(Point_random_access_range &points, + Landmark_choice_by_furthest_point(Point_random_access_range const &points, int nbL, KNearestNeighbours &knn) { diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h index 038deff6..a54f3848 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h @@ -46,7 +46,9 @@ public: template - Landmark_choice_by_random_point(Point_random_access_range &points, int nbL, KNearestNeighbours &knn) + Landmark_choice_by_random_point(Point_random_access_range const &points, + int nbL, + KNearestNeighbours &knn) { int nbP = points.end() - points.begin(); std::set landmarks; diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 8938e59d..2b6a6ad5 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -105,7 +105,7 @@ namespace Gudhi { * Landmarks are supposed to be in [0,nbL_-1] */ template< typename KNearestNeighbours > - Witness_complex(KNearestNeighbours & knn, + Witness_complex(KNearestNeighbours const & knn, Simplicial_complex & sc_, int nbL_, int dim ): nbL(nbL_), sc(sc_) @@ -164,7 +164,7 @@ namespace Gudhi { * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id */ template - bool all_faces_in(KNearestNeighbours &knn, int witness_id, int k) + bool all_faces_in(KNearestNeighbours const &knn, int witness_id, int k) { //std::cout << "All face in with the landmark " << inserted_vertex << std::endl; std::vector< Vertex_handle > facet; @@ -188,7 +188,7 @@ namespace Gudhi { } template - void print_vector(std::vector v) + void print_vector(const std::vector v) { std::cout << "["; if (!v.empty()) @@ -211,7 +211,7 @@ namespace Gudhi { * \remark Added for debugging purposes. */ template< class KNearestNeighbors > - bool is_witness_complex(KNearestNeighbors & knn, bool print_output) + bool is_witness_complex(KNearestNeighbors const & knn, bool print_output) { //bool final_result = true; for (Simplex_handle sh: sc.complex_simplex_range()) -- cgit v1.2.3 From c0ad466a28bd3cc0ac88c0bbd49fc2e0a711afe9 Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 19 Jan 2016 16:33:41 +0000 Subject: Added a concept for Simplicial_complex, also added to doc about knn git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@979 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 7d0a98369571ba5fc40196f41e74dd9d54b094ec --- src/CMakeLists.txt | 6 +++--- .../include/gudhi/Witness_complex.h | 23 +++++++++++++++------- 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5e79e0b5..4598bc19 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -52,10 +52,10 @@ else() add_subdirectory(example/Persistent_cohomology) add_subdirectory(example/Skeleton_blocker) add_subdirectory(example/Contraction) - add_subdirectory(example/Hasse_complex) - add_subdirectort(example/Witness_complex) + # add_subdirectory(example/Hasse_complex) + add_subdirectory(example/Witness_complex) # add_subdirectory(example/Alpha_shapes) - add_subdirectory(example/Bottleneck) + # add_subdirectory(example/Bottleneck) # data points generator add_subdirectory(data/points/generator) diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 2b6a6ad5..90b2e094 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -75,7 +75,7 @@ namespace Gudhi { typedef std::vector< double > Point_t; typedef std::vector< Point_t > Point_Vector; - typedef typename Simplicial_complex::Filtration_value Filtration_value; + //typedef typename Simplicial_complex::Filtration_value Filtration_value; typedef std::vector< Vertex_handle > typeVectorVertex; typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; typedef std::pair< Simplex_handle, bool > typePairSimplexBool; @@ -96,16 +96,25 @@ namespace Gudhi { */ //@{ + + // Witness_range> /** * \brief Iterative construction of the witness complex. * \details The witness complex is written in sc_ basing on a matrix knn of * nearest neighbours of the form {witnesses}x{landmarks}. - * Parameter dim serves as the limit for the number of closest landmarks to consider. + * + * The type KNearestNeighbors can be seen as + * Witness_range>, where + * Witness_range and Closest_landmark_range are random access ranges. + * + * Constructor takes into account at most (dim+1) + * first landmarks from each landmark range to construct simplices. + * * Landmarks are supposed to be in [0,nbL_-1] */ - template< typename KNearestNeighbours > - Witness_complex(KNearestNeighbours const & knn, + template< typename KNearestNeighbors > + Witness_complex(KNearestNeighbors const & knn, Simplicial_complex & sc_, int nbL_, int dim ): nbL(nbL_), sc(sc_) @@ -125,7 +134,7 @@ namespace Gudhi { // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore counter++; vv = {i}; - returnValue = sc.insert_simplex(vv, Filtration_value(0.0)); + returnValue = sc.insert_simplex(vv); /* TODO Error if not inserted : normally no need here though*/ } int k=1; /* current dimension in iterative construction */ @@ -163,8 +172,8 @@ namespace Gudhi { * by witness witness_id are already in the complex. * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id */ - template - bool all_faces_in(KNearestNeighbours const &knn, int witness_id, int k) + template + bool all_faces_in(KNearestNeighbors const &knn, int witness_id, int k) { //std::cout << "All face in with the landmark " << inserted_vertex << std::endl; std::vector< Vertex_handle > facet; -- cgit v1.2.3 From e8afd1278aac5b5d76c5171092dca5954961431a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 20 Jan 2016 08:44:44 +0000 Subject: Cmake witness fix for cmake in a build directory and 'make test' to work. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@980 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b3e08e5d5c04c4bc5fbc8a120332e2578cbbe586 --- src/Witness_complex/example/CMakeLists.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index b5770ba6..fa6dd062 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -3,13 +3,27 @@ project(GUDHIWitnessComplex) # A simple example add_executable( witness_complex_from_file witness_complex_from_file.cpp ) - add_test( witness_complex_from_bunny &{CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) + add_test( witness_complex_from_bunny ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 100) if(CGAL_FOUND) if (NOT CGAL_VERSION VERSION_LESS 4.6.0) message(STATUS "CGAL version: ${CGAL_VERSION}.") include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + # - End of workaround find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) -- cgit v1.2.3 From 9bb012812fe7789fe5cc8cb5cd0aa4212e0af221 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 20 Jan 2016 10:34:31 +0000 Subject: Added the forgotten concept, added asserts nbP >= nbL, some header_defines git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@981 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d7c27be6bb66c79cf73971a80659079b1c8b12e5 --- src/Witness_complex/concept/Simplicial_complex.h | 83 ++++++++++++++++++++++ .../gudhi/Landmark_choice_by_furthest_point.h | 5 +- .../gudhi/Landmark_choice_by_random_point.h | 5 +- .../include/gudhi/Witness_complex.h | 4 +- .../include/gudhi/Witness_complex_doc.h | 4 +- 5 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 src/Witness_complex/concept/Simplicial_complex.h (limited to 'src') diff --git a/src/Witness_complex/concept/Simplicial_complex.h b/src/Witness_complex/concept/Simplicial_complex.h new file mode 100644 index 00000000..6b0df212 --- /dev/null +++ b/src/Witness_complex/concept/Simplicial_complex.h @@ -0,0 +1,83 @@ + /* 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): Siargey Kachanovich + * + * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (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 . + */ + +/** \brief The concept Simplicial_Complex describes the requirements + * for a type to implement a simplicial complex, + * used for example to build a 'Witness_complex'. + */ +struct Simplicial_complex +{ +/** Handle to specify a simplex. */ + typedef unspecified Simplex_handle; +/** Handle to specify a vertex. Must be a non-negative integer. */ + typedef unspecified Vertex_handle; + +/** Returns a Simplex_hanlde that is different from all simplex handles + * of the simplices. */ + Simplex_handle null_simplex(); +/** \brief Returns the number of simplices in the complex. + * + * Does not count the empty simplex. */ + size_t num_simplices(); + +/** \brief Iterator over the simplices of the complex, + * in an arbitrary order. + * + * 'value_type' must be 'Simplex_handle'.*/ +typedef unspecified Complex_simplex_iterator; +typedef unspecified Complex_simplex_range; + +/** +* \brief Returns a range over all the simplices of a +* complex. +*/ +Complex_simplex_range complex_simplex_range(); + +/** \brief Iterator over vertices of a simplex. + * + * 'value type' must be 'Vertex_handle'.*/ + typedef unspecified Simplex_vertex_range; + +/** \brief Returns a range over vertices of a given + * simplex. */ + Simplex_vertex_range simplex_vertex_range(Simplex_handle const & simplex); + +/** \brief Return type of an insertion of a simplex + */ + typedef unspecified Insertion_result_type; + +/** \brief Input range of vertices. + * 'value_type' must be 'Vertex_handle'. */ + typedef unspecified Input_vertex_range; + +/** \brief Inserts a simplex with vertices from a given range + * 'vertex_range' in the simplicial complex. + * */ + Insertion_result_type insert_simplex(Input_vertex_range const & vertex_range); + +/** \brief Finds a simplex with vertices given by a range + * + * If a simplex exists, its Simplex_handle is returned. + * Otherwise null_simplex() is returned. */ + Simplex_handle find(Input_vertex_range const & vertex_range); + +}; diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h index 163975c9..8dfec99c 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef GUDHI_LANDMARK_CHOICE_BY_FURTHEST_POINT_H_ -#define GUDHI_LANDMARK_CHOICE_BY_FURTHEST_POINT_H_ +#ifndef LANDMARK_CHOICE_BY_FURTHEST_POINT_H_ +#define LANDMARK_CHOICE_BY_FURTHEST_POINT_H_ namespace Gudhi { @@ -56,6 +56,7 @@ public: KNearestNeighbours &knn) { int nb_points = points.end() - points.begin(); + assert(nb_points >= nbL); std::vector> wit_land_dist(nb_points, std::vector()); // distance matrix witness x landmarks typeVectorVertex chosen_landmarks; // landmark list diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h index a54f3848..3f8a8d32 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef GUDHI_LANDMARK_CHOICE_BY_RANDOM_POINT_H_ -#define GUDHI_LANDMARK_CHOICE_BY_RANDOM_POINT_H_ +#ifndef LANDMARK_CHOICE_BY_RANDOM_POINT_H_ +#define LANDMARK_CHOICE_BY_RANDOM_POINT_H_ namespace Gudhi { @@ -51,6 +51,7 @@ public: KNearestNeighbours &knn) { int nbP = points.end() - points.begin(); + assert(nbP >= nbL); std::set landmarks; int current_number_of_landmarks=0; // counter for landmarks diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 90b2e094..819a0583 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef GUDHI_WITNESS_COMPLEX_H_ -#define GUDHI_WITNESS_COMPLEX_H_ +#ifndef WITNESS_COMPLEX_H_ +#define WITNESS_COMPLEX_H_ #include #include diff --git a/src/Witness_complex/include/gudhi/Witness_complex_doc.h b/src/Witness_complex/include/gudhi/Witness_complex_doc.h index 71c8776b..dbe9e7ce 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex_doc.h +++ b/src/Witness_complex/include/gudhi/Witness_complex_doc.h @@ -1,5 +1,5 @@ -#ifndef WITNESS_COMPLEX_DOC_ -#define WITNESS_COMPLEX_DOC_ +#ifndef WITNESS_COMPLEX_DOC_H_ +#define WITNESS_COMPLEX_DOC_H_ /** \defgroup witness_complex Witness complex -- cgit v1.2.3 From d13a8867ca368b1f56be3ba151d2042728fb4754 Mon Sep 17 00:00:00 2001 From: skachano Date: Wed, 20 Jan 2016 10:43:59 +0000 Subject: Almost all Vincent's remarks git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@982 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 32564e3521e0807e26bd2c07d682751a3d47e6da --- .../example/witness_complex_sphere.cpp | 34 ++-------------------- .../test/simple_witness_complex.cpp | 4 +-- .../test/witness_complex_points.cpp | 4 +-- 3 files changed, 7 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index d73445b9..9dc458d4 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -41,36 +41,9 @@ using namespace Gudhi; using namespace Gudhi::witness_complex; typedef std::vector< Vertex_handle > typeVectorVertex; -//typedef std::vector< std::vector > Point_Vector; typedef Witness_complex< Simplex_tree<> > WitnessComplex; -/** - * \brief Customized version of read_points - * which takes into account a possible nbP first line - * - */ -inline void -read_points_cust ( std::string file_name , std::vector< std::vector< double > > & points) -{ - std::ifstream in_file (file_name.c_str(),std::ios::in); - if(!in_file.is_open()) - { - std::cerr << "Unable to open file " << file_name << std::endl; - return; - } - std::string line; - double x; - while( getline ( in_file , line ) ) - { - std::vector< double > point; - std::istringstream iss( line ); - while(iss >> x) { point.push_back(x); } - if (point.size() != 1) - points.push_back(point); - } - in_file.close(); -} /** Write a gnuplot readable file. * Data range is a random access range of pairs (arg, value) @@ -86,15 +59,14 @@ void write_data( Data_range & data, std::string filename ) int main (int argc, char * const argv[]) { - if (argc != 3) + if (argc != 2) { std::cerr << "Usage: " << argv[0] - << " path_to_point_file nbL \n"; + << " nbL \n"; return 0; } - std::string file_name = argv[1]; - int nbL = atoi(argv[2]); + int nbL = atoi(argv[1]); clock_t start, end; // Construct the Simplex Tree diff --git a/src/Witness_complex/test/simple_witness_complex.cpp b/src/Witness_complex/test/simple_witness_complex.cpp index 86f5bcd1..7735ca6f 100644 --- a/src/Witness_complex/test/simple_witness_complex.cpp +++ b/src/Witness_complex/test/simple_witness_complex.cpp @@ -2,9 +2,9 @@ * (Geometric Understanding in Higher Dimensions) is a generic C++ * library for computational topology. * - * Author(s): Vincent Rouvreau + * Author(s): Siargey Kachanovich * - * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France) + * Copyright (C) 2016 INRIA Sophia Antipolis-Méditerranée (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 diff --git a/src/Witness_complex/test/witness_complex_points.cpp b/src/Witness_complex/test/witness_complex_points.cpp index e9fac9b8..3850bd82 100644 --- a/src/Witness_complex/test/witness_complex_points.cpp +++ b/src/Witness_complex/test/witness_complex_points.cpp @@ -2,9 +2,9 @@ * (Geometric Understanding in Higher Dimensions) is a generic C++ * library for computational topology. * - * Author(s): Vincent Rouvreau + * Author(s): Siargey Kachanovich * - * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France) + * Copyright (C) 2016 INRIA Sophia Antipolis-Méditerranée (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 -- cgit v1.2.3 From 9ce621289b5061e30329426aef5695ae3e19a099 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 21 Jan 2016 20:46:10 +0000 Subject: cpplint/cppcheck fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/VR_witness@985 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4dc15b3ab0eecb8d4f5bbb1ac1cb9dabf95233e4 --- .../include/gudhi/Landmark_choice_by_random_point.h | 2 +- src/Witness_complex/include/gudhi/Witness_complex.h | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h index 215c9e65..4747dd73 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h @@ -76,7 +76,7 @@ class Landmark_choice_by_random_point { std::set::iterator landmarks_it; int landmarks_i = 0; for (landmarks_it = landmarks.begin(), landmarks_i = 0; landmarks_it != landmarks.end(); - landmarks_it++, landmarks_i++) { + ++landmarks_it, landmarks_i++) { dist_i dist = std::make_pair(euclidean_distance(points[points_i], points[*landmarks_it]), landmarks_i); l_heap.push(dist); } diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 27f7a9c0..34cbc882 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -82,7 +82,6 @@ class Witness_complex { private: int nbL; // Number of landmarks - double density; // Desired density Simplicial_complex& sc; // Simplicial complex public: @@ -116,8 +115,6 @@ class Witness_complex { // Construction of the active witness list int nbW = knn.size(); typeVectorVertex vv; - typeSimplex simplex; - typePairSimplexBool returnValue; int counter = 0; /* The list of still useful witnesses * it will diminuish in the course of iterations @@ -128,7 +125,7 @@ class Witness_complex { // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore counter++; vv = {i}; - returnValue = sc.insert_simplex(vv); + sc.insert_simplex(vv); // TODO(SK) Error if not inserted : normally no need here though } int k = 1; /* current dimension in iterative construction */ @@ -145,7 +142,8 @@ class Witness_complex { if (ok) { for (int i = 0; i != k + 1; ++i) simplex_vector.push_back(knn[*it][i]); - returnValue = sc.insert_simplex(simplex_vector, 0.0); + sc.insert_simplex(simplex_vector, 0.0); + // TODO(SK) Error if not inserted : normally no need here though it++; } else { active_w.erase(it++); // First increase the iterator and then erase the previous element @@ -183,7 +181,7 @@ class Witness_complex { } template - void print_vector(const std::vector v) { + static void print_vector(const std::vector& v) { std::cout << "["; if (!v.empty()) { std::cout << *(v.begin()); -- cgit v1.2.3 From 945a98537205d4f3e3f7c3c652f373af89723731 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 21 Jan 2016 21:41:33 +0000 Subject: Warning fix - if not BOOST_CHECK, variable b_print_output seen as not used. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/VR_witness@986 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 171f360b478c98edd9e177808e2c0b8410bfbd37 --- src/Witness_complex/test/witness_complex_points.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/test/witness_complex_points.cpp b/src/Witness_complex/test/witness_complex_points.cpp index 78f01e08..300b2ac5 100644 --- a/src/Witness_complex/test/witness_complex_points.cpp +++ b/src/Witness_complex/test/witness_complex_points.cpp @@ -55,12 +55,12 @@ BOOST_AUTO_TEST_CASE(witness_complex_points) { Landmark_choice_by_random_point lcrp(points, 100, knn); assert(!knn.empty()); WitnessComplex witnessComplex1(knn, complex1, 100, 3); - assert(witnessComplex1.is_witness_complex(knn, b_print_output)); + BOOST_CHECK(witnessComplex1.is_witness_complex(knn, b_print_output)); // Second test: furthest choice knn.clear(); Simplex_tree complex2; Landmark_choice_by_furthest_point lcfp(points, 100, knn); WitnessComplex witnessComplex2(knn, complex2, 100, 3); - assert(witnessComplex2.is_witness_complex(knn, b_print_output)); + BOOST_CHECK(witnessComplex2.is_witness_complex(knn, b_print_output)); } -- cgit v1.2.3 From 7e667b71d937f83b82240afbf90b8cde7225eb8a Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 2 Feb 2016 14:49:56 +0000 Subject: landmark choice functions are now static git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@994 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f83d337feab944e2c823b8e127f1a8d612d0a1bd --- .../example/witness_complex_from_file.cpp | 2 +- .../example/witness_complex_sphere.cpp | 2 +- .../gudhi/Landmark_choice_by_furthest_point.h | 22 +++++---------------- .../gudhi/Landmark_choice_by_random_point.h | 23 ++++++---------------- .../test/witness_complex_points.cpp | 6 ++---- 5 files changed, 15 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index d94502b1..77109512 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -102,7 +102,7 @@ int main(int argc, char * const argv[]) { // Choose landmarks start = clock(); std::vector > knn; - Landmark_choice_by_random_point(point_vector, nbL, knn); + Gudhi::witness_complex::landmark_choice_by_random_point(point_vector, nbL, knn); end = clock(); std::cout << "Landmark choice for " << nbL << " landmarks took " << static_cast(end - start) / CLOCKS_PER_SEC << " s. \n"; diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index 36f63437..1ff35bff 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -82,7 +82,7 @@ int main(int argc, char * const argv[]) { // Choose landmarks start = clock(); std::vector > knn; - Landmark_choice_by_random_point(point_vector, nbL, knn); + Gudhi::witness_complex::landmark_choice_by_random_point(point_vector, nbL, knn); // Compute witness complex WitnessComplex(knn, simplex_tree, nbL, point_vector[0].size()); diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h index bb7e87f5..47cd888d 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -31,20 +31,9 @@ namespace Gudhi { namespace witness_complex { -/** - * \class Landmark_choice_by_furthest_point - * \brief The class `Landmark_choice_by_furthest_point` allows to construct the matrix - * of closest landmarks per witness by iteratively choosing the furthest witness - * from the set of already chosen landmarks as the new landmark. - * \ingroup witness_complex - */ - -class Landmark_choice_by_furthest_point { - private: - typedef std::vector typeVectorVertex; + typedef std::vector typeVectorVertex; - public: - /** + /** * \brief Landmark choice strategy by iteratively adding the furthest witness from the * current landmark set as the new landmark. * \details It chooses nbL landmarks from a random access range `points` and @@ -53,9 +42,9 @@ class Landmark_choice_by_furthest_point { template - Landmark_choice_by_furthest_point(Point_random_access_range const &points, - int nbL, - KNearestNeighbours &knn) { + void landmark_choice_by_furthest_point(Point_random_access_range const &points, + int nbL, + KNearestNeighbours &knn) { int nb_points = points.end() - points.begin(); assert(nb_points >= nbL); // distance matrix witness x landmarks @@ -98,7 +87,6 @@ class Landmark_choice_by_furthest_point { [&wit_land_dist, i](int a, int b) { return wit_land_dist[i][a] < wit_land_dist[i][b]; }); } -}; } // namespace witness_complex diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h index 4747dd73..dc364007 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h @@ -32,26 +32,16 @@ namespace Gudhi { namespace witness_complex { -/** - * \class Landmark_choice_by_random_point - * \brief The class `Landmark_choice_by_random_point` allows to construct the matrix - * of closest landmarks per witness by iteratively choosing a random non-chosen witness - * as a new landmark. - * \ingroup witness_complex - */ - -class Landmark_choice_by_random_point { - public: /** \brief Landmark choice strategy by taking random vertices for landmarks. * \details It chooses nbL distinct landmarks from a random access range `points` * and outputs a matrix {witness}*{closest landmarks} in knn. */ template - Landmark_choice_by_random_point(Point_random_access_range const &points, - int nbL, - KNearestNeighbours &knn) { + typename Point_random_access_range> + void landmark_choice_by_random_point(Point_random_access_range const &points, + int nbL, + KNearestNeighbours &knn) { int nbP = points.end() - points.begin(); assert(nbP >= nbL); std::set landmarks; @@ -71,8 +61,8 @@ class Landmark_choice_by_random_point { knn = KNearestNeighbours(nbP); for (int points_i = 0; points_i < nbP; points_i++) { std::priority_queue, comp> l_heap([&](dist_i j1, dist_i j2) { - return j1.first > j2.first; - }); + return j1.first > j2.first; + }); std::set::iterator landmarks_it; int landmarks_i = 0; for (landmarks_it = landmarks.begin(), landmarks_i = 0; landmarks_it != landmarks.end(); @@ -87,7 +77,6 @@ class Landmark_choice_by_random_point { } } } -}; } // namespace witness_complex diff --git a/src/Witness_complex/test/witness_complex_points.cpp b/src/Witness_complex/test/witness_complex_points.cpp index 300b2ac5..cb1639e1 100644 --- a/src/Witness_complex/test/witness_complex_points.cpp +++ b/src/Witness_complex/test/witness_complex_points.cpp @@ -37,8 +37,6 @@ typedef std::vector Point; typedef std::vector< Vertex_handle > typeVectorVertex; typedef Gudhi::Simplex_tree<> Simplex_tree; typedef Gudhi::witness_complex::Witness_complex WitnessComplex; -typedef Gudhi::witness_complex::Landmark_choice_by_random_point Landmark_choice_by_random_point; -typedef Gudhi::witness_complex::Landmark_choice_by_furthest_point Landmark_choice_by_furthest_point; BOOST_AUTO_TEST_CASE(witness_complex_points) { std::vector< typeVectorVertex > knn; @@ -52,7 +50,7 @@ BOOST_AUTO_TEST_CASE(witness_complex_points) { bool b_print_output = false; // First test: random choice Simplex_tree complex1; - Landmark_choice_by_random_point lcrp(points, 100, knn); + Gudhi::witness_complex::landmark_choice_by_random_point(points, 100, knn); assert(!knn.empty()); WitnessComplex witnessComplex1(knn, complex1, 100, 3); BOOST_CHECK(witnessComplex1.is_witness_complex(knn, b_print_output)); @@ -60,7 +58,7 @@ BOOST_AUTO_TEST_CASE(witness_complex_points) { // Second test: furthest choice knn.clear(); Simplex_tree complex2; - Landmark_choice_by_furthest_point lcfp(points, 100, knn); + Gudhi::witness_complex::landmark_choice_by_furthest_point(points, 100, knn); WitnessComplex witnessComplex2(knn, complex2, 100, 3); BOOST_CHECK(witnessComplex2.is_witness_complex(knn, b_print_output)); } -- cgit v1.2.3 From 7fe2c44c56e4fbd176131f31bc4338932f7a9d32 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 5 Feb 2016 12:24:49 +0000 Subject: Over here I have linkd phat with Gudhi. So far it is done only for cubical complexes, but since I am ONLY using Filtration_simplex_iterator, there should be no problem to have it run with any other class we have. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1004 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ddb3e2c5fa0c2a816e7435c57d32c0644f8163d2 --- ...ubical_complex_periodic_boundary_conditions.cpp | 159 +++++++++++---------- src/Bitmap_cubical_complex/example/CMakeLists.txt | 2 + .../example/Compute_persistence_with_phat.cpp | 60 ++++++++ 3 files changed, 146 insertions(+), 75 deletions(-) create mode 100644 src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp (limited to 'src') diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp index 3d80c96d..df01240b 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp @@ -1,75 +1,84 @@ - /* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Saclay (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 - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff -#include -#include -#include - -using namespace std; - -int main( int argc , char** argv ) -{ - cout << "This program computes persistent homology, by using Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in Perseus style (the only numbered in \ -the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; - - int p = 2; - double min_persistence = 0; - - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > b( argv[1] ); - - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > - , Field_Zp - > pcoh(b,true); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology - pcoh.compute_persistent_cohomology( min_persistence ); - - - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out((char*)ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 0; -} + /* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include + +using namespace std; + +int main( int argc , char** argv ) +{ + clock_t beginOfProgram = clock(); + + cout << "This program computes persistent homology, by using Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in Perseus style (the only numbered in \ +the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > b( argv[1] ); + + cerr << "Here \n"; + + clock_t endCreateBitmap = clock(); + double elapsed_secsCreateBitmap = double(endCreateBitmap - beginOfProgram) / CLOCKS_PER_SEC; + cerr << "Time of creation of bitmap : " << elapsed_secsCreateBitmap << endl; + + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base >, Field_Zp > pcoh(b,true); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology( min_persistence ); + + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + clock_t endOfProgram = clock(); + double elapsed_secsOfProgram = double(endOfProgram - beginOfProgram) / CLOCKS_PER_SEC; + cerr << "Overall execution time : " << elapsed_secsOfProgram << endl; + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index 26796e9d..fbd1b28b 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -13,3 +13,5 @@ add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubical_complex_periodic_boundary_conditions.cpp ) target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) +add_executable ( Compute_persistence_with_phat Compute_persistence_with_phat.cpp ) +target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp b/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp new file mode 100644 index 00000000..fe9be33e --- /dev/null +++ b/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp @@ -0,0 +1,60 @@ + + /* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; + +//standard stuff +#include +#include +#include + +using namespace std; + + +int main( int argc , char** argv ) +{ + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); + cerr << "Cubical complex created \n"; + + + Compute_persistence_with_phat< Bitmap_cubical_complex< Bitmap_cubical_complex_base > , double > phat(&b); + phat::persistence_pairs pairs = phat.compute_persistence_pairs_dualized_chunk_reduction(); + std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > persistence = phat.get_the_intervals( pairs ); + writeBettiNumbersAndPersistenceIntervalsToFile( "phat_persistence" , persistence ); + + return 0; +} -- cgit v1.2.3 From 3be6acc35255b52a60a254fa101aec5b11173b6d Mon Sep 17 00:00:00 2001 From: pdlotko Date: Mon, 8 Feb 2016 15:10:49 +0000 Subject: Adding changes suggested by Marc. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1007 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2462c084e3269a3d44813619f44852d3c8d6e163 --- src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp b/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp index fe9be33e..f552a094 100644 --- a/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp +++ b/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp @@ -52,7 +52,7 @@ int main( int argc , char** argv ) Compute_persistence_with_phat< Bitmap_cubical_complex< Bitmap_cubical_complex_base > , double > phat(&b); - phat::persistence_pairs pairs = phat.compute_persistence_pairs_dualized_chunk_reduction(); + phat::persistence_pairs pairs = phat.compute_persistence_pairs_standard_reduction(); std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > persistence = phat.get_the_intervals( pairs ); writeBettiNumbersAndPersistenceIntervalsToFile( "phat_persistence" , persistence ); -- cgit v1.2.3 From 84399987baac2817e58bf9f5e18ded6aa6893b0f Mon Sep 17 00:00:00 2001 From: pdlotko Date: Tue, 9 Feb 2016 13:26:47 +0000 Subject: adding missing partsy git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1008 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f6de1ee4317763b50233f9a7212bdbf6587ee686 --- .../doc/Gudhi_Cubical_Complex_doc.h | 41 +- src/Bitmap_cubical_complex/doc/exampleBitmap.png | Bin 9594 -> 2549 bytes .../include/gudhi/Bitmap_cubical_complex.h | 28 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 114 +++++- ...cal_complex_periodic_boundary_conditions_base.h | 451 +++++++++++---------- .../include/gudhi/Compute_persistence_with_phat.h | 242 +++++++++++ .../gudhi/phat/algorithms/chunk_reduction.h | 240 +++++++++++ .../include/gudhi/phat/algorithms/row_reduction.h | 55 +++ .../gudhi/phat/algorithms/standard_reduction.h | 45 ++ .../gudhi/phat/algorithms/twist_reduction.h | 50 +++ .../include/gudhi/phat/boundary_matrix.h | 336 +++++++++++++++ .../include/gudhi/phat/compute_persistence_pairs.h | 69 ++++ .../include/gudhi/phat/helpers/dualize.h | 63 +++ .../include/gudhi/phat/helpers/misc.h | 74 ++++ .../gudhi/phat/helpers/thread_local_storage.h | 52 +++ .../include/gudhi/phat/persistence_pairs.h | 151 +++++++ .../phat/representations/abstract_pivot_column.h | 158 ++++++++ .../phat/representations/bit_tree_pivot_column.h | 169 ++++++++ .../gudhi/phat/representations/full_pivot_column.h | 81 ++++ .../phat/representations/sparse_pivot_column.h | 62 +++ .../gudhi/phat/representations/vector_list.h | 98 +++++ .../gudhi/phat/representations/vector_set.h | 100 +++++ .../gudhi/phat/representations/vector_vector.h | 93 +++++ src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 12 +- 24 files changed, 2532 insertions(+), 252 deletions(-) create mode 100644 src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h (limited to 'src') diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index 1a6310fb..c06678a1 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -38,20 +38,18 @@ namespace Cubical_complex *Cubical complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. * -* An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} \f$. The first one is called non-degenerated, while the second one is \a degenerated interval. A boundary of a elementary -*interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of non-degenerated elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerated elementary interval. An elementary cube \f$ C \f$ is a +* An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} \f$. The first one is called non-degenerate, while the second one is \a degenerate interval. A boundary of a elementary +*interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of non-degenerate elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerate elementary interval. An elementary cube \f$ C \f$ is a -*product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$. Embedding dimension of a cube is n, the number of elementary intervals (degenerated or not) in the product. A dimension of a cube \f$C=I_1 \times ... \times I_n\f$ is the -*number of non degenerated elementary intervals in the product. A boundary of a cube \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained in the following way: +*product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$. Embedding dimension of a cube is n, the number of elementary intervals (degenerate or not) in the product. A dimension of a cube \f$C=I_1 \times ... \times I_n\f$ is the +*number of non degenerate elementary intervals in the product. A boundary of a cube \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained in the following way: *\f[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\f] *A cubical complex \f$\mathcal{K}\f$ is a collection of cubes closed under operation of taking boundary (i.e. boundary of every cube from the collection is in the collection). A cube \f$C\f$ in cubical complex \f$\mathcal{K}\f$ is maximal if it is not in *a boundary of any other cube in \f$\mathcal{K}\f$. A \a support of a cube \f$C\f$ is the set in \f$\mathbb{R}^n\f$ occupied by \f$C\f$ (\f$n\f$ is the embedding dimension of \f$C\f$). * *Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may be a set of two elements). * -*For further details and theory of cubical complexes, please consult \cite kaczynski2004computational . -* -*as well as the following paper \cite peikert2012topological . +*For further details and theory of cubical complexes, please consult \cite kaczynski2004computational as well as the following paper \cite peikert2012topological . * *\section datastructure Data structure. * @@ -73,7 +71,8 @@ namespace Cubical_complex *In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star filtration to all cubes. There are a number of constructors *that can be used to construct cubical complex by users who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class. *Currently one input from a text file is used. It uses a format used already in Perseus software (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. -*Below we are providing a description of the format. +*Below we are providing a description of the format. The first line contains a number d begin the dimension of the bitmap (2 in the example below). Next d lines are the numbers of +*top dimensional cubes in each dimensions (3 and 3 in the example below). Next, in lexicographical order, the filtration of top dimensional cubes is given (1 4 6 8 20 4 7 6 5 in the example below). * * *\image html "exampleBitmap.png" "Example of a input data." @@ -84,6 +83,29 @@ namespace Cubical_complex 3 3 1 +4 +6 +8 +20 +4 +7 +6 +5 +\endverbatim + +\section Periodic boundary conditions +Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times I_n \f$ be a box +that is decomposed with a cubical complex \f$ \mathcal{K} \f$. Imposing periodic boundary conditions in the direction i, means that the left and the right side of a complex +\f$ \mathcal{K} \f$ are considered the same. In particular, if for a bitmap \f$ \mathcal{K} \f$ periodic boundary conditions are imposed in all directions, then complex +\f$ \mathcal{K} \f$ became n-dimensional torus. One can use various constructors from the file Bitmap_cubical_complex_periodic_boundary_conditions_base.h to construct cubical +complex with periodic boundary conditions. One can also use Perseus style input files. To indicate periodic boundary conditions in a given direction, then number of top dimensional cells +in this direction have to be multiplied by -1. For instance: + +*\verbatim +2 +-3 +3 +1 2 3 8 @@ -94,6 +116,9 @@ namespace Cubical_complex 5 \endverbatim +Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. + + */ /** @} */ // end defgroup cubical_complex diff --git a/src/Bitmap_cubical_complex/doc/exampleBitmap.png b/src/Bitmap_cubical_complex/doc/exampleBitmap.png index f8207473..069c6eb2 100644 Binary files a/src/Bitmap_cubical_complex/doc/exampleBitmap.png and b/src/Bitmap_cubical_complex/doc/exampleBitmap.png differ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 63edcadd..82ea8672 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -1,4 +1,4 @@ - /* This file is part of the Gudhi Library. The Gudhi library +/* This file is part of the Gudhi Library. The Gudhi library * (Geometric Understanding in Higher Dimensions) is a generic C++ * library for computational topology. * @@ -65,7 +65,8 @@ public: **/ Bitmap_cubical_complex( const char* perseus_style_file ): T(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) - { + { + //clock_t begin = clock(); if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) { @@ -74,7 +75,8 @@ public: //we initialize this only once, in each constructor, when the bitmap is constructed. //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. - this->initialize_simplex_associated_to_key(); + this->initialize_simplex_associated_to_key(); + //cerr << "Time of running Bitmap_cubical_complex( const char* perseus_style_file ) constructor : " << double(clock() - begin) / CLOCKS_PER_SEC << endl; } @@ -115,7 +117,8 @@ public: //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. this->initialize_simplex_associated_to_key(); - } + } + //*********************************************// //Other 'easy' functions @@ -328,6 +331,15 @@ public: **/ Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) { + /* + std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh); + Boundary_simplex_range result( bdry.size() ); + for ( size_t i = 0 ; i != bdry.size() ; ++i ) + { + result[i] = this->simplex_associated_to_key[ bdry[i] ]; + } + return result; + */ return this->get_boundary_of_a_cell(sh); } @@ -500,7 +512,13 @@ void Bitmap_cubical_complex::initialize_simplex_associated_to_key() std::iota (std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); std::sort( simplex_associated_to_key.begin() , simplex_associated_to_key.end() , - is_before_in_filtration(this) ); + is_before_in_filtration(this) ); + + //we still need to deal here with a key_associated_to_simplex: + for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) + { + this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; + } } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 600f250d..22b703a9 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include "Bitmap_cubical_complex/counter.h" @@ -68,7 +69,9 @@ public: /** *Default constructor **/ - Bitmap_cubical_complex_base(){} + Bitmap_cubical_complex_base() + { + } /** * There are a few constructors of a Bitmap_cubical_complex_base class. * First one, that takes vector, creates an empty bitmap of a dimension equal @@ -110,7 +113,7 @@ public: * non-negative integers pointing to the * positions of (co)boundary element of the input cell. **/ - inline std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + virtual inline std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; /** * In the case of get_dimension_of_a_cell function, the output is a non-negative integer * indicating the dimension of a cell. @@ -140,7 +143,7 @@ public: /** * Returns number of all cubes in the data structure. **/ - inline unsigned size_of_bitmap()const + inline unsigned size()const { return this->data.size(); } @@ -149,7 +152,19 @@ public: * Writing to stream operator. **/ template - friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); + friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); + + + /** + * Functions that put the input data to bins. + **/ + void put_data_toBins( size_t number_of_bins ); + void put_data_toBins( T diameter_of_bin ); + + /** + * Functions to find min and max values of filtration. + **/ + std::pair< T ,T > min_max_filtration(); //ITERATORS @@ -157,22 +172,41 @@ public: * Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ - typedef typename std::vector< T >::iterator all_cells_iterator; - all_cells_iterator all_cells_begin()const + typedef typename std::vector< T >::iterator all_cells_iterator; + + /** + * Function returning an iterator to the first cell of the bitmap. + **/ + all_cells_iterator all_cells_begin() { return this->data.begin(); - } + } + + /** + * Function returning an iterator to the last cell of the bitmap. + **/ all_cells_iterator all_cells_end()const { return this->data.end(); } - - typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + /** + * Constant iterator through all cells in the complex (in order they appear in the structure -- i.e. + * in lexicographical order). + **/ + typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + + /** + * Function returning a constant iterator to the first cell of the bitmap. + **/ all_cells_const_iterator all_cells_const_begin()const { return this->data.begin(); - } + } + + /** + * Function returning a constant iterator to the last cell of the bitmap. + **/ all_cells_const_iterator all_cells_const_end()const { return this->data.end(); @@ -269,12 +303,20 @@ public: protected: std::vector< size_t > counter; Bitmap_cubical_complex_base& b; - }; + }; + + /** + * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell cell of the bitmap. + **/ Top_dimensional_cells_iterator top_dimensional_cells_begin() { Top_dimensional_cells_iterator a(*this); return a; - } + } + + /** + * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell cell of the bitmap. + **/ Top_dimensional_cells_iterator top_dimensional_cells_end() { Top_dimensional_cells_iterator a(*this); @@ -351,6 +393,50 @@ protected: }; +template +void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) +{ + bool bdg = false; + + std::pair< T ,T > min_max = this->min_max_filtration(); + T dx = (min_max.second-min_max.first)/(T)number_of_bins; + + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + +template +void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) +{ + bool bdg = false; + std::pair< T ,T > min_max = this->min_max_filtration(); + + size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + +template +std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() +{ + std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( this->data[i] < min_max.first )min_max.first = this->data[i]; + if ( this->data[i] > min_max.second )min_max.second = this->data[i]; + } + return min_max; +} template @@ -422,7 +508,7 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu unsigned dimensionOfData; inFiltration >> dimensionOfData; - if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;} + if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;getchar();} std::vector sizes; sizes.reserve( dimensionOfData ); diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 28911ea8..38c218dc 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -1,120 +1,120 @@ -#pragma once -#include -#include "Bitmap_cubical_complex_base.h" - +#pragma once +#include +#include "Bitmap_cubical_complex_base.h" + using namespace std; namespace Gudhi { namespace Cubical_complex -{ - -//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures -//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the -//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base - -template -class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base -{ -public: - //constructors that take an extra parameter: - Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); - - //overwritten methods co compute boundary and coboundary - virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; - std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; - //inline unsigned get_dimension_of_a_cell( size_t cell )const; - -protected: - std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; +{ + +//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures +//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the +//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base + +template +class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base +{ +public: + //constructors that take an extra parameter: + Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); + + //overwritten methods co compute boundary and coboundary + virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; + std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + //inline unsigned get_dimension_of_a_cell( size_t cell )const; + +protected: + std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; void set_up_containers( const std::vector& sizes ) - { + { unsigned multiplier = 1; for ( size_t i = 0 ; i != sizes.size() ; ++i ) { this->sizes.push_back(sizes[i]); this->multipliers.push_back(multiplier); - - if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) - { - multiplier *= 2*sizes[i]; - } - else - { - multiplier *= 2*sizes[i]+1; + + if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) + { + multiplier *= 2*sizes[i]; + } + else + { + multiplier *= 2*sizes[i]+1; } } //std::reverse( this->sizes.begin() , this->sizes.end() ); this->data = std::vector(multiplier,std::numeric_limits::max()); this->total_number_of_cells = multiplier; - } - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ); - void construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); -}; - -template -void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; - this->set_up_containers( dimensions ); - - size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) - { - *it = topDimensionalCells[i]; - ++i; - } - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) -{ - //for Perseus style files: - bool dbg = false; - + } + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ); + void construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); +}; + +template +void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers( dimensions ); + + size_t i = 0; + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + *it = topDimensionalCells[i]; + ++i; + } + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) +{ + + //for Perseus style files: + bool dbg = false; ifstream inFiltration; inFiltration.open( perseus_style_file ); unsigned dimensionOfData; - inFiltration >> dimensionOfData; - - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); - - std::vector sizes; + inFiltration >> dimensionOfData; + + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); + + std::vector sizes; sizes.reserve( dimensionOfData ); for ( size_t i = 0 ; i != dimensionOfData ; ++i ) { int size_in_this_dimension; - inFiltration >> size_in_this_dimension; - if ( size_in_this_dimension < 0 ) - { - this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; + inFiltration >> size_in_this_dimension; + if ( size_in_this_dimension < 0 ) + { + this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; } sizes.push_back( abs(size_in_this_dimension) ); } - this->set_up_containers( sizes ); - + this->set_up_containers( sizes ); + typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); it = this->top_dimensional_cells_begin(); while ( !inFiltration.eof() ) { double filtrationLevel; - inFiltration >> filtrationLevel; - if ( inFiltration.eof() )break; + inFiltration >> filtrationLevel; + if ( inFiltration.eof() )break; if ( dbg ) { @@ -128,124 +128,137 @@ Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_comp ++it; } inFiltration.close(); - this->impose_lower_star_filtration(); - - /* - char* filename = (char*)perseus_style_file; - //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; - ifstream file( filename , ios::binary | ios::ate ); - unsigned realSizeOfFile = file.tellg(); - file.close(); - realSizeOfFile = realSizeOfFile/sizeof(T); - - unsigned w, h, d; - - w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); - - T* slice = new T[w*h*d]; - if (slice == NULL) - { - cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; - exit(EXIT_FAILURE); - } - - FILE* fp; - if ((fp=fopen( filename, "rb" )) == NULL ) - { - cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; - exit(1); - } - fread( slice,4,w*h*d,fp ); - fclose(fp); - std::vector data(slice,slice+w*h*d); - delete[] slice; - std::vector< unsigned > sizes; - sizes.push_back(w); - sizes.push_back(w); - sizes.push_back(w); - - std::vector< bool > directions; - directions.push_back( true ); - directions.push_back( true ); - directions.push_back( true ); - Bitmap_cubical_complex_periodic_boundary_conditions_base b( sizes, data, directions ); - *this = b; - */ -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ) -{ - std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - - - - - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - -//***********************Methods************************// - -template -std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const -{ - bool dbg = false; - if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} - + this->impose_lower_star_filtration(); + +/* + char* filename = (char*)perseus_style_file; + //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; + ifstream file( filename , ios::binary | ios::ate ); + unsigned realSizeOfFile = file.tellg(); + file.close(); + realSizeOfFile = realSizeOfFile/sizeof(T); + + unsigned w, h, d; + + w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); + + T* slice = new T[w*h*d]; + if (slice == NULL) + { + cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; + exit(EXIT_FAILURE); + } + + FILE* fp; + if ((fp=fopen( filename, "rb" )) == NULL ) + { + cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; + exit(1); + } + + clock_t read_begin = clock(); + fread( slice,4,w*h*d,fp ); + fclose(fp); + cerr << "Time of reading the file : " << double(clock() - read_begin) / CLOCKS_PER_SEC << endl; + + + clock_t begin_creation_bitap = clock(); + std::vector data(slice,slice+w*h*d); + delete[] slice; + std::vector< unsigned > sizes; + sizes.push_back(w); + sizes.push_back(w); + sizes.push_back(w); + + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->set_up_containers( sizes ); + + size_t i = 0; + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + *it = data[i]; + ++i; + } + this->impose_lower_star_filtration(); + cerr << "Time of creation of a bitmap : " << double(clock() - begin_creation_bitap ) / CLOCKS_PER_SEC << endl; +*/ +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ) +{ + std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + + + + + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + +//***********************Methods************************// + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const +{ + bool dbg = false; + if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} + std::vector< size_t > boundary_elements; size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { - unsigned position = cell1/this->multipliers[i-1]; - //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. + unsigned position = cell1/this->multipliers[i-1]; + //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. if ( position%2 == 1 ) - { - //if there are no periodic boundary conditions in this direction, we do not have to do anything. - if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { - //cerr << "A\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. - if ( position != 2*this->sizes[ i-1 ]-1 ) - { - //cerr << "B\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //cerr << "C\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} - } + { + //if there are no periodic boundary conditions in this direction, we do not have to do anything. + if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { + //cerr << "A\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. + if ( position != 2*this->sizes[ i-1 ]-1 ) + { + //cerr << "B\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //cerr << "C\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} + } } } cell1 = cell1%this->multipliers[i-1]; } - return boundary_elements; -} - + return boundary_elements; +} + template std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell( size_t cell )const { @@ -254,12 +267,12 @@ std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_basemultipliers.size() ; i != 0 ; --i ) { - unsigned position = cell1/this->multipliers[i-1]; - //if the cell has zero length in this direction, then it will have cbd in this direction. + unsigned position = cell1/this->multipliers[i-1]; + //if the cell has zero length in this direction, then it will have cbd in this direction. if ( position%2 == 0 ) - { - if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { + { + if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { //no periodic boundary conditions in this direction if ( (counter[i-1] != 0) && (cell > this->multipliers[i-1]) ) { @@ -268,31 +281,31 @@ std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_basesizes[i-1]) && (cell + this->multipliers[i-1] < this->data.size()) ) { coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - } - else - { - //we want to have periodic boundary conditions in this direction - if ( counter[i-1] != 0 ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - else - { - //in this case counter[i-1] == 0. - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); - } + } } - } + else + { + //we want to have periodic boundary conditions in this direction + if ( counter[i-1] != 0 ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } + else + { + //in this case counter[i-1] == 0. + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); + } + } + } cell1 = cell1%this->multipliers[i-1]; } return coboundary_elements; -} - - - -}//Cubical_complex -}//namespace Gudhi +} + + + +}//Cubical_complex +}//namespace Gudhi diff --git a/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h b/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h new file mode 100644 index 00000000..9f4ada45 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h @@ -0,0 +1,242 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-Saclay (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 . + */ + +#pragma once + + +#include "phat/compute_persistence_pairs.h" +#include "phat/representations/vector_vector.h" +#include "phat/algorithms/standard_reduction.h" +#include "phat/algorithms/chunk_reduction.h" +#include "phat/algorithms/row_reduction.h" +#include "phat/algorithms/twist_reduction.h" + + +namespace Gudhi +{ + + +//the only aim of this class is to have a ability to compute persistence with phat. +template +void writeBettiNumbersAndPersistenceIntervalsToFile( char* prefix , std::pair< std::vector > , std::vector< std::vector< std::pair > > > resutsFromPhat ) +{ + std::ostringstream filenameStr; + filenameStr << prefix << "_bettiNumbers"; + std::string str = filenameStr.str(); + const char* filename = str.c_str(); + ofstream out; + out.open( filename ); + for ( size_t dim = 0 ; dim != resutsFromPhat.first.size() ; ++dim ) + { + out << "Dimension : " << dim << endl; + for ( size_t i = 0 ; i != resutsFromPhat.first[dim].size() ; ++i ) + { + out << resutsFromPhat.first[dim][i] << endl; + } + out << endl; + } + out.close(); + + + cerr << "Write persistence to file \n"; + for ( size_t dim = 0 ; dim != resutsFromPhat.second.size() ; ++dim ) + { + cerr << "resutsFromPhat.second[dim].size() : " << resutsFromPhat.second[dim].size() << endl; + if ( resutsFromPhat.second[dim].size() == 0 )continue; + std::ostringstream filenameStr; + filenameStr << prefix << "_persistence_" << dim; + std::string str = filenameStr.str(); + const char* filename = str.c_str(); + ofstream out1; + out1.open( filename ); + for ( size_t i = 0 ; i != resutsFromPhat.second[dim].size() ; ++i ) + { + out1 << resutsFromPhat.second[dim][i].first << " " << resutsFromPhat.second[dim][i].second << endl; + } + out1.close(); + } +}//writeBettiNumbersAndPersistenceIntervalsToFile + + +template +class Compute_persistence_with_phat +{ +public: + Compute_persistence_with_phat( T* data_structure_ ); + std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > get_the_intervals( phat::persistence_pairs pairs ); + + phat::persistence_pairs compute_persistence_pairs_dualized_chunk_reduction(); + phat::persistence_pairs compute_persistence_pairs_twist_reduction(); + phat::persistence_pairs compute_persistence_pairs_standard_reduction(); + //phat::persistence_pairs compute_persistence_pairs_spectral_sequence_reduction(); +private: + void print_bd_matrix(); + phat::boundary_matrix< phat::vector_vector > boundary_matrix; + T* data_structure; +}; + +template +void Compute_persistence_with_phat::print_bd_matrix() +{ + std::cout << "The boundary matrix has " << this->boundary_matrix.get_num_cols() << " columns: " << std::endl; + for( phat::index col_idx = 0; col_idx < this->boundary_matrix.get_num_cols(); col_idx++ ) { + std::cout << "Colum " << col_idx << " represents a cell of dimension " << (int)this->boundary_matrix.get_dim( col_idx ) << ". "; + if( !this->boundary_matrix.is_empty( col_idx ) ) { + std::vector< phat::index > temp_col; + this->boundary_matrix.get_col( col_idx, temp_col ); + std::cout << "Its boundary consists of the cells"; + for( phat::index idx = 0; idx < (phat::index)temp_col.size(); idx++ ) + std::cout << " " << temp_col[ idx ]; + } + std::cout << std::endl; + } +} + +template +phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_dualized_chunk_reduction() +{ + phat::persistence_pairs pairs; + phat::compute_persistence_pairs_dualized< phat::chunk_reduction >( pairs, this->boundary_matrix ); + return pairs; +} + +template +phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_twist_reduction() +{ + phat::persistence_pairs pairs; + phat::compute_persistence_pairs< phat::twist_reduction >( pairs, this->boundary_matrix ); + return pairs; +} + +template +phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_standard_reduction() +{ + phat::persistence_pairs pairs; + phat::compute_persistence_pairs< phat::standard_reduction >( pairs, this->boundary_matrix ); + return pairs; +} + +//template +//phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_spectral_sequence_reduction() +//{ +// phat::persistence_pairs pairs; +// phat::compute_persistence_pairs< phat::spectral_sequence_reduction >( pairs, this->boundary_matrix ); +// return pairs; +//} + +template +Compute_persistence_with_phat::Compute_persistence_with_phat( T* data_structure_ ):data_structure( data_structure_ ) +{ + bool dbg = false; + this->boundary_matrix.set_num_cols( this->data_structure->num_simplices() ); + + //setting up the dimensions of cells: + for ( size_t i = 0 ; i != this->data_structure->num_simplices() ; ++i ) + { + this->boundary_matrix.set_dim( i, this->data_structure->dimension( this->data_structure->simplex(i) ) ); + } + + + //now it is time to set up the boundary matrix: + typename T::Filtration_simplex_range range = this->data_structure->filtration_simplex_range(); + std::vector< phat::index > temp_col; + for ( typename T::Filtration_simplex_iterator it = range.begin() ; it != range.end() ; ++it ) + { + typename T::Boundary_simplex_range boundary_range = this->data_structure->boundary_simplex_range( *it ); + for ( typename T::Boundary_simplex_iterator bd = boundary_range.begin() ; bd != boundary_range.end() ; ++bd ) + { + temp_col.push_back( this->data_structure->key( *bd ) ); + } + //we do not know if the boundary elements are sorted according to filtration, that is why I am enforcing it here: + this->boundary_matrix.set_col( this->data_structure->key( *it ) , temp_col ); + temp_col.clear(); + } +} + +template +std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > Compute_persistence_with_phat::get_the_intervals( phat::persistence_pairs pairs ) +{ + bool dbg = false; + //in order to find the birth times of the infinite homology classes, we need to know which elements are not paired. To search for them, we will use this vector: + std::vector isTheElementPaired( this->data_structure->num_simplices() , false ); + + //now it is time to recover the finite persistence pairs and the Betti numbers: + std::vector< std::vector< std::pair > > finitePersistencePairs( this->data_structure->dimension() ); + for( phat::index idx = 0; idx < pairs.get_num_pairs(); idx++ ) + { + typename T::Simplex_key positionOfBeginOfInterval = pairs.get_pair( idx ).first; + typename T::Simplex_key positionOfEndOfInterval = pairs.get_pair( idx ).second; + + typename T::Simplex_handle first_simplex = this->data_structure->simplex(positionOfBeginOfInterval); + typename T::Simplex_handle second_simplex = this->data_structure->simplex(positionOfEndOfInterval); + + typename T::Filtration_value valueFirst = this->data_structure->filtration( first_simplex ); + typename T::Filtration_value valueSecond = this->data_structure->filtration( second_simplex ); + + if ( valueFirst > valueSecond ){std::swap( valueFirst , valueSecond );} + + unsigned dimFirst = this->data_structure->dimension(first_simplex); + unsigned dimSecond = this->data_structure->dimension(second_simplex); + unsigned dim = std::min( dimFirst , dimSecond ); + + + //we are ignoring trivial barcodes + if ( valueFirst != valueSecond ) + { + finitePersistencePairs[ dim ].push_back( std::make_pair(valueFirst , valueSecond) ); + if ( dbg ){cerr << "Adding barcode : " << valueFirst << "," << valueSecond << endl;} + } + + //isTheElementPaired[ positionOfBeginOfIntervalInBitmap ] = true; + //isTheElementPaired[ positionOfEndOfIntervalInBitmap ] = true; + isTheElementPaired[ pairs.get_pair( idx ).first ] = true; + isTheElementPaired[ pairs.get_pair( idx ).second ] = true; + } + + + std::vector< std::vector > birthTimesOfInfinitePersistnceClasses(this->data_structure->dimension()+1 ); + for ( size_t i = 0 ; i != this->data_structure->dimension()+1 ; ++i ) + { + std::vector v; + birthTimesOfInfinitePersistnceClasses[i] = v; + } + for ( size_t i = 0 ; i != isTheElementPaired.size() ; ++i ) + { + if ( isTheElementPaired[i] == false ) + { + //i-th element is not paired, therefore it gives an infinite class + typename T::Simplex_handle simplex = this->data_structure->simplex(i); + birthTimesOfInfinitePersistnceClasses[ this->data_structure->dimension( simplex ) ].push_back( this->data_structure->filtration(simplex) ); + } + } + + //sorting finite persistence pairs: + for ( size_t dim = 0 ; dim != finitePersistencePairs.size() ; ++dim ) + { + std::sort( finitePersistencePairs[dim].begin() , finitePersistencePairs[dim].end() ); + } + return std::make_pair( birthTimesOfInfinitePersistnceClasses , finitePersistencePairs ); +}//Compute_persistence_with_phat + + + +}//namespace Gudhi diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h new file mode 100644 index 00000000..352392a8 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h @@ -0,0 +1,240 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../boundary_matrix.h" + +namespace phat { + class chunk_reduction { + public: + enum column_type { GLOBAL + , LOCAL_POSITIVE + , LOCAL_NEGATIVE }; + + public: + template< typename Representation > + void operator() ( boundary_matrix< Representation >& boundary_matrix ) { + + const index nr_columns = boundary_matrix.get_num_cols(); + const dimension max_dim = boundary_matrix.get_max_dim(); + + std::vector< index > lowest_one_lookup( nr_columns, -1 ); + std::vector < column_type > column_type( nr_columns, GLOBAL ); + std::vector< char > is_active( nr_columns, false ); + + std::vector chunk_boundaries; + _get_chunks( boundary_matrix, chunk_boundaries ); + + // Phase 1: Reduce chunks locally -- 1st pass + #pragma omp parallel for schedule( guided, 1 ) + for( index chunk_id = 0; chunk_id < (index) chunk_boundaries.size() - 2; chunk_id += 2 ) + _local_chunk_reduction( boundary_matrix, lowest_one_lookup, column_type, max_dim, + chunk_boundaries[chunk_id], chunk_boundaries[chunk_id+2] - 1 ); + boundary_matrix.sync(); + + // Phase 1: Reduce chunks locally -- 2nd pass + #pragma omp parallel for schedule( guided, 1 ) + for( index chunk_id = 1; chunk_id < (index) chunk_boundaries.size() - 2; chunk_id += 2 ) + _local_chunk_reduction( boundary_matrix, lowest_one_lookup, column_type, max_dim, + chunk_boundaries[chunk_id], chunk_boundaries[chunk_id+2] - 1 ); + boundary_matrix.sync(); + + // get global columns + std::vector< index > global_columns; + for( index cur_col_idx = 0; cur_col_idx < nr_columns; cur_col_idx++ ) + if( column_type[ cur_col_idx ] == GLOBAL ) + global_columns.push_back( cur_col_idx ); + + // get active columns + #pragma omp parallel for + for( index idx = 0; idx < (index)global_columns.size(); idx++ ) + is_active[ global_columns[ idx ] ] = true; + _get_active_columns( boundary_matrix, lowest_one_lookup, column_type, global_columns, is_active ); + + // Phase 2+3: Simplify columns and reduce them + for( dimension cur_dim = max_dim; cur_dim >= 1; cur_dim-- ) { + // Phase 2: Simplify columns + std::vector< index > temp_col; + #pragma omp parallel for schedule( guided, 1 ), private( temp_col ) + for( index idx = 0; idx < (index)global_columns.size(); idx++ ) + if( boundary_matrix.get_dim( global_columns[ idx ] ) == cur_dim ) + _global_column_simplification( global_columns[ idx ], boundary_matrix, lowest_one_lookup, column_type, is_active, temp_col ); + boundary_matrix.sync(); + + // Phase 3: Reduce columns + for( index idx = 0; idx < (index)global_columns.size(); idx++ ) { + index cur_col = global_columns[ idx ]; + if( boundary_matrix.get_dim( cur_col ) == cur_dim && column_type[ cur_col ] == GLOBAL ) { + index lowest_one = boundary_matrix.get_max_index( cur_col ); + while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { + boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); + lowest_one = boundary_matrix.get_max_index( cur_col ); + } + if( lowest_one != -1 ) { + lowest_one_lookup[ lowest_one ] = cur_col; + boundary_matrix.clear( lowest_one ); + } + } + } + } + + boundary_matrix.sync(); + } + + protected: + template< typename Representation > + void _get_chunks( const boundary_matrix< Representation >& boundary_matrix + , std::vector< index >& chunk_boundaries) + { + chunk_boundaries.clear(); + std::vector temp_chunk_boundaries; + const index nr_columns = boundary_matrix.get_num_cols(); + + // size of chuks = sqrt(N) + const index chunk_size = (index) sqrt( (float)nr_columns ); + + // size of chunks = N / num_threads + //const index chunk_size = nr_columns / omp_get_max_threads(); + + for ( index cur_col = 0; cur_col < nr_columns; cur_col++ ) + if( cur_col % chunk_size == 0 ) + temp_chunk_boundaries.push_back( cur_col ); + temp_chunk_boundaries.push_back( nr_columns ); + + // subdivide chunks for interleaved 2 pass appraoch + for( index chunk_id = 0; chunk_id < (index) temp_chunk_boundaries.size(); chunk_id ++ ) { + chunk_boundaries.push_back( temp_chunk_boundaries[ chunk_id ] ); + if( chunk_id < (index) temp_chunk_boundaries.size() - 1 ) { + index midPoint = ( temp_chunk_boundaries[ chunk_id ] + temp_chunk_boundaries[ chunk_id + 1 ] ) / 2; + chunk_boundaries.push_back( midPoint ); + } + } + } + + template< typename Representation > + void _local_chunk_reduction( boundary_matrix< Representation >& boundary_matrix + , std::vector& lowest_one_lookup + , std::vector< column_type >& column_type + , const dimension max_dim + , const index chunk_begin + , const index chunk_end ) { + for( dimension cur_dim = max_dim; cur_dim >= 1; cur_dim-- ) { + for( index cur_col = chunk_begin; cur_col <= chunk_end; cur_col++ ) { + if( column_type[ cur_col ] == GLOBAL && boundary_matrix.get_dim( cur_col ) == cur_dim ) { + index lowest_one = boundary_matrix.get_max_index( cur_col ); + while( lowest_one != -1 && lowest_one >= chunk_begin && lowest_one_lookup[ lowest_one ] != -1 ) { + boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); + lowest_one = boundary_matrix.get_max_index( cur_col ); + } + if( lowest_one >= chunk_begin ) { + lowest_one_lookup[ lowest_one ] = cur_col; + column_type[ cur_col ] = LOCAL_NEGATIVE; + column_type[ lowest_one ] = LOCAL_POSITIVE; + boundary_matrix.clear( lowest_one ); + } + } + } + } + } + + template< typename Representation > + void _get_active_columns( const boundary_matrix< Representation >& boundary_matrix + , const std::vector< index >& lowest_one_lookup + , const std::vector< column_type >& column_type + , const std::vector< index >& global_columns + , std::vector< char >& is_active ) { + + const index nr_columns = boundary_matrix.get_num_cols(); + std::vector< char > finished( nr_columns, false ); + + std::vector< std::pair < index, index > > stack; + std::vector< index > cur_col_values; + #pragma omp parallel for schedule( guided, 1 ), private( stack, cur_col_values ) + for( index idx = 0; idx < (index)global_columns.size(); idx++ ) { + bool pop_next = false; + index start_col = global_columns[ idx ]; + stack.push_back( std::pair< index, index >( start_col, -1 ) ); + while( !stack.empty() ) { + index cur_col = stack.back().first; + index prev_col = stack.back().second; + if( pop_next ) { + stack.pop_back(); + pop_next = false; + if( prev_col != -1 ) { + if( is_active[ cur_col ] ) { + is_active[ prev_col ] = true; + } + if( prev_col == stack.back().first ) { + finished[ prev_col ] = true; + pop_next = true; + } + } + } else { + pop_next = true; + boundary_matrix.get_col( cur_col, cur_col_values ); + for( index idx = 0; idx < (index) cur_col_values.size(); idx++ ) { + index cur_row = cur_col_values[ idx ]; + if( ( column_type[ cur_row ] == GLOBAL ) ) { + is_active[ cur_col ] = true; + } else if( column_type[ cur_row ] == LOCAL_POSITIVE ) { + index next_col = lowest_one_lookup[ cur_row ]; + if( next_col != cur_col && !finished[ cur_col ] ) { + stack.push_back( std::make_pair( next_col, cur_col ) ); + pop_next = false; + } + } + } + } + } + } + } + + template< typename Representation > + void _global_column_simplification( const index col_idx + , boundary_matrix< Representation >& boundary_matrix + , const std::vector< index >& lowest_one_lookup + , const std::vector< column_type >& column_type + , const std::vector< char >& is_active + , std::vector< index >& temp_col ) + { + temp_col.clear(); + while( !boundary_matrix.is_empty( col_idx ) ) { + index cur_row = boundary_matrix.get_max_index( col_idx ); + switch( column_type[ cur_row ] ) { + case GLOBAL: + temp_col.push_back( cur_row ); + boundary_matrix.remove_max( col_idx ); + break; + case LOCAL_NEGATIVE: + boundary_matrix.remove_max( col_idx ); + break; + case LOCAL_POSITIVE: + if( is_active[ lowest_one_lookup[ cur_row ] ] ) + boundary_matrix.add_to( lowest_one_lookup[ cur_row ], col_idx ); + else + boundary_matrix.remove_max( col_idx ); + break; + } + } + std::reverse( temp_col.begin(), temp_col.end() ); + boundary_matrix.set_col( col_idx, temp_col ); + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h new file mode 100644 index 00000000..2047cafd --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h @@ -0,0 +1,55 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../boundary_matrix.h" + +namespace phat { + class row_reduction { + public: + template< typename Representation > + void operator() ( boundary_matrix< Representation >& boundary_matrix ) { + + const index nr_columns = boundary_matrix.get_num_cols(); + std::vector< std::vector< index > > lowest_one_lookup( nr_columns ); + + for( index cur_col = nr_columns - 1; cur_col >= 0; cur_col-- ) { + if( !boundary_matrix.is_empty( cur_col ) ) + lowest_one_lookup[ boundary_matrix.get_max_index( cur_col ) ].push_back( cur_col ); + + if( !lowest_one_lookup[ cur_col ].empty() ) { + boundary_matrix.clear( cur_col ); + std::vector< index >& cols_with_cur_lowest = lowest_one_lookup[ cur_col ]; + index source = *min_element( cols_with_cur_lowest.begin(), cols_with_cur_lowest.end() ); + for( index idx = 0; idx < (index)cols_with_cur_lowest.size(); idx++ ) { + index target = cols_with_cur_lowest[ idx ]; + if( target != source && !boundary_matrix.is_empty( target ) ) { + boundary_matrix.add_to( source, target ); + if( !boundary_matrix.is_empty( target ) ) { + index lowest_one_of_target = boundary_matrix.get_max_index( target ); + lowest_one_lookup[ lowest_one_of_target ].push_back( target ); + } + } + } + } + } + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h new file mode 100644 index 00000000..b2c91a85 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h @@ -0,0 +1,45 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../boundary_matrix.h" + +namespace phat { + class standard_reduction { + public: + template< typename Representation > + void operator() ( boundary_matrix< Representation >& boundary_matrix ) { + + const index nr_columns = boundary_matrix.get_num_cols(); + std::vector< index > lowest_one_lookup( nr_columns, -1 ); + + for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { + index lowest_one = boundary_matrix.get_max_index( cur_col ); + while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { + boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); + lowest_one = boundary_matrix.get_max_index( cur_col ); + } + if( lowest_one != -1 ) { + lowest_one_lookup[ lowest_one ] = cur_col; + } + } + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h new file mode 100644 index 00000000..1bdd8de2 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h @@ -0,0 +1,50 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../boundary_matrix.h" + +namespace phat { + class twist_reduction { + public: + template< typename Representation > + void operator () ( boundary_matrix< Representation >& boundary_matrix ) { + + const index nr_columns = boundary_matrix.get_num_cols(); + std::vector< index > lowest_one_lookup( nr_columns, -1 ); + + for( index cur_dim = boundary_matrix.get_max_dim(); cur_dim >= 1 ; cur_dim-- ) { + for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { + if( boundary_matrix.get_dim( cur_col ) == cur_dim ) { + index lowest_one = boundary_matrix.get_max_index( cur_col ); + while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { + boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); + lowest_one = boundary_matrix.get_max_index( cur_col ); + } + if( lowest_one != -1 ) { + lowest_one_lookup[ lowest_one ] = cur_col; + boundary_matrix.clear( lowest_one ); + } + } + } + } + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h b/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h new file mode 100644 index 00000000..941537da --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h @@ -0,0 +1,336 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "helpers/misc.h" +#include "representations/bit_tree_pivot_column.h" + +// interface class for the main data structure -- implementations of the interface can be found in ./representations +namespace phat { + template< class Representation = bit_tree_pivot_column > + class boundary_matrix + { + + protected: + Representation rep; + + // interface functions -- actual implementation and complexity depends on chosen @Representation template + public: + // get overall number of columns in boundary_matrix + index get_num_cols() const { return rep._get_num_cols(); } + + // set overall number of columns in boundary_matrix + void set_num_cols( index nr_of_columns ) { rep._set_num_cols( nr_of_columns ); } + + // get dimension of given index + dimension get_dim( index idx ) const { return rep._get_dim( idx ); } + + // set dimension of given index + void set_dim( index idx, dimension dim ) { rep._set_dim( idx, dim ); } + + // replaces content of @col with boundary of given index + void get_col( index idx, column& col ) const { rep._get_col( idx, col ); } + + // set column @idx to the values contained in @col + void set_col( index idx, const column& col ) { rep._set_col( idx, col ); } + + // true iff boundary of given column is empty + bool is_empty( index idx ) const { return rep._is_empty( idx ); } + + // largest index of given column (new name for lowestOne()) + index get_max_index( index idx ) const { return rep._get_max_index( idx ); } + + // removes maximal index from given column + void remove_max( index idx ) { rep._remove_max( idx ); } + + // adds column @source to column @target' + void add_to( index source, index target ) { rep._add_to( source, target ); } + + // clears given column + void clear( index idx ) { rep._clear( idx ); } + + // syncronizes all internal data structures -- has to be called before and after any multithreaded access! + void sync() { rep._sync(); } + + // info functions -- independent of chosen 'Representation' + public: + // maximal dimension + dimension get_max_dim() const { + dimension cur_max_dim = 0; + for( index idx = 0; idx < get_num_cols(); idx++ ) + cur_max_dim = get_dim( idx ) > cur_max_dim ? get_dim( idx ) : cur_max_dim; + return cur_max_dim; + } + + // number of nonzero rows for given column @idx + index get_num_rows( index idx ) const { + column cur_col; + get_col( idx, cur_col ); + return cur_col.size(); + } + + // maximal number of nonzero rows of all columns + index get_max_col_entries() const { + index max_col_entries = -1; + const index nr_of_columns = get_num_cols(); + for( index idx = 0; idx < nr_of_columns; idx++ ) + max_col_entries = get_num_rows( idx ) > max_col_entries ? get_num_rows( idx ) : max_col_entries; + return max_col_entries; + } + + // maximal number of nonzero cols of all rows + index get_max_row_entries() const { + size_t max_row_entries = 0; + const index nr_of_columns = get_num_cols(); + std::vector< std::vector< index > > transposed_matrix( nr_of_columns ); + column temp_col; + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + get_col( cur_col, temp_col ); + for( index idx = 0; idx < (index)temp_col.size(); idx++) + transposed_matrix[ temp_col[ idx ] ].push_back( cur_col ); + } + for( index idx = 0; idx < nr_of_columns; idx++ ) + max_row_entries = transposed_matrix[ idx ].size() > max_row_entries ? transposed_matrix[ idx ].size() : max_row_entries; + return max_row_entries; + } + + // overall number of entries in the matrix + index get_num_entries() const { + index number_of_nonzero_entries = 0; + const index nr_of_columns = get_num_cols(); + for( index idx = 0; idx < nr_of_columns; idx++ ) + number_of_nonzero_entries += get_num_rows( idx ); + return number_of_nonzero_entries; + } + + // operators / constructors + public: + boundary_matrix() {}; + + template< class OtherRepresentation > + boundary_matrix( const boundary_matrix< OtherRepresentation >& other ) { + *this = other; + } + + template< typename OtherRepresentation > + bool operator==( const boundary_matrix< OtherRepresentation >& other_boundary_matrix ) const { + const index number_of_columns = this->get_num_cols(); + + if( number_of_columns != other_boundary_matrix.get_num_cols() ) + return false; + + column temp_col; + column other_temp_col; + for( index idx = 0; idx < number_of_columns; idx++ ) { + this->get_col( idx, temp_col ); + other_boundary_matrix.get_col( idx, other_temp_col ); + if( temp_col != other_temp_col || this->get_dim( idx ) != other_boundary_matrix.get_dim( idx ) ) + return false; + } + return true; + } + + template< typename OtherRepresentation > + bool operator!=( const boundary_matrix< OtherRepresentation >& other_boundary_matrix ) const { + return !( *this == other_boundary_matrix ); + } + + template< typename OtherRepresentation > + boundary_matrix< Representation >& operator=( const boundary_matrix< OtherRepresentation >& other ) + { + const index nr_of_columns = other.get_num_cols(); + this->set_num_cols( nr_of_columns ); + column temp_col; + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + this->set_dim( cur_col, other.get_dim( cur_col ) ); + other.get_col( cur_col, temp_col ); + this->set_col( cur_col, temp_col ); + } + + // by convention, always return *this + return *this; + } + + // I/O -- independent of chosen 'Representation' + public: + + // initializes boundary_matrix from (vector, vector) pair -- untested + template< typename index_type, typename dimemsion_type > + void load_vector_vector( const std::vector< std::vector< index_type > >& input_matrix, const std::vector< dimemsion_type >& input_dims ) { + const index nr_of_columns = (index)input_matrix.size(); + this->set_num_cols( nr_of_columns ); + column temp_col; + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + this->set_dim( cur_col, (dimension)input_dims[ cur_col ] ); + + index num_rows = input_matrix[ cur_col ].size(); + temp_col.resize( num_rows ); + for( index cur_row = 0; cur_row < num_rows; cur_row++ ) + temp_col[ cur_row ] = (index)input_matrix[ cur_col ][ cur_row ]; + this->set_col( cur_col, temp_col ); + } + } + + template< typename index_type, typename dimemsion_type > + void save_vector_vector( std::vector< std::vector< index_type > >& output_matrix, std::vector< dimemsion_type >& output_dims ) { + const index nr_of_columns = get_num_cols(); + output_matrix.resize( nr_of_columns ); + output_dims.resize( nr_of_columns ); + column temp_col; + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + output_dims[ cur_col ] = (dimemsion_type)get_dim( cur_col ); + get_col( cur_col, temp_col ); + index num_rows = temp_col.size(); + output_matrix[ cur_col ].clear(); + output_matrix[ cur_col ].resize( num_rows ); + for( index cur_row = 0; cur_row < num_rows; cur_row++ ) + output_matrix[ cur_col ][ cur_row ] = (index_type)temp_col[ cur_row ]; + } + } + + // Loads the boundary_matrix from given file in ascii format + // Format: each line represents a column, first number is dimension, other numbers are the content of the column. + // Ignores empty lines and lines starting with a '#'. + bool load_ascii( std::string filename ) { + // first count number of columns: + std::string cur_line; + std::ifstream dummy( filename .c_str() ); + if( dummy.fail() ) + return false; + + index number_of_columns = 0; + while( getline( dummy, cur_line ) ) { + cur_line.erase(cur_line.find_last_not_of(" \t\n\r\f\v") + 1); + if( cur_line != "" && cur_line[ 0 ] != '#' ) + number_of_columns++; + + } + this->set_num_cols( number_of_columns ); + dummy.close(); + + std::ifstream input_stream( filename.c_str() ); + if( input_stream.fail() ) + return false; + + column temp_col; + index cur_col = -1; + while( getline( input_stream, cur_line ) ) { + cur_line.erase(cur_line.find_last_not_of(" \t\n\r\f\v") + 1); + if( cur_line != "" && cur_line[ 0 ] != '#' ) { + cur_col++; + std::stringstream ss( cur_line ); + + int64_t temp_dim; + ss >> temp_dim; + this->set_dim( cur_col, (dimension) temp_dim ); + + int64_t temp_index; + temp_col.clear(); + while( ss.good() ) { + ss >> temp_index; + temp_col.push_back( (index)temp_index ); + } + std::sort( temp_col.begin(), temp_col.end() ); + this->set_col( cur_col, temp_col ); + } + } + + input_stream.close(); + return true; + } + + // Saves the boundary_matrix to given file in ascii format + // Format: each line represents a column, first number is dimension, other numbers are the content of the column + bool save_ascii( std::string filename ) { + std::ofstream output_stream( filename.c_str() ); + if( output_stream.fail() ) + return false; + + const index nr_columns = this->get_num_cols(); + column tempCol; + for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { + output_stream << (int64_t)this->get_dim( cur_col ); + this->get_col( cur_col, tempCol ); + for( index cur_row_idx = 0; cur_row_idx < (index)tempCol.size(); cur_row_idx++ ) + output_stream << " " << tempCol[ cur_row_idx ]; + output_stream << std::endl; + } + + output_stream.close(); + return true; + } + + // Loads boundary_matrix from given file + // Format: nr_columns % dim1 % N1 % row1 row2 % ...% rowN1 % dim2 % N2 % ... + bool load_binary( std::string filename ) { + std::ifstream input_stream( filename.c_str(), std::ios_base::binary | std::ios_base::in ); + if( input_stream.fail() ) + return false; + + int64_t nr_columns; + input_stream.read( (char*)&nr_columns, sizeof( int64_t ) ); + this->set_num_cols( (index)nr_columns ); + + column temp_col; + for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { + int64_t cur_dim; + input_stream.read( (char*)&cur_dim, sizeof( int64_t ) ); + this->set_dim( cur_col, (dimension) cur_dim ); + int64_t nr_rows; + input_stream.read( (char*)&nr_rows, sizeof( int64_t ) ); + temp_col.resize( (std::size_t)nr_rows ); + for( index idx = 0; idx < nr_rows; idx++ ) { + int64_t cur_row; + input_stream.read( (char*)&cur_row, sizeof( int64_t ) ); + temp_col[ idx ] = (index)cur_row; + } + this->set_col( cur_col, temp_col ); + } + + input_stream.close(); + return true; + } + + // Saves the boundary_matrix to given file in binary format + // Format: nr_columns % dim1 % N1 % row1 row2 % ...% rowN1 % dim2 % N2 % ... + bool save_binary( std::string filename ) { + std::ofstream output_stream( filename.c_str(), std::ios_base::binary | std::ios_base::out ); + if( output_stream.fail() ) + return false; + + const int64_t nr_columns = this->get_num_cols(); + output_stream.write( (char*)&nr_columns, sizeof( int64_t ) ); + column tempCol; + for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { + int64_t cur_dim = this->get_dim( cur_col ); + output_stream.write( (char*)&cur_dim, sizeof( int64_t ) ); + this->get_col( cur_col, tempCol ); + int64_t cur_nr_rows = tempCol.size(); + output_stream.write( (char*)&cur_nr_rows, sizeof( int64_t ) ); + for( index cur_row_idx = 0; cur_row_idx < (index)tempCol.size(); cur_row_idx++ ) { + int64_t cur_row = tempCol[ cur_row_idx ]; + output_stream.write( (char*)&cur_row, sizeof( int64_t ) ); + } + } + + output_stream.close(); + return true; + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h b/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h new file mode 100644 index 00000000..f5b04d5a --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h @@ -0,0 +1,69 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "persistence_pairs.h" +#include "boundary_matrix.h" +#include "helpers/dualize.h" +#include "algorithms/twist_reduction.h" + +namespace phat { + + template< typename ReductionAlgorithm, typename Representation > + void compute_persistence_pairs( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { + ReductionAlgorithm reduce; + reduce( boundary_matrix ); + pairs.clear(); + for( index idx = 0; idx < boundary_matrix.get_num_cols(); idx++ ) { + if( !boundary_matrix.is_empty( idx ) ) { + index birth = boundary_matrix.get_max_index( idx ); + index death = idx; + pairs.append_pair( birth, death ); + } + } + } + + template< typename ReductionAlgorithm, typename Representation > + void compute_persistence_pairs_dualized( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { + ReductionAlgorithm reduce; + const index nr_columns = boundary_matrix.get_num_cols(); + dualize( boundary_matrix ); + reduce( boundary_matrix ); + pairs.clear(); + for( index idx = 0; idx < nr_columns; idx++ ) { + if( !boundary_matrix.is_empty( idx ) ) { + index death = nr_columns - 1 - boundary_matrix.get_max_index( idx ); + index birth = nr_columns - 1 - idx; + pairs.append_pair( birth, death ); + } + } + } + + template< typename Representation > + void compute_persistence_pairs( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { + phat::compute_persistence_pairs< twist_reduction >( pairs, boundary_matrix ); + } + + + template< typename Representation > + void compute_persistence_pairs_dualized( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { + compute_persistence_pairs_dualized< twist_reduction >( pairs, boundary_matrix ); + } + +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h new file mode 100644 index 00000000..60caa05c --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h @@ -0,0 +1,63 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "misc.h" +#include "../boundary_matrix.h" + +namespace phat { + template< typename Representation > + void dualize( boundary_matrix< Representation >& boundary_matrix ) { + + std::vector< dimension > dual_dims; + std::vector< std::vector< index > > dual_matrix; + + index nr_of_columns = boundary_matrix.get_num_cols(); + dual_matrix.resize( nr_of_columns ); + dual_dims.resize( nr_of_columns ); + + std::vector< index > dual_sizes( nr_of_columns, 0 ); + + column temp_col; + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + boundary_matrix.get_col( cur_col, temp_col ); + for( index idx = 0; idx < (index)temp_col.size(); idx++) + dual_sizes[ nr_of_columns - 1 - temp_col[ idx ] ]++; + } + + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + dual_matrix[cur_col].reserve(dual_sizes[cur_col]); + } + + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + boundary_matrix.get_col( cur_col, temp_col ); + for( index idx = 0; idx < (index)temp_col.size(); idx++) + dual_matrix[ nr_of_columns - 1 - temp_col[ idx ] ].push_back( nr_of_columns - 1 - cur_col ); + } + + const dimension max_dim = boundary_matrix.get_max_dim(); + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) + dual_dims[ nr_of_columns - 1 - cur_col ] = max_dim - boundary_matrix.get_dim( cur_col ); + + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) + std::reverse( dual_matrix[ cur_col ].begin(), dual_matrix[ cur_col ].end() ); + + boundary_matrix.load_vector_vector( dual_matrix, dual_dims ); + } +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h new file mode 100644 index 00000000..abbf8d53 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h @@ -0,0 +1,74 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +// STL includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// VS2008 and below unfortunately do not support stdint.h +#if defined(_MSC_VER)&& _MSC_VER < 1600 + typedef __int8 int8_t; + typedef unsigned __int8 uint8_t; + typedef __int16 int16_t; + typedef unsigned __int16 uint16_t; + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; +#else + #include +#endif + +// basic types. index can be changed to int32_t to save memory on small instances +namespace phat { + typedef int64_t index; + typedef int8_t dimension; + typedef std::vector< index > column; +} + +// OpenMP (proxy) functions +#if defined _OPENMP + #include +#else + #define omp_get_thread_num() 0 + #define omp_get_max_threads() 1 + #define omp_get_num_threads() 1 + void omp_set_num_threads( int ) {}; + #include + #define omp_get_wtime() (float)clock() / (float)CLOCKS_PER_SEC +#endif + +#include "thread_local_storage.h" + + + diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h new file mode 100644 index 00000000..06e95c20 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h @@ -0,0 +1,52 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "misc.h" + +// should ideally be equal to the cache line size of the CPU +#define PHAT_TLS_SPACING_FACTOR 64 + +// ThreadLocalStorage with some spacing to avoid "false sharing" (see wikipedia) +template< typename T > +class thread_local_storage +{ +public: + + thread_local_storage() : per_thread_storage( omp_get_max_threads() * PHAT_TLS_SPACING_FACTOR ) {}; + + T& operator()() { + return per_thread_storage[ omp_get_thread_num() * PHAT_TLS_SPACING_FACTOR ]; + } + + const T& operator()() const { + return per_thread_storage[ omp_get_thread_num() * PHAT_TLS_SPACING_FACTOR ]; + } + + T& operator[]( int tid ) { + return per_thread_storage[ tid * PHAT_TLS_SPACING_FACTOR ]; + } + + const T& operator[]( int tid ) const { + return per_thread_storage[ tid * PHAT_TLS_SPACING_FACTOR ]; + } + +protected: + std::vector< T > per_thread_storage; +}; diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h b/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h new file mode 100644 index 00000000..f8006353 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h @@ -0,0 +1,151 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "helpers/misc.h" + +namespace phat { + class persistence_pairs { + + protected: + std::vector< std::pair< index, index > > pairs; + + public: + index get_num_pairs() const { + return (index)pairs.size(); + } + + void append_pair( index birth, index death ) { + pairs.push_back( std::make_pair( birth, death ) ); + } + + std::pair< index, index > get_pair( index idx ) const { + return pairs[ idx ]; + } + + void clear() { + pairs.clear(); + } + + void sort() { + std::sort( pairs.begin(), pairs.end() ); + } + + // Loads the persistence pairs from given file in asci format + // Format: nr_pairs % newline % birth1 % death1 % newline % birth2 % death2 % newline ... + bool load_ascii( std::string filename ) { + std::ifstream input_stream( filename.c_str() ); + if( input_stream.fail() ) + return false; + + int64_t nr_pairs; + input_stream >> nr_pairs; + pairs.clear(); + for( index idx = 0; idx < nr_pairs; idx++ ) { + int64_t birth; + input_stream >> birth; + int64_t death; + input_stream >> death; + append_pair( (index)birth, (index)death ); + } + + input_stream.close(); + return true; + } + + // Saves the persistence pairs to given file in binary format + // Format: nr_pairs % newline % birth1 % death1 % newline % birth2 % death2 % newline ... + bool save_ascii( std::string filename ) { + std::ofstream output_stream( filename.c_str() ); + if( output_stream.fail() ) + return false; + + this->sort(); + output_stream << get_num_pairs() << std::endl; + for( std::size_t idx = 0; idx < pairs.size(); idx++ ) { + output_stream << pairs[idx].first << " " << pairs[idx].second << std::endl; + } + + output_stream.close(); + return true; + } + + // Loads the persistence pairs from given file in binary format + // Format: nr_pairs % birth1 % death1 % birth2 % death2 ... + bool load_binary( std::string filename ) { + std::ifstream input_stream( filename.c_str(), std::ios_base::binary | std::ios_base::in ); + if( input_stream.fail() ) + return false; + + int64_t nr_pairs; + input_stream.read( (char*)&nr_pairs, sizeof( int64_t ) ); + for( index idx = 0; idx < nr_pairs; idx++ ) { + int64_t birth; + input_stream.read( (char*)&birth, sizeof( int64_t ) ); + int64_t death; + input_stream.read( (char*)&death, sizeof( int64_t ) ); + append_pair( (index)birth, (index)death ); + } + + input_stream.close(); + return true; + } + + // Saves the persistence pairs to given file in binary format + // Format: nr_pairs % birth1 % death1 % birth2 % death2 ... + bool save_binary( std::string filename ) { + std::ofstream output_stream( filename.c_str(), std::ios_base::binary | std::ios_base::out ); + if( output_stream.fail() ) + return false; + + this->sort(); + int64_t nr_pairs = get_num_pairs(); + output_stream.write( (char*)&nr_pairs, sizeof( int64_t ) ); + for( std::size_t idx = 0; idx < pairs.size(); idx++ ) { + int64_t birth = pairs[ idx ].first; + output_stream.write( (char*)&birth, sizeof( int64_t ) ); + int64_t death = pairs[ idx ].second; + output_stream.write( (char*)&death, sizeof( int64_t ) ); + } + + output_stream.close(); + return true; + } + + bool operator==( persistence_pairs& other_pairs ) { + this->sort(); + other_pairs.sort(); + if( pairs.size() != (std::size_t)other_pairs.get_num_pairs() ) + return false; + + for( index idx = 0; idx < (index)pairs.size(); idx++ ) + if( get_pair( idx ) != other_pairs.get_pair( idx ) ) + return false; + + return true; + } + + bool operator!=( persistence_pairs& other_pairs ) { + return !( *this == other_pairs ); + } + }; + + + +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h new file mode 100644 index 00000000..41104108 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h @@ -0,0 +1,158 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../representations/vector_vector.h" + +namespace phat { + + // Note: We could even make the rep generic in the underlying Const representation + // But I cannot imagine that anything else than vector> would + // make sense + template< typename PivotColumn > + class abstract_pivot_column : public vector_vector { + public: + + protected: + typedef vector_vector Base; + typedef PivotColumn pivot_column; + + // For parallization purposes, it could be more than one full column + mutable thread_local_storage< pivot_column > _pivot_columns; + mutable thread_local_storage< index > pos_of_pivot_columns; + + pivot_column& get_pivot_column() const { + return _pivot_columns(); + } + + bool is_represented_by_pivot_column( index idx ) const { + return pos_of_pivot_columns() == idx; + } + + void unset_pos_of_pivot_column() { + index idx = pos_of_pivot_columns(); + if( idx != -1 ) { + _pivot_columns().get_column_and_clear( this->matrix[ idx ] ); + } + pos_of_pivot_columns() = -1; + } + + void represent_by_pivot_column( index idx ) { + pos_of_pivot_columns() = idx; + get_pivot_column().add_column( matrix[ idx ] ); + } + + public: + + void _set_num_cols( index nr_of_columns ) { + #pragma omp parallel for + for( int tid = 0; tid < omp_get_num_threads(); tid++ ) { + _pivot_columns[ tid ].init( nr_of_columns ); + pos_of_pivot_columns[ tid ] = -1; + } + Base::_set_num_cols( nr_of_columns ); + } + // replaces(!) content of 'col' with boundary of given index + void _get_col( index idx, column& col ) const { + col.clear(); + if( is_represented_by_pivot_column( idx ) ) { + pivot_column& pivot_column = get_pivot_column(); + pivot_column.get_column_and_clear( col ); + pivot_column.add_column( col ); + } else { + Base::_get_col( idx, col ); + } + } + + // true iff boundary of given idx is empty + bool _is_empty( index idx ) const { + return is_represented_by_pivot_column( idx ) ? get_pivot_column().empty() : Base::_is_empty( idx ); + } + + // largest row index of given column idx (new name for lowestOne()) + index _get_max_index( index idx ) const { + if( is_represented_by_pivot_column( idx ) ) { + pivot_column& pivot_column = get_pivot_column(); + if( pivot_column.empty() ) { + return -1; + } else { + return pivot_column.max_index(); + } + } else { + return Base::_get_max_index( idx ); + } + } + + // adds column 'source' to column 'target' + void _add_to( index source, index target ) { + if( !is_represented_by_pivot_column( target ) ) { + unset_pos_of_pivot_column(); + represent_by_pivot_column( target ); + } + get_pivot_column().add_column( matrix[source] ); + } + + // clears given column + void _clear( index idx ) { + if( is_represented_by_pivot_column( idx ) ) { + column dummy; + get_pivot_column().get_column_and_clear(dummy); + } else { + Base::_clear( idx ); + } + } + + void _set_col( index idx, const column& col ) { + if( is_represented_by_pivot_column( idx ) ) { + column dummy; + pivot_column& pivot_column = get_pivot_column(); + pivot_column.get_column_and_clear( dummy ); + pivot_column.add_column( col ); + } else { + Base::_set_col( idx, col ); + } + } + + // removes the maximal index of a column + void _remove_max( index idx ) { + _toggle( idx, _get_max_index( idx ) ); + } + + //// toggles given index pair + void _toggle( index col_idx, index row_idx ) { + if( !is_represented_by_pivot_column( col_idx ) ) { + unset_pos_of_pivot_column(); + represent_by_pivot_column( col_idx ); + } + get_pivot_column().add_index( row_idx ); + } + + // syncronizes all data structures (essential for openmp stuff) + // has to be called before and after any multithreaded access! + void _sync() { + #pragma omp parallel for + for( int tid = 0; tid < omp_get_num_threads(); tid++ ) + unset_pos_of_pivot_column(); + } + + }; +} + + diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h new file mode 100644 index 00000000..34366d6a --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h @@ -0,0 +1,169 @@ +/* Copyright 2013 IST Austria + Contributed by: Hubert Wagner + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../representations/abstract_pivot_column.h" + +namespace phat { + + // This is a bitset indexed with a 64-ary tree. Each node in the index + // has 64 bits; i-th bit says that the i-th subtree is non-empty. + // Supports practically O(1), inplace, zero-allocation: insert, remove, max_element + // and clear in O(number of ones in the bitset). + // 'add_index' is still the real bottleneck in practice. + class bit_tree_column + { + size_t offset; // data[i + offset] = ith block of the data-bitset + typedef uint64_t block_type; + std::vector< block_type > data; + + // this static is not a problem with OMP, it's initialized just after program starts + static const size_t debrujin_magic_table[64]; + + enum { block_size_in_bits = 64 }; + enum { block_shift = 6 }; + + // Some magic: http://graphics.stanford.edu/~seander/bithacks.html + // Gets the position of the rightmost bit of 'x'. 0 means the most significant bit. + // (-x)&x isolates the rightmost bit. + // The whole method is much faster than calling log2i, and very comparable to using ScanBitForward/Reverse intrinsic, + // which should be one CPU instruction, but is not portable. + size_t rightmost_pos(const block_type value) const + { + return 64 - 1 - debrujin_magic_table[((value & (-(int64_t)value))*0x07EDD5E59A4E28C2) >> 58]; + } + + public: + + void init(index num_cols) + { + int64_t n = 1; // in case of overflow + int64_t bottom_blocks_needed = (num_cols+block_size_in_bits-1)/block_size_in_bits; + int64_t upper_blocks = 1; + + // How many blocks/nodes of index needed to index the whole bitset? + while(n * block_size_in_bits < bottom_blocks_needed) + { + n *= block_size_in_bits; + upper_blocks += n; + } + + offset = upper_blocks; + data.resize(upper_blocks + bottom_blocks_needed, 0); + } + + index max_index() const + { + if (!data[0]) + return -1; + + const size_t size = data.size(); + size_t n = 0; + + while(true) + { + const block_type val = data[n]; + const size_t index = rightmost_pos(val); + const size_t newn = (n << block_shift) + index + 1; + + if (newn >= size) + { + const size_t bottom_index = n - offset; + return (bottom_index << block_shift) + index; + } + + n = newn; + } + + return -1; + } + + bool empty() const + { + return data[0] == 0; + } + + void add_index(const size_t entry) + { + const block_type ONE = 1; + const block_type block_modulo_mask = ((ONE << block_shift) - 1); + size_t index_in_level = entry >> block_shift; + size_t address = index_in_level + offset; + size_t index_in_block = entry & block_modulo_mask; + + block_type mask = (ONE << (block_size_in_bits - index_in_block - 1)); + + while(true) + { + data[address]^=mask; + + // First we check if we reached the root. + // Also, if anyone else was in this block, we don't need to update the path up. + if (!address || (data[address] & ~mask)) + return; + + index_in_block = index_in_level & block_modulo_mask; + index_in_level >>= block_shift; + --address; + address >>= block_shift; + mask = (ONE << (block_size_in_bits - index_in_block - 1)); + } + } + + void get_column_and_clear(column &out) + { + out.clear(); + while(true) + { + index mx = this->max_index(); + if (mx == -1) + break; + out.push_back(mx); + add_index(mx); + } + + std::reverse(out.begin(), out.end()); + } + + void add_column(const column &col) + { + for (size_t i = 0; i < col.size(); ++i) + { + add_index(col[i]); + } + } + + bool empty() { + return !data[0]; + } + }; + + const size_t bit_tree_column::debrujin_magic_table[64] = { + 63, 0, 58, 1, 59, 47, 53, 2, + 60, 39, 48, 27, 54, 33, 42, 3, + 61, 51, 37, 40, 49, 18, 28, 20, + 55, 30, 34, 11, 43, 14, 22, 4, + 62, 57, 46, 52, 38, 26, 32, 41, + 50, 36, 17, 19, 29, 10, 13, 21, + 56, 45, 25, 31, 35, 16, 9, 12, + 44, 24, 15, 8, 23, 7, 6, 5}; + + typedef abstract_pivot_column bit_tree_pivot_column; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h new file mode 100644 index 00000000..9e0c348d --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h @@ -0,0 +1,81 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include +#include + +namespace phat { + class full_column { + + protected: + std::priority_queue< index > m_history; + std::vector< char > m_isInHistory; + std::vector< char > m_data; + + public: + void init( const index total_size ) { + m_data.resize( total_size, false ); + m_isInHistory.resize( total_size, false ); + } + + void add_column( const column& col ) { + for( index idx = 0; idx < (index) col.size(); idx++ ) { + add_index( col[ idx ] ); + } + } + void add_index( const index idx ) { + if( !m_isInHistory[ idx ] ) { + m_history.push( idx ); + m_isInHistory[ idx ] = true; + } + + m_data[ idx ] = !m_data[ idx ]; + } + + index max_index() { + while( m_history.size() > 0 ) { + index topIndex = m_history.top(); + if( m_data[ topIndex ] ) { + return topIndex; + } else { + m_history.pop(); + m_isInHistory[ topIndex ] = false; + } + } + + return -1; + } + + void get_column_and_clear( column& col ) { + col.clear(); + while( !empty() ) { + col.push_back( max_index() ); + add_index( max_index() ); + } + std::reverse( col.begin(), col.end() ); + } + + bool empty() { + return (max_index() == -1); + } + }; + + typedef abstract_pivot_column< full_column > full_pivot_column; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h new file mode 100644 index 00000000..c851a2b5 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h @@ -0,0 +1,62 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include +#include + +namespace phat { + class sparse_column { + + protected: + std::set< index > m_data; + + public: + void init( const index total_size ) { + m_data.clear(); + } + + void add_column( const column& col ) { + for( index idx = 0; idx < (index) col.size(); idx++ ) + add_index( col[ idx ] ); + } + + void add_index( const index idx ) { + std::pair< std::set< index >::iterator, bool > result = m_data.insert( idx ); + if( result.second == false ) + m_data.erase( result.first ); + } + + index max_index() { + return m_data.empty() ? -1 : *m_data.rbegin(); + } + + void get_column_and_clear( column& col ) { + col.clear(); + col.assign( m_data.begin(), m_data.end() ); + m_data.clear(); + } + + bool empty() { + return m_data.empty(); + } + }; + + typedef abstract_pivot_column< sparse_column > sparse_pivot_column; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h new file mode 100644 index 00000000..38e3090c --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h @@ -0,0 +1,98 @@ +/* Copyright 2013 IST Austria + Contributed by: Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include + +namespace phat { + class vector_list { + + protected: + typedef std::list< index > internal_column; + std::vector< dimension > dims; + std::vector< internal_column > matrix; + + public: + // overall number of cells in boundary_matrix + index _get_num_cols() const { + return (index)matrix.size(); + } + void _set_num_cols( index nr_of_columns ) { + dims.resize( nr_of_columns ); + matrix.resize( nr_of_columns ); + } + + // dimension of given index + dimension _get_dim( index idx ) const { + return dims[ idx ]; + } + void _set_dim( index idx, dimension dim ) { + dims[ idx ] = dim; + } + + // replaces(!) content of 'col' with boundary of given index + void _get_col( index idx, column& col ) const { + col.clear(); + col.reserve( matrix[idx].size() ); + std::copy (matrix[idx].begin(), matrix[idx].end(), std::back_inserter(col) ); + } + + void _set_col( index idx, const column& col ) { + matrix[ idx ].clear(); + matrix[ idx ].resize( col.size() ); + std::copy (col.begin(), col.end(), matrix[ idx ].begin() ); + } + + // true iff boundary of given idx is empty + bool _is_empty( index idx ) const { + return matrix[ idx ].empty(); + } + + // largest row index of given column idx (new name for lowestOne()) + index _get_max_index( index idx ) const { + return matrix[ idx ].empty() ? -1 : *matrix[ idx ].rbegin(); + } + + // removes the maximal index of a column + void _remove_max( index idx ) { + internal_column::iterator it = matrix[ idx ].end(); + it--; + matrix[ idx ].erase( it ); + } + + // clears given column + void _clear( index idx ) { + matrix[ idx ].clear(); + } + + // syncronizes all data structures (essential for openmp stuff) + void _sync() {} + + // adds column 'source' to column 'target' + void _add_to( index source, index target ) { + internal_column& source_col = matrix[ source ]; + internal_column& target_col = matrix[ target ]; + internal_column temp_col; + target_col.swap( temp_col ); + std::set_symmetric_difference( temp_col.begin(), temp_col.end(), + source_col.begin(), source_col.end(), + std::back_inserter( target_col ) ); + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h new file mode 100644 index 00000000..dadf1b34 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h @@ -0,0 +1,100 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include + +namespace phat { + class vector_set { + + protected: + typedef std::set< index > internal_column; + std::vector< dimension > dims; + std::vector< internal_column > matrix; + + public: + // overall number of cells in boundary_matrix + index _get_num_cols() const { + return (index)matrix.size(); + } + void _set_num_cols( index nr_of_columns ) { + dims.resize( nr_of_columns ); + matrix.resize( nr_of_columns ); + } + + // dimension of given index + dimension _get_dim( index idx ) const { + return dims[ idx ]; + } + void _set_dim( index idx, dimension dim ) { + dims[ idx ] = dim; + } + + // replaces(!) content of 'col' with boundary of given index + void _get_col( index idx, column& col ) const { + col.clear(); + col.reserve( matrix[idx].size() ); + std::copy (matrix[idx].begin(), matrix[idx].end(), std::back_inserter(col) ); + } + void _set_col( index idx, const column& col ) { + matrix[ idx ].clear(); + matrix[ idx ].insert( col.begin(), col.end() ); + } + + // true iff boundary of given idx is empty + bool _is_empty( index idx ) const { + return matrix[ idx ].empty(); + } + + // largest row index of given column idx (new name for lowestOne()) + index _get_max_index( index idx ) const { + return matrix[ idx ].empty() ? -1 : *matrix[ idx ].rbegin(); + } + + // removes the maximal index of a column + void _remove_max( index idx ) { + internal_column::iterator it = matrix[ idx ].end(); + it--; + matrix[ idx ].erase( it ); + } + + // clears given column + void _clear( index idx ) { + matrix[ idx ].clear(); + } + + // syncronizes all data structures (essential for openmp stuff) + void _sync() {} + + // adds column 'source' to column 'target' + void _add_to( index source, index target ) { + for( internal_column::iterator it = matrix[ source ].begin(); it != matrix[ source ].end(); it++ ) + _toggle( target, *it ); + } + + //// toggles given index pair + void _toggle( index col_idx, index row_idx ) { + internal_column& col = matrix[ col_idx ]; + std::pair< internal_column::iterator, bool > result = col.insert( row_idx ); + if( !result.second ) { + col.erase( result.first ); + } + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h new file mode 100644 index 00000000..efe8de4d --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h @@ -0,0 +1,93 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" + +namespace phat { + class vector_vector { + + protected: + std::vector< dimension > dims; + std::vector< column > matrix; + + thread_local_storage< column > temp_column_buffer; + + public: + // overall number of cells in boundary_matrix + index _get_num_cols() const { + return (index)matrix.size(); + } + void _set_num_cols( index nr_of_columns ) { + dims.resize( nr_of_columns ); + matrix.resize( nr_of_columns ); + } + + // dimension of given index + dimension _get_dim( index idx ) const { + return dims[ idx ]; + } + void _set_dim( index idx, dimension dim ) { + dims[ idx ] = dim; + } + + // replaces(!) content of 'col' with boundary of given index + void _get_col( index idx, column& col ) const { + col = matrix[ idx ]; + } + void _set_col( index idx, const column& col ) { + matrix[ idx ] = col; + } + + // true iff boundary of given idx is empty + bool _is_empty( index idx ) const { + return matrix[ idx ].empty(); + } + + // largest row index of given column idx (new name for lowestOne()) + index _get_max_index( index idx ) const { + return matrix[ idx ].empty() ? -1 : matrix[ idx ].back(); + } + + // removes the maximal index of a column + void _remove_max( index idx ) { + matrix[ idx ].pop_back(); + } + + // clears given column + void _clear( index idx ) { + matrix[ idx ].clear(); + } + + // syncronizes all data structures (essential for openmp stuff) + void _sync() {} + + // adds column 'source' to column 'target' + void _add_to( index source, index target ) { + column& source_col = matrix[ source ]; + column& target_col = matrix[ target ]; + column& temp_col = temp_column_buffer(); + temp_col.clear(); + std::set_symmetric_difference( target_col.begin(), target_col.end(), + source_col.begin(), source_col.end(), + std::back_inserter( temp_col ) ); + target_col.swap( temp_col ); + } + }; +} diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index 4235761f..968483a3 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -310,7 +310,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { dimensions.push_back(3); Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + for (size_t i = 0; i != increasing.size(); ++i) { std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { BOOST_CHECK(boundaries[i][j] == bd[j]); @@ -423,7 +423,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { coboundaryElements.push_back(41); coboundaryElements.push_back(47); size_t number = 0; - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + for (size_t i = 0; i != increasing.size(); ++i) { std::vector< size_t > bd = increasing.get_coboundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { BOOST_CHECK(coboundaryElements[number] == bd[j]); @@ -502,7 +502,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { dim.push_back(1); dim.push_back(0); - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + for (size_t i = 0; i != increasing.size(); ++i) { BOOST_CHECK(increasing.get_dimension_of_a_cell(i) == dim[i]); } } @@ -726,7 +726,7 @@ BOOST_AUTO_TEST_CASE(boudary_operator_2d_bitmap_with_periodic_bcond) { boundaries.push_back( boundary14 ); boundaries.push_back( boundary15 ); - for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) { + for (size_t i = 0; i != cmplx.size(); ++i) { std::vector< size_t > bd = cmplx.get_boundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { BOOST_CHECK(boundaries[i][j] == bd[j]); @@ -826,7 +826,7 @@ BOOST_AUTO_TEST_CASE(coboudary_operator_2d_bitmap_with_periodic_bcond) { coboundaries.push_back( coboundary14 ); coboundaries.push_back( coboundary15 ); - for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) { + for (size_t i = 0; i != cmplx.size(); ++i) { std::vector< size_t > cbd = cmplx.get_coboundary_of_a_cell(i); for (size_t j = 0; j != cbd.size(); ++j) { BOOST_CHECK(coboundaries[i][j] == cbd[j]); @@ -879,7 +879,7 @@ BOOST_AUTO_TEST_CASE(bitmap_2d_with_periodic_bcond_filtration) { filtration.push_back(3);//15 - for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) + for (size_t i = 0; i != cmplx.size(); ++i) { BOOST_CHECK( filtration[i] == cmplx.get_cell_data(i) ); } -- cgit v1.2.3 From 904e931e2938ed3a5b526711b073c957b938ae63 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 9 Feb 2016 14:04:23 +0000 Subject: Doxygen fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1009 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 490dcfd0ca24df97b9bf7735fa167ef844d49b71 --- .../doc/Gudhi_Cubical_Complex_doc.h | 11 +- .../include/gudhi/Bitmap_cubical_complex.h | 117 +++++++++++---------- 2 files changed, 68 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index c06678a1..00b39f01 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -36,7 +36,7 @@ namespace Cubical_complex * @{ * -*Cubical complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. +*Bitmap_cubical_complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. * * An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} \f$. The first one is called non-degenerate, while the second one is \a degenerate interval. A boundary of a elementary *interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of non-degenerate elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerate elementary interval. An elementary cube \f$ C \f$ is a @@ -93,7 +93,7 @@ namespace Cubical_complex 5 \endverbatim -\section Periodic boundary conditions +\section PeriodicBoundaryConditions Periodic boundary conditions Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times I_n \f$ be a box that is decomposed with a cubical complex \f$ \mathcal{K} \f$. Imposing periodic boundary conditions in the direction i, means that the left and the right side of a complex \f$ \mathcal{K} \f$ are considered the same. In particular, if for a bitmap \f$ \mathcal{K} \f$ periodic boundary conditions are imposed in all directions, then complex @@ -106,8 +106,8 @@ in this direction have to be multiplied by -1. For instance: -3 3 1 -2 -3 +4 +6 8 20 4 @@ -118,6 +118,9 @@ in this direction have to be multiplied by -1. For instance: Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. + * \section BitmapExamples Examples + * End user programs are available in example/Bitmap_cubical_complex folder. + */ /** @} */ // end defgroup cubical_complex diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 82ea8672..b599a0d9 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -23,7 +23,7 @@ #pragma once #include -#include "Bitmap_cubical_complex_base.h" +#include "Bitmap_cubical_complex_base.h" #include "Bitmap_cubical_complex_periodic_boundary_conditions_base.h" @@ -35,10 +35,15 @@ namespace Cubical_complex { //global variable, was used just for debugging. -const bool globalDbg = false; - +const bool globalDbg = false; + template class is_before_in_filtration; +/** + *@class Bitmap_cubical_complex + *@brief Cubical complex represented as a bitmap. + *@ingroup cubical_complex + */ template class Bitmap_cubical_complex : public T { @@ -47,8 +52,8 @@ public: //Typedefs and typenames //*********************************************// typedef size_t Simplex_key; - typedef typename T::filtration_type Filtration_value; - typedef Simplex_key Simplex_handle; + typedef typename T::filtration_type Filtration_value; + typedef Simplex_key Simplex_handle; //*********************************************// @@ -65,7 +70,7 @@ public: **/ Bitmap_cubical_complex( const char* perseus_style_file ): T(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) - { + { //clock_t begin = clock(); if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) @@ -75,7 +80,7 @@ public: //we initialize this only once, in each constructor, when the bitmap is constructed. //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. - this->initialize_simplex_associated_to_key(); + this->initialize_simplex_associated_to_key(); //cerr << "Time of running Bitmap_cubical_complex( const char* perseus_style_file ) constructor : " << double(clock() - begin) / CLOCKS_PER_SEC << endl; } @@ -97,12 +102,12 @@ public: //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. this->initialize_simplex_associated_to_key(); - } - + } + /** * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells * in the following directions and vector of element of a type T::filtration_type - * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. + * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. * If the position i on this vector is true, then we impose periodic boundary conditions in this direction. **/ Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ): @@ -117,7 +122,7 @@ public: //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. this->initialize_simplex_associated_to_key(); - } + } //*********************************************// @@ -135,10 +140,10 @@ public: * Returns a Simplex_handle to a cube that do not exist in this complex. **/ static Simplex_handle null_simplex() - { + { if ( globalDbg ){cerr << "Simplex_handle null_simplex()\n";} return std::numeric_limits::max(); - } + } /** @@ -184,10 +189,10 @@ public: **/ Simplex_key key(Simplex_handle sh)const { - if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} - if ( sh != std::numeric_limits::max() ) - { - return this->key_associated_to_simplex[sh]; + if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} + if ( sh != std::numeric_limits::max() ) + { + return this->key_associated_to_simplex[sh]; } return this->null_key(); } @@ -197,10 +202,10 @@ public: **/ Simplex_handle simplex(Simplex_key key) { - if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} - if ( key != std::numeric_limits::max() ) - { - return this->simplex_associated_to_key[ key ]; + if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} + if ( key != std::numeric_limits::max() ) + { + return this->simplex_associated_to_key[ key ]; } return null_simplex(); } @@ -210,8 +215,8 @@ public: **/ void assign_key(Simplex_handle sh, Simplex_key key) { - if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} - if ( key == std::numeric_limits::max() ) return; + if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} + if ( key == std::numeric_limits::max() ) return; this->key_associated_to_simplex[sh] = key; this->simplex_associated_to_key[key] = sh; } @@ -231,10 +236,10 @@ public: /** * Boundary_simplex_range class provides ranges for boundary iterators. - **/ - typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; - typedef typename std::vector< Simplex_handle > Boundary_simplex_range; - + **/ + typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; + typedef typename std::vector< Simplex_handle > Boundary_simplex_range; + /** @@ -301,8 +306,8 @@ public: { //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. - public: - typedef Filtration_simplex_iterator const_iterator; + public: + typedef Filtration_simplex_iterator const_iterator; typedef Filtration_simplex_iterator iterator; Filtration_simplex_range(Bitmap_cubical_complex* b):b(b){}; Filtration_simplex_iterator begin() @@ -328,19 +333,19 @@ public: /** * boundary_simplex_range creates an object of a Boundary_simplex_range class * that provides ranges for the Boundary_simplex_iterator. - **/ - Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) - { - /* - std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh); - Boundary_simplex_range result( bdry.size() ); - for ( size_t i = 0 ; i != bdry.size() ; ++i ) - { - result[i] = this->simplex_associated_to_key[ bdry[i] ]; - } - return result; - */ - return this->get_boundary_of_a_cell(sh); + **/ + Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) + { + /* + std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh); + Boundary_simplex_range result( bdry.size() ); + for ( size_t i = 0 ; i != bdry.size() ; ++i ) + { + result[i] = this->simplex_associated_to_key[ bdry[i] ]; + } + return result; + */ + return this->get_boundary_of_a_cell(sh); } /** @@ -463,8 +468,8 @@ public: { //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. - public: - typedef Skeleton_simplex_iterator const_iterator; + public: + typedef Skeleton_simplex_iterator const_iterator; typedef Skeleton_simplex_iterator iterator; Skeleton_simplex_range(Bitmap_cubical_complex* b , unsigned dimension):b(b),dimension(dimension){}; Skeleton_simplex_iterator begin() @@ -500,28 +505,28 @@ protected: std::vector< size_t > key_associated_to_simplex; std::vector< size_t > simplex_associated_to_key; };//Bitmap_cubical_complex - + template void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { if ( globalDbg ) { cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; - } - this->simplex_associated_to_key = std::vector( this->data.size() ); + } + this->simplex_associated_to_key = std::vector( this->data.size() ); std::iota (std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); std::sort( simplex_associated_to_key.begin() , simplex_associated_to_key.end() , - is_before_in_filtration(this) ); - - //we still need to deal here with a key_associated_to_simplex: - for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) - { - this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; + is_before_in_filtration(this) ); + + //we still need to deal here with a key_associated_to_simplex: + for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) + { + this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; } } - - + + template class is_before_in_filtration { @@ -560,4 +565,4 @@ protected: } -} +} -- cgit v1.2.3 From 81d5f63b5107dd8229fd8b8576982d22acb9a57e Mon Sep 17 00:00:00 2001 From: pdlotko Date: Tue, 9 Feb 2016 14:35:03 +0000 Subject: Adding documentation to the bitmap cubical complex with periodic boundary conditions class. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1010 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e1d9516f57be5e824203037b74998ed897741261 --- .../include/gudhi/Bitmap_cubical_complex.h | 7 +- ...cal_complex_periodic_boundary_conditions_base.h | 666 +++++++++++---------- 2 files changed, 361 insertions(+), 312 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index b599a0d9..2ec7594d 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -37,7 +37,12 @@ namespace Cubical_complex //global variable, was used just for debugging. const bool globalDbg = false; -template class is_before_in_filtration; +template class is_before_in_filtration; + +/** +* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex__base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into +* Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template parameter is supposed to be either Bitmap_cubical_complex__base or Bitmap_cubical_complex_periodic_boundary_conditions_base class. +**/ /** *@class Bitmap_cubical_complex diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 38c218dc..f0fd785f 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -1,311 +1,355 @@ -#pragma once -#include -#include "Bitmap_cubical_complex_base.h" - -using namespace std; - -namespace Gudhi -{ - -namespace Cubical_complex -{ - -//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures -//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the -//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base - -template -class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base -{ -public: - //constructors that take an extra parameter: - Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); - - //overwritten methods co compute boundary and coboundary - virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; - std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; - //inline unsigned get_dimension_of_a_cell( size_t cell )const; - -protected: - std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; - void set_up_containers( const std::vector& sizes ) - { - - unsigned multiplier = 1; - for ( size_t i = 0 ; i != sizes.size() ; ++i ) - { - this->sizes.push_back(sizes[i]); - this->multipliers.push_back(multiplier); - - if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) - { - multiplier *= 2*sizes[i]; - } - else - { - multiplier *= 2*sizes[i]+1; - } - } - //std::reverse( this->sizes.begin() , this->sizes.end() ); - this->data = std::vector(multiplier,std::numeric_limits::max()); - this->total_number_of_cells = multiplier; - } - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ); - void construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); -}; - -template -void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; - this->set_up_containers( dimensions ); - - size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) - { - *it = topDimensionalCells[i]; - ++i; - } - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) -{ - - //for Perseus style files: - bool dbg = false; - ifstream inFiltration; - inFiltration.open( perseus_style_file ); - unsigned dimensionOfData; - inFiltration >> dimensionOfData; - - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); - - std::vector sizes; - sizes.reserve( dimensionOfData ); - for ( size_t i = 0 ; i != dimensionOfData ; ++i ) - { - int size_in_this_dimension; - inFiltration >> size_in_this_dimension; - if ( size_in_this_dimension < 0 ) - { - this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; - } - sizes.push_back( abs(size_in_this_dimension) ); - } - this->set_up_containers( sizes ); - - typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_begin(); - - while ( !inFiltration.eof() ) - { - double filtrationLevel; - inFiltration >> filtrationLevel; - if ( inFiltration.eof() )break; - - if ( dbg ) - { - cerr << "Cell of an index : " - << it.compute_index_in_bitmap() - << " and dimension: " - << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) - << " get the value : " << filtrationLevel << endl; - } - *it = filtrationLevel; - ++it; - } - inFiltration.close(); - this->impose_lower_star_filtration(); - -/* - char* filename = (char*)perseus_style_file; - //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; - ifstream file( filename , ios::binary | ios::ate ); - unsigned realSizeOfFile = file.tellg(); - file.close(); - realSizeOfFile = realSizeOfFile/sizeof(T); - - unsigned w, h, d; - - w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); - - T* slice = new T[w*h*d]; - if (slice == NULL) - { - cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; - exit(EXIT_FAILURE); - } - - FILE* fp; - if ((fp=fopen( filename, "rb" )) == NULL ) - { - cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; - exit(1); - } - - clock_t read_begin = clock(); - fread( slice,4,w*h*d,fp ); - fclose(fp); - cerr << "Time of reading the file : " << double(clock() - read_begin) / CLOCKS_PER_SEC << endl; - - - clock_t begin_creation_bitap = clock(); - std::vector data(slice,slice+w*h*d); - delete[] slice; - std::vector< unsigned > sizes; - sizes.push_back(w); - sizes.push_back(w); - sizes.push_back(w); - - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->set_up_containers( sizes ); - - size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) - { - *it = data[i]; - ++i; - } - this->impose_lower_star_filtration(); - cerr << "Time of creation of a bitmap : " << double(clock() - begin_creation_bitap ) / CLOCKS_PER_SEC << endl; -*/ -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ) -{ - std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - - - - - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - -//***********************Methods************************// - -template -std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const -{ - bool dbg = false; - if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} - - std::vector< size_t > boundary_elements; - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. - - if ( position%2 == 1 ) - { - //if there are no periodic boundary conditions in this direction, we do not have to do anything. - if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { - //cerr << "A\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. - if ( position != 2*this->sizes[ i-1 ]-1 ) - { - //cerr << "B\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //cerr << "C\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} - } - } - } - cell1 = cell1%this->multipliers[i-1]; - } - return boundary_elements; -} - -template -std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell( size_t cell )const -{ - std::vector counter = this->compute_counter_for_given_cell( cell ); - std::vector< size_t > coboundary_elements; - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - //if the cell has zero length in this direction, then it will have cbd in this direction. - if ( position%2 == 0 ) - { - if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { - //no periodic boundary conditions in this direction - if ( (counter[i-1] != 0) && (cell > this->multipliers[i-1]) ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - } - if ( (counter[i-1] != 2*this->sizes[i-1]) && (cell + this->multipliers[i-1] < this->data.size()) ) - { - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - } - else - { - //we want to have periodic boundary conditions in this direction - if ( counter[i-1] != 0 ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - else - { - //in this case counter[i-1] == 0. - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); - } - } - } - - cell1 = cell1%this->multipliers[i-1]; - } - return coboundary_elements; -} - - - -}//Cubical_complex -}//namespace Gudhi +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-Saclay (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 . + */ + +#pragma once +#include +#include "Bitmap_cubical_complex_base.h" + +using namespace std; + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures +//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the +//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base + + +/** +* This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are identical to the functions from Bitmap_cubical_complex_base. +* The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell. +*/ +template +class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base +{ +public: + //constructors that take an extra parameter: + /** + * Default constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; + + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of booleans. If at i-th position of this vector there is true value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction i. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the name of Perseus style file as an input. Please consult the documentation about the specification of the file. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of top dimensional cells (ordered lexicographically) and (3) vector of booleans. If at i-th position of this vector there is true value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction i. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); + + //overwritten methods co compute boundary and coboundary + /** + * A version of a function that return boundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; + /** + * A version of a function that return coboundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + virtual std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; +protected: + std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; + void set_up_containers( const std::vector& sizes ) + { + + unsigned multiplier = 1; + for ( size_t i = 0 ; i != sizes.size() ; ++i ) + { + this->sizes.push_back(sizes[i]); + this->multipliers.push_back(multiplier); + + if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) + { + multiplier *= 2*sizes[i]; + } + else + { + multiplier *= 2*sizes[i]+1; + } + } + //std::reverse( this->sizes.begin() , this->sizes.end() ); + this->data = std::vector(multiplier,std::numeric_limits::max()); + this->total_number_of_cells = multiplier; + } + Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells ); + void construct_complex_based_on_top_dimensional_cells( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); +}; + +template +void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers( dimensions ); + + size_t i = 0; + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + *it = topDimensionalCells[i]; + ++i; + } + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed(directions_in_which_periodic_b_cond_are_to_be_imposed); + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) +{ + + //for Perseus style files: + bool dbg = false; + ifstream inFiltration; + inFiltration.open( perseus_style_file ); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); + + std::vector sizes; + sizes.reserve( dimensionOfData ); + for ( size_t i = 0 ; i != dimensionOfData ; ++i ) + { + int size_in_this_dimension; + inFiltration >> size_in_this_dimension; + if ( size_in_this_dimension < 0 ) + { + this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; + } + sizes.push_back( abs(size_in_this_dimension) ); + } + this->set_up_containers( sizes ); + + typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_begin(); + + while ( !inFiltration.eof() ) + { + double filtrationLevel; + inFiltration >> filtrationLevel; + if ( inFiltration.eof() )break; + + if ( dbg ) + { + cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + << " get the value : " << filtrationLevel << endl; + } + *it = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); + +/* + char* filename = (char*)perseus_style_file; + //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; + ifstream file( filename , ios::binary | ios::ate ); + unsigned realSizeOfFile = file.tellg(); + file.close(); + realSizeOfFile = realSizeOfFile/sizeof(T); + + unsigned w, h, d; + + w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); + + T* slice = new T[w*h*d]; + if (slice == NULL) + { + cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; + exit(EXIT_FAILURE); + } + + FILE* fp; + if ((fp=fopen( filename, "rb" )) == NULL ) + { + cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; + exit(1); + } + + clock_t read_begin = clock(); + fread( slice,4,w*h*d,fp ); + fclose(fp); + cerr << "Time of reading the file : " << double(clock() - read_begin) / CLOCKS_PER_SEC << endl; + + + clock_t begin_creation_bitap = clock(); + std::vector data(slice,slice+w*h*d); + delete[] slice; + std::vector< unsigned > sizes; + sizes.push_back(w); + sizes.push_back(w); + sizes.push_back(w); + + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->set_up_containers( sizes ); + + size_t i = 0; + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + *it = data[i]; + ++i; + } + this->impose_lower_star_filtration(); + cerr << "Time of creation of a bitmap : " << double(clock() - begin_creation_bitap ) / CLOCKS_PER_SEC << endl; + */ +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells ) +{ + std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + + + + + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + +//***********************Methods************************// + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const +{ + bool dbg = false; + if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} + + std::vector< size_t > boundary_elements; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/this->multipliers[i-1]; + //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. + + if ( position%2 == 1 ) + { + //if there are no periodic boundary conditions in this direction, we do not have to do anything. + if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { + //cerr << "A\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. + if ( position != 2*this->sizes[ i-1 ]-1 ) + { + //cerr << "B\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //cerr << "C\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} + } + } + } + cell1 = cell1%this->multipliers[i-1]; + } + return boundary_elements; +} + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell( size_t cell )const +{ + std::vector counter = this->compute_counter_for_given_cell( cell ); + std::vector< size_t > coboundary_elements; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/this->multipliers[i-1]; + //if the cell has zero length in this direction, then it will have cbd in this direction. + if ( position%2 == 0 ) + { + if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { + //no periodic boundary conditions in this direction + if ( (counter[i-1] != 0) && (cell > this->multipliers[i-1]) ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + } + if ( (counter[i-1] != 2*this->sizes[i-1]) && (cell + this->multipliers[i-1] < this->data.size()) ) + { + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } + } + else + { + //we want to have periodic boundary conditions in this direction + if ( counter[i-1] != 0 ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } + else + { + //in this case counter[i-1] == 0. + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); + } + } + } + + cell1 = cell1%this->multipliers[i-1]; + } + return coboundary_elements; +} + + + +}//Cubical_complex +}//namespace Gudhi -- cgit v1.2.3 From 2d8cc490a799d991fee29d923c15368c83d24f85 Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 11 Feb 2016 14:17:55 +0000 Subject: A small change in sphere example git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@1015 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4c479a899c1a3686ac53a03affea63bc96208c7c --- src/Witness_complex/example/witness_complex_sphere.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index 1ff35bff..f9d0b5a2 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -90,6 +90,7 @@ int main(int argc, char * const argv[]) { double time = static_cast(end - start) / CLOCKS_PER_SEC; std::cout << "Witness complex for " << nbL << " landmarks took " << time << " s. \n"; + std::cout << "Number of simplices is: " << simplex_tree.num_simplices() << "\n"; l_time.push_back(std::make_pair(nbP, time)); } write_data(l_time, "w_time.dat"); -- cgit v1.2.3 From b7796215d4eac6b4c43ad70998c3737a6527eebb Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 11 Feb 2016 16:05:15 +0000 Subject: Commited Marc's remarks git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@1017 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d87eb82f60f4f943f59622f33521bcdce7873091 --- src/Witness_complex/concept/Simplicial_complex.h | 11 ++--------- .../example/witness_complex_from_file.cpp | 13 +------------ src/Witness_complex/example/witness_complex_sphere.cpp | 10 +++++----- .../include/gudhi/Landmark_choice_by_random_point.h | 6 ++++++ src/Witness_complex/include/gudhi/Witness_complex.h | 18 ++++++------------ src/Witness_complex/test/simple_witness_complex.cpp | 2 +- src/Witness_complex/test/witness_complex_points.cpp | 4 ++-- 7 files changed, 23 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/concept/Simplicial_complex.h b/src/Witness_complex/concept/Simplicial_complex.h index d7f3496d..9e9f2ff8 100644 --- a/src/Witness_complex/concept/Simplicial_complex.h +++ b/src/Witness_complex/concept/Simplicial_complex.h @@ -40,16 +40,11 @@ struct Simplicial_complex { /** Returns a Simplex_hanlde that is different from all simplex handles * of the simplices. */ Simplex_handle null_simplex(); - /** \brief Returns the number of simplices in the complex. - * - * Does not count the empty simplex. */ - size_t num_simplices(); /** \brief Iterator over the simplices of the complex, * in an arbitrary order. * * 'value_type' must be 'Simplex_handle'.*/ - typedef unspecified Complex_simplex_iterator; typedef unspecified Complex_simplex_range; /** @@ -71,19 +66,17 @@ struct Simplicial_complex { */ typedef unspecified Insertion_result_type; - /** \brief Input range of vertices. - * 'value_type' must be 'Vertex_handle'. */ - typedef unspecified Input_vertex_range; - /** \brief Inserts a simplex with vertices from a given range * 'vertex_range' in the simplicial complex. * */ + template< typedef Input_vertex_range > Insertion_result_type insert_simplex(Input_vertex_range const & vertex_range); /** \brief Finds a simplex with vertices given by a range * * If a simplex exists, its Simplex_handle is returned. * Otherwise null_simplex() is returned. */ + template< typedef Input_vertex_range > Simplex_handle find(Input_vertex_range const & vertex_range); }; diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index 77109512..98d1fe9c 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -68,17 +68,6 @@ read_points_cust(std::string file_name, std::vector< std::vector< double > > & p in_file.close(); } -/** Write a gnuplot readable file. - * Data range is a random access range of pairs (arg, value) - */ -template < typename Data_range > -void write_data(Data_range & data, std::string filename) { - std::ofstream ofs(filename, std::ofstream::out); - for (auto entry : data) - ofs << entry.first << ", " << entry.second << "\n"; - ofs.close(); -} - int main(int argc, char * const argv[]) { if (argc != 3) { std::cerr << "Usage: " << argv[0] @@ -109,7 +98,7 @@ int main(int argc, char * const argv[]) { // Compute witness complex start = clock(); - WitnessComplex(knn, simplex_tree, nbL, point_vector[0].size()); + WitnessComplex(knn, nbL, point_vector[0].size(), simplex_tree); end = clock(); std::cout << "Witness complex took " << static_cast(end - start) / CLOCKS_PER_SEC << " s. \n"; diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index f9d0b5a2..fae80d67 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -60,11 +60,11 @@ void write_data(Data_range & data, std::string filename) { int main(int argc, char * const argv[]) { if (argc != 2) { std::cerr << "Usage: " << argv[0] - << " nbL \n"; + << " number_of_landmarks \n"; return 0; } - int nbL = atoi(argv[1]); + int number_of_landmarks = atoi(argv[1]); clock_t start, end; // Construct the Simplex Tree @@ -82,13 +82,13 @@ int main(int argc, char * const argv[]) { // Choose landmarks start = clock(); std::vector > knn; - Gudhi::witness_complex::landmark_choice_by_random_point(point_vector, nbL, knn); + Gudhi::witness_complex::landmark_choice_by_random_point(point_vector, number_of_landmarks, knn); // Compute witness complex - WitnessComplex(knn, simplex_tree, nbL, point_vector[0].size()); + WitnessComplex(knn, number_of_landmarks, point_vector[0].size(), simplex_tree); end = clock(); double time = static_cast(end - start) / CLOCKS_PER_SEC; - std::cout << "Witness complex for " << nbL << " landmarks took " + std::cout << "Witness complex for " << number_of_landmarks << " landmarks took " << time << " s. \n"; std::cout << "Number of simplices is: " << simplex_tree.num_simplices() << "\n"; l_time.push_back(std::make_pair(nbP, time)); diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h index dc364007..617c0258 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h @@ -35,6 +35,12 @@ namespace witness_complex { /** \brief Landmark choice strategy by taking random vertices for landmarks. * \details It chooses nbL distinct landmarks from a random access range `points` * and outputs a matrix {witness}*{closest landmarks} in knn. + * + * The type KNearestNeighbors can be seen as + * Witness_range>, where + * Witness_range and Closest_landmark_range are random access ranges and + * Vertex_handle is the label type of a vertex in a simplicial complex. + * Closest_landmark_range needs to have push_back operation. */ template Point_t; typedef std::vector< Point_t > Point_Vector; - // typedef typename Simplicial_complex::Filtration_value Filtration_value; typedef std::vector< Vertex_handle > typeVectorVertex; typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex; typedef std::pair< Simplex_handle, bool > typePairSimplexBool; @@ -109,9 +108,9 @@ class Witness_complex { */ template< typename KNearestNeighbors > Witness_complex(KNearestNeighbors const & knn, - Simplicial_complex & sc_, int nbL_, - int dim) : nbL(nbL_), sc(sc_) { + int dim, + Simplicial_complex & sc_) : nbL(nbL_), sc(sc_) { // Construction of the active witness list int nbW = knn.size(); typeVectorVertex vv; @@ -120,7 +119,7 @@ class Witness_complex { * it will diminuish in the course of iterations */ ActiveWitnessList active_w; // = new ActiveWitnessList(); - for (int i = 0; i != nbL; ++i) { + for (Vertex_handle i = 0; i != nbL; ++i) { // initial fill of 0-dimensional simplices // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore counter++; @@ -131,9 +130,7 @@ class Witness_complex { int k = 1; /* current dimension in iterative construction */ for (int i = 0; i != nbW; ++i) active_w.push_back(i); - // std::cout << "Successfully added edges" << std::endl; while (!active_w.empty() && k < dim) { - // std::cout << "Started the step k=" << k << std::endl; typename ActiveWitnessList::iterator it = active_w.begin(); while (it != active_w.end()) { typeVectorVertex simplex_vector; @@ -142,7 +139,7 @@ class Witness_complex { if (ok) { for (int i = 0; i != k + 1; ++i) simplex_vector.push_back(knn[*it][i]); - sc.insert_simplex(simplex_vector, 0.0); + sc.insert_simplex(simplex_vector); // TODO(SK) Error if not inserted : normally no need here though it++; } else { @@ -162,9 +159,7 @@ class Witness_complex { */ template bool all_faces_in(KNearestNeighbors const &knn, int witness_id, int k) { - // std::cout << "All face in with the landmark " << inserted_vertex << std::endl; std::vector< Vertex_handle > facet; - // Vertex_handle curr_vh = curr_sh->first; // CHECK ALL THE FACETS for (int i = 0; i != k + 1; ++i) { facet = {}; @@ -175,7 +170,6 @@ class Witness_complex { } // endfor if (sc.find(facet) == sc.null_simplex()) return false; - // std::cout << "++++ finished loop safely\n"; } // endfor return true; } @@ -206,12 +200,12 @@ class Witness_complex { bool is_witnessed = false; typeVectorVertex simplex; int nbV = 0; // number of verticed in the simplex - for (int v : sc.simplex_vertex_range(sh)) + for (Vertex_handle v : sc.simplex_vertex_range(sh)) simplex.push_back(v); nbV = simplex.size(); for (typeVectorVertex w : knn) { bool has_vertices = true; - for (int v : simplex) + for (Vertex_handle v : simplex) if (std::find(w.begin(), w.begin() + nbV, v) == w.begin() + nbV) { has_vertices = false; // break; diff --git a/src/Witness_complex/test/simple_witness_complex.cpp b/src/Witness_complex/test/simple_witness_complex.cpp index 7d44b90c..03df78ee 100644 --- a/src/Witness_complex/test/simple_witness_complex.cpp +++ b/src/Witness_complex/test/simple_witness_complex.cpp @@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE(simple_witness_complex) { knn.push_back({5, 0, 1, 3, 6, 2, 4}); knn.push_back({5, 6, 1, 0, 2, 3, 4}); knn.push_back({1, 6, 0, 5, 2, 3, 4}); - WitnessComplex witnessComplex(knn, complex, 7, 7); + WitnessComplex witnessComplex(knn, 7, 7, complex); BOOST_CHECK(witnessComplex.is_witness_complex(knn, false)); } diff --git a/src/Witness_complex/test/witness_complex_points.cpp b/src/Witness_complex/test/witness_complex_points.cpp index cb1639e1..bd3df604 100644 --- a/src/Witness_complex/test/witness_complex_points.cpp +++ b/src/Witness_complex/test/witness_complex_points.cpp @@ -52,13 +52,13 @@ BOOST_AUTO_TEST_CASE(witness_complex_points) { Simplex_tree complex1; Gudhi::witness_complex::landmark_choice_by_random_point(points, 100, knn); assert(!knn.empty()); - WitnessComplex witnessComplex1(knn, complex1, 100, 3); + WitnessComplex witnessComplex1(knn, 100, 3, complex1); BOOST_CHECK(witnessComplex1.is_witness_complex(knn, b_print_output)); // Second test: furthest choice knn.clear(); Simplex_tree complex2; Gudhi::witness_complex::landmark_choice_by_furthest_point(points, 100, knn); - WitnessComplex witnessComplex2(knn, complex2, 100, 3); + WitnessComplex witnessComplex2(knn, 100, 3, complex2); BOOST_CHECK(witnessComplex2.is_witness_complex(knn, b_print_output)); } -- cgit v1.2.3 From 6496035f0c8232469bf652c1047eeb66645c1bd6 Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 11 Feb 2016 16:07:37 +0000 Subject: Changed concept's name to CamelCase git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@1018 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ddc6e2d57b2dd547407e42da44868d1d0658e57c --- src/Witness_complex/concept/Simplicial_complex.h | 2 +- src/Witness_complex/include/gudhi/Witness_complex.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/concept/Simplicial_complex.h b/src/Witness_complex/concept/Simplicial_complex.h index 9e9f2ff8..74d60388 100644 --- a/src/Witness_complex/concept/Simplicial_complex.h +++ b/src/Witness_complex/concept/Simplicial_complex.h @@ -31,7 +31,7 @@ namespace witness_complex { * for a type to implement a simplicial complex, * used for example to build a 'Witness_complex'. */ -struct Simplicial_complex { +struct SimplicialComplex { /** Handle to specify a simplex. */ typedef unspecified Simplex_handle; /** Handle to specify a vertex. Must be a non-negative integer. */ diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 3e14a623..455e008a 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -52,7 +52,7 @@ namespace witness_complex { \brief Constructs the witness complex for the given set of witnesses and landmarks. \ingroup witness_complex */ -template< class Simplicial_complex> +template< class SimplicialComplex> class Witness_complex { private: struct Active_witness { @@ -81,7 +81,7 @@ class Witness_complex { private: int nbL; // Number of landmarks - Simplicial_complex& sc; // Simplicial complex + SimplicialComplex& sc; // Simplicial complex public: ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -110,7 +110,7 @@ class Witness_complex { Witness_complex(KNearestNeighbors const & knn, int nbL_, int dim, - Simplicial_complex & sc_) : nbL(nbL_), sc(sc_) { + SimplicialComplex & sc_) : nbL(nbL_), sc(sc_) { // Construction of the active witness list int nbW = knn.size(); typeVectorVertex vv; -- cgit v1.2.3 From c9eb5f3526459162fdc241560802b8fa0c5bf6d6 Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 11 Feb 2016 16:08:34 +0000 Subject: now it compiles... git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@1019 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 5b4cd7b1f767b47190a9bf2f6dd7eab2682df6e8 --- src/Witness_complex/include/gudhi/Witness_complex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 455e008a..50058740 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -65,8 +65,8 @@ class Witness_complex { }; private: - typedef typename Simplicial_complex::Simplex_handle Simplex_handle; - typedef typename Simplicial_complex::Vertex_handle Vertex_handle; + typedef typename SimplicialComplex::Simplex_handle Simplex_handle; + typedef typename SimplicialComplex::Vertex_handle Vertex_handle; typedef std::vector< double > Point_t; typedef std::vector< Point_t > Point_Vector; -- cgit v1.2.3 From 1ed10d89ae07c069cf408de2e178962f23723c8b Mon Sep 17 00:00:00 2001 From: pdlotko Date: Sat, 13 Feb 2016 12:21:41 +0000 Subject: removing phat relaed compontns. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1021 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d0c9c23ca3f3a5b2131179949ba80659b13f7777 --- .../example/Compute_persistence_with_phat.cpp | 60 ---- .../include/gudhi/Compute_persistence_with_phat.h | 242 --------------- .../gudhi/phat/algorithms/chunk_reduction.h | 240 --------------- .../include/gudhi/phat/algorithms/row_reduction.h | 55 ---- .../gudhi/phat/algorithms/standard_reduction.h | 45 --- .../gudhi/phat/algorithms/twist_reduction.h | 50 --- .../include/gudhi/phat/boundary_matrix.h | 336 --------------------- .../include/gudhi/phat/compute_persistence_pairs.h | 69 ----- .../include/gudhi/phat/helpers/dualize.h | 63 ---- .../include/gudhi/phat/helpers/misc.h | 74 ----- .../gudhi/phat/helpers/thread_local_storage.h | 52 ---- .../include/gudhi/phat/persistence_pairs.h | 151 --------- .../phat/representations/abstract_pivot_column.h | 158 ---------- .../phat/representations/bit_tree_pivot_column.h | 169 ----------- .../gudhi/phat/representations/full_pivot_column.h | 81 ----- .../phat/representations/sparse_pivot_column.h | 62 ---- .../gudhi/phat/representations/vector_list.h | 98 ------ .../gudhi/phat/representations/vector_set.h | 100 ------ .../gudhi/phat/representations/vector_vector.h | 93 ------ 19 files changed, 2198 deletions(-) delete mode 100644 src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h (limited to 'src') diff --git a/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp b/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp deleted file mode 100644 index f552a094..00000000 --- a/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp +++ /dev/null @@ -1,60 +0,0 @@ - - /* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Saclay (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 - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; - -//standard stuff -#include -#include -#include - -using namespace std; - - -int main( int argc , char** argv ) -{ - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); - cerr << "Cubical complex created \n"; - - - Compute_persistence_with_phat< Bitmap_cubical_complex< Bitmap_cubical_complex_base > , double > phat(&b); - phat::persistence_pairs pairs = phat.compute_persistence_pairs_standard_reduction(); - std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > persistence = phat.get_the_intervals( pairs ); - writeBettiNumbersAndPersistenceIntervalsToFile( "phat_persistence" , persistence ); - - return 0; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h b/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h deleted file mode 100644 index 9f4ada45..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h +++ /dev/null @@ -1,242 +0,0 @@ -/* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-Saclay (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 . - */ - -#pragma once - - -#include "phat/compute_persistence_pairs.h" -#include "phat/representations/vector_vector.h" -#include "phat/algorithms/standard_reduction.h" -#include "phat/algorithms/chunk_reduction.h" -#include "phat/algorithms/row_reduction.h" -#include "phat/algorithms/twist_reduction.h" - - -namespace Gudhi -{ - - -//the only aim of this class is to have a ability to compute persistence with phat. -template -void writeBettiNumbersAndPersistenceIntervalsToFile( char* prefix , std::pair< std::vector > , std::vector< std::vector< std::pair > > > resutsFromPhat ) -{ - std::ostringstream filenameStr; - filenameStr << prefix << "_bettiNumbers"; - std::string str = filenameStr.str(); - const char* filename = str.c_str(); - ofstream out; - out.open( filename ); - for ( size_t dim = 0 ; dim != resutsFromPhat.first.size() ; ++dim ) - { - out << "Dimension : " << dim << endl; - for ( size_t i = 0 ; i != resutsFromPhat.first[dim].size() ; ++i ) - { - out << resutsFromPhat.first[dim][i] << endl; - } - out << endl; - } - out.close(); - - - cerr << "Write persistence to file \n"; - for ( size_t dim = 0 ; dim != resutsFromPhat.second.size() ; ++dim ) - { - cerr << "resutsFromPhat.second[dim].size() : " << resutsFromPhat.second[dim].size() << endl; - if ( resutsFromPhat.second[dim].size() == 0 )continue; - std::ostringstream filenameStr; - filenameStr << prefix << "_persistence_" << dim; - std::string str = filenameStr.str(); - const char* filename = str.c_str(); - ofstream out1; - out1.open( filename ); - for ( size_t i = 0 ; i != resutsFromPhat.second[dim].size() ; ++i ) - { - out1 << resutsFromPhat.second[dim][i].first << " " << resutsFromPhat.second[dim][i].second << endl; - } - out1.close(); - } -}//writeBettiNumbersAndPersistenceIntervalsToFile - - -template -class Compute_persistence_with_phat -{ -public: - Compute_persistence_with_phat( T* data_structure_ ); - std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > get_the_intervals( phat::persistence_pairs pairs ); - - phat::persistence_pairs compute_persistence_pairs_dualized_chunk_reduction(); - phat::persistence_pairs compute_persistence_pairs_twist_reduction(); - phat::persistence_pairs compute_persistence_pairs_standard_reduction(); - //phat::persistence_pairs compute_persistence_pairs_spectral_sequence_reduction(); -private: - void print_bd_matrix(); - phat::boundary_matrix< phat::vector_vector > boundary_matrix; - T* data_structure; -}; - -template -void Compute_persistence_with_phat::print_bd_matrix() -{ - std::cout << "The boundary matrix has " << this->boundary_matrix.get_num_cols() << " columns: " << std::endl; - for( phat::index col_idx = 0; col_idx < this->boundary_matrix.get_num_cols(); col_idx++ ) { - std::cout << "Colum " << col_idx << " represents a cell of dimension " << (int)this->boundary_matrix.get_dim( col_idx ) << ". "; - if( !this->boundary_matrix.is_empty( col_idx ) ) { - std::vector< phat::index > temp_col; - this->boundary_matrix.get_col( col_idx, temp_col ); - std::cout << "Its boundary consists of the cells"; - for( phat::index idx = 0; idx < (phat::index)temp_col.size(); idx++ ) - std::cout << " " << temp_col[ idx ]; - } - std::cout << std::endl; - } -} - -template -phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_dualized_chunk_reduction() -{ - phat::persistence_pairs pairs; - phat::compute_persistence_pairs_dualized< phat::chunk_reduction >( pairs, this->boundary_matrix ); - return pairs; -} - -template -phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_twist_reduction() -{ - phat::persistence_pairs pairs; - phat::compute_persistence_pairs< phat::twist_reduction >( pairs, this->boundary_matrix ); - return pairs; -} - -template -phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_standard_reduction() -{ - phat::persistence_pairs pairs; - phat::compute_persistence_pairs< phat::standard_reduction >( pairs, this->boundary_matrix ); - return pairs; -} - -//template -//phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_spectral_sequence_reduction() -//{ -// phat::persistence_pairs pairs; -// phat::compute_persistence_pairs< phat::spectral_sequence_reduction >( pairs, this->boundary_matrix ); -// return pairs; -//} - -template -Compute_persistence_with_phat::Compute_persistence_with_phat( T* data_structure_ ):data_structure( data_structure_ ) -{ - bool dbg = false; - this->boundary_matrix.set_num_cols( this->data_structure->num_simplices() ); - - //setting up the dimensions of cells: - for ( size_t i = 0 ; i != this->data_structure->num_simplices() ; ++i ) - { - this->boundary_matrix.set_dim( i, this->data_structure->dimension( this->data_structure->simplex(i) ) ); - } - - - //now it is time to set up the boundary matrix: - typename T::Filtration_simplex_range range = this->data_structure->filtration_simplex_range(); - std::vector< phat::index > temp_col; - for ( typename T::Filtration_simplex_iterator it = range.begin() ; it != range.end() ; ++it ) - { - typename T::Boundary_simplex_range boundary_range = this->data_structure->boundary_simplex_range( *it ); - for ( typename T::Boundary_simplex_iterator bd = boundary_range.begin() ; bd != boundary_range.end() ; ++bd ) - { - temp_col.push_back( this->data_structure->key( *bd ) ); - } - //we do not know if the boundary elements are sorted according to filtration, that is why I am enforcing it here: - this->boundary_matrix.set_col( this->data_structure->key( *it ) , temp_col ); - temp_col.clear(); - } -} - -template -std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > Compute_persistence_with_phat::get_the_intervals( phat::persistence_pairs pairs ) -{ - bool dbg = false; - //in order to find the birth times of the infinite homology classes, we need to know which elements are not paired. To search for them, we will use this vector: - std::vector isTheElementPaired( this->data_structure->num_simplices() , false ); - - //now it is time to recover the finite persistence pairs and the Betti numbers: - std::vector< std::vector< std::pair > > finitePersistencePairs( this->data_structure->dimension() ); - for( phat::index idx = 0; idx < pairs.get_num_pairs(); idx++ ) - { - typename T::Simplex_key positionOfBeginOfInterval = pairs.get_pair( idx ).first; - typename T::Simplex_key positionOfEndOfInterval = pairs.get_pair( idx ).second; - - typename T::Simplex_handle first_simplex = this->data_structure->simplex(positionOfBeginOfInterval); - typename T::Simplex_handle second_simplex = this->data_structure->simplex(positionOfEndOfInterval); - - typename T::Filtration_value valueFirst = this->data_structure->filtration( first_simplex ); - typename T::Filtration_value valueSecond = this->data_structure->filtration( second_simplex ); - - if ( valueFirst > valueSecond ){std::swap( valueFirst , valueSecond );} - - unsigned dimFirst = this->data_structure->dimension(first_simplex); - unsigned dimSecond = this->data_structure->dimension(second_simplex); - unsigned dim = std::min( dimFirst , dimSecond ); - - - //we are ignoring trivial barcodes - if ( valueFirst != valueSecond ) - { - finitePersistencePairs[ dim ].push_back( std::make_pair(valueFirst , valueSecond) ); - if ( dbg ){cerr << "Adding barcode : " << valueFirst << "," << valueSecond << endl;} - } - - //isTheElementPaired[ positionOfBeginOfIntervalInBitmap ] = true; - //isTheElementPaired[ positionOfEndOfIntervalInBitmap ] = true; - isTheElementPaired[ pairs.get_pair( idx ).first ] = true; - isTheElementPaired[ pairs.get_pair( idx ).second ] = true; - } - - - std::vector< std::vector > birthTimesOfInfinitePersistnceClasses(this->data_structure->dimension()+1 ); - for ( size_t i = 0 ; i != this->data_structure->dimension()+1 ; ++i ) - { - std::vector v; - birthTimesOfInfinitePersistnceClasses[i] = v; - } - for ( size_t i = 0 ; i != isTheElementPaired.size() ; ++i ) - { - if ( isTheElementPaired[i] == false ) - { - //i-th element is not paired, therefore it gives an infinite class - typename T::Simplex_handle simplex = this->data_structure->simplex(i); - birthTimesOfInfinitePersistnceClasses[ this->data_structure->dimension( simplex ) ].push_back( this->data_structure->filtration(simplex) ); - } - } - - //sorting finite persistence pairs: - for ( size_t dim = 0 ; dim != finitePersistencePairs.size() ; ++dim ) - { - std::sort( finitePersistencePairs[dim].begin() , finitePersistencePairs[dim].end() ); - } - return std::make_pair( birthTimesOfInfinitePersistnceClasses , finitePersistencePairs ); -}//Compute_persistence_with_phat - - - -}//namespace Gudhi diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h deleted file mode 100644 index 352392a8..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h +++ /dev/null @@ -1,240 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../boundary_matrix.h" - -namespace phat { - class chunk_reduction { - public: - enum column_type { GLOBAL - , LOCAL_POSITIVE - , LOCAL_NEGATIVE }; - - public: - template< typename Representation > - void operator() ( boundary_matrix< Representation >& boundary_matrix ) { - - const index nr_columns = boundary_matrix.get_num_cols(); - const dimension max_dim = boundary_matrix.get_max_dim(); - - std::vector< index > lowest_one_lookup( nr_columns, -1 ); - std::vector < column_type > column_type( nr_columns, GLOBAL ); - std::vector< char > is_active( nr_columns, false ); - - std::vector chunk_boundaries; - _get_chunks( boundary_matrix, chunk_boundaries ); - - // Phase 1: Reduce chunks locally -- 1st pass - #pragma omp parallel for schedule( guided, 1 ) - for( index chunk_id = 0; chunk_id < (index) chunk_boundaries.size() - 2; chunk_id += 2 ) - _local_chunk_reduction( boundary_matrix, lowest_one_lookup, column_type, max_dim, - chunk_boundaries[chunk_id], chunk_boundaries[chunk_id+2] - 1 ); - boundary_matrix.sync(); - - // Phase 1: Reduce chunks locally -- 2nd pass - #pragma omp parallel for schedule( guided, 1 ) - for( index chunk_id = 1; chunk_id < (index) chunk_boundaries.size() - 2; chunk_id += 2 ) - _local_chunk_reduction( boundary_matrix, lowest_one_lookup, column_type, max_dim, - chunk_boundaries[chunk_id], chunk_boundaries[chunk_id+2] - 1 ); - boundary_matrix.sync(); - - // get global columns - std::vector< index > global_columns; - for( index cur_col_idx = 0; cur_col_idx < nr_columns; cur_col_idx++ ) - if( column_type[ cur_col_idx ] == GLOBAL ) - global_columns.push_back( cur_col_idx ); - - // get active columns - #pragma omp parallel for - for( index idx = 0; idx < (index)global_columns.size(); idx++ ) - is_active[ global_columns[ idx ] ] = true; - _get_active_columns( boundary_matrix, lowest_one_lookup, column_type, global_columns, is_active ); - - // Phase 2+3: Simplify columns and reduce them - for( dimension cur_dim = max_dim; cur_dim >= 1; cur_dim-- ) { - // Phase 2: Simplify columns - std::vector< index > temp_col; - #pragma omp parallel for schedule( guided, 1 ), private( temp_col ) - for( index idx = 0; idx < (index)global_columns.size(); idx++ ) - if( boundary_matrix.get_dim( global_columns[ idx ] ) == cur_dim ) - _global_column_simplification( global_columns[ idx ], boundary_matrix, lowest_one_lookup, column_type, is_active, temp_col ); - boundary_matrix.sync(); - - // Phase 3: Reduce columns - for( index idx = 0; idx < (index)global_columns.size(); idx++ ) { - index cur_col = global_columns[ idx ]; - if( boundary_matrix.get_dim( cur_col ) == cur_dim && column_type[ cur_col ] == GLOBAL ) { - index lowest_one = boundary_matrix.get_max_index( cur_col ); - while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { - boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); - lowest_one = boundary_matrix.get_max_index( cur_col ); - } - if( lowest_one != -1 ) { - lowest_one_lookup[ lowest_one ] = cur_col; - boundary_matrix.clear( lowest_one ); - } - } - } - } - - boundary_matrix.sync(); - } - - protected: - template< typename Representation > - void _get_chunks( const boundary_matrix< Representation >& boundary_matrix - , std::vector< index >& chunk_boundaries) - { - chunk_boundaries.clear(); - std::vector temp_chunk_boundaries; - const index nr_columns = boundary_matrix.get_num_cols(); - - // size of chuks = sqrt(N) - const index chunk_size = (index) sqrt( (float)nr_columns ); - - // size of chunks = N / num_threads - //const index chunk_size = nr_columns / omp_get_max_threads(); - - for ( index cur_col = 0; cur_col < nr_columns; cur_col++ ) - if( cur_col % chunk_size == 0 ) - temp_chunk_boundaries.push_back( cur_col ); - temp_chunk_boundaries.push_back( nr_columns ); - - // subdivide chunks for interleaved 2 pass appraoch - for( index chunk_id = 0; chunk_id < (index) temp_chunk_boundaries.size(); chunk_id ++ ) { - chunk_boundaries.push_back( temp_chunk_boundaries[ chunk_id ] ); - if( chunk_id < (index) temp_chunk_boundaries.size() - 1 ) { - index midPoint = ( temp_chunk_boundaries[ chunk_id ] + temp_chunk_boundaries[ chunk_id + 1 ] ) / 2; - chunk_boundaries.push_back( midPoint ); - } - } - } - - template< typename Representation > - void _local_chunk_reduction( boundary_matrix< Representation >& boundary_matrix - , std::vector& lowest_one_lookup - , std::vector< column_type >& column_type - , const dimension max_dim - , const index chunk_begin - , const index chunk_end ) { - for( dimension cur_dim = max_dim; cur_dim >= 1; cur_dim-- ) { - for( index cur_col = chunk_begin; cur_col <= chunk_end; cur_col++ ) { - if( column_type[ cur_col ] == GLOBAL && boundary_matrix.get_dim( cur_col ) == cur_dim ) { - index lowest_one = boundary_matrix.get_max_index( cur_col ); - while( lowest_one != -1 && lowest_one >= chunk_begin && lowest_one_lookup[ lowest_one ] != -1 ) { - boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); - lowest_one = boundary_matrix.get_max_index( cur_col ); - } - if( lowest_one >= chunk_begin ) { - lowest_one_lookup[ lowest_one ] = cur_col; - column_type[ cur_col ] = LOCAL_NEGATIVE; - column_type[ lowest_one ] = LOCAL_POSITIVE; - boundary_matrix.clear( lowest_one ); - } - } - } - } - } - - template< typename Representation > - void _get_active_columns( const boundary_matrix< Representation >& boundary_matrix - , const std::vector< index >& lowest_one_lookup - , const std::vector< column_type >& column_type - , const std::vector< index >& global_columns - , std::vector< char >& is_active ) { - - const index nr_columns = boundary_matrix.get_num_cols(); - std::vector< char > finished( nr_columns, false ); - - std::vector< std::pair < index, index > > stack; - std::vector< index > cur_col_values; - #pragma omp parallel for schedule( guided, 1 ), private( stack, cur_col_values ) - for( index idx = 0; idx < (index)global_columns.size(); idx++ ) { - bool pop_next = false; - index start_col = global_columns[ idx ]; - stack.push_back( std::pair< index, index >( start_col, -1 ) ); - while( !stack.empty() ) { - index cur_col = stack.back().first; - index prev_col = stack.back().second; - if( pop_next ) { - stack.pop_back(); - pop_next = false; - if( prev_col != -1 ) { - if( is_active[ cur_col ] ) { - is_active[ prev_col ] = true; - } - if( prev_col == stack.back().first ) { - finished[ prev_col ] = true; - pop_next = true; - } - } - } else { - pop_next = true; - boundary_matrix.get_col( cur_col, cur_col_values ); - for( index idx = 0; idx < (index) cur_col_values.size(); idx++ ) { - index cur_row = cur_col_values[ idx ]; - if( ( column_type[ cur_row ] == GLOBAL ) ) { - is_active[ cur_col ] = true; - } else if( column_type[ cur_row ] == LOCAL_POSITIVE ) { - index next_col = lowest_one_lookup[ cur_row ]; - if( next_col != cur_col && !finished[ cur_col ] ) { - stack.push_back( std::make_pair( next_col, cur_col ) ); - pop_next = false; - } - } - } - } - } - } - } - - template< typename Representation > - void _global_column_simplification( const index col_idx - , boundary_matrix< Representation >& boundary_matrix - , const std::vector< index >& lowest_one_lookup - , const std::vector< column_type >& column_type - , const std::vector< char >& is_active - , std::vector< index >& temp_col ) - { - temp_col.clear(); - while( !boundary_matrix.is_empty( col_idx ) ) { - index cur_row = boundary_matrix.get_max_index( col_idx ); - switch( column_type[ cur_row ] ) { - case GLOBAL: - temp_col.push_back( cur_row ); - boundary_matrix.remove_max( col_idx ); - break; - case LOCAL_NEGATIVE: - boundary_matrix.remove_max( col_idx ); - break; - case LOCAL_POSITIVE: - if( is_active[ lowest_one_lookup[ cur_row ] ] ) - boundary_matrix.add_to( lowest_one_lookup[ cur_row ], col_idx ); - else - boundary_matrix.remove_max( col_idx ); - break; - } - } - std::reverse( temp_col.begin(), temp_col.end() ); - boundary_matrix.set_col( col_idx, temp_col ); - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h deleted file mode 100644 index 2047cafd..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../boundary_matrix.h" - -namespace phat { - class row_reduction { - public: - template< typename Representation > - void operator() ( boundary_matrix< Representation >& boundary_matrix ) { - - const index nr_columns = boundary_matrix.get_num_cols(); - std::vector< std::vector< index > > lowest_one_lookup( nr_columns ); - - for( index cur_col = nr_columns - 1; cur_col >= 0; cur_col-- ) { - if( !boundary_matrix.is_empty( cur_col ) ) - lowest_one_lookup[ boundary_matrix.get_max_index( cur_col ) ].push_back( cur_col ); - - if( !lowest_one_lookup[ cur_col ].empty() ) { - boundary_matrix.clear( cur_col ); - std::vector< index >& cols_with_cur_lowest = lowest_one_lookup[ cur_col ]; - index source = *min_element( cols_with_cur_lowest.begin(), cols_with_cur_lowest.end() ); - for( index idx = 0; idx < (index)cols_with_cur_lowest.size(); idx++ ) { - index target = cols_with_cur_lowest[ idx ]; - if( target != source && !boundary_matrix.is_empty( target ) ) { - boundary_matrix.add_to( source, target ); - if( !boundary_matrix.is_empty( target ) ) { - index lowest_one_of_target = boundary_matrix.get_max_index( target ); - lowest_one_lookup[ lowest_one_of_target ].push_back( target ); - } - } - } - } - } - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h deleted file mode 100644 index b2c91a85..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../boundary_matrix.h" - -namespace phat { - class standard_reduction { - public: - template< typename Representation > - void operator() ( boundary_matrix< Representation >& boundary_matrix ) { - - const index nr_columns = boundary_matrix.get_num_cols(); - std::vector< index > lowest_one_lookup( nr_columns, -1 ); - - for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { - index lowest_one = boundary_matrix.get_max_index( cur_col ); - while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { - boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); - lowest_one = boundary_matrix.get_max_index( cur_col ); - } - if( lowest_one != -1 ) { - lowest_one_lookup[ lowest_one ] = cur_col; - } - } - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h deleted file mode 100644 index 1bdd8de2..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../boundary_matrix.h" - -namespace phat { - class twist_reduction { - public: - template< typename Representation > - void operator () ( boundary_matrix< Representation >& boundary_matrix ) { - - const index nr_columns = boundary_matrix.get_num_cols(); - std::vector< index > lowest_one_lookup( nr_columns, -1 ); - - for( index cur_dim = boundary_matrix.get_max_dim(); cur_dim >= 1 ; cur_dim-- ) { - for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { - if( boundary_matrix.get_dim( cur_col ) == cur_dim ) { - index lowest_one = boundary_matrix.get_max_index( cur_col ); - while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { - boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); - lowest_one = boundary_matrix.get_max_index( cur_col ); - } - if( lowest_one != -1 ) { - lowest_one_lookup[ lowest_one ] = cur_col; - boundary_matrix.clear( lowest_one ); - } - } - } - } - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h b/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h deleted file mode 100644 index 941537da..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h +++ /dev/null @@ -1,336 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "helpers/misc.h" -#include "representations/bit_tree_pivot_column.h" - -// interface class for the main data structure -- implementations of the interface can be found in ./representations -namespace phat { - template< class Representation = bit_tree_pivot_column > - class boundary_matrix - { - - protected: - Representation rep; - - // interface functions -- actual implementation and complexity depends on chosen @Representation template - public: - // get overall number of columns in boundary_matrix - index get_num_cols() const { return rep._get_num_cols(); } - - // set overall number of columns in boundary_matrix - void set_num_cols( index nr_of_columns ) { rep._set_num_cols( nr_of_columns ); } - - // get dimension of given index - dimension get_dim( index idx ) const { return rep._get_dim( idx ); } - - // set dimension of given index - void set_dim( index idx, dimension dim ) { rep._set_dim( idx, dim ); } - - // replaces content of @col with boundary of given index - void get_col( index idx, column& col ) const { rep._get_col( idx, col ); } - - // set column @idx to the values contained in @col - void set_col( index idx, const column& col ) { rep._set_col( idx, col ); } - - // true iff boundary of given column is empty - bool is_empty( index idx ) const { return rep._is_empty( idx ); } - - // largest index of given column (new name for lowestOne()) - index get_max_index( index idx ) const { return rep._get_max_index( idx ); } - - // removes maximal index from given column - void remove_max( index idx ) { rep._remove_max( idx ); } - - // adds column @source to column @target' - void add_to( index source, index target ) { rep._add_to( source, target ); } - - // clears given column - void clear( index idx ) { rep._clear( idx ); } - - // syncronizes all internal data structures -- has to be called before and after any multithreaded access! - void sync() { rep._sync(); } - - // info functions -- independent of chosen 'Representation' - public: - // maximal dimension - dimension get_max_dim() const { - dimension cur_max_dim = 0; - for( index idx = 0; idx < get_num_cols(); idx++ ) - cur_max_dim = get_dim( idx ) > cur_max_dim ? get_dim( idx ) : cur_max_dim; - return cur_max_dim; - } - - // number of nonzero rows for given column @idx - index get_num_rows( index idx ) const { - column cur_col; - get_col( idx, cur_col ); - return cur_col.size(); - } - - // maximal number of nonzero rows of all columns - index get_max_col_entries() const { - index max_col_entries = -1; - const index nr_of_columns = get_num_cols(); - for( index idx = 0; idx < nr_of_columns; idx++ ) - max_col_entries = get_num_rows( idx ) > max_col_entries ? get_num_rows( idx ) : max_col_entries; - return max_col_entries; - } - - // maximal number of nonzero cols of all rows - index get_max_row_entries() const { - size_t max_row_entries = 0; - const index nr_of_columns = get_num_cols(); - std::vector< std::vector< index > > transposed_matrix( nr_of_columns ); - column temp_col; - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - get_col( cur_col, temp_col ); - for( index idx = 0; idx < (index)temp_col.size(); idx++) - transposed_matrix[ temp_col[ idx ] ].push_back( cur_col ); - } - for( index idx = 0; idx < nr_of_columns; idx++ ) - max_row_entries = transposed_matrix[ idx ].size() > max_row_entries ? transposed_matrix[ idx ].size() : max_row_entries; - return max_row_entries; - } - - // overall number of entries in the matrix - index get_num_entries() const { - index number_of_nonzero_entries = 0; - const index nr_of_columns = get_num_cols(); - for( index idx = 0; idx < nr_of_columns; idx++ ) - number_of_nonzero_entries += get_num_rows( idx ); - return number_of_nonzero_entries; - } - - // operators / constructors - public: - boundary_matrix() {}; - - template< class OtherRepresentation > - boundary_matrix( const boundary_matrix< OtherRepresentation >& other ) { - *this = other; - } - - template< typename OtherRepresentation > - bool operator==( const boundary_matrix< OtherRepresentation >& other_boundary_matrix ) const { - const index number_of_columns = this->get_num_cols(); - - if( number_of_columns != other_boundary_matrix.get_num_cols() ) - return false; - - column temp_col; - column other_temp_col; - for( index idx = 0; idx < number_of_columns; idx++ ) { - this->get_col( idx, temp_col ); - other_boundary_matrix.get_col( idx, other_temp_col ); - if( temp_col != other_temp_col || this->get_dim( idx ) != other_boundary_matrix.get_dim( idx ) ) - return false; - } - return true; - } - - template< typename OtherRepresentation > - bool operator!=( const boundary_matrix< OtherRepresentation >& other_boundary_matrix ) const { - return !( *this == other_boundary_matrix ); - } - - template< typename OtherRepresentation > - boundary_matrix< Representation >& operator=( const boundary_matrix< OtherRepresentation >& other ) - { - const index nr_of_columns = other.get_num_cols(); - this->set_num_cols( nr_of_columns ); - column temp_col; - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - this->set_dim( cur_col, other.get_dim( cur_col ) ); - other.get_col( cur_col, temp_col ); - this->set_col( cur_col, temp_col ); - } - - // by convention, always return *this - return *this; - } - - // I/O -- independent of chosen 'Representation' - public: - - // initializes boundary_matrix from (vector, vector) pair -- untested - template< typename index_type, typename dimemsion_type > - void load_vector_vector( const std::vector< std::vector< index_type > >& input_matrix, const std::vector< dimemsion_type >& input_dims ) { - const index nr_of_columns = (index)input_matrix.size(); - this->set_num_cols( nr_of_columns ); - column temp_col; - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - this->set_dim( cur_col, (dimension)input_dims[ cur_col ] ); - - index num_rows = input_matrix[ cur_col ].size(); - temp_col.resize( num_rows ); - for( index cur_row = 0; cur_row < num_rows; cur_row++ ) - temp_col[ cur_row ] = (index)input_matrix[ cur_col ][ cur_row ]; - this->set_col( cur_col, temp_col ); - } - } - - template< typename index_type, typename dimemsion_type > - void save_vector_vector( std::vector< std::vector< index_type > >& output_matrix, std::vector< dimemsion_type >& output_dims ) { - const index nr_of_columns = get_num_cols(); - output_matrix.resize( nr_of_columns ); - output_dims.resize( nr_of_columns ); - column temp_col; - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - output_dims[ cur_col ] = (dimemsion_type)get_dim( cur_col ); - get_col( cur_col, temp_col ); - index num_rows = temp_col.size(); - output_matrix[ cur_col ].clear(); - output_matrix[ cur_col ].resize( num_rows ); - for( index cur_row = 0; cur_row < num_rows; cur_row++ ) - output_matrix[ cur_col ][ cur_row ] = (index_type)temp_col[ cur_row ]; - } - } - - // Loads the boundary_matrix from given file in ascii format - // Format: each line represents a column, first number is dimension, other numbers are the content of the column. - // Ignores empty lines and lines starting with a '#'. - bool load_ascii( std::string filename ) { - // first count number of columns: - std::string cur_line; - std::ifstream dummy( filename .c_str() ); - if( dummy.fail() ) - return false; - - index number_of_columns = 0; - while( getline( dummy, cur_line ) ) { - cur_line.erase(cur_line.find_last_not_of(" \t\n\r\f\v") + 1); - if( cur_line != "" && cur_line[ 0 ] != '#' ) - number_of_columns++; - - } - this->set_num_cols( number_of_columns ); - dummy.close(); - - std::ifstream input_stream( filename.c_str() ); - if( input_stream.fail() ) - return false; - - column temp_col; - index cur_col = -1; - while( getline( input_stream, cur_line ) ) { - cur_line.erase(cur_line.find_last_not_of(" \t\n\r\f\v") + 1); - if( cur_line != "" && cur_line[ 0 ] != '#' ) { - cur_col++; - std::stringstream ss( cur_line ); - - int64_t temp_dim; - ss >> temp_dim; - this->set_dim( cur_col, (dimension) temp_dim ); - - int64_t temp_index; - temp_col.clear(); - while( ss.good() ) { - ss >> temp_index; - temp_col.push_back( (index)temp_index ); - } - std::sort( temp_col.begin(), temp_col.end() ); - this->set_col( cur_col, temp_col ); - } - } - - input_stream.close(); - return true; - } - - // Saves the boundary_matrix to given file in ascii format - // Format: each line represents a column, first number is dimension, other numbers are the content of the column - bool save_ascii( std::string filename ) { - std::ofstream output_stream( filename.c_str() ); - if( output_stream.fail() ) - return false; - - const index nr_columns = this->get_num_cols(); - column tempCol; - for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { - output_stream << (int64_t)this->get_dim( cur_col ); - this->get_col( cur_col, tempCol ); - for( index cur_row_idx = 0; cur_row_idx < (index)tempCol.size(); cur_row_idx++ ) - output_stream << " " << tempCol[ cur_row_idx ]; - output_stream << std::endl; - } - - output_stream.close(); - return true; - } - - // Loads boundary_matrix from given file - // Format: nr_columns % dim1 % N1 % row1 row2 % ...% rowN1 % dim2 % N2 % ... - bool load_binary( std::string filename ) { - std::ifstream input_stream( filename.c_str(), std::ios_base::binary | std::ios_base::in ); - if( input_stream.fail() ) - return false; - - int64_t nr_columns; - input_stream.read( (char*)&nr_columns, sizeof( int64_t ) ); - this->set_num_cols( (index)nr_columns ); - - column temp_col; - for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { - int64_t cur_dim; - input_stream.read( (char*)&cur_dim, sizeof( int64_t ) ); - this->set_dim( cur_col, (dimension) cur_dim ); - int64_t nr_rows; - input_stream.read( (char*)&nr_rows, sizeof( int64_t ) ); - temp_col.resize( (std::size_t)nr_rows ); - for( index idx = 0; idx < nr_rows; idx++ ) { - int64_t cur_row; - input_stream.read( (char*)&cur_row, sizeof( int64_t ) ); - temp_col[ idx ] = (index)cur_row; - } - this->set_col( cur_col, temp_col ); - } - - input_stream.close(); - return true; - } - - // Saves the boundary_matrix to given file in binary format - // Format: nr_columns % dim1 % N1 % row1 row2 % ...% rowN1 % dim2 % N2 % ... - bool save_binary( std::string filename ) { - std::ofstream output_stream( filename.c_str(), std::ios_base::binary | std::ios_base::out ); - if( output_stream.fail() ) - return false; - - const int64_t nr_columns = this->get_num_cols(); - output_stream.write( (char*)&nr_columns, sizeof( int64_t ) ); - column tempCol; - for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { - int64_t cur_dim = this->get_dim( cur_col ); - output_stream.write( (char*)&cur_dim, sizeof( int64_t ) ); - this->get_col( cur_col, tempCol ); - int64_t cur_nr_rows = tempCol.size(); - output_stream.write( (char*)&cur_nr_rows, sizeof( int64_t ) ); - for( index cur_row_idx = 0; cur_row_idx < (index)tempCol.size(); cur_row_idx++ ) { - int64_t cur_row = tempCol[ cur_row_idx ]; - output_stream.write( (char*)&cur_row, sizeof( int64_t ) ); - } - } - - output_stream.close(); - return true; - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h b/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h deleted file mode 100644 index f5b04d5a..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "persistence_pairs.h" -#include "boundary_matrix.h" -#include "helpers/dualize.h" -#include "algorithms/twist_reduction.h" - -namespace phat { - - template< typename ReductionAlgorithm, typename Representation > - void compute_persistence_pairs( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { - ReductionAlgorithm reduce; - reduce( boundary_matrix ); - pairs.clear(); - for( index idx = 0; idx < boundary_matrix.get_num_cols(); idx++ ) { - if( !boundary_matrix.is_empty( idx ) ) { - index birth = boundary_matrix.get_max_index( idx ); - index death = idx; - pairs.append_pair( birth, death ); - } - } - } - - template< typename ReductionAlgorithm, typename Representation > - void compute_persistence_pairs_dualized( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { - ReductionAlgorithm reduce; - const index nr_columns = boundary_matrix.get_num_cols(); - dualize( boundary_matrix ); - reduce( boundary_matrix ); - pairs.clear(); - for( index idx = 0; idx < nr_columns; idx++ ) { - if( !boundary_matrix.is_empty( idx ) ) { - index death = nr_columns - 1 - boundary_matrix.get_max_index( idx ); - index birth = nr_columns - 1 - idx; - pairs.append_pair( birth, death ); - } - } - } - - template< typename Representation > - void compute_persistence_pairs( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { - phat::compute_persistence_pairs< twist_reduction >( pairs, boundary_matrix ); - } - - - template< typename Representation > - void compute_persistence_pairs_dualized( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { - compute_persistence_pairs_dualized< twist_reduction >( pairs, boundary_matrix ); - } - -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h deleted file mode 100644 index 60caa05c..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "misc.h" -#include "../boundary_matrix.h" - -namespace phat { - template< typename Representation > - void dualize( boundary_matrix< Representation >& boundary_matrix ) { - - std::vector< dimension > dual_dims; - std::vector< std::vector< index > > dual_matrix; - - index nr_of_columns = boundary_matrix.get_num_cols(); - dual_matrix.resize( nr_of_columns ); - dual_dims.resize( nr_of_columns ); - - std::vector< index > dual_sizes( nr_of_columns, 0 ); - - column temp_col; - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - boundary_matrix.get_col( cur_col, temp_col ); - for( index idx = 0; idx < (index)temp_col.size(); idx++) - dual_sizes[ nr_of_columns - 1 - temp_col[ idx ] ]++; - } - - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - dual_matrix[cur_col].reserve(dual_sizes[cur_col]); - } - - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - boundary_matrix.get_col( cur_col, temp_col ); - for( index idx = 0; idx < (index)temp_col.size(); idx++) - dual_matrix[ nr_of_columns - 1 - temp_col[ idx ] ].push_back( nr_of_columns - 1 - cur_col ); - } - - const dimension max_dim = boundary_matrix.get_max_dim(); - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) - dual_dims[ nr_of_columns - 1 - cur_col ] = max_dim - boundary_matrix.get_dim( cur_col ); - - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) - std::reverse( dual_matrix[ cur_col ].begin(), dual_matrix[ cur_col ].end() ); - - boundary_matrix.load_vector_vector( dual_matrix, dual_dims ); - } -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h deleted file mode 100644 index abbf8d53..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -// STL includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// VS2008 and below unfortunately do not support stdint.h -#if defined(_MSC_VER)&& _MSC_VER < 1600 - typedef __int8 int8_t; - typedef unsigned __int8 uint8_t; - typedef __int16 int16_t; - typedef unsigned __int16 uint16_t; - typedef __int32 int32_t; - typedef unsigned __int32 uint32_t; - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; -#else - #include -#endif - -// basic types. index can be changed to int32_t to save memory on small instances -namespace phat { - typedef int64_t index; - typedef int8_t dimension; - typedef std::vector< index > column; -} - -// OpenMP (proxy) functions -#if defined _OPENMP - #include -#else - #define omp_get_thread_num() 0 - #define omp_get_max_threads() 1 - #define omp_get_num_threads() 1 - void omp_set_num_threads( int ) {}; - #include - #define omp_get_wtime() (float)clock() / (float)CLOCKS_PER_SEC -#endif - -#include "thread_local_storage.h" - - - diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h deleted file mode 100644 index 06e95c20..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "misc.h" - -// should ideally be equal to the cache line size of the CPU -#define PHAT_TLS_SPACING_FACTOR 64 - -// ThreadLocalStorage with some spacing to avoid "false sharing" (see wikipedia) -template< typename T > -class thread_local_storage -{ -public: - - thread_local_storage() : per_thread_storage( omp_get_max_threads() * PHAT_TLS_SPACING_FACTOR ) {}; - - T& operator()() { - return per_thread_storage[ omp_get_thread_num() * PHAT_TLS_SPACING_FACTOR ]; - } - - const T& operator()() const { - return per_thread_storage[ omp_get_thread_num() * PHAT_TLS_SPACING_FACTOR ]; - } - - T& operator[]( int tid ) { - return per_thread_storage[ tid * PHAT_TLS_SPACING_FACTOR ]; - } - - const T& operator[]( int tid ) const { - return per_thread_storage[ tid * PHAT_TLS_SPACING_FACTOR ]; - } - -protected: - std::vector< T > per_thread_storage; -}; diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h b/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h deleted file mode 100644 index f8006353..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "helpers/misc.h" - -namespace phat { - class persistence_pairs { - - protected: - std::vector< std::pair< index, index > > pairs; - - public: - index get_num_pairs() const { - return (index)pairs.size(); - } - - void append_pair( index birth, index death ) { - pairs.push_back( std::make_pair( birth, death ) ); - } - - std::pair< index, index > get_pair( index idx ) const { - return pairs[ idx ]; - } - - void clear() { - pairs.clear(); - } - - void sort() { - std::sort( pairs.begin(), pairs.end() ); - } - - // Loads the persistence pairs from given file in asci format - // Format: nr_pairs % newline % birth1 % death1 % newline % birth2 % death2 % newline ... - bool load_ascii( std::string filename ) { - std::ifstream input_stream( filename.c_str() ); - if( input_stream.fail() ) - return false; - - int64_t nr_pairs; - input_stream >> nr_pairs; - pairs.clear(); - for( index idx = 0; idx < nr_pairs; idx++ ) { - int64_t birth; - input_stream >> birth; - int64_t death; - input_stream >> death; - append_pair( (index)birth, (index)death ); - } - - input_stream.close(); - return true; - } - - // Saves the persistence pairs to given file in binary format - // Format: nr_pairs % newline % birth1 % death1 % newline % birth2 % death2 % newline ... - bool save_ascii( std::string filename ) { - std::ofstream output_stream( filename.c_str() ); - if( output_stream.fail() ) - return false; - - this->sort(); - output_stream << get_num_pairs() << std::endl; - for( std::size_t idx = 0; idx < pairs.size(); idx++ ) { - output_stream << pairs[idx].first << " " << pairs[idx].second << std::endl; - } - - output_stream.close(); - return true; - } - - // Loads the persistence pairs from given file in binary format - // Format: nr_pairs % birth1 % death1 % birth2 % death2 ... - bool load_binary( std::string filename ) { - std::ifstream input_stream( filename.c_str(), std::ios_base::binary | std::ios_base::in ); - if( input_stream.fail() ) - return false; - - int64_t nr_pairs; - input_stream.read( (char*)&nr_pairs, sizeof( int64_t ) ); - for( index idx = 0; idx < nr_pairs; idx++ ) { - int64_t birth; - input_stream.read( (char*)&birth, sizeof( int64_t ) ); - int64_t death; - input_stream.read( (char*)&death, sizeof( int64_t ) ); - append_pair( (index)birth, (index)death ); - } - - input_stream.close(); - return true; - } - - // Saves the persistence pairs to given file in binary format - // Format: nr_pairs % birth1 % death1 % birth2 % death2 ... - bool save_binary( std::string filename ) { - std::ofstream output_stream( filename.c_str(), std::ios_base::binary | std::ios_base::out ); - if( output_stream.fail() ) - return false; - - this->sort(); - int64_t nr_pairs = get_num_pairs(); - output_stream.write( (char*)&nr_pairs, sizeof( int64_t ) ); - for( std::size_t idx = 0; idx < pairs.size(); idx++ ) { - int64_t birth = pairs[ idx ].first; - output_stream.write( (char*)&birth, sizeof( int64_t ) ); - int64_t death = pairs[ idx ].second; - output_stream.write( (char*)&death, sizeof( int64_t ) ); - } - - output_stream.close(); - return true; - } - - bool operator==( persistence_pairs& other_pairs ) { - this->sort(); - other_pairs.sort(); - if( pairs.size() != (std::size_t)other_pairs.get_num_pairs() ) - return false; - - for( index idx = 0; idx < (index)pairs.size(); idx++ ) - if( get_pair( idx ) != other_pairs.get_pair( idx ) ) - return false; - - return true; - } - - bool operator!=( persistence_pairs& other_pairs ) { - return !( *this == other_pairs ); - } - }; - - - -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h deleted file mode 100644 index 41104108..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../representations/vector_vector.h" - -namespace phat { - - // Note: We could even make the rep generic in the underlying Const representation - // But I cannot imagine that anything else than vector> would - // make sense - template< typename PivotColumn > - class abstract_pivot_column : public vector_vector { - public: - - protected: - typedef vector_vector Base; - typedef PivotColumn pivot_column; - - // For parallization purposes, it could be more than one full column - mutable thread_local_storage< pivot_column > _pivot_columns; - mutable thread_local_storage< index > pos_of_pivot_columns; - - pivot_column& get_pivot_column() const { - return _pivot_columns(); - } - - bool is_represented_by_pivot_column( index idx ) const { - return pos_of_pivot_columns() == idx; - } - - void unset_pos_of_pivot_column() { - index idx = pos_of_pivot_columns(); - if( idx != -1 ) { - _pivot_columns().get_column_and_clear( this->matrix[ idx ] ); - } - pos_of_pivot_columns() = -1; - } - - void represent_by_pivot_column( index idx ) { - pos_of_pivot_columns() = idx; - get_pivot_column().add_column( matrix[ idx ] ); - } - - public: - - void _set_num_cols( index nr_of_columns ) { - #pragma omp parallel for - for( int tid = 0; tid < omp_get_num_threads(); tid++ ) { - _pivot_columns[ tid ].init( nr_of_columns ); - pos_of_pivot_columns[ tid ] = -1; - } - Base::_set_num_cols( nr_of_columns ); - } - // replaces(!) content of 'col' with boundary of given index - void _get_col( index idx, column& col ) const { - col.clear(); - if( is_represented_by_pivot_column( idx ) ) { - pivot_column& pivot_column = get_pivot_column(); - pivot_column.get_column_and_clear( col ); - pivot_column.add_column( col ); - } else { - Base::_get_col( idx, col ); - } - } - - // true iff boundary of given idx is empty - bool _is_empty( index idx ) const { - return is_represented_by_pivot_column( idx ) ? get_pivot_column().empty() : Base::_is_empty( idx ); - } - - // largest row index of given column idx (new name for lowestOne()) - index _get_max_index( index idx ) const { - if( is_represented_by_pivot_column( idx ) ) { - pivot_column& pivot_column = get_pivot_column(); - if( pivot_column.empty() ) { - return -1; - } else { - return pivot_column.max_index(); - } - } else { - return Base::_get_max_index( idx ); - } - } - - // adds column 'source' to column 'target' - void _add_to( index source, index target ) { - if( !is_represented_by_pivot_column( target ) ) { - unset_pos_of_pivot_column(); - represent_by_pivot_column( target ); - } - get_pivot_column().add_column( matrix[source] ); - } - - // clears given column - void _clear( index idx ) { - if( is_represented_by_pivot_column( idx ) ) { - column dummy; - get_pivot_column().get_column_and_clear(dummy); - } else { - Base::_clear( idx ); - } - } - - void _set_col( index idx, const column& col ) { - if( is_represented_by_pivot_column( idx ) ) { - column dummy; - pivot_column& pivot_column = get_pivot_column(); - pivot_column.get_column_and_clear( dummy ); - pivot_column.add_column( col ); - } else { - Base::_set_col( idx, col ); - } - } - - // removes the maximal index of a column - void _remove_max( index idx ) { - _toggle( idx, _get_max_index( idx ) ); - } - - //// toggles given index pair - void _toggle( index col_idx, index row_idx ) { - if( !is_represented_by_pivot_column( col_idx ) ) { - unset_pos_of_pivot_column(); - represent_by_pivot_column( col_idx ); - } - get_pivot_column().add_index( row_idx ); - } - - // syncronizes all data structures (essential for openmp stuff) - // has to be called before and after any multithreaded access! - void _sync() { - #pragma omp parallel for - for( int tid = 0; tid < omp_get_num_threads(); tid++ ) - unset_pos_of_pivot_column(); - } - - }; -} - - diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h deleted file mode 100644 index 34366d6a..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Hubert Wagner - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../representations/abstract_pivot_column.h" - -namespace phat { - - // This is a bitset indexed with a 64-ary tree. Each node in the index - // has 64 bits; i-th bit says that the i-th subtree is non-empty. - // Supports practically O(1), inplace, zero-allocation: insert, remove, max_element - // and clear in O(number of ones in the bitset). - // 'add_index' is still the real bottleneck in practice. - class bit_tree_column - { - size_t offset; // data[i + offset] = ith block of the data-bitset - typedef uint64_t block_type; - std::vector< block_type > data; - - // this static is not a problem with OMP, it's initialized just after program starts - static const size_t debrujin_magic_table[64]; - - enum { block_size_in_bits = 64 }; - enum { block_shift = 6 }; - - // Some magic: http://graphics.stanford.edu/~seander/bithacks.html - // Gets the position of the rightmost bit of 'x'. 0 means the most significant bit. - // (-x)&x isolates the rightmost bit. - // The whole method is much faster than calling log2i, and very comparable to using ScanBitForward/Reverse intrinsic, - // which should be one CPU instruction, but is not portable. - size_t rightmost_pos(const block_type value) const - { - return 64 - 1 - debrujin_magic_table[((value & (-(int64_t)value))*0x07EDD5E59A4E28C2) >> 58]; - } - - public: - - void init(index num_cols) - { - int64_t n = 1; // in case of overflow - int64_t bottom_blocks_needed = (num_cols+block_size_in_bits-1)/block_size_in_bits; - int64_t upper_blocks = 1; - - // How many blocks/nodes of index needed to index the whole bitset? - while(n * block_size_in_bits < bottom_blocks_needed) - { - n *= block_size_in_bits; - upper_blocks += n; - } - - offset = upper_blocks; - data.resize(upper_blocks + bottom_blocks_needed, 0); - } - - index max_index() const - { - if (!data[0]) - return -1; - - const size_t size = data.size(); - size_t n = 0; - - while(true) - { - const block_type val = data[n]; - const size_t index = rightmost_pos(val); - const size_t newn = (n << block_shift) + index + 1; - - if (newn >= size) - { - const size_t bottom_index = n - offset; - return (bottom_index << block_shift) + index; - } - - n = newn; - } - - return -1; - } - - bool empty() const - { - return data[0] == 0; - } - - void add_index(const size_t entry) - { - const block_type ONE = 1; - const block_type block_modulo_mask = ((ONE << block_shift) - 1); - size_t index_in_level = entry >> block_shift; - size_t address = index_in_level + offset; - size_t index_in_block = entry & block_modulo_mask; - - block_type mask = (ONE << (block_size_in_bits - index_in_block - 1)); - - while(true) - { - data[address]^=mask; - - // First we check if we reached the root. - // Also, if anyone else was in this block, we don't need to update the path up. - if (!address || (data[address] & ~mask)) - return; - - index_in_block = index_in_level & block_modulo_mask; - index_in_level >>= block_shift; - --address; - address >>= block_shift; - mask = (ONE << (block_size_in_bits - index_in_block - 1)); - } - } - - void get_column_and_clear(column &out) - { - out.clear(); - while(true) - { - index mx = this->max_index(); - if (mx == -1) - break; - out.push_back(mx); - add_index(mx); - } - - std::reverse(out.begin(), out.end()); - } - - void add_column(const column &col) - { - for (size_t i = 0; i < col.size(); ++i) - { - add_index(col[i]); - } - } - - bool empty() { - return !data[0]; - } - }; - - const size_t bit_tree_column::debrujin_magic_table[64] = { - 63, 0, 58, 1, 59, 47, 53, 2, - 60, 39, 48, 27, 54, 33, 42, 3, - 61, 51, 37, 40, 49, 18, 28, 20, - 55, 30, 34, 11, 43, 14, 22, 4, - 62, 57, 46, 52, 38, 26, 32, 41, - 50, 36, 17, 19, 29, 10, 13, 21, - 56, 45, 25, 31, 35, 16, 9, 12, - 44, 24, 15, 8, 23, 7, 6, 5}; - - typedef abstract_pivot_column bit_tree_pivot_column; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h deleted file mode 100644 index 9e0c348d..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include -#include - -namespace phat { - class full_column { - - protected: - std::priority_queue< index > m_history; - std::vector< char > m_isInHistory; - std::vector< char > m_data; - - public: - void init( const index total_size ) { - m_data.resize( total_size, false ); - m_isInHistory.resize( total_size, false ); - } - - void add_column( const column& col ) { - for( index idx = 0; idx < (index) col.size(); idx++ ) { - add_index( col[ idx ] ); - } - } - void add_index( const index idx ) { - if( !m_isInHistory[ idx ] ) { - m_history.push( idx ); - m_isInHistory[ idx ] = true; - } - - m_data[ idx ] = !m_data[ idx ]; - } - - index max_index() { - while( m_history.size() > 0 ) { - index topIndex = m_history.top(); - if( m_data[ topIndex ] ) { - return topIndex; - } else { - m_history.pop(); - m_isInHistory[ topIndex ] = false; - } - } - - return -1; - } - - void get_column_and_clear( column& col ) { - col.clear(); - while( !empty() ) { - col.push_back( max_index() ); - add_index( max_index() ); - } - std::reverse( col.begin(), col.end() ); - } - - bool empty() { - return (max_index() == -1); - } - }; - - typedef abstract_pivot_column< full_column > full_pivot_column; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h deleted file mode 100644 index c851a2b5..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include -#include - -namespace phat { - class sparse_column { - - protected: - std::set< index > m_data; - - public: - void init( const index total_size ) { - m_data.clear(); - } - - void add_column( const column& col ) { - for( index idx = 0; idx < (index) col.size(); idx++ ) - add_index( col[ idx ] ); - } - - void add_index( const index idx ) { - std::pair< std::set< index >::iterator, bool > result = m_data.insert( idx ); - if( result.second == false ) - m_data.erase( result.first ); - } - - index max_index() { - return m_data.empty() ? -1 : *m_data.rbegin(); - } - - void get_column_and_clear( column& col ) { - col.clear(); - col.assign( m_data.begin(), m_data.end() ); - m_data.clear(); - } - - bool empty() { - return m_data.empty(); - } - }; - - typedef abstract_pivot_column< sparse_column > sparse_pivot_column; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h deleted file mode 100644 index 38e3090c..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include - -namespace phat { - class vector_list { - - protected: - typedef std::list< index > internal_column; - std::vector< dimension > dims; - std::vector< internal_column > matrix; - - public: - // overall number of cells in boundary_matrix - index _get_num_cols() const { - return (index)matrix.size(); - } - void _set_num_cols( index nr_of_columns ) { - dims.resize( nr_of_columns ); - matrix.resize( nr_of_columns ); - } - - // dimension of given index - dimension _get_dim( index idx ) const { - return dims[ idx ]; - } - void _set_dim( index idx, dimension dim ) { - dims[ idx ] = dim; - } - - // replaces(!) content of 'col' with boundary of given index - void _get_col( index idx, column& col ) const { - col.clear(); - col.reserve( matrix[idx].size() ); - std::copy (matrix[idx].begin(), matrix[idx].end(), std::back_inserter(col) ); - } - - void _set_col( index idx, const column& col ) { - matrix[ idx ].clear(); - matrix[ idx ].resize( col.size() ); - std::copy (col.begin(), col.end(), matrix[ idx ].begin() ); - } - - // true iff boundary of given idx is empty - bool _is_empty( index idx ) const { - return matrix[ idx ].empty(); - } - - // largest row index of given column idx (new name for lowestOne()) - index _get_max_index( index idx ) const { - return matrix[ idx ].empty() ? -1 : *matrix[ idx ].rbegin(); - } - - // removes the maximal index of a column - void _remove_max( index idx ) { - internal_column::iterator it = matrix[ idx ].end(); - it--; - matrix[ idx ].erase( it ); - } - - // clears given column - void _clear( index idx ) { - matrix[ idx ].clear(); - } - - // syncronizes all data structures (essential for openmp stuff) - void _sync() {} - - // adds column 'source' to column 'target' - void _add_to( index source, index target ) { - internal_column& source_col = matrix[ source ]; - internal_column& target_col = matrix[ target ]; - internal_column temp_col; - target_col.swap( temp_col ); - std::set_symmetric_difference( temp_col.begin(), temp_col.end(), - source_col.begin(), source_col.end(), - std::back_inserter( target_col ) ); - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h deleted file mode 100644 index dadf1b34..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include - -namespace phat { - class vector_set { - - protected: - typedef std::set< index > internal_column; - std::vector< dimension > dims; - std::vector< internal_column > matrix; - - public: - // overall number of cells in boundary_matrix - index _get_num_cols() const { - return (index)matrix.size(); - } - void _set_num_cols( index nr_of_columns ) { - dims.resize( nr_of_columns ); - matrix.resize( nr_of_columns ); - } - - // dimension of given index - dimension _get_dim( index idx ) const { - return dims[ idx ]; - } - void _set_dim( index idx, dimension dim ) { - dims[ idx ] = dim; - } - - // replaces(!) content of 'col' with boundary of given index - void _get_col( index idx, column& col ) const { - col.clear(); - col.reserve( matrix[idx].size() ); - std::copy (matrix[idx].begin(), matrix[idx].end(), std::back_inserter(col) ); - } - void _set_col( index idx, const column& col ) { - matrix[ idx ].clear(); - matrix[ idx ].insert( col.begin(), col.end() ); - } - - // true iff boundary of given idx is empty - bool _is_empty( index idx ) const { - return matrix[ idx ].empty(); - } - - // largest row index of given column idx (new name for lowestOne()) - index _get_max_index( index idx ) const { - return matrix[ idx ].empty() ? -1 : *matrix[ idx ].rbegin(); - } - - // removes the maximal index of a column - void _remove_max( index idx ) { - internal_column::iterator it = matrix[ idx ].end(); - it--; - matrix[ idx ].erase( it ); - } - - // clears given column - void _clear( index idx ) { - matrix[ idx ].clear(); - } - - // syncronizes all data structures (essential for openmp stuff) - void _sync() {} - - // adds column 'source' to column 'target' - void _add_to( index source, index target ) { - for( internal_column::iterator it = matrix[ source ].begin(); it != matrix[ source ].end(); it++ ) - _toggle( target, *it ); - } - - //// toggles given index pair - void _toggle( index col_idx, index row_idx ) { - internal_column& col = matrix[ col_idx ]; - std::pair< internal_column::iterator, bool > result = col.insert( row_idx ); - if( !result.second ) { - col.erase( result.first ); - } - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h deleted file mode 100644 index efe8de4d..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" - -namespace phat { - class vector_vector { - - protected: - std::vector< dimension > dims; - std::vector< column > matrix; - - thread_local_storage< column > temp_column_buffer; - - public: - // overall number of cells in boundary_matrix - index _get_num_cols() const { - return (index)matrix.size(); - } - void _set_num_cols( index nr_of_columns ) { - dims.resize( nr_of_columns ); - matrix.resize( nr_of_columns ); - } - - // dimension of given index - dimension _get_dim( index idx ) const { - return dims[ idx ]; - } - void _set_dim( index idx, dimension dim ) { - dims[ idx ] = dim; - } - - // replaces(!) content of 'col' with boundary of given index - void _get_col( index idx, column& col ) const { - col = matrix[ idx ]; - } - void _set_col( index idx, const column& col ) { - matrix[ idx ] = col; - } - - // true iff boundary of given idx is empty - bool _is_empty( index idx ) const { - return matrix[ idx ].empty(); - } - - // largest row index of given column idx (new name for lowestOne()) - index _get_max_index( index idx ) const { - return matrix[ idx ].empty() ? -1 : matrix[ idx ].back(); - } - - // removes the maximal index of a column - void _remove_max( index idx ) { - matrix[ idx ].pop_back(); - } - - // clears given column - void _clear( index idx ) { - matrix[ idx ].clear(); - } - - // syncronizes all data structures (essential for openmp stuff) - void _sync() {} - - // adds column 'source' to column 'target' - void _add_to( index source, index target ) { - column& source_col = matrix[ source ]; - column& target_col = matrix[ target ]; - column& temp_col = temp_column_buffer(); - temp_col.clear(); - std::set_symmetric_difference( target_col.begin(), target_col.end(), - source_col.begin(), source_col.end(), - std::back_inserter( temp_col ) ); - target_col.swap( temp_col ); - } - }; -} -- cgit v1.2.3 From ff41ff166c9ea66fcc1187056053e43bf7d7be8f Mon Sep 17 00:00:00 2001 From: glisse Date: Mon, 15 Feb 2016 11:51:20 +0000 Subject: typo git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1022 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d6068c0b757949d2e404ba99812ae7a0b8a8908d --- src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 2ec7594d..70f19e03 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -40,8 +40,8 @@ const bool globalDbg = false; template class is_before_in_filtration; /** -* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex__base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into -* Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template parameter is supposed to be either Bitmap_cubical_complex__base or Bitmap_cubical_complex_periodic_boundary_conditions_base class. +* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into +* Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template parameter is supposed to be either Bitmap_cubical_complex_base or Bitmap_cubical_complex_periodic_boundary_conditions_base class. **/ /** -- cgit v1.2.3 From 897f3b6016dac740c5b990c72e2e0ba30cf29963 Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 16 Feb 2016 13:53:04 +0000 Subject: Moved the doc file + changed notations in Witness_complex.h git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@1023 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1053d8ac2f833be8086c81b50dbb34c18de07ebb --- src/Witness_complex/doc/Witness_complex_doc.h | 38 ++++++++++++++++++++++ .../include/gudhi/Witness_complex.h | 20 ++++++------ .../include/gudhi/Witness_complex_doc.h | 38 ---------------------- 3 files changed, 48 insertions(+), 48 deletions(-) create mode 100644 src/Witness_complex/doc/Witness_complex_doc.h delete mode 100644 src/Witness_complex/include/gudhi/Witness_complex_doc.h (limited to 'src') diff --git a/src/Witness_complex/doc/Witness_complex_doc.h b/src/Witness_complex/doc/Witness_complex_doc.h new file mode 100644 index 00000000..e9f78170 --- /dev/null +++ b/src/Witness_complex/doc/Witness_complex_doc.h @@ -0,0 +1,38 @@ +#ifndef WITNESS_COMPLEX_DOC_H_ +#define WITNESS_COMPLEX_DOC_H_ + +/** + \defgroup witness_complex Witness complex + + \author Siargey Kachanovich + + \section Definitions + + Witness complex \f$ Wit(W,L) \f$ is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$: + + \li \f$W\f$ set of **witnesses** and + \li \f$L \subseteq W\f$ set of **landmarks**. + + The simplices are based on landmarks + and a simplex belongs to the witness complex if and only if it is witnessed, that is: + + \f$ \sigma \subset L \f$ is witnessed if there exists a point \f$w \in W\f$ such that + w is closer to the vertices of \f$ \sigma \f$ than other points in \f$ L \f$ and all of its faces are witnessed as well. + + \section Implementation + + The principal class of this module is Gudhi::Witness_complex. + + In both cases, the constructor for this class takes a {witness}x{closest_landmarks} table, where each row represents a witness and consists of landmarks sorted by distance to this witness. + This table can be constructed by two additional classes Landmark_choice_by_furthest_point and Landmark_choice_by_random_point also included in the module. + + *\image html "bench_Cy8.png" "Running time as function on number of landmarks" width=10cm + *\image html "bench_sphere.png" "Running time as function on number of witnesses for |L|=300" width=10cm + + + \copyright GNU General Public License v3. + + + */ + +#endif // WITNESS_COMPLEX_DOC_H_ diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 50058740..dab80be6 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -80,8 +80,8 @@ class Witness_complex { typedef std::list< Vertex_handle > ActiveWitnessList; private: - int nbL; // Number of landmarks - SimplicialComplex& sc; // Simplicial complex + int nbL_; // Number of landmarks + SimplicialComplex& sc_; // Simplicial complex public: ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -108,9 +108,9 @@ class Witness_complex { */ template< typename KNearestNeighbors > Witness_complex(KNearestNeighbors const & knn, - int nbL_, + int nbL, int dim, - SimplicialComplex & sc_) : nbL(nbL_), sc(sc_) { + SimplicialComplex & sc) : nbL_(nbL), sc_(sc) { // Construction of the active witness list int nbW = knn.size(); typeVectorVertex vv; @@ -119,12 +119,12 @@ class Witness_complex { * it will diminuish in the course of iterations */ ActiveWitnessList active_w; // = new ActiveWitnessList(); - for (Vertex_handle i = 0; i != nbL; ++i) { + for (Vertex_handle i = 0; i != nbL_; ++i) { // initial fill of 0-dimensional simplices // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore counter++; vv = {i}; - sc.insert_simplex(vv); + sc_.insert_simplex(vv); // TODO(SK) Error if not inserted : normally no need here though } int k = 1; /* current dimension in iterative construction */ @@ -139,7 +139,7 @@ class Witness_complex { if (ok) { for (int i = 0; i != k + 1; ++i) simplex_vector.push_back(knn[*it][i]); - sc.insert_simplex(simplex_vector); + sc_.insert_simplex(simplex_vector); // TODO(SK) Error if not inserted : normally no need here though it++; } else { @@ -168,7 +168,7 @@ class Witness_complex { facet.push_back(knn[witness_id][j]); } } // endfor - if (sc.find(facet) == sc.null_simplex()) + if (sc_.find(facet) == sc_.null_simplex()) return false; } // endfor return true; @@ -196,11 +196,11 @@ class Witness_complex { template< class KNearestNeighbors > bool is_witness_complex(KNearestNeighbors const & knn, bool print_output) { // bool final_result = true; - for (Simplex_handle sh : sc.complex_simplex_range()) { + for (Simplex_handle sh : sc_.complex_simplex_range()) { bool is_witnessed = false; typeVectorVertex simplex; int nbV = 0; // number of verticed in the simplex - for (Vertex_handle v : sc.simplex_vertex_range(sh)) + for (Vertex_handle v : sc_.simplex_vertex_range(sh)) simplex.push_back(v); nbV = simplex.size(); for (typeVectorVertex w : knn) { diff --git a/src/Witness_complex/include/gudhi/Witness_complex_doc.h b/src/Witness_complex/include/gudhi/Witness_complex_doc.h deleted file mode 100644 index e9f78170..00000000 --- a/src/Witness_complex/include/gudhi/Witness_complex_doc.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef WITNESS_COMPLEX_DOC_H_ -#define WITNESS_COMPLEX_DOC_H_ - -/** - \defgroup witness_complex Witness complex - - \author Siargey Kachanovich - - \section Definitions - - Witness complex \f$ Wit(W,L) \f$ is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$: - - \li \f$W\f$ set of **witnesses** and - \li \f$L \subseteq W\f$ set of **landmarks**. - - The simplices are based on landmarks - and a simplex belongs to the witness complex if and only if it is witnessed, that is: - - \f$ \sigma \subset L \f$ is witnessed if there exists a point \f$w \in W\f$ such that - w is closer to the vertices of \f$ \sigma \f$ than other points in \f$ L \f$ and all of its faces are witnessed as well. - - \section Implementation - - The principal class of this module is Gudhi::Witness_complex. - - In both cases, the constructor for this class takes a {witness}x{closest_landmarks} table, where each row represents a witness and consists of landmarks sorted by distance to this witness. - This table can be constructed by two additional classes Landmark_choice_by_furthest_point and Landmark_choice_by_random_point also included in the module. - - *\image html "bench_Cy8.png" "Running time as function on number of landmarks" width=10cm - *\image html "bench_sphere.png" "Running time as function on number of witnesses for |L|=300" width=10cm - - - \copyright GNU General Public License v3. - - - */ - -#endif // WITNESS_COMPLEX_DOC_H_ -- cgit v1.2.3 From c5469621436305badbc4c5a64380881b6571f7bc Mon Sep 17 00:00:00 2001 From: skachano Date: Tue, 16 Feb 2016 15:02:50 +0000 Subject: Commented is_witness_complex's documentation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@1026 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 912a482e67e92b02a20db1be8b602ff8576632ae --- .../include/gudhi/Landmark_choice_by_furthest_point.h | 1 + src/Witness_complex/include/gudhi/Witness_complex.h | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h index 47cd888d..2491b319 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -34,6 +34,7 @@ namespace witness_complex { typedef std::vector typeVectorVertex; /** + * \ingroup witness_complex * \brief Landmark choice strategy by iteratively adding the furthest witness from the * current landmark set as the new landmark. * \details It chooses nbL landmarks from a random access range `points` and diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index dab80be6..046343db 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -188,11 +188,11 @@ class Witness_complex { } public: - /** - * \brief Verification if every simplex in the complex is witnessed by witnesses in knn. - * \param print_output =true will print the witnesses for each simplex - * \remark Added for debugging purposes. - */ + // /** + // * \brief Verification if every simplex in the complex is witnessed by witnesses in knn. + // * \param print_output =true will print the witnesses for each simplex + // * \remark Added for debugging purposes. + // */ template< class KNearestNeighbors > bool is_witness_complex(KNearestNeighbors const & knn, bool print_output) { // bool final_result = true; -- cgit v1.2.3 From 67f7ecf8e35b51256304b5120daf2827450b6dcd Mon Sep 17 00:00:00 2001 From: skachano Date: Thu, 18 Feb 2016 13:02:25 +0000 Subject: The rest of changes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@1031 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: af29326bd4293697211c20001fc120108a38b3f4 --- .../include/gudhi/Landmark_choice_by_furthest_point.h | 7 ++++++- .../include/gudhi/Landmark_choice_by_random_point.h | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h index 2491b319..472cc0f7 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -39,6 +39,11 @@ namespace witness_complex { * current landmark set as the new landmark. * \details It chooses nbL landmarks from a random access range `points` and * writes {witness}*{closest landmarks} matrix in `knn`. + * + * The type KNearestNeighbors can be seen as + * Witness_range>, where + * Witness_range and Closest_landmark_range are random access ranges + * */ template Date: Fri, 11 Mar 2016 10:36:42 +0000 Subject: Put the class Witness_complex to private in doc git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@1037 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 351b135de4d345830ab7fb796eb69b23063fd494 --- .../example/witness_complex_from_file.cpp | 4 +-- .../example/witness_complex_sphere.cpp | 4 +-- .../include/gudhi/Witness_complex.h | 29 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index 98d1fe9c..a8294bad 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -40,7 +40,7 @@ using namespace Gudhi::witness_complex; typedef std::vector< Vertex_handle > typeVectorVertex; typedef std::vector< std::vector > Point_Vector; -typedef Witness_complex< Simplex_tree<> > WitnessComplex; +//typedef Witness_complex< Simplex_tree<> > WitnessComplex; /** * \brief Customized version of read_points @@ -98,7 +98,7 @@ int main(int argc, char * const argv[]) { // Compute witness complex start = clock(); - WitnessComplex(knn, nbL, point_vector[0].size(), simplex_tree); + Gudhi::witness_complex::witness_complex(knn, nbL, point_vector[0].size(), simplex_tree); end = clock(); std::cout << "Witness complex took " << static_cast(end - start) / CLOCKS_PER_SEC << " s. \n"; diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index fae80d67..7bbf983a 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -44,8 +44,6 @@ using namespace Gudhi::witness_complex; typedef std::vector< Vertex_handle > typeVectorVertex; -typedef Witness_complex< Simplex_tree<> > WitnessComplex; - /** Write a gnuplot readable file. * Data range is a random access range of pairs (arg, value) */ @@ -85,7 +83,7 @@ int main(int argc, char * const argv[]) { Gudhi::witness_complex::landmark_choice_by_random_point(point_vector, number_of_landmarks, knn); // Compute witness complex - WitnessComplex(knn, number_of_landmarks, point_vector[0].size(), simplex_tree); + Gudhi::witness_complex::witness_complex(knn, number_of_landmarks, point_vector[0].size(), simplex_tree); end = clock(); double time = static_cast(end - start) / CLOCKS_PER_SEC; std::cout << "Witness complex for " << number_of_landmarks << " landmarks took " diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 046343db..524912cf 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -48,6 +48,7 @@ namespace Gudhi { namespace witness_complex { /** + * \private \class Witness_complex \brief Constructs the witness complex for the given set of witnesses and landmarks. \ingroup witness_complex @@ -236,6 +237,34 @@ class Witness_complex { } }; + /** + * \ingroup witness_complex + * \brief Iterative construction of the witness complex. + * \details The witness complex is written in simplicial complex sc_ + * basing on a matrix knn of + * nearest neighbours of the form {witnesses}x{landmarks}. + * + * The type KNearestNeighbors can be seen as + * Witness_range>, where + * Witness_range and Closest_landmark_range are random access ranges. + * + * Procedure takes into account at most (dim+1) + * first landmarks from each landmark range to construct simplices. + * + * Landmarks are supposed to be in [0,nbL_-1] + */ + + + template + void witness_complex(KNearestNeighbors const & knn, + int nbL, + int dim, + SimplicialComplexForWitness & sc) + { + + Witness_complex(knn, nbL, dim, sc); + } + } // namespace witness_complex } // namespace Gudhi -- cgit v1.2.3 From b94ae59cf3441a2aa93824e081baa102abf0c286 Mon Sep 17 00:00:00 2001 From: skachano Date: Fri, 11 Mar 2016 13:33:20 +0000 Subject: concept and documentation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@1038 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d96a449cd155761d4ae5c61987046733b864e11e --- src/Witness_complex/concept/Simplicial_complex.h | 87 ---------------------- .../concept/Simplicial_complex_for_witness.h | 87 ++++++++++++++++++++++ .../include/gudhi/Witness_complex.h | 20 ++--- 3 files changed, 97 insertions(+), 97 deletions(-) delete mode 100644 src/Witness_complex/concept/Simplicial_complex.h create mode 100644 src/Witness_complex/concept/Simplicial_complex_for_witness.h (limited to 'src') diff --git a/src/Witness_complex/concept/Simplicial_complex.h b/src/Witness_complex/concept/Simplicial_complex.h deleted file mode 100644 index 74d60388..00000000 --- a/src/Witness_complex/concept/Simplicial_complex.h +++ /dev/null @@ -1,87 +0,0 @@ -/* 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): Siargey Kachanovich - * - * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (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 . - */ - -#ifndef CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_H_ -#define CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_H_ - -namespace Gudhi { - -namespace witness_complex { - -/** \brief The concept Simplicial_Complex describes the requirements - * for a type to implement a simplicial complex, - * used for example to build a 'Witness_complex'. - */ -struct SimplicialComplex { - /** Handle to specify a simplex. */ - typedef unspecified Simplex_handle; - /** Handle to specify a vertex. Must be a non-negative integer. */ - typedef unspecified Vertex_handle; - - /** Returns a Simplex_hanlde that is different from all simplex handles - * of the simplices. */ - Simplex_handle null_simplex(); - - /** \brief Iterator over the simplices of the complex, - * in an arbitrary order. - * - * 'value_type' must be 'Simplex_handle'.*/ - typedef unspecified Complex_simplex_range; - - /** - * \brief Returns a range over all the simplices of a - * complex. - */ - Complex_simplex_range complex_simplex_range(); - - /** \brief Iterator over vertices of a simplex. - * - * 'value type' must be 'Vertex_handle'.*/ - typedef unspecified Simplex_vertex_range; - - /** \brief Returns a range over vertices of a given - * simplex. */ - Simplex_vertex_range simplex_vertex_range(Simplex_handle const & simplex); - - /** \brief Return type of an insertion of a simplex - */ - typedef unspecified Insertion_result_type; - - /** \brief Inserts a simplex with vertices from a given range - * 'vertex_range' in the simplicial complex. - * */ - template< typedef Input_vertex_range > - Insertion_result_type insert_simplex(Input_vertex_range const & vertex_range); - - /** \brief Finds a simplex with vertices given by a range - * - * If a simplex exists, its Simplex_handle is returned. - * Otherwise null_simplex() is returned. */ - template< typedef Input_vertex_range > - Simplex_handle find(Input_vertex_range const & vertex_range); -}; - -} // namespace witness_complex - -} // namespace Gudhi - -#endif // CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_H_ diff --git a/src/Witness_complex/concept/Simplicial_complex_for_witness.h b/src/Witness_complex/concept/Simplicial_complex_for_witness.h new file mode 100644 index 00000000..a4cf3c77 --- /dev/null +++ b/src/Witness_complex/concept/Simplicial_complex_for_witness.h @@ -0,0 +1,87 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (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 . + */ + +#ifndef CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_H_ +#define CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_H_ + +namespace Gudhi { + +namespace witness_complex { + +/** \brief The concept Simplicial_Complex describes the requirements + * for a type to implement a simplicial complex, + * used for example to build a 'Witness_complex'. + */ +struct SimplicialComplexForWitness { + /** Handle to specify a simplex. */ + typedef unspecified Simplex_handle; + /** Handle to specify a vertex. Must be a non-negative integer. */ + typedef unspecified Vertex_handle; + + /** Returns a Simplex_hanlde that is different from all simplex handles + * of the simplices. */ + Simplex_handle null_simplex(); + + /** \brief Iterator over the simplices of the complex, + * in an arbitrary order. + * + * 'value_type' must be 'Simplex_handle'.*/ + typedef unspecified Complex_simplex_range; + + /** + * \brief Returns a range over all the simplices of a + * complex. + */ + Complex_simplex_range complex_simplex_range(); + + /** \brief Iterator over vertices of a simplex. + * + * 'value type' must be 'Vertex_handle'.*/ + typedef unspecified Simplex_vertex_range; + + /** \brief Returns a range over vertices of a given + * simplex. */ + Simplex_vertex_range simplex_vertex_range(Simplex_handle const & simplex); + + /** \brief Return type of an insertion of a simplex + */ + typedef unspecified Insertion_result_type; + + /** \brief Inserts a simplex with vertices from a given range + * 'vertex_range' in the simplicial complex. + * */ + template< typedef Input_vertex_range > + Insertion_result_type insert_simplex(Input_vertex_range const & vertex_range); + + /** \brief Finds a simplex with vertices given by a range + * + * If a simplex exists, its Simplex_handle is returned. + * Otherwise null_simplex() is returned. */ + template< typedef Input_vertex_range > + Simplex_handle find(Input_vertex_range const & vertex_range); +}; + +} // namespace witness_complex + +} // namespace Gudhi + +#endif // CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_H_ diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 524912cf..60734efe 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -47,12 +47,12 @@ namespace Gudhi { namespace witness_complex { -/** - * \private - \class Witness_complex - \brief Constructs the witness complex for the given set of witnesses and landmarks. - \ingroup witness_complex - */ +// /* +// * \private +// \class Witness_complex +// \brief Constructs the witness complex for the given set of witnesses and landmarks. +// \ingroup witness_complex +// */ template< class SimplicialComplex> class Witness_complex { private: @@ -86,14 +86,14 @@ class Witness_complex { public: ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** @name Constructor + /* @name Constructor */ //@{ // Witness_range> - /** + /* * \brief Iterative construction of the witness complex. * \details The witness complex is written in sc_ basing on a matrix knn of * nearest neighbours of the form {witnesses}x{landmarks}. @@ -154,7 +154,7 @@ class Witness_complex { //@} private: - /** \brief Check if the facets of the k-dimensional simplex witnessed + /* \brief Check if the facets of the k-dimensional simplex witnessed * by witness witness_id are already in the complex. * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id */ @@ -189,7 +189,7 @@ class Witness_complex { } public: - // /** + // /* // * \brief Verification if every simplex in the complex is witnessed by witnesses in knn. // * \param print_output =true will print the witnesses for each simplex // * \remark Added for debugging purposes. -- cgit v1.2.3 From 5389d8969d8386bb4c74dbef4b7c7992e9130f13 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Mon, 14 Mar 2016 12:59:53 +0000 Subject: Answers to Marc's comments. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1042 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 481841d609bae68df85a93527e6d3cc20f1b06e2 --- .../example/Bitmap_cubical_complex.cpp | 146 ++++----- src/Bitmap_cubical_complex/example/CMakeLists.txt | 4 +- .../include/gudhi/Bitmap_cubical_complex.h | 8 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 355 ++++++++++++--------- ...cal_complex_periodic_boundary_conditions_base.h | 10 + 5 files changed, 288 insertions(+), 235 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index 39a55f24..4c30ee85 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -1,73 +1,73 @@ - /* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Saclay (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 - - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff -#include -#include -#include - -using namespace std; - - -int main( int argc , char** argv ) -{ - cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbered in \ -the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; - - int p = 2; - double min_persistence = 0; - - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); - - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology - pcoh.compute_persistent_cohomology( min_persistence ); - - - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out((char*)ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 0; -} + /* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 + + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include + +using namespace std; + + +int main( int argc , char** argv ) +{ + cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbered in \ +the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + + pcoh.compute_persistent_cohomology( min_persistence ); + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index fbd1b28b..14c94e8e 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -13,5 +13,5 @@ add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubical_complex_periodic_boundary_conditions.cpp ) target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) -add_executable ( Compute_persistence_with_phat Compute_persistence_with_phat.cpp ) -target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file +#add_executable ( Compute_persistence_with_phat Compute_persistence_with_phat.cpp ) +#target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 70f19e03..4dd295e7 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include "Bitmap_cubical_complex_base.h" #include "Bitmap_cubical_complex_periodic_boundary_conditions_base.h" @@ -127,7 +128,12 @@ public: //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. this->initialize_simplex_associated_to_key(); - } + } + + /** + * Destructor of the Bitmap_cubical_complex class. + **/ + virtual ~Bitmap_cubical_complex(){} //*********************************************// diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 22b703a9..807be335 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -23,13 +23,14 @@ #pragma once #include +#include #include #include #include #include #include #include -#include +#include #include #include "Bitmap_cubical_complex/counter.h" @@ -43,7 +44,11 @@ namespace Cubical_complex { - +/** + *@class Bitmap_cubical_complex_base + *@brief Cubical complex represented as a bitmap, class with basic implementation. + *@ingroup cubical_complex + */ /** * This is a class implementing a basic bitmap data structure to store cubical complexes. * It implements only the most basic subroutines. @@ -64,13 +69,13 @@ namespace Cubical_complex template class Bitmap_cubical_complex_base { -public: - typedef T filtration_type; - /** - *Default constructor - **/ - Bitmap_cubical_complex_base() - { +public: + typedef T filtration_type; + /** + *Default constructor + **/ + Bitmap_cubical_complex_base() + { } /** * There are a few constructors of a Bitmap_cubical_complex_base class. @@ -92,6 +97,11 @@ public: **/ Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells ); + /** + * Destructor of the Bitmap_cubical_complex_base class. + **/ + virtual ~Bitmap_cubical_complex_base(){} + /** * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell * and get_cell_data are the basic @@ -152,18 +162,27 @@ public: * Writing to stream operator. **/ template - friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); - - + friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); + + /** - * Functions that put the input data to bins. + * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( size_t number_of_bins ) + * ais designed for that purpose. The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. **/ void put_data_toBins( size_t number_of_bins ); - void put_data_toBins( T diameter_of_bin ); - + + /** + * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( T diameter_of_bin ) is + * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex + * before and after using such a function will be bounded by the parameter diameter_of_bin. + **/ + void put_data_toBins( T diameter_of_bin ); + /** * Functions to find min and max values of filtration. - **/ + **/ std::pair< T ,T > min_max_filtration(); //ITERATORS @@ -172,42 +191,60 @@ public: * Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ - typedef typename std::vector< T >::iterator all_cells_iterator; - + typedef typename std::vector< T >::iterator all_cells_iterator; + + /** - * Function returning an iterator to the first cell of the bitmap. + * Constant iterator through all cells in the complex (in order they appear in the structure -- i.e. + * in lexicographical order). **/ - all_cells_iterator all_cells_begin() + typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + + /** + * Function returning a constant iterator to the first cell of the bitmap. + **/ + all_cells_const_iterator all_cells_const_begin()const { return this->data.begin(); - } - - /** - * Function returning an iterator to the last cell of the bitmap. + } + + + /** + * Function returning a constant iterator to the last cell of the bitmap. **/ - all_cells_iterator all_cells_end()const + all_cells_const_iterator all_cells_const_end()const { return this->data.end(); } /** - * Constant iterator through all cells in the complex (in order they appear in the structure -- i.e. - * in lexicographical order). + * Function returning an iterator to the first cell of the bitmap. **/ - typedef typename std::vector< T >::const_iterator all_cells_const_iterator; - + all_cells_iterator all_cells_begin() + { + return this->data.begin(); + } + /** * Function returning a constant iterator to the first cell of the bitmap. **/ - all_cells_const_iterator all_cells_const_begin()const + all_cells_const_iterator all_cells_begin() const { return this->data.begin(); - } - + } + + /** + * Function returning an iterator to the last cell of the bitmap. + **/ + all_cells_iterator all_cells_end() + { + return this->data.end(); + } + /** * Function returning a constant iterator to the last cell of the bitmap. **/ - all_cells_const_iterator all_cells_const_end()const + all_cells_const_iterator all_cells_end() const { return this->data.end(); } @@ -303,8 +340,8 @@ public: protected: std::vector< size_t > counter; Bitmap_cubical_complex_base& b; - }; - + }; + /** * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell cell of the bitmap. **/ @@ -312,8 +349,8 @@ public: { Top_dimensional_cells_iterator a(*this); return a; - } - + } + /** * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell cell of the bitmap. **/ @@ -333,11 +370,11 @@ public: //****************************************************************************************************************// //****************************************************************************************************************// //****************************************************************************************************************// - - -inline size_t number_cells()const -{ - return this->total_number_of_cells; + + +inline size_t number_cells()const +{ + return this->total_number_of_cells; } //****************************************************************************************************************// @@ -375,7 +412,7 @@ protected: std::vector compute_counter_for_given_cell( size_t cell )const { - std::vector counter; + std::vector counter; counter.reserve( this->sizes.size() ); for ( size_t dim = this->sizes.size() ; dim != 0 ; --dim ) { @@ -384,59 +421,59 @@ protected: } std::reverse( counter.begin() , counter.end() ); return counter; - } - void read_perseus_style_file( const char* perseus_style_file ); - void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); - Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); - Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); + } + void read_perseus_style_file( const char* perseus_style_file ); + void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); + Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); + Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ); }; -template -void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) -{ - bool bdg = false; - - std::pair< T ,T > min_max = this->min_max_filtration(); - T dx = (min_max.second-min_max.first)/(T)number_of_bins; - - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - template -void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) -{ - bool bdg = false; - std::pair< T ,T > min_max = this->min_max_filtration(); - - size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - -template -std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() -{ - std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( this->data[i] < min_max.first )min_max.first = this->data[i]; - if ( this->data[i] > min_max.second )min_max.second = this->data[i]; - } - return min_max; -} +void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) +{ + bool bdg = false; + + std::pair< T ,T > min_max = this->min_max_filtration(); + T dx = (min_max.second-min_max.first)/(T)number_of_bins; + + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + +template +void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) +{ + bool bdg = false; + std::pair< T ,T > min_max = this->min_max_filtration(); + + size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + +template +std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() +{ + std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( this->data[i] < min_max.first )min_max.first = this->data[i]; + if ( this->data[i] > min_max.second )min_max.second = this->data[i]; + } + return min_max; +} template @@ -457,10 +494,10 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base { this->set_up_containers( sizes ); } - -template -void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) -{ + +template +void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) +{ this->set_up_containers( sizes_in_following_directions ); size_t number_of_top_dimensional_elements = 1; @@ -489,19 +526,19 @@ void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells (*it) = top_dimensional_cells[index]; ++index; } - this->impose_lower_star_filtration(); -} + this->impose_lower_star_filtration(); +} template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base ( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) { this->setup_bitmap_based_on_top_dimensional_cells_list( sizes_in_following_directions , top_dimensional_cells ); -} - -template -void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) -{ +} + +template +void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) +{ bool dbg = false; ifstream inFiltration, inIds; inFiltration.open( perseus_style_file ); @@ -510,7 +547,7 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;getchar();} - std::vector sizes; + std::vector sizes; sizes.reserve( dimensionOfData ); for ( size_t i = 0 ; i != dimensionOfData ; ++i ) { @@ -541,31 +578,31 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu ++it; } inFiltration.close(); - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->read_perseus_style_file( perseus_style_file ); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->set_up_containers( sizes ); -} - -template + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->read_perseus_style_file( perseus_style_file ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->set_up_containers( sizes ); +} + +template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); } template @@ -578,29 +615,29 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const { - std::vector< size_t > boundary_elements; - - //Speed traded of for memory. Check if it is better in practice. - boundary_elements.reserve( this->dimension()*2 ); + std::vector< size_t > boundary_elements; + + //Speed traded of for memory. Check if it is better in practice. + boundary_elements.reserve( this->dimension()*2 ); size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { unsigned position = cell1/this->multipliers[i-1]; if ( position%2 == 1 ) - { - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + { + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); } cell1 = cell1%this->multipliers[i-1]; } return boundary_elements; -} +} + + + - - - template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const { @@ -625,8 +662,8 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( cell1 = cell1%this->multipliers[i-1]; } return coboundary_elements; -} - +} + @@ -675,14 +712,14 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() //this vector will be used to check which elements have already been taken care of //in imposing lower star filtration: std::vector is_this_cell_considered( this->data.size() , false ); - - size_t size_to_reserve = 1; - for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) - { - size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); - } - - std::vector indices_to_consider; + + size_t size_to_reserve = 1; + for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) + { + size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); + } + + std::vector indices_to_consider; indices_to_consider.reserve( size_to_reserve ); //we assume here that we already have a filtration on the top dimensional cells and //we have to extend it to lower ones. @@ -708,20 +745,20 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { std::vector bd = this->get_boundary_of_a_cell( indices_to_consider[i] ); for ( size_t boundaryIt = 0 ; boundaryIt != bd.size() ; ++boundaryIt ) - { - if ( dbg ) - { - cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; - getchar(); - + { + if ( dbg ) + { + cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; + getchar(); + } if ( this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ] ) { - this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; - if ( dbg ) - { - cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; - getchar(); + this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + if ( dbg ) + { + cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; + getchar(); } } if ( is_this_cell_considered[ bd[boundaryIt] ] == false ) @@ -760,4 +797,4 @@ bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , ch } -} +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index f0fd785f..8c1254db 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -37,6 +37,11 @@ namespace Cubical_complex //right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base +/** + *@class Bitmap_cubical_complex_periodic_boundary_conditions_base + *@brief Cubical complex with periodic boundary conditions represented as a bitmap. + *@ingroup cubical_complex + */ /** * This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are identical to the functions from Bitmap_cubical_complex_base. * The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell. @@ -64,6 +69,11 @@ public: */ Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); + /** + * Destructor of the Bitmap_cubical_complex_periodic_boundary_conditions_base class. + **/ + virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base(){} + //overwritten methods co compute boundary and coboundary /** * A version of a function that return boundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. -- cgit v1.2.3 From d133f17dede836cee1dfff47d2e00532573b9ead Mon Sep 17 00:00:00 2001 From: pdlotko Date: Thu, 17 Mar 2016 08:43:58 +0000 Subject: cleanning up the stuff with iterators in Bitmap_cubical_complex_base.h class. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1049 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 9630d6df6a2ecdb51ab25150454a563cd928b09a --- .../example/Random_bitmap_cubical_complex.cpp | 7 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 515 +++++++++++++-------- ...cal_complex_periodic_boundary_conditions_base.h | 4 +- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 183 +++++++- 4 files changed, 500 insertions(+), 209 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index 97347162..8b7f6a04 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -70,11 +70,12 @@ The program will create random cubical complex of that sizes and compute persist for ( size_t i = 0 ; i != multipliers ; ++i ) { data.push_back( rand()/(double)RAND_MAX ); - } - + } + Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( sizes , data ); + + - Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( sizes , data ); // Compute the persistence diagram of the complex diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 807be335..6d2b705c 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include #include #include @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include "Bitmap_cubical_complex/counter.h" @@ -69,13 +69,13 @@ namespace Cubical_complex template class Bitmap_cubical_complex_base { -public: - typedef T filtration_type; - /** - *Default constructor - **/ - Bitmap_cubical_complex_base() - { +public: + typedef T filtration_type; + /** + *Default constructor + **/ + Bitmap_cubical_complex_base() + { } /** * There are a few constructors of a Bitmap_cubical_complex_base class. @@ -96,11 +96,11 @@ public: * together with vector of filtration values of top dimensional cells. **/ Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells ); - + /** * Destructor of the Bitmap_cubical_complex_base class. - **/ - virtual ~Bitmap_cubical_complex_base(){} + **/ + virtual ~Bitmap_cubical_complex_base(){} /** * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell @@ -130,7 +130,9 @@ public: **/ inline unsigned get_dimension_of_a_cell( size_t cell )const; /** - * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. + * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. This allows reading and changing the value of filtration. + * Note that if the value of a filtration is changed, the code do not check if we have a filtration or not. i.e. it do not check if the value of a filtration of a cell is + * not smaller than the value of a filtration of its boundary and not greater than the value of its coboundary. **/ inline T& get_cell_data( size_t cell ); @@ -162,27 +164,27 @@ public: * Writing to stream operator. **/ template - friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); - - + friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); + + /** - * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( size_t number_of_bins ) + * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( size_t number_of_bins ) * ais designed for that purpose. The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. **/ - void put_data_toBins( size_t number_of_bins ); - + void put_data_toBins( size_t number_of_bins ); + /** - * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( T diameter_of_bin ) is - * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex + * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( T diameter_of_bin ) is + * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex * before and after using such a function will be bounded by the parameter diameter_of_bin. **/ - void put_data_toBins( T diameter_of_bin ); - + void put_data_toBins( T diameter_of_bin ); + /** * Functions to find min and max values of filtration. - **/ + **/ std::pair< T ,T > min_max_filtration(); //ITERATORS @@ -191,76 +193,179 @@ public: * Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ - typedef typename std::vector< T >::iterator all_cells_iterator; + //typedef typename std::vector< T >::iterator all_cells_iterator; /** * Constant iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ - typedef typename std::vector< T >::const_iterator all_cells_const_iterator; - + //typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + /** * Function returning a constant iterator to the first cell of the bitmap. **/ - all_cells_const_iterator all_cells_const_begin()const - { - return this->data.begin(); - } - - + //all_cells_const_iterator all_cells_const_begin()const + //{ + // return this->data.begin(); + //} + + /** * Function returning a constant iterator to the last cell of the bitmap. **/ - all_cells_const_iterator all_cells_const_end()const + //all_cells_const_iterator all_cells_const_end()const + //{ + // return this->data.end(); + //} + + /** + * Function returning an iterator to the first cell of the bitmap. + **/ + //all_cells_iterator all_cells_begin() + //{ + // return this->data.begin(); + //} + + /** + * Function returning a constant iterator to the first cell of the bitmap. + **/ + //all_cells_const_iterator all_cells_begin() const + //{ + // return this->data.begin(); + //} + + /** + * Function returning an iterator to the last cell of the bitmap. + **/ + //all_cells_iterator all_cells_end() + //{ + // return this->data.end(); + //} + + /** + * Function returning a constant iterator to the last cell of the bitmap. + **/ + //all_cells_const_iterator all_cells_end() const + //{ + // return this->data.end(); + //} + + /** + * Iterator through all cells in the complex (in order they appear in the structure -- i.e. + * in lexicographical order). + **/ + class All_cells_iterator : std::iterator< std::input_iterator_tag, T > { - return this->data.end(); - } + public: + All_cells_iterator() + { + this->counter = 0; + } + All_cells_iterator operator++() + { + //first find first element of the counter that can be increased: + ++this->counter; + return *this; + } + All_cells_iterator operator++(int) + { + All_cells_iterator result = *this; + ++(*this); + return result; + } + All_cells_iterator operator =( const All_cells_iterator& rhs ) + { + this->counter = rhs.counter; + return *this; + } + bool operator == ( const All_cells_iterator& rhs )const + { + if ( this->counter != rhs.counter )return false; + return true; + } + bool operator != ( const All_cells_iterator& rhs )const + { + return !(*this == rhs); + } + size_t operator*() + { + return this->counter; + } + friend class Bitmap_cubical_complex_base; + protected: + size_t counter; + }; + /** - * Function returning an iterator to the first cell of the bitmap. + * Function returning a All_cells_iterator to the first cell of the bitmap. **/ - all_cells_iterator all_cells_begin() + All_cells_iterator all_cells_iterator_begin() { - return this->data.begin(); - } - + All_cells_iterator a; + return a; + } + /** - * Function returning a constant iterator to the first cell of the bitmap. + * Function returning a All_cells_iterator to the last cell of the bitmap. **/ - all_cells_const_iterator all_cells_begin() const + All_cells_iterator all_cells_iterator_end() { - return this->data.begin(); - } - + All_cells_iterator a; + a.counter = this->data.size(); + return a; + } + /** - * Function returning an iterator to the last cell of the bitmap. + * Boundary_range class provides ranges for boundary iterators. + **/ + typedef typename std::vector< size_t >::iterator Boundary_iterator; + typedef typename std::vector< size_t > Boundary_range; + + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. **/ - all_cells_iterator all_cells_end() + Boundary_range boundary_range(size_t sh) { - return this->data.end(); - } - + return this->get_boundary_of_a_cell(sh); + } + /** - * Function returning a constant iterator to the last cell of the bitmap. + * Coboundary_range class provides ranges for boundary iterators. + **/ + typedef typename std::vector< size_t >::iterator Coboundary_iterator; + typedef typename std::vector< size_t > Coboundary_range; + + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. **/ - all_cells_const_iterator all_cells_end() const + Coboundary_range coboundary_range(size_t sh) { - return this->data.end(); - } + return this->get_coboundary_of_a_cell(sh); + } + + + + + + + /** * Iterator through top dimensional cells of the complex. The cells appear in order they are stored * in the structure (i.e. in lexicographical order) **/ - class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > + class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, T > { public: Top_dimensional_cells_iterator( Bitmap_cubical_complex_base& b ):b(b) { - this->counter = std::vector(b.dimension()); - //std::fill( this->counter.begin() , this->counter.end() , 0 ); - } + this->counter = std::vector(b.dimension()); + //std::fill( this->counter.begin() , this->counter.end() , 0 ); + } Top_dimensional_cells_iterator operator++() { //first find first element of the counter that can be increased: @@ -308,15 +413,20 @@ public: return !(*this == rhs); } - T& operator*() - { - //given the counter, compute the index in the array and return this element. - unsigned index = 0; - for ( size_t i = 0 ; i != this->counter.size() ; ++i ) - { - index += (2*this->counter[i]+1)*this->b.multipliers[i]; - } - return this->b.data[index]; + //T& operator*() + //{ + // //given the counter, compute the index in the array and return this element. + // unsigned index = 0; + // for ( size_t i = 0 ; i != this->counter.size() ; ++i ) + // { + // index += (2*this->counter[i]+1)*this->b.multipliers[i]; + // } + // return this->b.data[index]; + //} + + size_t operator*() + { + return this->compute_index_in_bitmap(); } size_t compute_index_in_bitmap()const @@ -327,7 +437,8 @@ public: index += (2*this->counter[i]+1)*this->b.multipliers[i]; } return index; - } + } + void print_counter()const { @@ -340,19 +451,19 @@ public: protected: std::vector< size_t > counter; Bitmap_cubical_complex_base& b; - }; - + }; + /** - * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell cell of the bitmap. + * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell of the bitmap. **/ Top_dimensional_cells_iterator top_dimensional_cells_begin() { Top_dimensional_cells_iterator a(*this); return a; - } - + } + /** - * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell cell of the bitmap. + * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell of the bitmap. **/ Top_dimensional_cells_iterator top_dimensional_cells_end() { @@ -370,11 +481,11 @@ public: //****************************************************************************************************************// //****************************************************************************************************************// //****************************************************************************************************************// - - -inline size_t number_cells()const -{ - return this->total_number_of_cells; + + +inline size_t number_cells()const +{ + return this->total_number_of_cells; } //****************************************************************************************************************// @@ -412,7 +523,7 @@ protected: std::vector compute_counter_for_given_cell( size_t cell )const { - std::vector counter; + std::vector counter; counter.reserve( this->sizes.size() ); for ( size_t dim = this->sizes.size() ; dim != 0 ; --dim ) { @@ -421,59 +532,59 @@ protected: } std::reverse( counter.begin() , counter.end() ); return counter; - } - void read_perseus_style_file( const char* perseus_style_file ); - void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); - Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); - Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); + } + void read_perseus_style_file( const char* perseus_style_file ); + void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); + Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); + Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ); }; +template +void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) +{ + bool bdg = false; + + std::pair< T ,T > min_max = this->min_max_filtration(); + T dx = (min_max.second-min_max.first)/(T)number_of_bins; + + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + template -void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) -{ - bool bdg = false; - - std::pair< T ,T > min_max = this->min_max_filtration(); - T dx = (min_max.second-min_max.first)/(T)number_of_bins; - - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - -template -void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) -{ - bool bdg = false; - std::pair< T ,T > min_max = this->min_max_filtration(); - - size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - -template -std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() -{ - std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( this->data[i] < min_max.first )min_max.first = this->data[i]; - if ( this->data[i] > min_max.second )min_max.second = this->data[i]; - } - return min_max; -} +void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) +{ + bool bdg = false; + std::pair< T ,T > min_max = this->min_max_filtration(); + + size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + +template +std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() +{ + std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( this->data[i] < min_max.first )min_max.first = this->data[i]; + if ( this->data[i] > min_max.second )min_max.second = this->data[i]; + } + return min_max; +} template @@ -494,10 +605,10 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base { this->set_up_containers( sizes ); } - -template -void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) -{ + +template +void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) +{ this->set_up_containers( sizes_in_following_directions ); size_t number_of_top_dimensional_elements = 1; @@ -523,22 +634,22 @@ void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells size_t index = 0; for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) { - (*it) = top_dimensional_cells[index]; + this->get_cell_data(*it) = top_dimensional_cells[index]; ++index; } - this->impose_lower_star_filtration(); -} + this->impose_lower_star_filtration(); +} template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base ( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) { this->setup_bitmap_based_on_top_dimensional_cells_list( sizes_in_following_directions , top_dimensional_cells ); -} - -template -void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) -{ +} + +template +void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) +{ bool dbg = false; ifstream inFiltration, inIds; inFiltration.open( perseus_style_file ); @@ -547,7 +658,7 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;getchar();} - std::vector sizes; + std::vector sizes; sizes.reserve( dimensionOfData ); for ( size_t i = 0 ; i != dimensionOfData ; ++i ) { @@ -564,7 +675,7 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu while ( !inFiltration.eof() ) { - double filtrationLevel; + T filtrationLevel; inFiltration >> filtrationLevel; if ( dbg ) { @@ -574,35 +685,35 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) << " get the value : " << filtrationLevel << endl; } - *it = filtrationLevel; + this->get_cell_data(*it) = filtrationLevel; ++it; } inFiltration.close(); - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->read_perseus_style_file( perseus_style_file ); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->set_up_containers( sizes ); -} - -template + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->read_perseus_style_file( perseus_style_file ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->set_up_containers( sizes ); +} + +template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); } template @@ -615,29 +726,29 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const { - std::vector< size_t > boundary_elements; - - //Speed traded of for memory. Check if it is better in practice. - boundary_elements.reserve( this->dimension()*2 ); + std::vector< size_t > boundary_elements; + + //Speed traded of for memory. Check if it is better in practice. + boundary_elements.reserve( this->dimension()*2 ); size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { unsigned position = cell1/this->multipliers[i-1]; if ( position%2 == 1 ) - { - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + { + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); } cell1 = cell1%this->multipliers[i-1]; } return boundary_elements; -} - - - +} + + + template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const { @@ -662,8 +773,8 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( cell1 = cell1%this->multipliers[i-1]; } return coboundary_elements; -} - +} + @@ -712,14 +823,14 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() //this vector will be used to check which elements have already been taken care of //in imposing lower star filtration: std::vector is_this_cell_considered( this->data.size() , false ); - - size_t size_to_reserve = 1; - for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) - { - size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); - } - - std::vector indices_to_consider; + + size_t size_to_reserve = 1; + for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) + { + size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); + } + + std::vector indices_to_consider; indices_to_consider.reserve( size_to_reserve ); //we assume here that we already have a filtration on the top dimensional cells and //we have to extend it to lower ones. @@ -745,20 +856,20 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { std::vector bd = this->get_boundary_of_a_cell( indices_to_consider[i] ); for ( size_t boundaryIt = 0 ; boundaryIt != bd.size() ; ++boundaryIt ) - { - if ( dbg ) - { - cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; - getchar(); - + { + if ( dbg ) + { + cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; + getchar(); + } if ( this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ] ) { - this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; - if ( dbg ) - { - cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; - getchar(); + this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + if ( dbg ) + { + cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; + getchar(); } } if ( is_this_cell_considered[ bd[boundaryIt] ] == false ) @@ -797,4 +908,4 @@ bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , ch } -} +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 8c1254db..9a5ef0eb 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -121,7 +121,7 @@ void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_comp size_t i = 0; for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) { - *it = topDimensionalCells[i]; + this->get_cell_data(*it) = topDimensionalCells[i]; ++i; } this->impose_lower_star_filtration(); @@ -178,7 +178,7 @@ Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_comp << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) << " get the value : " << filtrationLevel << endl; } - *it = filtrationLevel; + this->get_cell_data(*it) = filtrationLevel; ++it; } inFiltration.close(); diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index 968483a3..c1c846c9 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -95,13 +95,13 @@ BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { int i = 0; for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { - BOOST_CHECK(*it == expectedFiltrationValues2[i]); + BOOST_CHECK(increasing.get_cell_data(*it) == expectedFiltrationValues2[i]); ++i; } i = 0; for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { - BOOST_CHECK(*it == expectedFiltrationValues1[i]); + BOOST_CHECK(hole.get_cell_data(*it) == expectedFiltrationValues1[i]); ++i; } } @@ -884,3 +884,182 @@ BOOST_AUTO_TEST_CASE(bitmap_2d_with_periodic_bcond_filtration) { BOOST_CHECK( filtration[i] == cmplx.get_cell_data(i) ); } } + +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + for ( Bitmap_cubical_complex_base::All_cells_iterator it = ba.all_cells_iterator_begin() ; it != ba.all_cells_iterator_end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} -- cgit v1.2.3 From 4b19b4553e909c46b1710fde0bec2b5702e1cb73 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 18 Mar 2016 15:07:43 +0000 Subject: Fix cpplint/cppcheck issues git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/witness@1054 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 9f850be55ab0565a2004ba23f6a5098aa227a92a --- .../concept/Simplicial_complex_for_witness.h | 6 +++--- .../example/witness_complex_from_file.cpp | 7 +------ src/Witness_complex/example/witness_complex_sphere.cpp | 7 +------ .../include/gudhi/Landmark_choice_by_furthest_point.h | 2 +- .../include/gudhi/Landmark_choice_by_random_point.h | 2 +- src/Witness_complex/include/gudhi/Witness_complex.h | 16 +++++----------- 6 files changed, 12 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/concept/Simplicial_complex_for_witness.h b/src/Witness_complex/concept/Simplicial_complex_for_witness.h index a4cf3c77..caaf0db6 100644 --- a/src/Witness_complex/concept/Simplicial_complex_for_witness.h +++ b/src/Witness_complex/concept/Simplicial_complex_for_witness.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_H_ -#define CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_H_ +#ifndef CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_FOR_WITNESS_H_ +#define CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_FOR_WITNESS_H_ namespace Gudhi { @@ -84,4 +84,4 @@ struct SimplicialComplexForWitness { } // namespace Gudhi -#endif // CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_H_ +#endif // CONCEPT_WITNESS_COMPLEX_SIMPLICIAL_COMPLEX_FOR_WITNESS_H_ diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/witness_complex_from_file.cpp index a8294bad..53207ad2 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/witness_complex_from_file.cpp @@ -34,14 +34,9 @@ #include #include -using namespace Gudhi; -using namespace Gudhi::witness_complex; - typedef std::vector< Vertex_handle > typeVectorVertex; typedef std::vector< std::vector > Point_Vector; -//typedef Witness_complex< Simplex_tree<> > WitnessComplex; - /** * \brief Customized version of read_points * which takes into account a possible nbP first line @@ -80,7 +75,7 @@ int main(int argc, char * const argv[]) { clock_t start, end; // Construct the Simplex Tree - Simplex_tree<> simplex_tree; + Gudhi::Simplex_tree<> simplex_tree; // Read the point file Point_Vector point_vector; diff --git a/src/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/witness_complex_sphere.cpp index 7bbf983a..b26c9f36 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/witness_complex_sphere.cpp @@ -39,11 +39,6 @@ #include "generators.h" -using namespace Gudhi; -using namespace Gudhi::witness_complex; - -typedef std::vector< Vertex_handle > typeVectorVertex; - /** Write a gnuplot readable file. * Data range is a random access range of pairs (arg, value) */ @@ -66,7 +61,7 @@ int main(int argc, char * const argv[]) { clock_t start, end; // Construct the Simplex Tree - Simplex_tree<> simplex_tree; + Gudhi::Simplex_tree<> simplex_tree; std::vector< std::pair > l_time; diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h index 472cc0f7..86d8ac61 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -31,7 +31,7 @@ namespace Gudhi { namespace witness_complex { - typedef std::vector typeVectorVertex; + typedef std::vector typeVectorVertex; /** * \ingroup witness_complex diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h index 7da74066..a73c04ac 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h @@ -68,7 +68,7 @@ namespace witness_complex { typedef bool (*comp)(dist_i, dist_i); knn = KNearestNeighbours(nbP); for (int points_i = 0; points_i < nbP; points_i++) { - std::priority_queue, comp> l_heap([&](dist_i j1, dist_i j2) { + std::priority_queue, comp> l_heap([](dist_i j1, dist_i j2) { return j1.first > j2.first; }); std::set::iterator landmarks_it; diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 60734efe..52f374f3 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -142,7 +142,7 @@ class Witness_complex { simplex_vector.push_back(knn[*it][i]); sc_.insert_simplex(simplex_vector); // TODO(SK) Error if not inserted : normally no need here though - it++; + ++it; } else { active_w.erase(it++); // First increase the iterator and then erase the previous element } @@ -196,7 +196,6 @@ class Witness_complex { // */ template< class KNearestNeighbors > bool is_witness_complex(KNearestNeighbors const & knn, bool print_output) { - // bool final_result = true; for (Simplex_handle sh : sc_.complex_simplex_range()) { bool is_witnessed = false; typeVectorVertex simplex; @@ -209,7 +208,6 @@ class Witness_complex { for (Vertex_handle v : simplex) if (std::find(w.begin(), w.begin() + nbV, v) == w.begin() + nbV) { has_vertices = false; - // break; } if (has_vertices) { is_witnessed = true; @@ -244,27 +242,23 @@ class Witness_complex { * basing on a matrix knn of * nearest neighbours of the form {witnesses}x{landmarks}. * - * The type KNearestNeighbors can be seen as + * The type KNearestNeighbors can be seen as * Witness_range>, where * Witness_range and Closest_landmark_range are random access ranges. * - * Procedure takes into account at most (dim+1) + * Procedure takes into account at most (dim+1) * first landmarks from each landmark range to construct simplices. * * Landmarks are supposed to be in [0,nbL_-1] */ - - template void witness_complex(KNearestNeighbors const & knn, int nbL, int dim, - SimplicialComplexForWitness & sc) - { - + SimplicialComplexForWitness & sc) { Witness_complex(knn, nbL, dim, sc); } - + } // namespace witness_complex } // namespace Gudhi -- cgit v1.2.3 From c19dafdee66ca80c5bf5e71129d9cca9b9243c92 Mon Sep 17 00:00:00 2001 From: glisse Date: Sun, 20 Mar 2016 13:04:38 +0000 Subject: Let the witness code match its doc better. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1057 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 99dc557a03f1ea85730ce286b80e384257ab2a77 --- .../include/gudhi/Landmark_choice_by_furthest_point.h | 14 +++++++++----- .../include/gudhi/Landmark_choice_by_random_point.h | 7 +++++-- src/Witness_complex/include/gudhi/Witness_complex.h | 5 ++--- 3 files changed, 16 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h index 86d8ac61..df93155b 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_furthest_point.h @@ -23,7 +23,10 @@ #ifndef LANDMARK_CHOICE_BY_FURTHEST_POINT_H_ #define LANDMARK_CHOICE_BY_FURTHEST_POINT_H_ +#include + #include // for numeric_limits<> +#include #include // for sort #include @@ -51,7 +54,7 @@ namespace witness_complex { void landmark_choice_by_furthest_point(Point_random_access_range const &points, int nbL, KNearestNeighbours &knn) { - int nb_points = points.end() - points.begin(); + int nb_points = boost::size(points); assert(nb_points >= nbL); // distance matrix witness x landmarks std::vector> wit_land_dist(nb_points, std::vector()); @@ -65,6 +68,7 @@ namespace witness_complex { std::vector< double > dist_to_L(nb_points, infty); // vector of current distances to L from points // TODO(SK) Consider using rand_r(...) instead of rand(...) for improved thread safety + // or better yet std::uniform_int_distribution int rand_int = rand() % nb_points; int curr_max_w = rand_int; // For testing purposes a pseudo-random number is used here @@ -73,7 +77,7 @@ namespace witness_complex { chosen_landmarks.push_back(curr_max_w); unsigned i = 0; for (auto& p : points) { - double curr_dist = euclidean_distance(p, *(points.begin() + chosen_landmarks[current_number_of_landmarks])); + double curr_dist = euclidean_distance(p, *(std::begin(points) + chosen_landmarks[current_number_of_landmarks])); wit_land_dist[i].push_back(curr_dist); knn[i].push_back(current_number_of_landmarks); if (curr_dist < dist_to_L[i]) @@ -87,9 +91,9 @@ namespace witness_complex { curr_max_w = i; } } - for (unsigned i = 0; i < nb_points; ++i) - std::sort(knn[i].begin(), - knn[i].end(), + for (int i = 0; i < nb_points; ++i) + std::sort(std::begin(knn[i]), + std::end(knn[i]), [&wit_land_dist, i](int a, int b) { return wit_land_dist[i][a] < wit_land_dist[i][b]; }); } diff --git a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h index a73c04ac..ebf6aad1 100644 --- a/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h +++ b/src/Witness_complex/include/gudhi/Landmark_choice_by_random_point.h @@ -23,8 +23,11 @@ #ifndef LANDMARK_CHOICE_BY_RANDOM_POINT_H_ #define LANDMARK_CHOICE_BY_RANDOM_POINT_H_ +#include + #include // for priority_queue<> #include // for pair<> +#include #include #include @@ -50,7 +53,7 @@ namespace witness_complex { void landmark_choice_by_random_point(Point_random_access_range const &points, int nbL, KNearestNeighbours &knn) { - int nbP = points.end() - points.begin(); + int nbP = boost::size(points); assert(nbP >= nbL); std::set landmarks; int current_number_of_landmarks = 0; // counter for landmarks @@ -63,7 +66,7 @@ namespace witness_complex { landmarks.insert(chosen_landmark); } - int dim = points.begin()->size(); + int dim = boost::size(*std::begin(points)); typedef std::pair dist_i; typedef bool (*comp)(dist_i, dist_i); knn = KNearestNeighbours(nbP); diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 52f374f3..489cdf11 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -28,8 +28,7 @@ #include #include -#include -#include +#include #include @@ -113,7 +112,7 @@ class Witness_complex { int dim, SimplicialComplex & sc) : nbL_(nbL), sc_(sc) { // Construction of the active witness list - int nbW = knn.size(); + int nbW = boost::size(knn); typeVectorVertex vv; int counter = 0; /* The list of still useful witnesses -- cgit v1.2.3 From 2e66c57e9290fd1ac0304dbd8050bb57ead4b683 Mon Sep 17 00:00:00 2001 From: glisse Date: Sun, 20 Mar 2016 13:22:02 +0000 Subject: Clarify some details in the concept FilteredComplex. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1058 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 825978488684e4dcf5b4fc491e6c4467332dbd20 --- src/Persistent_cohomology/concept/FilteredComplex.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Persistent_cohomology/concept/FilteredComplex.h b/src/Persistent_cohomology/concept/FilteredComplex.h index e124d524..e47babe4 100644 --- a/src/Persistent_cohomology/concept/FilteredComplex.h +++ b/src/Persistent_cohomology/concept/FilteredComplex.h @@ -43,7 +43,7 @@ struct FilteredComplex * is model of IndexingTag. */ typedef unspecified Indexing_tag; -/** Returns a Simplex_hanlde that is different from all simplex handles +/** Returns a Simplex_handle that is different from all simplex handles * of the simplices. */ Simplex_handle null_simplex(); /** \brief Returns the number of simplices in the complex. @@ -61,12 +61,13 @@ struct FilteredComplex /** \brief Returns a key that is different from the keys associated * to the simplices. */ Simplex_key null_key (); -/** \brief Returns the key associated to a simplex. */ +/** \brief Returns the key associated to a simplex. + * + * This is never called on null_simplex(). */ Simplex_key key ( Simplex_handle sh ); -/** \brief Returns the simplex associated to a key. - * - * If key is different from null_key(), returns the simplex that - * has index idx in the filtration. */ +/** \brief Returns the simplex that has index idx in the filtration. + * + * This is never called on null_key(). */ Simplex_handle simplex ( Simplex_key idx ); /** \brief Assign a key to a simplex. */ void assign_key(Simplex_handle sh, Simplex_key key); -- cgit v1.2.3 From 10083c1ed5ae478b54b6bb1b17be3325838533fe Mon Sep 17 00:00:00 2001 From: pdlotko Date: Sun, 20 Mar 2016 17:41:52 +0000 Subject: answering Marc's comments git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1059 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2f0e6e894c0c48ffc80a0864f4a4992066fd2273 --- src/Bitmap_cubical_complex/example/CMakeLists.txt | 5 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 137 +++---- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 426 +++++++++++++++++++++ 3 files changed, 493 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index 14c94e8e..088e6fbd 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -14,4 +14,7 @@ add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubi target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) #add_executable ( Compute_persistence_with_phat Compute_persistence_with_phat.cpp ) -#target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file +#target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) + +#add_executable ( periodic_boundary_conditions_phat periodic_boundary_conditions_phat.cpp ) +#target_link_libraries(periodic_boundary_conditions_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 6d2b705c..e081764c 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -161,96 +161,35 @@ public: } /** - * Writing to stream operator. + * Writing to stream operator. By using it we get the values T of cells in order in which they are stored in the structure. This procedure is used for debugging purposes. **/ template friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); /** - * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. + * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( size_t number_of_bins ) * ais designed for that purpose. The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. **/ - void put_data_toBins( size_t number_of_bins ); + void put_data_to_bins( size_t number_of_bins ); /** - * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. + * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( T diameter_of_bin ) is * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex * before and after using such a function will be bounded by the parameter diameter_of_bin. **/ - void put_data_toBins( T diameter_of_bin ); + void put_data_to_bins( T diameter_of_bin ); /** * Functions to find min and max values of filtration. **/ std::pair< T ,T > min_max_filtration(); - //ITERATORS - - /** - * Iterator through all cells in the complex (in order they appear in the structure -- i.e. - * in lexicographical order). - **/ - //typedef typename std::vector< T >::iterator all_cells_iterator; - - - /** - * Constant iterator through all cells in the complex (in order they appear in the structure -- i.e. - * in lexicographical order). - **/ - //typedef typename std::vector< T >::const_iterator all_cells_const_iterator; - - /** - * Function returning a constant iterator to the first cell of the bitmap. - **/ - //all_cells_const_iterator all_cells_const_begin()const - //{ - // return this->data.begin(); - //} - - - /** - * Function returning a constant iterator to the last cell of the bitmap. - **/ - //all_cells_const_iterator all_cells_const_end()const - //{ - // return this->data.end(); - //} - - /** - * Function returning an iterator to the first cell of the bitmap. - **/ - //all_cells_iterator all_cells_begin() - //{ - // return this->data.begin(); - //} - - /** - * Function returning a constant iterator to the first cell of the bitmap. - **/ - //all_cells_const_iterator all_cells_begin() const - //{ - // return this->data.begin(); - //} - - /** - * Function returning an iterator to the last cell of the bitmap. - **/ - //all_cells_iterator all_cells_end() - //{ - // return this->data.end(); - //} - - /** - * Function returning a constant iterator to the last cell of the bitmap. - **/ - //all_cells_const_iterator all_cells_end() const - //{ - // return this->data.end(); - //} - + //ITERATORS /** * Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). @@ -288,7 +227,12 @@ public: { return !(*this == rhs); } - + + /* + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * and in function get_cell_data to get a filtration of a cell. + */ size_t operator*() { return this->counter; @@ -317,10 +261,31 @@ public: return a; } + + /** + * All_cells_iterator_range class provides ranges for All_cells_iterator + **/ + class All_cells_iterator_range + { + public: + All_cells_iterator_range(Bitmap_cubical_complex_base* b):b(b){}; + All_cells_iterator begin() + { + return b->all_cells_iterator_begin(); + } + All_cells_iterator end() + { + return b->all_cells_iterator_end(); + } + private: + Bitmap_cubical_complex_base* b; + }; + + /** * Boundary_range class provides ranges for boundary iterators. **/ - typedef typename std::vector< size_t >::iterator Boundary_iterator; + typedef typename std::vector< size_t >::const_iterator Boundary_iterator; typedef typename std::vector< size_t > Boundary_range; /** @@ -424,6 +389,11 @@ public: // return this->b.data[index]; //} + /* + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * and in function get_cell_data to get a filtration of a cell. + */ size_t operator*() { return this->compute_index_in_bitmap(); @@ -474,7 +444,26 @@ public: } a.counter[0]++; return a; - } + } + + /** + * All_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range + **/ + class Top_dimensional_cells_iterator_range + { + public: + Top_dimensional_cells_iterator_range(Bitmap_cubical_complex_base* b):b(b){}; + Top_dimensional_cells_iterator begin() + { + return b->top_dimensional_cells_begin(); + } + Top_dimensional_cells_iterator end() + { + return b->top_dimensional_cells_end(); + } + private: + Bitmap_cubical_complex_base* b; + }; //****************************************************************************************************************// @@ -542,7 +531,7 @@ protected: template -void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) +void Bitmap_cubical_complex_base::put_data_to_bins( size_t number_of_bins ) { bool bdg = false; @@ -559,7 +548,7 @@ void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) } template -void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) +void Bitmap_cubical_complex_base::put_data_to_bins( T diameter_of_bin ) { bool bdg = false; std::pair< T ,T > min_max = this->min_max_filtration(); diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index c1c846c9..b7a1c8b6 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -1063,3 +1063,429 @@ BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical ++i; } } + + + + + + + + +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check_2) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + + Bitmap_cubical_complex_base::All_cells_iterator_range range(&ba); + for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} + + + + + + +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + + Bitmap_cubical_complex_base::All_cells_iterator_range range(&ba); + for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} + +BOOST_AUTO_TEST_CASE(Top_dimensional_cells_iterator_range_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator_range range(&ba); + for ( Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( data[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( ba.get_dimension_of_a_cell( *it ) == 2 ); + ++i; + } +} -- cgit v1.2.3 From 245a316b04bbf0883f17cc5116fb8f26251aabd4 Mon Sep 17 00:00:00 2001 From: glisse Date: Sun, 20 Mar 2016 18:22:24 +0000 Subject: Quiet a signed/unsigned comparison warning. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1060 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e7640912b59f8bb7357316e4a5cf3d75898dca21 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 096270ee..8a1a1344 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -576,7 +576,7 @@ class Simplex_tree { bool contiguous_vertices() const { if (root_.members_.empty()) return true; if (root_.members_.begin()->first != 0) return false; - if (std::prev(root_.members_.end())->first != root_.members_.size()-1) return false; + if (std::prev(root_.members_.end())->first != static_cast(root_.members_.size() - 1)) return false; return true; } -- cgit v1.2.3 From 04c63ee74520c966451b0cb1713df8b3e9ca5bfb Mon Sep 17 00:00:00 2001 From: pdlotko Date: Mon, 21 Mar 2016 08:21:22 +0000 Subject: Answers to comments. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1063 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 99cebe0573d75c98c8559ae4572b8f510e5cd9c0 --- .../include/gudhi/Bitmap_cubical_complex_base.h | 46 +++++++++++++--------- ...cal_complex_periodic_boundary_conditions_base.h | 6 +-- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 10 ++--- 3 files changed, 36 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index e081764c..f0517a86 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -170,7 +170,7 @@ public: /** * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( size_t number_of_bins ) + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_to_bins( size_t number_of_bins ) * ais designed for that purpose. The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. **/ void put_data_to_bins( size_t number_of_bins ); @@ -178,7 +178,7 @@ public: /** * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( T diameter_of_bin ) is + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_to_bins( T diameter_of_bin ) is * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex * before and after using such a function will be bounded by the parameter diameter_of_bin. **/ @@ -263,12 +263,12 @@ public: /** - * All_cells_iterator_range class provides ranges for All_cells_iterator + * All_cells_range class provides ranges for All_cells_iterator **/ - class All_cells_iterator_range + class All_cells_range { public: - All_cells_iterator_range(Bitmap_cubical_complex_base* b):b(b){}; + All_cells_range(Bitmap_cubical_complex_base* b):b(b){}; All_cells_iterator begin() { return b->all_cells_iterator_begin(); @@ -279,7 +279,12 @@ public: } private: Bitmap_cubical_complex_base* b; - }; + }; + + All_cells_range all_cells_range() + { + return All_cells_range(this); + } /** @@ -300,7 +305,7 @@ public: /** * Coboundary_range class provides ranges for boundary iterators. **/ - typedef typename std::vector< size_t >::iterator Coboundary_iterator; + typedef typename std::vector< size_t >::const_iterator Coboundary_iterator; typedef typename std::vector< size_t > Coboundary_range; /** @@ -426,7 +431,7 @@ public: /** * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell of the bitmap. **/ - Top_dimensional_cells_iterator top_dimensional_cells_begin() + Top_dimensional_cells_iterator top_dimensional_cells_iterator_begin() { Top_dimensional_cells_iterator a(*this); return a; @@ -435,7 +440,7 @@ public: /** * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell of the bitmap. **/ - Top_dimensional_cells_iterator top_dimensional_cells_end() + Top_dimensional_cells_iterator top_dimensional_cells_iterator_end() { Top_dimensional_cells_iterator a(*this); for ( size_t i = 0 ; i != this->dimension() ; ++i ) @@ -447,23 +452,28 @@ public: } /** - * All_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range + * Top_dimensional_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range **/ - class Top_dimensional_cells_iterator_range + class Top_dimensional_cells_range { public: - Top_dimensional_cells_iterator_range(Bitmap_cubical_complex_base* b):b(b){}; + Top_dimensional_cells_range(Bitmap_cubical_complex_base* b):b(b){}; Top_dimensional_cells_iterator begin() { - return b->top_dimensional_cells_begin(); + return b->top_dimensional_cells_iterator_begin(); } Top_dimensional_cells_iterator end() { - return b->top_dimensional_cells_end(); + return b->top_dimensional_cells_iterator_end(); } private: Bitmap_cubical_complex_base* b; - }; + }; + + Top_dimensional_cells_range top_dimensional_cells_range() + { + return Top_dimensional_cells_range(this); + } //****************************************************************************************************************// @@ -621,7 +631,7 @@ void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); size_t index = 0; - for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + for ( it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) { this->get_cell_data(*it) = top_dimensional_cells[index]; ++index; @@ -660,7 +670,7 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu this->set_up_containers( sizes ); Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_begin(); + it = this->top_dimensional_cells_iterator_begin(); while ( !inFiltration.eof() ) { @@ -824,7 +834,7 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() //we assume here that we already have a filtration on the top dimensional cells and //we have to extend it to lower ones. typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + for ( it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) { indices_to_consider.push_back( it.compute_index_in_bitmap() ); } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 9a5ef0eb..956e74a7 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -119,7 +119,7 @@ void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_comp this->set_up_containers( dimensions ); size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) { this->get_cell_data(*it) = topDimensionalCells[i]; ++i; @@ -162,7 +162,7 @@ Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_comp this->set_up_containers( sizes ); typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_begin(); + it = this->top_dimensional_cells_iterator_begin(); while ( !inFiltration.eof() ) { @@ -230,7 +230,7 @@ Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_comp this->set_up_containers( sizes ); size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) { *it = data[i]; ++i; diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index b7a1c8b6..35c54ade 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -94,13 +94,13 @@ BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { int i = 0; for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator - it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { + it = increasing.top_dimensional_cells_iterator_begin(); it != increasing.top_dimensional_cells_iterator_end(); ++it) { BOOST_CHECK(increasing.get_cell_data(*it) == expectedFiltrationValues2[i]); ++i; } i = 0; for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator - it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { + it = hole.top_dimensional_cells_iterator_begin(); it != hole.top_dimensional_cells_iterator_end(); ++it) { BOOST_CHECK(hole.get_cell_data(*it) == expectedFiltrationValues1[i]); ++i; } @@ -1229,7 +1229,7 @@ BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical int bd_it = 0; int cbd_it = 0; - Bitmap_cubical_complex_base::All_cells_iterator_range range(&ba); + Bitmap_cubical_complex_base::All_cells_range range(&ba); for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) { BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); @@ -1415,7 +1415,7 @@ BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical int bd_it = 0; int cbd_it = 0; - Bitmap_cubical_complex_base::All_cells_iterator_range range(&ba); + Bitmap_cubical_complex_base::All_cells_range range = ba.all_cells_range(); for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) { BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); @@ -1481,7 +1481,7 @@ BOOST_AUTO_TEST_CASE(Top_dimensional_cells_iterator_range_check) Bitmap_cubical_complex_base ba( sizes , data ); int i = 0; - Bitmap_cubical_complex_base::Top_dimensional_cells_iterator_range range(&ba); + Bitmap_cubical_complex_base::Top_dimensional_cells_range range = ba.top_dimensional_cells_range(); for ( Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it = range.begin() ; it != range.end() ; ++it ) { BOOST_CHECK( data[i] == ba.get_cell_data( *it ) ); -- cgit v1.2.3 From d1a3b2267b7e638b5d868720cf46987641b22132 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 29 Mar 2016 16:05:12 +0000 Subject: Merge VR_bitmap git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1074 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4c9ac225ffcfb924371c72fccc44cbd6ecb3d6e3 --- .../doc/Gudhi_Cubical_Complex_doc.h | 160 +- .../example/Bitmap_cubical_complex.cpp | 107 +- ...ubical_complex_periodic_boundary_conditions.cpp | 134 +- src/Bitmap_cubical_complex/example/CMakeLists.txt | 11 +- .../example/Random_bitmap_cubical_complex.cpp | 159 +- .../include/gudhi/Bitmap_cubical_complex.h | 1060 +++++------ .../include/gudhi/Bitmap_cubical_complex_base.h | 1499 ++++++++-------- ...cal_complex_periodic_boundary_conditions_base.h | 625 +++---- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 1837 +++++++++----------- 9 files changed, 2663 insertions(+), 2929 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index 00b39f01..cde0b2fc 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -21,64 +21,87 @@ */ -#pragma once +#ifndef DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_ +#define DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_ -namespace Gudhi -{ +namespace Gudhi { -namespace Cubical_complex -{ +namespace Cubical_complex { /** \defgroup cubical_complex Cubical complex -* -* \author Pawel Dlotko -* -* @{ -* - -*Bitmap_cubical_complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. -* -* An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} \f$. The first one is called non-degenerate, while the second one is \a degenerate interval. A boundary of a elementary -*interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of non-degenerate elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerate elementary interval. An elementary cube \f$ C \f$ is a + * + * \author Pawel Dlotko + * + * @{ + * -*product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$. Embedding dimension of a cube is n, the number of elementary intervals (degenerate or not) in the product. A dimension of a cube \f$C=I_1 \times ... \times I_n\f$ is the -*number of non degenerate elementary intervals in the product. A boundary of a cube \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained in the following way: -*\f[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\f] -*A cubical complex \f$\mathcal{K}\f$ is a collection of cubes closed under operation of taking boundary (i.e. boundary of every cube from the collection is in the collection). A cube \f$C\f$ in cubical complex \f$\mathcal{K}\f$ is maximal if it is not in -*a boundary of any other cube in \f$\mathcal{K}\f$. A \a support of a cube \f$C\f$ is the set in \f$\mathbb{R}^n\f$ occupied by \f$C\f$ (\f$n\f$ is the embedding dimension of \f$C\f$). -* -*Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may be a set of two elements). -* -*For further details and theory of cubical complexes, please consult \cite kaczynski2004computational as well as the following paper \cite peikert2012topological . -* -*\section datastructure Data structure. -* -*The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in \f$\mathbb{R}^n\f$. This extra -*assumption allows for a memory efficient way of storing cubical complexes in a form of so called bitmaps. Let \f$R = [b_1,e_1] \times \ldots \times [b_n,e_n]\f$, for \f$b_1,...b_n,e_1,...,e_n \in \mathbb{Z}\f$ -*, \f$b_i \leq d_i\f$ be the considered rectangular region and let \f$\mathcal{K}\f$ be a filtered cubical complex having the rectangle \f$R\f$ as its support. Note that the structure of the coordinate system gives a way -*a lexicographical ordering of cells of \f$\mathcal{K}\f$. This ordering is a base of the presented bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector -*of the values of filtration. This, together with dimension of \f$\mathcal{K}\f$ and the sizes of \f$\mathcal{K}\f$ in all directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube \f$C \in \mathcal{K}\f$. -* -*\image html "bitmapAllCubes.png" "Cubical complex. -* -*Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical complexes in \f$\mathbb{R}\f$. The number of all cubes in each direction is -*equal \f$2n+1\f$, where \f$n\f$ is the number of maximal cubes in the considered direction. Let us consider a cube at the position \f$k\f$ in the bitmap. Knowing the sizes of the bitmap, -*by a series of modulo operation, we can determine which elementary intervals are present in the product that gives the cube \f$C\f$. In a similar way, we can compute boundary -*and the coboundary of each cube. Further details can be found in the literature. -* -*\section inputformat Input Format. -* -*In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star filtration to all cubes. There are a number of constructors -*that can be used to construct cubical complex by users who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class. -*Currently one input from a text file is used. It uses a format used already in Perseus software (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. -*Below we are providing a description of the format. The first line contains a number d begin the dimension of the bitmap (2 in the example below). Next d lines are the numbers of -*top dimensional cubes in each dimensions (3 and 3 in the example below). Next, in lexicographical order, the filtration of top dimensional cubes is given (1 4 6 8 20 4 7 6 5 in the example below). -* -* -*\image html "exampleBitmap.png" "Example of a input data." -* -*The input file for the following complex is: -*\verbatim + * Bitmap_cubical_complex is an example of a structured complex useful in computational mathematics (specially rigorous + * numerics) and image analysis. The presented implementation of cubical complexes is based on the following + * definition. + * + * An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} + * \f$. The first one is called non-degenerate, while the second one is \a degenerate interval. A + * boundary of a elementary interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of + * non-degenerated elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerate elementary interval. An + * elementary cube \f$ C \f$ is a product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$. + * Embedding dimension of a cube is n, the number of elementary intervals (degenerate or not) in the product. + * A dimension of a cube \f$C=I_1 \times ... \times I_n\f$ is the number of non degenerate elementary + * intervals in the product. A boundary of a cube \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained + * in the following way: + * \f[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + + * \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\f] + * A cubical complex \f$\mathcal{K}\f$ is a collection of cubes closed under operation of taking boundary + * (i.e. boundary of every cube from the collection is in the collection). A cube \f$C\f$ in cubical complex + * \f$\mathcal{K}\f$ is maximal if it is not in a boundary of any other cube in \f$\mathcal{K}\f$. A \a + * support of a cube \f$C\f$ is the set in \f$\mathbb{R}^n\f$ occupied by \f$C\f$ (\f$n\f$ is the embedding dimension + * of \f$C\f$). + * + * Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical + * complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may + * be a set of two elements). + * + * For further details and theory of cubical complexes, please consult \cite kaczynski2004computational as well as the + * following paper \cite peikert2012topological . + * + * \section datastructure Data structure. + * + * The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in + * \f$\mathbb{R}^n\f$. This extra assumption allows for a memory efficient way of storing cubical complexes in a form + * of so called bitmaps. Let \f$R = [b_1,e_1] \times \ldots \times [b_n,e_n]\f$, for \f$b_1,...b_n,e_1,...,e_n \in + * \mathbb{Z}\f$, \f$b_i \leq d_i\f$ be the considered rectangular region and let \f$\mathcal{K}\f$ be a filtered + * cubical complex having the rectangle \f$R\f$ as its support. Note that the structure of the coordinate system gives + * a way a lexicographical ordering of cells of \f$\mathcal{K}\f$. This ordering is a base of the presented + * bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector of the values + * of filtration. This, together with dimension of \f$\mathcal{K}\f$ and the sizes of \f$\mathcal{K}\f$ in all + * directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube \f$C \in + * \mathcal{K}\f$. + * + * \image html "bitmapAllCubes.png" "Cubical complex. + * + * Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical + * complexes in \f$\mathbb{R}\f$. The number of all cubes in each direction is equal \f$2n+1\f$, where \f$n\f$ is the + * number of maximal cubes in the considered direction. Let us consider a cube at the position \f$k\f$ in the bitmap. + * Knowing the sizes of the bitmap, by a series of modulo operation, we can determine which elementary intervals are + * present in the product that gives the cube \f$C\f$. In a similar way, we can compute boundary and the coboundary of + * each cube. Further details can be found in the literature. + * + * \section inputformat Input Format. + * + * In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star + * filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users + * who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class. + * Currently one input from a text file is used. It uses a format used already in Perseus software + * (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. + * Below we are providing a description of the format. The first line contains a number d begin the dimension of the + * bitmap (2 in the example below). Next d lines are the numbers of top dimensional cubes in each dimensions (3 and 3 + * in the example below). Next, in lexicographical order, the filtration of top dimensional cubes is given (1 4 6 8 + * 20 4 7 6 5 in the example below). + * + * + * \image html "exampleBitmap.png" "Example of a input data." + * + * The input file for the following complex is: + * \verbatim 2 3 3 @@ -93,15 +116,17 @@ namespace Cubical_complex 5 \endverbatim -\section PeriodicBoundaryConditions Periodic boundary conditions -Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times I_n \f$ be a box -that is decomposed with a cubical complex \f$ \mathcal{K} \f$. Imposing periodic boundary conditions in the direction i, means that the left and the right side of a complex -\f$ \mathcal{K} \f$ are considered the same. In particular, if for a bitmap \f$ \mathcal{K} \f$ periodic boundary conditions are imposed in all directions, then complex -\f$ \mathcal{K} \f$ became n-dimensional torus. One can use various constructors from the file Bitmap_cubical_complex_periodic_boundary_conditions_base.h to construct cubical -complex with periodic boundary conditions. One can also use Perseus style input files. To indicate periodic boundary conditions in a given direction, then number of top dimensional cells -in this direction have to be multiplied by -1. For instance: + * \section PeriodicBoundaryConditions Periodic boundary conditions + * Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times + * I_n \f$ be a box that is decomposed with a cubical complex \f$ \mathcal{K} \f$. Imposing periodic boundary + * conditions in the direction i, means that the left and the right side of a complex \f$ \mathcal{K} \f$ are + * considered the same. In particular, if for a bitmap \f$ \mathcal{K} \f$ periodic boundary conditions are imposed + * in all directions, then complex \f$ \mathcal{K} \f$ became n-dimensional torus. One can use various constructors + * from the file Bitmap_cubical_complex_periodic_boundary_conditions_base.h to construct cubical complex with periodic + * boundary conditions. One can also use Perseus style input files. To indicate periodic boundary conditions in a + * given direction, then number of top dimensional cells in this direction have to be multiplied by -1. For instance: -*\verbatim + *\verbatim 2 -3 3 @@ -116,15 +141,16 @@ in this direction have to be multiplied by -1. For instance: 5 \endverbatim -Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. + * Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. * \section BitmapExamples Examples * End user programs are available in example/Bitmap_cubical_complex folder. - -*/ + */ /** @} */ // end defgroup cubical_complex -*@}//end of the group -} -} +} // namespace Cubical_complex + +} // namespace Gudhi + +#endif // DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_ diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index 4c30ee85..7c7e8ac5 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -1,73 +1,72 @@ - /* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Saclay (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 . - */ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff +// standard stuff #include #include #include -using namespace std; +int main(int argc, char** argv) { + std::cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical " << + "complexes provided in text files in Perseus style (the only numbered in the first line is a dimension D of a" << + "bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let " << + "N denote product of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are " << + "filtrations of top dimensional cells. We assume that the cells are in the lexicographical order. See " << + "CubicalOneSphere.txt or CubicalTwoSphere.txt for example.\n" << std::endl; + int p = 2; + double min_persistence = 0; -int main( int argc , char** argv ) -{ - cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbered in \ -the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + if (argc != 2) { + std::cerr << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at " << + "the input. The program will now terminate.\n"; + return 1; + } - int p = 2; - double min_persistence = 0; + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex_base Bitmap_cubical_complex_base; + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex Bitmap_cubical_complex; + typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp; + typedef Gudhi::persistent_cohomology::Persistent_cohomology Persistent_cohomology; - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } + Bitmap_cubical_complex b(argv[1]); - Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); + // Compute the persistence diagram of the complex + Persistent_cohomology pcoh(b); + pcoh.init_coefficients(p); // initializes the coefficient field for homology + pcoh.compute_persistent_cohomology(min_persistence); - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + std::stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out(ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); - pcoh.compute_persistent_cohomology( min_persistence ); + std::cout << "Result in file: " << ss.str().c_str() << "\n"; - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out((char*)ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 0; + return 0; } + diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp index df01240b..2c5d7fd3 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp @@ -1,24 +1,24 @@ - /* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Saclay (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 . - */ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 @@ -26,59 +26,49 @@ #include #include -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff +// standard stuff #include #include #include -using namespace std; - -int main( int argc , char** argv ) -{ - clock_t beginOfProgram = clock(); - - cout << "This program computes persistent homology, by using Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in Perseus style (the only numbered in \ -the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; - - int p = 2; - double min_persistence = 0; - - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > b( argv[1] ); - - cerr << "Here \n"; - - clock_t endCreateBitmap = clock(); - double elapsed_secsCreateBitmap = double(endCreateBitmap - beginOfProgram) / CLOCKS_PER_SEC; - cerr << "Time of creation of bitmap : " << elapsed_secsCreateBitmap << endl; - - - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base >, Field_Zp > pcoh(b,true); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology - pcoh.compute_persistent_cohomology( min_persistence ); - - - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out((char*)ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - clock_t endOfProgram = clock(); - double elapsed_secsOfProgram = double(endOfProgram - beginOfProgram) / CLOCKS_PER_SEC; - cerr << "Overall execution time : " << elapsed_secsOfProgram << endl; - return 0; +int main(int argc, char** argv) { + std::cout << "This program computes persistent homology, by using " << + "Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in " << + "Perseus style (the only numbered in the first line is a dimension D of a bitmap. In the lines I between 2 " << + "and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product of the numbers " << + "in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We " << + "assume that the cells are in the lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for" << + " example.\n" << std::endl; + + int p = 2; + double min_persistence = 0; + + if (argc != 2) { + std::cerr << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at " << + "the input. The program will now terminate.\n"; + return 1; + } + + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base Bitmap_base; + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex< Bitmap_base > Bitmap_cubical_complex; + + Bitmap_cubical_complex b(argv[1]); + + typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp; + typedef Gudhi::persistent_cohomology::Persistent_cohomology Persistent_cohomology; + // Compute the persistence diagram of the complex + Persistent_cohomology pcoh(b, true); + pcoh.init_coefficients(p); // initializes the coefficient field for homology + pcoh.compute_persistent_cohomology(min_persistence); + + std::stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out(ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + std::cout << "Result in file: " << ss.str().c_str() << "\n"; + + return 0; } + diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index 088e6fbd..8f9cfa80 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -3,8 +3,8 @@ project(GUDHIBitmap) add_executable ( Bitmap_cubical_complex Bitmap_cubical_complex.cpp ) target_link_libraries(Bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) -add_test(Bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalOneSphere.txt) -add_test(Bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) +add_test(Bitmap_cubical_complex_one_sphere ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalOneSphere.txt) +add_test(Bitmap_cubical_complex_two_sphere ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) add_executable ( Random_bitmap_cubical_complex Random_bitmap_cubical_complex.cpp ) target_link_libraries(Random_bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) @@ -12,9 +12,6 @@ add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubical_complex_periodic_boundary_conditions.cpp ) target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) +add_test(Bitmap_cubical_complex_periodic_2d_torus ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex_periodic_boundary_conditions ${CMAKE_SOURCE_DIR}/data/bitmap/2d_torus.txt) +add_test(Bitmap_cubical_complex_periodic_3d_torus ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex_periodic_boundary_conditions ${CMAKE_SOURCE_DIR}/data/bitmap/3d_torus.txt) -#add_executable ( Compute_persistence_with_phat Compute_persistence_with_phat.cpp ) -#target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) - -#add_executable ( periodic_boundary_conditions_phat periodic_boundary_conditions_phat.cpp ) -#target_link_libraries(periodic_boundary_conditions_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index 8b7f6a04..416ad8f2 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -1,94 +1,83 @@ - /* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Saclay (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 . - */ - - -//for persistence algorithm +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 . + */ + + +// for persistence algorithm #include #include #include - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff +// standard stuff #include #include #include -using namespace std; - -int main( int argc , char** argv ) -{ - srand( time(0) ); - - cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes. \ -The first parameter of the program is the dimension D of the bitmap. \ -The next D parameters are number of top dimensional cubes in each dimension of the bitmap.\ -The program will create random cubical complex of that sizes and compute persistent homology of it." << endl; - - int p = 2; - double min_persistence = 0; - - if ( argc < 3 ) - { - cerr << "Wrong number of parameters, the program will now terminate\n"; - return 1; - } - - size_t dimensionOfBitmap = (size_t)atoi( argv[1] ); - std::vector< unsigned > sizes; - size_t multipliers = 1; - for ( size_t dim = 0 ; dim != dimensionOfBitmap ; ++dim ) - { - unsigned sizeInThisDimension = (unsigned)atoi( argv[2+dim] ); - sizes.push_back( sizeInThisDimension ); - multipliers *= sizeInThisDimension; - } - - std::vector< double > data; - for ( size_t i = 0 ; i != multipliers ; ++i ) - { - data.push_back( rand()/(double)RAND_MAX ); - } - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( sizes , data ); - - - - - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology - pcoh.compute_persistent_cohomology( min_persistence ); - - - stringstream ss; - ss << "randomComplex_persistence"; - std::ofstream out(ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 0; +int main(int argc, char** argv) { + srand(time(0)); + + std::cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical " << + "complexes. The first parameter of the program is the dimension D of the bitmap. The next D parameters are " << + "number of top dimensional cubes in each dimension of the bitmap. The program will create random cubical " << + "complex of that sizes and compute persistent homology of it." << std::endl; + + int p = 2; + double min_persistence = 0; + + if (argc < 3) { + std::cerr << "Wrong number of parameters, the program will now terminate\n"; + return 1; + } + + size_t dimensionOfBitmap = (size_t) atoi(argv[1]); + std::vector< unsigned > sizes; + size_t multipliers = 1; + for (size_t dim = 0; dim != dimensionOfBitmap; ++dim) { + unsigned sizeInThisDimension = (unsigned) atoi(argv[2 + dim]); + sizes.push_back(sizeInThisDimension); + multipliers *= sizeInThisDimension; + } + + std::vector< double > data; + for (size_t i = 0; i != multipliers; ++i) { + data.push_back(rand() / static_cast(RAND_MAX)); + } + + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex_base Bitmap_cubical_complex_base; + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex Bitmap_cubical_complex; + Bitmap_cubical_complex b(sizes, data); + + // Compute the persistence diagram of the complex + typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp; + typedef Gudhi::persistent_cohomology::Persistent_cohomology Persistent_cohomology; + Persistent_cohomology pcoh(b); + pcoh.init_coefficients(p); // initializes the coefficient field for homology + pcoh.compute_persistent_cohomology(min_persistence); + + std::stringstream ss; + ss << "randomComplex_persistence"; + std::ofstream out(ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; } + diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 4dd295e7..1fd36914 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -20,28 +20,28 @@ * along with this program. If not, see . */ +#ifndef BITMAP_CUBICAL_COMPLEX_H_ +#define BITMAP_CUBICAL_COMPLEX_H_ -#pragma once -#include -#include -#include "Bitmap_cubical_complex_base.h" -#include "Bitmap_cubical_complex_periodic_boundary_conditions_base.h" - +#include +#include +#include +#include // for pair<> +#include // for sort +#include -namespace Gudhi -{ +namespace Gudhi { -namespace Cubical_complex -{ +namespace Cubical_complex { -//global variable, was used just for debugging. +// global variable, was used just for debugging. const bool globalDbg = false; -template class is_before_in_filtration; - +template class is_before_in_filtration; + /** -* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into +* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into * Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template parameter is supposed to be either Bitmap_cubical_complex_base or Bitmap_cubical_complex_periodic_boundary_conditions_base class. **/ @@ -51,529 +51,533 @@ template class is_before_in_filtration; *@ingroup cubical_complex */ template -class Bitmap_cubical_complex : public T -{ -public: -//*********************************************// -//Typedefs and typenames -//*********************************************// - typedef size_t Simplex_key; - typedef typename T::filtration_type Filtration_value; - typedef Simplex_key Simplex_handle; - - -//*********************************************// -//Constructors -//*********************************************// - //Over here we need to definie various input types. I am proposing the following ones: - //Perseus style - //H5 files? TODO - //binary files with little endiangs / big endians? TODO - //constructor from a vector of elements of a type T. TODO - - /** - * Constructor form a Perseus-style file. - **/ - Bitmap_cubical_complex( const char* perseus_style_file ): - T(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) - { - //clock_t begin = clock(); - if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} - for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) - { - this->key_associated_to_simplex[i] = i; - } - //we initialize this only once, in each constructor, when the bitmap is constructed. - //If the user decide to change some elements of the bitmap, then this procedure need - //to be called again. - this->initialize_simplex_associated_to_key(); - //cerr << "Time of running Bitmap_cubical_complex( const char* perseus_style_file ) constructor : " << double(clock() - begin) / CLOCKS_PER_SEC << endl; - } - - - /** - * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells - * in the following directions and vector of element of a type T - * with filtration on top dimensional cells. - **/ - Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells ): - T(dimensions,top_dimensional_cells), - key_associated_to_simplex(this->total_number_of_cells+1) - { - for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) - { - this->key_associated_to_simplex[i] = i; - } - //we initialize this only once, in each constructor, when the bitmap is constructed. - //If the user decide to change some elements of the bitmap, then this procedure need - //to be called again. - this->initialize_simplex_associated_to_key(); - } - - /** - * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells - * in the following directions and vector of element of a type T::filtration_type - * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. - * If the position i on this vector is true, then we impose periodic boundary conditions in this direction. - **/ - Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ): - T(dimensions,top_dimensional_cells,directions_in_which_periodic_b_cond_are_to_be_imposed), - key_associated_to_simplex(this->total_number_of_cells+1) - { - for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) - { - this->key_associated_to_simplex[i] = i; - } - //we initialize this only once, in each constructor, when the bitmap is constructed. - //If the user decide to change some elements of the bitmap, then this procedure need - //to be called again. - this->initialize_simplex_associated_to_key(); - } - - /** - * Destructor of the Bitmap_cubical_complex class. - **/ - virtual ~Bitmap_cubical_complex(){} - - -//*********************************************// -//Other 'easy' functions -//*********************************************// - /** - * Returns number of all cubes in the complex. - **/ - size_t num_simplices()const - { - return this->total_number_of_cells; - } - - /** - * Returns a Simplex_handle to a cube that do not exist in this complex. - **/ - static Simplex_handle null_simplex() - { - if ( globalDbg ){cerr << "Simplex_handle null_simplex()\n";} - return std::numeric_limits::max(); - } - - - /** - * Returns dimension of the complex. - **/ - inline size_t dimension()const - { - return this->sizes.size(); - } - - /** - * Return dimension of a cell pointed by the Simplex_handle. - **/ - inline unsigned dimension(Simplex_handle sh)const - { - if ( globalDbg ){cerr << "unsigned dimension(const Simplex_handle& sh)\n";} - if ( sh != std::numeric_limits::max() ) return this->get_dimension_of_a_cell( sh ); - return -1; - } - - /** - * Return the filtration of a cell pointed by the Simplex_handle. - **/ - typename T::filtration_type filtration(Simplex_handle sh) - { - if ( globalDbg ){cerr << "T::filtration_type filtration(const Simplex_handle& sh)\n";} - //Returns the filtration value of a simplex. - if ( sh != std::numeric_limits::max() ) return this->data[sh]; - return std::numeric_limits::max(); - } - - /** - * Return a key which is not a key of any cube in the considered data structure. - **/ - static Simplex_key null_key() - { - if ( globalDbg ){cerr << "Simplex_key null_key()\n";} - return std::numeric_limits::max(); - } - - /** - * Return the key of a cube pointed by the Simplex_handle. - **/ - Simplex_key key(Simplex_handle sh)const - { - if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} - if ( sh != std::numeric_limits::max() ) - { - return this->key_associated_to_simplex[sh]; - } - return this->null_key(); - } - - /** - * Return the Simplex_handle given the key of the cube. - **/ - Simplex_handle simplex(Simplex_key key) - { - if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} - if ( key != std::numeric_limits::max() ) - { - return this->simplex_associated_to_key[ key ]; - } - return null_simplex(); - } - - /** - * Assign key to a cube pointed by the Simplex_handle - **/ - void assign_key(Simplex_handle sh, Simplex_key key) - { - if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} - if ( key == std::numeric_limits::max() ) return; - this->key_associated_to_simplex[sh] = key; - this->simplex_associated_to_key[key] = sh; - } - - /** - * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. - **/ - void initialize_simplex_associated_to_key(); - - - -//*********************************************// -//Iterators -//*********************************************// - - - - /** - * Boundary_simplex_range class provides ranges for boundary iterators. - **/ - typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; - typedef typename std::vector< Simplex_handle > Boundary_simplex_range; - - - - /** - * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. - * Secondary criteria for filtration are: - * (1) Dimension of a cube (lower dimensional comes first). - * (2) Position in the data structure (the ones that are earlies in the data structure comes first). - **/ - class Filtration_simplex_range; - class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > - { - //Iterator over all simplices of the complex in the order of the indexing scheme. - //'value_type' must be 'Simplex_handle'. - public: - Filtration_simplex_iterator( Bitmap_cubical_complex* b ):b(b),position(0){}; - Filtration_simplex_iterator():b(NULL){}; - - Filtration_simplex_iterator operator++() - { - if ( globalDbg ){cerr << "Filtration_simplex_iterator operator++\n";} - ++this->position; - return (*this); - } - Filtration_simplex_iterator operator++(int) - { - Filtration_simplex_iterator result = *this; - ++(*this); - return result; - } - Filtration_simplex_iterator operator =( const Filtration_simplex_iterator& rhs ) - { - if ( globalDbg ){cerr << "Filtration_simplex_iterator operator =\n";} - this->b = rhs.b; - this->position = rhs.position; - } - bool operator == ( const Filtration_simplex_iterator& rhs )const - { - if ( globalDbg ){cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n";} - return ( this->position == rhs.position ); - } - - bool operator != ( const Filtration_simplex_iterator& rhs )const - { - if ( globalDbg ){cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n";} - return !(*this == rhs); - } - Simplex_handle operator*() - { - if ( globalDbg ){cerr << "Simplex_handle operator*()\n";} - return this->b->simplex_associated_to_key[ this->position ]; - } - - friend class Filtration_simplex_range; - private: - Bitmap_cubical_complex* b; - size_t position; - }; - - - /** - * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. - **/ - class Filtration_simplex_range - { - //Range over the simplices of the complex in the order of the filtration. - //.begin() and .end() return type Filtration_simplex_iterator. - public: - typedef Filtration_simplex_iterator const_iterator; - typedef Filtration_simplex_iterator iterator; - Filtration_simplex_range(Bitmap_cubical_complex* b):b(b){}; - Filtration_simplex_iterator begin() - { - if ( globalDbg ){cerr << "Filtration_simplex_iterator begin() \n";} - return Filtration_simplex_iterator( this->b ); - } - Filtration_simplex_iterator end() - { - if ( globalDbg ){cerr << "Filtration_simplex_iterator end()\n";} - Filtration_simplex_iterator it( this->b ); - it.position = this->b->simplex_associated_to_key.size(); - return it; - } - private: - Bitmap_cubical_complex* b; - }; - - - -//*********************************************// -//Methods to access iterators from the container: - /** - * boundary_simplex_range creates an object of a Boundary_simplex_range class - * that provides ranges for the Boundary_simplex_iterator. - **/ - Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) - { - /* - std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh); - Boundary_simplex_range result( bdry.size() ); - for ( size_t i = 0 ; i != bdry.size() ; ++i ) - { - result[i] = this->simplex_associated_to_key[ bdry[i] ]; - } - return result; - */ - return this->get_boundary_of_a_cell(sh); - } - - /** - * filtration_simplex_range creates an object of a Filtration_simplex_range class - * that provides ranges for the Filtration_simplex_iterator. - **/ - Filtration_simplex_range filtration_simplex_range() - { - if ( globalDbg ){cerr << "Filtration_simplex_range filtration_simplex_range()\n";} - //Returns a range over the simplices of the complex in the order of the filtration - return Filtration_simplex_range(this); - } -//*********************************************// - - - -//*********************************************// -//Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are there. - //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so - //I understand that this is something that was planned (for simplicial maps?) - //but was never finished. The only idea I have here is to use the same empty structure from - //IndexingTag.h file, but only if the compiler needs it. If the compiler - //do not need it, then I would rather not add here elements which I do not understand. - //typedef Indexing_tag - /** - * Function needed for compatibility with Gudhi. Not useful for other purposes. - **/ - std::pair endpoints( Simplex_handle sh ) - { - std::vector< size_t > bdry = this->get_boundary_of_a_cell( sh ); - if ( globalDbg ) - { - cerr << "std::pair endpoints( Simplex_handle sh )\n"; - cerr << "bdry.size() : " << bdry.size() << endl; - } - //this method returns two first elements from the boundary of sh. - if ( bdry.size() < 2 ) - throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the boundary."); - return std::make_pair( bdry[0] , bdry[1] ); - } - - - /** - * Class needed for compatibility with Gudhi. Not useful for other purposes. - **/ - class Skeleton_simplex_range; - class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > - { - //Iterator over all simplices of the complex in the order of the indexing scheme. - //'value_type' must be 'Simplex_handle'. - public: - Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d ):b(b),dimension(d) - { - if ( globalDbg ){cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n";} - //find the position of the first simplex of a dimension d - this->position = 0; - while ( - (this->position != b->data.size()) && - ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) - ) - { - ++this->position; - } - }; - Skeleton_simplex_iterator ():b(NULL),dimension(0){}; - - Skeleton_simplex_iterator operator++() - { - if ( globalDbg ){cerr << "Skeleton_simplex_iterator operator++()\n";} - //increment the position as long as you did not get to the next element of the dimension dimension. - ++this->position; - while ( - (this->position != this->b->data.size()) && - ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) - ) - { - ++this->position; - } - return (*this); - } - Skeleton_simplex_iterator operator++(int) - { - Skeleton_simplex_iterator result = *this; - ++(*this); - return result; - } - Skeleton_simplex_iterator operator =( const Skeleton_simplex_iterator& rhs ) - { - if ( globalDbg ){cerr << "Skeleton_simplex_iterator operator =\n";} - this->b = rhs.b; - this->position = rhs.position; - } - bool operator == ( const Skeleton_simplex_iterator& rhs )const - { - if ( globalDbg ){cerr << "bool operator ==\n";} - return ( this->position == rhs.position ); - } - - bool operator != ( const Skeleton_simplex_iterator& rhs )const - { - if ( globalDbg ){cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n";} - return !(*this == rhs); - } - Simplex_handle operator*() - { - if ( globalDbg ){cerr << "Simplex_handle operator*() \n";} - return this->position; - } - - friend class Skeleton_simplex_range; - private: - Bitmap_cubical_complex* b; - size_t position; - unsigned dimension; - }; - /** - * Class needed for compatibility with Gudhi. Not useful for other purposes. - **/ - class Skeleton_simplex_range - { - //Range over the simplices of the complex in the order of the filtration. - //.begin() and .end() return type Filtration_simplex_iterator. - public: - typedef Skeleton_simplex_iterator const_iterator; - typedef Skeleton_simplex_iterator iterator; - Skeleton_simplex_range(Bitmap_cubical_complex* b , unsigned dimension):b(b),dimension(dimension){}; - Skeleton_simplex_iterator begin() - { - if ( globalDbg ){cerr << "Skeleton_simplex_iterator begin()\n";} - return Skeleton_simplex_iterator( this->b , this->dimension ); - } - Skeleton_simplex_iterator end() - { - if ( globalDbg ){cerr << "Skeleton_simplex_iterator end()\n";} - Skeleton_simplex_iterator it( this->b , this->dimension ); - it.position = this->b->data.size(); - return it; - } - private: - Bitmap_cubical_complex* b; - unsigned dimension; - }; - - /** - * Function needed for compatibility with Gudhi. Not useful for other purposes. - **/ - Skeleton_simplex_range skeleton_simplex_range( unsigned dimension ) - { - if ( globalDbg ){cerr << "Skeleton_simplex_range skeleton_simplex_range( unsigned dimension )\n";} - return Skeleton_simplex_range( this , dimension ); - } - - friend class is_before_in_filtration; - - -protected: - std::vector< size_t > key_associated_to_simplex; - std::vector< size_t > simplex_associated_to_key; -};//Bitmap_cubical_complex +class Bitmap_cubical_complex : public T { + public: + //*********************************************// + // Typedefs and typenames + //*********************************************// + typedef size_t Simplex_key; + typedef typename T::filtration_type Filtration_value; + typedef Simplex_key Simplex_handle; + + + //*********************************************// + // Constructors + //*********************************************// + // Over here we need to define various input types. I am proposing the following ones: + // Perseus style + // TODO(PD) H5 files? + // TODO(PD) binary files with little endiangs / big endians ? + // TODO(PD) constructor from a vector of elements of a type T. ? + + /** + * Constructor form a Perseus-style file. + **/ + Bitmap_cubical_complex(const char* perseus_style_file) : + T(perseus_style_file), key_associated_to_simplex(this->total_number_of_cells + 1) { + if (globalDbg) { + std::cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n"; + } + for (size_t i = 0; i != this->total_number_of_cells; ++i) { + this->key_associated_to_simplex[i] = i; + } + // we initialize this only once, in each constructor, when the bitmap is constructed. + // If the user decide to change some elements of the bitmap, then this procedure need + // to be called again. + this->initialize_simplex_associated_to_key(); + } + + /** + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells + * in the following directions and vector of element of a type T + * with filtration on top dimensional cells. + **/ + Bitmap_cubical_complex(const std::vector& dimensions, + const std::vector& top_dimensional_cells) : + T(dimensions, top_dimensional_cells), + key_associated_to_simplex(this->total_number_of_cells + 1) { + for (size_t i = 0; i != this->total_number_of_cells; ++i) { + this->key_associated_to_simplex[i] = i; + } + // we initialize this only once, in each constructor, when the bitmap is constructed. + // If the user decide to change some elements of the bitmap, then this procedure need + // to be called again. + this->initialize_simplex_associated_to_key(); + } + + /** + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells + * in the following directions and vector of element of a type T::filtration_type + * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. + * If the position i on this vector is true, then we impose periodic boundary conditions in this direction. + **/ + Bitmap_cubical_complex(const std::vector& dimensions, + const std::vector& top_dimensional_cells, + std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed) : + T(dimensions, top_dimensional_cells, directions_in_which_periodic_b_cond_are_to_be_imposed), + key_associated_to_simplex(this->total_number_of_cells + 1) { + for (size_t i = 0; i != this->total_number_of_cells; ++i) { + this->key_associated_to_simplex[i] = i; + } + // we initialize this only once, in each constructor, when the bitmap is constructed. + // If the user decide to change some elements of the bitmap, then this procedure need + // to be called again. + this->initialize_simplex_associated_to_key(); + } + + /** + * Destructor of the Bitmap_cubical_complex class. + **/ + virtual ~Bitmap_cubical_complex(){} + + //*********************************************// + // Other 'easy' functions + //*********************************************// + + /** + * Returns number of all cubes in the complex. + **/ + size_t num_simplices()const { + return this->total_number_of_cells; + } + + /** + * Returns a Simplex_handle to a cube that do not exist in this complex. + **/ + static Simplex_handle null_simplex() { + if (globalDbg) { + std::cerr << "Simplex_handle null_simplex()\n"; + } + return std::numeric_limits::max(); + } + + /** + * Returns dimension of the complex. + **/ + inline size_t dimension()const { + return this->sizes.size(); + } + + /** + * Return dimension of a cell pointed by the Simplex_handle. + **/ + inline unsigned dimension(Simplex_handle sh)const { + if (globalDbg) { + std::cerr << "unsigned dimension(const Simplex_handle& sh)\n"; + } + if (sh != std::numeric_limits::max()) return this->get_dimension_of_a_cell(sh); + return -1; + } + + /** + * Return the filtration of a cell pointed by the Simplex_handle. + **/ + typename T::filtration_type filtration(Simplex_handle sh) { + if (globalDbg) { + std::cerr << "T::filtration_type filtration(const Simplex_handle& sh)\n"; + } + // Returns the filtration value of a simplex. + if (sh != std::numeric_limits::max()) return this->data[sh]; + return std::numeric_limits::max(); + } + + /** + * Return a key which is not a key of any cube in the considered data structure. + **/ + static Simplex_key null_key() { + if (globalDbg) { + std::cerr << "Simplex_key null_key()\n"; + } + return std::numeric_limits::max(); + } + + /** + * Return the key of a cube pointed by the Simplex_handle. + **/ + Simplex_key key(Simplex_handle sh)const { + if (globalDbg) { + std::cerr << "Simplex_key key(const Simplex_handle& sh)\n"; + } + if (sh != std::numeric_limits::max()) { + return this->key_associated_to_simplex[sh]; + } + return this->null_key(); + } + + /** + * Return the Simplex_handle given the key of the cube. + **/ + Simplex_handle simplex(Simplex_key key) { + if (globalDbg) { + std::cerr << "Simplex_handle simplex(Simplex_key key)\n"; + } + if (key != std::numeric_limits::max()) { + return this->simplex_associated_to_key[ key ]; + } + return null_simplex(); + } + + /** + * Assign key to a cube pointed by the Simplex_handle + **/ + void assign_key(Simplex_handle sh, Simplex_key key) { + if (globalDbg) { + std::cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n"; + } + if (key == std::numeric_limits::max()) return; + this->key_associated_to_simplex[sh] = key; + this->simplex_associated_to_key[key] = sh; + } + + /** + * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. + **/ + void initialize_simplex_associated_to_key(); + + //*********************************************// + // Iterators + //*********************************************// + + /** + * Boundary_simplex_range class provides ranges for boundary iterators. + **/ + typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; + typedef typename std::vector< Simplex_handle > Boundary_simplex_range; + + /** + * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. + * Secondary criteria for filtration are: + * (1) Dimension of a cube (lower dimensional comes first). + * (2) Position in the data structure (the ones that are earlies in the data structure comes first). + **/ + class Filtration_simplex_range; + + class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { + // Iterator over all simplices of the complex in the order of the indexing scheme. + // 'value_type' must be 'Simplex_handle'. + public: + Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { } + + Filtration_simplex_iterator() : b(NULL) { } + + Filtration_simplex_iterator operator++() { + if (globalDbg) { + std::cerr << "Filtration_simplex_iterator operator++\n"; + } + ++this->position; + return (*this); + } -template -void Bitmap_cubical_complex::initialize_simplex_associated_to_key() -{ - if ( globalDbg ) - { - cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; - } - this->simplex_associated_to_key = std::vector( this->data.size() ); - std::iota (std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); - std::sort( simplex_associated_to_key.begin() , - simplex_associated_to_key.end() , - is_before_in_filtration(this) ); - - //we still need to deal here with a key_associated_to_simplex: - for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) - { - this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; + Filtration_simplex_iterator operator++(int) { + Filtration_simplex_iterator result = *this; + ++(*this); + return result; } -} + Filtration_simplex_iterator& operator=(const Filtration_simplex_iterator& rhs) { + if (globalDbg) { + std::cerr << "Filtration_simplex_iterator operator =\n"; + } + this->b = rhs.b; + this->position = rhs.position; + } -template -class is_before_in_filtration -{ -public: - explicit is_before_in_filtration(Bitmap_cubical_complex * CC) - : CC_(CC) { } - - bool operator()( const typename Bitmap_cubical_complex::Simplex_handle sh1, const typename Bitmap_cubical_complex::Simplex_handle sh2) const - { - // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. - typename T::filtration_type fil1 = CC_->data[sh1]; - typename T::filtration_type fil2 = CC_->data[sh2]; - if ( fil1 != fil2 ) - { - return fil1 < fil2; + bool operator==(const Filtration_simplex_iterator& rhs)const { + if (globalDbg) { + std::cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n"; + } + return ( this->position == rhs.position); + } + + bool operator!=(const Filtration_simplex_iterator& rhs)const { + if (globalDbg) { + std::cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n"; + } + return !(*this == rhs); + } + + Simplex_handle operator*() { + if (globalDbg) { + std::cerr << "Simplex_handle operator*()\n"; + } + return this->b->simplex_associated_to_key[ this->position ]; + } + + friend class Filtration_simplex_range; + + private: + Bitmap_cubical_complex* b; + size_t position; + }; + + /** + * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. + **/ + class Filtration_simplex_range { + // Range over the simplices of the complex in the order of the filtration. + // .begin() and .end() return type Filtration_simplex_iterator. + public: + typedef Filtration_simplex_iterator const_iterator; + typedef Filtration_simplex_iterator iterator; + + Filtration_simplex_range(Bitmap_cubical_complex* b) : b(b) { } + + Filtration_simplex_iterator begin() { + if (globalDbg) { + std::cerr << "Filtration_simplex_iterator begin() \n"; } - //in this case they are on the same filtration level, so the dimension decide. - size_t dim1 = CC_->get_dimension_of_a_cell(sh1); - size_t dim2 = CC_->get_dimension_of_a_cell(sh2); - if ( dim1 != dim2 ) - { - return dim1 < dim2; + return Filtration_simplex_iterator(this->b); + } + + Filtration_simplex_iterator end() { + if (globalDbg) { + std::cerr << "Filtration_simplex_iterator end()\n"; } - //in this case both filtration and dimensions of the considered cubes are the same. To have stable sort, we simply compare their positions in the bitmap: - return sh1 < sh2; - } -protected: - Bitmap_cubical_complex* CC_; + Filtration_simplex_iterator it(this->b); + it.position = this->b->simplex_associated_to_key.size(); + return it; + } + + private: + Bitmap_cubical_complex* b; }; -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// + //*********************************************// + // Methods to access iterators from the container: + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. + **/ + Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) { + return this->get_boundary_of_a_cell(sh); + } + + /** + * filtration_simplex_range creates an object of a Filtration_simplex_range class + * that provides ranges for the Filtration_simplex_iterator. + **/ + Filtration_simplex_range filtration_simplex_range() { + if (globalDbg) { + std::cerr << "Filtration_simplex_range filtration_simplex_range()\n"; + } + // Returns a range over the simplices of the complex in the order of the filtration + return Filtration_simplex_range(this); + } + //*********************************************// + + + + //*********************************************// + // Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are + // there. + // TODO(PD) the file IndexingTag.h in the Gudhi library contains an empty structure, so + // I understand that this is something that was planned (for simplicial maps?) + // but was never finished. The only idea I have here is to use the same empty structure from + // IndexingTag.h file, but only if the compiler needs it. If the compiler + // do not need it, then I would rather not add here elements which I do not understand. + // typedef Indexing_tag + + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + std::pair endpoints(Simplex_handle sh) { + std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh); + if (globalDbg) { + std::cerr << "std::pair endpoints( Simplex_handle sh )\n"; + std::cerr << "bdry.size() : " << bdry.size() << std::endl; + } + // this method returns two first elements from the boundary of sh. + if (bdry.size() < 2) + throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the boundary."); + return std::make_pair(bdry[0], bdry[1]); + } + + + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range; + + class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { + // Iterator over all simplices of the complex in the order of the indexing scheme. + // 'value_type' must be 'Simplex_handle'. + public: + Skeleton_simplex_iterator(Bitmap_cubical_complex* b, size_t d) : b(b), dimension(d) { + if (globalDbg) { + std::cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n"; + } + // find the position of the first simplex of a dimension d + this->position = 0; + while ( + (this->position != b->data.size()) && + (this->b->get_dimension_of_a_cell(this->position) != this->dimension) + ) { + ++this->position; + } + } + + Skeleton_simplex_iterator() : b(NULL), position(0), dimension(0) { } + + Skeleton_simplex_iterator operator++() { + if (globalDbg) { + std::cerr << "Skeleton_simplex_iterator operator++()\n"; + } + // increment the position as long as you did not get to the next element of the dimension dimension. + ++this->position; + while ( + (this->position != this->b->data.size()) && + (this->b->get_dimension_of_a_cell(this->position) != this->dimension) + ) { + ++this->position; + } + return (*this); + } + + Skeleton_simplex_iterator operator++(int) { + Skeleton_simplex_iterator result = *this; + ++(*this); + return result; + } + + Skeleton_simplex_iterator& operator=(const Skeleton_simplex_iterator& rhs) { + if (globalDbg) { + std::cerr << "Skeleton_simplex_iterator operator =\n"; + } + this->b = rhs.b; + this->position = rhs.position; + this->dimension = rhs.dimension; + } + + bool operator==(const Skeleton_simplex_iterator& rhs)const { + if (globalDbg) { + std::cerr << "bool operator ==\n"; + } + return ( this->position == rhs.position); + } + + bool operator!=(const Skeleton_simplex_iterator& rhs)const { + if (globalDbg) { + std::cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n"; + } + return !(*this == rhs); + } + + Simplex_handle operator*() { + if (globalDbg) { + std::cerr << "Simplex_handle operator*() \n"; + } + return this->position; + } + + friend class Skeleton_simplex_range; + private: + Bitmap_cubical_complex* b; + size_t position; + unsigned dimension; + }; + + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range { + // Range over the simplices of the complex in the order of the filtration. + // .begin() and .end() return type Filtration_simplex_iterator. + public: + typedef Skeleton_simplex_iterator const_iterator; + typedef Skeleton_simplex_iterator iterator; + + Skeleton_simplex_range(Bitmap_cubical_complex* b, unsigned dimension) : b(b), dimension(dimension) { } + + Skeleton_simplex_iterator begin() { + if (globalDbg) { + std::cerr << "Skeleton_simplex_iterator begin()\n"; + } + return Skeleton_simplex_iterator(this->b, this->dimension); + } + + Skeleton_simplex_iterator end() { + if (globalDbg) { + std::cerr << "Skeleton_simplex_iterator end()\n"; + } + Skeleton_simplex_iterator it(this->b, this->dimension); + it.position = this->b->data.size(); + return it; + } + + private: + Bitmap_cubical_complex* b; + unsigned dimension; + }; + + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + Skeleton_simplex_range skeleton_simplex_range(unsigned dimension) { + if (globalDbg) { + std::cerr << "Skeleton_simplex_range skeleton_simplex_range( unsigned dimension )\n"; + } + return Skeleton_simplex_range(this, dimension); + } + + friend class is_before_in_filtration; + + protected: + std::vector< size_t > key_associated_to_simplex; + std::vector< size_t > simplex_associated_to_key; +}; // Bitmap_cubical_complex + +template +void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { + if (globalDbg) { + std::cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; + } + this->simplex_associated_to_key = std::vector(this->data.size()); + std::iota(std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); + std::sort(simplex_associated_to_key.begin(), + simplex_associated_to_key.end(), + is_before_in_filtration(this)); + + // we still need to deal here with a key_associated_to_simplex: + for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) + { + this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; + } } -} + +template +class is_before_in_filtration { + public: + explicit is_before_in_filtration(Bitmap_cubical_complex * CC) + : CC_(CC) { } + + bool operator()(const typename Bitmap_cubical_complex::Simplex_handle& sh1, + const typename Bitmap_cubical_complex::Simplex_handle& sh2) const { + // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. + typename T::filtration_type fil1 = CC_->data[sh1]; + typename T::filtration_type fil2 = CC_->data[sh2]; + if (fil1 != fil2) { + return fil1 < fil2; + } + // in this case they are on the same filtration level, so the dimension decide. + size_t dim1 = CC_->get_dimension_of_a_cell(sh1); + size_t dim2 = CC_->get_dimension_of_a_cell(sh2); + if (dim1 != dim2) { + return dim1 < dim2; + } + // in this case both filtration and dimensions of the considered cubes are the same. To have stable sort, we simply + // compare their positions in the bitmap: + return sh1 < sh2; + } + + protected: + Bitmap_cubical_complex* CC_; +}; + +} // namespace Cubical_complex + +} // namespace Gudhi + +#endif // BITMAP_CUBICAL_COMPLEX_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index f0517a86..62776019 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -20,35 +20,30 @@ * along with this program. If not, see . */ -#pragma once +#ifndef BITMAP_CUBICAL_COMPLEX_BASE_H_ +#define BITMAP_CUBICAL_COMPLEX_BASE_H_ -#include -#include -#include +#include + +#include #include #include #include #include #include -#include -#include -#include "Bitmap_cubical_complex/counter.h" - - -using namespace std; +#include +#include // for pair<> -namespace Gudhi -{ - -namespace Cubical_complex -{ +namespace Gudhi { +namespace Cubical_complex { /** - *@class Bitmap_cubical_complex_base - *@brief Cubical complex represented as a bitmap, class with basic implementation. - *@ingroup cubical_complex + * @class Bitmap_cubical_complex_base + * @brief Cubical complex represented as a bitmap, class with basic implementation. + * @ingroup cubical_complex */ + /** * This is a class implementing a basic bitmap data structure to store cubical complexes. * It implements only the most basic subroutines. @@ -67,844 +62,750 @@ namespace Cubical_complex * The default filtration used in this implementation is the lower star filtration. */ template -class Bitmap_cubical_complex_base -{ -public: - typedef T filtration_type; - /** - *Default constructor - **/ - Bitmap_cubical_complex_base() - { - } - /** - * There are a few constructors of a Bitmap_cubical_complex_base class. - * First one, that takes vector, creates an empty bitmap of a dimension equal - * the number of elements in the - * input vector and size in the i-th dimension equal the number in the position i-of the input vector. - */ - Bitmap_cubical_complex_base( const std::vector& sizes ); - /** - * The second constructor takes as a input a Perseus style file. For more details, - * please consult the documentations of - * Perseus software as well as examples attached to this - * implementation. - **/ - Bitmap_cubical_complex_base( const char* perseus_style_file ); - /** - * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) - * together with vector of filtration values of top dimensional cells. - **/ - Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells ); - - /** - * Destructor of the Bitmap_cubical_complex_base class. - **/ - virtual ~Bitmap_cubical_complex_base(){} - - /** - * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell - * and get_cell_data are the basic - * functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a - * non-negative integer, indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to - * the positions of (co)boundary element of the input cell. - */ - virtual inline std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; - /** - * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, - * get_dimension_of_a_cell and get_cell_data are the basic - * functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. - * The input parameter of all of those function is a non-negative integer, - * indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if - * non-negative integers pointing to the - * positions of (co)boundary element of the input cell. - **/ - virtual inline std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; - /** - * In the case of get_dimension_of_a_cell function, the output is a non-negative integer - * indicating the dimension of a cell. - **/ - inline unsigned get_dimension_of_a_cell( size_t cell )const; - /** - * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. This allows reading and changing the value of filtration. - * Note that if the value of a filtration is changed, the code do not check if we have a filtration or not. i.e. it do not check if the value of a filtration of a cell is - * not smaller than the value of a filtration of its boundary and not greater than the value of its coboundary. - **/ - inline T& get_cell_data( size_t cell ); - - - /** - * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. - * Then, there are a few ways one can pick the filtration of lower dimensional - * cells. The most typical one is by so called lower star filtration. This function is always called by any - * constructor which takes the top dimensional cells. If you use such a constructor, - * then there is no need to call this function. Call it only if you are putting the filtration - * of the cells by your own (for instance by using Top_dimensional_cells_iterator). - **/ - void impose_lower_star_filtration();//assume that top dimensional cells are already set. - - /** - * Returns dimension of a complex. - **/ - inline unsigned dimension()const{ return sizes.size(); } - - /** - * Returns number of all cubes in the data structure. - **/ - inline unsigned size()const - { - return this->data.size(); - } - - /** - * Writing to stream operator. By using it we get the values T of cells in order in which they are stored in the structure. This procedure is used for debugging purposes. - **/ - template - friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); - - - /** - * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. - * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_to_bins( size_t number_of_bins ) - * ais designed for that purpose. The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. - **/ - void put_data_to_bins( size_t number_of_bins ); - - /** - * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. - * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_to_bins( T diameter_of_bin ) is - * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex - * before and after using such a function will be bounded by the parameter diameter_of_bin. - **/ - void put_data_to_bins( T diameter_of_bin ); - - /** - * Functions to find min and max values of filtration. - **/ - std::pair< T ,T > min_max_filtration(); - - //ITERATORS - /** - * Iterator through all cells in the complex (in order they appear in the structure -- i.e. - * in lexicographical order). - **/ - class All_cells_iterator : std::iterator< std::input_iterator_tag, T > - { - public: - All_cells_iterator() - { - this->counter = 0; - } - All_cells_iterator operator++() - { - //first find first element of the counter that can be increased: - ++this->counter; - return *this; - } - All_cells_iterator operator++(int) - { - All_cells_iterator result = *this; - ++(*this); - return result; - } - All_cells_iterator operator =( const All_cells_iterator& rhs ) - { - this->counter = rhs.counter; - return *this; - } - bool operator == ( const All_cells_iterator& rhs )const - { - if ( this->counter != rhs.counter )return false; - return true; - } - bool operator != ( const All_cells_iterator& rhs )const - { - return !(*this == rhs); - } - - /* - * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: - * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension - * and in function get_cell_data to get a filtration of a cell. - */ - size_t operator*() - { - return this->counter; - } - friend class Bitmap_cubical_complex_base; - protected: - size_t counter; - }; - - /** - * Function returning a All_cells_iterator to the first cell of the bitmap. - **/ - All_cells_iterator all_cells_iterator_begin() - { - All_cells_iterator a; - return a; - } - - /** - * Function returning a All_cells_iterator to the last cell of the bitmap. - **/ - All_cells_iterator all_cells_iterator_end() - { - All_cells_iterator a; - a.counter = this->data.size(); - return a; - } - - - /** - * All_cells_range class provides ranges for All_cells_iterator - **/ - class All_cells_range - { - public: - All_cells_range(Bitmap_cubical_complex_base* b):b(b){}; - All_cells_iterator begin() - { - return b->all_cells_iterator_begin(); - } - All_cells_iterator end() - { - return b->all_cells_iterator_end(); - } - private: - Bitmap_cubical_complex_base* b; - }; - - All_cells_range all_cells_range() - { - return All_cells_range(this); - } - - - /** - * Boundary_range class provides ranges for boundary iterators. - **/ - typedef typename std::vector< size_t >::const_iterator Boundary_iterator; - typedef typename std::vector< size_t > Boundary_range; - - /** - * boundary_simplex_range creates an object of a Boundary_simplex_range class - * that provides ranges for the Boundary_simplex_iterator. - **/ - Boundary_range boundary_range(size_t sh) - { - return this->get_boundary_of_a_cell(sh); - } - - /** - * Coboundary_range class provides ranges for boundary iterators. - **/ - typedef typename std::vector< size_t >::const_iterator Coboundary_iterator; - typedef typename std::vector< size_t > Coboundary_range; - - /** - * boundary_simplex_range creates an object of a Boundary_simplex_range class - * that provides ranges for the Boundary_simplex_iterator. - **/ - Coboundary_range coboundary_range(size_t sh) - { - return this->get_coboundary_of_a_cell(sh); - } - - - - - - - - - /** - * Iterator through top dimensional cells of the complex. The cells appear in order they are stored - * in the structure (i.e. in lexicographical order) - **/ - class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, T > - { - public: - Top_dimensional_cells_iterator( Bitmap_cubical_complex_base& b ):b(b) - { - this->counter = std::vector(b.dimension()); - //std::fill( this->counter.begin() , this->counter.end() , 0 ); - } - Top_dimensional_cells_iterator operator++() - { - //first find first element of the counter that can be increased: - size_t dim = 0; - while ( ( dim != this->b.dimension() ) && ( this->counter[dim] == this->b.sizes[dim]-1 ) )++dim; - - if ( dim != this->b.dimension() ) - { - ++this->counter[dim]; - for ( size_t i = 0 ; i != dim ; ++i ) - { - this->counter[i] = 0; - } - } - else - { - ++this->counter[0]; - } - return *this; - } - Top_dimensional_cells_iterator operator++(int) - { - Top_dimensional_cells_iterator result = *this; - ++(*this); - return result; - } - Top_dimensional_cells_iterator operator =( const Top_dimensional_cells_iterator& rhs ) - { - this->counter = rhs.counter; - this->b = rhs.b; - return *this; - } - bool operator == ( const Top_dimensional_cells_iterator& rhs )const - { - if ( &this->b != &rhs.b )return false; - if ( this->counter.size() != rhs.counter.size() )return false; - for ( size_t i = 0 ; i != this->counter.size() ; ++i ) - { - if ( this->counter[i] != rhs.counter[i] )return false; - } - return true; - } - bool operator != ( const Top_dimensional_cells_iterator& rhs )const - { - return !(*this == rhs); - } - - //T& operator*() - //{ - // //given the counter, compute the index in the array and return this element. - // unsigned index = 0; - // for ( size_t i = 0 ; i != this->counter.size() ; ++i ) - // { - // index += (2*this->counter[i]+1)*this->b.multipliers[i]; - // } - // return this->b.data[index]; - //} - - /* - * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: - * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension - * and in function get_cell_data to get a filtration of a cell. - */ - size_t operator*() - { - return this->compute_index_in_bitmap(); - } - - size_t compute_index_in_bitmap()const - { - size_t index = 0; - for ( size_t i = 0 ; i != this->counter.size() ; ++i ) - { - index += (2*this->counter[i]+1)*this->b.multipliers[i]; - } - return index; - } - - - void print_counter()const - { - for ( size_t i = 0 ; i != this->counter.size() ; ++i ) - { - cout << this->counter[i] << " "; - } - } - friend class Bitmap_cubical_complex_base; - protected: - std::vector< size_t > counter; - Bitmap_cubical_complex_base& b; - }; - - /** - * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell of the bitmap. - **/ - Top_dimensional_cells_iterator top_dimensional_cells_iterator_begin() - { - Top_dimensional_cells_iterator a(*this); - return a; - } - - /** - * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell of the bitmap. - **/ - Top_dimensional_cells_iterator top_dimensional_cells_iterator_end() - { - Top_dimensional_cells_iterator a(*this); - for ( size_t i = 0 ; i != this->dimension() ; ++i ) - { - a.counter[i] = this->sizes[i]-1; - } - a.counter[0]++; - return a; - } - - /** - * Top_dimensional_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range - **/ - class Top_dimensional_cells_range - { - public: - Top_dimensional_cells_range(Bitmap_cubical_complex_base* b):b(b){}; - Top_dimensional_cells_iterator begin() - { - return b->top_dimensional_cells_iterator_begin(); - } - Top_dimensional_cells_iterator end() - { - return b->top_dimensional_cells_iterator_end(); - } - private: - Bitmap_cubical_complex_base* b; - }; - - Top_dimensional_cells_range top_dimensional_cells_range() - { - return Top_dimensional_cells_range(this); - } - - -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// - - -inline size_t number_cells()const -{ - return this->total_number_of_cells; -} +class Bitmap_cubical_complex_base { + public: + typedef T filtration_type; + + /** + *Default constructor + **/ + Bitmap_cubical_complex_base() : + total_number_of_cells(0) { } + /** + * There are a few constructors of a Bitmap_cubical_complex_base class. + * First one, that takes vector, creates an empty bitmap of a dimension equal + * the number of elements in the + * input vector and size in the i-th dimension equal the number in the position i-of the input vector. + */ + Bitmap_cubical_complex_base(const std::vector& sizes); + /** + * The second constructor takes as a input a Perseus style file. For more details, + * please consult the documentations of + * Perseus software as well as examples attached to this + * implementation. + **/ + Bitmap_cubical_complex_base(const char* perseus_style_file); + /** + * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) + * together with vector of filtration values of top dimensional cells. + **/ + Bitmap_cubical_complex_base(const std::vector& dimensions, const std::vector& top_dimensional_cells); + + /** + * Destructor of the Bitmap_cubical_complex_base class. + **/ + virtual ~Bitmap_cubical_complex_base() { } + + /** + * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell + * and get_cell_data are the basic + * functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a + * non-negative integer, indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to + * the positions of (co)boundary element of the input cell. + */ + virtual inline std::vector< size_t > get_boundary_of_a_cell(size_t cell)const; + /** + * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, + * get_dimension_of_a_cell and get_cell_data are the basic + * functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. + * The input parameter of all of those function is a non-negative integer, + * indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if + * non-negative integers pointing to the + * positions of (co)boundary element of the input cell. + **/ + virtual inline std::vector< size_t > get_coboundary_of_a_cell(size_t cell)const; + /** + * In the case of get_dimension_of_a_cell function, the output is a non-negative integer + * indicating the dimension of a cell. + **/ + inline unsigned get_dimension_of_a_cell(size_t cell)const; + /** + * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. + * This allows reading and changing the value of filtration. Note that if the value of a filtration is changed, the + * code do not check if we have a filtration or not. i.e. it do not check if the value of a filtration of a cell is + * not smaller than the value of a filtration of its boundary and not greater than the value of its coboundary. + **/ + inline T& get_cell_data(size_t cell); + + + /** + * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. + * Then, there are a few ways one can pick the filtration of lower dimensional + * cells. The most typical one is by so called lower star filtration. This function is always called by any + * constructor which takes the top dimensional cells. If you use such a constructor, + * then there is no need to call this function. Call it only if you are putting the filtration + * of the cells by your own (for instance by using Top_dimensional_cells_iterator). + **/ + void impose_lower_star_filtration(); // assume that top dimensional cells are already set. + + /** + * Returns dimension of a complex. + **/ + inline unsigned dimension()const { + return sizes.size(); + } + + /** + * Returns number of all cubes in the data structure. + **/ + inline unsigned size()const { + return this->data.size(); + } + + /** + * Writing to stream operator. By using it we get the values T of cells in order in which they are stored in the + * structure. This procedure is used for debugging purposes. + **/ + template + friend std::ostream& operator<<(std::ostream & os, const Bitmap_cubical_complex_base& b); + + /** + * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values + * equally distributed in the range of data. + * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute + * persistence gets worst. When dealing with this type of data, one may want to put different values on cells to + * some number of bins. The function put_data_to_bins( size_t number_of_bins ) is designed for that purpose. + * The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. + **/ + void put_data_to_bins(size_t number_of_bins); + + /** + * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values + * equally distributed in the range of data. + * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute + * persistence gets worst. When dealing with this type of data, one may want to put different values on cells to + * some number of bins. The function put_data_to_bins( T diameter_of_bin ) is designed for that purpose. + * The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence + * diagram of the cubical complex before and after using such a function will be bounded by the parameter + * diameter_of_bin. + **/ + void put_data_to_bins(T diameter_of_bin); + + /** + * Functions to find min and max values of filtration. + **/ + std::pair< T, T > min_max_filtration(); + + // ITERATORS + + /** + * Iterator through all cells in the complex (in order they appear in the structure -- i.e. + * in lexicographical order). + **/ + class All_cells_iterator : std::iterator< std::input_iterator_tag, T > { + public: + + All_cells_iterator() { + this->counter = 0; + } -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// - -protected: - std::vector sizes; - std::vector multipliers; - std::vector data; - size_t total_number_of_cells; - void set_up_containers( const std::vector& sizes ) - { - unsigned multiplier = 1; - for ( size_t i = 0 ; i != sizes.size() ; ++i ) - { - this->sizes.push_back(sizes[i]); - this->multipliers.push_back(multiplier); - multiplier *= 2*sizes[i]+1; - } - this->data = std::vector(multiplier, std::numeric_limits::max()); - this->total_number_of_cells = multiplier; + All_cells_iterator operator++() { + //first find first element of the counter that can be increased: + ++this->counter; + return *this; } - size_t compute_position_in_bitmap( const std::vector< unsigned >& counter ) - { - size_t position = 0; - for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) - { - position += this->multipliers[i]*counter[i]; - } - return position; + All_cells_iterator operator++(int) { + All_cells_iterator result = *this; + ++(*this); + return result; + } + + All_cells_iterator operator=(const All_cells_iterator& rhs) { + this->counter = rhs.counter; + return *this; } - std::vector compute_counter_for_given_cell( size_t cell )const - { - std::vector counter; - counter.reserve( this->sizes.size() ); - for ( size_t dim = this->sizes.size() ; dim != 0 ; --dim ) - { - counter.push_back(cell/this->multipliers[dim-1]); - cell = cell%this->multipliers[dim-1]; + bool operator==(const All_cells_iterator& rhs)const { + if (this->counter != rhs.counter)return false; + return true; + } + + bool operator!=(const All_cells_iterator& rhs)const { + return !(*this == rhs); + } + + /* + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * and in function get_cell_data to get a filtration of a cell. + */ + size_t operator*() { + return this->counter; + } + friend class Bitmap_cubical_complex_base; + protected: + size_t counter; + }; + + /** + * Function returning a All_cells_iterator to the first cell of the bitmap. + **/ + All_cells_iterator all_cells_iterator_begin() { + All_cells_iterator a; + return a; + } + + /** + * Function returning a All_cells_iterator to the last cell of the bitmap. + **/ + All_cells_iterator all_cells_iterator_end() { + All_cells_iterator a; + a.counter = this->data.size(); + return a; + } + + /** + * All_cells_range class provides ranges for All_cells_iterator + **/ + class All_cells_range { + public: + + All_cells_range(Bitmap_cubical_complex_base* b) : b(b) { }; + + All_cells_iterator begin() { + return b->all_cells_iterator_begin(); + } + + All_cells_iterator end() { + return b->all_cells_iterator_end(); + } + private: + Bitmap_cubical_complex_base* b; + }; + + All_cells_range all_cells_range() { + return All_cells_range(this); + } + + + /** + * Boundary_range class provides ranges for boundary iterators. + **/ + typedef typename std::vector< size_t >::const_iterator Boundary_iterator; + typedef typename std::vector< size_t > Boundary_range; + + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. + **/ + Boundary_range boundary_range(size_t sh) { + return this->get_boundary_of_a_cell(sh); + } + + /** + * Coboundary_range class provides ranges for boundary iterators. + **/ + typedef typename std::vector< size_t >::const_iterator Coboundary_iterator; + typedef typename std::vector< size_t > Coboundary_range; + + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. + **/ + Coboundary_range coboundary_range(size_t sh) { + return this->get_coboundary_of_a_cell(sh); + } + + /** + * Iterator through top dimensional cells of the complex. The cells appear in order they are stored + * in the structure (i.e. in lexicographical order) + **/ + class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, T > { + public: + + Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b) : b(b) { + this->counter = std::vector(b.dimension()); + //std::fill( this->counter.begin() , this->counter.end() , 0 ); + } + + Top_dimensional_cells_iterator operator++() { + //first find first element of the counter that can be increased: + size_t dim = 0; + while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1))++dim; + + if (dim != this->b.dimension()) { + ++this->counter[dim]; + for (size_t i = 0; i != dim; ++i) { + this->counter[i] = 0; } - std::reverse( counter.begin() , counter.end() ); - return counter; - } - void read_perseus_style_file( const char* perseus_style_file ); - void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); - Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); - Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); - Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ); + } else { + ++this->counter[0]; + } + return *this; + } + + Top_dimensional_cells_iterator operator++(int) { + Top_dimensional_cells_iterator result = *this; + ++(*this); + return result; + } + + Top_dimensional_cells_iterator operator=(const Top_dimensional_cells_iterator& rhs) { + this->counter = rhs.counter; + this->b = rhs.b; + return *this; + } + + bool operator==(const Top_dimensional_cells_iterator& rhs)const { + if (&this->b != &rhs.b)return false; + if (this->counter.size() != rhs.counter.size())return false; + for (size_t i = 0; i != this->counter.size(); ++i) { + if (this->counter[i] != rhs.counter[i])return false; + } + return true; + } + + bool operator!=(const Top_dimensional_cells_iterator& rhs)const { + return !(*this == rhs); + } + + /* + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * and in function get_cell_data to get a filtration of a cell. + */ + size_t operator*() { + return this->compute_index_in_bitmap(); + } + + size_t compute_index_in_bitmap()const { + size_t index = 0; + for (size_t i = 0; i != this->counter.size(); ++i) { + index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; + } + return index; + } + + void print_counter()const { + for (size_t i = 0; i != this->counter.size(); ++i) { + std::cout << this->counter[i] << " "; + } + } + friend class Bitmap_cubical_complex_base; + protected: + std::vector< size_t > counter; + Bitmap_cubical_complex_base& b; + }; + + /** + * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell of the bitmap. + **/ + Top_dimensional_cells_iterator top_dimensional_cells_iterator_begin() { + Top_dimensional_cells_iterator a(*this); + return a; + } + + /** + * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell of the bitmap. + **/ + Top_dimensional_cells_iterator top_dimensional_cells_iterator_end() { + Top_dimensional_cells_iterator a(*this); + for (size_t i = 0; i != this->dimension(); ++i) { + a.counter[i] = this->sizes[i] - 1; + } + a.counter[0]++; + return a; + } + + /** + * Top_dimensional_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range + **/ + class Top_dimensional_cells_range { + public: + + Top_dimensional_cells_range(Bitmap_cubical_complex_base* b) : b(b) { }; + + Top_dimensional_cells_iterator begin() { + return b->top_dimensional_cells_iterator_begin(); + } + + Top_dimensional_cells_iterator end() { + return b->top_dimensional_cells_iterator_end(); + } + private: + Bitmap_cubical_complex_base* b; + }; + + Top_dimensional_cells_range top_dimensional_cells_range() { + return Top_dimensional_cells_range(this); + } + + + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + + inline size_t number_cells()const { + return this->total_number_of_cells; + } + + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + + protected: + std::vector sizes; + std::vector multipliers; + std::vector data; + size_t total_number_of_cells; + + void set_up_containers(const std::vector& sizes) { + unsigned multiplier = 1; + for (size_t i = 0; i != sizes.size(); ++i) { + this->sizes.push_back(sizes[i]); + this->multipliers.push_back(multiplier); + multiplier *= 2 * sizes[i] + 1; + } + this->data = std::vector(multiplier, std::numeric_limits::max()); + this->total_number_of_cells = multiplier; + } + + size_t compute_position_in_bitmap(const std::vector< unsigned >& counter) { + size_t position = 0; + for (size_t i = 0; i != this->multipliers.size(); ++i) { + position += this->multipliers[i] * counter[i]; + } + return position; + } + + std::vector compute_counter_for_given_cell(size_t cell)const { + std::vector counter; + counter.reserve(this->sizes.size()); + for (size_t dim = this->sizes.size(); dim != 0; --dim) { + counter.push_back(cell / this->multipliers[dim - 1]); + cell = cell % this->multipliers[dim - 1]; + } + std::reverse(counter.begin(), counter.end()); + return counter; + } + void read_perseus_style_file(const char* perseus_style_file); + void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, const std::vector& top_dimensional_cells); + Bitmap_cubical_complex_base(const char* perseus_style_file, std::vector directions); + Bitmap_cubical_complex_base(const std::vector& sizes, std::vector directions); + Bitmap_cubical_complex_base(const std::vector& dimensions, const std::vector& top_dimensional_cells, std::vector directions); }; +template +void Bitmap_cubical_complex_base::put_data_to_bins(size_t number_of_bins) { + bool bdg = false; + + std::pair< T, T > min_max = this->min_max_filtration(); + T dx = (min_max.second - min_max.first) / (T) number_of_bins; + + //now put the data into the appropriate bins: + for (size_t i = 0; i != this->data.size(); ++i) { + if (bdg) { + std::cerr << "Before binning : " << this->data[i] << std::endl; + } + this->data[i] = min_max.first + dx * (this->data[i] - min_max.first) / number_of_bins; + if (bdg) { + std::cerr << "After binning : " << this->data[i] << std::endl; + getchar(); + } + } +} -template -void Bitmap_cubical_complex_base::put_data_to_bins( size_t number_of_bins ) -{ - bool bdg = false; - - std::pair< T ,T > min_max = this->min_max_filtration(); - T dx = (min_max.second-min_max.first)/(T)number_of_bins; - - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - template -void Bitmap_cubical_complex_base::put_data_to_bins( T diameter_of_bin ) -{ - bool bdg = false; - std::pair< T ,T > min_max = this->min_max_filtration(); - - size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - -template -std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() -{ - std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( this->data[i] < min_max.first )min_max.first = this->data[i]; - if ( this->data[i] > min_max.second )min_max.second = this->data[i]; - } - return min_max; -} +void Bitmap_cubical_complex_base::put_data_to_bins(T diameter_of_bin) { + bool bdg = false; + std::pair< T, T > min_max = this->min_max_filtration(); + + size_t number_of_bins = (min_max.second - min_max.first) / diameter_of_bin; + //now put the data into the appropriate bins: + for (size_t i = 0; i != this->data.size(); ++i) { + if (bdg) { + std::cerr << "Before binning : " << this->data[i] << std::endl; + } + this->data[i] = min_max.first + diameter_of_bin * (this->data[i] - min_max.first) / number_of_bins; + if (bdg) { + std::cerr << "After binning : " << this->data[i] << std::endl; + getchar(); + } + } +} +template +std::pair< T, T > Bitmap_cubical_complex_base::min_max_filtration() { + std::pair< T, T > min_max(std::numeric_limits::max(), std::numeric_limits::min()); + for (size_t i = 0; i != this->data.size(); ++i) { + if (this->data[i] < min_max.first)min_max.first = this->data[i]; + if (this->data[i] > min_max.second)min_max.second = this->data[i]; + } + return min_max; +} template -ostream& operator << ( ostream & out , const Bitmap_cubical_complex_base& b ) -{ - for ( typename Bitmap_cubical_complex_base::all_cells_const_iterator - it = b.all_cells_const_begin() ; it != b.all_cells_const_end() ; ++it ) - { - out << *it << " "; - } - return out; +ostream& operator<<(ostream & out, const Bitmap_cubical_complex_base& b) { + for (typename Bitmap_cubical_complex_base::all_cells_const_iterator + it = b.all_cells_const_begin(); it != b.all_cells_const_end(); ++it) { + out << *it << " "; + } + return out; } - template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base -( const std::vector& sizes ) -{ - this->set_up_containers( sizes ); +(const std::vector& sizes) { + this->set_up_containers(sizes); } - -template -void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) -{ - this->set_up_containers( sizes_in_following_directions ); - - size_t number_of_top_dimensional_elements = 1; - for ( size_t i = 0 ; i != sizes_in_following_directions.size() ; ++i ) - { - number_of_top_dimensional_elements *= sizes_in_following_directions[i]; - } - if ( number_of_top_dimensional_elements != top_dimensional_cells.size() ) - { - cerr << - "Error in constructor\ + +template +void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, const std::vector& top_dimensional_cells) { + this->set_up_containers(sizes_in_following_directions); + + size_t number_of_top_dimensional_elements = 1; + for (size_t i = 0; i != sizes_in_following_directions.size(); ++i) { + number_of_top_dimensional_elements *= sizes_in_following_directions[i]; + } + if (number_of_top_dimensional_elements != top_dimensional_cells.size()) { + std::cerr << + "Error in constructor\ Bitmap_cubical_complex_base\ ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ Number of top dimensional elements that follow from sizes_in_following_directions vector is different\ - than the size of top_dimensional_cells vector." << endl; - throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions,\ + than the size of top_dimensional_cells vector." << std::endl; + throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions,\ std::vector top_dimensional_cells )\ . Number of top dimensional elements that follow from sizes_in_following_directions vector is different than the\ size of top_dimensional_cells vector."); - } - - Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - size_t index = 0; - for ( it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) - { - this->get_cell_data(*it) = top_dimensional_cells[index]; - ++index; - } - this->impose_lower_star_filtration(); -} + } + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + size_t index = 0; + for (it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { + this->get_cell_data(*it) = top_dimensional_cells[index]; + ++index; + } + this->impose_lower_star_filtration(); +} template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base -( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) -{ - this->setup_bitmap_based_on_top_dimensional_cells_list( sizes_in_following_directions , top_dimensional_cells ); -} - -template -void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) -{ - bool dbg = false; - ifstream inFiltration, inIds; - inFiltration.open( perseus_style_file ); - unsigned dimensionOfData; - inFiltration >> dimensionOfData; - - if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;getchar();} - - std::vector sizes; - sizes.reserve( dimensionOfData ); - for ( size_t i = 0 ; i != dimensionOfData ; ++i ) - { - unsigned size_in_this_dimension; - inFiltration >> size_in_this_dimension; - size_in_this_dimension = size_in_this_dimension; - sizes.push_back( size_in_this_dimension ); - if (dbg){cerr << "size_in_this_dimension : " << size_in_this_dimension << endl;} - } - this->set_up_containers( sizes ); - - Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_iterator_begin(); - - while ( !inFiltration.eof() ) - { - T filtrationLevel; - inFiltration >> filtrationLevel; - if ( dbg ) - { - cerr << "Cell of an index : " - << it.compute_index_in_bitmap() - << " and dimension: " - << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) - << " get the value : " << filtrationLevel << endl; - } - this->get_cell_data(*it) = filtrationLevel; - ++it; - } - inFiltration.close(); - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->read_perseus_style_file( perseus_style_file ); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); +(const std::vector& sizes_in_following_directions, const std::vector& top_dimensional_cells) { + this->setup_bitmap_based_on_top_dimensional_cells_list(sizes_in_following_directions, top_dimensional_cells); } template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file ) -{ - this->read_perseus_style_file( perseus_style_file ); +void Bitmap_cubical_complex_base::read_perseus_style_file(const char* perseus_style_file) { + bool dbg = false; + std::ifstream inFiltration, inIds; + inFiltration.open(perseus_style_file); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + if (dbg) { + std::cerr << "dimensionOfData : " << dimensionOfData << std::endl; + getchar(); + } + + std::vector sizes; + sizes.reserve(dimensionOfData); + for (size_t i = 0; i != dimensionOfData; ++i) { + unsigned size_in_this_dimension; + inFiltration >> size_in_this_dimension; + size_in_this_dimension = size_in_this_dimension; + sizes.push_back(size_in_this_dimension); + if (dbg) { + std::cerr << "size_in_this_dimension : " << size_in_this_dimension << std::endl; + } + } + this->set_up_containers(sizes); + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_iterator_begin(); + + while (!inFiltration.eof()) { + T filtrationLevel; + inFiltration >> filtrationLevel; + if (dbg) { + std::cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + << " get the value : " << filtrationLevel << std::endl; + } + this->get_cell_data(*it) = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); } - template -std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const -{ - std::vector< size_t > boundary_elements; - - //Speed traded of for memory. Check if it is better in practice. - boundary_elements.reserve( this->dimension()*2 ); - - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - if ( position%2 == 1 ) - { - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - } - cell1 = cell1%this->multipliers[i-1]; - } - return boundary_elements; -} - +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const char* perseus_style_file, std::vector directions) { + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->read_perseus_style_file(perseus_style_file); +} - - - template -std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const -{ - std::vector counter = this->compute_counter_for_given_cell( cell ); - std::vector< size_t > coboundary_elements; - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - if ( position%2 == 0 ) - { - if ( (cell > this->multipliers[i-1]) && (counter[i-1] != 0) ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - } - if ( - (cell + this->multipliers[i-1] < this->data.size()) && (counter[i-1] != 2*this->sizes[i-1]) ) - { - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - } - cell1 = cell1%this->multipliers[i-1]; - } - return coboundary_elements; -} - - - - +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& sizes, std::vector directions) { + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->set_up_containers(sizes); +} +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& dimensions, const std::vector& top_dimensional_cells, std::vector directions) { + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->setup_bitmap_based_on_top_dimensional_cells_list(dimensions, top_dimensional_cells); +} +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const char* perseus_style_file) { + this->read_perseus_style_file(perseus_style_file); +} +template +std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(size_t cell)const { + std::vector< size_t > boundary_elements; + + //Speed traded of for memory. Check if it is better in practice. + boundary_elements.reserve(this->dimension()*2); + + size_t cell1 = cell; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / this->multipliers[i - 1]; + if (position % 2 == 1) { + boundary_elements.push_back(cell - this->multipliers[ i - 1 ]); + boundary_elements.push_back(cell + this->multipliers[ i - 1 ]); + } + cell1 = cell1 % this->multipliers[i - 1]; + } + return boundary_elements; +} template -unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell( size_t cell )const -{ - bool dbg = false; - if (dbg)cerr << "\n\n\n Computing position o a cell of an index : " << cell << endl; - unsigned dimension = 0; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell/this->multipliers[i-1]; - - if (dbg)cerr << "i-1 :" << i-1 << endl; - if (dbg)cerr << "cell : " << cell << endl; - if (dbg)cerr << "position : " << position << endl; - if (dbg)cerr << "multipliers["<multipliers[i-1] << endl; - if (dbg)getchar(); - - if ( position%2 == 1 ) - { - if (dbg)cerr << "Nonzero length in this direction \n"; - dimension++; - } - cell = cell%this->multipliers[i-1]; +std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(size_t cell)const { + std::vector counter = this->compute_counter_for_given_cell(cell); + std::vector< size_t > coboundary_elements; + size_t cell1 = cell; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / this->multipliers[i - 1]; + if (position % 2 == 0) { + if ((cell > this->multipliers[i - 1]) && (counter[i - 1] != 0)) { + coboundary_elements.push_back(cell - this->multipliers[i - 1]); + } + if ( + (cell + this->multipliers[i - 1] < this->data.size()) && (counter[i - 1] != 2 * this->sizes[i - 1])) { + coboundary_elements.push_back(cell + this->multipliers[i - 1]); + } } - return dimension; + cell1 = cell1 % this->multipliers[i - 1]; + } + return coboundary_elements; } template -inline T& Bitmap_cubical_complex_base::get_cell_data( size_t cell ) -{ - return this->data[cell]; +unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell(size_t cell)const { + bool dbg = false; + if (dbg) std::cerr << "\n\n\n Computing position o a cell of an index : " << cell << std::endl; + unsigned dimension = 0; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell / this->multipliers[i - 1]; + + if (dbg) { + std::cerr << "i-1 :" << i - 1 << std::endl; + std::cerr << "cell : " << cell << std::endl; + std::cerr << "position : " << position << std::endl; + std::cerr << "multipliers[" << i - 1 << "] = " << this->multipliers[i - 1] << std::endl; + getchar(); + } + + if (position % 2 == 1) { + if (dbg) std::cerr << "Nonzero length in this direction \n"; + dimension++; + } + cell = cell % this->multipliers[i - 1]; + } + return dimension; } +template +inline T& Bitmap_cubical_complex_base::get_cell_data(size_t cell) { + return this->data[cell]; +} template -void Bitmap_cubical_complex_base::impose_lower_star_filtration() -{ - bool dbg = false; - - //this vector will be used to check which elements have already been taken care of - //in imposing lower star filtration: - std::vector is_this_cell_considered( this->data.size() , false ); - - size_t size_to_reserve = 1; - for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) - { - size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); - } - - std::vector indices_to_consider; - indices_to_consider.reserve( size_to_reserve ); - //we assume here that we already have a filtration on the top dimensional cells and - //we have to extend it to lower ones. - typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - for ( it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) - { - indices_to_consider.push_back( it.compute_index_in_bitmap() ); - } - - while ( indices_to_consider.size() ) - { - if ( dbg ) - { - cerr << "indices_to_consider in this iteration \n"; - for ( size_t i = 0 ; i != indices_to_consider.size() ; ++i ) - { - cout << indices_to_consider[i] << " "; - } +void Bitmap_cubical_complex_base::impose_lower_star_filtration() { + bool dbg = false; + + //this vector will be used to check which elements have already been taken care of + //in imposing lower star filtration: + std::vector is_this_cell_considered(this->data.size(), false); + + size_t size_to_reserve = 1; + for (size_t i = 0; i != this->multipliers.size(); ++i) { + size_to_reserve *= (size_t) ((this->multipliers[i] - 1) / 2); + } + + std::vector indices_to_consider; + indices_to_consider.reserve(size_to_reserve); + //we assume here that we already have a filtration on the top dimensional cells and + //we have to extend it to lower ones. + typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + for (it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { + indices_to_consider.push_back(it.compute_index_in_bitmap()); + } + + while (indices_to_consider.size()) { + if (dbg) { + std::cerr << "indices_to_consider in this iteration \n"; + for (size_t i = 0; i != indices_to_consider.size(); ++i) { + std::cout << indices_to_consider[i] << " "; + } + getchar(); + } + std::vector new_indices_to_consider; + for (size_t i = 0; i != indices_to_consider.size(); ++i) { + std::vector bd = this->get_boundary_of_a_cell(indices_to_consider[i]); + for (size_t boundaryIt = 0; boundaryIt != bd.size(); ++boundaryIt) { + if (dbg) { + std::cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << std::endl; + getchar(); + + } + if (this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ]) { + this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + if (dbg) { + std::cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << std::endl; getchar(); + } } - std::vector new_indices_to_consider; - for ( size_t i = 0 ; i != indices_to_consider.size() ; ++i ) - { - std::vector bd = this->get_boundary_of_a_cell( indices_to_consider[i] ); - for ( size_t boundaryIt = 0 ; boundaryIt != bd.size() ; ++boundaryIt ) - { - if ( dbg ) - { - cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; - getchar(); - - } - if ( this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ] ) - { - this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; - if ( dbg ) - { - cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; - getchar(); - } - } - if ( is_this_cell_considered[ bd[boundaryIt] ] == false ) - { - new_indices_to_consider.push_back( bd[boundaryIt] ); - is_this_cell_considered[ bd[boundaryIt] ] = true; - } - } + if (is_this_cell_considered[ bd[boundaryIt] ] == false) { + new_indices_to_consider.push_back(bd[boundaryIt]); + is_this_cell_considered[ bd[boundaryIt] ] = true; } - indices_to_consider.swap(new_indices_to_consider); + } } + indices_to_consider.swap(new_indices_to_consider); + } } - template -bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , char >& first , - const std::pair< std::pair< T , size_t > , char >& second ) -{ - if ( first.first.first < second.first.first ) - { - return true; - } - else - { - if ( first.first.first > second.first.first ) - { - return false; - } - //in this case first.first.first == second.first.first, so we need to compare dimensions - return first.second < second.second; +bool compareFirstElementsOfTuples(const std::pair< std::pair< T, size_t >, char >& first, + const std::pair< std::pair< T, size_t >, char >& second) { + if (first.first.first < second.first.first) { + return true; + } else { + if (first.first.first > second.first.first) { + return false; } + //in this case first.first.first == second.first.first, so we need to compare dimensions + return first.second < second.second; + } } +} // namespace Cubical_complex +} // namespace Gudhi - -} - -} +#endif // BITMAP_CUBICAL_COMPLEX_BASE_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 956e74a7..2c0d77fe 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -18,348 +18,289 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - */ - -#pragma once -#include -#include "Bitmap_cubical_complex_base.h" - -using namespace std; - -namespace Gudhi -{ - -namespace Cubical_complex -{ - -//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures -//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the -//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base - - + */ + +#ifndef BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_ +#define BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_ + +#include + +#include +#include // for numeric_limits<> +#include + +namespace Gudhi { + +namespace Cubical_complex { + +// in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic +// boundary conditions). But, we set up the iterators and the procedures to compute boundary and coboundary in the way +// that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all +// the cells on the right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base + /** - *@class Bitmap_cubical_complex_periodic_boundary_conditions_base - *@brief Cubical complex with periodic boundary conditions represented as a bitmap. - *@ingroup cubical_complex - */ + * @class Bitmap_cubical_complex_periodic_boundary_conditions_base + * @brief Cubical complex with periodic boundary conditions represented as a bitmap. + * @ingroup cubical_complex + */ /** -* This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are identical to the functions from Bitmap_cubical_complex_base. +* This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are identical to the functions from Bitmap_cubical_complex_base. * The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell. -*/ -template -class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base -{ -public: - //constructors that take an extra parameter: - /** - * Default constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class. - */ - Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; - - /** - * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of booleans. If at i-th position of this vector there is true value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction i. - */ - Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); - /** - * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the name of Perseus style file as an input. Please consult the documentation about the specification of the file. - */ - Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); - /** - * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of top dimensional cells (ordered lexicographically) and (3) vector of booleans. If at i-th position of this vector there is true value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction i. - */ - Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); - - /** - * Destructor of the Bitmap_cubical_complex_periodic_boundary_conditions_base class. - **/ - virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base(){} - - //overwritten methods co compute boundary and coboundary - /** - * A version of a function that return boundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. - */ - virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; - /** - * A version of a function that return coboundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. - */ - virtual std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; -protected: - std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; - void set_up_containers( const std::vector& sizes ) - { - - unsigned multiplier = 1; - for ( size_t i = 0 ; i != sizes.size() ; ++i ) - { - this->sizes.push_back(sizes[i]); - this->multipliers.push_back(multiplier); - - if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) - { - multiplier *= 2*sizes[i]; - } - else - { - multiplier *= 2*sizes[i]+1; - } - } - //std::reverse( this->sizes.begin() , this->sizes.end() ); - this->data = std::vector(multiplier,std::numeric_limits::max()); - this->total_number_of_cells = multiplier; - } - Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells ); - void construct_complex_based_on_top_dimensional_cells( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); -}; - -template -void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; - this->set_up_containers( dimensions ); - - size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) - { - this->get_cell_data(*it) = topDimensionalCells[i]; - ++i; - } - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed(directions_in_which_periodic_b_cond_are_to_be_imposed); - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) -{ - - //for Perseus style files: - bool dbg = false; - ifstream inFiltration; - inFiltration.open( perseus_style_file ); - unsigned dimensionOfData; - inFiltration >> dimensionOfData; - - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); - - std::vector sizes; - sizes.reserve( dimensionOfData ); - for ( size_t i = 0 ; i != dimensionOfData ; ++i ) - { - int size_in_this_dimension; - inFiltration >> size_in_this_dimension; - if ( size_in_this_dimension < 0 ) - { - this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; - } - sizes.push_back( abs(size_in_this_dimension) ); - } - this->set_up_containers( sizes ); - - typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_iterator_begin(); - - while ( !inFiltration.eof() ) - { - double filtrationLevel; - inFiltration >> filtrationLevel; - if ( inFiltration.eof() )break; - - if ( dbg ) - { - cerr << "Cell of an index : " - << it.compute_index_in_bitmap() - << " and dimension: " - << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) - << " get the value : " << filtrationLevel << endl; - } - this->get_cell_data(*it) = filtrationLevel; - ++it; - } - inFiltration.close(); - this->impose_lower_star_filtration(); - -/* - char* filename = (char*)perseus_style_file; - //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; - ifstream file( filename , ios::binary | ios::ate ); - unsigned realSizeOfFile = file.tellg(); - file.close(); - realSizeOfFile = realSizeOfFile/sizeof(T); - - unsigned w, h, d; - - w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); - - T* slice = new T[w*h*d]; - if (slice == NULL) - { - cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; - exit(EXIT_FAILURE); - } - - FILE* fp; - if ((fp=fopen( filename, "rb" )) == NULL ) - { - cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; - exit(1); - } - - clock_t read_begin = clock(); - fread( slice,4,w*h*d,fp ); - fclose(fp); - cerr << "Time of reading the file : " << double(clock() - read_begin) / CLOCKS_PER_SEC << endl; - - - clock_t begin_creation_bitap = clock(); - std::vector data(slice,slice+w*h*d); - delete[] slice; - std::vector< unsigned > sizes; - sizes.push_back(w); - sizes.push_back(w); - sizes.push_back(w); - - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->set_up_containers( sizes ); - - size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) - { - *it = data[i]; - ++i; - } - this->impose_lower_star_filtration(); - cerr << "Time of creation of a bitmap : " << double(clock() - begin_creation_bitap ) / CLOCKS_PER_SEC << endl; - */ -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells ) -{ - std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - - - - - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - -//***********************Methods************************// - -template -std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const -{ - bool dbg = false; - if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} - - std::vector< size_t > boundary_elements; - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. - - if ( position%2 == 1 ) - { - //if there are no periodic boundary conditions in this direction, we do not have to do anything. - if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { - //cerr << "A\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. - if ( position != 2*this->sizes[ i-1 ]-1 ) - { - //cerr << "B\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //cerr << "C\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} - } - } - } - cell1 = cell1%this->multipliers[i-1]; - } - return boundary_elements; -} - -template -std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell( size_t cell )const -{ - std::vector counter = this->compute_counter_for_given_cell( cell ); - std::vector< size_t > coboundary_elements; - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - //if the cell has zero length in this direction, then it will have cbd in this direction. - if ( position%2 == 0 ) - { - if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { - //no periodic boundary conditions in this direction - if ( (counter[i-1] != 0) && (cell > this->multipliers[i-1]) ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - } - if ( (counter[i-1] != 2*this->sizes[i-1]) && (cell + this->multipliers[i-1] < this->data.size()) ) - { - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - } - else - { - //we want to have periodic boundary conditions in this direction - if ( counter[i-1] != 0 ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - else - { - //in this case counter[i-1] == 0. - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); - } - } - } - - cell1 = cell1%this->multipliers[i-1]; - } - return coboundary_elements; -} - - - -}//Cubical_complex -}//namespace Gudhi +*/ +template +class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base { + public: + // constructors that take an extra parameter: + + /** + * Default constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base() { } + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following + * parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of booleans. If + * at i-th position of this vector there is true value, that means that periodic boundary conditions are to be + * imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction + * i. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& sizes, + const std::vector& directions_in_which_periodic_b_cond_are_to_be_imposed); + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the name of Perseus + * style file as an input. Please consult the documentation about the specification of the file. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base(const char* perseusStyleFile); + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following + * parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of top dimensional + * cells (ordered lexicographically) and (3) vector of booleans. If at i-th position of this vector there is true + * value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the + * periodic boundary conditions will not be imposed in the direction i. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& dimensions, + const std::vector& topDimensionalCells, + const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed); + + /** + * Destructor of the Bitmap_cubical_complex_periodic_boundary_conditions_base class. + **/ + virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base(){} + + // overwritten methods co compute boundary and coboundary + /** + * A version of a function that return boundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + virtual std::vector< size_t > get_boundary_of_a_cell(size_t cell)const; + + /** + * A version of a function that return coboundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + virtual std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + + protected: + std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; + + void set_up_containers(const std::vector& sizes) { + unsigned multiplier = 1; + for (size_t i = 0; i != sizes.size(); ++i) { + this->sizes.push_back(sizes[i]); + this->multipliers.push_back(multiplier); + + if (directions_in_which_periodic_b_cond_are_to_be_imposed[i]) { + multiplier *= 2 * sizes[i]; + } else { + multiplier *= 2 * sizes[i] + 1; + } + } + // std::reverse( this->sizes.begin() , this->sizes.end() ); + this->data = std::vector(multiplier, std::numeric_limits::max()); + this->total_number_of_cells = multiplier; + } + Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& sizes); + Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& dimensions, + const std::vector& topDimensionalCells); + void construct_complex_based_on_top_dimensional_cells(const std::vector& dimensions, + const std::vector& topDimensionalCells, + const std::vector& directions_in_which_periodic_b_cond_are_to_be_imposed); +}; + +template +void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells(const std::vector& dimensions, + const std::vector& topDimensionalCells, + const std::vector& directions_in_which_periodic_b_cond_are_to_be_imposed) { + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers(dimensions); + + size_t i = 0; + for (typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { + this->get_cell_data(*it) = topDimensionalCells[i]; + ++i; + } + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& sizes, + const std::vector& directions_in_which_periodic_b_cond_are_to_be_imposed) { + this->directions_in_which_periodic_b_cond_are_to_be_imposed(directions_in_which_periodic_b_cond_are_to_be_imposed); + this->set_up_containers(sizes); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base(const char* perseus_style_file) { + // for Perseus style files: + bool dbg = false; + + std::ifstream inFiltration; + inFiltration.open(perseus_style_file); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector(dimensionOfData, false); + + std::vector sizes; + sizes.reserve(dimensionOfData); + for (size_t i = 0; i != dimensionOfData; ++i) { + int size_in_this_dimension; + inFiltration >> size_in_this_dimension; + if (size_in_this_dimension < 0) { + this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; + } + sizes.push_back(abs(size_in_this_dimension)); + } + this->set_up_containers(sizes); + + typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_iterator_begin(); + + while (!inFiltration.eof()) { + double filtrationLevel; + inFiltration >> filtrationLevel; + if (inFiltration.eof())break; + + if (dbg) { + std::cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + << " get the value : " << filtrationLevel << std::endl; + } + this->get_cell_data(*it) = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& sizes) { + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector(sizes.size(), false); + this->set_up_containers(sizes); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& dimensions, + const std::vector& topDimensionalCells) { + std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector(dimensions.size(), false); + this->construct_complex_based_on_top_dimensional_cells(dimensions, topDimensionalCells, + directions_in_which_periodic_b_cond_are_to_be_imposed); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base:: +Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& dimensions, + const std::vector& topDimensionalCells, + const std::vector& directions_in_which_periodic_b_cond_are_to_be_imposed) { + this->construct_complex_based_on_top_dimensional_cells(dimensions, topDimensionalCells, + directions_in_which_periodic_b_cond_are_to_be_imposed); +} + +// ***********************Methods************************ // + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell(size_t cell) const { + bool dbg = false; + if (dbg) { + std::cerr << "Computations of boundary of a cell : " << cell << std::endl; + } + + std::vector< size_t > boundary_elements; + size_t cell1 = cell; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / this->multipliers[i - 1]; + // this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. + + if (position % 2 == 1) { + // if there are no periodic boundary conditions in this direction, we do not have to do anything. + if (!directions_in_which_periodic_b_cond_are_to_be_imposed[i - 1]) { + // std::cerr << "A\n"; + boundary_elements.push_back(cell - this->multipliers[ i - 1 ]); + boundary_elements.push_back(cell + this->multipliers[ i - 1 ]); + if (dbg) { + std::cerr << cell - this->multipliers[ i - 1 ] << " " << cell + this->multipliers[ i - 1 ] << " "; + } + } else { + // in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. + if (position != 2 * this->sizes[ i - 1 ] - 1) { + // std::cerr << "B\n"; + boundary_elements.push_back(cell - this->multipliers[ i - 1 ]); + boundary_elements.push_back(cell + this->multipliers[ i - 1 ]); + if (dbg) { + std::cerr << cell - this->multipliers[ i - 1 ] << " " << cell + this->multipliers[ i - 1 ] << " "; + } + } else { + // std::cerr << "C\n"; + boundary_elements.push_back(cell - this->multipliers[ i - 1 ]); + boundary_elements.push_back(cell - (2 * this->sizes[ i - 1 ] - 1) * this->multipliers[ i - 1 ]); + if (dbg) { + std::cerr << cell - this->multipliers[ i - 1 ] << " " << + cell - (2 * this->sizes[ i - 1 ] - 1) * this->multipliers[ i - 1 ] << " "; + } + } + } + } + cell1 = cell1 % this->multipliers[i - 1]; + } + return boundary_elements; +} + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell(size_t cell) const { + std::vector counter = this->compute_counter_for_given_cell(cell); + std::vector< size_t > coboundary_elements; + size_t cell1 = cell; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / this->multipliers[i - 1]; + // if the cell has zero length in this direction, then it will have cbd in this direction. + if (position % 2 == 0) { + if (!this->directions_in_which_periodic_b_cond_are_to_be_imposed[i - 1]) { + // no periodic boundary conditions in this direction + if ((counter[i - 1] != 0) && (cell > this->multipliers[i - 1])) { + coboundary_elements.push_back(cell - this->multipliers[i - 1]); + } + if ((counter[i - 1] != 2 * this->sizes[i - 1]) && (cell + this->multipliers[i - 1] < this->data.size())) { + coboundary_elements.push_back(cell + this->multipliers[i - 1]); + } + } else { + // we want to have periodic boundary conditions in this direction + if (counter[i - 1] != 0) { + coboundary_elements.push_back(cell - this->multipliers[i - 1]); + coboundary_elements.push_back(cell + this->multipliers[i - 1]); + } else { + // in this case counter[i-1] == 0. + coboundary_elements.push_back(cell + this->multipliers[i - 1]); + coboundary_elements.push_back(cell + (2 * this->sizes[ i - 1 ] - 1) * this->multipliers[i - 1]); + } + } + } + + cell1 = cell1 % this->multipliers[i - 1]; + } + return coboundary_elements; +} + +} // namespace Cubical_complex + +} // namespace Gudhi + +#endif // BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_ diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index 35c54ade..a9162cee 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -1,105 +1,79 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Saclay (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 . + */ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "cubical_complex" +#include + #include #include #include -#include // standard stuff #include #include +#include -#define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE "cubical_complex" -#include +typedef Gudhi::Cubical_complex::Bitmap_cubical_complex_base Bitmap_cubical_complex_base; +typedef Gudhi::Cubical_complex::Bitmap_cubical_complex Bitmap_cubical_complex; -using namespace std; -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; +typedef Gudhi::Cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base +Bitmap_cubical_complex_periodic_boundary_conditions_base; +typedef Gudhi::Cubical_complex::Bitmap_cubical_complex +Bitmap_cubical_complex_periodic_boundary_conditions; +BOOST_AUTO_TEST_CASE(check_dimension) { + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); + std::vector dimensions({3, 3}); -BOOST_AUTO_TEST_CASE(check_dimension) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); BOOST_CHECK(increasing.dimension() == 2); } BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { - std::vector< double > expectedFiltrationValues1; - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(100); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - - std::vector< double > expectedFiltrationValues2; - expectedFiltrationValues2.push_back(1); - expectedFiltrationValues2.push_back(2); - expectedFiltrationValues2.push_back(3); - expectedFiltrationValues2.push_back(4); - expectedFiltrationValues2.push_back(5); - expectedFiltrationValues2.push_back(6); - expectedFiltrationValues2.push_back(7); - expectedFiltrationValues2.push_back(8); - expectedFiltrationValues2.push_back(9); - - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector< double > oneDimensionalCycle; - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(100); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - Bitmap_cubical_complex< Bitmap_cubical_complex_base > hole(dimensions, oneDimensionalCycle); + std::vector< double > expectedFiltrationValues1({0, 0, 0, 0, 100, 0, 0, 0, 0}); + + std::vector< double > expectedFiltrationValues2({1, 2, 3, 4, 5, 6, 7, 8, 9}); + + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); + + std::vector< double > oneDimensionalCycle({0, 0, 0, 0, 100, 0, 0, 0, 0}); + + std::vector dimensions({3, 3}); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle); int i = 0; - for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = increasing.top_dimensional_cells_iterator_begin(); it != increasing.top_dimensional_cells_iterator_end(); ++it) { BOOST_CHECK(increasing.get_cell_data(*it) == expectedFiltrationValues2[i]); ++i; } i = 0; - for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = hole.top_dimensional_cells_iterator_begin(); it != hole.top_dimensional_cells_iterator_end(); ++it) { BOOST_CHECK(hole.get_cell_data(*it) == expectedFiltrationValues1[i]); ++i; @@ -107,7 +81,6 @@ BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { } BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { - std::vector boundary0; std::vector boundary1; boundary1.push_back(0); @@ -294,22 +267,11 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); + std::vector dimensions({3, 3}); - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); for (size_t i = 0; i != increasing.size(); ++i) { std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { @@ -319,22 +281,11 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { } BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); + std::vector dimensions({3, 3}); - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector coboundaryElements; @@ -429,27 +380,15 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { BOOST_CHECK(coboundaryElements[number] == bd[j]); ++number; } - } } BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); + + std::vector dimensions({3, 3}); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector dim; dim.push_back(0); @@ -508,22 +447,11 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { } BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); + + std::vector dimensions({3, 3}); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector< unsigned > dim; dim.push_back(0); @@ -628,104 +556,93 @@ BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { fil.push_back(9); - Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Filtration_simplex_range range = increasing.filtration_simplex_range(); + Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range(); size_t position = 0; - for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { + for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { BOOST_CHECK(increasing.dimension(*it) == dim[position]); BOOST_CHECK(increasing.filtration(*it) == fil[position]); ++position; } } - - - + BOOST_AUTO_TEST_CASE(boudary_operator_2d_bitmap_with_periodic_bcond) { - std::vector< double > filtration; - filtration.push_back(0); - filtration.push_back(0); - filtration.push_back(0); - filtration.push_back(0); - - - std::vector dimensions; - dimensions.push_back(2); - dimensions.push_back(2); - - std::vector periodic_directions; - periodic_directions.push_back(true); - periodic_directions.push_back(true); - - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtration,periodic_directions); - BOOST_CHECK(cmplx.dimension() == 2); - - + std::vector< double > filtration({0, 0, 0, 0}); + + std::vector dimensions({2, 2}); + + std::vector periodic_directions({true, true}); + + Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtration, periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + std::vector boundary0; - std::vector boundary1; - boundary1.push_back(0); - boundary1.push_back(2); - std::vector boundary2; - std::vector boundary3; - boundary3.push_back(2); - boundary3.push_back(0); - std::vector boundary4; - boundary4.push_back(0); - boundary4.push_back(8); - std::vector boundary5; - boundary5.push_back(1); - boundary5.push_back(9); - boundary5.push_back(4); - boundary5.push_back(6); - std::vector boundary6; - boundary6.push_back(2); - boundary6.push_back(10); - std::vector boundary7; - boundary7.push_back(3); - boundary7.push_back(11); - boundary7.push_back(6); - boundary7.push_back(4); - std::vector boundary8; - std::vector boundary9; - boundary9.push_back(8); - boundary9.push_back(10); - std::vector boundary10; - std::vector boundary11; - boundary11.push_back(10); - boundary11.push_back(8); - std::vector boundary12; - boundary12.push_back(8); - boundary12.push_back(0); - std::vector boundary13; - boundary13.push_back(9); - boundary13.push_back(1); - boundary13.push_back(12); - boundary13.push_back(14); - std::vector boundary14; - boundary14.push_back(10); - boundary14.push_back(2); - std::vector boundary15; - boundary15.push_back(11); - boundary15.push_back(3); - boundary15.push_back(14); - boundary15.push_back(12); - - std::vector< std::vector > boundaries; - boundaries.push_back( boundary0 ); - boundaries.push_back( boundary1 ); - boundaries.push_back( boundary2 ); - boundaries.push_back( boundary3 ); - boundaries.push_back( boundary4 ); - boundaries.push_back( boundary5 ); - boundaries.push_back( boundary6 ); - boundaries.push_back( boundary7 ); - boundaries.push_back( boundary8 ); - boundaries.push_back( boundary9 ); - boundaries.push_back( boundary10 ); - boundaries.push_back( boundary11 ); - boundaries.push_back( boundary12 ); - boundaries.push_back( boundary13 ); - boundaries.push_back( boundary14 ); - boundaries.push_back( boundary15 ); - + std::vector boundary1; + boundary1.push_back(0); + boundary1.push_back(2); + std::vector boundary2; + std::vector boundary3; + boundary3.push_back(2); + boundary3.push_back(0); + std::vector boundary4; + boundary4.push_back(0); + boundary4.push_back(8); + std::vector boundary5; + boundary5.push_back(1); + boundary5.push_back(9); + boundary5.push_back(4); + boundary5.push_back(6); + std::vector boundary6; + boundary6.push_back(2); + boundary6.push_back(10); + std::vector boundary7; + boundary7.push_back(3); + boundary7.push_back(11); + boundary7.push_back(6); + boundary7.push_back(4); + std::vector boundary8; + std::vector boundary9; + boundary9.push_back(8); + boundary9.push_back(10); + std::vector boundary10; + std::vector boundary11; + boundary11.push_back(10); + boundary11.push_back(8); + std::vector boundary12; + boundary12.push_back(8); + boundary12.push_back(0); + std::vector boundary13; + boundary13.push_back(9); + boundary13.push_back(1); + boundary13.push_back(12); + boundary13.push_back(14); + std::vector boundary14; + boundary14.push_back(10); + boundary14.push_back(2); + std::vector boundary15; + boundary15.push_back(11); + boundary15.push_back(3); + boundary15.push_back(14); + boundary15.push_back(12); + + std::vector< std::vector > boundaries; + boundaries.push_back(boundary0); + boundaries.push_back(boundary1); + boundaries.push_back(boundary2); + boundaries.push_back(boundary3); + boundaries.push_back(boundary4); + boundaries.push_back(boundary5); + boundaries.push_back(boundary6); + boundaries.push_back(boundary7); + boundaries.push_back(boundary8); + boundaries.push_back(boundary9); + boundaries.push_back(boundary10); + boundaries.push_back(boundary11); + boundaries.push_back(boundary12); + boundaries.push_back(boundary13); + boundaries.push_back(boundary14); + boundaries.push_back(boundary15); + for (size_t i = 0; i != cmplx.size(); ++i) { std::vector< size_t > bd = cmplx.get_boundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { @@ -733,759 +650,729 @@ BOOST_AUTO_TEST_CASE(boudary_operator_2d_bitmap_with_periodic_bcond) { } } } - - - - - - + BOOST_AUTO_TEST_CASE(coboudary_operator_2d_bitmap_with_periodic_bcond) { - std::vector< double > filtration; - filtration.push_back(0); - filtration.push_back(0); - filtration.push_back(0); - filtration.push_back(0); - - - std::vector dimensions; - dimensions.push_back(2); - dimensions.push_back(2); - - std::vector periodic_directions; - periodic_directions.push_back(true); - periodic_directions.push_back(true); - - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtration,periodic_directions); - BOOST_CHECK(cmplx.dimension() == 2); - - - std::vector coboundary0; - coboundary0.push_back(4); - coboundary0.push_back(12); - coboundary0.push_back(1); - coboundary0.push_back(3); - std::vector coboundary1; - coboundary1.push_back(5); - coboundary1.push_back(13); - std::vector coboundary2; - coboundary2.push_back(6); - coboundary2.push_back(14); - coboundary2.push_back(1); - coboundary2.push_back(3); - std::vector coboundary3; - coboundary3.push_back(7); - coboundary3.push_back(15); - std::vector coboundary4; - coboundary4.push_back(5); - coboundary4.push_back(7); - std::vector coboundary5; - std::vector coboundary6; - coboundary6.push_back(5); - coboundary6.push_back(7); - std::vector coboundary7; - std::vector coboundary8; - coboundary8.push_back(4); - coboundary8.push_back(12); - coboundary8.push_back(9); - coboundary8.push_back(11); - std::vector coboundary9; - coboundary9.push_back(5); - coboundary9.push_back(13); - std::vector coboundary10; - coboundary10.push_back(6); - coboundary10.push_back(14); - coboundary10.push_back(9); - coboundary10.push_back(11); - std::vector coboundary11; - coboundary11.push_back(7); - coboundary11.push_back(15); - std::vector coboundary12; - coboundary12.push_back(13); - coboundary12.push_back(15); - std::vector coboundary13; - std::vector coboundary14; - coboundary14.push_back(13); - coboundary14.push_back(15); + std::vector< double > filtration({0, 0, 0, 0}); + + std::vector dimensions({2, 2}); + + std::vector periodic_directions({true, true}); + + Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtration, periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + + std::vector coboundary0; + coboundary0.push_back(4); + coboundary0.push_back(12); + coboundary0.push_back(1); + coboundary0.push_back(3); + std::vector coboundary1; + coboundary1.push_back(5); + coboundary1.push_back(13); + std::vector coboundary2; + coboundary2.push_back(6); + coboundary2.push_back(14); + coboundary2.push_back(1); + coboundary2.push_back(3); + std::vector coboundary3; + coboundary3.push_back(7); + coboundary3.push_back(15); + std::vector coboundary4; + coboundary4.push_back(5); + coboundary4.push_back(7); + std::vector coboundary5; + std::vector coboundary6; + coboundary6.push_back(5); + coboundary6.push_back(7); + std::vector coboundary7; + std::vector coboundary8; + coboundary8.push_back(4); + coboundary8.push_back(12); + coboundary8.push_back(9); + coboundary8.push_back(11); + std::vector coboundary9; + coboundary9.push_back(5); + coboundary9.push_back(13); + std::vector coboundary10; + coboundary10.push_back(6); + coboundary10.push_back(14); + coboundary10.push_back(9); + coboundary10.push_back(11); + std::vector coboundary11; + coboundary11.push_back(7); + coboundary11.push_back(15); + std::vector coboundary12; + coboundary12.push_back(13); + coboundary12.push_back(15); + std::vector coboundary13; + std::vector coboundary14; + coboundary14.push_back(13); + coboundary14.push_back(15); std::vector coboundary15; - - std::vector< std::vector > coboundaries; - coboundaries.push_back( coboundary0 ); - coboundaries.push_back( coboundary1 ); - coboundaries.push_back( coboundary2 ); - coboundaries.push_back( coboundary3 ); - coboundaries.push_back( coboundary4 ); - coboundaries.push_back( coboundary5 ); - coboundaries.push_back( coboundary6 ); - coboundaries.push_back( coboundary7 ); - coboundaries.push_back( coboundary8 ); - coboundaries.push_back( coboundary9 ); - coboundaries.push_back( coboundary10 ); - coboundaries.push_back( coboundary11 ); - coboundaries.push_back( coboundary12 ); - coboundaries.push_back( coboundary13 ); - coboundaries.push_back( coboundary14 ); - coboundaries.push_back( coboundary15 ); - + + std::vector< std::vector > coboundaries; + coboundaries.push_back(coboundary0); + coboundaries.push_back(coboundary1); + coboundaries.push_back(coboundary2); + coboundaries.push_back(coboundary3); + coboundaries.push_back(coboundary4); + coboundaries.push_back(coboundary5); + coboundaries.push_back(coboundary6); + coboundaries.push_back(coboundary7); + coboundaries.push_back(coboundary8); + coboundaries.push_back(coboundary9); + coboundaries.push_back(coboundary10); + coboundaries.push_back(coboundary11); + coboundaries.push_back(coboundary12); + coboundaries.push_back(coboundary13); + coboundaries.push_back(coboundary14); + coboundaries.push_back(coboundary15); + for (size_t i = 0; i != cmplx.size(); ++i) { std::vector< size_t > cbd = cmplx.get_coboundary_of_a_cell(i); for (size_t j = 0; j != cbd.size(); ++j) { BOOST_CHECK(coboundaries[i][j] == cbd[j]); } } -} - - - - - - - +} + BOOST_AUTO_TEST_CASE(bitmap_2d_with_periodic_bcond_filtration) { - std::vector< double > filtrationOrg; - filtrationOrg.push_back(0); - filtrationOrg.push_back(1); - filtrationOrg.push_back(2); - filtrationOrg.push_back(3); - - - std::vector dimensions; - dimensions.push_back(2); - dimensions.push_back(2); - - std::vector periodic_directions; - periodic_directions.push_back(true); - periodic_directions.push_back(true); - - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtrationOrg,periodic_directions); - BOOST_CHECK(cmplx.dimension() == 2); - - - std::vector filtration; - filtration.push_back(0);//0 - filtration.push_back(0);//1 - filtration.push_back(0);//2 - filtration.push_back(1);//3 - filtration.push_back(0);//4 - filtration.push_back(0);//5 - filtration.push_back(0);//6 - filtration.push_back(1);//7 - filtration.push_back(0);//8 - filtration.push_back(0);//9 - filtration.push_back(0);//10 - filtration.push_back(1);//11 - filtration.push_back(2);//12 - filtration.push_back(2);//13 - filtration.push_back(2);//14 - filtration.push_back(3);//15 - - - for (size_t i = 0; i != cmplx.size(); ++i) - { - BOOST_CHECK( filtration[i] == cmplx.get_cell_data(i) ); + std::vector< double > filtrationOrg({0, 1, 2, 3}); + + std::vector dimensions({2, 2}); + + std::vector periodic_directions({true, true}); + + Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtrationOrg, periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + + std::vector filtration; + filtration.push_back(0); // 0 + filtration.push_back(0); // 1 + filtration.push_back(0); // 2 + filtration.push_back(1); // 3 + filtration.push_back(0); // 4 + filtration.push_back(0); // 5 + filtration.push_back(0); // 6 + filtration.push_back(1); // 7 + filtration.push_back(0); // 8 + filtration.push_back(0); // 9 + filtration.push_back(0); // 10 + filtration.push_back(1); // 11 + filtration.push_back(2); // 12 + filtration.push_back(2); // 13 + filtration.push_back(2); // 14 + filtration.push_back(3); // 15 + + + for (size_t i = 0; i != cmplx.size(); ++i) { + BOOST_CHECK(filtration[i] == cmplx.get_cell_data(i)); } -} - -BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check) -{ - std::vector< double > expected_filtration; - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - - std::vector expected_dimension; - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - - std::vector expected_boundary; - expected_boundary.push_back(0); - expected_boundary.push_back(2); - expected_boundary.push_back(2); - expected_boundary.push_back(4); - expected_boundary.push_back(0); - expected_boundary.push_back(10); - expected_boundary.push_back(1); - expected_boundary.push_back(11); - expected_boundary.push_back(5); - expected_boundary.push_back(7); - expected_boundary.push_back(2); - expected_boundary.push_back(12); - expected_boundary.push_back(3); - expected_boundary.push_back(13); - expected_boundary.push_back(7); - expected_boundary.push_back(9); - expected_boundary.push_back(4); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(12); - expected_boundary.push_back(12); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(20); - expected_boundary.push_back(11); - expected_boundary.push_back(21); - expected_boundary.push_back(15); - expected_boundary.push_back(17); - expected_boundary.push_back(12); - expected_boundary.push_back(22); - expected_boundary.push_back(13); - expected_boundary.push_back(23); - expected_boundary.push_back(17); - expected_boundary.push_back(19); - expected_boundary.push_back(14); - expected_boundary.push_back(24); - expected_boundary.push_back(20); - expected_boundary.push_back(22); - expected_boundary.push_back(22); - expected_boundary.push_back(24); - - - std::vector expected_coboundary; - expected_coboundary.push_back(5); - expected_coboundary.push_back(1); - expected_coboundary.push_back(6); - expected_coboundary.push_back(7); - expected_coboundary.push_back(1); - expected_coboundary.push_back(3); - expected_coboundary.push_back(8); - expected_coboundary.push_back(9); - expected_coboundary.push_back(3); - expected_coboundary.push_back(6); - expected_coboundary.push_back(6); - expected_coboundary.push_back(8); - expected_coboundary.push_back(8); - expected_coboundary.push_back(5); - expected_coboundary.push_back(15); - expected_coboundary.push_back(11); - expected_coboundary.push_back(6); - expected_coboundary.push_back(16); - expected_coboundary.push_back(7); - expected_coboundary.push_back(17); - expected_coboundary.push_back(11); - expected_coboundary.push_back(13); - expected_coboundary.push_back(8); - expected_coboundary.push_back(18); - expected_coboundary.push_back(9); - expected_coboundary.push_back(19); - expected_coboundary.push_back(13); - expected_coboundary.push_back(16); - expected_coboundary.push_back(16); - expected_coboundary.push_back(18); - expected_coboundary.push_back(18); - expected_coboundary.push_back(15); - expected_coboundary.push_back(21); - expected_coboundary.push_back(16); - expected_coboundary.push_back(17); - expected_coboundary.push_back(21); - expected_coboundary.push_back(23); - expected_coboundary.push_back(18); - expected_coboundary.push_back(19); - expected_coboundary.push_back(23); - - - - std::vector< unsigned > sizes(2); - sizes[0] = 2; - sizes[1] = 2; - - std::vector< double > data(4); - data[0] = 0; - data[1] = 1; - data[2] = 2; - data[3] = 3; - - Bitmap_cubical_complex_base ba( sizes , data ); - int i = 0; - int bd_it = 0; - int cbd_it = 0; - for ( Bitmap_cubical_complex_base::All_cells_iterator it = ba.all_cells_iterator_begin() ; it != ba.all_cells_iterator_end() ; ++it ) - { - BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); - BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); - - Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); - for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) - { - BOOST_CHECK( expected_boundary[bd_it] == *bd ); - ++bd_it; - } - - Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); - for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) - { - BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); - ++cbd_it; - } - ++i; - } -} - - - - - - - - -BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check_2) -{ - std::vector< double > expected_filtration; - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - - std::vector expected_dimension; - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - - std::vector expected_boundary; - expected_boundary.push_back(0); - expected_boundary.push_back(2); - expected_boundary.push_back(2); - expected_boundary.push_back(4); - expected_boundary.push_back(0); - expected_boundary.push_back(10); - expected_boundary.push_back(1); - expected_boundary.push_back(11); - expected_boundary.push_back(5); - expected_boundary.push_back(7); - expected_boundary.push_back(2); - expected_boundary.push_back(12); - expected_boundary.push_back(3); - expected_boundary.push_back(13); - expected_boundary.push_back(7); - expected_boundary.push_back(9); - expected_boundary.push_back(4); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(12); - expected_boundary.push_back(12); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(20); - expected_boundary.push_back(11); - expected_boundary.push_back(21); - expected_boundary.push_back(15); - expected_boundary.push_back(17); - expected_boundary.push_back(12); - expected_boundary.push_back(22); - expected_boundary.push_back(13); - expected_boundary.push_back(23); - expected_boundary.push_back(17); - expected_boundary.push_back(19); - expected_boundary.push_back(14); - expected_boundary.push_back(24); - expected_boundary.push_back(20); - expected_boundary.push_back(22); - expected_boundary.push_back(22); - expected_boundary.push_back(24); - - - std::vector expected_coboundary; - expected_coboundary.push_back(5); - expected_coboundary.push_back(1); - expected_coboundary.push_back(6); - expected_coboundary.push_back(7); - expected_coboundary.push_back(1); - expected_coboundary.push_back(3); - expected_coboundary.push_back(8); - expected_coboundary.push_back(9); - expected_coboundary.push_back(3); - expected_coboundary.push_back(6); - expected_coboundary.push_back(6); - expected_coboundary.push_back(8); - expected_coboundary.push_back(8); - expected_coboundary.push_back(5); - expected_coboundary.push_back(15); - expected_coboundary.push_back(11); - expected_coboundary.push_back(6); - expected_coboundary.push_back(16); - expected_coboundary.push_back(7); - expected_coboundary.push_back(17); - expected_coboundary.push_back(11); - expected_coboundary.push_back(13); - expected_coboundary.push_back(8); - expected_coboundary.push_back(18); - expected_coboundary.push_back(9); - expected_coboundary.push_back(19); - expected_coboundary.push_back(13); - expected_coboundary.push_back(16); - expected_coboundary.push_back(16); - expected_coboundary.push_back(18); - expected_coboundary.push_back(18); - expected_coboundary.push_back(15); - expected_coboundary.push_back(21); - expected_coboundary.push_back(16); - expected_coboundary.push_back(17); - expected_coboundary.push_back(21); - expected_coboundary.push_back(23); - expected_coboundary.push_back(18); - expected_coboundary.push_back(19); - expected_coboundary.push_back(23); - - - - std::vector< unsigned > sizes(2); - sizes[0] = 2; - sizes[1] = 2; - - std::vector< double > data(4); - data[0] = 0; - data[1] = 1; - data[2] = 2; - data[3] = 3; - - Bitmap_cubical_complex_base ba( sizes , data ); - int i = 0; - int bd_it = 0; - int cbd_it = 0; - - Bitmap_cubical_complex_base::All_cells_range range(&ba); - for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) - { - BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); - BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); - - Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); - for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) - { - BOOST_CHECK( expected_boundary[bd_it] == *bd ); - ++bd_it; - } - - Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); - for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) - { - BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); - ++cbd_it; - } - ++i; - } -} - - - - - - -BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check) -{ - std::vector< double > expected_filtration; - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - - std::vector expected_dimension; - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - - std::vector expected_boundary; - expected_boundary.push_back(0); - expected_boundary.push_back(2); - expected_boundary.push_back(2); - expected_boundary.push_back(4); - expected_boundary.push_back(0); - expected_boundary.push_back(10); - expected_boundary.push_back(1); - expected_boundary.push_back(11); - expected_boundary.push_back(5); - expected_boundary.push_back(7); - expected_boundary.push_back(2); - expected_boundary.push_back(12); - expected_boundary.push_back(3); - expected_boundary.push_back(13); - expected_boundary.push_back(7); - expected_boundary.push_back(9); - expected_boundary.push_back(4); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(12); - expected_boundary.push_back(12); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(20); - expected_boundary.push_back(11); - expected_boundary.push_back(21); - expected_boundary.push_back(15); - expected_boundary.push_back(17); - expected_boundary.push_back(12); - expected_boundary.push_back(22); - expected_boundary.push_back(13); - expected_boundary.push_back(23); - expected_boundary.push_back(17); - expected_boundary.push_back(19); - expected_boundary.push_back(14); - expected_boundary.push_back(24); - expected_boundary.push_back(20); - expected_boundary.push_back(22); - expected_boundary.push_back(22); - expected_boundary.push_back(24); - - - std::vector expected_coboundary; - expected_coboundary.push_back(5); - expected_coboundary.push_back(1); - expected_coboundary.push_back(6); - expected_coboundary.push_back(7); - expected_coboundary.push_back(1); - expected_coboundary.push_back(3); - expected_coboundary.push_back(8); - expected_coboundary.push_back(9); - expected_coboundary.push_back(3); - expected_coboundary.push_back(6); - expected_coboundary.push_back(6); - expected_coboundary.push_back(8); - expected_coboundary.push_back(8); - expected_coboundary.push_back(5); - expected_coboundary.push_back(15); - expected_coboundary.push_back(11); - expected_coboundary.push_back(6); - expected_coboundary.push_back(16); - expected_coboundary.push_back(7); - expected_coboundary.push_back(17); - expected_coboundary.push_back(11); - expected_coboundary.push_back(13); - expected_coboundary.push_back(8); - expected_coboundary.push_back(18); - expected_coboundary.push_back(9); - expected_coboundary.push_back(19); - expected_coboundary.push_back(13); - expected_coboundary.push_back(16); - expected_coboundary.push_back(16); - expected_coboundary.push_back(18); - expected_coboundary.push_back(18); - expected_coboundary.push_back(15); - expected_coboundary.push_back(21); - expected_coboundary.push_back(16); - expected_coboundary.push_back(17); - expected_coboundary.push_back(21); - expected_coboundary.push_back(23); - expected_coboundary.push_back(18); - expected_coboundary.push_back(19); - expected_coboundary.push_back(23); - - - - std::vector< unsigned > sizes(2); - sizes[0] = 2; - sizes[1] = 2; - - std::vector< double > data(4); - data[0] = 0; - data[1] = 1; - data[2] = 2; - data[3] = 3; - - Bitmap_cubical_complex_base ba( sizes , data ); - int i = 0; - int bd_it = 0; - int cbd_it = 0; - - Bitmap_cubical_complex_base::All_cells_range range = ba.all_cells_range(); - for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) - { - BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); - BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); - - Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); - for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) - { - BOOST_CHECK( expected_boundary[bd_it] == *bd ); - ++bd_it; - } - - Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); - for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) - { - BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); - ++cbd_it; - } - ++i; - } -} - -BOOST_AUTO_TEST_CASE(Top_dimensional_cells_iterator_range_check) -{ - std::vector< double > expected_filtration; - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - - - std::vector< unsigned > sizes(2); - sizes[0] = 2; - sizes[1] = 2; - - std::vector< double > data(4); - data[0] = 0; - data[1] = 1; - data[2] = 2; - data[3] = 3; - - Bitmap_cubical_complex_base ba( sizes , data ); - int i = 0; - - Bitmap_cubical_complex_base::Top_dimensional_cells_range range = ba.top_dimensional_cells_range(); - for ( Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it = range.begin() ; it != range.end() ; ++it ) - { - BOOST_CHECK( data[i] == ba.get_cell_data( *it ) ); - BOOST_CHECK( ba.get_dimension_of_a_cell( *it ) == 2 ); - ++i; - } -} +} +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + for ( Bitmap_cubical_complex_base::All_cells_iterator it = ba.all_cells_iterator_begin() ; it != ba.all_cells_iterator_end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} + + + + + + + + +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check_2) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + + Bitmap_cubical_complex_base::All_cells_range range(&ba); + for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} + + + + + + +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + + Bitmap_cubical_complex_base::All_cells_range range = ba.all_cells_range(); + for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} + +BOOST_AUTO_TEST_CASE(Top_dimensional_cells_iterator_range_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + + Bitmap_cubical_complex_base::Top_dimensional_cells_range range = ba.top_dimensional_cells_range(); + for ( Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( data[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( ba.get_dimension_of_a_cell( *it ) == 2 ); + ++i; + } +} + -- cgit v1.2.3 From 019a4fd1f7e624603f85740cbec859f3daab39d4 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 29 Mar 2016 19:33:05 +0000 Subject: Add include numeric for std::iota git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1076 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6bb361c7ff62c5a8812db125cfd0375d64696504 --- src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 1fd36914..adfe33b5 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -30,6 +30,7 @@ #include // for pair<> #include // for sort #include +#include // for iota namespace Gudhi { -- cgit v1.2.3 From c3f3b627da09dc85616ae4a43787ea5f1fdeaf1f Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 30 Mar 2016 05:45:58 +0000 Subject: Fix cppcheck/cpplint Add TBB for parallel sort git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1077 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8d4692b14e59bf7a6556bc7f69dbdc18582d6c0d --- .../include/gudhi/Bitmap_cubical_complex.h | 16 +- .../include/gudhi/Bitmap_cubical_complex/counter.h | 244 +++++++++------------ .../include/gudhi/Bitmap_cubical_complex_base.h | 40 ++-- ...cal_complex_periodic_boundary_conditions_base.h | 2 +- 4 files changed, 137 insertions(+), 165 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index adfe33b5..86bfbd56 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -26,6 +26,10 @@ #include #include +#ifdef GUDHI_USE_TBB +#include +#endif + #include #include // for pair<> #include // for sort @@ -129,7 +133,7 @@ class Bitmap_cubical_complex : public T { /** * Destructor of the Bitmap_cubical_complex class. **/ - virtual ~Bitmap_cubical_complex(){} + virtual ~Bitmap_cubical_complex() {} //*********************************************// // Other 'easy' functions @@ -259,7 +263,7 @@ class Bitmap_cubical_complex : public T { public: Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { } - Filtration_simplex_iterator() : b(NULL) { } + Filtration_simplex_iterator() : b(NULL), position(0) { } Filtration_simplex_iterator operator++() { if (globalDbg) { @@ -537,9 +541,11 @@ void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { } this->simplex_associated_to_key = std::vector(this->data.size()); std::iota(std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); - std::sort(simplex_associated_to_key.begin(), - simplex_associated_to_key.end(), - is_before_in_filtration(this)); +#ifdef GUDHI_USE_TBB + tbb::parallel_sort(filtration_vect_, is_before_in_filtration(this)); +#else + std::sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(), is_before_in_filtration(this)); +#endif // we still need to deal here with a key_associated_to_simplex: for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h index c13d96e1..266ce051 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h @@ -20,152 +20,124 @@ * along with this program. If not, see . */ -#pragma once +#ifndef BITMAP_CUBICAL_COMPLEX_COUNTER_H_ +#define BITMAP_CUBICAL_COMPLEX_COUNTER_H_ #include #include -using namespace std; +namespace Gudhi { -namespace Gudhi -{ - -namespace Cubical_complex -{ +namespace Cubical_complex { /** -* This is an implementation of a counter being a vector of integers. -* The constructor of the class takes as an input two vectors W and V. -* It assumes that W < V coordinatewise. -* If the initial counter W is not specified, it is assumed to be vector of zeros. -* The class allows to iterate between W and V by using increment() function. -* The increment() function returns a bool value. -* The current counter reach the end counter V if the value returned by the increment function is FALSE. -* This class is needed for the implementation of a bitmapCubicalComplex. -**/ - -class counter -{ -public: - /** - * Constructor of a counter class. It takes only the parameter which is the end value of the counter. - * The default beginning value is a vector of the same length as the endd, filled-in with zeros. - **/ - counter(const std::vector& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} - //counter(std::vector< int >& endd) - //{ - // for ( size_t i = 0 ; i != endd.size() ; ++i ) - // { - // this->current.push_back(0); - // this->begin.push_back(0); - // this->end.push_back( endd[i] ); - // } - //} - - - /** - * Constructor of a counter class. It takes as the input beginn and end vector. - * It assumes that begin vector is lexicographically below the end vector. - **/ - counter(const std::vector< unsigned >& beginn , const std::vector< unsigned >& endd):begin(beginn),end(endd),current(endd.size(),0) - { - if ( beginn.size() != endd.size() ) - throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; - } - - /** - * Function to increment the counter. If the value returned by the function is true, - * then the incrementation process was successful. - * If the value of the function is false, that means, that the counter have reached its end-value. - **/ - bool increment() - { - size_t i = 0; - while( (i != this->end.size()) && (this->current[i] == this->end[i]) ) - { - ++i; - } - - if ( i == this->end.size() )return false; - ++this->current[i]; - for ( size_t j = 0 ; j != i ; ++j ) - { - this->current[j] = this->begin[j]; - } - return true; - } - - /** - * Function to check if we are at the end of counter. - **/ - bool isFinal() - { - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( this->current[i] == this->end[i] )return true; - } - return false; - } - - /** - * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. - * Its aim is to find an counter corresponding to the element the following - * boundary element is identified with when periodic boundary conditions are imposed. - **/ - std::vector< unsigned > find_opposite( const std::vector< bool >& directionsForPeriodicBCond ) - { - std::vector< unsigned > result; - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( (this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true) ) - { - result.push_back( this->begin[i] ); - } - else - { - result.push_back( this->current[i] ); - } - } - return result; + * This is an implementation of a counter being a vector of integers. + * The constructor of the class takes as an input two vectors W and V. + * It assumes that W < V coordinatewise. + * If the initial counter W is not specified, it is assumed to be vector of zeros. + * The class allows to iterate between W and V by using increment() function. + * The increment() function returns a bool value. + * The current counter reach the end counter V if the value returned by the increment function is FALSE. + * This class is needed for the implementation of a bitmapCubicalComplex. + **/ + +class counter { + public: + /** + * Constructor of a counter class. It takes only the parameter which is the end value of the counter. + * The default beginning value is a vector of the same length as the endd, filled-in with zeros. + **/ + counter(const std::vector& endd) : begin(endd.size(), 0), end(endd), current(endd.size(), 0) { } + + /** + * Constructor of a counter class. It takes as the input beginn and end vector. + * It assumes that begin vector is lexicographically below the end vector. + **/ + counter(const std::vector< unsigned >& beginn, const std::vector< unsigned >& endd) : begin(beginn), end(endd), current(endd.size(), 0) { + if (beginn.size() != endd.size()) + throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; + } + + /** + * Function to increment the counter. If the value returned by the function is true, + * then the incrementation process was successful. + * If the value of the function is false, that means, that the counter have reached its end-value. + **/ + bool increment() { + size_t i = 0; + while ((i != this->end.size()) && (this->current[i] == this->end[i])) { + ++i; } - /** - * Function checking at which positions the current value of a counter is the final value of the counter. - **/ - std::vector< bool > directions_of_finals() - { - std::vector< bool > result; - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( this->current[i] == this->end[i] ) - { - result.push_back( true ); - } - else - { - result.push_back( false ); - } - } - return result; + if (i == this->end.size())return false; + ++this->current[i]; + for (size_t j = 0; j != i; ++j) { + this->current[j] = this->begin[j]; } - - /** - * Function to write counter to the stream. - **/ - friend std::ostream& operator<<(std::ostream& out , const counter& c ) - { - //cerr << "c.current.size() : " << c.current.size() << endl; - for ( size_t i = 0 ; i != c.current.size() ; ++i ) - { - out << c.current[i] << " "; - } - return out; + return true; + } + + /** + * Function to check if we are at the end of counter. + **/ + bool isFinal() { + for (size_t i = 0; i != this->current.size(); ++i) { + if (this->current[i] == this->end[i])return true; + } + return false; + } + + /** + * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. + * Its aim is to find an counter corresponding to the element the following + * boundary element is identified with when periodic boundary conditions are imposed. + **/ + std::vector< unsigned > find_opposite(const std::vector< bool >& directionsForPeriodicBCond) { + std::vector< unsigned > result; + for (size_t i = 0; i != this->current.size(); ++i) { + if ((this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true)) { + result.push_back(this->begin[i]); + } else { + result.push_back(this->current[i]); + } + } + return result; + } + + /** + * Function checking at which positions the current value of a counter is the final value of the counter. + **/ + std::vector< bool > directions_of_finals() { + std::vector< bool > result; + for (size_t i = 0; i != this->current.size(); ++i) { + if (this->current[i] == this->end[i]) { + result.push_back(true); + } else { + result.push_back(false); + } } -private: - std::vector< unsigned > begin; - std::vector< unsigned > end; - std::vector< unsigned > current; + return result; + } + + /** + * Function to write counter to the stream. + **/ + friend std::ostream& operator<<(std::ostream& out, const counter& c) { + // std::cerr << "c.current.size() : " << c.current.size() << endl; + for (size_t i = 0; i != c.current.size(); ++i) { + out << c.current[i] << " "; + } + return out; + } + + private: + std::vector< unsigned > begin; + std::vector< unsigned > end; + std::vector< unsigned > current; }; -} -} \ No newline at end of file +} // namespace Cubical_complex + +} // namespace Gudhi + +#endif // BITMAP_CUBICAL_COMPLEX_COUNTER_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 62776019..d858f3c5 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -204,7 +204,7 @@ class Bitmap_cubical_complex_base { } All_cells_iterator operator++() { - //first find first element of the counter that can be increased: + // first find first element of the counter that can be increased: ++this->counter; return *this; } @@ -317,14 +317,13 @@ class Bitmap_cubical_complex_base { **/ class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, T > { public: - Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b) : b(b) { this->counter = std::vector(b.dimension()); - //std::fill( this->counter.begin() , this->counter.end() , 0 ); + // std::fill( this->counter.begin() , this->counter.end() , 0 ); } Top_dimensional_cells_iterator operator++() { - //first find first element of the counter that can be increased: + // first find first element of the counter that can be increased: size_t dim = 0; while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1))++dim; @@ -499,7 +498,7 @@ void Bitmap_cubical_complex_base::put_data_to_bins(size_t number_of_bins) { std::pair< T, T > min_max = this->min_max_filtration(); T dx = (min_max.second - min_max.first) / (T) number_of_bins; - //now put the data into the appropriate bins: + // now put the data into the appropriate bins: for (size_t i = 0; i != this->data.size(); ++i) { if (bdg) { std::cerr << "Before binning : " << this->data[i] << std::endl; @@ -518,7 +517,7 @@ void Bitmap_cubical_complex_base::put_data_to_bins(T diameter_of_bin) { std::pair< T, T > min_max = this->min_max_filtration(); size_t number_of_bins = (min_max.second - min_max.first) / diameter_of_bin; - //now put the data into the appropriate bins: + // now put the data into the appropriate bins: for (size_t i = 0; i != this->data.size(); ++i) { if (bdg) { std::cerr << "Before binning : " << this->data[i] << std::endl; @@ -542,7 +541,7 @@ std::pair< T, T > Bitmap_cubical_complex_base::min_max_filtration() { } template -ostream& operator<<(ostream & out, const Bitmap_cubical_complex_base& b) { +std::ostream& operator<<(std::ostream & out, const Bitmap_cubical_complex_base& b) { for (typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b.all_cells_const_begin(); it != b.all_cells_const_end(); ++it) { out << *it << " "; @@ -565,16 +564,13 @@ void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells number_of_top_dimensional_elements *= sizes_in_following_directions[i]; } if (number_of_top_dimensional_elements != top_dimensional_cells.size()) { - std::cerr << - "Error in constructor\ - Bitmap_cubical_complex_base\ - ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ - Number of top dimensional elements that follow from sizes_in_following_directions vector is different\ - than the size of top_dimensional_cells vector." << std::endl; - throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions,\ - std::vector top_dimensional_cells )\ - . Number of top dimensional elements that follow from sizes_in_following_directions vector is different than the\ - size of top_dimensional_cells vector."); + std::cerr << "Error in constructor Bitmap_cubical_complex_base ( std::vector sizes_in_following_directions" + << ", std::vector top_dimensional_cells ). Number of top dimensional elements that follow from " + << "sizes_in_following_directions vector is different than the size of top_dimensional_cells vector." + << std::endl; + throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions," + "std::vector top_dimensional_cells ). Number of top dimensional elements that follow from " + "sizes_in_following_directions vector is different than the size of top_dimensional_cells vector."); } Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); @@ -610,7 +606,6 @@ void Bitmap_cubical_complex_base::read_perseus_style_file(const char* perseus for (size_t i = 0; i != dimensionOfData; ++i) { unsigned size_in_this_dimension; inFiltration >> size_in_this_dimension; - size_in_this_dimension = size_in_this_dimension; sizes.push_back(size_in_this_dimension); if (dbg) { std::cerr << "size_in_this_dimension : " << size_in_this_dimension << std::endl; @@ -738,8 +733,7 @@ template void Bitmap_cubical_complex_base::impose_lower_star_filtration() { bool dbg = false; - //this vector will be used to check which elements have already been taken care of - //in imposing lower star filtration: + // this vector will be used to check which elements have already been taken care of in imposing lower star filtration std::vector is_this_cell_considered(this->data.size(), false); size_t size_to_reserve = 1; @@ -749,8 +743,8 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { std::vector indices_to_consider; indices_to_consider.reserve(size_to_reserve); - //we assume here that we already have a filtration on the top dimensional cells and - //we have to extend it to lower ones. + // we assume here that we already have a filtration on the top dimensional cells and + // we have to extend it to lower ones. typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); for (it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { indices_to_consider.push_back(it.compute_index_in_bitmap()); @@ -799,7 +793,7 @@ bool compareFirstElementsOfTuples(const std::pair< std::pair< T, size_t >, char if (first.first.first > second.first.first) { return false; } - //in this case first.first.first == second.first.first, so we need to compare dimensions + // in this case first.first.first == second.first.first, so we need to compare dimensions return first.second < second.second; } } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 2c0d77fe..8afa342e 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -84,7 +84,7 @@ class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_c /** * Destructor of the Bitmap_cubical_complex_periodic_boundary_conditions_base class. **/ - virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base(){} + virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base() {} // overwritten methods co compute boundary and coboundary /** -- cgit v1.2.3 From bea7dab826c2dcff4632df3d99480adc94be3f8d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 30 Mar 2016 06:14:43 +0000 Subject: cpplint/cppcheck fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1078 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 794e42d37fa8417489d92d6d67d05399225d6fcd --- .../include/gudhi/Bitmap_cubical_complex.h | 2 + .../include/gudhi/Bitmap_cubical_complex_base.h | 77 +++++++++++++--------- ...cal_complex_periodic_boundary_conditions_base.h | 19 +++--- 3 files changed, 59 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 86bfbd56..de463d8e 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -285,6 +285,7 @@ class Bitmap_cubical_complex : public T { } this->b = rhs.b; this->position = rhs.position; + return (*this); } bool operator==(const Filtration_simplex_iterator& rhs)const { @@ -454,6 +455,7 @@ class Bitmap_cubical_complex : public T { this->b = rhs.b; this->position = rhs.position; this->dimension = rhs.dimension; + return (*this); } bool operator==(const Skeleton_simplex_iterator& rhs)const { diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index d858f3c5..2258b581 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -140,7 +140,7 @@ class Bitmap_cubical_complex_base { * then there is no need to call this function. Call it only if you are putting the filtration * of the cells by your own (for instance by using Top_dimensional_cells_iterator). **/ - void impose_lower_star_filtration(); // assume that top dimensional cells are already set. + void impose_lower_star_filtration(); // assume that top dimensional cells are already set. /** * Returns dimension of a complex. @@ -198,7 +198,6 @@ class Bitmap_cubical_complex_base { **/ class All_cells_iterator : std::iterator< std::input_iterator_tag, T > { public: - All_cells_iterator() { this->counter = 0; } @@ -215,7 +214,7 @@ class Bitmap_cubical_complex_base { return result; } - All_cells_iterator operator=(const All_cells_iterator& rhs) { + All_cells_iterator& operator=(const All_cells_iterator& rhs) { this->counter = rhs.counter; return *this; } @@ -230,8 +229,10 @@ class Bitmap_cubical_complex_base { } /* - * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: - * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as + * an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell + * boundary and coboundary and dimension * and in function get_cell_data to get a filtration of a cell. */ size_t operator*() { @@ -264,8 +265,7 @@ class Bitmap_cubical_complex_base { **/ class All_cells_range { public: - - All_cells_range(Bitmap_cubical_complex_base* b) : b(b) { }; + All_cells_range(Bitmap_cubical_complex_base* b) : b(b) { } All_cells_iterator begin() { return b->all_cells_iterator_begin(); @@ -344,7 +344,7 @@ class Bitmap_cubical_complex_base { return result; } - Top_dimensional_cells_iterator operator=(const Top_dimensional_cells_iterator& rhs) { + Top_dimensional_cells_iterator& operator=(const Top_dimensional_cells_iterator& rhs) { this->counter = rhs.counter; this->b = rhs.b; return *this; @@ -364,8 +364,10 @@ class Bitmap_cubical_complex_base { } /* - * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: - * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as + * an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell + * boundary and coboundary and dimension * and in function get_cell_data to get a filtration of a cell. */ size_t operator*() { @@ -416,8 +418,7 @@ class Bitmap_cubical_complex_base { **/ class Top_dimensional_cells_range { public: - - Top_dimensional_cells_range(Bitmap_cubical_complex_base* b) : b(b) { }; + Top_dimensional_cells_range(Bitmap_cubical_complex_base* b) : b(b) { } Top_dimensional_cells_iterator begin() { return b->top_dimensional_cells_iterator_begin(); @@ -485,10 +486,13 @@ class Bitmap_cubical_complex_base { return counter; } void read_perseus_style_file(const char* perseus_style_file); - void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, const std::vector& top_dimensional_cells); + void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, + const std::vector& top_dimensional_cells); Bitmap_cubical_complex_base(const char* perseus_style_file, std::vector directions); Bitmap_cubical_complex_base(const std::vector& sizes, std::vector directions); - Bitmap_cubical_complex_base(const std::vector& dimensions, const std::vector& top_dimensional_cells, std::vector directions); + Bitmap_cubical_complex_base(const std::vector& dimensions, + const std::vector& top_dimensional_cells, + std::vector directions); }; template @@ -556,7 +560,8 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base } template -void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, const std::vector& top_dimensional_cells) { +void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, + const std::vector& top_dimensional_cells) { this->set_up_containers(sizes_in_following_directions); size_t number_of_top_dimensional_elements = 1; @@ -568,7 +573,7 @@ void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells << ", std::vector top_dimensional_cells ). Number of top dimensional elements that follow from " << "sizes_in_following_directions vector is different than the size of top_dimensional_cells vector." << std::endl; - throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions," + throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions," "std::vector top_dimensional_cells ). Number of top dimensional elements that follow from " "sizes_in_following_directions vector is different than the size of top_dimensional_cells vector."); } @@ -591,7 +596,7 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base template void Bitmap_cubical_complex_base::read_perseus_style_file(const char* perseus_style_file) { bool dbg = false; - std::ifstream inFiltration, inIds; + std::ifstream inFiltration; inFiltration.open(perseus_style_file); unsigned dimensionOfData; inFiltration >> dimensionOfData; @@ -634,23 +639,30 @@ void Bitmap_cubical_complex_base::read_perseus_style_file(const char* perseus } template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const char* perseus_style_file, std::vector directions) { - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const char* perseus_style_file, + std::vector directions) { + // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary + // conditions. + // It ignores the last parameter of the function. this->read_perseus_style_file(perseus_style_file); } template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& sizes, std::vector directions) { - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& sizes, + std::vector directions) { + // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary + // conditions. + // It ignores the last parameter of the function. this->set_up_containers(sizes); } template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& dimensions, const std::vector& top_dimensional_cells, std::vector directions) { - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& dimensions, + const std::vector& top_dimensional_cells, + std::vector directions) { + // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary + // conditions. + // It ignores the last parameter of the function. this->setup_bitmap_based_on_top_dimensional_cells_list(dimensions, top_dimensional_cells); } @@ -663,7 +675,7 @@ template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(size_t cell)const { std::vector< size_t > boundary_elements; - //Speed traded of for memory. Check if it is better in practice. + // Speed traded of for memory. Check if it is better in practice. boundary_elements.reserve(this->dimension()*2); size_t cell1 = cell; @@ -763,14 +775,17 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { std::vector bd = this->get_boundary_of_a_cell(indices_to_consider[i]); for (size_t boundaryIt = 0; boundaryIt != bd.size(); ++boundaryIt) { if (dbg) { - std::cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << std::endl; + std::cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] + << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] + << std::endl; getchar(); } if (this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ]) { this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; if (dbg) { - std::cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << std::endl; + std::cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " + << this->data[ indices_to_consider[i] ] << std::endl; getchar(); } } @@ -798,8 +813,8 @@ bool compareFirstElementsOfTuples(const std::pair< std::pair< T, size_t >, char } } -} // namespace Cubical_complex +} // namespace Cubical_complex -} // namespace Gudhi +} // namespace Gudhi #endif // BITMAP_CUBICAL_COMPLEX_BASE_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 8afa342e..a446c0e8 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -44,9 +44,10 @@ namespace Cubical_complex { * @ingroup cubical_complex */ /** -* This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are identical to the functions from Bitmap_cubical_complex_base. -* The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell. -*/ + * This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are + * identical to the functions from Bitmap_cubical_complex_base. + * The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell. + */ template class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base { public: @@ -88,14 +89,16 @@ class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_c // overwritten methods co compute boundary and coboundary /** - * A version of a function that return boundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + * A version of a function that return boundary of a given cell for an object of + * Bitmap_cubical_complex_periodic_boundary_conditions_base class. */ - virtual std::vector< size_t > get_boundary_of_a_cell(size_t cell)const; + virtual std::vector< size_t > get_boundary_of_a_cell(size_t cell) const; /** - * A version of a function that return coboundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + * A version of a function that return coboundary of a given cell for an object of + * Bitmap_cubical_complex_periodic_boundary_conditions_base class. */ - virtual std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + virtual std::vector< size_t > get_coboundary_of_a_cell(size_t cell) const; protected: std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; @@ -132,7 +135,7 @@ void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_comp this->set_up_containers(dimensions); size_t i = 0; - for (typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { + for (auto it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { this->get_cell_data(*it) = topDimensionalCells[i]; ++i; } -- cgit v1.2.3 From dea986187f3a214db300a909f8f8a02cf3d9014d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 30 Mar 2016 06:31:24 +0000 Subject: cpplint/cppcheck fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1079 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 812004416560ad653025d02ea7ff05677ec5b3fc --- src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h | 6 +++--- .../include/gudhi/Bitmap_cubical_complex_base.h | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index de463d8e..7bf9617e 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -397,7 +397,8 @@ class Bitmap_cubical_complex : public T { } // this method returns two first elements from the boundary of sh. if (bdry.size() < 2) - throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the boundary."); + throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the " + "boundary."); return std::make_pair(bdry[0], bdry[1]); } @@ -550,8 +551,7 @@ void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { #endif // we still need to deal here with a key_associated_to_simplex: - for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) - { + for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) { this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; } } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 2258b581..7294da98 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -779,7 +779,6 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << std::endl; getchar(); - } if (this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ]) { this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; -- cgit v1.2.3 From aa1b1f242900b678e29f93ab3439c59e93fdda4b Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 30 Mar 2016 09:20:49 +0000 Subject: Fix use of TBB parallel sort. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1082 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 337109ed520bf0e5836ceb0dba11948b75cafae2 --- .../include/gudhi/Bitmap_cubical_complex.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 7bf9617e..67e1fed3 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -46,9 +46,12 @@ const bool globalDbg = false; template class is_before_in_filtration; /** -* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into -* Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template parameter is supposed to be either Bitmap_cubical_complex_base or Bitmap_cubical_complex_periodic_boundary_conditions_base class. -**/ + * This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and + * Bitmap_cubical_complex_periodic_boundary_conditions_base classes into + * Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template + * parameter is supposed to be either Bitmap_cubical_complex_base or + * Bitmap_cubical_complex_periodic_boundary_conditions_base class. + **/ /** *@class Bitmap_cubical_complex @@ -113,7 +116,8 @@ class Bitmap_cubical_complex : public T { /** * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells * in the following directions and vector of element of a type T::filtration_type - * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. + * with filtration on top dimensional cells. The last parameter of the constructor is a vector of boolean of a length + * equal to the dimension of cubical complex. * If the position i on this vector is true, then we impose periodic boundary conditions in this direction. **/ Bitmap_cubical_complex(const std::vector& dimensions, @@ -545,7 +549,7 @@ void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { this->simplex_associated_to_key = std::vector(this->data.size()); std::iota(std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); #ifdef GUDHI_USE_TBB - tbb::parallel_sort(filtration_vect_, is_before_in_filtration(this)); + tbb::parallel_sort(simplex_associated_to_key, is_before_in_filtration(this)); #else std::sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(), is_before_in_filtration(this)); #endif -- cgit v1.2.3 From 94638281f656211b429ee20ed6be25a84db8074c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 6 Apr 2016 19:21:39 +0000 Subject: GUDHIConfig.cmake fix Modules were missing in src/CMakeLists.txt generate_version.sh must copy GUDHIConfig.cmake and not GUDHIConfig.cmake.in nor CMakeGUDHIVersion.txt git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1100 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2b618b7a395017cb1bde8a9a7afd7c9e54c29710 --- CMakeLists.txt | 2 +- scripts/generate_version.sh | 3 +-- src/CMakeLists.txt | 10 ++++------ 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/CMakeLists.txt b/CMakeLists.txt index abb66ec2..e35da63e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ project(GUDHIdev) include(CMakeGUDHIVersion.txt) # Generate GUDHI official version file -configure_file(GUDHIVersion.cmake.in "${PROJECT_BINARY_DIR}/GUDHIVersion.cmake" @ONLY) +configure_file(GUDHIVersion.cmake.in "${CMAKE_SOURCE_DIR}/GUDHIVersion.cmake" @ONLY) find_package(Boost REQUIRED COMPONENTS system filesystem unit_test_framework chrono timer program_options thread REQUIRED) diff --git a/scripts/generate_version.sh b/scripts/generate_version.sh index 323396dc..4482c506 100755 --- a/scripts/generate_version.sh +++ b/scripts/generate_version.sh @@ -45,7 +45,6 @@ mkdir "$VERSION_DIR" # TOP LEVEL FILE COPY cp $VERSION_FILE $VERSION_DIR -cp $ROOT_DIR/CMakeGUDHIVersion.txt $VERSION_DIR cp $ROOT_DIR/README $VERSION_DIR cp $ROOT_DIR/Conventions.txt $VERSION_DIR cp $ROOT_DIR/COPYING $VERSION_DIR @@ -55,7 +54,7 @@ cp $ROOT_DIR/src/Doxyfile $VERSION_DIR cp -R $ROOT_DIR/biblio $VERSION_DIR cp $ROOT_DIR/src/GUDHIConfigVersion.cmake.in $VERSION_DIR cp $ROOT_DIR/src/GUDHIConfig.cmake.in $VERSION_DIR -cp $ROOT_DIR/GUDHIVersion.cmake.in $VERSION_DIR +cp $ROOT_DIR/GUDHIVersion.cmake $VERSION_DIR # PACKAGE LEVEL COPY PACKAGE_INC_DIR="/include" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 40b7dd58..42d3755a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 2.6) project(GUDHI) -include("CMakeGUDHIVersion.txt") - enable_testing() list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") @@ -66,10 +64,10 @@ else() # Gudhi compilation part include_directories(include) - #add_subdirectory(example/Simplex_tree) - #add_subdirectory(example/Persistent_cohomology) - #add_subdirectory(example/Skeleton_blocker) - #add_subdirectory(example/Contraction) + add_subdirectory(example/Simplex_tree) + add_subdirectory(example/Persistent_cohomology) + add_subdirectory(example/Skeleton_blocker) + add_subdirectory(example/Contraction) add_subdirectory(example/Bitmap_cubical_complex) add_subdirectory(example/Witness_complex) -- cgit v1.2.3 From 0ca1fbeb35a9a681320186f63a7cf26256ebf05a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 8 Apr 2016 08:44:07 +0000 Subject: GUDHIConfig.cmake fix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1106 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 79bac32f28985e759f0e3c04a470e29325ecd64f --- scripts/generate_version.sh | 5 ++--- src/CMakeLists.txt | 7 ++++++- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/scripts/generate_version.sh b/scripts/generate_version.sh index 4482c506..6f66a638 100755 --- a/scripts/generate_version.sh +++ b/scripts/generate_version.sh @@ -44,7 +44,6 @@ echo $VERSION_DIR mkdir "$VERSION_DIR" # TOP LEVEL FILE COPY -cp $VERSION_FILE $VERSION_DIR cp $ROOT_DIR/README $VERSION_DIR cp $ROOT_DIR/Conventions.txt $VERSION_DIR cp $ROOT_DIR/COPYING $VERSION_DIR @@ -54,11 +53,11 @@ cp $ROOT_DIR/src/Doxyfile $VERSION_DIR cp -R $ROOT_DIR/biblio $VERSION_DIR cp $ROOT_DIR/src/GUDHIConfigVersion.cmake.in $VERSION_DIR cp $ROOT_DIR/src/GUDHIConfig.cmake.in $VERSION_DIR -cp $ROOT_DIR/GUDHIVersion.cmake $VERSION_DIR +cp $ROOT_DIR/CMakeGUDHIVersion.txt $VERSION_DIR +cp $ROOT_DIR/GUDHIVersion.cmake.in $VERSION_DIR # PACKAGE LEVEL COPY PACKAGE_INC_DIR="/include" -#PACKAGE_SRC_DIR="/source" PACKAGE_EX_DIR="/example" PACKAGE_CONCEPT_DIR="/concept" PACKAGE_DOC_DIR="/doc" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 42d3755a..00bdf800 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,10 @@ cmake_minimum_required(VERSION 2.6) project(GUDHI) +include("CMakeGUDHIVersion.txt") +# Generate GUDHI official version file +configure_file(GUDHIVersion.cmake.in "${CMAKE_SOURCE_DIR}/GUDHIVersion.cmake" @ONLY) + enable_testing() list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") @@ -85,8 +89,9 @@ else() # (this registers the build-tree with a global CMake-registry) export(PACKAGE GUDHI) + message("++ make install will install ${PROJECT_NAME} in the following directory : ${CMAKE_INSTALL_PREFIX}") # Create the GUDHIConfig.cmake and GUDHIConfigVersion files - set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include") + set(CONF_INCLUDE_DIRS "${CMAKE_INSTALL_PREFIX}/include") configure_file(GUDHIConfig.cmake.in "${PROJECT_BINARY_DIR}/GUDHIConfig.cmake" @ONLY) configure_file(GUDHIConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/GUDHIConfigVersion.cmake" @ONLY) -- cgit v1.2.3