From 7a6ebbd6c26306bca806bbc8c08f74a13c63fca6 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Tue, 11 Oct 2016 07:43:50 +0000 Subject: adding answert to Vincent's comments git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/gudhi_stat@1688 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3e90519425010bfedae7af946238188fee6cf420 --- .../compute_distance_of_landscapes_on_grid.cpp | 107 +++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp (limited to 'src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp') diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp new file mode 100644 index 00000000..1813e297 --- /dev/null +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp @@ -0,0 +1,107 @@ +/* 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 (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 + + + +using namespace Gudhi; +using namespace Gudhi::Gudhi_stat; + +#include +#include + + +int main( int argc , char** argv ) +{ + std::cout << "This program compute dsitance of persistence landscapes on grid stored in a file (the file needs to be created beforehand). \n"; + std::cout << "The first parameter of a program is an interger p. The program compute L^p distance of the the landscapes on grid. For L^infty distance choose p = -1. \n"; + std::cout << "The remaining parameters of this programs are names of files with persistence landscapes on grid.\n"; + + if ( argc < 3 ) + { + std::cout << "Wrong number of parameters, the program will now terminate \n"; + return 1; + } + + int p = atoi( argv[1] ); + + std::vector< const char* > filenames; + for ( int i = 2 ; i < argc ; ++i ) + { + filenames.push_back( argv[i] ); + } + std::vector< Persistence_landscape_on_grid > landscaspes; + landscaspes.reserve( filenames.size() ); + for ( size_t file_no = 0 ; file_no != filenames.size() ; ++file_no ) + { + Persistence_landscape_on_grid l; + l.load_landscape_from_file( filenames[file_no] ); + landscaspes.push_back( l ); + } + + //and now we will compute the scalar product of landscapes. + + //first we prepare an array: + std::vector< std::vector< double > > distance( filenames.size() ); + for ( size_t i = 0 ; i != filenames.size() ; ++i ) + { + std::vector< double > v( filenames.size() , 0 ); + distance[i] = v; + } + + //and now we can compute the scalar product: + for ( size_t i = 0 ; i != landscaspes.size() ; ++i ) + { + for ( size_t j = i ; j != landscaspes.size() ; ++j ) + { + distance[i][j] = distance[j][i] = compute_discance_of_landscapes_on_grid( landscaspes[i], landscaspes[j] , p ) ; + } + } + + //and now output the result to the screen and a file: + ofstream out; + out.open( "distance" ); + for ( size_t i = 0 ; i != distance.size() ; ++i ) + { + for ( size_t j = 0 ; j != distance.size() ; ++j ) + { + cout << distance[i][j] << " "; + out << distance[i][j] << " "; + } + cout << endl; + out << endl; + } + out.close(); + + return 0; +} + + + + + + + -- cgit v1.2.3 From 19451e20b6d47b6a84d5ad89d99497e0e60cd377 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 21 Oct 2016 12:26:22 +0000 Subject: The library changed from inherritance to templates. Are the files from include/abstract removed? git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/gudhi_stat@1741 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6f768b08a7a900a56278adcf371a31840916d3ba --- .../concept/Real_valued_topological_data.h | 38 ++++ .../concept/Topological_data_with_averages.h | 35 ++++ .../concept/Topological_data_with_distances.h | 31 +++ .../concept/Topological_data_with_scalar_product.h | 31 +++ .../concept/Vectorized_topological_data.h | 39 ++++ src/Gudhi_stat/example/persistence_heat_maps.cpp | 10 +- src/Gudhi_stat/example/persistence_landscape.cpp | 10 +- .../example/persistence_landscape_on_grid.cpp | 10 +- src/Gudhi_stat/example/vector_representation.cpp | 10 +- .../gudhi/concretizations/Persistence_heat_maps.h | 101 +++++---- .../gudhi/concretizations/Persistence_intervals.h | 163 +++++++++------ .../gudhi/concretizations/Persistence_landscape.h | 127 +++++++++--- .../Persistence_landscape_on_grid.h | 230 ++++++++++++++------- .../concretizations/Vector_distances_in_diagram.h | 139 +++++++------ .../concretizations/read_persitence_from_file.h | 5 +- src/Gudhi_stat/include/gudhi/permutation_test.h | 80 +++++++ src/Gudhi_stat/include/gudhi/topological_process.h | 101 +++++++++ src/Gudhi_stat/test/persistence_heat_maps_test.cpp | 84 ++++---- .../test/persistence_lanscapes_on_grid_test.cpp | 12 +- src/Gudhi_stat/test/persistence_lanscapes_test.cpp | 10 +- src/Gudhi_stat/test/vector_representation_test.cpp | 8 +- src/Gudhi_stat/utilities/CMakeLists.txt | 4 +- src/Gudhi_stat/utilities/permutation_test.cpp | 84 ++++++++ .../average_persistence_heat_maps.cpp | 5 +- .../compute_distance_of_persistence_heat_maps.cpp | 12 +- ...ute_scalar_product_of_persistence_heat_maps.cpp | 10 +- .../create_persistence_heat_maps.cpp | 1 - ...aps_weighted_by_arctan_of_their_persistence.cpp | 1 - ...eat_maps_weighted_by_distance_from_diagonal.cpp | 2 - ..._weighted_by_squared_distance_from_diagonal.cpp | 2 - .../persistence_heat_maps/create_pssk.cpp | 3 - .../plot_persistence_heat_map.cpp | 2 - ...te_birth_death_range_in_persistence_diagram.cpp | 1 - .../compute_number_of_dominant_intervals.cpp | 1 - .../plot_histogram_of_intervals_lengths.cpp | 1 - .../plot_persistence_Betti_numebrs.cpp | 1 - .../plot_persistence_intervals.cpp | 1 - .../persistence_landscapes/average_landscapes.cpp | 5 +- .../compute_distance_of_landscapes.cpp | 3 - .../compute_scalar_product_of_landscapes.cpp | 3 - .../persistence_landscapes/create_landscapes.cpp | 3 - .../persistence_landscapes/plot_landscapes.cpp | 3 - .../average_landscapes_on_grid.cpp | 7 +- .../compute_distance_of_landscapes_on_grid.cpp | 3 - ...ompute_scalar_product_of_landscapes_on_grid.cpp | 2 - .../create_landscapes_on_grid.cpp | 3 - .../plot_landscapes_on_grid.cpp | 3 - .../average_persistence_vectors.cpp | 6 +- .../compute_distance_of_persistence_vectors.cpp | 11 +- ...mpute_scalar_product_of_persistence_vectors.cpp | 20 +- .../create_persistence_vectors.cpp | 3 - .../plot_persistence_vectors.cpp | 3 - 52 files changed, 1047 insertions(+), 436 deletions(-) create mode 100644 src/Gudhi_stat/concept/Real_valued_topological_data.h create mode 100644 src/Gudhi_stat/concept/Topological_data_with_averages.h create mode 100644 src/Gudhi_stat/concept/Topological_data_with_distances.h create mode 100644 src/Gudhi_stat/concept/Topological_data_with_scalar_product.h create mode 100644 src/Gudhi_stat/concept/Vectorized_topological_data.h create mode 100644 src/Gudhi_stat/include/gudhi/permutation_test.h create mode 100644 src/Gudhi_stat/include/gudhi/topological_process.h create mode 100644 src/Gudhi_stat/utilities/permutation_test.cpp (limited to 'src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp') diff --git a/src/Gudhi_stat/concept/Real_valued_topological_data.h b/src/Gudhi_stat/concept/Real_valued_topological_data.h new file mode 100644 index 00000000..ead22bf4 --- /dev/null +++ b/src/Gudhi_stat/concept/Real_valued_topological_data.h @@ -0,0 +1,38 @@ +/* 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 (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 Real_valued_topological_data describes the requirements + * for a type to implement a container that allows computations of its projections to R. + */ +class Real_valued_topological_data +{ +public: + /** + * Typically there are various ways data can be projected to R. This function give us the number of functions for vectorization provided by a given class. + **/ + size_t number_of_projections_to_R(); + /** + * This is a function to compute the projection from this container to reals. The parameter of a function have to be between 0 and the value returned by number_of_projections_to_R(). + **/ + double project_to_R; +}; + diff --git a/src/Gudhi_stat/concept/Topological_data_with_averages.h b/src/Gudhi_stat/concept/Topological_data_with_averages.h new file mode 100644 index 00000000..67433860 --- /dev/null +++ b/src/Gudhi_stat/concept/Topological_data_with_averages.h @@ -0,0 +1,35 @@ + +/* 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 (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 Topological_data_with_averages describes the requirements + * for a type to implement a container that allows computations of averages. + */ +class Topological_data_with_averages +{ +public: + void compute_average( const std::vector< Topological_data_with_averages* >& to_average ); +}; + + diff --git a/src/Gudhi_stat/concept/Topological_data_with_distances.h b/src/Gudhi_stat/concept/Topological_data_with_distances.h new file mode 100644 index 00000000..536ae821 --- /dev/null +++ b/src/Gudhi_stat/concept/Topological_data_with_distances.h @@ -0,0 +1,31 @@ +/* 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 (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 Topological_data_with_distances describes the requirements + * for a type to implement a container that allows computations of distance to another contained of that type. + */ +class Topological_data_with_distances +{ +public: + double distance( const Topological_data_with_distances& second , double power = 1); +}; + diff --git a/src/Gudhi_stat/concept/Topological_data_with_scalar_product.h b/src/Gudhi_stat/concept/Topological_data_with_scalar_product.h new file mode 100644 index 00000000..f32271c7 --- /dev/null +++ b/src/Gudhi_stat/concept/Topological_data_with_scalar_product.h @@ -0,0 +1,31 @@ +/* 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 (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 Topological_data_with_scalar_product describes the requirements + * for a type to implement a container that allows computations of scalar products. + */ +class Topological_data_with_scalar_product +{ +public: + double compute_scalar_product( const Topological_data_with_scalar_product& second ); +}; diff --git a/src/Gudhi_stat/concept/Vectorized_topological_data.h b/src/Gudhi_stat/concept/Vectorized_topological_data.h new file mode 100644 index 00000000..2dd966fd --- /dev/null +++ b/src/Gudhi_stat/concept/Vectorized_topological_data.h @@ -0,0 +1,39 @@ +/* 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 (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 Vectorized_topological_data describes the requirements + * for a type to implement a container that allows vectorization. + */ +class Vectorized_topological_data +{ +public: + /** + * There are various ways data can be verctorized. This function give us the number of functions for vectorization provided by a given class. + **/ + size_t number_of_vectorize_functions(); + /** + * This is a function to vectorize given container. The parameter of a function have to be between 0 and the value returned by number_of_vectorize_functions(). + **/ + std::vector vectorize( int number_of_function ); +}; + diff --git a/src/Gudhi_stat/example/persistence_heat_maps.cpp b/src/Gudhi_stat/example/persistence_heat_maps.cpp index 7f5580da..645f63f7 100644 --- a/src/Gudhi_stat/example/persistence_heat_maps.cpp +++ b/src/Gudhi_stat/example/persistence_heat_maps.cpp @@ -75,17 +75,17 @@ int main( int argc , char** argv ) median.compute_median( vector_of_maps ); //to compute L^1 disance between hm1 and hm2: - std::cout << "The L^1 distance is : " << hm1.distance( (Abs_Topological_data_with_distances*)(&hm2) , 1 ) << std::endl; + std::cout << "The L^1 distance is : " << hm1.distance( hm2 , 1 ) << std::endl; //to average of hm1 and hm2: - std::vector< Abs_Topological_data_with_averages* > to_average; - to_average.push_back( (Abs_Topological_data_with_averages*)(&hm1) ); - to_average.push_back( (Abs_Topological_data_with_averages*)(&hm2) ); + std::vector< Persistence_heat_maps* > to_average; + to_average.push_back( &hm1 ); + to_average.push_back( &hm2 ); Persistence_heat_maps av; av.compute_average( to_average ); //to compute scalar product of hm1 and hm2: - std::cout << "Scalar product is : " << hm1.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)(&hm2) ) << std::endl; + std::cout << "Scalar product is : " << hm1.compute_scalar_product( hm2 ) << std::endl; return 0; } diff --git a/src/Gudhi_stat/example/persistence_landscape.cpp b/src/Gudhi_stat/example/persistence_landscape.cpp index f5110153..106864c0 100644 --- a/src/Gudhi_stat/example/persistence_landscape.cpp +++ b/src/Gudhi_stat/example/persistence_landscape.cpp @@ -76,17 +76,17 @@ int main( int argc , char** argv ) //here is the average of landscapes: Persistence_landscape average; - std::vector< Abs_Topological_data_with_averages* > to_average; - to_average.push_back( (Abs_Topological_data_with_averages*)(&l1) ); - to_average.push_back( (Abs_Topological_data_with_averages*)(&l2) ); + std::vector< Persistence_landscape* > to_average; + to_average.push_back( &l1 ); + to_average.push_back( &l2 ); average.compute_average( to_average ); std::cout << "average : " << average << std::endl; //here is the distance of landscapes: - std::cout << "Distance : " << l1.distance( (Abs_Topological_data_with_distances*)(&l2) ) << std::endl; + std::cout << "Distance : " << l1.distance( l2 ) << std::endl; //here is the scalar product of landscapes: - std::cout << "Scalar product : " << l1.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)(&l2) ) << std::endl; + std::cout << "Scalar product : " << l1.compute_scalar_product( l2 ) << std::endl; //here is how to create a file which is suitable for vizualization via gnuplot: average.plot( "average_landscape" ); diff --git a/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp b/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp index ddda78d2..223c9d50 100644 --- a/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp +++ b/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp @@ -72,17 +72,17 @@ int main( int argc , char** argv ) //here is the average of landscapes: Persistence_landscape_on_grid average; - std::vector< Abs_Topological_data_with_averages* > to_average; - to_average.push_back( (Abs_Topological_data_with_averages*)(&l1) ); - to_average.push_back( (Abs_Topological_data_with_averages*)(&l2) ); + std::vector< Persistence_landscape_on_grid* > to_average; + to_average.push_back( &l1 ); + to_average.push_back( &l2 ); average.compute_average( to_average ); std::cout << "average : " << average << std::endl; //here is the distance of landscapes: - std::cout << "Distance : " << l1.distance( (Abs_Topological_data_with_distances*)(&l2) ) << std::endl; + std::cout << "Distance : " << l1.distance( l2 ) << std::endl; //here is the scalar product of landscapes: - std::cout << "Scalar product : " << l1.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)(&l2) ) << std::endl; + std::cout << "Scalar product : " << l1.compute_scalar_product( l2 ) << std::endl; //here is how to create a file which is suitable for vizualization via gnuplot: average.plot( "average_landscape" ); diff --git a/src/Gudhi_stat/example/vector_representation.cpp b/src/Gudhi_stat/example/vector_representation.cpp index 773c60fa..835b52f9 100644 --- a/src/Gudhi_stat/example/vector_representation.cpp +++ b/src/Gudhi_stat/example/vector_representation.cpp @@ -66,17 +66,17 @@ int main( int argc , char** argv ) //averages: Vector_distances_in_diagram > average; - std::vector< Abs_Topological_data_with_averages* > to_average; - to_average.push_back( (Abs_Topological_data_with_averages*)(&v1) ); - to_average.push_back( (Abs_Topological_data_with_averages*)(&v2) ); + std::vector< Vector_distances_in_diagram >* > to_average; + to_average.push_back( &v1 ); + to_average.push_back( &v2 ); average.compute_average( to_average ); std::cout << "Average : " << average << std::endl; //computations of distances: - std::cout << "l^1 distance : " << v1.distance( (Abs_Topological_data_with_distances*)(&v2) ) << std::endl; + std::cout << "l^1 distance : " << v1.distance( v2 ) << std::endl; //computations of scalar product: - std::cout << "Scalar product of l1 and l2 : " << v1.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)(&v2) ) << std::endl; + std::cout << "Scalar product of l1 and l2 : " << v1.compute_scalar_product( v2 ) << std::endl; //create a file with a gnuplot script: v1.plot( "plot_of_vector_representation" ); diff --git a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_heat_maps.h b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_heat_maps.h index e9175af9..d2c1bfc9 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_heat_maps.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_heat_maps.h @@ -33,11 +33,6 @@ #include //gudhi include -#include -#include -#include -#include -#include #include #include @@ -161,13 +156,10 @@ private: }; - -class Persistence_heat_maps : - public Abs_Vectorized_topological_data , - public Abs_Topological_data_with_distances , - public Abs_Real_valued_topological_data, - public Abs_Topological_data_with_averages, - public Abs_Topological_data_with_scalar_product +/** + * This class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product +**/ +class Persistence_heat_maps { public: /** @@ -321,16 +313,59 @@ public: void plot( const char* filename ); - //Concretizations of virtual methods: - std::vector vectorize( int number_of_function ); - double distance( const Abs_Topological_data_with_distances* second_ , double power = 1); + //Implementations of functions for various concepts. + + /** + * This function produce a vector of doubles based on a persisence heat map. It is required in a concept Vectorized_topological_data + */ + std::vector vectorize( int number_of_function ); + /** + * This function return the number of functions that allows vectorization of persistence heat map. It is required in a concept Vectorized_topological_data. + **/ + size_t number_of_vectorize_functions() + { + return this->number_of_functions_for_vectorization; + } + + /** + * This function is required by the Real_valued_topological_data concept. It returns various projections od the persistence heat map to a real line. + **/ double project_to_R( int number_of_function ); - void compute_average( const std::vector< Abs_Topological_data_with_averages* >& to_average ); - double compute_scalar_product( const Abs_Topological_data_with_scalar_product* second_ ); + /** + * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. + **/ + size_t number_of_projections_to_R() + { + return this->number_of_functions_for_projections_to_reals; + } + + /** + * A function to compute distance between persistence heat maps. + * The parameter of this function is a const reference to an object of a class Persistence_heat_maps. + * This function is required in Topological_data_with_distances concept. + **/ + double distance( const Persistence_heat_maps& second_ , double power = 1); + + /** + * A function to compute averaged persistence heat map, based on vector of persistence heat maps. + * This function is required by Topological_data_with_averages concept. + **/ + void compute_average( const std::vector< Persistence_heat_maps* >& to_average ); + + /** + * A function to compute scalar product of persistence heat maps. + * The parameter of this functionis a const reference to an object of a class Persistence_heat_maps. + * This function is required in Topological_data_with_scalar_product concept. + **/ + double compute_scalar_product( const Persistence_heat_maps& second_ ); + + //end of implementation of functions needed for concepts. protected: //private methods std::vector< std::vector > check_and_initialize_maps( const std::vector& maps ); + size_t number_of_functions_for_vectorization; + size_t number_of_functions_for_projections_to_reals; void construct( const std::vector< std::pair >& intervals_ , std::vector< std::vector > filter = create_Gaussian_filter(5,1), double (*scalling_function_with_respect_to_distance_from_diagonal)( const std::pair< double , double >& point_in_diagram ) = constant_function, @@ -717,12 +752,10 @@ std::vector Persistence_heat_maps::vectorize( int number_of_function ) return result; } -double Persistence_heat_maps::distance( const Abs_Topological_data_with_distances* second_ , double power ) -{ - Persistence_heat_maps* second = (Persistence_heat_maps*)second_; - +double Persistence_heat_maps::distance( const Persistence_heat_maps& second , double power ) +{ //first we need to check if (*this) and second are defined on the same domain and have the same dimensions: - if ( !this->check_if_the_same(*second) ) + if ( !this->check_if_the_same(second) ) { std::cerr << "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; throw "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; @@ -735,7 +768,7 @@ double Persistence_heat_maps::distance( const Abs_Topological_data_with_distance { for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) { - distance += pow( abs(this->heat_map[i][j] - second->heat_map[i][j]) , power ); + distance += pow( abs(this->heat_map[i][j] - second.heat_map[i][j]) , power ); } } return distance; @@ -754,23 +787,15 @@ double Persistence_heat_maps::project_to_R( int number_of_function ) return result; } -void Persistence_heat_maps::compute_average( const std::vector< Abs_Topological_data_with_averages* >& to_average ) -{ - std::vector maps; - maps.reserve( to_average.size() ); - for ( size_t i = 0 ; i != to_average.size() ; ++i ) - { - maps.push_back( (Persistence_heat_maps*)to_average[i] ); - } - this->compute_mean( maps ); +void Persistence_heat_maps::compute_average( const std::vector< Persistence_heat_maps* >& to_average ) +{ + this->compute_mean( to_average ); } -double Persistence_heat_maps::compute_scalar_product( const Abs_Topological_data_with_scalar_product* second_ ) -{ - Persistence_heat_maps* second = (Persistence_heat_maps*)second_; - +double Persistence_heat_maps::compute_scalar_product( const Persistence_heat_maps& second ) +{ //first we need to check if (*this) and second are defined on the same domain and have the same dimensions: - if ( !this->check_if_the_same(*second) ) + if ( !this->check_if_the_same(second) ) { std::cerr << "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; throw "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; @@ -782,7 +807,7 @@ double Persistence_heat_maps::compute_scalar_product( const Abs_Topological_data { for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) { - scalar_prod += this->heat_map[i][j]*second->heat_map[i][j]; + scalar_prod += this->heat_map[i][j]*second.heat_map[i][j]; } } return scalar_prod; diff --git a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_intervals.h b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_intervals.h index f694541b..5d21ba97 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_intervals.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_intervals.h @@ -24,9 +24,6 @@ #define Persistence_intervals_H_ //gudhi include -#include -#include -#include #include //standard include @@ -43,7 +40,10 @@ namespace Gudhi namespace Gudhi_stat { -class Persistence_intervals : public Abs_Vectorized_topological_data , public Abs_Topological_data_with_distances, public Abs_Real_valued_topological_data +/** + * This class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data +**/ +class Persistence_intervals { public: /** @@ -114,11 +114,11 @@ public: /** * Operator that send the diagram to a stream. **/ - friend ostream& operator << ( ostream& out , const Persistence_intervals& intervals ) + friend std::ostream& operator << ( std::ostream& out , const Persistence_intervals& intervals ) { for ( size_t i = 0 ; i != intervals.intervals.size() ; ++i ) { - out << intervals.intervals[i].first << " " << intervals.intervals[i].second << endl; + out << intervals.intervals[i].first << " " << intervals.intervals[i].second << std::endl; } return out; } @@ -129,38 +129,30 @@ public: void plot( const char* filename ) { //this program create a gnuplot script file that allows to plot persistence diagram. - ofstream out; + std::ofstream out; std::ostringstream nameSS; nameSS << filename << "_GnuplotScript"; std::string nameStr = nameSS.str(); out.open( (char*)nameStr.c_str() ); std::pair min_max_values = this->min_max(); - out << "set xrange [" << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " : " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " ]" << endl; - out << "set yrange [" << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " : " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " ]" << endl; - out << "plot '-' using 1:2 notitle \"" << filename << "\", \\" << endl; - out << " '-' using 1:2 notitle with lp" << endl; + out << "set xrange [" << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " : " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " ]" << std::endl; + out << "set yrange [" << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " : " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " ]" << std::endl; + out << "plot '-' using 1:2 notitle \"" << filename << "\", \\" << std::endl; + out << " '-' using 1:2 notitle with lp" << std::endl; for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) { - out << this->intervals[i].first << " " << this->intervals[i].second << endl; + out << this->intervals[i].first << " " << this->intervals[i].second << std::endl; } - out << "EOF" << endl; - out << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " " << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << endl; - out << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << endl; + out << "EOF" << std::endl; + out << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " " << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << std::endl; + out << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << std::endl; out.close(); - cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << endl; + std::cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << std::endl; } - /** - * Return a familly of vectors obtained from the persistence diagram. The i-th vector consist of the lenfth of i dominant persistence intervals. - **/ - std::vector vectorize( int number_of_function )//comment: in this case, number_of_functions (a static member of Abs_Vectorized_topological_data cannot be set a priori. - //In this cas, maybe it is better not to make this parameter static. - { - return this->length_of_dominant_intervals( number_of_function ); - } /** * Retun numbr of points in the diagram. @@ -176,22 +168,71 @@ public: return this->intervals[i]; } + + + + + + + + + + + + + + + //Implementations of functions for various concepts. + /** + * This is a simple function projectig the persistence intervals to a real number. The function we use here is a sum of squared lendgths of intervals. It can be naturally interpreted as + * sum of step function, where the step hight it equal to the length of the interval. + **/ + double project_to_R( int number_of_function ); + /** + * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. + **/ + size_t number_of_projections_to_R() + { + return this->number_of_functions_for_projections_to_reals; + } + + /** + * Return a familly of vectors obtained from the persistence diagram. The i-th vector consist of the lenfth of i dominant persistence intervals. + **/ + std::vector vectorize( int number_of_function ) + { + return this->length_of_dominant_intervals( number_of_function ); + } + /** + * This function return the number of functions that allows vectorization of a persisence diagram. It is required in a concept Vectorized_topological_data. + **/ + size_t number_of_vectorize_functions() + { + return this->number_of_functions_for_vectorization; + } + /** *Computations of distance from the current persistnce diagram to the persistence diagram given as a parameter of this function. *The last parameter, power, is here in case we would like to compute p=th Wasserstein distance. At the moment, for the bottleneck distances, it will be ignored. **/ - double distance( const Abs_Topological_data_with_distances* second , double power = 1) + double distance( const Persistence_intervals& second , double power = 1) { return 1; //waiting for Francois Godi for the code. We will compute here the Bottleneck distnace. } + //end of implementation of functions needed for concepts. - /** - * This is a simple function projectig the persistence intervals to a real number. The function we use here is a sum of squared lendgths of intervals. It can be naturally interpreted as - * sum of step function, where the step hight it equal to the length of the interval. - **/ - double project_to_R( int number_of_function ); - + + + + + + + + + + + //For visualization use output from vectorize and build histograms. std::vector< std::pair< double,double > > output_for_visualization() @@ -208,7 +249,9 @@ protected: this->number_of_functions_for_projections_to_reals = 1; } - std::vector< std::pair< double,double > > intervals; + std::vector< std::pair< double,double > > intervals; + size_t number_of_functions_for_vectorization; + size_t number_of_functions_for_projections_to_reals; }; @@ -240,7 +283,7 @@ Persistence_intervals::Persistence_intervals( const char* filename ) // this->intervals.push_back( std::make_pair( first,second ) ); // if ( dbg ) // { - // cerr << "Adding interval [ " << first << " , " << second << " ]\n"; + // std::cerr << "Adding interval [ " << first << " , " << second << " ]\n"; // getchar(); // } //} @@ -303,7 +346,7 @@ std::vector< std::pair > Persistence_intervals::dominant_interval for ( size_t i = 0 ; i != std::min( where_to_cut , position_length_vector.size() ) ; ++i ) { result.push_back( this->intervals[ position_length_vector[i].first ] ); - if ( dbg )cerr << "Position : " << position_length_vector[i].first << " length : " << position_length_vector[i].second << endl; + if ( dbg )std::cerr << "Position : " << position_length_vector[i].first << " length : " << position_length_vector[i].second << std::endl; } return result; @@ -314,7 +357,7 @@ std::vector< size_t > Persistence_intervals::histograms_of_lengths( size_t numbe { bool dbg = false; - if ( dbg )cerr << "this->intervals.size() : " << this->intervals.size() << endl; + if ( dbg )std::cerr << "this->intervals.size() : " << this->intervals.size() << std::endl; //first find the length of the longest interval: double lengthOfLongest = 0; for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) @@ -325,7 +368,7 @@ std::vector< size_t > Persistence_intervals::histograms_of_lengths( size_t numbe } } - if ( dbg ){cerr << "lengthOfLongest : " << lengthOfLongest << endl;} + if ( dbg ){std::cerr << "lengthOfLongest : " << lengthOfLongest << std::endl;} //this is a container we will use to store the resulting histogram std::vector< size_t > result( number_of_bins + 1 , 0 ); @@ -344,16 +387,16 @@ std::vector< size_t > Persistence_intervals::histograms_of_lengths( size_t numbe if ( dbg ) { - cerr << "i : " << i << endl; - cerr << "Interval : [" << this->intervals[i].first << " , " << this->intervals[i].second << " ] \n"; - cerr << "relative_length_of_this_interval : " << relative_length_of_this_interval << endl; - cerr << "position : " << position << endl; + std::cerr << "i : " << i << std::endl; + std::cerr << "Interval : [" << this->intervals[i].first << " , " << this->intervals[i].second << " ] \n"; + std::cerr << "relative_length_of_this_interval : " << relative_length_of_this_interval << std::endl; + std::cerr << "position : " << position << std::endl; getchar(); } } - if ( dbg ){for ( size_t i = 0 ; i != result.size() ; ++i )cerr << result[i] << endl;} + if ( dbg ){for ( size_t i = 0 ; i != result.size() ; ++i )std::cerr << result[i] << std::endl;} return result; } @@ -384,7 +427,7 @@ std::vector< double > Persistence_intervals::characteristic_function_of_diagram( { if ( dbg ) { - cerr << "Interval : " << this->intervals[i].first << " , " << this->intervals[i].second << endl; + std::cerr << "Interval : " << this->intervals[i].first << " , " << this->intervals[i].second << std::endl; } size_t beginIt = 0; @@ -407,8 +450,8 @@ std::vector< double > Persistence_intervals::characteristic_function_of_diagram( if ( dbg ) { - cerr << "beginIt : " << beginIt << endl; - cerr << "endIt : " << endIt << endl; + std::cerr << "beginIt : " << beginIt << std::endl; + std::cerr << "endIt : " << endIt << std::endl; } @@ -419,12 +462,12 @@ std::vector< double > Persistence_intervals::characteristic_function_of_diagram( //cerr << "x_max : " << x_max << " x_min : " << x_min << " , number_of_bins : " << number_of_bins << " this->intervals[i].second : " << this->intervals[i].second << " this->intervals[i].first : " << this->intervals[i].first << endl; if ( dbg ) { - cerr << "Result at this stage \n"; + std::cerr << "Result at this stage \n"; for ( size_t aa = 0 ; aa != result.size() ; ++aa ) { - cerr << result[aa] << " "; + std::cerr << result[aa] << " "; } - cerr << endl; + std::cerr << std::endl; //getchar(); } } @@ -498,10 +541,10 @@ std::vector< double > Persistence_intervals::k_n_n( size_t k , size_t where_to_c bool dbg = false; if ( dbg ) { - cerr << "Here are the intervals : \n"; + std::cerr << "Here are the intervals : \n"; for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) { - cerr << "[ " << this->intervals[i].first << " , " << this->intervals[i].second << "] \n"; + std::cerr << "[ " << this->intervals[i].first << " , " << this->intervals[i].second << "] \n"; } getchar(); } @@ -532,12 +575,12 @@ std::vector< double > Persistence_intervals::k_n_n( size_t k , size_t where_to_c if ( dbg ) { - cerr << "Here are the distances form the point : [" << this->intervals[i].first << " , " << this->intervals[i].second << "] in the diagram \n"; + std::cerr << "Here are the distances form the point : [" << this->intervals[i].first << " , " << this->intervals[i].second << "] in the diagram \n"; for ( size_t aa = 0 ; aa != distancesFromI.size() ; ++aa ) { - cerr << "To : " << i+aa << " : " << distancesFromI[aa] << " "; + std::cerr << "To : " << i+aa << " : " << distancesFromI[aa] << " "; } - cerr << endl; + std::cerr << std::endl; getchar(); } @@ -550,21 +593,21 @@ std::vector< double > Persistence_intervals::k_n_n( size_t k , size_t where_to_c } if ( dbg ) { - cerr << "Here is the distance matrix : \n"; + std::cerr << "Here is the distance matrix : \n"; for ( size_t i = 0 ; i != distances.size() ; ++i ) { for ( size_t j = 0 ; j != distances.size() ; ++j ) { - cerr << distances[i][j] << " "; + std::cerr << distances[i][j] << " "; } - cerr << endl; + std::cerr << std::endl; } - cerr << endl << endl << "And here are the distances to the diagonal : " << endl; + std::cerr << std::endl << std::endl << "And here are the distances to the diagonal : " << std::endl; for ( size_t i = 0 ; i != distances_from_diagonal. size() ; ++i ) { - cerr << distances_from_diagonal[i] << " "; + std::cerr << distances_from_diagonal[i] << " "; } - cerr << endl << endl; + std::cerr << std::endl << std::endl; getchar(); } @@ -580,7 +623,7 @@ std::vector< double > Persistence_intervals::k_n_n( size_t k , size_t where_to_c { if ( dbg ) { - cerr << "There are not enough neighbors in your set. We set the result to plus infty \n"; + std::cerr << "There are not enough neighbors in your set. We set the result to plus infty \n"; } result.push_back( std::numeric_limits::max() ); } @@ -590,7 +633,7 @@ std::vector< double > Persistence_intervals::k_n_n( size_t k , size_t where_to_c { if ( dbg ) { - cerr << "The k-th n.n. is on a diagonal. Therefore we set up a distance to diagonal \n"; + std::cerr << "The k-th n.n. is on a diagonal. Therefore we set up a distance to diagonal \n"; } result.push_back( distances_from_diagonal[i] ); } diff --git a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape.h b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape.h index aa74514e..b3caaedc 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape.h @@ -36,11 +36,6 @@ //gudhi include -#include -#include -#include -#include -#include #include #include using namespace std; @@ -62,13 +57,9 @@ namespace Gudhi_stat * A clas implementing persistence landascpes data structures. For theroretical desciritpion, please consult a paper ''Statistical topological data analysis using persistence landscapes'' by Peter Bubenik. * For details of algorithms, please consult ''A persistence landscapes toolbox for topological statistics'' by Peter Bubenik and Pawel Dlotko. * Persistence landscapes allow vertorization, computations of distances, computations of projections to Real, computations of averages and scalar products. Therefore they implement suitable interfaces. + * It implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product **/ -class Persistence_landscape : - public Abs_Vectorized_topological_data , - public Abs_Topological_data_with_distances, - public Abs_Real_valued_topological_data, - public Abs_Topological_data_with_averages, - public Abs_Topological_data_with_scalar_product +class Persistence_landscape { public: /** @@ -326,16 +317,39 @@ public: - //concretization of abstract functions: + + + + + + + + + + + + //Implementations of functions for various concepts. /** * The number of projections to R is defined to the number of nonzero landscape functions. I-th projection is an integral of i-th landscape function over whole R. + * This function is required by the Real_valued_topological_data concept. **/ double project_to_R( int number_of_function ) { return this->compute_integral_of_landscape( (size_t)number_of_function ); } + + /** + * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. + **/ + size_t number_of_projections_to_R() + { + return this->number_of_functions_for_projections_to_reals; + } + /** + * This function produce a vector of doubles based on a landscape. It is required in a concept Vectorized_topological_data + */ std::vector vectorize( int number_of_function ) { //TODO, think of something smarter over here @@ -351,14 +365,28 @@ public: } return v; } - void compute_average( const std::vector< Abs_Topological_data_with_averages* >& to_average ) + /** + * This function return the number of functions that allows vectorization of persistence laandscape. It is required in a concept Vectorized_topological_data. + **/ + size_t number_of_vectorize_functions() + { + return this->number_of_functions_for_vectorization; + } + + /** + * A function to compute averaged persistence landscape, based on vector of persistence landscapes. + * This function is required by Topological_data_with_averages concept. + **/ + void compute_average( const std::vector< Persistence_landscape* >& to_average ) { - bool dbg = false; + bool dbg = false; + + if ( dbg ){std::cerr << "to_average.size() : " << to_average.size() << std::endl;} std::vector< Persistence_landscape* > nextLevelMerge( to_average.size() ); for ( size_t i = 0 ; i != to_average.size() ; ++i ) { - nextLevelMerge[i] = (Persistence_landscape*)to_average[i]; + nextLevelMerge[i] = to_average[i]; } bool is_this_first_level = true;//in the loop, we will create dynamically a unmber of intermediate complexes. We have to clean that up, but we cannot erase the initial andscapes we have //to average. In this case, we simply check if the nextLevelMerge are the input landscapes or the ones created in that loop by usig this extra variable. @@ -373,8 +401,8 @@ public: if ( dbg ){cerr << "i : " << i << endl;} Persistence_landscape* l = new Persistence_landscape; if ( i+1 != nextLevelMerge.size() ) - { - (*l) = (*nextLevelMerge[i])+(*nextLevelMerge[i+1]); + { + (*l) = (*nextLevelMerge[i])+(*nextLevelMerge[i+1]); } else { @@ -382,7 +410,7 @@ public: } nextNextLevelMerge.push_back( l ); } - if ( dbg ){cerr << "After this iteration \n";} + if ( dbg ){cerr << "After this iteration \n";getchar();} if ( !is_this_first_level ) { @@ -400,23 +428,53 @@ public: } - double distance( const Abs_Topological_data_with_distances* second , double power = 1 ) + /** + * A function to compute distance between persistence landscape. + * The parameter of this functionis a Persistence_landscape. + * This function is required in Topological_data_with_distances concept. + **/ + double distance( const Persistence_landscape& second , double power = 1 ) { if ( power != -1 ) { - return compute_discance_of_landscapes( *this , *((Persistence_landscape*)second) , power ); + return compute_discance_of_landscapes( *this , second , power ); } else { - return compute_max_norm_discance_of_landscapes( *this , *((Persistence_landscape*)second) ); + return compute_max_norm_discance_of_landscapes( *this , second ); } } - double compute_scalar_product( const Abs_Topological_data_with_scalar_product* second ) + /** + * A function to compute scalar product of persistence landscapes. + * The parameter of this functionis a Persistence_landscape. + * This function is required in Topological_data_with_scalar_product concept. + **/ + double compute_scalar_product( const Persistence_landscape& second ) { - return compute_inner_product( (*this) , *((Persistence_landscape*)second) ); - } + return compute_inner_product( (*this) , second ); + } + //end of implementation of functions needed for concepts. + + + + + + + + + + + + + + + + + + + std::vector< std::vector< std::pair > > output_for_visualization() @@ -431,6 +489,8 @@ public: protected: std::vector< std::vector< std::pair > > land; + size_t number_of_functions_for_vectorization; + size_t number_of_functions_for_projections_to_reals; void construct_persistence_landscape_from_barcode( const std::vector< std::pair< double , double > > & p ); Persistence_landscape multiply_lanscape_by_real_number_not_overwrite( double x )const; @@ -1019,6 +1079,16 @@ Persistence_landscape operation_on_pair_of_landscapes ( const Persistence_landsc std::vector< std::vector< std::pair > > land( std::max( land1.land.size() , land2.land.size() ) ); result.land = land; T oper; + + if ( operation_on_pair_of_landscapesDBG ) + { + for ( size_t i = 0 ; i != std::min( land1.land.size() , land2.land.size() ) ; ++i ) + { + std::cerr << "land1.land[" << i << "].size() : " << land1.land[i].size() << std::endl; + std::cerr << "land2.land[" << i << "].size() : " << land2.land[i].size() << std::endl; + } + getchar(); + } for ( size_t i = 0 ; i != std::min( land1.land.size() , land2.land.size() ) ; ++i ) { @@ -1031,8 +1101,13 @@ Persistence_landscape operation_on_pair_of_landscapes ( const Persistence_landsc { std::cerr << "p : " << p << "\n"; std::cerr << "q : " << q << "\n"; + std::cerr << "land1.land.size() : " << land1.land.size() << std::endl; + std::cerr << "land2.land.size() : " << land2.land.size() << std::endl; + std::cerr << "land1.land[" << i << "].size() : " << land1.land[i].size() << std::endl; + std::cerr << "land2.land[" << i << "].size() : " << land2.land[i].size() << std::endl; std::cout << "land1.land[i][p].first : " << land1.land[i][p].first << "\n"; std::cout << "land2.land[i][q].first : " << land2.land[i][q].first << "\n"; + //getchar(); } if ( land1.land[i][p].first < land2.land[i][q].first ) @@ -1070,7 +1145,7 @@ Persistence_landscape operation_on_pair_of_landscapes ( const Persistence_landsc lambda_n.push_back( std::make_pair( land2.land[i][q].first , oper( land1.land[i][p].second , land2.land[i][q].second ) ) ); ++p;++q; } - if (operation_on_pair_of_landscapesDBG){std::cout << "Next iteration \n";getchar();} + if (operation_on_pair_of_landscapesDBG){std::cout << "Next iteration \n";} } while ( (p+1 < land1.land[i].size())&&(q+1 >= land2.land[i].size()) ) { @@ -1125,7 +1200,7 @@ Persistence_landscape operation_on_pair_of_landscapes ( const Persistence_landsc result.land[i].swap(lambda_n); } } - if ( operation_on_pair_of_landscapesDBG ){std::cout << "operation_on_pair_of_landscapes\n";std::cin.ignore();} + if ( operation_on_pair_of_landscapesDBG ){std::cout << "operation_on_pair_of_landscapes END\n";std::cin.ignore();} return result; }//operation_on_pair_of_landscapes diff --git a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape_on_grid.h b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape_on_grid.h index 988c9f16..80c6628d 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape_on_grid.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape_on_grid.h @@ -36,11 +36,7 @@ //gudhi include -#include -#include -#include -#include -#include + #include #include @@ -54,12 +50,9 @@ namespace Gudhi namespace Gudhi_stat { -class Persistence_landscape_on_grid : - public Abs_Vectorized_topological_data , - public Abs_Topological_data_with_distances, - public Abs_Real_valued_topological_data, - public Abs_Topological_data_with_averages, - public Abs_Topological_data_with_scalar_product + +//this class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product +class Persistence_landscape_on_grid { public: /** @@ -700,20 +693,120 @@ public: } return result; } + + + /** + * Computations of L^{p} distance between two landscapes on a grid. p is the parameter of the procedure. + **/ + friend double compute_discance_of_landscapes_on_grid( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second , int p ) + { + bool dbg = false; + //This is what we want to compute: (\int_{- \infty}^{+\infty}| first-second |^p)^(1/p). We will do it one step at a time: + + if ( dbg ) + { + cerr << "first : " << first << endl; + cerr << "second : " << second << endl; + getchar(); + } + + //first-second : + Persistence_landscape_on_grid lan = first-second; + + if ( dbg ) + { + cerr << "Difference : " << lan << endl; + } + + //| first-second |: + lan.abs(); + + if ( dbg ) + { + cerr << "Abs : " << lan << endl; + } + + if ( p != -1 ) + { + //\int_{- \infty}^{+\infty}| first-second |^p + double result; + if ( p != 1 ) + { + if (dbg){cerr << "p : " << p << endl; getchar();} + result = lan.compute_integral_of_landscape( (double)p ); + if (dbg){cerr << "integral : " << result << endl;getchar();} + } + else + { + result = lan.compute_integral_of_landscape(); + if (dbg){cerr << "integral, wihtout power : " << result << endl;getchar();} + } + //(\int_{- \infty}^{+\infty}| first-second |^p)^(1/p) + return pow( result , 1/(double)p ); + } + else + { + //p == -1 + return lan.compute_maximum(); + } + } + + + + + + + + + - //concretization of abstract functions: + + + + + + + + + + + + + + + + + + + + //Functions that are needed for that class to implement the concept. /** * The number of projections to R is defined to the number of nonzero landscape functions. I-th projection is an integral of i-th landscape function over whole R. + * This function is required by the Real_valued_topological_data concept. **/ double project_to_R( int number_of_function ) { return this->compute_integral_of_landscape( (size_t)number_of_function ); } + + /** + * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. + **/ + size_t number_of_projections_to_R() + { + return number_of_functions_for_projections_to_reals; + } + + + + /** + * This function produce a vector of doubles based on a landscape. It is required in a concept Vectorized_topological_data + */ std::vector vectorize( int number_of_function ) { //TODO, think of something smarter over here @@ -726,14 +819,27 @@ public: } /** - * A function to compute averaged persistence landscape on a grid, based on vector of persistence landscapes on grid (projected to Abs_Topological_data_with_averages*, since this is a concretization of a virtual method. + * This function return the number of functions that allows vectorization of persistence laandscape. It is required in a concept Vectorized_topological_data. + **/ + size_t number_of_vectorize_functions() + { + return number_of_functions_for_vectorization; + } + + + + + + /** + * A function to compute averaged persistence landscape on a grid, based on vector of persistence landscapes on grid. + * This function is required by Topological_data_with_averages concept. **/ - void compute_average( const std::vector< Abs_Topological_data_with_averages* >& to_average ) + void compute_average( const std::vector< Persistence_landscape_on_grid* >& to_average ) { bool dbg = false; //After execution of this procedure, the average is supposed to be in the current object. To make sure that this is the case, we need to do some cleaning first. - this->values_of_landscapes.clear(); + this->values_of_landscapes .clear(); this->grid_min = this->grid_max = 0; //if there is nothing to averate, then the average is a zero landscape. @@ -791,87 +897,53 @@ public: }//compute_average - /** - * Computations of L^{p} distance between two landscapes on a grid. p is the parameter of the procedure. - **/ - friend double compute_discance_of_landscapes_on_grid( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second , int p ) - { - bool dbg = false; - //This is what we want to compute: (\int_{- \infty}^{+\infty}| first-second |^p)^(1/p). We will do it one step at a time: - - if ( dbg ) - { - cerr << "first : " << first << endl; - cerr << "second : " << second << endl; - getchar(); - } - - //first-second : - Persistence_landscape_on_grid lan = first-second; - - if ( dbg ) - { - cerr << "Difference : " << lan << endl; - } - - //| first-second |: - lan.abs(); - - if ( dbg ) - { - cerr << "Abs : " << lan << endl; - } - - if ( p != -1 ) - { - //\int_{- \infty}^{+\infty}| first-second |^p - double result; - if ( p != 1 ) - { - if (dbg){cerr << "p : " << p << endl; getchar();} - result = lan.compute_integral_of_landscape( (double)p ); - if (dbg){cerr << "integral : " << result << endl;getchar();} - } - else - { - result = lan.compute_integral_of_landscape(); - if (dbg){cerr << "integral, wihtout power : " << result << endl;getchar();} - } - //(\int_{- \infty}^{+\infty}| first-second |^p)^(1/p) - return pow( result , 1/(double)p ); - } - else - { - //p == -1 - return lan.compute_maximum(); - } - } - /** * A function to compute distance between persistence landscape on a grid. - * The parameter of this functionis a persistence landscapes on grid (projected to Abs_Topological_data_with_averages*, since this is a concretization of a virtual method. + * The parameter of this functionis a Persistence_landscape_on_grid. + * This function is required in Topological_data_with_distances concept. **/ - double distance( const Abs_Topological_data_with_distances* second , double power = 1 ) + double distance( const Persistence_landscape_on_grid& second , double power = 1 ) { if ( power != -1 ) { - return compute_discance_of_landscapes_on_grid( *this , *((Persistence_landscape_on_grid*)second) , power ); + return compute_discance_of_landscapes_on_grid( *this , second , power ); } else { - return compute_max_norm_discance_of_landscapes( *this , *((Persistence_landscape_on_grid*)second) ); + return compute_max_norm_discance_of_landscapes( *this , second ); } } /** * A function to compute scalar product of persistence landscape on a grid. - * The parameter of this functionis a persistence landscapes on grid (projected to Abs_Topological_data_with_averages*, since this is a concretization of a virtual method. + * The parameter of this functionis a Persistence_landscape_on_grid. + * This function is required in Topological_data_with_scalar_product concept. **/ - double compute_scalar_product( const Abs_Topological_data_with_scalar_product* second ) + double compute_scalar_product( const Persistence_landscape_on_grid& second ) { - return compute_inner_product( (*this) , *((Persistence_landscape_on_grid*)second) ); + return compute_inner_product( (*this) , second ); } + //end of implementation of functions needed for concepts. + + + + + + + + + + + + + + + + + + + /** * A function that returns values of landsapes. It can be used for vizualization @@ -891,6 +963,8 @@ protected: double grid_min; double grid_max; std::vector< std::vector< double > > values_of_landscapes; + size_t number_of_functions_for_vectorization; + size_t number_of_functions_for_projections_to_reals; void set_up_numbers_of_functions_for_vectorization_and_projections_to_reals() { diff --git a/src/Gudhi_stat/include/gudhi/concretizations/Vector_distances_in_diagram.h b/src/Gudhi_stat/include/gudhi/concretizations/Vector_distances_in_diagram.h index bb350040..7211f6eb 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/Vector_distances_in_diagram.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/Vector_distances_in_diagram.h @@ -30,12 +30,7 @@ #include #include - -#include -#include -#include -#include -#include +//gudhi include #include #include using namespace std; @@ -67,16 +62,13 @@ struct maximum_distance /** * This is an implementation of idea presented in the paper by Steve, Matthew and Max. The parameter of the class is the class that computes distance used to construct the vectors. The typical function is -* either Eucludean of maximum (Manhattan) distance. +* either Eucludean of maximum (Manhattan) distance. +* This class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product +* **/ template -class Vector_distances_in_diagram : - public Abs_Vectorized_topological_data, - public Abs_Topological_data_with_distances, - public Abs_Real_valued_topological_data, - public Abs_Topological_data_with_averages, - public Abs_Topological_data_with_scalar_product +class Vector_distances_in_diagram { public: /** @@ -168,31 +160,66 @@ public: return !( *this == second ); } - //concretization of abstract methods: + + + + //Implementations of functions for various concepts. /** - * Compute projection to real numbers of persistence vector. + * Compute projection to real numbers of persistence vector. This function is required by the Real_valued_topological_data concept **/ double project_to_R( int number_of_function ); + /** + * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. + **/ + size_t number_of_projections_to_R() + { + return this->number_of_functions_for_projections_to_reals; + } /** - * Compute a vectorization of a persistent vectors. + * Compute a vectorization of a persistent vectors. It is required in a concept Vectorized_topological_data. **/ std::vector vectorize( int number_of_function ); + /** + * This function return the number of functions that allows vectorization of a persisence vector. It is required in a concept Vectorized_topological_data. + **/ + size_t number_of_vectorize_functions() + { + return this->number_of_functions_for_vectorization; + } /** - * Compute a average of two persistent vectors. + * Compute a average of two persistent vectors. This function is required by Topological_data_with_averages concept. **/ - void compute_average( const std::vector< Abs_Topological_data_with_averages* >& to_average ); + void compute_average( const std::vector< Vector_distances_in_diagram* >& to_average ); /** - * Compute a distance of two persistent vectors. + * Compute a distance of two persistent vectors. This function is required in Topological_data_with_distances concept. **/ - double distance( const Abs_Topological_data_with_distances* second , double power = 1); + double distance( const Vector_distances_in_diagram& second , double power = 1); /** - * Compute a scalar product of two persistent vectors. + * Compute a scalar product of two persistent vectors. This function is required in Topological_data_with_scalar_product concept. **/ - double compute_scalar_product( const Abs_Topological_data_with_scalar_product* second ); + double compute_scalar_product( const Vector_distances_in_diagram& second ); + //end of implementation of functions needed for concepts. + + + + + + + + + + + + + + + + + /** * For visualization use output from vectorize and build histograms. @@ -202,6 +229,7 @@ public: return this->sorted_vector_of_distances; } + /** * Create a gnuplot script to vizualize the data structure. **/ @@ -228,6 +256,9 @@ public: private: std::vector< std::pair< double , double > > intervals; std::vector< double > sorted_vector_of_distances; + size_t number_of_functions_for_vectorization; + size_t number_of_functions_for_projections_to_reals; + size_t where_to_cut; void compute_sorted_vector_of_distances_via_heap( size_t where_to_cut ); void compute_sorted_vector_of_distances_via_vector_sorting( size_t where_to_cut ); @@ -247,7 +278,7 @@ private: template -Vector_distances_in_diagram::Vector_distances_in_diagram( const std::vector< std::pair< double,double > >& intervals_ , size_t where_to_cut ):Abs_Vectorized_topological_data(where_to_cut) +Vector_distances_in_diagram::Vector_distances_in_diagram( const std::vector< std::pair< double,double > >& intervals_ , size_t where_to_cut_ ):where_to_cut(where_to_cut_) { std::vector< std::pair< double,double > > i( intervals_ ); this->intervals = i; @@ -279,7 +310,7 @@ Vector_distances_in_diagram& Vector_distances_in_diagram::operator =( cons template -Vector_distances_in_diagram::Vector_distances_in_diagram( const char* filename , size_t where_to_cut ):Abs_Vectorized_topological_data(where_to_cut) +Vector_distances_in_diagram::Vector_distances_in_diagram( const char* filename , size_t where_to_cut ):where_to_cut(where_to_cut) { //standard file with barcode std::vector< std::pair< double , double > > intervals = read_standard_file( filename ); @@ -425,7 +456,7 @@ void Vector_distances_in_diagram::compute_sorted_vector_of_distances_via_vect -//concretization of abstract methods: +//Implementations of functions for various concepts. template double Vector_distances_in_diagram::project_to_R( int number_of_function ) { @@ -441,7 +472,7 @@ double Vector_distances_in_diagram::project_to_R( int number_of_function ) } template -void Vector_distances_in_diagram::compute_average( const std::vector< Abs_Topological_data_with_averages* >& to_average ) +void Vector_distances_in_diagram::compute_average( const std::vector< Vector_distances_in_diagram* >& to_average ) { if ( to_average.size() == 0 ) @@ -452,23 +483,19 @@ void Vector_distances_in_diagram::compute_average( const std::vector< Abs_Top size_t maximal_length_of_vector = 0; for ( size_t i = 0 ; i != to_average.size() ; ++i ) - { - Vector_distances_in_diagram* current = (Vector_distances_in_diagram*)to_average[i]; - if ( current->sorted_vector_of_distances.size() > maximal_length_of_vector ) + { + if ( to_average[i]->sorted_vector_of_distances.size() > maximal_length_of_vector ) { - maximal_length_of_vector = current->sorted_vector_of_distances.size(); + maximal_length_of_vector = to_average[i]->sorted_vector_of_distances.size(); } - } - - //cerr << "maximal_length_of_vector : " << maximal_length_of_vector << endl; + } std::vector< double > av( maximal_length_of_vector , 0 ); for ( size_t i = 0 ; i != to_average.size() ; ++i ) - { - Vector_distances_in_diagram* current = (Vector_distances_in_diagram*)to_average[i]; - for ( size_t j = 0 ; j != current->sorted_vector_of_distances.size() ; ++j ) + { + for ( size_t j = 0 ; j != to_average[i]->sorted_vector_of_distances.size() ; ++j ) { - av[j] += current->sorted_vector_of_distances[j]; + av[j] += to_average[i]->sorted_vector_of_distances[j]; } } @@ -481,7 +508,7 @@ void Vector_distances_in_diagram::compute_average( const std::vector< Abs_Top } template -double Vector_distances_in_diagram::distance( const Abs_Topological_data_with_distances* second , double power ) +double Vector_distances_in_diagram::distance( const Vector_distances_in_diagram& second_ , double power ) { bool dbg = false; @@ -490,47 +517,45 @@ double Vector_distances_in_diagram::distance( const Abs_Topological_data_with std::cerr << "Entering double Vector_distances_in_diagram::distance( const Abs_Topological_data_with_distances* second , double power ) procedure \n"; std::cerr << "Power : " << power << std::endl; std::cerr << "This : " << *this << std::endl; - std::cerr << "second : " << *((Vector_distances_in_diagram*)second) << std::endl; - } - - Vector_distances_in_diagram* second_ = ((Vector_distances_in_diagram*)second); + std::cerr << "second : " << second_ << std::endl; + } double result = 0; - for ( size_t i = 0 ; i != std::min(this->sorted_vector_of_distances.size(), second_->sorted_vector_of_distances.size()) ; ++i ) + for ( size_t i = 0 ; i != std::min(this->sorted_vector_of_distances.size(), second_.sorted_vector_of_distances.size()) ; ++i ) { if ( power == 1 ) { if ( dbg ) { - cerr << "|" << this->sorted_vector_of_distances[i] << " - " << second_->sorted_vector_of_distances[i] << " | : " << fabs( this->sorted_vector_of_distances[i] - second_->sorted_vector_of_distances[i] ) << endl; + cerr << "|" << this->sorted_vector_of_distances[i] << " - " << second_.sorted_vector_of_distances[i] << " | : " << fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) << endl; } - result += fabs( this->sorted_vector_of_distances[i] - second_->sorted_vector_of_distances[i] ); + result += fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ); } else { - result += std::pow( fabs( this->sorted_vector_of_distances[i] - second_->sorted_vector_of_distances[i] ) , power ); + result += std::pow( fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) , power ); if ( dbg ) { - cerr << "| " << this->sorted_vector_of_distances[i] << " - " << second_->sorted_vector_of_distances[i] << " : " << fabs( this->sorted_vector_of_distances[i] - second_->sorted_vector_of_distances[i] ) << endl; + cerr << "| " << this->sorted_vector_of_distances[i] << " - " << second_.sorted_vector_of_distances[i] << " : " << fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) << endl; } } } - if ( this->sorted_vector_of_distances.size() != second_->sorted_vector_of_distances.size() ) + if ( this->sorted_vector_of_distances.size() != second_.sorted_vector_of_distances.size() ) { - if ( this->sorted_vector_of_distances.size() > second_->sorted_vector_of_distances.size() ) + if ( this->sorted_vector_of_distances.size() > second_.sorted_vector_of_distances.size() ) { - for ( size_t i = second_->sorted_vector_of_distances.size() ; i != this->sorted_vector_of_distances.size() ; ++i ) + for ( size_t i = second_.sorted_vector_of_distances.size() ; i != this->sorted_vector_of_distances.size() ; ++i ) { result += fabs( this->sorted_vector_of_distances[i] ); } } else { - //this->sorted_vector_of_distances.size() < second_->sorted_vector_of_distances.size() - for ( size_t i = this->sorted_vector_of_distances.size() ; i != second_->sorted_vector_of_distances.size() ; ++i ) + //this->sorted_vector_of_distances.size() < second_.sorted_vector_of_distances.size() + for ( size_t i = this->sorted_vector_of_distances.size() ; i != second_.sorted_vector_of_distances.size() ; ++i ) { - result += fabs( second_->sorted_vector_of_distances[i] ); + result += fabs( second_.sorted_vector_of_distances[i] ); } } } @@ -595,14 +620,12 @@ void Vector_distances_in_diagram::load_from_file( const char* filename ) } template < typename F> -double Vector_distances_in_diagram::compute_scalar_product( const Abs_Topological_data_with_scalar_product* second ) +double Vector_distances_in_diagram::compute_scalar_product( const Vector_distances_in_diagram& second_vector ) { - Vector_distances_in_diagram* second_vector = (Vector_distances_in_diagram*)second; - double result = 0; - for ( size_t i = 0 ; i != std::min(this->sorted_vector_of_distances.size(),second_vector->sorted_vector_of_distances.size()) ; ++i ) + for ( size_t i = 0 ; i != std::min(this->sorted_vector_of_distances.size(),second_vector.sorted_vector_of_distances.size()) ; ++i ) { - result += this->sorted_vector_of_distances[i] * second_vector->sorted_vector_of_distances[i]; + result += this->sorted_vector_of_distances[i] * second_vector.sorted_vector_of_distances[i]; } return result; } diff --git a/src/Gudhi_stat/include/gudhi/concretizations/read_persitence_from_file.h b/src/Gudhi_stat/include/gudhi/concretizations/read_persitence_from_file.h index 519c44fa..0a740996 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/read_persitence_from_file.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/read_persitence_from_file.h @@ -47,7 +47,7 @@ std::vector< std::pair< double,double > > read_file_names_that_may_contain_inf_s if ( !( access( filename, F_OK ) != -1 ) ) { - cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; throw "The file from which you are trying to read do not exist. The program will now terminate \n"; } @@ -111,7 +111,7 @@ std::vector< std::string > readFileNames( char* filenameWithFilenames ) if ( !( access( filenameWithFilenames, F_OK ) != -1 ) ) { - cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + std::cerr << "The file : " << filenameWithFilenames << " do not exist. The program will now terminate \n"; throw "The file from which you are trying to read do not exist. The program will now terminate \n"; } @@ -174,6 +174,7 @@ std::vector< std::pair< double , double > > read_standard_file( const char* file double beginn, endd; lineSS >> beginn; lineSS >> endd; + if ( beginn == endd )continue; if ( beginn > endd ) { double b = beginn; diff --git a/src/Gudhi_stat/include/gudhi/permutation_test.h b/src/Gudhi_stat/include/gudhi/permutation_test.h new file mode 100644 index 00000000..18b94eab --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/permutation_test.h @@ -0,0 +1,80 @@ +/* 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 (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 PERMUTATION_TEST_H +#define PERMUTATION_TEST_H + + +//concretizations +#include +#include +#include +#include +#include + +using namespace std; + +namespace Gudhi +{ +namespace Gudhi_stat +{ + +template +double permutation_test( const std::vector& data_1 , const std::vector& data_2 , size_t number_of_permutations , double exponent = 1 ) +{ + try + { + Representation_of_persistence* av_1 = new Representation_of_persistence; + av_1->compute_average( data_1 ); + Representation_of_persistence* av_2 = new Representation_of_persistence; + av_2->compute_average( data_2 ); + double initial_distance = av_1->distance( *av_2 , exponent ); + double counter = 0; + + for ( size_t i = 0 ; i != number_of_permutations ; ++i ) + { + std::vector all_data; + all_data.insert(all_data.end() , data_1.begin() , data_1.end() ); + all_data.insert(all_data.end() , data_2.begin() , data_2.end() ); + std::random_shuffle( all_data.begin() , all_data.end() ); + + std::vector first_part(&all_data[0],&all_data[data_1.size()]); + std::vector second_part(&all_data[data_1.size()],&all_data[all_data.size()]); + + av_1->compute_average( first_part ); + av_2->compute_average( second_part ); + double distance_after_permutations = av_1->distance( *av_2 , exponent ); + if ( distance_after_permutations > initial_distance )++counter; + } + return counter / (double)number_of_permutations; + } + catch (...) + { + std::cout << "The data structure do not support the operations that are neccessay for a permutation test (averaging, distances) \n"; + } + return 0; +}//permutation_test + +}//Gudhi_stat +}//Gudhi + +#endif diff --git a/src/Gudhi_stat/include/gudhi/topological_process.h b/src/Gudhi_stat/include/gudhi/topological_process.h new file mode 100644 index 00000000..d8d8e696 --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/topological_process.h @@ -0,0 +1,101 @@ +/* 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 (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 PERMUTATION_TEST_H +#define PERMUTATION_TEST_H +//abstract classes: +#include +#include +#include + + +//concretizations +#include +#include +#include +#include + +//extras +#include + +namespace Gudhi +{ +namespace Gudhi_stat +{ + +template +class Topological_process +{ +public: + Topological_process(); + Topological_process( const std::vetor< Representation* >& data_ ):data(data_){} + Topological_process( const char* filename );//we assume that the filename contains a list of files with the diagrams. + double distance( const Topological_process& second ) + { + if ( this->data.size() != second.data.size() ) + { + throw "Incompatible lengths of topological processes, we cannot compute the distance in this case \n"; + } + double result = 0; + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + result += this->data[i].distance( secod.data[i] ); + } + return result; + } + + compute_average( const std::vector< Representation* >& to_average ) + { + //since we will substitute whatever data we have in this object with an average, we clear the data in this object first: + this->data.clear(); + //then we need to check if all the topological processes in the vector to_average have the same length. + if ( to_average.size() == 0 )return; + for ( size_t i = 1 ; i != to_average.size() ; ++i ) + { + if ( to_average[0].data.size() != to_average[i].data.size ) + { + throw "Incompatible lengths of topological processes, the averages cannot be computed \n"; + } + } + } + //scalar products? + //confidence bounds? +private: + std::vetor< Representation* > data; +}; + +template +Topological_process::Topological_process( const char* filename ) +{ + std::vector< std::string > filenames = readFileNames( filename ); + this->data.reserve( filenames.size() ); + for ( size_t file = 0 ; file != filenames.size() ; ++file ) + { + std::vector< std::pair > intervals_in_this_file = read_file_names_that_may_contain_inf_string( filenames[i] ); + this-data[i] = new Representation( intervals_in_this_file ); + } +} + +}//Gudhi_stat +}//Gudhi + +#endif diff --git a/src/Gudhi_stat/test/persistence_heat_maps_test.cpp b/src/Gudhi_stat/test/persistence_heat_maps_test.cpp index c4c97d72..d9cba466 100644 --- a/src/Gudhi_stat/test/persistence_heat_maps_test.cpp +++ b/src/Gudhi_stat/test/persistence_heat_maps_test.cpp @@ -61,10 +61,10 @@ BOOST_AUTO_TEST_CASE(check_averages_of_heat_maps) Persistence_heat_maps q( "data/file_with_diagram_1" , filter , constant_function, false , 1000 , 0 , 10 ); Persistence_heat_maps r( "data/file_with_diagram_2" , filter , constant_function, false , 1000 , 0 , 10 ); - std::vector< Abs_Topological_data_with_averages* > to_average; - to_average.push_back( (Abs_Topological_data_with_averages*)(&p) ); - to_average.push_back( (Abs_Topological_data_with_averages*)(&q) ); - to_average.push_back( (Abs_Topological_data_with_averages*)(&r) ); + std::vector< Persistence_heat_maps* > to_average; + to_average.push_back( &p ); + to_average.push_back( &q ); + to_average.push_back( &r ); Persistence_heat_maps av; av.compute_average( to_average ); @@ -164,28 +164,28 @@ BOOST_AUTO_TEST_CASE(check_distance_for_heat_maps) Persistence_heat_maps q( "data/file_with_diagram_1" , filter , constant_function, false , 1000 , 0 , 1 ); Persistence_heat_maps r( "data/file_with_diagram_2" , filter , constant_function, false , 1000 , 0 , 1 ); - //cerr << p.distance( (Abs_Topological_data_with_distances*)&p ) << endl; - //cerr << p.distance( (Abs_Topological_data_with_distances*)&q ) << endl; - //cerr << p.distance( (Abs_Topological_data_with_distances*)&r ) << endl; - //cerr << q.distance( (Abs_Topological_data_with_distances*)&p ) << endl; - //cerr << q.distance( (Abs_Topological_data_with_distances*)&q ) << endl; - //cerr << q.distance( (Abs_Topological_data_with_distances*)&r ) << endl; - //cerr << r.distance( (Abs_Topological_data_with_distances*)&p ) << endl; - //cerr << r.distance( (Abs_Topological_data_with_distances*)&q ) << endl; - //cerr << r.distance( (Abs_Topological_data_with_distances*)&r ) << endl; + //cerr << p.distance( p ) << endl; + //cerr << p.distance( q ) << endl; + //cerr << p.distance( r ) << endl; + //cerr << q.distance( p ) << endl; + //cerr << q.distance( q ) << endl; + //cerr << q.distance( r ) << endl; + //cerr << r.distance( p ) << endl; + //cerr << r.distance( q ) << endl; + //cerr << r.distance( r ) << endl; //0 624.183 415.815 //624.183 0 528.06Z //415.815 528.066 0 - BOOST_CHECK( fabs( p.distance( (Abs_Topological_data_with_distances*)&p ) - 0) < 0.0005); - BOOST_CHECK( fabs( p.distance( (Abs_Topological_data_with_distances*)&q ) - 624.183)< 0.0005); - BOOST_CHECK( fabs( p.distance( (Abs_Topological_data_with_distances*)&r ) - 415.815)< 0.0005); - BOOST_CHECK( fabs( q.distance( (Abs_Topological_data_with_distances*)&p ) - 624.183)< 0.0005); - BOOST_CHECK( fabs( q.distance( (Abs_Topological_data_with_distances*)&q ) - 0)< 0.0005); - BOOST_CHECK( fabs( q.distance( (Abs_Topological_data_with_distances*)&r ) - 528.066)< 0.0005); - BOOST_CHECK( fabs( r.distance( (Abs_Topological_data_with_distances*)&p ) - 415.815)< 0.0005); - BOOST_CHECK( fabs( r.distance( (Abs_Topological_data_with_distances*)&q ) - 528.066)< 0.0005); - BOOST_CHECK( fabs( r.distance( (Abs_Topological_data_with_distances*)&r ) - 0)< 0.0005); + BOOST_CHECK( fabs( p.distance( p ) - 0) < 0.0005); + BOOST_CHECK( fabs( p.distance( q ) - 624.183)< 0.0005); + BOOST_CHECK( fabs( p.distance( r ) - 415.815)< 0.0005); + BOOST_CHECK( fabs( q.distance( p ) - 624.183)< 0.0005); + BOOST_CHECK( fabs( q.distance( q ) - 0)< 0.0005); + BOOST_CHECK( fabs( q.distance( r ) - 528.066)< 0.0005); + BOOST_CHECK( fabs( r.distance( p ) - 415.815)< 0.0005); + BOOST_CHECK( fabs( r.distance( q ) - 528.066)< 0.0005); + BOOST_CHECK( fabs( r.distance( r ) - 0)< 0.0005); } @@ -214,25 +214,25 @@ BOOST_AUTO_TEST_CASE(check_scalar_products_for_heat_maps) Persistence_heat_maps q( "data/file_with_diagram_1" , filter , constant_function, false , 1000 , 0 , 1 ); Persistence_heat_maps r( "data/file_with_diagram_2" , filter , constant_function, false , 1000 , 0 , 1 ); - //cerr << p.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&p ) << endl; - //cerr << p.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&q ) << endl; - //cerr << p.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&r ) << endl; - //cerr << q.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&p ) << endl; - //cerr << q.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&q ) << endl; - //cerr << q.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&r ) << endl; - //cerr << r.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&p ) << endl; - //cerr << r.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&q ) << endl; - //cerr << r.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&r ) << endl; - - - BOOST_CHECK( fabs( p.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&p ) - 0.0345687 )< 0.0005); - BOOST_CHECK( fabs( p.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&q ) - 0.0509357 )< 0.0005); - BOOST_CHECK( fabs( p.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&r ) - 0.0375608 )< 0.0005); - BOOST_CHECK( fabs( q.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&p ) - 0.0509357 )< 0.0005); - BOOST_CHECK( fabs( q.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&q ) - 1.31293 )< 0.0005); - BOOST_CHECK( fabs( q.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&r ) - 0.536799)< 0.0005); - BOOST_CHECK( fabs( r.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&p ) - 0.0375608)< 0.0005); - BOOST_CHECK( fabs( r.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&q ) - 0.536799)< 0.0005); - BOOST_CHECK( fabs( r.compute_scalar_product( (Abs_Topological_data_with_scalar_product*)&r ) - 0.672907)< 0.0005); + //cerr << p.compute_scalar_product( p ) << endl; + //cerr << p.compute_scalar_product( q ) << endl; + //cerr << p.compute_scalar_product( r ) << endl; + //cerr << q.compute_scalar_product( p ) << endl; + //cerr << q.compute_scalar_product( q ) << endl; + //cerr << q.compute_scalar_product( r ) << endl; + //cerr << r.compute_scalar_product( p ) << endl; + //cerr << r.compute_scalar_product( q ) << endl; + //cerr << r.compute_scalar_product( r ) << endl; + + + BOOST_CHECK( fabs( p.compute_scalar_product( p ) - 0.0345687 )< 0.0005); + BOOST_CHECK( fabs( p.compute_scalar_product( q ) - 0.0509357 )< 0.0005); + BOOST_CHECK( fabs( p.compute_scalar_product( r ) - 0.0375608 )< 0.0005); + BOOST_CHECK( fabs( q.compute_scalar_product( p ) - 0.0509357 )< 0.0005); + BOOST_CHECK( fabs( q.compute_scalar_product( q ) - 1.31293 )< 0.0005); + BOOST_CHECK( fabs( q.compute_scalar_product( r ) - 0.536799)< 0.0005); + BOOST_CHECK( fabs( r.compute_scalar_product( p ) - 0.0375608)< 0.0005); + BOOST_CHECK( fabs( r.compute_scalar_product( q ) - 0.536799)< 0.0005); + BOOST_CHECK( fabs( r.compute_scalar_product( r ) - 0.672907)< 0.0005); } diff --git a/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp b/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp index d7d72d6b..17ed9fde 100644 --- a/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp +++ b/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp @@ -219,7 +219,7 @@ BOOST_AUTO_TEST_CASE(check_computations_of_averages) { Persistence_landscape_on_grid p( "data/file_with_diagram", 0,1,100 ); Persistence_landscape_on_grid q( "data/file_with_diagram_1", 0,1,100 ); - std::vector< Abs_Topological_data_with_averages* > to_average; + std::vector< Persistence_landscape_on_grid* > to_average; to_average.push_back( &p ); to_average.push_back( &q ); Persistence_landscape_on_grid av; @@ -237,9 +237,9 @@ BOOST_AUTO_TEST_CASE(check_computations_of_distances) { Persistence_landscape_on_grid p( "data/file_with_diagram", 0,1,10000 ); Persistence_landscape_on_grid q( "data/file_with_diagram_1", 0,1,10000 ); - BOOST_CHECK( fabs( p.distance( &q )- 25.5779) <= 0.00005 ); - BOOST_CHECK( fabs( p.distance( &q , 2) - 2.04891) <= 0.00001 ); - BOOST_CHECK( fabs( p.distance( &q , -1 )-0.359 ) <= 0.00001 ); + BOOST_CHECK( fabs( p.distance( q )- 25.5779) <= 0.00005 ); + BOOST_CHECK( fabs( p.distance( q , 2) - 2.04891) <= 0.00001 ); + BOOST_CHECK( fabs( p.distance( q , -1 )-0.359 ) <= 0.00001 ); } @@ -247,8 +247,8 @@ BOOST_AUTO_TEST_CASE(check_computations_of_scalar_product) { Persistence_landscape_on_grid p( "data/file_with_diagram" , 0,1,10000); Persistence_landscape_on_grid q( "data/file_with_diagram_1", 0,1,10000 ); - //std::cerr << p.compute_scalar_product( &q ) << std::endl; - BOOST_CHECK( almost_equal( p.compute_scalar_product( &q ) , p.compute_scalar_product( &q ) ) ); + //std::cerr << p.compute_scalar_product( q ) << std::endl; + BOOST_CHECK( almost_equal( p.compute_scalar_product( q ) , 0.754367 ) ); } diff --git a/src/Gudhi_stat/test/persistence_lanscapes_test.cpp b/src/Gudhi_stat/test/persistence_lanscapes_test.cpp index 9506410a..9ec7f880 100644 --- a/src/Gudhi_stat/test/persistence_lanscapes_test.cpp +++ b/src/Gudhi_stat/test/persistence_lanscapes_test.cpp @@ -191,7 +191,7 @@ BOOST_AUTO_TEST_CASE(check_computations_of_averages) { Persistence_landscape p( "data/file_with_diagram" ); Persistence_landscape q( "data/file_with_diagram_1" ); - std::vector< Abs_Topological_data_with_averages* > to_average; + std::vector< Persistence_landscape* > to_average; to_average.push_back( &p ); to_average.push_back( &q ); Persistence_landscape av; @@ -209,9 +209,9 @@ BOOST_AUTO_TEST_CASE(check_computations_of_distances) { Persistence_landscape p( "data/file_with_diagram" ); Persistence_landscape q( "data/file_with_diagram_1" ); - BOOST_CHECK( fabs( p.distance( &q )- 25.5824) <= 0.00005 ); - BOOST_CHECK( fabs( p.distance( &q , 2) - 2.12636 ) <= 0.00001 ); - BOOST_CHECK( fabs( p.distance( &q , -1 )-0.359068 ) <= 0.00001 ); + BOOST_CHECK( fabs( p.distance( q )- 25.5824) <= 0.00005 ); + BOOST_CHECK( fabs( p.distance( q , 2) - 2.12636 ) <= 0.00001 ); + BOOST_CHECK( fabs( p.distance( q , -1 )-0.359068 ) <= 0.00001 ); } @@ -219,6 +219,6 @@ BOOST_AUTO_TEST_CASE(check_computations_of_scalar_product) { Persistence_landscape p( "data/file_with_diagram" ); Persistence_landscape q( "data/file_with_diagram_1" ); - BOOST_CHECK( fabs( p.compute_scalar_product( &q ) - 0.754498 ) <= 0.00001 ); + BOOST_CHECK( fabs( p.compute_scalar_product( q ) - 0.754498 ) <= 0.00001 ); } diff --git a/src/Gudhi_stat/test/vector_representation_test.cpp b/src/Gudhi_stat/test/vector_representation_test.cpp index 44801ad9..3e14bd59 100644 --- a/src/Gudhi_stat/test/vector_representation_test.cpp +++ b/src/Gudhi_stat/test/vector_representation_test.cpp @@ -315,7 +315,7 @@ BOOST_AUTO_TEST_CASE(check_distance_computations) intervals[9] = std::pair( 19,20 ); Vector_distances_in_diagram< euclidean_distance > p_bis( intervals , 10 ); //cerr << "p_prime.distance( (Abs_Topological_data_with_distances*)(&p_bis) , 1 ) : " << p_prime.distance( (Abs_Topological_data_with_distances*)(&p_bis) , 1 ) << endl; - BOOST_CHECK( almost_equal ( p_prime.distance( (Abs_Topological_data_with_distances*)(&p_bis) , 1 ) , 1.86428 ) ); + BOOST_CHECK( almost_equal ( p_prime.distance( p_bis , 1 ) , 1.86428 ) ); } @@ -337,9 +337,9 @@ BOOST_AUTO_TEST_CASE(check_compute_average) Vector_distances_in_diagram< euclidean_distance > A( i1 , -1 ); Vector_distances_in_diagram< euclidean_distance > B( i1 , -1 ); - std::vector< Abs_Topological_data_with_averages* > to_average; - to_average.push_back( (Abs_Topological_data_with_averages*)(&A) ); - to_average.push_back( (Abs_Topological_data_with_averages*)(&B) ); + std::vector< Vector_distances_in_diagram< euclidean_distance >* > to_average; + to_average.push_back( &A ); + to_average.push_back( &B ); Vector_distances_in_diagram< euclidean_distance > average; average.compute_average( to_average ); diff --git a/src/Gudhi_stat/utilities/CMakeLists.txt b/src/Gudhi_stat/utilities/CMakeLists.txt index 4fc11b57..e97c5708 100644 --- a/src/Gudhi_stat/utilities/CMakeLists.txt +++ b/src/Gudhi_stat/utilities/CMakeLists.txt @@ -101,6 +101,6 @@ target_link_libraries(persistence_vectors/plot_persistence_vectors ${Boost_SYSTE #some stat libraries: -#add_executable ( permutation_test permutation_test.cpp ) -#target_link_libraries(permutation_test ${Boost_SYSTEM_LIBRARY}) +add_executable ( permutation_test permutation_test.cpp ) +target_link_libraries(permutation_test ${Boost_SYSTEM_LIBRARY}) diff --git a/src/Gudhi_stat/utilities/permutation_test.cpp b/src/Gudhi_stat/utilities/permutation_test.cpp new file mode 100644 index 00000000..809802d7 --- /dev/null +++ b/src/Gudhi_stat/utilities/permutation_test.cpp @@ -0,0 +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 (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 std; +using namespace Gudhi; +using namespace Gudhi::Gudhi_stat; + +int main( int argc , char** argv ) +{ + + std::cout << "This program require the following parameters: \n"; + std::cout << "(1-2) Names of files each of them contains the names of files with persistence diagrams. The diagrams from a single file are assumed to be in the same group \n"; + std::cout << "Third parameter is an integer being the number of permutations to be made \n"; + std::cout << "The last parameter is a double, the power of a distance \n"; + if ( argc != 5 ) + { + std::cout << "Wrong number of parameters, the program will now terminat \n"; + return 1; + } + std::cout << "We will now read the data from files : " << argv[1] << " and " << argv[2] << std::endl; + size_t number_of_permutations = (size_t)(atoi(argv[3])); + size_t exponent = (double)atof( argv[4] ); + + std::vector< std::string > first_group = readFileNames( argv[1] ); + std::vector< std::string > second_group =readFileNames( argv[2] ); + + std::cout << "Here are the filenames in the first group :\n"; + for ( size_t i = 0 ; i != first_group.size() ; ++i ) + { + std::cout << first_group[i] << std::endl; + } + std::cout << "Here are the filenames in the second group :\n"; + for ( size_t i = 0 ; i != second_group.size() ; ++i ) + { + std::cout << second_group[i] << std::endl; + } + + std::vector< Persistence_landscape* > first_collection( first_group.size() ); + for ( size_t i = 0 ; i != first_group.size() ; ++i ) + { + std::vector< std::pair< double , double > > diag = read_standard_file( first_group[i].c_str() ); + Persistence_landscape* l = new Persistence_landscape( diag ); + first_collection[i] = l; + } + + std::vector< Persistence_landscape* > second_collection( second_group.size() ); + for ( size_t i = 0 ; i != second_group.size() ; ++i ) + { + std::vector< std::pair< double , double > > diag = read_standard_file( second_group[i].c_str() ); + Persistence_landscape* l = new Persistence_landscape( diag ); + second_collection[i] = l; + } + + std::cout << "The p-value form a permutation test is : " << permutation_test( first_collection , second_collection , number_of_permutations , exponent ) << std::endl; + + + + return 0; +} diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp index 811e4557..a3094e07 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp @@ -22,7 +22,6 @@ -#include #include @@ -50,12 +49,12 @@ int main( int argc , char** argv ) } std::cout << "Creating persistence landscapes...\n"; - std::vector< Abs_Topological_data_with_averages* > maps; + std::vector< Persistence_heat_maps* > maps; for ( size_t i = 0 ; i != filenames.size() ; ++i ) { Persistence_heat_maps* l = new Persistence_heat_maps; l->load_from_file( filenames[i] ); - maps.push_back( (Abs_Topological_data_with_averages*)l ); + maps.push_back( l ); } Persistence_heat_maps av; diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp index e462f009..bfe2a7ab 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp @@ -21,8 +21,6 @@ */ - -#include #include @@ -53,13 +51,13 @@ int main( int argc , char** argv ) { filenames.push_back( argv[i] ); } - std::vector< Abs_Topological_data_with_distances* > maps; + std::vector< Persistence_heat_maps > maps; maps.reserve( filenames.size() ); for ( size_t file_no = 0 ; file_no != filenames.size() ; ++file_no ) { - Persistence_heat_maps* l = new Persistence_heat_maps; - l->load_from_file( filenames[file_no] ); - maps.push_back( (Abs_Topological_data_with_distances*)l ); + Persistence_heat_maps l; + l.load_from_file( filenames[file_no] ); + maps.push_back( l ); } //and now we will compute the scalar product of landscapes. @@ -77,7 +75,7 @@ int main( int argc , char** argv ) { for ( size_t j = i ; j != filenames.size() ; ++j ) { - distance[i][j] = distance[j][i] = ((Persistence_heat_maps*)maps[i])->distance( maps[j] , p ) ; + distance[i][j] = distance[j][i] = maps[i].distance( maps[j] , p ) ; } } diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp index c9ffa22e..d6899d1e 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp @@ -21,8 +21,6 @@ */ - -#include #include @@ -44,12 +42,12 @@ int main( int argc , char** argv ) { filenames.push_back( argv[i] ); } - std::vector< Persistence_heat_maps* > maps; + std::vector< Persistence_heat_maps > maps; maps.reserve( filenames.size() ); for ( size_t file_no = 0 ; file_no != filenames.size() ; ++file_no ) { - Persistence_heat_maps* l = new Persistence_heat_maps; - l->load_from_file( filenames[file_no] ); + Persistence_heat_maps l; + l.load_from_file( filenames[file_no] ); maps.push_back( l ); } @@ -68,7 +66,7 @@ int main( int argc , char** argv ) { for ( size_t j = i ; j != maps.size() ; ++j ) { - scalar_product[i][j] = scalar_product[j][i] = ((Persistence_heat_maps*)maps[i])->compute_scalar_product( maps[j] ) ; + scalar_product[i][j] = scalar_product[j][i] = maps[i].compute_scalar_product( maps[j] ) ; } } diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp index 2cc00b87..b300d350 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp @@ -22,7 +22,6 @@ -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp index ae579329..3ce0fcec 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp @@ -22,7 +22,6 @@ -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp index 7877d699..4738d946 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp @@ -21,8 +21,6 @@ */ - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp index 67972afe..8dab998a 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp @@ -21,8 +21,6 @@ */ - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp index 1fc9d263..ec35f81c 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp index 6b67ea57..c4eed502 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp @@ -21,8 +21,6 @@ */ - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp b/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp index 2c55a806..d73165b7 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp @@ -23,7 +23,6 @@ #include -#include #include #include diff --git a/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp b/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp index b29aea3a..d4949932 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp @@ -23,7 +23,6 @@ #include -#include #include #include diff --git a/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp b/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp index 99f7e640..96e6fa47 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp @@ -23,7 +23,6 @@ #include -#include #include #include diff --git a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numebrs.cpp b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numebrs.cpp index e23a4f20..e4efdf79 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numebrs.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numebrs.cpp @@ -23,7 +23,6 @@ #include -#include #include #include diff --git a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp index 5950240e..6830a58b 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp @@ -23,7 +23,6 @@ #include -#include #include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp index 895146f5..35aec203 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp @@ -22,7 +22,6 @@ -#include #include @@ -51,12 +50,12 @@ int main( int argc , char** argv ) } std::cout << "Creating persistence landscapes...\n"; - std::vector< Abs_Topological_data_with_averages* > lands; + std::vector< Persistence_landscape* > lands; for ( size_t i = 0 ; i != filenames.size() ; ++i ) { Persistence_landscape* l = new Persistence_landscape; l->load_landscape_from_file( filenames[i] ); - lands.push_back( (Abs_Topological_data_with_averages*)l ); + lands.push_back( l ); } Persistence_landscape av; diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp index 34ec0bfa..e3c3a33e 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp index 443240ff..ef9de9c7 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp index fe96a067..212e6b16 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp index e035e4aa..0d72a17c 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp index 3b580181..2f6875b2 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include @@ -50,12 +47,12 @@ int main( int argc , char** argv ) } std::cout << "Creating persistence landscapes...\n"; - std::vector< Abs_Topological_data_with_averages* > lands; + std::vector< Persistence_landscape_on_grid* > lands; for ( size_t i = 0 ; i != filenames.size() ; ++i ) { Persistence_landscape_on_grid* l = new Persistence_landscape_on_grid; l->load_landscape_from_file( filenames[i] ); - lands.push_back( (Abs_Topological_data_with_averages*)l ); + lands.push_back( l ); } Persistence_landscape_on_grid av; diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp index 1813e297..ace5066a 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp index 33e111d5..a039a97a 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp @@ -21,8 +21,6 @@ */ - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp index f6545e44..2b205513 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp index c12c3862..27946075 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp index 3262b157..cb3ea03d 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp @@ -21,8 +21,6 @@ */ - -#include #include @@ -51,12 +49,12 @@ int main( int argc , char** argv ) } std::cout << "Reading persistence vectors...\n"; - std::vector< Abs_Topological_data_with_averages* > lands; + std::vector< Vector_distances_in_diagram< euclidean_distance >* > lands; for ( size_t i = 0 ; i != filenames.size() ; ++i ) { Vector_distances_in_diagram< euclidean_distance >* l = new Vector_distances_in_diagram< euclidean_distance >; l->load_from_file( filenames[i] ); - lands.push_back( (Abs_Topological_data_with_averages*)l ); + lands.push_back(l ); } Vector_distances_in_diagram< euclidean_distance > av; diff --git a/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp index 33d92a72..5f8c6b52 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include @@ -53,13 +50,13 @@ int main( int argc , char** argv ) { filenames.push_back( argv[i] ); } - std::vector< Vector_distances_in_diagram< euclidean_distance >* > vectors; + std::vector< Vector_distances_in_diagram< euclidean_distance > > vectors; vectors.reserve( filenames.size() ); for ( size_t file_no = 0 ; file_no != filenames.size() ; ++file_no ) { //cerr << filenames[file_no] << endl; - Vector_distances_in_diagram< euclidean_distance >* l = new Vector_distances_in_diagram< euclidean_distance >; - l->load_from_file( filenames[file_no] ); + Vector_distances_in_diagram< euclidean_distance > l; + l.load_from_file( filenames[file_no] ); vectors.push_back( l ); } @@ -78,7 +75,7 @@ int main( int argc , char** argv ) { for ( size_t j = i+1 ; j != vectors.size() ; ++j ) { - distance[i][j] = distance[j][i] = ((Vector_distances_in_diagram< euclidean_distance >*)vectors[i])->distance( vectors[j] , p ) ; + distance[i][j] = distance[j][i] = vectors[i].distance( vectors[j] , p ) ; } } diff --git a/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp index 5bea2765..a02cd078 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include @@ -44,12 +41,12 @@ int main( int argc , char** argv ) { filenames.push_back( argv[i] ); } - std::vector< Vector_distances_in_diagram< euclidean_distance >* > vectors; + std::vector< Vector_distances_in_diagram< euclidean_distance > > vectors; vectors.reserve( filenames.size() ); for ( size_t file_no = 0 ; file_no != filenames.size() ; ++file_no ) { - Vector_distances_in_diagram< euclidean_distance >* l = new Vector_distances_in_diagram< euclidean_distance >; - l->load_from_file( filenames[file_no] ); + Vector_distances_in_diagram< euclidean_distance > l; + l.load_from_file( filenames[file_no] ); vectors.push_back( l ); } @@ -68,7 +65,7 @@ int main( int argc , char** argv ) { for ( size_t j = i ; j != vectors.size() ; ++j ) { - scalar_product[i][j] = scalar_product[j][i] = ((Vector_distances_in_diagram< euclidean_distance >*)vectors[i])->compute_scalar_product( vectors[j] ) ; + scalar_product[i][j] = scalar_product[j][i] = vectors[i].compute_scalar_product( vectors[j] ) ; } } @@ -85,13 +82,6 @@ int main( int argc , char** argv ) cout << endl; out << endl; } - out.close(); - - //cleaning up - for ( size_t i = 0 ; i != vectors.size() ; ++i ) - { - delete vectors[i]; - } - + out.close(); return 0; } diff --git a/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp index 657dd2d4..9f6b79cb 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp index 53f53654..de19a66d 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp @@ -20,9 +20,6 @@ * along with this program. If not, see . */ - - -#include #include -- cgit v1.2.3 From b7b23c26b855b83d03870cfd90b001fa2dedfd86 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 9 Dec 2016 14:55:03 +0000 Subject: Fix to Marc's comments. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/gudhi_stat@1841 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c5be190621dcbb43433c027c78e782916cc6ae93 --- src/Gudhi_stat/example/persistence_intervals.cpp | 40 +-- src/Gudhi_stat/example/persistence_landscape.cpp | 18 +- .../example/persistence_landscape_on_grid.cpp | 20 +- src/Gudhi_stat/example/vector_representation.cpp | 13 +- src/Gudhi_stat/include/gudhi/Hausdorff_distances.h | 7 + src/Gudhi_stat/include/gudhi/bootstrap.h | 15 +- src/Gudhi_stat/include/gudhi/common.h | 6 +- src/Gudhi_stat/include/gudhi/common_gudhi_stat.h | 160 +++++++++++ .../include/gudhi/concretizations/PSSK.h | 18 +- .../gudhi/concretizations/Persistence_heat_maps.h | 98 ++++--- .../gudhi/concretizations/Persistence_intervals.h | 8 +- .../gudhi/concretizations/Persistence_landscape.h | 127 ++++----- .../Persistence_landscape_on_grid.h | 185 ++++++------- .../concretizations/Vector_distances_in_diagram.h | 76 ++---- .../concretizations/read_persitence_from_file.h | 300 --------------------- .../include/gudhi/fill_in_missing_data.h | 8 + .../include/gudhi/multiplicative_bootstrap.h | 10 +- src/Gudhi_stat/include/gudhi/permutation_test.h | 2 +- .../include/gudhi/read_persitence_from_file.h | 300 +++++++++++++++++++++ src/Gudhi_stat/include/gudhi/topological_process.h | 34 +-- src/Gudhi_stat/test/persistence_heat_maps_test.cpp | 8 +- .../test/persistence_lanscapes_on_grid_test.cpp | 21 +- src/Gudhi_stat/test/persistence_lanscapes_test.cpp | 13 +- src/Gudhi_stat/test/vector_representation_test.cpp | 11 +- src/Gudhi_stat/utilities/Hausdorff_bootstrap.cpp | 2 +- src/Gudhi_stat/utilities/Landscape_bootstrap.cpp | 2 +- .../utilities/Multiplicative_bootstrap.cpp | 2 +- .../compute_distance_of_persistence_heat_maps.cpp | 16 +- ...ute_scalar_product_of_persistence_heat_maps.cpp | 8 +- .../plot_persistence_intervals.cpp | 2 +- .../compute_distance_of_landscapes.cpp | 18 +- .../compute_scalar_product_of_landscapes.cpp | 8 +- .../compute_distance_of_landscapes_on_grid.cpp | 18 +- ...ompute_scalar_product_of_landscapes_on_grid.cpp | 8 +- .../compute_distance_of_persistence_vectors.cpp | 16 +- ...mpute_scalar_product_of_persistence_vectors.cpp | 8 +- 36 files changed, 856 insertions(+), 750 deletions(-) create mode 100644 src/Gudhi_stat/include/gudhi/common_gudhi_stat.h delete mode 100644 src/Gudhi_stat/include/gudhi/concretizations/read_persitence_from_file.h create mode 100644 src/Gudhi_stat/include/gudhi/read_persitence_from_file.h (limited to 'src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp') diff --git a/src/Gudhi_stat/example/persistence_intervals.cpp b/src/Gudhi_stat/example/persistence_intervals.cpp index 6e2b0ddb..04a3d948 100644 --- a/src/Gudhi_stat/example/persistence_intervals.cpp +++ b/src/Gudhi_stat/example/persistence_intervals.cpp @@ -39,67 +39,67 @@ int main( int argc , char** argv ) { if ( argc != 2 ) { - cout << "To run this program, please provide the name of a file with persistence diagram \n"; + std::cout << "To run this program, please provide the name of a file with persistence diagram \n"; return 1; } Persistence_intervals p( argv[1] ); std::pair min_max_ = p.min_max(); - cout << "Birth-death range : " << min_max_.first << " " << min_max_.second << endl; + std::cout << "Birth-death range : " << min_max_.first << " " << min_max_.second << std::endl; std::vector dominant_ten_intervals_length = p.length_of_dominant_intervals(10); - cout << "Lendth of ten dominant intervals : " << endl; + std::cout << "Lendth of ten dominant intervals : " < > ten_dominant_intervals = p.dominant_intervals( 10 ); - cout << "Here are the dominant intervals : " << endl; + std::cout << "Here are the dominant intervals : " < histogram = p.histograms_of_lengths( 10 ); - cout << "Here is the histogram of barcode's length : " << endl; + std::cout << "Here is the histogram of barcode's length : " < cumulative_histogram = p.cumulative_histograms_of_lengths( 10 ); - cout<< "Cumuative histogram : " << endl; + std::cout<< "Cumuative histogram : " < char_funct_diag = p.characteristic_function_of_diagram( min_max_.first , min_max_.second ); - cout << "Characteristic function of diagram : " << endl; + std::cout << "Characteristic function of diagram : " < cumul_char_funct_diag = p.cumulative_characteristic_function_of_diagram( min_max_.first , min_max_.second ); - cout << "Cumulative characteristic function of diagram : " << endl; + std::cout << "Cumulative characteristic function of diagram : " < > pbns = p.compute_persistent_betti_numbers(); for ( size_t i = 0 ; i != pbns.size() ; ++i ) { - cout << pbns[i].first << " " << pbns[i].second << endl; + std::cout << pbns[i].first << " " << pbns[i].second < to_average; - to_average.push_back( &l1 ); - to_average.push_back( &l2 ); - average.compute_average( to_average ); + average.compute_average( {&l1,&l2} ); std::cout << "average : " << average << std::endl; //here is the distance of landscapes: @@ -187,16 +184,13 @@ if ( argc != 2 ) cout << "L^1 distance : " << compute_discance_of_landscapes(p,sum,1) << endl; cout << "L^2 distance : " << compute_discance_of_landscapes(p,sum,2) << endl; - cout << "L^infty distance : " << compute_discance_of_landscapes(p,sum,-1) << endl; + cout << "L^infty distance : " << compute_discance_of_landscapes(p,sum,std::numeric_limits::max() ) << endl; { Persistence_landscape p( "../test/data/file_with_diagram" ); Persistence_landscape q( "../test/data/file_with_diagram_1" ); - std::vector< Abs_Topological_data_with_averages* > to_average; - to_average.push_back( &p ); - to_average.push_back( &q ); Persistence_landscape av; - av.compute_average( to_average ); + av.compute_average( {&p,&q} ); Persistence_landscape template_average; template_average.load_landscape_from_file( "average" ); @@ -212,7 +206,7 @@ if ( argc != 2 ) Persistence_landscape q( "../test/data/file_with_diagram_1" ); cout << "L^1 distance : " << p.distance( &q ) << endl; cout << "L^2 distance : " << p.distance( &q , 2) << endl; - cout << "L^infty distance : " << p.distance( &q , -1 ) << endl; + cout << "L^infty distance : " << p.distance( &q , std::numeric_limits::max() ) << endl; } diff --git a/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp b/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp index 331ae4ae..282acb2d 100644 --- a/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp +++ b/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp @@ -54,8 +54,8 @@ int main( int argc , char** argv ) Persistence_landscape_on_grid l2( persistence2 , 0 , 11 , 20 ); //This is how to compute integral of landscapes: - std::cout << "Integral of the first landscape : " << l1.compute_integral_of_landscape() << endl; - std::cout << "Integral of the second landscape : " << l2.compute_integral_of_landscape() << endl; + std::cout << "Integral of the first landscape : " << l1.compute_integral_of_landscape() << std::endl; + std::cout << "Integral of the second landscape : " << l2.compute_integral_of_landscape() << std::endl; //And here how to write landscapes to stream: std::cout << "l1 : " << l1 << std::endl; @@ -70,11 +70,8 @@ int main( int argc , char** argv ) std::cout << "L^1 Norm of l2 : " << l2.compute_norm_of_landscape( 1. ) << std::endl; //here is the average of landscapes: - Persistence_landscape_on_grid average; - std::vector< Persistence_landscape_on_grid* > to_average; - to_average.push_back( &l1 ); - to_average.push_back( &l2 ); - average.compute_average( to_average ); + Persistence_landscape_on_grid average; + average.compute_average( {&l1,&l2} ); std::cout << "average : " << average << std::endl; //here is the distance of landscapes: @@ -166,12 +163,9 @@ int main( int argc , char** argv ) /* Persistence_landscape_on_grid p( "file_with_diagram", 0,1,100 ); - Persistence_landscape_on_grid q( "file_with_diagram_1", 0,1,100 ); - std::vector< Abs_Topological_data_with_averages* > to_average; - to_average.push_back( &p ); - to_average.push_back( &q ); + Persistence_landscape_on_grid q( "file_with_diagram_1", 0,1,100 ); Persistence_landscape_on_grid av; - av.compute_average( to_average ); + av.compute_average( {&p,&q} ); av.print_to_file("average_on_a_grid"); Persistence_landscape_on_grid template_average; @@ -186,7 +180,7 @@ int main( int argc , char** argv ) Persistence_landscape_on_grid q( "file_with_diagram_1" , 0,1,10000); cerr << p.distance( &q )<< endl; cerr << p.distance( &q , 2 ) << endl; - cerr << p.distance( &q , -1 ) << endl; + cerr << p.distance( &q , std::numeric_limits::max() ) << endl; */ /* diff --git a/src/Gudhi_stat/example/vector_representation.cpp b/src/Gudhi_stat/example/vector_representation.cpp index bb4b5d01..e8963722 100644 --- a/src/Gudhi_stat/example/vector_representation.cpp +++ b/src/Gudhi_stat/example/vector_representation.cpp @@ -66,10 +66,7 @@ int main( int argc , char** argv ) //averages: Vector_distances_in_diagram > average; - std::vector< Vector_distances_in_diagram >* > to_average; - to_average.push_back( &v1 ); - to_average.push_back( &v2 ); - average.compute_average( to_average ); + average.compute_average( {&v1,&v2} ); std::cout << "Average : " << average << std::endl; //computations of distances: @@ -106,13 +103,9 @@ int main( int argc , char** argv ) cout << "p_prime : " < to_average; - to_average.push_back( (Abs_Topological_data_with_averages*)(&p) ); - to_average.push_back( (Abs_Topological_data_with_averages*)(&p_prime) ); - + cout << "Distance between input persistence diagrams : " << p.distance( (Abs_Topological_data_with_distances*)(&p_prime) ) << endl; Vector_distances_in_diagram< Euclidean_distance > average; - average.compute_average( to_average ); + average.compute_average( {&p,&p_prime} ); cout << "Here is an average : " << average << endl; } diff --git a/src/Gudhi_stat/include/gudhi/Hausdorff_distances.h b/src/Gudhi_stat/include/gudhi/Hausdorff_distances.h index de39ad7d..39de764e 100644 --- a/src/Gudhi_stat/include/gudhi/Hausdorff_distances.h +++ b/src/Gudhi_stat/include/gudhi/Hausdorff_distances.h @@ -29,6 +29,11 @@ #include #include +namespace Gudhi +{ +namespace Gudhi_stat +{ + /** * This file contains various implementations of Hausrodff distances between collections of points. It contains various implementations that can be used for specific case. @@ -138,5 +143,7 @@ public: }; +}//namespace Gudhi_stat +}//namespace Gudhi #endif diff --git a/src/Gudhi_stat/include/gudhi/bootstrap.h b/src/Gudhi_stat/include/gudhi/bootstrap.h index ca40f9c7..83edb2e1 100644 --- a/src/Gudhi_stat/include/gudhi/bootstrap.h +++ b/src/Gudhi_stat/include/gudhi/bootstrap.h @@ -23,11 +23,6 @@ #ifndef BOOTSTRAP_H #define BOOTSTRAP_H -//concretizations -#include -#include -#include -#include #ifdef GUDHI_USE_TBB #include @@ -39,6 +34,11 @@ #include #include +namespace Gudhi +{ +namespace Gudhi_stat +{ + /** * This is a generic function to perform bootstrap. * In this function we assume that there is a class to compute characteristic of collection of points (PointCloudCharacteristics) and that it stores coordinates of all points. It allows to compute the characteristic @@ -140,4 +140,9 @@ double bootstrap( size_t number_of_points , CharacteristicFunction f , DistanceB }//bootstrap + + +}//namespace Gudhi_stat +}//namespace Gudhi + #endif diff --git a/src/Gudhi_stat/include/gudhi/common.h b/src/Gudhi_stat/include/gudhi/common.h index d573a92a..916b4499 100644 --- a/src/Gudhi_stat/include/gudhi/common.h +++ b/src/Gudhi_stat/include/gudhi/common.h @@ -20,9 +20,13 @@ * along with this program. If not, see . */ -#pragma once +#ifndef HAUSDORFF_DISTANCES_H +#define HAUSDORFF_DISTANCES_H //this file contain an implementation of some common procedures used in Gudhi_stat. + + + //double epsi = std::numeric_limits::epsilon(); double epsi = 0.000005; diff --git a/src/Gudhi_stat/include/gudhi/common_gudhi_stat.h b/src/Gudhi_stat/include/gudhi/common_gudhi_stat.h new file mode 100644 index 00000000..1767b1be --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/common_gudhi_stat.h @@ -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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA (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 common_gudhi_stat_H +#define common_gudhi_stat_H + + +namespace Gudhi +{ +namespace Gudhi_stat +{ + //this file contain an implementation of some common procedures used in Gudhi_stat. + + //double epsi = std::numeric_limits::epsilon(); +double epsi = 0.000005; + + +double plus_( double a,double b ){return a+b;} +double minus_( double a,double b ){return a-b;} + + + +/** + * A procedure used to compare doubles. Typically gien two doubles A and B, comparing A == B is not good idea. In this case, we use the procedure almostEqual with the epsi defined at + * the top of the file. Setting up the epsi give the user a tolerance on what should be consider equal. +**/ +inline bool almost_equal( double a , double b ) +{ + if ( fabs(a-b) < epsi ) + return true; + return false; +} + + + + +//landscapes +/** + * Extra functions needed in construction of barcodes. +**/ +double minus_length( std::pair a ) +{ + return a.first-a.second; +} +double birth_plus_deaths( std::pair a ) +{ + return a.first+a.second; +} + + +//landscapes +/** + * Given two points in R^2, the procedure compute the parameters A and B of the line y = Ax + B that crosses those two points. +**/ +std::pair compute_parameters_of_a_line( std::pair p1 , std::pair p2 ) +{ + double a = (p2.second-p1.second)/( p2.first - p1.first ); + double b = p1.second - a*p1.first; + return std::make_pair(a,b); +} + +//landscapes +/** + * This procedure given two points which lies on the opposide sides of x axis, compute x for which the line connecting those two points crosses x axis. +**/ +double find_zero_of_a_line_segment_between_those_two_points ( std::pair p1, std::pair p2 ) +{ + if ( p1.first == p2.first )return p1.first; + if ( p1.second*p2.second > 0 ) + { + std::ostringstream errMessage; + errMessage <<"In function find_zero_of_a_line_segment_between_those_two_points the agguments are: (" << p1.first << "," << p1.second << ") and (" << p2.first << "," << p2.second << "). There is no zero in line between those two points. Program terminated."; + std::string errMessageStr = errMessage.str(); + const char* err = errMessageStr.c_str(); + throw(err); + } + //we assume here, that x \in [ p1.first, p2.first ] and p1 and p2 are points between which we will put the line segment + double a = (p2.second - p1.second)/(p2.first - p1.first); + double b = p1.second - a*p1.first; + //cerr << "Line crossing points : (" << p1.first << "," << p1.second << ") oraz (" << p2.first << "," << p2.second << ") : \n"; + //cerr << "a : " << a << " , b : " << b << " , x : " << x << endl; + return -b/a; +} + + + +//landscapes +/** + * Lexicographical ordering of points . +**/ +bool compare_points_sorting( std::pair f, std::pair s ) +{ + if ( f.first < s.first ) + { + return true; + } + else + {//f.first >= s.first + if ( f.first > s.first ) + { + return false; + } + else + {//f.first == s.first + if ( f.second > s.second ) + { + return true; + } + else + { + return false; + } + } + } +} + + +//landscapes +/** + * This procedure takes two points in R^2 and a double value x. It conputes the line pasing through those two points and return the value of that linear function at x. +**/ +double function_value ( std::pair p1, std::pair p2 , double x ) +{ + //we assume here, that x \in [ p1.first, p2.first ] and p1 and p2 are points between which we will put the line segment + double a = (p2.second - p1.second)/(p2.first - p1.first); + double b = p1.second - a*p1.first; + return (a*x+b); +} + +//landscapes on a grid +struct greater_landscapes_on_grid +{ + template + bool operator()(T const &a, T const &b) const { return a > b; } +}; + + +}//namespace Gudhi_stat +}//namespace Gudhi + +#endif diff --git a/src/Gudhi_stat/include/gudhi/concretizations/PSSK.h b/src/Gudhi_stat/include/gudhi/concretizations/PSSK.h index e61711f4..89da2a2d 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/PSSK.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/PSSK.h @@ -95,9 +95,9 @@ void PSSK::construct( const std::vector< std::pair >& intervals_ if ( dbg ) { - cerr << "min_ : " << min_ << endl; - cerr << "max_ : " << max_ << endl; - cerr << "number_of_pixels : " << number_of_pixels << endl; + std::cerr << "min_ : " << min_ << std::endl; + std::cerr << "max_ : " << max_ << std::endl; + std::cerr << "number_of_pixels : " << number_of_pixels << std::endl; getchar(); } @@ -115,7 +115,7 @@ void PSSK::construct( const std::vector< std::pair >& intervals_ } this->heat_map = heat_map_; - if (dbg)cerr << "Done creating of the heat map, now we will fill in the structure \n"; + if (dbg)std::cerr << "Done creating of the heat map, now we will fill in the structure \n"; for ( size_t pt_nr = 0 ; pt_nr != intervals_.size() ; ++pt_nr ) { @@ -125,9 +125,9 @@ void PSSK::construct( const std::vector< std::pair >& intervals_ if ( dbg ) { - std::cerr << "point : " << intervals_[pt_nr].first << " , " << intervals_[pt_nr].second << endl; - std::cerr << "x_grid : " << x_grid << endl; - std::cerr << "y_grid : " << y_grid << endl; + std::cerr << "point : " << intervals_[pt_nr].first << " , " << intervals_[pt_nr].second << std::endl; + std::cerr << "x_grid : " << x_grid << std::endl; + std::cerr << "y_grid : " << y_grid << std::endl; } //x_grid and y_grid gives a center of the kernel. We want to have its lower left cordner. To get this, we need to shift x_grid and y_grid by a grid diameter. @@ -138,8 +138,8 @@ void PSSK::construct( const std::vector< std::pair >& intervals_ if ( dbg ) { std::cerr << "After shift : \n";; - std::cerr << "x_grid : " << x_grid << endl; - std::cerr << "y_grid : " << y_grid << endl; + std::cerr << "x_grid : " << x_grid << std::endl; + std::cerr << "y_grid : " << y_grid << std::endl; std::cerr << "filter.size() : " << filter.size() << std::endl; getchar(); } diff --git a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_heat_maps.h b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_heat_maps.h index 83583a57..22df8d8e 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_heat_maps.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_heat_maps.h @@ -33,12 +33,11 @@ #include //gudhi include -#include +#include #include -using namespace std; namespace Gudhi { @@ -71,8 +70,8 @@ std::vector< std::vector > create_Gaussian_filter( size_t pixel_radius , if ( dbg ) { std::cerr << "Kernel initalize \n"; - cerr << "pixel_radius : " << pixel_radius << endl; - std::cerr << "kernel.size() : " << kernel.size() << endl; + std::cerr << "pixel_radius : " << pixel_radius << std::endl; + std::cerr << "kernel.size() : " << kernel.size() << std::endl; getchar(); } @@ -277,12 +276,12 @@ public: /** * Return minimal range value of persistent image. **/ - inline double gimme_min()const{return this->min_;} + inline double give_me_min()const{return this->min_;} /** * Return maximal range value of persistent image. **/ - inline double gimme_max()const{return this->max_;} + inline double give_me_max()const{return this->max_;} /** @@ -329,8 +328,9 @@ public: void plot( const char* filename )const; - //implementation of arythmetic operations: - + /** + * Binary (arythmetic) operation on two Persistence_heat_maps. + **/ friend Persistence_heat_maps operation_on_pair_of_heat_maps( const Persistence_heat_maps& first , const Persistence_heat_maps& second , double (*opertion)( double,double ) ) { //first check if the heat maps are compatible @@ -356,6 +356,10 @@ public: return result; }//operation_on_pair_of_heat_maps + + /** + * Multiplication of Persistence_heat_maps by scalar (so that all values of the heat map gets multiplied by that scalar). + **/ Persistence_heat_maps multiply_by_scalar( double scalar )const { Persistence_heat_maps result; @@ -376,42 +380,42 @@ public: } /** - * This function computes a sum of two objects of a type Vector_distances_in_diagram. + * This function computes a sum of two objects of a type Persistence_heat_maps. **/ friend Persistence_heat_maps operator+( const Persistence_heat_maps& first , const Persistence_heat_maps& second ) { return operation_on_pair_of_heat_maps( first , second , plus_ ); } /** - * This function computes a difference of two objects of a type Vector_distances_in_diagram. + * This function computes a difference of two objects of a type Persistence_heat_maps. **/ friend Persistence_heat_maps operator-( const Persistence_heat_maps& first , const Persistence_heat_maps& second ) { return operation_on_pair_of_heat_maps( first , second , minus_ ); } /** - * This function computes a product of an object of a type Vector_distances_in_diagram with real number. + * This function computes a product of an object of a type Persistence_heat_maps with real number. **/ friend Persistence_heat_maps operator*( double scalar , const Persistence_heat_maps& A ) { return A.multiply_by_scalar( scalar ); } /** - * This function computes a product of an object of a type Vector_distances_in_diagram with real number. + * This function computes a product of an object of a type Persistence_heat_maps with real number. **/ friend Persistence_heat_maps operator*( const Persistence_heat_maps& A , double scalar ) { return A.multiply_by_scalar( scalar ); } /** - * This function computes a product of an object of a type Vector_distances_in_diagram with real number. + * This function computes a product of an object of a type Persistence_heat_maps with real number. **/ Persistence_heat_maps operator*( double scalar ) { return this->multiply_by_scalar( scalar ); } /** - * += operator for Vector_distances_in_diagram. + * += operator for Persistence_heat_maps. **/ Persistence_heat_maps operator += ( const Persistence_heat_maps& rhs ) { @@ -419,7 +423,7 @@ public: return *this; } /** - * -= operator for Vector_distances_in_diagram. + * -= operator for Persistence_heat_maps. **/ Persistence_heat_maps operator -= ( const Persistence_heat_maps& rhs ) { @@ -427,7 +431,7 @@ public: return *this; } /** - * *= operator for Vector_distances_in_diagram. + * *= operator for Persistence_heat_maps. **/ Persistence_heat_maps operator *= ( double x ) { @@ -435,7 +439,7 @@ public: return *this; } /** - * /= operator for Vector_distances_in_diagram. + * /= operator for Persistence_heat_maps. **/ Persistence_heat_maps operator /= ( double x ) { @@ -475,6 +479,7 @@ public: * A function to compute distance between persistence heat maps. * The parameter of this function is a const reference to an object of a class Persistence_heat_maps. * This function is required in Topological_data_with_distances concept. + * For max norm distance, set power to std::numeric_limits::max() **/ double distance( const Persistence_heat_maps& second_ , double power = 1)const; @@ -497,7 +502,7 @@ public: /** * The x-range of the persistence heat map. **/ - std::pair< double , double > gimme_x_range()const + std::pair< double , double > give_me_x_range()const { return std::make_pair( this->min_ , this->max_ ); } @@ -505,9 +510,9 @@ public: /** * The y-range of the persistence heat map. **/ - std::pair< double , double > gimme_y_range()const + std::pair< double , double > give_me_y_range()const { - return this->gimme_x_range(); + return this->give_me_x_range(); } @@ -571,9 +576,9 @@ void Persistence_heat_maps::construct( const std::vector< s if ( dbg ) { - cerr << "min_ : " << min_ << endl; - cerr << "max_ : " << max_ << endl; - cerr << "number_of_pixels : " << number_of_pixels << endl; + std::cerr << "min_ : " << min_ << std::endl; + std::cerr << "max_ : " << max_ << std::endl; + std::cerr << "number_of_pixels : " << number_of_pixels << std::endl; getchar(); } @@ -589,7 +594,7 @@ void Persistence_heat_maps::construct( const std::vector< s } this->heat_map = heat_map_; - if (dbg)cerr << "Done creating of the heat map, now we will fill in the structure \n"; + if (dbg)std::cerr << "Done creating of the heat map, now we will fill in the structure \n"; for ( size_t pt_nr = 0 ; pt_nr != intervals_.size() ; ++pt_nr ) { @@ -599,9 +604,9 @@ void Persistence_heat_maps::construct( const std::vector< s if ( dbg ) { - std::cerr << "point : " << intervals_[pt_nr].first << " , " << intervals_[pt_nr].second << endl; - std::cerr << "x_grid : " << x_grid << endl; - std::cerr << "y_grid : " << y_grid << endl; + std::cerr << "point : " << intervals_[pt_nr].first << " , " << intervals_[pt_nr].second << std::endl; + std::cerr << "x_grid : " << x_grid << std::endl; + std::cerr << "y_grid : " << y_grid << std::endl; } //x_grid and y_grid gives a center of the kernel. We want to have its lower left cordner. To get this, we need to shift x_grid and y_grid by a grid diameter. @@ -612,8 +617,8 @@ void Persistence_heat_maps::construct( const std::vector< s if ( dbg ) { std::cerr << "After shift : \n";; - std::cerr << "x_grid : " << x_grid << endl; - std::cerr << "y_grid : " << y_grid << endl; + std::cerr << "x_grid : " << x_grid << std::endl; + std::cerr << "y_grid : " << y_grid << std::endl; } double scaling_value = this->f(intervals_[pt_nr]); @@ -782,7 +787,7 @@ void Persistence_heat_maps::compute_percentage_of_active( c template void Persistence_heat_maps::plot( const char* filename )const { - ofstream out; + std::ofstream out; std::stringstream ss; ss << filename << "_GnuplotScript"; @@ -794,7 +799,7 @@ void Persistence_heat_maps::plot( const char* filename )con { out << this->heat_map[i][j] << " "; } - out << endl; + out << std::endl; } out.close(); std::cout << "Gnuplot script have been created. Open gnuplot and type load \'" << ss.str().c_str() << "\' to see the picture." << std::endl; @@ -805,7 +810,7 @@ template void Persistence_heat_maps::print_to_file( const char* filename )const { - ofstream out; + std::ofstream out; out.open( filename ); //First we store this->min_ and this->max_ values: @@ -816,7 +821,7 @@ void Persistence_heat_maps::print_to_file( const char* file { out << this->heat_map[i][j] << " "; } - out << endl; + out << std::endl; } out.close(); } @@ -826,13 +831,13 @@ void Persistence_heat_maps::load_from_file( const char* fil { bool dbg = false; - ifstream in; + std::ifstream in; in.open( filename ); //checking if the file exist / if it was open. if ( !( access( filename, F_OK ) != -1 ) ) { - cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; } @@ -918,11 +923,28 @@ double Persistence_heat_maps::distance( const Persistence_h //if we are here, we know that the two persistence iomages are defined on the same domain, so we can start computing their distances: double distance = 0; - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + if ( power != std::numeric_limits::max() ) { - for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + { + distance += pow( fabs(this->heat_map[i][j] - second.heat_map[i][j]) , power ); + } + } + } + else + { + //in this case, we compute max norm distance + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) { - distance += pow( abs(this->heat_map[i][j] - second.heat_map[i][j]) , power ); + for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + { + if ( distance < fabs(this->heat_map[i][j] - second.heat_map[i][j]) ) + { + distance = fabs(this->heat_map[i][j] - second.heat_map[i][j]); + } + } } } return distance; diff --git a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_intervals.h b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_intervals.h index b917de69..3bd98835 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_intervals.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_intervals.h @@ -24,7 +24,7 @@ #define Persistence_intervals_H_ //gudhi include -#include +#include //standard include #include @@ -66,7 +66,7 @@ public: /** * This procedure returns x-range of a given persistence diagram. **/ - std::pair< double , double > gimme_x_range()const + std::pair< double , double > give_me_x_range()const { double min_ = std::numeric_limits::max(); double max_ = -std::numeric_limits::max(); @@ -81,7 +81,7 @@ public: /** * This procedure returns y-range of a given persistence diagram. **/ - std::pair< double , double > gimme_y_range()const + std::pair< double , double > give_me_y_range()const { double min_ = std::numeric_limits::max(); double max_ = -std::numeric_limits::max(); @@ -478,7 +478,7 @@ std::vector< double > Persistence_intervals::characteristic_function_of_diagram( beginIt = number_of_bins*(this->intervals[i].first-x_min)/(x_max - x_min); } - size_t endIt; + size_t endIt = 0; if ( this->intervals[i].second < x_min )endIt = 0; if ( this->intervals[i].second >= x_max )endIt = result.size(); if ( ( this->intervals[i].second > x_min ) && ( this->intervals[i].second < x_max ) ) diff --git a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape.h b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape.h index fd6837c0..bd41e1bd 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape.h @@ -36,9 +36,8 @@ //gudhi include -#include +#include #include -using namespace std; @@ -75,16 +74,6 @@ public: **/ Persistence_landscape( const std::vector< std::pair< double , double > >& p ); - /** - * Assignement operator. - **/ - Persistence_landscape& operator=( const Persistence_landscape& org ); - - /** - * Copy constructor. - **/ - Persistence_landscape(const Persistence_landscape&); - /** * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. @@ -141,7 +130,7 @@ public: /** - * A function that compute sum of two landscapes. + *\private A function that compute sum of two landscapes. **/ friend Persistence_landscape add_two_landscapes ( const Persistence_landscape& land1 , const Persistence_landscape& land2 ) { @@ -149,7 +138,7 @@ public: } /** - * A function that compute difference of two landscapes. + *\private A function that compute difference of two landscapes. **/ friend Persistence_landscape subtract_two_landscapes ( const Persistence_landscape& land1 , const Persistence_landscape& land2 ) { @@ -189,7 +178,7 @@ public: } /** - * Operator +=. The second parameter is persistnece landwscape. + * Operator +=. The second parameter is persistence landscape. **/ Persistence_landscape operator += ( const Persistence_landscape& rhs ) { @@ -198,7 +187,7 @@ public: } /** - * Operator -=. The second parameter is persistnece landwscape. + * Operator -=. The second parameter is a persistence landscape. **/ Persistence_landscape operator -= ( const Persistence_landscape& rhs ) { @@ -282,13 +271,13 @@ public: double compute_norm_of_landscape( double i ) { Persistence_landscape l; - if ( i != -1 ) + if ( i != std::numeric_limits< double >::max() ) { - return compute_discance_of_landscapes(*this,l,i); + return compute_distance_of_landscapes(*this,l,i); } else { - return compute_max_norm_discance_of_landscapes(*this,l); + return compute_max_norm_distance_of_landscapes(*this,l); } } @@ -300,14 +289,14 @@ public: /** * Computations of L^{\infty} distance between two landscapes. **/ - friend double compute_max_norm_discance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second ); - //friend double compute_max_norm_discance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , unsigned& nrOfLand , double&x , double& y1, double& y2 ); + friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second ); + //friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , unsigned& nrOfLand , double&x , double& y1, double& y2 ); /** * Computations of L^{p} distance between two landscapes. p is the parameter of the procedure. **/ - friend double compute_discance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , int p ); + friend double compute_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , double p ); @@ -411,12 +400,12 @@ public: while ( nextLevelMerge.size() != 1 ) { - if ( dbg ){cerr << "nextLevelMerge.size() : " << nextLevelMerge.size() << endl;} + if ( dbg ){std::cerr << "nextLevelMerge.size() : " << nextLevelMerge.size() << std::endl;} std::vector< Persistence_landscape* > nextNextLevelMerge; nextNextLevelMerge.reserve( to_average.size() ); for ( size_t i = 0 ; i < nextLevelMerge.size() ; i=i+2 ) { - if ( dbg ){cerr << "i : " << i << endl;} + if ( dbg ){std::cerr << "i : " << i << std::endl;} Persistence_landscape* l = new Persistence_landscape; if ( i+1 != nextLevelMerge.size() ) { @@ -428,7 +417,7 @@ public: } nextNextLevelMerge.push_back( l ); } - if ( dbg ){cerr << "After this iteration \n";getchar();} + if ( dbg ){std::cerr << "After this iteration \n";getchar();} if ( !is_this_first_level ) { @@ -450,16 +439,17 @@ public: * A function to compute distance between persistence landscape. * The parameter of this functionis a Persistence_landscape. * This function is required in Topological_data_with_distances concept. + * For max norm distance, set power to std::numeric_limits::max() **/ double distance( const Persistence_landscape& second , double power = 1 )const { - if ( power != -1 ) + if ( power != std::numeric_limits::max() ) { - return compute_discance_of_landscapes( *this , second , power ); + return compute_distance_of_landscapes( *this , second , power ); } else { - return compute_max_norm_discance_of_landscapes( *this , second ); + return compute_max_norm_distance_of_landscapes( *this , second ); } } @@ -480,7 +470,7 @@ public: * This procedure returns x-range of a given level persistence landscape. If a default value is used, the x-range * of 0th level landscape is given (and this range contains the ranges of all other landscapes). **/ - std::pair< double , double > gimme_x_range( size_t level = 0 )const + std::pair< double , double > give_me_x_range( size_t level = 0 )const { std::pair< double , double > result; if ( level < this->land.size() ) @@ -498,7 +488,7 @@ public: * This procedure returns y-range of a given level persistence landscape. If a default value is used, the y-range * of 0th level landscape is given (and this range contains the ranges of all other landscapes). **/ - std::pair< double , double > gimme_y_range( size_t level = 0 )const + std::pair< double , double > give_me_y_range( size_t level = 0 )const { std::pair< double , double > result; if ( level < this->land.size() ) @@ -561,17 +551,7 @@ protected: }; -Persistence_landscape::Persistence_landscape(const Persistence_landscape& oryginal) -{ - //std::cerr << "Running copy constructor \n"; - std::vector< std::vector< std::pair > > land( oryginal.land.size() ); - for ( size_t i = 0 ; i != oryginal.land.size() ; ++i ) - { - land[i].insert( land[i].end() , oryginal.land[i].begin() , oryginal.land[i].end() ); - } - this->land = land; - this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); -} + @@ -615,7 +595,7 @@ bool Persistence_landscape::operator == ( const Persistence_landscape& rhs )con { if ( !( almost_equal(this->land[level][i].first , rhs.land[level][i].first) && almost_equal(this->land[level][i].second , rhs.land[level][i].second) ) ) { - //cerr<< this->land[level][i].first << " , " << rhs.land[level][i].first << " and " << this->land[level][i].second << " , " << rhs.land[level][i].second << endl; + //std::cerr<< this->land[level][i].first << " , " << rhs.land[level][i].first << " and " << this->land[level][i].second << " , " << rhs.land[level][i].second << std::endl; if (operatorEqualDbg)std::cerr << "this->land[level][i] : " << this->land[level][i].first << " " << this->land[level][i].second << "\n"; if (operatorEqualDbg)std::cerr << "rhs.land[level][i] : " << rhs.land[level][i].first << " " << rhs.land[level][i].second << "\n"; if (operatorEqualDbg)std::cerr << "3\n"; @@ -627,17 +607,6 @@ bool Persistence_landscape::operator == ( const Persistence_landscape& rhs )con } -Persistence_landscape& Persistence_landscape::operator=( const Persistence_landscape& oryginal ) -{ - std::vector< std::vector< std::pair > > land( oryginal.land.size() ); - for ( size_t i = 0 ; i != oryginal.land.size() ; ++i ) - { - land[i].insert( land[i].end() , oryginal.land[i].begin() , oryginal.land[i].end() ); - } - this->land = land; - return *this; -} - Persistence_landscape::Persistence_landscape( const std::vector< std::pair< double , double > > & p ) @@ -650,7 +619,7 @@ Persistence_landscape::Persistence_landscape( const std::vector< std::pair< doub void Persistence_landscape::construct_persistence_landscape_from_barcode( const std::vector< std::pair< double , double > > & p ) { bool dbg = false; - if ( dbg ){cerr << "Persistence_landscape::Persistence_landscape( const std::vector< std::pair< double , double > >& p )" << endl;} + if ( dbg ){std::cerr << "Persistence_landscape::Persistence_landscape( const std::vector< std::pair< double , double > >& p )" << std::endl;} //this is a general algorithm to construct persistence landscapes. std::vector< std::pair > bars; @@ -889,7 +858,7 @@ double Persistence_landscape::compute_value_at_a_given_point( unsigned level , d if ( compute_value_at_a_given_pointDbg ) { - std::cerr << "Tutaj \n"; + std::cerr << "Here \n"; std::cerr << "x : " << x << "\n"; std::cerr << "this->land[level][coordBegin].first : " << this->land[level][coordBegin].first << "\n"; std::cerr << "this->land[level][coordEnd].first : " << this->land[level][coordEnd].first << "\n"; @@ -1074,7 +1043,7 @@ void Persistence_landscape::load_landscape_from_file( const char* filename ) in.open( filename ); if ( !( access( filename, F_OK ) != -1 ) ) { - cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; } @@ -1326,7 +1295,7 @@ double compute_maximal_distance_non_symmetric( const Persistence_landscape& pl1, -double compute_discance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , int p ) +double compute_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , double p ) { bool dbg = false; //This is what we want to compute: (\int_{- \infty}^{+\infty}| first-second |^p)^(1/p). We will do it one step at a time: @@ -1337,9 +1306,9 @@ double compute_discance_of_landscapes( const Persistence_landscape& first, const //| first-second |: lan = lan.abs(); - if ( dbg ){cerr << "Abs of difference ; " << lan << endl;getchar();} + if ( dbg ){std::cerr << "Abs of difference ; " << lan << std::endl;getchar();} - if ( p != -1 ) + if ( p != std::numeric_limits::max() ) { //\int_{- \infty}^{+\infty}| first-second |^p double result; @@ -1358,13 +1327,13 @@ double compute_discance_of_landscapes( const Persistence_landscape& first, const } else { - //p == -1 - if ( dbg )std::cerr << "Power = -1, compute maximum \n"; + //p == infty + if ( dbg )std::cerr << "Power = infty, compute maximum \n"; return lan.compute_maximum(); } } -double compute_max_norm_discance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second ) +double compute_max_norm_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second ) { return std::max( compute_maximal_distance_non_symmetric(first,second) , compute_maximal_distance_non_symmetric(second,first) ); } @@ -1385,7 +1354,7 @@ double compute_inner_product( const Persistence_landscape& l1 , const Persistenc for ( size_t level = 0 ; level != std::min( l1.size() , l2.size() ) ; ++level ) { - if ( dbg ){cerr << "Computing inner product for a level : " << level << endl;getchar();} + if ( dbg ){std::cerr << "Computing inner product for a level : " << level << std::endl;getchar();} if ( l1.land[level].size() * l2.land[level].size() == 0 )continue; //endpoints of the interval on which we will compute the inner product of two locally linear functions: @@ -1437,12 +1406,12 @@ double compute_inner_product( const Persistence_landscape& l1 , const Persistenc if ( dbg ) { - cerr << "[l1.land[level][l1It].first,l1.land[level][l1It+1].first] : " << l1.land[level][l1It].first << " , " << l1.land[level][l1It+1].first << endl; - cerr << "[l2.land[level][l2It].first,l2.land[level][l2It+1].first] : " << l2.land[level][l2It].first << " , " << l2.land[level][l2It+1].first << endl; - cerr << "a : " << a << ", b : " << b << " , c: " << c << ", d : " << d << endl; - cerr << "x1 : " << x1 << " , x2 : " << x2 << endl; - cerr << "contributionFromThisPart : " << contributionFromThisPart << endl; - cerr << "result : " << result << endl; + std::cerr << "[l1.land[level][l1It].first,l1.land[level][l1It+1].first] : " << l1.land[level][l1It].first << " , " << l1.land[level][l1It+1].first << std::endl; + std::cerr << "[l2.land[level][l2It].first,l2.land[level][l2It+1].first] : " << l2.land[level][l2It].first << " , " << l2.land[level][l2It+1].first << std::endl; + std::cerr << "a : " << a << ", b : " << b << " , c: " << c << ", d : " << d << std::endl; + std::cerr << "x1 : " << x1 << " , x2 : " << x2 << std::endl; + std::cerr << "contributionFromThisPart : " << contributionFromThisPart << std::endl; + std::cerr << "result : " << result << std::endl; getchar(); } @@ -1458,11 +1427,11 @@ double compute_inner_product( const Persistence_landscape& l1 , const Persistenc { //in this case, we increment both: ++l2It; - if ( dbg ){cerr << "Incrementing both \n";} + if ( dbg ){std::cerr << "Incrementing both \n";} } else { - if ( dbg ){cerr << "Incrementing first \n";} + if ( dbg ){std::cerr << "Incrementing first \n";} } ++l1It; } @@ -1470,7 +1439,7 @@ double compute_inner_product( const Persistence_landscape& l1 , const Persistenc { //in this case we increment l2It ++l2It; - if ( dbg ){cerr << "Incrementing second \n";} + if ( dbg ){std::cerr << "Incrementing second \n";} } //Now, we shift x1 and x2: x1 = x2; @@ -1493,7 +1462,7 @@ double compute_inner_product( const Persistence_landscape& l1 , const Persistenc void Persistence_landscape::plot( const char* filename, double xRangeBegin , double xRangeEnd , double yRangeBegin , double yRangeEnd , int from , int to ) { //this program create a gnuplot script file that allows to plot persistence diagram. - ofstream out; + std::ofstream out; std::ostringstream nameSS; nameSS << filename << "_GnuplotScript"; @@ -1502,8 +1471,8 @@ void Persistence_landscape::plot( const char* filename, double xRangeBegin , do if ( (xRangeBegin != -1) || (xRangeEnd != -1) || (yRangeBegin != -1) || (yRangeEnd != -1) ) { - out << "set xrange [" << xRangeBegin << " : " << xRangeEnd << "]" << endl; - out << "set yrange [" << yRangeBegin << " : " << yRangeEnd << "]" << endl; + out << "set xrange [" << xRangeBegin << " : " << xRangeEnd << "]" << std::endl; + out << "set yrange [" << yRangeBegin << " : " << yRangeEnd << "]" << std::endl; } if ( from == -1 ){from = 0;} @@ -1518,18 +1487,18 @@ void Persistence_landscape::plot( const char* filename, double xRangeBegin , do { out << ", \\"; } - out << endl; + out << std::endl; } for ( size_t lambda= std::min((size_t)from,this->land.size()) ; lambda != std::min((size_t)to,this->land.size()) ; ++lambda ) { for ( size_t i = 1 ; i != this->land[lambda].size()-1 ; ++i ) { - out << this->land[lambda][i].first << " " << this->land[lambda][i].second << endl; + out << this->land[lambda][i].first << " " << this->land[lambda][i].second << std::endl; } - out << "EOF" << endl; + out << "EOF" << std::endl; } - cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << endl; + std::cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << std::endl; } diff --git a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape_on_grid.h b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape_on_grid.h index 6ac4deca..be60f858 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape_on_grid.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/Persistence_landscape_on_grid.h @@ -1,7 +1,7 @@ /* This file is part of the Gudhi Library. The Gudhi library * (Geometric Understanding in Higher Dimensions) is a generic C++ * library for computational topology. - * + *h * Author(s): Pawel Dlotko * * Copyright (C) 2015 INRIA (France) @@ -37,14 +37,11 @@ //gudhi include -#include +#include #include -using namespace std; - - namespace Gudhi { namespace Gudhi_stat @@ -68,17 +65,7 @@ public: * Constructor that takes as an input a vector of birth-death pairs. **/ Persistence_landscape_on_grid( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_ ); - - /** - * Assignement operator. - **/ - Persistence_landscape_on_grid& operator=( const Persistence_landscape_on_grid& org ); - - /** - * Copy constructor. - **/ - Persistence_landscape_on_grid(const Persistence_landscape_on_grid&); - + /** * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. The additional parameters of this procedure are: ranges of grid, resoltion of a grid @@ -133,9 +120,9 @@ public: if ( dbg ) { - cerr << "this->grid_max : " << this->grid_max << endl; - cerr << "this->grid_min : " << this->grid_min << endl; - cerr << "this->values_of_landscapes.size() : " << this->values_of_landscapes.size() << endl; + std::cerr << "this->grid_max : " << this->grid_max << std::endl; + std::cerr << "this->grid_min : " << this->grid_min << std::endl; + std::cerr << "this->values_of_landscapes.size() : " << this->values_of_landscapes.size() << std::endl; getchar(); } @@ -150,12 +137,12 @@ public: if ( dbg ) { - cerr << "this->values_of_landscapes[i].size() : " << this->values_of_landscapes[i].size() << " , level : " << level << endl; - if ( this->values_of_landscapes[i].size() > level )cerr << "this->values_of_landscapes[i][level] : " << this->values_of_landscapes[i][level] << endl; - cerr << "previous_y : " << previous_y << endl; - cerr << "current_y : " << current_y << endl; - cerr << "dx : " << dx << endl; - cerr << "0.5*dx*( previous_y + current_y ); " << 0.5*dx*( previous_y + current_y ) << endl; + std::cerr << "this->values_of_landscapes[i].size() : " << this->values_of_landscapes[i].size() << " , level : " << level << std::endl; + if ( this->values_of_landscapes[i].size() > level )std::cerr << "this->values_of_landscapes[i][level] : " << this->values_of_landscapes[i][level] << std::endl; + std::cerr << "previous_y : " << previous_y << std::endl; + std::cerr << "current_y : " << current_y << std::endl; + std::cerr << "dx : " << dx << std::endl; + std::cerr << "0.5*dx*( previous_y + current_y ); " << 0.5*dx*( previous_y + current_y ) << std::endl; } result += 0.5*dx*( previous_y + current_y ); @@ -194,10 +181,10 @@ public: if ( dbg ) { - cerr << "dx : " << dx << endl; - cerr << "previous_x : " << previous_x << endl; - cerr << "previous_y : " << previous_y << endl; - cerr << "power : " << p << endl; + std::cerr << "dx : " << dx << std::endl; + std::cerr << "previous_x : " << previous_x << std::endl; + std::cerr << "previous_y : " << previous_y << std::endl; + std::cerr << "power : " << p << std::endl; getchar(); } @@ -207,7 +194,7 @@ public: double current_y = 0; if ( this->values_of_landscapes[i].size() > level )current_y = this->values_of_landscapes[i][level]; - if ( dbg )cerr << "current_y : " << current_y << endl; + if ( dbg )std::cerr << "current_y : " << current_y << std::endl; if ( current_y == previous_y )continue; @@ -217,7 +204,7 @@ public: if ( dbg ) { - cerr << "A line passing through points : (" << previous_x << "," << previous_y << ") and (" << current_x << "," << current_y << ") is : " << a << "x+" << b << endl; + std::cerr << "A line passing through points : (" << previous_x << "," << previous_y << ") and (" << current_x << "," << current_y << ") is : " << a << "x+" << b << std::endl; } //In this interval, the landscape has a form f(x) = ax+b. We want to compute integral of (ax+b)^p = 1/a * (ax+b)^{p+1}/(p+1) @@ -233,14 +220,14 @@ public: result += value_to_add; if ( dbg ) { - cerr << "Increasing result by : " << value_to_add << endl; - cerr << "restult : " << result << endl; + std::cerr << "Increasing result by : " << value_to_add << std::endl; + std::cerr << "restult : " << result << std::endl; getchar(); } previous_x = current_x; previous_y = current_y; } - if ( dbg )cerr << "The total result is : " << result << endl; + if ( dbg )std::cerr << "The total result is : " << result << std::endl; return result; } @@ -259,7 +246,7 @@ public: { out << land.values_of_landscapes[i][j] << " "; } - out << endl; + out << std::endl; x += dx; } return out; @@ -282,9 +269,9 @@ public: if ( dbg ) { std::cerr << "This is a procedure compute_value_at_a_given_point \n"; - std::cerr << "level : " << level << endl; - std::cerr << "x : " << x << endl; - std::cerr << "psoition : " << position << endl; + std::cerr << "level : " << level << std::endl; + std::cerr << "x : " << x << std::endl; + std::cerr << "psoition : " << position << std::endl; } //check if we are not exacly in the grid point: if ( almost_equal( position*dx+ this->grid_min , x) ) @@ -430,17 +417,17 @@ public: bool dbg = true; if ( ! this->values_of_landscapes.size() == rhs.values_of_landscapes.size() ) { - if (dbg) cerr << "values_of_landscapes of incompatable sizes\n"; + if (dbg) std::cerr << "values_of_landscapes of incompatable sizes\n"; return false; } if ( !almost_equal( this->grid_min , rhs.grid_min ) ) { - if (dbg) cerr << "grid_min not equal\n"; + if (dbg) std::cerr << "grid_min not equal\n"; return false; } if ( !almost_equal(this->grid_max,rhs.grid_max ) ) { - if (dbg) cerr << "grid_max not equal\n"; + if (dbg) std::cerr << "grid_max not equal\n"; return false; } for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) @@ -451,8 +438,8 @@ public: { if (dbg) { - cerr << "Problem in the position : " << i << " of values_of_landscapes. \n"; - cerr << this->values_of_landscapes[i][aa] << " " << rhs.values_of_landscapes[i][aa] << endl; + std::cerr << "Problem in the position : " << i << " of values_of_landscapes. \n"; + std::cerr << this->values_of_landscapes[i][aa] << " " << rhs.values_of_landscapes[i][aa] << std::endl; } return false; } @@ -515,7 +502,7 @@ public: * This procedure returns x-range of a given level persistence landscape. If a default value is used, the x-range * of 0th level landscape is given (and this range contains the ranges of all other landscapes). **/ - std::pair< double , double > gimme_x_range( size_t level = 0 )const + std::pair< double , double > give_me_x_range( size_t level = 0 )const { return std::make_pair( this->grid_min , this->grid_max ); //std::pair< double , double > result; @@ -546,7 +533,7 @@ public: * This procedure returns y-range of a persistence landscape. If a default value is used, the y-range * of 0th level landscape is given (and this range contains the ranges of all other landscapes). **/ - std::pair< double , double > gimme_y_range( size_t level = 0 )const + std::pair< double , double > give_me_y_range( size_t level = 0 )const { return this->compute_minimum_maximum(); //std::pair< double , double > result; @@ -582,13 +569,13 @@ public: std::vector< std::pair< double , double > > p; Persistence_landscape_on_grid l(p,this->grid_min,this->grid_max,this->values_of_landscapes.size()-1); - if ( i != -1 ) + if ( i != std::numeric_limits::max() ) { - return compute_discance_of_landscapes_on_grid(*this,l,i); + return compute_distance_of_landscapes_on_grid(*this,l,i); } else { - return compute_max_norm_discance_of_landscapes(*this,l); + return compute_max_norm_distance_of_landscapes(*this,l); } } @@ -600,8 +587,8 @@ public: /** * Computations of L^{\infty} distance between two landscapes. **/ - friend double compute_max_norm_discance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second ); - //friend double compute_max_norm_discance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second , unsigned& nrOfLand , double&x , double& y1, double& y2 ); + friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second ); + //friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second , unsigned& nrOfLand , double&x , double& y1, double& y2 ); @@ -611,8 +598,7 @@ public: * them. In this case, a general PL-function with negative value can appear as a result. Then in order to compute distance, we need to take its absolute value. This is the purpose of this procedure. **/ void abs() - { - //Be careful here. We assume that the functions are either entirely positive or negative. They do not change signs. That is why I can implemnt abs in the way presented below: + { for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) { for ( size_t j = 0 ; j != this->values_of_landscapes[i].size() ; ++j ) @@ -748,15 +734,15 @@ public: /** * Computations of L^{p} distance between two landscapes on a grid. p is the parameter of the procedure. **/ - friend double compute_discance_of_landscapes_on_grid( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second , int p ) + friend double compute_distance_of_landscapes_on_grid( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second , double p ) { bool dbg = false; //This is what we want to compute: (\int_{- \infty}^{+\infty}| first-second |^p)^(1/p). We will do it one step at a time: if ( dbg ) { - cerr << "first : " << first << endl; - cerr << "second : " << second << endl; + std::cerr << "first : " << first << std::endl; + std::cerr << "second : " << second << std::endl; getchar(); } @@ -765,7 +751,7 @@ public: if ( dbg ) { - cerr << "Difference : " << lan << endl; + std::cerr << "Difference : " << lan << std::endl; } //| first-second |: @@ -773,30 +759,30 @@ public: if ( dbg ) { - cerr << "Abs : " << lan << endl; + std::cerr << "Abs : " << lan << std::endl; } - if ( p != -1 ) + if ( p != std::numeric_limits< double >::max() ) { //\int_{- \infty}^{+\infty}| first-second |^p double result; if ( p != 1 ) { - if (dbg){cerr << "p : " << p << endl; getchar();} + if (dbg){std::cerr << "p : " << p << std::endl; getchar();} result = lan.compute_integral_of_landscape( (double)p ); - if (dbg){cerr << "integral : " << result << endl;getchar();} + if (dbg){std::cerr << "integral : " << result << std::endl;getchar();} } else { result = lan.compute_integral_of_landscape(); - if (dbg){cerr << "integral, wihtout power : " << result << endl;getchar();} + if (dbg){std::cerr << "integral, wihtout power : " << result << std::endl;getchar();} } //(\int_{- \infty}^{+\infty}| first-second |^p)^(1/p) return pow( result , 1/(double)p ); } else { - //p == -1 + //p == infty return lan.compute_maximum(); } } @@ -898,44 +884,44 @@ public: //now we need to check if the grids in all objects of to_average are the same: for ( size_t i = 0 ; i != to_average.size() ; ++i ) { - if ( !check_if_defined_on_the_same_domain(*((Persistence_landscape_on_grid*)(to_average[0])),*((Persistence_landscape_on_grid*)(to_average[i]))) )throw "Two grids are not compatible"; + if ( !check_if_defined_on_the_same_domain(*(to_average[0]),*(to_average[i])) )throw "Two grids are not compatible"; } - this->values_of_landscapes = std::vector< std::vector >( ((Persistence_landscape_on_grid*)(to_average[0]))->values_of_landscapes.size() ); - this->grid_min = ((Persistence_landscape_on_grid*)(to_average[0]))->grid_min; - this->grid_max = ((Persistence_landscape_on_grid*)(to_average[0]))->grid_max; + this->values_of_landscapes = std::vector< std::vector >( (to_average[0])->values_of_landscapes.size() ); + this->grid_min = (to_average[0])->grid_min; + this->grid_max = (to_average[0])->grid_max; if ( dbg ) { - cerr << "Computations of average. The data from the current landscape have been cleared. We are ready to do the computations. \n"; + std::cerr << "Computations of average. The data from the current landscape have been cleared. We are ready to do the computations. \n"; } //for every point in the grid: - for ( size_t grid_point = 0 ; grid_point != ((Persistence_landscape_on_grid*)(to_average[0]))->values_of_landscapes.size() ; ++grid_point ) + for ( size_t grid_point = 0 ; grid_point != (to_average[0])->values_of_landscapes.size() ; ++grid_point ) { //set up a vector of the correct size: size_t maximal_size_of_vector = 0; for ( size_t land_no = 0 ; land_no != to_average.size() ; ++land_no ) { - if ( ((Persistence_landscape_on_grid*)(to_average[land_no]))->values_of_landscapes[grid_point].size() > maximal_size_of_vector ) - maximal_size_of_vector = ((Persistence_landscape_on_grid*)(to_average[land_no]))->values_of_landscapes[grid_point].size(); + if ( (to_average[land_no])->values_of_landscapes[grid_point].size() > maximal_size_of_vector ) + maximal_size_of_vector = (to_average[land_no])->values_of_landscapes[grid_point].size(); } this->values_of_landscapes[grid_point] = std::vector( maximal_size_of_vector ); if ( dbg ) { - cerr << "We are considering the point : " << grid_point << " of the grid. In this point, there are at most : " << maximal_size_of_vector << " nonzero landscape functions \n"; + std::cerr << "We are considering the point : " << grid_point << " of the grid. In this point, there are at most : " << maximal_size_of_vector << " nonzero landscape functions \n"; } //and compute an arythmetic average: for ( size_t land_no = 0 ; land_no != to_average.size() ; ++land_no ) { //summing: - for ( size_t i = 0 ; i != ((Persistence_landscape_on_grid*)(to_average[land_no]))->values_of_landscapes[grid_point].size() ; ++i ) + for ( size_t i = 0 ; i != (to_average[land_no])->values_of_landscapes[grid_point].size() ; ++i ) { //compute the average in a smarter way. - this->values_of_landscapes[grid_point][i] += ((Persistence_landscape_on_grid*)(to_average[land_no]))->values_of_landscapes[grid_point][i]; + this->values_of_landscapes[grid_point][i] += (to_average[land_no])->values_of_landscapes[grid_point][i]; } } //normalizing: @@ -951,16 +937,17 @@ public: * A function to compute distance between persistence landscape on a grid. * The parameter of this functionis a Persistence_landscape_on_grid. * This function is required in Topological_data_with_distances concept. + * For max norm distance, set power to std::numeric_limits::max() **/ double distance( const Persistence_landscape_on_grid& second , double power = 1 )const { - if ( power != -1 ) + if ( power != std::numeric_limits::max() ) { - return compute_discance_of_landscapes_on_grid( *this , second , power ); + return compute_distance_of_landscapes_on_grid( *this , second , power ); } else { - return compute_max_norm_discance_of_landscapes( *this , second ); + return compute_max_norm_distance_of_landscapes( *this , second ); } } @@ -1008,7 +995,7 @@ public: **/ void plot( const char* filename , size_t from_ , size_t to_ )const { - this->plot( filename , from_ , to_ ); + this->plot( filename , -1 , -1 , -1 , -1 , from_ , to_ ); } /** @@ -1042,12 +1029,12 @@ void Persistence_landscape_on_grid::set_up_values_of_landscapes( const std::vect bool dbg = false; if ( dbg ) { - std::cerr << "Here is the procedure : set_up_values_of_landscapes. The parameters are : grid_min_ : " << grid_min_ << ", grid_max_ : " << grid_max_ << ", number_of_points_ : " << number_of_points_ << endl; + std::cerr << "Here is the procedure : set_up_values_of_landscapes. The parameters are : grid_min_ : " << grid_min_ << ", grid_max_ : " << grid_max_ << ", number_of_points_ : " << number_of_points_ << std::endl; //getchar(); std::cerr << "Here are the intervals at our disposal : \n"; for ( size_t i = 0 ; i != p.size() ; ++i ) { - std::cerr << p[i].first << " , " << p[i].second << endl; + std::cerr << p[i].first << " , " << p[i].second << std::endl; } } @@ -1075,7 +1062,7 @@ void Persistence_landscape_on_grid::set_up_values_of_landscapes( const std::vect if ( dbg ) { - cerr << "Considering an interval : " << p[int_no].first << "," << p[int_no].second << endl; + std::cerr << "Considering an interval : " << p[int_no].first << "," << p[int_no].second << std::endl; std::cerr << "grid_interval_begin : " << grid_interval_begin << std::endl; std::cerr << "grid_interval_end : " << grid_interval_end << std::endl; @@ -1118,20 +1105,6 @@ Persistence_landscape_on_grid::Persistence_landscape_on_grid( const std::vector< this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ ); }//Persistence_landscape_on_grid -Persistence_landscape_on_grid& Persistence_landscape_on_grid::operator=( const Persistence_landscape_on_grid& org ) -{ - this->grid_min = org.grid_min; - this->grid_max = org.grid_max; - this->values_of_landscapes = org.values_of_landscapes; - return (*this); -}//operator= - -Persistence_landscape_on_grid::Persistence_landscape_on_grid(const Persistence_landscape_on_grid& org) -{ - this->grid_min = org.grid_min; - this->grid_max = org.grid_max; - this->values_of_landscapes = org.values_of_landscapes; -}//copy constructor Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename , double grid_min_, double grid_max_ , size_t number_of_points_ , size_t dimension ) { @@ -1165,7 +1138,7 @@ void Persistence_landscape_on_grid::load_landscape_from_file( const char* filena //check if the file exist. if ( !( access( filename, F_OK ) != -1 ) ) { - cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; } std::ifstream in; @@ -1183,7 +1156,7 @@ void Persistence_landscape_on_grid::load_landscape_from_file( const char* filena //read a line of a file and convert it to a vector. std::vector< double > vv; std::getline(in, line); - //cerr << "Reading line : " << line << endl;getchar(); + //std::cerr << "Reading line : " << line << std::endl;getchar(); std::istringstream stream(line); while (stream >> number) { @@ -1219,7 +1192,7 @@ void Persistence_landscape_on_grid::print_to_file( const char* filename )const void Persistence_landscape_on_grid::plot( const char* filename, double min_x , double max_x , double min_y , double max_y, size_t from_ , size_t to_ )const { //this program create a gnuplot script file that allows to plot persistence diagram. - ofstream out; + std::ofstream out; std::ostringstream nameSS; nameSS << filename << "_GnuplotScript"; @@ -1229,13 +1202,13 @@ void Persistence_landscape_on_grid::plot( const char* filename, double min_x , d if ( min_x == max_x ) { std::pair min_max = compute_minimum_maximum(); - out << "set xrange [" << this->grid_min << " : " << this->grid_max << "]" << endl; - out << "set yrange [" << min_max.first << " : " << min_max.second << "]" << endl; + out << "set xrange [" << this->grid_min << " : " << this->grid_max << "]" << std::endl; + out << "set yrange [" << min_max.first << " : " << min_max.second << "]" << std::endl; } else { - out << "set xrange [" << min_x << " : " << max_x << "]" << endl; - out << "set yrange [" << min_y << " : " << max_y << "]" << endl; + out << "set xrange [" << min_x << " : " << max_x << "]" << std::endl; + out << "set yrange [" << min_y << " : " << max_y << "]" << std::endl; } size_t number_of_nonzero_levels = this->number_of_nonzero_levels(); @@ -1273,7 +1246,7 @@ void Persistence_landscape_on_grid::plot( const char* filename, double min_x , d { out << ", \\"; } - out << endl; + out << std::endl; } for ( size_t lambda = from ; lambda != to ; ++lambda ) @@ -1286,12 +1259,12 @@ void Persistence_landscape_on_grid::plot( const char* filename, double min_x , d { value = this->values_of_landscapes[i][lambda]; } - out << point << " " << value << endl; + out << point << " " << value << std::endl; point += dx; } - out << "EOF" << endl; + out << "EOF" << std::endl; } - cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << endl; + std::cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << std::endl; } template < typename T > @@ -1342,7 +1315,7 @@ Persistence_landscape_on_grid Persistence_landscape_on_grid::multiply_lanscape_b return result; } -double compute_max_norm_discance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second ) +double compute_max_norm_distance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second ) { double result = 0; diff --git a/src/Gudhi_stat/include/gudhi/concretizations/Vector_distances_in_diagram.h b/src/Gudhi_stat/include/gudhi/concretizations/Vector_distances_in_diagram.h index 11e4b163..dc1df0c6 100644 --- a/src/Gudhi_stat/include/gudhi/concretizations/Vector_distances_in_diagram.h +++ b/src/Gudhi_stat/include/gudhi/concretizations/Vector_distances_in_diagram.h @@ -31,10 +31,9 @@ #include //gudhi include -#include +#include #include -using namespace std; namespace Gudhi { @@ -104,22 +103,12 @@ public: **/ Vector_distances_in_diagram( const char* filename , size_t where_to_cut ); - /** - * Assignement operator. - **/ - Vector_distances_in_diagram& operator =( const Vector_distances_in_diagram& org ); - - - /** - * Copy constructor. - **/ - Vector_distances_in_diagram( const Vector_distances_in_diagram& org ); /** * Writing to a stream. **/ template - friend ostream& operator << ( ostream& out , const Vector_distances_in_diagram& d ) + friend std::ostream& operator << ( std::ostream& out , const Vector_distances_in_diagram& d ) { for ( size_t i = 0 ; i != std::min( d.sorted_vector_of_distances.size() , d.where_to_cut) ; ++i ) { @@ -213,6 +202,7 @@ public: /** * Compute a distance of two persistent vectors. This function is required in Topological_data_with_distances concept. + * For max norm distance, set power to std::numeric_limits::max() **/ double distance( const Vector_distances_in_diagram& second , double power = 1)const; @@ -255,7 +245,7 @@ public: { std::stringstream gnuplot_script; gnuplot_script << filename << "_GnuplotScript"; - ofstream out; + std::ofstream out; out.open( gnuplot_script.str().c_str() ); out << "set style data histogram" << std::endl; out << "set style histogram cluster gap 1" << std::endl; @@ -265,7 +255,7 @@ public: { out << this->sorted_vector_of_distances[i] << std::endl; } - out << endl; + out < gimme_x_range()const + std::pair< double , double > give_me_x_range()const { return std::make_pair( 0 , this->sorted_vector_of_distances.size() ); } @@ -281,7 +271,7 @@ public: /** * The y-range of the persistence vector. **/ - std::pair< double , double > gimme_y_range()const + std::pair< double , double > give_me_y_range()const { if ( this->sorted_vector_of_distances.size() == 0 )return std::make_pair(0,0); return std::make_pair( this->sorted_vector_of_distances[0] , 0); @@ -440,28 +430,6 @@ Vector_distances_in_diagram::Vector_distances_in_diagram( const std::vector< this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); } -template -Vector_distances_in_diagram::Vector_distances_in_diagram( const Vector_distances_in_diagram& org ) -{ - std::vector< std::pair< double,double > > inter( org.intervals ); - this->intervals = inter; - std::vector< double > sorted_vector_of_distances( org.sorted_vector_of_distances ); - this->sorted_vector_of_distances = sorted_vector_of_distances; - set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); -} - - -template -Vector_distances_in_diagram& Vector_distances_in_diagram::operator =( const Vector_distances_in_diagram& org ) -{ - std::vector< std::pair< double , double > > inter( org.intervals ); - this->intervals = inter; - std::vector< double > sorted_vector_of_distances( org.sorted_vector_of_distances ); - this->sorted_vector_of_distances = sorted_vector_of_distances; - return *this; -} - - template Vector_distances_in_diagram::Vector_distances_in_diagram( const char* filename , size_t where_to_cut ):where_to_cut(where_to_cut) { @@ -483,10 +451,10 @@ void Vector_distances_in_diagram::compute_sorted_vector_of_distances_via_heap bool dbg = false; if ( dbg ) { - cerr << "Here are the intervals : \n"; + std::cerr << "Here are the intervals : \n"; for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) { - cerr << this->intervals[i].first << " , " << this->intervals[i].second << endl; + std::cerr << this->intervals[i].first << " , " << this->intervals[i].second <intervals.size() * ( this->intervals.size() - 1 ) + this->intervals.size())); @@ -510,14 +478,14 @@ void Vector_distances_in_diagram::compute_sorted_vector_of_distances_via_heap if ( dbg ) { - cerr << "Value : " << value << endl; - cerr << "heap.front() : " << heap.front() << endl; + std::cerr << "Value : " << value <::compute_sorted_vector_of_distances_via_heap double value = f( this->intervals[i] , std::make_pair( 0.5*(this->intervals[i].first+this->intervals[i].second) , 0.5*(this->intervals[i].first+this->intervals[i].second) ) ); if ( -value < heap.front() ) { - //cerr << "Replacing : " << heap.front() << " with : " << -value << endl;getchar(); + //std::cerr << "Replacing : " << heap.front() << " with : " << -value <::compute_sorted_vector_of_distances_via_heap { std::cout << heap[i] << " "; } - std::cout << endl; + std::cout <sorted_vector_of_distances = heap; @@ -681,16 +649,24 @@ double Vector_distances_in_diagram::distance( const Vector_distances_in_diagr { if ( dbg ) { - cerr << "|" << this->sorted_vector_of_distances[i] << " - " << second_.sorted_vector_of_distances[i] << " | : " << fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) << endl; + std::cerr << "|" << this->sorted_vector_of_distances[i] << " - " << second_.sorted_vector_of_distances[i] << " | : " << fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) <sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ); } else { - result += std::pow( fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) , power ); + if ( power != std::numeric_limits::max() ) + { + result += std::pow( fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) , power ); + } + else + { + //nax morm + if ( result < fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) )result = fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ); + } if ( dbg ) { - cerr << "| " << this->sorted_vector_of_distances[i] << " - " << second_.sorted_vector_of_distances[i] << " : " << fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) << endl; + std::cerr << "| " << this->sorted_vector_of_distances[i] << " - " << second_.sorted_vector_of_distances[i] << " : " << fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) <::load_from_file( const char* filename ) //check if the file exist. if ( !( access( filename, F_OK ) != -1 ) ) { - cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; } std::ifstream in; diff --git a/src/Gudhi_stat/include/gudhi/concretizations/read_persitence_from_file.h b/src/Gudhi_stat/include/gudhi/concretizations/read_persitence_from_file.h deleted file mode 100644 index e16c1f20..00000000 --- a/src/Gudhi_stat/include/gudhi/concretizations/read_persitence_from_file.h +++ /dev/null @@ -1,300 +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 (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 Read_Persitence_From_File_H -#define Read_Persitence_From_File_H - -#include -#include -#include -#include -#include -#include - - -namespace Gudhi -{ -namespace Gudhi_stat -{ - - -/** - * This procedure reads birth-death dagta from a file. We assume that in the file, there may be one type of string 'inf' or 'Inf'. If the second parameter of the program is set to -1, - * then those vales are ignored. If the second parameter of this program is set to a positive value, then the infinite intervals will be substituted by that number. -**/ -std::vector< std::pair< double,double > > read_file_names_that_may_contain_inf_string( char* filename , double what_to_substitute_for_infinite_bar = -1 ) -{ - - bool dbg = true; - - if ( !( access( filename, F_OK ) != -1 ) ) - { - std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; - throw "The file from which you are trying to read do not exist. The program will now terminate \n"; - } - - std::string line; - std::vector< std::pair > barcode; - - std::ifstream in; - in.open( filename ); - while (!in.eof()) - { - getline(in,line); - if ( !(line.length() == 0 || line[0] == '#') ) - { - std::stringstream lineSS; - lineSS << line; - double beginn, endd; - if ( (line.find("inf") != std::string::npos) || (line.find("Inf") != std::string::npos) ) - { - if ( dbg ) - { - std::cerr << "This line: " << line << " contains infinite interval. We will skip it. \n"; - } - if ( what_to_substitute_for_infinite_bar != -1 ) - { - lineSS >> beginn; - endd = what_to_substitute_for_infinite_bar; - } - else - { - continue; - } - } - else - { - lineSS >> beginn; - lineSS >> endd; - } - if ( beginn > endd ) - { - double b = beginn; - beginn = endd; - endd = b; - } - if ( dbg ) - { - std::cerr << "Getting an interval : " << beginn << "," << endd << std::endl; - } - barcode.push_back( std::make_pair( beginn , endd ) ); - } - } - return barcode; -}//readFileNames - - -/** - * This procedure reads names of files which are stored in a file. -**/ -std::vector< std::string > readFileNames( const char* filenameWithFilenames ) -{ - bool dbg = false; - - if ( !( access( filenameWithFilenames, F_OK ) != -1 ) ) - { - std::cerr << "The file : " << filenameWithFilenames << " do not exist. The program will now terminate \n"; - throw "The file from which you are trying to read do not exist. The program will now terminate \n"; - } - - std::vector< std::string > result; - std::ifstream in; - in.open( filenameWithFilenames ); - std::string line; - while (!in.eof()) - { - getline(in,line); - line.erase( std::remove_if( line.begin(), line.end(), ::isspace) , line.end() ); - - if (dbg){std::cerr << "line : " << line << std::endl;} - - if ( (line.length() == 0) || (line[0] == '#') ) - { - //in this case we have a file name. First we should remove all the white spaces. - if ( dbg ){std::cerr << "This is a line with comment, it will be ignored n";} - } - else - { - result.push_back( line.c_str() ); - if (dbg){std::cerr << "Line after removing white spaces : " << line << std::endl;} - } - } - in.close(); - - return result; -}//readFileNames - - -/** - * This method reads persistence from standalone file. The format of the file is as follows: - * In every line there are two numbers which denotes birth and death of a persistence interval. The file is not supposed to contains any nonwhite characters excet from digits. In particular symbols - * like 'inf' are not allowed. - * If begin of the interval is greater than the end of the interval, those two numbers are swapped. -**/ -std::vector< std::pair< double , double > > read_standard_file( const char* filename ) -{ - bool dbg = false; - - std::ifstream in; - in.open( filename ); - if ( !( access( filename, F_OK ) != -1 ) ) - { - std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; - throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; - } - - std::string line; - std::vector< std::pair > barcode; - - while (!in.eof()) - { - getline(in,line); - if ( !(line.length() == 0 || line[0] == '#') ) - { - std::stringstream lineSS; - lineSS << line; - double beginn, endd; - lineSS >> beginn; - lineSS >> endd; - if ( beginn == endd )continue; - if ( beginn > endd ) - { - double b = beginn; - beginn = endd; - endd = b; - } - barcode.push_back( std::make_pair( beginn , endd ) ); - if (dbg) - { - std::cerr << beginn << " , " << endd << std::endl; - } - } - } - in.close(); - return barcode; -}//read_standard_file - - - -/** - * This procedure reads Gudhi style file. The format of a Gudhi style file is as follows: - * Each line consist of the following information: - * A prime number p indicating that the class is nontrivial over Z_p field. - * A positive numebr, being a dimension of a persistence class - * A birth and a death time of a class. - * Death time may be infitnity, in which case a string 'inf' is used. - * If begin of the interval is greater than the end of the interval, those two numbers are swapped. -**/ -std::vector< std::pair< double , double > > read_gudhi_file( const char* filename , size_t dimension = 0 ) -{ - bool dbg = false; - std::ifstream in; - in.open( filename ); - - std::string line; - std::vector< std::pair > barcode; - - while (!in.eof()) - { - getline(in,line); - if ( !(line.length() == 0 || line[0] == '#') ) - { - if ( line.find("inf") != std::string::npos ) - { - if ( dbg ) - { - std::cerr << "This line: " << line << " contains infinite interval. We will skip it. \n"; - } - continue; - } - std::stringstream lineSS; - lineSS << line; - double beginn, endd, field, dim; - lineSS >> field; - lineSS >> dim; - lineSS >> beginn; - lineSS >> endd; - if ( beginn > endd ) - { - double b = beginn; - beginn = endd; - endd = b; - } - if ( dim == dimension ) - { - barcode.push_back( std::make_pair( beginn , endd ) ); - if (dbg) - { - std::cerr << beginn << " , " << endd << std::endl; - } - } - } - } - in.close(); - return barcode; -}//read_gudhi_file - - -std::vector< std::vector< double > > read_numbers_from_file_line_by_line( const char* filename ) -{ - bool dbg = false; - if ( !( access( filename, F_OK ) != -1 ) ) - { - std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; - throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; - } - - std::vector< std::vector< double > > result; - double number; - - std::ifstream in(filename); - std::string line; - while ( in.good() ) - { - std::getline(in,line); - std::stringstream ss; - ss << line; - - if ( dbg )std::cerr << "\n Reading line : " << line << std::endl; - - std::vector< double > this_line; - while ( ss.good() ) - { - ss >> number; - this_line.push_back( number ); - if ( dbg )std::cerr << number << " "; - } - if ( this_line.size() && in.good() ) result.push_back( this_line ); - } - in.close(); - - return result; -}//read_numbers_from_file_line_by_line - -}//namespace Gudhi_stat -}//namespace Gudhi - - - - -#endif diff --git a/src/Gudhi_stat/include/gudhi/fill_in_missing_data.h b/src/Gudhi_stat/include/gudhi/fill_in_missing_data.h index eb948438..d6ae6fe1 100644 --- a/src/Gudhi_stat/include/gudhi/fill_in_missing_data.h +++ b/src/Gudhi_stat/include/gudhi/fill_in_missing_data.h @@ -23,6 +23,11 @@ #ifndef FILL_IN_MISSING_DATA_H #define FILL_IN_MISSING_DATA_H +namespace Gudhi +{ +namespace Gudhi_stat +{ + /** * Quite often in biological sciences we are facing a problem of missing data. We may have for instance a number of sequences of observations made in between times A and B in a discrete * collection of times A = t1, t2,...,tn = B. But quite typically some of the observations may be missing. Then quite often it is hard to estimate the values in the missing times. @@ -133,4 +138,7 @@ void fill_in_missing_data( std::vector< Representation_of_topology* >& data , st } }//fill_in_missing_data +}//namespace Gudhi_stat +}//namespace Gudhi + #endif diff --git a/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h b/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h index daac8f2a..627923fe 100644 --- a/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h +++ b/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h @@ -39,6 +39,11 @@ #include #include +namespace Gudhi +{ +namespace Gudhi_stat +{ + template < typename TopologicalObject > class difference_of_objects { @@ -138,6 +143,9 @@ double multiplicative_bootstrap( const std::vector< TopologicalObject* >& topolo return result; -}//bootstrap +}//multiplicative_bootstrap + +}//namespace Gudhi_stat +}//namespace Gudhi #endif diff --git a/src/Gudhi_stat/include/gudhi/permutation_test.h b/src/Gudhi_stat/include/gudhi/permutation_test.h index 7f8f7552..fa31c3c0 100644 --- a/src/Gudhi_stat/include/gudhi/permutation_test.h +++ b/src/Gudhi_stat/include/gudhi/permutation_test.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include using namespace std; diff --git a/src/Gudhi_stat/include/gudhi/read_persitence_from_file.h b/src/Gudhi_stat/include/gudhi/read_persitence_from_file.h new file mode 100644 index 00000000..e16c1f20 --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/read_persitence_from_file.h @@ -0,0 +1,300 @@ +/* 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 (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 Read_Persitence_From_File_H +#define Read_Persitence_From_File_H + +#include +#include +#include +#include +#include +#include + + +namespace Gudhi +{ +namespace Gudhi_stat +{ + + +/** + * This procedure reads birth-death dagta from a file. We assume that in the file, there may be one type of string 'inf' or 'Inf'. If the second parameter of the program is set to -1, + * then those vales are ignored. If the second parameter of this program is set to a positive value, then the infinite intervals will be substituted by that number. +**/ +std::vector< std::pair< double,double > > read_file_names_that_may_contain_inf_string( char* filename , double what_to_substitute_for_infinite_bar = -1 ) +{ + + bool dbg = true; + + if ( !( access( filename, F_OK ) != -1 ) ) + { + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + throw "The file from which you are trying to read do not exist. The program will now terminate \n"; + } + + std::string line; + std::vector< std::pair > barcode; + + std::ifstream in; + in.open( filename ); + while (!in.eof()) + { + getline(in,line); + if ( !(line.length() == 0 || line[0] == '#') ) + { + std::stringstream lineSS; + lineSS << line; + double beginn, endd; + if ( (line.find("inf") != std::string::npos) || (line.find("Inf") != std::string::npos) ) + { + if ( dbg ) + { + std::cerr << "This line: " << line << " contains infinite interval. We will skip it. \n"; + } + if ( what_to_substitute_for_infinite_bar != -1 ) + { + lineSS >> beginn; + endd = what_to_substitute_for_infinite_bar; + } + else + { + continue; + } + } + else + { + lineSS >> beginn; + lineSS >> endd; + } + if ( beginn > endd ) + { + double b = beginn; + beginn = endd; + endd = b; + } + if ( dbg ) + { + std::cerr << "Getting an interval : " << beginn << "," << endd << std::endl; + } + barcode.push_back( std::make_pair( beginn , endd ) ); + } + } + return barcode; +}//readFileNames + + +/** + * This procedure reads names of files which are stored in a file. +**/ +std::vector< std::string > readFileNames( const char* filenameWithFilenames ) +{ + bool dbg = false; + + if ( !( access( filenameWithFilenames, F_OK ) != -1 ) ) + { + std::cerr << "The file : " << filenameWithFilenames << " do not exist. The program will now terminate \n"; + throw "The file from which you are trying to read do not exist. The program will now terminate \n"; + } + + std::vector< std::string > result; + std::ifstream in; + in.open( filenameWithFilenames ); + std::string line; + while (!in.eof()) + { + getline(in,line); + line.erase( std::remove_if( line.begin(), line.end(), ::isspace) , line.end() ); + + if (dbg){std::cerr << "line : " << line << std::endl;} + + if ( (line.length() == 0) || (line[0] == '#') ) + { + //in this case we have a file name. First we should remove all the white spaces. + if ( dbg ){std::cerr << "This is a line with comment, it will be ignored n";} + } + else + { + result.push_back( line.c_str() ); + if (dbg){std::cerr << "Line after removing white spaces : " << line << std::endl;} + } + } + in.close(); + + return result; +}//readFileNames + + +/** + * This method reads persistence from standalone file. The format of the file is as follows: + * In every line there are two numbers which denotes birth and death of a persistence interval. The file is not supposed to contains any nonwhite characters excet from digits. In particular symbols + * like 'inf' are not allowed. + * If begin of the interval is greater than the end of the interval, those two numbers are swapped. +**/ +std::vector< std::pair< double , double > > read_standard_file( const char* filename ) +{ + bool dbg = false; + + std::ifstream in; + in.open( filename ); + if ( !( access( filename, F_OK ) != -1 ) ) + { + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; + } + + std::string line; + std::vector< std::pair > barcode; + + while (!in.eof()) + { + getline(in,line); + if ( !(line.length() == 0 || line[0] == '#') ) + { + std::stringstream lineSS; + lineSS << line; + double beginn, endd; + lineSS >> beginn; + lineSS >> endd; + if ( beginn == endd )continue; + if ( beginn > endd ) + { + double b = beginn; + beginn = endd; + endd = b; + } + barcode.push_back( std::make_pair( beginn , endd ) ); + if (dbg) + { + std::cerr << beginn << " , " << endd << std::endl; + } + } + } + in.close(); + return barcode; +}//read_standard_file + + + +/** + * This procedure reads Gudhi style file. The format of a Gudhi style file is as follows: + * Each line consist of the following information: + * A prime number p indicating that the class is nontrivial over Z_p field. + * A positive numebr, being a dimension of a persistence class + * A birth and a death time of a class. + * Death time may be infitnity, in which case a string 'inf' is used. + * If begin of the interval is greater than the end of the interval, those two numbers are swapped. +**/ +std::vector< std::pair< double , double > > read_gudhi_file( const char* filename , size_t dimension = 0 ) +{ + bool dbg = false; + std::ifstream in; + in.open( filename ); + + std::string line; + std::vector< std::pair > barcode; + + while (!in.eof()) + { + getline(in,line); + if ( !(line.length() == 0 || line[0] == '#') ) + { + if ( line.find("inf") != std::string::npos ) + { + if ( dbg ) + { + std::cerr << "This line: " << line << " contains infinite interval. We will skip it. \n"; + } + continue; + } + std::stringstream lineSS; + lineSS << line; + double beginn, endd, field, dim; + lineSS >> field; + lineSS >> dim; + lineSS >> beginn; + lineSS >> endd; + if ( beginn > endd ) + { + double b = beginn; + beginn = endd; + endd = b; + } + if ( dim == dimension ) + { + barcode.push_back( std::make_pair( beginn , endd ) ); + if (dbg) + { + std::cerr << beginn << " , " << endd << std::endl; + } + } + } + } + in.close(); + return barcode; +}//read_gudhi_file + + +std::vector< std::vector< double > > read_numbers_from_file_line_by_line( const char* filename ) +{ + bool dbg = false; + if ( !( access( filename, F_OK ) != -1 ) ) + { + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; + } + + std::vector< std::vector< double > > result; + double number; + + std::ifstream in(filename); + std::string line; + while ( in.good() ) + { + std::getline(in,line); + std::stringstream ss; + ss << line; + + if ( dbg )std::cerr << "\n Reading line : " << line << std::endl; + + std::vector< double > this_line; + while ( ss.good() ) + { + ss >> number; + this_line.push_back( number ); + if ( dbg )std::cerr << number << " "; + } + if ( this_line.size() && in.good() ) result.push_back( this_line ); + } + in.close(); + + return result; +}//read_numbers_from_file_line_by_line + +}//namespace Gudhi_stat +}//namespace Gudhi + + + + +#endif diff --git a/src/Gudhi_stat/include/gudhi/topological_process.h b/src/Gudhi_stat/include/gudhi/topological_process.h index e7bd46de..0cd8670a 100644 --- a/src/Gudhi_stat/include/gudhi/topological_process.h +++ b/src/Gudhi_stat/include/gudhi/topological_process.h @@ -218,22 +218,6 @@ public: delete this->data[i]; } } - Topological_process( const Topological_process& org ) - { - this->data = std::vector< Representation* >( org.data.size() ); - for ( size_t i = 0 ; i != org.data.size() ; ++i ) - { - this->data[i] = new Representation( *org.data[i] ); - } - } - Topological_process& operator = ( const Topological_process& rhs ) - { - for ( size_t i = 0 ; i != rhs.data.size() ; ++i ) - { - this->data[i] = new Representation( *rhs.data[i] ); - } - return *this; - } Topological_process( const std::vector< Representation* >& data_ ):data(data_){} double distance( const Topological_process& second , double exponent = 1 ) @@ -281,26 +265,26 @@ public: } } - std::pair< double , double > gimme_x_range()const + std::pair< double , double > give_me_x_range()const { double min_x = std::numeric_limits< double >::max(); double max_x = -std::numeric_limits< double >::max(); for ( size_t i = 0 ; i != this->data.size() ; ++i ) { - std::pair< double , double > xrange = this->data[i]->gimme_x_range(); + std::pair< double , double > xrange = this->data[i]->give_me_x_range(); if ( min_x > xrange.first )min_x = xrange.first; if ( max_x < xrange.second )max_x = xrange.second; } return std::make_pair( min_x , max_x ); } - std::pair< double , double > gimme_y_range()const + std::pair< double , double > give_me_y_range()const { double min_y = std::numeric_limits< double >::max(); double max_y = -std::numeric_limits< double >::max(); for ( size_t i = 0 ; i != this->data.size() ; ++i ) { - std::pair< double , double > yrange = this->data[i]->gimme_y_range(); + std::pair< double , double > yrange = this->data[i]->give_me_y_range(); if ( min_y > yrange.first )min_y = yrange.first; if ( max_y < yrange.second )max_y = yrange.second; } @@ -313,11 +297,11 @@ public: bool are_the_data_aligned()const { if ( this->data.size() == 0 )return true;//empty collection is aligned - std::pair< double , double > x_range = this->data[0]->gimme_x_range(); - std::pair< double , double > y_range = this->data[0]->gimme_y_range(); + std::pair< double , double > x_range = this->data[0]->give_me_x_range(); + std::pair< double , double > y_range = this->data[0]->give_me_y_range(); for ( size_t i = 1 ; i != this->data.size() ; ++i ) { - if ( (x_range != this->data[i]->gimme_x_range()) || (y_range != this->data[i]->gimme_y_range()) ) + if ( (x_range != this->data[i]->give_me_x_range()) || (y_range != this->data[i]->give_me_y_range()) ) { return false; } @@ -358,7 +342,7 @@ public: std::stringstream gif_gnuplot_script_file_name; gif_gnuplot_script_file_name << filename << "_gif_gnuplot_script"; - ofstream out; + std::ofstream out; out.open( gif_gnuplot_script_file_name.str().c_str() ); out << "set terminal gif animate delay " << delay << std::endl; out << "set output '" << gif_file_name.str() << "'" << std::endl; @@ -378,7 +362,7 @@ public: }//plot - std::vector< Representation* > gimme_data(){return this->data;} + std::vector< Representation* > give_me_data(){return this->data;} private: std::vector< Representation* > data; }; diff --git a/src/Gudhi_stat/test/persistence_heat_maps_test.cpp b/src/Gudhi_stat/test/persistence_heat_maps_test.cpp index d1f4da76..ccfc208b 100644 --- a/src/Gudhi_stat/test/persistence_heat_maps_test.cpp +++ b/src/Gudhi_stat/test/persistence_heat_maps_test.cpp @@ -59,13 +59,9 @@ BOOST_AUTO_TEST_CASE(check_averages_of_heat_maps) Persistence_heat_maps p( "data/file_with_diagram" , filter , false , 1000 , 0 , 10 ); Persistence_heat_maps q( "data/file_with_diagram_1" , filter , false , 1000 , 0 , 10 ); Persistence_heat_maps r( "data/file_with_diagram_2" , filter , false , 1000 , 0 , 10 ); - - std::vector< Persistence_heat_maps* > to_average; - to_average.push_back( &p ); - to_average.push_back( &q ); - to_average.push_back( &r ); + Persistence_heat_maps av; - av.compute_average( to_average ); + av.compute_average( {&p,&q,&r} ); Persistence_heat_maps template_average; template_average.load_from_file( "data/template_average_of_heat_maps" ); diff --git a/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp b/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp index 87ed0241..2e24f932 100644 --- a/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp +++ b/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp @@ -198,17 +198,17 @@ BOOST_AUTO_TEST_CASE(check_computations_of_maxima_and_norms) //cerr << p.compute_norm_of_landscape(1) << endl; //cerr << p.compute_norm_of_landscape(2) << endl; //cerr << p.compute_norm_of_landscape(3) << endl; - //cerr << compute_discance_of_landscapes_on_grid(p,sum,1) << endl; - //cerr << compute_discance_of_landscapes_on_grid(p,sum,2) << endl; - //cerr << compute_discance_of_landscapes_on_grid(p,sum,-1) << endl; + //cerr << compute_distance_of_landscapes_on_grid(p,sum,1) << endl; + //cerr << compute_distance_of_landscapes_on_grid(p,sum,2) << endl; + //cerr << compute_distance_of_landscapes_on_grid(p,sum,std::numeric_limits::max()) << endl; BOOST_CHECK( fabs( p.compute_maximum() - 0.46 ) <= 0.00001 ); BOOST_CHECK( fabs( p.compute_norm_of_landscape(1) - 27.3373 ) <= 0.00001 ); BOOST_CHECK( fabs( p.compute_norm_of_landscape(2) - 1.84143 ) <= 0.00001 ); BOOST_CHECK( fabs( p.compute_norm_of_landscape(3) - 0.927067 ) <= 0.00001 ); - BOOST_CHECK( fabs( compute_discance_of_landscapes_on_grid(p,sum,1) - 16.8519 ) <= 0.00005 ); - BOOST_CHECK( fabs( compute_discance_of_landscapes_on_grid(p,sum,2) - 1.44542 ) <= 0.00001 ); - BOOST_CHECK( fabs(compute_discance_of_landscapes_on_grid(p,sum,-1) - 0.45 ) <= 0.00001 ); + BOOST_CHECK( fabs( compute_distance_of_landscapes_on_grid(p,sum,1) - 16.8519 ) <= 0.00005 ); + BOOST_CHECK( fabs( compute_distance_of_landscapes_on_grid(p,sum,2) - 1.44542 ) <= 0.00001 ); + BOOST_CHECK( fabs(compute_distance_of_landscapes_on_grid(p,sum,std::numeric_limits::max()) - 0.45 ) <= 0.00001 ); } @@ -217,12 +217,9 @@ BOOST_AUTO_TEST_CASE(check_computations_of_maxima_and_norms) BOOST_AUTO_TEST_CASE(check_computations_of_averages) { Persistence_landscape_on_grid p( "data/file_with_diagram", 0,1,100 ); - Persistence_landscape_on_grid q( "data/file_with_diagram_1", 0,1,100 ); - std::vector< Persistence_landscape_on_grid* > to_average; - to_average.push_back( &p ); - to_average.push_back( &q ); + Persistence_landscape_on_grid q( "data/file_with_diagram_1", 0,1,100 ); Persistence_landscape_on_grid av; - av.compute_average( to_average ); + av.compute_average( {&p,&q} ); Persistence_landscape_on_grid template_average; template_average.load_landscape_from_file( "data/average_on_a_grid" ); @@ -238,7 +235,7 @@ BOOST_AUTO_TEST_CASE(check_computations_of_distances) Persistence_landscape_on_grid q( "data/file_with_diagram_1", 0,1,10000 ); BOOST_CHECK( fabs( p.distance( q )- 25.5779) <= 0.00005 ); BOOST_CHECK( fabs( p.distance( q , 2) - 2.04891) <= 0.00001 ); - BOOST_CHECK( fabs( p.distance( q , -1 )-0.359 ) <= 0.00001 ); + BOOST_CHECK( fabs( p.distance( q , std::numeric_limits::max() )-0.359 ) <= 0.00001 ); } diff --git a/src/Gudhi_stat/test/persistence_lanscapes_test.cpp b/src/Gudhi_stat/test/persistence_lanscapes_test.cpp index eb00a718..d0a29588 100644 --- a/src/Gudhi_stat/test/persistence_lanscapes_test.cpp +++ b/src/Gudhi_stat/test/persistence_lanscapes_test.cpp @@ -181,20 +181,17 @@ BOOST_AUTO_TEST_CASE(check_computations_of_maxima_and_norms) BOOST_CHECK( fabs( p.compute_norm_of_landscape(1) - 2.34992 ) <= 0.00001 ); BOOST_CHECK( fabs( p.compute_norm_of_landscape(2) - 0.706095 ) <= 0.00001 ); BOOST_CHECK( fabs( p.compute_norm_of_landscape(3) - 0.501867 ) <= 0.00001 ); - BOOST_CHECK( fabs( compute_discance_of_landscapes(p,sum,1) - 27.9323 ) <= 0.00005 ); - BOOST_CHECK( fabs( compute_discance_of_landscapes(p,sum,2) - 2.35199 ) <= 0.00001 ); - BOOST_CHECK( fabs(compute_discance_of_landscapes(p,sum,-1) - 0.464478 ) <= 0.00001 ); + BOOST_CHECK( fabs( compute_distance_of_landscapes(p,sum,1) - 27.9323 ) <= 0.00005 ); + BOOST_CHECK( fabs( compute_distance_of_landscapes(p,sum,2) - 2.35199 ) <= 0.00001 ); + BOOST_CHECK( fabs(compute_distance_of_landscapes( p , sum , std::numeric_limits::max() ) - 0.464478 ) <= 0.00001 ); } BOOST_AUTO_TEST_CASE(check_computations_of_averages) { Persistence_landscape p( "data/file_with_diagram" ); Persistence_landscape q( "data/file_with_diagram_1" ); - std::vector< Persistence_landscape* > to_average; - to_average.push_back( &p ); - to_average.push_back( &q ); Persistence_landscape av; - av.compute_average( to_average ); + av.compute_average( {&p,&q} ); Persistence_landscape template_average; template_average.load_landscape_from_file( "data/average" ); @@ -210,7 +207,7 @@ BOOST_AUTO_TEST_CASE(check_computations_of_distances) Persistence_landscape q( "data/file_with_diagram_1" ); BOOST_CHECK( fabs( p.distance( q )- 25.5824) <= 0.00005 ); BOOST_CHECK( fabs( p.distance( q , 2) - 2.12636 ) <= 0.00001 ); - BOOST_CHECK( fabs( p.distance( q , -1 )-0.359068 ) <= 0.00001 ); + BOOST_CHECK( fabs( p.distance( q , std::numeric_limits::max() )-0.359068 ) <= 0.00001 ); } diff --git a/src/Gudhi_stat/test/vector_representation_test.cpp b/src/Gudhi_stat/test/vector_representation_test.cpp index 40409205..b38c5147 100644 --- a/src/Gudhi_stat/test/vector_representation_test.cpp +++ b/src/Gudhi_stat/test/vector_representation_test.cpp @@ -336,13 +336,9 @@ BOOST_AUTO_TEST_CASE(check_compute_average) Vector_distances_in_diagram< Euclidean_distance > A( i1 , -1 ); Vector_distances_in_diagram< Euclidean_distance > B( i1 , -1 ); - - std::vector< Vector_distances_in_diagram< Euclidean_distance >* > to_average; - to_average.push_back( &A ); - to_average.push_back( &B ); - + Vector_distances_in_diagram< Euclidean_distance > average; - average.compute_average( to_average ); + average.compute_average( {&A,&B} ); Vector_distances_in_diagram< Euclidean_distance > template_average; template_average.load_from_file( "data/average_of_persistence_vectors" ); @@ -354,8 +350,7 @@ BOOST_AUTO_TEST_CASE(check_compute_average) BOOST_AUTO_TEST_CASE(check_arythmetic_operations) -{ - //compute average +{ std::vector< std::pair > i1(3); i1[0] = std::pair( 1,2 ); i1[1] = std::pair( 3,8 ); diff --git a/src/Gudhi_stat/utilities/Hausdorff_bootstrap.cpp b/src/Gudhi_stat/utilities/Hausdorff_bootstrap.cpp index 16c9b085..9b8f539d 100644 --- a/src/Gudhi_stat/utilities/Hausdorff_bootstrap.cpp +++ b/src/Gudhi_stat/utilities/Hausdorff_bootstrap.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include using namespace std; diff --git a/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp b/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp index 5b3d0609..f9757020 100644 --- a/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp +++ b/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include //persistence part: #include diff --git a/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp b/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp index d968b460..abcb3f55 100644 --- a/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp +++ b/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include using namespace std; diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp index efe4ec3d..631057af 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp @@ -44,7 +44,13 @@ int main( int argc , char** argv ) return 1; } - int p = atoi( argv[1] ); + int pp = atoi( argv[1] ); + double p = std::numeric_limits::max(); + if ( pp != -1 ) + { + p = pp; + } + std::vector< const char* > filenames; for ( int i = 2 ; i < argc ; ++i ) @@ -80,17 +86,17 @@ int main( int argc , char** argv ) } //and now output the result to the screen and a file: - ofstream out; + std::ofstream out; out.open( "distance" ); for ( size_t i = 0 ; i != distance.size() ; ++i ) { for ( size_t j = 0 ; j != distance.size() ; ++j ) { - cout << distance[i][j] << " "; + std::cout << distance[i][j] << " "; out << distance[i][j] << " "; } - cout << endl; - out << endl; + std::cout << std::endl; + out << std::endl; } out.close(); diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp index 4caf30af..46edbc28 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp @@ -71,17 +71,17 @@ int main( int argc , char** argv ) } //and now output the result to the screen and a file: - ofstream out; + std::ofstream out; out.open( "scalar_product" ); for ( size_t i = 0 ; i != scalar_product.size() ; ++i ) { for ( size_t j = 0 ; j != scalar_product.size() ; ++j ) { - cout << scalar_product[i][j] << " "; + std::cout << scalar_product[i][j] << " "; out << scalar_product[i][j] << " "; } - cout << endl; - out << endl; + std::cout << std::endl; + out << std::endl; } out.close(); diff --git a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp index 5f961332..2c398742 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp index e3c3a33e..937a902e 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp @@ -43,7 +43,13 @@ int main( int argc , char** argv ) return 1; } - int p = atoi( argv[1] ); + int pp = atoi( argv[1] ); + double p = std::numeric_limits::max(); + if ( pp != -1 ) + { + p = pp; + } + std::vector< const char* > filenames; for ( int i = 2 ; i < argc ; ++i ) @@ -75,23 +81,23 @@ int main( int argc , char** argv ) { for ( size_t j = i ; j != landscaspes.size() ; ++j ) { - distance[i][j] = distance[j][i] = compute_discance_of_landscapes( landscaspes[i], landscaspes[j] , p ) ; + distance[i][j] = distance[j][i] = compute_distance_of_landscapes( landscaspes[i], landscaspes[j] , p ) ; } } //and now output the result to the screen and a file: - ofstream out; + std::ofstream out; out.open( "distance" ); for ( size_t i = 0 ; i != distance.size() ; ++i ) { for ( size_t j = 0 ; j != distance.size() ; ++j ) { - cout << distance[i][j] << " "; + std::cout << distance[i][j] << " "; out << distance[i][j] << " "; } - cout << endl; - out << endl; + std::cout << std::endl; + out << std::endl; } out.close(); diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp index ef9de9c7..39772b9b 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp @@ -71,17 +71,17 @@ int main( int argc , char** argv ) } //and now output the result to the screen and a file: - ofstream out; + std::ofstream out; out.open( "scalar_product" ); for ( size_t i = 0 ; i != scalar_product.size() ; ++i ) { for ( size_t j = 0 ; j != scalar_product.size() ; ++j ) { - cout << scalar_product[i][j] << " "; + std::cout << scalar_product[i][j] << " "; out << scalar_product[i][j] << " "; } - cout << endl; - out << endl; + std::cout << std::endl; + out << std::endl; } out.close(); diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp index ace5066a..58c5ec47 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp @@ -43,7 +43,13 @@ int main( int argc , char** argv ) return 1; } - int p = atoi( argv[1] ); + int pp = atoi( argv[1] ); + double p = std::numeric_limits::max(); + if ( pp != -1 ) + { + p = pp; + } + std::vector< const char* > filenames; for ( int i = 2 ; i < argc ; ++i ) @@ -74,22 +80,22 @@ int main( int argc , char** argv ) { for ( size_t j = i ; j != landscaspes.size() ; ++j ) { - distance[i][j] = distance[j][i] = compute_discance_of_landscapes_on_grid( landscaspes[i], landscaspes[j] , p ) ; + distance[i][j] = distance[j][i] = compute_distance_of_landscapes_on_grid( landscaspes[i], landscaspes[j] , p ) ; } } //and now output the result to the screen and a file: - ofstream out; + std::ofstream out; out.open( "distance" ); for ( size_t i = 0 ; i != distance.size() ; ++i ) { for ( size_t j = 0 ; j != distance.size() ; ++j ) { - cout << distance[i][j] << " "; + std::cout << distance[i][j] << " "; out << distance[i][j] << " "; } - cout << endl; - out << endl; + std::cout << std::endl; + out << std::endl; } out.close(); diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp index a039a97a..e1a4788f 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp @@ -71,17 +71,17 @@ int main( int argc , char** argv ) } //and now output the result to the screen and a file: - ofstream out; + std::ofstream out; out.open( "scalar_product" ); for ( size_t i = 0 ; i != scalar_product.size() ; ++i ) { for ( size_t j = 0 ; j != scalar_product.size() ; ++j ) { - cout << scalar_product[i][j] << " "; + std::cout << scalar_product[i][j] << " "; out << scalar_product[i][j] << " "; } - cout << endl; - out << endl; + std::cout << std::endl; + out << std::endl; } out.close(); diff --git a/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp index 7b7faef0..2ca5989e 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp @@ -43,7 +43,13 @@ int main( int argc , char** argv ) return 1; } - int p = atoi( argv[1] ); + int pp = atoi( argv[1] ); + double p = std::numeric_limits::max(); + if ( pp != -1 ) + { + p = pp; + } + std::vector< const char* > filenames; for ( int i = 2 ; i < argc ; ++i ) @@ -80,17 +86,17 @@ int main( int argc , char** argv ) } //and now output the result to the screen and a file: - ofstream out; + std::ofstream out; out.open( "distance" ); for ( size_t i = 0 ; i != distance.size() ; ++i ) { for ( size_t j = 0 ; j != distance.size() ; ++j ) { - cout << distance[i][j] << " "; + std::cout << distance[i][j] << " "; out << distance[i][j] << " "; } - cout << endl; - out << endl; + std::cout << std::endl; + out << std::endl; } out.close(); diff --git a/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp index 74172712..78c6ab91 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp @@ -70,17 +70,17 @@ int main( int argc , char** argv ) } //and now output the result to the screen and a file: - ofstream out; + std::ofstream out; out.open( "scalar_product" ); for ( size_t i = 0 ; i != scalar_product.size() ; ++i ) { for ( size_t j = 0 ; j != scalar_product.size() ; ++j ) { - cout << scalar_product[i][j] << " "; + std::cout << scalar_product[i][j] << " "; out << scalar_product[i][j] << " "; } - cout << endl; - out << endl; + std::cout << std::endl; + out << std::endl; } out.close(); return 0; -- cgit v1.2.3 From ee086a78f61f1ac6dd14ecab6e34d6710c971f64 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 24 Mar 2017 20:22:47 +0000 Subject: Answer to Marc's comments. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/gudhi_stat@2240 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 20c02d536373553322a3e10eb4aacc2959db654a --- .../concept/Topological_data_with_averages.h | 1 + .../concept/Topological_data_with_distances.h | 4 + src/Gudhi_stat/example/persistence_heat_maps.cpp | 120 +------------------ src/Gudhi_stat/example/persistence_intervals.cpp | 2 +- src/Gudhi_stat/example/persistence_landscape.cpp | 128 +------------------- .../example/persistence_landscape_on_grid.cpp | 109 +---------------- src/Gudhi_stat/example/vector_representation.cpp | 32 +---- .../include/gudhi/multiplicative_bootstrap.h | 8 +- src/Gudhi_stat/include/gudhi/topological_process.h | 8 +- src/Gudhi_stat/test/persistence_heat_maps_test.cpp | 120 ++++++++++++++++++- src/Gudhi_stat/test/persistence_intervals_test.cpp | 2 +- .../test/persistence_lanscapes_on_grid_test.cpp | 109 ++++++++++++++++- src/Gudhi_stat/test/persistence_lanscapes_test.cpp | 129 ++++++++++++++++++++- src/Gudhi_stat/test/vector_representation_test.cpp | 2 +- src/Gudhi_stat/utilities/Hausdorff_bootstrap.cpp | 2 +- src/Gudhi_stat/utilities/Landscape_bootstrap.cpp | 4 +- .../utilities/Multiplicative_bootstrap.cpp | 2 +- src/Gudhi_stat/utilities/permutation_test.cpp | 2 +- .../average_persistence_heat_maps.cpp | 2 +- .../compute_distance_of_persistence_heat_maps.cpp | 2 +- ...ute_scalar_product_of_persistence_heat_maps.cpp | 2 +- .../create_persistence_heat_maps.cpp | 2 +- ...aps_weighted_by_arctan_of_their_persistence.cpp | 2 +- ...eat_maps_weighted_by_distance_from_diagonal.cpp | 2 +- ..._weighted_by_squared_distance_from_diagonal.cpp | 2 +- .../persistence_heat_maps/create_pssk.cpp | 2 +- .../plot_persistence_heat_map.cpp | 2 +- ...te_birth_death_range_in_persistence_diagram.cpp | 2 +- .../compute_number_of_dominant_intervals.cpp | 2 +- .../plot_histogram_of_intervals_lengths.cpp | 4 +- .../plot_persistence_Betti_numebrs.cpp | 2 +- .../plot_persistence_intervals.cpp | 2 +- .../persistence_landscapes/average_landscapes.cpp | 2 +- .../compute_distance_of_landscapes.cpp | 2 +- .../compute_scalar_product_of_landscapes.cpp | 2 +- .../persistence_landscapes/create_landscapes.cpp | 6 +- .../persistence_landscapes/plot_landscapes.cpp | 2 +- .../average_landscapes_on_grid.cpp | 2 +- .../compute_distance_of_landscapes_on_grid.cpp | 2 +- ...ompute_scalar_product_of_landscapes_on_grid.cpp | 2 +- .../create_landscapes_on_grid.cpp | 2 +- .../plot_landscapes_on_grid.cpp | 2 +- .../average_persistence_vectors.cpp | 2 +- .../compute_distance_of_persistence_vectors.cpp | 2 +- ...mpute_scalar_product_of_persistence_vectors.cpp | 2 +- .../create_persistence_vectors.cpp | 2 +- .../plot_persistence_vectors.cpp | 2 +- 47 files changed, 412 insertions(+), 436 deletions(-) (limited to 'src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp') diff --git a/src/Gudhi_stat/concept/Topological_data_with_averages.h b/src/Gudhi_stat/concept/Topological_data_with_averages.h index 67433860..aeeb94f0 100644 --- a/src/Gudhi_stat/concept/Topological_data_with_averages.h +++ b/src/Gudhi_stat/concept/Topological_data_with_averages.h @@ -25,6 +25,7 @@ /** \brief The concept Topological_data_with_averages describes the requirements * for a type to implement a container that allows computations of averages. + * Note that the average object after being computed is stored in *this. */ class Topological_data_with_averages { diff --git a/src/Gudhi_stat/concept/Topological_data_with_distances.h b/src/Gudhi_stat/concept/Topological_data_with_distances.h index 536ae821..1318b9d1 100644 --- a/src/Gudhi_stat/concept/Topological_data_with_distances.h +++ b/src/Gudhi_stat/concept/Topological_data_with_distances.h @@ -22,6 +22,10 @@ /** \brief The concept Topological_data_with_distances describes the requirements * for a type to implement a container that allows computations of distance to another contained of that type. + * The second parameter of the distance function allow to declare power of a distance. The exact meaning of that + * number will be different for different distances. A few examples are given below: + * In case of p-Wasserstein distance, the power is equal to p. power = std::limit::max() for bottleneck distance. + * In case of L^p landscape distance, the power is equal to p. s */ class Topological_data_with_distances { diff --git a/src/Gudhi_stat/example/persistence_heat_maps.cpp b/src/Gudhi_stat/example/persistence_heat_maps.cpp index c8dde3cd..0e5f7b79 100644 --- a/src/Gudhi_stat/example/persistence_heat_maps.cpp +++ b/src/Gudhi_stat/example/persistence_heat_maps.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include #include @@ -91,121 +91,3 @@ int main( int argc , char** argv ) - - - -//Below I am storing the code used to generate tests for that functionality. -/* - std::vector< std::pair< double,double > > intervals; - intervals.push_back( std::make_pair(0.5,0.5) ); - std::vector< std::vector > filter = create_Gaussian_filter(5,1); - Persistence_heat_maps p( intervals , filter , constant_function, false , 100 , 0 , 1 ); - p.plot( "heat_map_1" ); - - - std::vector< std::pair< double,double > > intervals2; - intervals2.push_back( std::make_pair(7,12) ); - Persistence_heat_maps q( intervals2 , filter , constant_function, false , 100 , 0 , 10 ); - q.plot( "heat_map_2" ); -*/ -/* - std::vector< std::pair< double,double > > intervals; - intervals.push_back( std::make_pair(0.5,0.5) ); - std::vector< std::vector > filter = create_Gaussian_filter(5,1); - Persistence_heat_maps p( intervals , filter , constant_function, false , 10 , 0 , 1 ); - p.write_to_file( "aaa" ); - - Persistence_heat_maps q; - q.load_from_file( "aaa" ); - - cerr << ( p == q ) << endl; - */ - -/* - std::vector< std::vector > filter = create_Gaussian_filter(30,1); - Persistence_heat_maps p( "file_with_diagram" , filter , constant_function, false , 100 , 0 , 1 ); - p.plot( "heat_map_1" ); -*/ - -/* - //test to construct persistence heat map: - std::vector< std::vector > filter = create_Gaussian_filter(100,1); - Persistence_heat_maps p( "file_with_diagram" , filter , constant_function, false , 1000 , 0 , 1 ); - p.print_to_file( "persistence_heat_map_from_file_with_diagram" ); - - Persistence_heat_maps q; - q.load_from_file( "persistence_heat_map_from_file_with_diagram" ); - - cerr << (p == q) << endl; -*/ -/* - //test of computations of a mean: - std::vector< std::pair< double,double > > intervals; - intervals.push_back( std::make_pair(5,5) ); - std::vector< std::vector > filter = create_Gaussian_filter(5,1); - Persistence_heat_maps p( intervals , filter , constant_function, false , 100 , 0 , 10 ); - p.plot( "heat_map_1" ); - - - std::vector< std::pair< double,double > > intervals2; - intervals2.push_back( std::make_pair(7,7) ); - Persistence_heat_maps q( intervals2 , filter , constant_function, false , 100 , 0 , 10 ); - q.plot( "heat_map_2" ); - - - Persistence_heat_maps av; - av.compute_average( { &P , &q } ); - av.plot( "average" ); -*/ - -/* - std::vector< std::vector > filter = create_Gaussian_filter(30,1); - Persistence_heat_maps p( "file_with_diagram" , filter , constant_function, false , 1000 , 0 , 10 ); - Persistence_heat_maps q( "file_with_diagram_1" , filter , constant_function, false , 1000 , 0 , 10 ); - Persistence_heat_maps r( "file_with_diagram_2" , filter , constant_function, false , 1000 , 0 , 10 ); - Persistence_heat_maps av; - av.compute_average( {&p,&q,&r} ); - - av.print_to_file( "template_average_of_heat_maps" ); -*/ - -/* - std::vector< std::pair< double,double > > intervals; - intervals.push_back( std::make_pair(5,5) ); - std::vector< std::vector > filter = create_Gaussian_filter(5,1); - Persistence_heat_maps p( intervals , filter , constant_function, false , 10 , 0 , 10 ); - p.plot( "heat_map_1" ); - - std::vector< std::pair< double,double > > intervals2; - intervals2.push_back( std::make_pair(7,7) ); - Persistence_heat_maps q( intervals2 , filter , constant_function, false , 10 , 0 , 10 ); - q.plot( "heat_map_2" ); - - Persistence_heat_maps median; - median.compute_median( {&p,&q} ); - median.plot( "median" ); -*/ - -/* - std::vector< std::vector > filter = create_Gaussian_filter(30,1); - Persistence_heat_maps p( "file_with_diagram" , filter , constant_function, false , 1000 , 0 , 1 ); - Persistence_heat_maps q( "file_with_diagram_1" , filter , constant_function, false , 1000 , 0 , 1 ); - Persistence_heat_maps r( "file_with_diagram_2" , filter , constant_function, false , 1000 , 0 , 1 ); - Persistence_heat_maps median; - median.compute_median( {&p,&q,&r} ); - median.print_to_file( "template_median_of_heat_maps" ); -*/ - - -/* - std::vector< std::vector > filter = create_Gaussian_filter(30,1); - Persistence_heat_maps p( "file_with_diagram" , filter , constant_function, false , 1000 , 0 , 1 ); - Persistence_heat_maps q( "file_with_diagram_1" , filter , constant_function, false , 1000 , 0 , 1 ); - Persistence_heat_maps r( "file_with_diagram_2" , filter , constant_function, false , 1000 , 0 , 1 ); - - Persistence_heat_maps percentage_of_active; - percentage_of_active.compute_percentage_of_active( {&p,&q,&r} , 0.1 ); - - percentage_of_active.print_to_file( "template_percentage_of_active_of_heat_maps" ); - //percentage_of_active.plot( "template_percentage_of_active_of_heat_maps" ); -*/ diff --git a/src/Gudhi_stat/example/persistence_intervals.cpp b/src/Gudhi_stat/example/persistence_intervals.cpp index 044ba3c3..04c758e6 100644 --- a/src/Gudhi_stat/example/persistence_intervals.cpp +++ b/src/Gudhi_stat/example/persistence_intervals.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include diff --git a/src/Gudhi_stat/example/persistence_landscape.cpp b/src/Gudhi_stat/example/persistence_landscape.cpp index bb1cecea..9385c408 100644 --- a/src/Gudhi_stat/example/persistence_landscape.cpp +++ b/src/Gudhi_stat/example/persistence_landscape.cpp @@ -22,7 +22,7 @@ -#include +#include @@ -90,129 +90,3 @@ int main( int argc , char** argv ) return 0; } - -//Below I am storing the code used to generate tests for that functionality. -/* -if ( argc != 2 ) - { - std::cerr << "To run this program, please provide a name of a file with persistence landscape \n"; - //return 1; - } - Persistence_landscape p("../test/data/file_with_diagram"); - - Persistence_landscape q; - q.load_landscape_from_file( "file_with_landscape_from_file_with_diagram" ); - - if ( p != q ) - { - cout << "Not equal \n"; - } - - double integral = p.compute_integral_of_landscape(); - cout << "integral : " << integral <::max() ) << endl; - - { - Persistence_landscape p( "../test/data/file_with_diagram" ); - Persistence_landscape q( "../test/data/file_with_diagram_1" ); - Persistence_landscape av; - av.compute_average( {&p,&q} ); - - Persistence_landscape template_average; - template_average.load_landscape_from_file( "average" ); - if ( template_average != av ) - { - cerr << "We have a problem with average \n"; - } - } - - - { - Persistence_landscape p( "../test/data/file_with_diagram" ); - Persistence_landscape q( "../test/data/file_with_diagram_1" ); - cout << "L^1 distance : " << p.distance( &q ) << endl; - cout << "L^2 distance : " << p.distance( &q , 2) << endl; - cout << "L^infty distance : " << p.distance( &q , std::numeric_limits::max() ) << endl; - } - - - { - Persistence_landscape p( "../test/data/file_with_diagram" ); - Persistence_landscape q( "../test/data/file_with_diagram_1" ); - cout << "Scalar product : " << p.compute_scalar_product( &q ) << endl; - } -*/ diff --git a/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp b/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp index 9133944d..d432d757 100644 --- a/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp +++ b/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp @@ -22,7 +22,7 @@ -#include +#include @@ -86,110 +86,3 @@ int main( int argc , char** argv ) return 0; } - - -//Below I am storing the code used to generate tests for that functionality. -/* - Persistence_landscape_on_grid l( "file_with_diagram_1" , 100 ); - l.print_to_file( "landscape_from_file_with_diagram_1" ); - - Persistence_landscape_on_grid g; - g.load_landscape_from_file( "landscape_from_file_with_diagram_1" ); - - cerr << ( l == g ); - */ - - /* - Persistence_landscape_on_grid l( "file_with_diagram_1" , 100 ); - cerr << l << endl; - cerr << l.compute_integral_of_landscape() << endl; - */ - - /* - Persistence_landscape_on_grid p( "file_with_diagram_1" , 100 ); - for ( size_t level = 0 ; level != 30 ; ++level ) - { - double integral = p.compute_integral_of_landscape( level ); - cerr << integral << endl; - } - */ - - /* - Persistence_landscape_on_grid p( "file_with_diagram_1" , 100 ); - for ( size_t power = 0 ; power != 5 ; ++power ) - { - double integral = p.compute_integral_of_landscape( (double)power ); - cerr << integral << endl; - } - */ - - /* - Persistence_landscape_on_grid p( "file_with_diagram_1" , 100 ); - double x = 0.0012321; - double dx = 0.05212; - for ( size_t i = 0 ; i != 10 ; ++i ) - { - cerr << p.compute_value_at_a_given_point(10,x) << endl; - x += dx; - } - */ - - /* - Persistence_landscape_on_grid p( "file_with_diagram_1",100 ); - Persistence_landscape_on_grid second("file_with_diagram_1",100 ); - Persistence_landscape_on_grid sum = p + second; - Persistence_landscape_on_grid difference = p - second; - Persistence_landscape_on_grid multiply_by_scalar = 10*p; - sum.print_to_file( "sum_on_grid_test" ); - difference.print_to_file( "difference_on_grid_test" ); - multiply_by_scalar.print_to_file( "multiply_by_scalar_on_grid_test" ); - */ - - - /* - Persistence_landscape_on_grid p( "file_with_diagram_1" , 0 , 1 , 100 ); - Persistence_landscape_on_grid second("file_with_diagram_1", 0 , 1 , 100 ); - Persistence_landscape_on_grid sum = p + second; - - cerr << "max : " << p.compute_maximum() << endl; - cerr << "1-norm : " << p.compute_norm_of_landscape(1) << endl; - cerr << "2-norm : " << p.compute_norm_of_landscape(2) << endl; - cerr << "3-norm : " << p.compute_norm_of_landscape(3) << endl; - - cerr << compute_distance_of_landscapes_on_grid(p,sum,1) << endl; - cerr << compute_distance_of_landscapes_on_grid(p,sum,2) << endl; - cerr << compute_distance_of_landscapes_on_grid(p,sum,-1) << endl; - */ - - /* - Persistence_landscape_on_grid p( "file_with_diagram", 0,1,100 ); - Persistence_landscape_on_grid q( "file_with_diagram_1", 0,1,100 ); - Persistence_landscape_on_grid av; - av.compute_average( {&p,&q} ); - av.print_to_file("average_on_a_grid"); - - Persistence_landscape_on_grid template_average; - template_average.load_landscape_from_file( "average_on_a_grid" ); - if ( template_average == av ) - { - cerr << "OK OK \n"; - }*/ - - /* - Persistence_landscape_on_grid p( "file_with_diagram" , 0,1,10000); - Persistence_landscape_on_grid q( "file_with_diagram_1" , 0,1,10000); - cerr << p.distance( &q )<< endl; - cerr << p.distance( &q , 2 ) << endl; - cerr << p.distance( &q , std::numeric_limits::max() ) << endl; - */ - -/* - Persistence_landscape_on_grid p( "file_with_diagram", 0,1,10000 ); - Persistence_landscape_on_grid q( "file_with_diagram_1", 0,1,10000 ); - - //std::vector< std::pair< double,double > > aa; - //aa.push_back( std::make_pair( 0,1 ) ); - //Persistence_landscape_on_grid p( aa, 0,1,10 ); - //Persistence_landscape_on_grid q( aa, 0,1,10 ); - cerr << p.compute_scalar_product( &q ) << endl; -*/ diff --git a/src/Gudhi_stat/example/vector_representation.cpp b/src/Gudhi_stat/example/vector_representation.cpp index 981e63de..476deeba 100644 --- a/src/Gudhi_stat/example/vector_representation.cpp +++ b/src/Gudhi_stat/example/vector_representation.cpp @@ -22,7 +22,7 @@ -#include +#include #include @@ -78,33 +78,3 @@ int main( int argc , char** argv ) return 0; } - - - - -/* - if ( argc < 2 ) - { - cout << "To run this program, please provide the name of a file with persistence diagram. If you provide two files, we will do distance, scalar produc and average computations \n"; - return 1; - } - - Vector_distances_in_diagram< Euclidean_distance > p( argv[1] , 100 ); - cout << "This is a vector corresponding to the input persistence diagram : \n"; - cout << p << endl; - - - - if ( argc == 3 ) - { - Vector_distances_in_diagram< Euclidean_distance > p_prime( argv[2] , 100); - - cout << "p_prime : " < > average; - average.compute_average( {&p,&p_prime} ); - - cout << "Here is an average : " << average << endl; - } -*/ diff --git a/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h b/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h index b38536d9..c350349c 100644 --- a/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h +++ b/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h @@ -24,10 +24,10 @@ #define BOOTSTRAP_H //concretizations -#include -#include -#include -#include +#include +#include +#include +#include #ifdef GUDHI_USE_TBB #include diff --git a/src/Gudhi_stat/include/gudhi/topological_process.h b/src/Gudhi_stat/include/gudhi/topological_process.h index ac658aee..4a41c0a7 100644 --- a/src/Gudhi_stat/include/gudhi/topological_process.h +++ b/src/Gudhi_stat/include/gudhi/topological_process.h @@ -25,10 +25,10 @@ //concretizations -#include -#include -#include -#include +#include +#include +#include +#include #include #include diff --git a/src/Gudhi_stat/test/persistence_heat_maps_test.cpp b/src/Gudhi_stat/test/persistence_heat_maps_test.cpp index 4447ba37..fb094912 100644 --- a/src/Gudhi_stat/test/persistence_heat_maps_test.cpp +++ b/src/Gudhi_stat/test/persistence_heat_maps_test.cpp @@ -26,7 +26,7 @@ #define BOOST_TEST_MODULE "gudhi_stat" #include #include -#include +#include #include @@ -258,3 +258,121 @@ BOOST_AUTO_TEST_CASE(check_arythmetic_operations_for_heat_maps) } + + + +//Below I am storing the code used to generate tests for that functionality. +/* + std::vector< std::pair< double,double > > intervals; + intervals.push_back( std::make_pair(0.5,0.5) ); + std::vector< std::vector > filter = create_Gaussian_filter(5,1); + Persistence_heat_maps p( intervals , filter , constant_function, false , 100 , 0 , 1 ); + p.plot( "heat_map_1" ); + + + std::vector< std::pair< double,double > > intervals2; + intervals2.push_back( std::make_pair(7,12) ); + Persistence_heat_maps q( intervals2 , filter , constant_function, false , 100 , 0 , 10 ); + q.plot( "heat_map_2" ); +*/ +/* + std::vector< std::pair< double,double > > intervals; + intervals.push_back( std::make_pair(0.5,0.5) ); + std::vector< std::vector > filter = create_Gaussian_filter(5,1); + Persistence_heat_maps p( intervals , filter , constant_function, false , 10 , 0 , 1 ); + p.write_to_file( "aaa" ); + + Persistence_heat_maps q; + q.load_from_file( "aaa" ); + + cerr << ( p == q ) << endl; + */ + +/* + std::vector< std::vector > filter = create_Gaussian_filter(30,1); + Persistence_heat_maps p( "file_with_diagram" , filter , constant_function, false , 100 , 0 , 1 ); + p.plot( "heat_map_1" ); +*/ + +/* + //test to construct persistence heat map: + std::vector< std::vector > filter = create_Gaussian_filter(100,1); + Persistence_heat_maps p( "file_with_diagram" , filter , constant_function, false , 1000 , 0 , 1 ); + p.print_to_file( "persistence_heat_map_from_file_with_diagram" ); + + Persistence_heat_maps q; + q.load_from_file( "persistence_heat_map_from_file_with_diagram" ); + + cerr << (p == q) << endl; +*/ +/* + //test of computations of a mean: + std::vector< std::pair< double,double > > intervals; + intervals.push_back( std::make_pair(5,5) ); + std::vector< std::vector > filter = create_Gaussian_filter(5,1); + Persistence_heat_maps p( intervals , filter , constant_function, false , 100 , 0 , 10 ); + p.plot( "heat_map_1" ); + + + std::vector< std::pair< double,double > > intervals2; + intervals2.push_back( std::make_pair(7,7) ); + Persistence_heat_maps q( intervals2 , filter , constant_function, false , 100 , 0 , 10 ); + q.plot( "heat_map_2" ); + + + Persistence_heat_maps av; + av.compute_average( { &P , &q } ); + av.plot( "average" ); +*/ + +/* + std::vector< std::vector > filter = create_Gaussian_filter(30,1); + Persistence_heat_maps p( "file_with_diagram" , filter , constant_function, false , 1000 , 0 , 10 ); + Persistence_heat_maps q( "file_with_diagram_1" , filter , constant_function, false , 1000 , 0 , 10 ); + Persistence_heat_maps r( "file_with_diagram_2" , filter , constant_function, false , 1000 , 0 , 10 ); + Persistence_heat_maps av; + av.compute_average( {&p,&q,&r} ); + + av.print_to_file( "template_average_of_heat_maps" ); +*/ + +/* + std::vector< std::pair< double,double > > intervals; + intervals.push_back( std::make_pair(5,5) ); + std::vector< std::vector > filter = create_Gaussian_filter(5,1); + Persistence_heat_maps p( intervals , filter , constant_function, false , 10 , 0 , 10 ); + p.plot( "heat_map_1" ); + + std::vector< std::pair< double,double > > intervals2; + intervals2.push_back( std::make_pair(7,7) ); + Persistence_heat_maps q( intervals2 , filter , constant_function, false , 10 , 0 , 10 ); + q.plot( "heat_map_2" ); + + Persistence_heat_maps median; + median.compute_median( {&p,&q} ); + median.plot( "median" ); +*/ + +/* + std::vector< std::vector > filter = create_Gaussian_filter(30,1); + Persistence_heat_maps p( "file_with_diagram" , filter , constant_function, false , 1000 , 0 , 1 ); + Persistence_heat_maps q( "file_with_diagram_1" , filter , constant_function, false , 1000 , 0 , 1 ); + Persistence_heat_maps r( "file_with_diagram_2" , filter , constant_function, false , 1000 , 0 , 1 ); + Persistence_heat_maps median; + median.compute_median( {&p,&q,&r} ); + median.print_to_file( "template_median_of_heat_maps" ); +*/ + + +/* + std::vector< std::vector > filter = create_Gaussian_filter(30,1); + Persistence_heat_maps p( "file_with_diagram" , filter , constant_function, false , 1000 , 0 , 1 ); + Persistence_heat_maps q( "file_with_diagram_1" , filter , constant_function, false , 1000 , 0 , 1 ); + Persistence_heat_maps r( "file_with_diagram_2" , filter , constant_function, false , 1000 , 0 , 1 ); + + Persistence_heat_maps percentage_of_active; + percentage_of_active.compute_percentage_of_active( {&p,&q,&r} , 0.1 ); + + percentage_of_active.print_to_file( "template_percentage_of_active_of_heat_maps" ); + //percentage_of_active.plot( "template_percentage_of_active_of_heat_maps" ); +*/ diff --git a/src/Gudhi_stat/test/persistence_intervals_test.cpp b/src/Gudhi_stat/test/persistence_intervals_test.cpp index 96d913e0..d46d009b 100644 --- a/src/Gudhi_stat/test/persistence_intervals_test.cpp +++ b/src/Gudhi_stat/test/persistence_intervals_test.cpp @@ -26,7 +26,7 @@ #define BOOST_TEST_MODULE "gudhi_stat" #include #include -#include "gudhi/concretizations/Persistence_intervals.h" +#include "gudhi/persistence_representations/Persistence_intervals.h" #include diff --git a/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp b/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp index 84b01f3e..2e4ba8d9 100644 --- a/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp +++ b/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp @@ -26,7 +26,7 @@ #define BOOST_TEST_MODULE "gudhi_stat" #include #include -#include +#include #include @@ -247,3 +247,110 @@ BOOST_AUTO_TEST_CASE(check_computations_of_scalar_product) } + + +//Below I am storing the code used to generate tests for that functionality. +/* + Persistence_landscape_on_grid l( "file_with_diagram_1" , 100 ); + l.print_to_file( "landscape_from_file_with_diagram_1" ); + + Persistence_landscape_on_grid g; + g.load_landscape_from_file( "landscape_from_file_with_diagram_1" ); + + cerr << ( l == g ); + */ + + /* + Persistence_landscape_on_grid l( "file_with_diagram_1" , 100 ); + cerr << l << endl; + cerr << l.compute_integral_of_landscape() << endl; + */ + + /* + Persistence_landscape_on_grid p( "file_with_diagram_1" , 100 ); + for ( size_t level = 0 ; level != 30 ; ++level ) + { + double integral = p.compute_integral_of_landscape( level ); + cerr << integral << endl; + } + */ + + /* + Persistence_landscape_on_grid p( "file_with_diagram_1" , 100 ); + for ( size_t power = 0 ; power != 5 ; ++power ) + { + double integral = p.compute_integral_of_landscape( (double)power ); + cerr << integral << endl; + } + */ + + /* + Persistence_landscape_on_grid p( "file_with_diagram_1" , 100 ); + double x = 0.0012321; + double dx = 0.05212; + for ( size_t i = 0 ; i != 10 ; ++i ) + { + cerr << p.compute_value_at_a_given_point(10,x) << endl; + x += dx; + } + */ + + /* + Persistence_landscape_on_grid p( "file_with_diagram_1",100 ); + Persistence_landscape_on_grid second("file_with_diagram_1",100 ); + Persistence_landscape_on_grid sum = p + second; + Persistence_landscape_on_grid difference = p - second; + Persistence_landscape_on_grid multiply_by_scalar = 10*p; + sum.print_to_file( "sum_on_grid_test" ); + difference.print_to_file( "difference_on_grid_test" ); + multiply_by_scalar.print_to_file( "multiply_by_scalar_on_grid_test" ); + */ + + + /* + Persistence_landscape_on_grid p( "file_with_diagram_1" , 0 , 1 , 100 ); + Persistence_landscape_on_grid second("file_with_diagram_1", 0 , 1 , 100 ); + Persistence_landscape_on_grid sum = p + second; + + cerr << "max : " << p.compute_maximum() << endl; + cerr << "1-norm : " << p.compute_norm_of_landscape(1) << endl; + cerr << "2-norm : " << p.compute_norm_of_landscape(2) << endl; + cerr << "3-norm : " << p.compute_norm_of_landscape(3) << endl; + + cerr << compute_distance_of_landscapes_on_grid(p,sum,1) << endl; + cerr << compute_distance_of_landscapes_on_grid(p,sum,2) << endl; + cerr << compute_distance_of_landscapes_on_grid(p,sum,-1) << endl; + */ + + /* + Persistence_landscape_on_grid p( "file_with_diagram", 0,1,100 ); + Persistence_landscape_on_grid q( "file_with_diagram_1", 0,1,100 ); + Persistence_landscape_on_grid av; + av.compute_average( {&p,&q} ); + av.print_to_file("average_on_a_grid"); + + Persistence_landscape_on_grid template_average; + template_average.load_landscape_from_file( "average_on_a_grid" ); + if ( template_average == av ) + { + cerr << "OK OK \n"; + }*/ + + /* + Persistence_landscape_on_grid p( "file_with_diagram" , 0,1,10000); + Persistence_landscape_on_grid q( "file_with_diagram_1" , 0,1,10000); + cerr << p.distance( &q )<< endl; + cerr << p.distance( &q , 2 ) << endl; + cerr << p.distance( &q , std::numeric_limits::max() ) << endl; + */ + +/* + Persistence_landscape_on_grid p( "file_with_diagram", 0,1,10000 ); + Persistence_landscape_on_grid q( "file_with_diagram_1", 0,1,10000 ); + + //std::vector< std::pair< double,double > > aa; + //aa.push_back( std::make_pair( 0,1 ) ); + //Persistence_landscape_on_grid p( aa, 0,1,10 ); + //Persistence_landscape_on_grid q( aa, 0,1,10 ); + cerr << p.compute_scalar_product( &q ) << endl; +*/ diff --git a/src/Gudhi_stat/test/persistence_lanscapes_test.cpp b/src/Gudhi_stat/test/persistence_lanscapes_test.cpp index dd010174..9b9f9d7b 100644 --- a/src/Gudhi_stat/test/persistence_lanscapes_test.cpp +++ b/src/Gudhi_stat/test/persistence_lanscapes_test.cpp @@ -26,7 +26,7 @@ #define BOOST_TEST_MODULE "gudhi_stat" #include #include -#include +#include #include @@ -217,3 +217,130 @@ BOOST_AUTO_TEST_CASE(check_computations_of_scalar_product) BOOST_CHECK( fabs( p.compute_scalar_product( q ) - 0.754498 ) <= 0.00001 ); } + + +//Below I am storing the code used to generate tests for that functionality. +/* +if ( argc != 2 ) + { + std::cerr << "To run this program, please provide a name of a file with persistence landscape \n"; + //return 1; + } + Persistence_landscape p("../test/data/file_with_diagram"); + + Persistence_landscape q; + q.load_landscape_from_file( "file_with_landscape_from_file_with_diagram" ); + + if ( p != q ) + { + cout << "Not equal \n"; + } + + double integral = p.compute_integral_of_landscape(); + cout << "integral : " << integral <::max() ) << endl; + + { + Persistence_landscape p( "../test/data/file_with_diagram" ); + Persistence_landscape q( "../test/data/file_with_diagram_1" ); + Persistence_landscape av; + av.compute_average( {&p,&q} ); + + Persistence_landscape template_average; + template_average.load_landscape_from_file( "average" ); + if ( template_average != av ) + { + cerr << "We have a problem with average \n"; + } + } + + + { + Persistence_landscape p( "../test/data/file_with_diagram" ); + Persistence_landscape q( "../test/data/file_with_diagram_1" ); + cout << "L^1 distance : " << p.distance( &q ) << endl; + cout << "L^2 distance : " << p.distance( &q , 2) << endl; + cout << "L^infty distance : " << p.distance( &q , std::numeric_limits::max() ) << endl; + } + + + { + Persistence_landscape p( "../test/data/file_with_diagram" ); + Persistence_landscape q( "../test/data/file_with_diagram_1" ); + cout << "Scalar product : " << p.compute_scalar_product( &q ) << endl; + } +*/ diff --git a/src/Gudhi_stat/test/vector_representation_test.cpp b/src/Gudhi_stat/test/vector_representation_test.cpp index dd84fc33..f69673dd 100644 --- a/src/Gudhi_stat/test/vector_representation_test.cpp +++ b/src/Gudhi_stat/test/vector_representation_test.cpp @@ -21,7 +21,7 @@ */ -#include +#include #include #include diff --git a/src/Gudhi_stat/utilities/Hausdorff_bootstrap.cpp b/src/Gudhi_stat/utilities/Hausdorff_bootstrap.cpp index 78c75bd4..7fd665c3 100644 --- a/src/Gudhi_stat/utilities/Hausdorff_bootstrap.cpp +++ b/src/Gudhi_stat/utilities/Hausdorff_bootstrap.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include using namespace Gudhi; diff --git a/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp b/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp index 1b24771a..0827bfdf 100644 --- a/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp +++ b/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp @@ -23,9 +23,9 @@ //stat part: #include #include -#include +#include #include -#include +#include //persistence part: #include #include diff --git a/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp b/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp index 92020c21..9a607251 100644 --- a/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp +++ b/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include using namespace Gudhi; using namespace Gudhi::Gudhi_stat; diff --git a/src/Gudhi_stat/utilities/permutation_test.cpp b/src/Gudhi_stat/utilities/permutation_test.cpp index dfbe3129..94f92d29 100644 --- a/src/Gudhi_stat/utilities/permutation_test.cpp +++ b/src/Gudhi_stat/utilities/permutation_test.cpp @@ -22,7 +22,7 @@ #include -#include +#include #include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp index 3ef863c6..901f1a03 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp @@ -22,7 +22,7 @@ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp index cb094dff..e4f5fca6 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp @@ -21,7 +21,7 @@ */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp index 46edbc28..cdeba692 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp @@ -21,7 +21,7 @@ */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp index d5f5d75f..5d2100aa 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp @@ -22,7 +22,7 @@ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp index 6c306566..8496e33e 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp @@ -22,7 +22,7 @@ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp index 6ac9e40c..83d4f3bc 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp @@ -21,7 +21,7 @@ */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp index 91b3fb22..f62615f5 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp @@ -21,7 +21,7 @@ */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp index ec35f81c..d38bb8b9 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp index 39a46adb..59b14fe8 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp @@ -21,7 +21,7 @@ */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp b/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp index 46711d27..145040fe 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include #include diff --git a/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp b/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp index 8c263705..eeda703a 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include diff --git a/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp b/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp index f21afdd2..db9c3f98 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include @@ -44,7 +44,7 @@ int main( int argc , char** argv ) Persistence_intervals p( argv[1] ); std::vector< std::pair > dominant_intervals = p.dominant_intervals( atoi( argv[2] ) ); - std::vector< size_t > histogram = p.histograms_of_lengths( 10 ); + std::vector< size_t > histogram = p.histogram_of_lengths( 10 ); std::stringstream gnuplot_script; gnuplot_script << argv[1] << "_Gnuplot_script"; diff --git a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numebrs.cpp b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numebrs.cpp index d12c4605..cb89f6b9 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numebrs.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numebrs.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include diff --git a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp index d2e49ef3..40f6fbaf 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp index 35aec203..2a50acd8 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp @@ -22,7 +22,7 @@ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp index 937a902e..0b16ac26 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp index 39772b9b..16a15174 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp index b67ec566..5485bf2a 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp @@ -20,8 +20,7 @@ * along with this program. If not, see . */ -#include - +#include using namespace Gudhi; @@ -43,7 +42,8 @@ int main( int argc , char** argv ) std::cout << "Creating persistence landscapes...\n"; for ( size_t i = 0 ; i != filenames.size() ; ++i ) { - Persistence_landscape l( filenames[i] , 0 ); + //std::vector< std::pair< double , double > > pers = read_standard_file( filename ); + Persistence_landscape l( filenames[i] , 1 ); std::stringstream ss; ss << filenames[i] << ".land"; l.print_to_file( ss.str().c_str() ); diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp index 0d72a17c..aad8e147 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp index 2f6875b2..d3851734 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp index 58c5ec47..29c37159 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp index e1a4788f..326e5587 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp @@ -21,7 +21,7 @@ */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp index 2b205513..4f36f02d 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp index 27946075..b5687ea2 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp index 3f6409c6..822d0e2a 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp @@ -21,7 +21,7 @@ */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp index 2ca5989e..6d242cd1 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp index 78c6ab91..e4c62194 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp index f3cf7289..926e46fd 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp index 06411283..0ef30be8 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include +#include -- cgit v1.2.3 From aa2c2318ea1c6f8eef50aee6f98ade3ea0ae5ca1 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Thu, 27 Apr 2017 14:41:27 +0000 Subject: initial preparation to change the name of the package. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/gudhi_stat@2382 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3648a6470eca09c85b60802148cc1e2462b92f79 --- .../doc/Persistence_representations_doc.h | 202 +++ src/Gudhi_stat/doc/gudhi_stat_doc.h | 202 --- src/Gudhi_stat/example/persistence_heat_maps.cpp | 4 +- src/Gudhi_stat/example/persistence_intervals.cpp | 4 +- src/Gudhi_stat/example/persistence_landscape.cpp | 4 +- .../example/persistence_landscape_on_grid.cpp | 4 +- src/Gudhi_stat/example/persistence_vectors.cpp | 4 +- src/Gudhi_stat/include/gudhi/PSSK.h | 181 +++ .../include/gudhi/Persistence_heat_maps.h | 1040 +++++++++++++ .../include/gudhi/Persistence_intervals.h | 697 +++++++++ .../gudhi/Persistence_intervals_with_distances.h | 65 + .../include/gudhi/Persistence_landscape.h | 1503 +++++++++++++++++++ .../include/gudhi/Persistence_landscape_on_grid.h | 1560 ++++++++++++++++++++ src/Gudhi_stat/include/gudhi/common_gudhi_stat.h | 154 -- .../gudhi/common_persistence_representations.h | 154 ++ .../include/gudhi/multiplicative_bootstrap.h | 8 +- .../gudhi/persistence_representations/PSSK.h | 181 --- .../Persistence_heat_maps.h | 1040 ------------- .../Persistence_intervals.h | 697 --------- .../Persistence_intervals_with_distances.h | 65 - .../Persistence_landscape.h | 1503 ------------------- .../Persistence_landscape_on_grid.h | 1560 -------------------- .../persistence_vectors.h | 775 ---------- src/Gudhi_stat/include/gudhi/persistence_vectors.h | 775 ++++++++++ .../include/gudhi/read_persistence_from_file.h | 2 +- src/Gudhi_stat/include/gudhi/topological_process.h | 12 +- src/Gudhi_stat/test/persistence_heat_maps_test.cpp | 4 +- src/Gudhi_stat/test/persistence_intervals_test.cpp | 4 +- .../test/persistence_lanscapes_on_grid_test.cpp | 4 +- src/Gudhi_stat/test/persistence_lanscapes_test.cpp | 4 +- .../test/read_persistence_from_file_test.cpp | 2 +- src/Gudhi_stat/test/vector_representation_test.cpp | 6 +- src/Gudhi_stat/utilities/Hausdorff_subsampling.cpp | 3 +- src/Gudhi_stat/utilities/Landscape_bootstrap.cpp | 11 +- .../utilities/Multiplicative_bootstrap.cpp | 3 +- src/Gudhi_stat/utilities/permutation_test.cpp | 3 +- .../average_persistence_heat_maps.cpp | 4 +- .../compute_distance_of_persistence_heat_maps.cpp | 4 +- ...ute_scalar_product_of_persistence_heat_maps.cpp | 4 +- .../create_persistence_heat_maps.cpp | 4 +- ...aps_weighted_by_arctan_of_their_persistence.cpp | 4 +- ...eat_maps_weighted_by_distance_from_diagonal.cpp | 4 +- ..._weighted_by_squared_distance_from_diagonal.cpp | 4 +- .../persistence_heat_maps/create_pssk.cpp | 4 +- .../plot_persistence_heat_map.cpp | 4 +- ...te_birth_death_range_in_persistence_diagram.cpp | 4 +- .../compute_bottleneck_distance.cpp | 4 +- .../compute_number_of_dominant_intervals.cpp | 4 +- .../plot_histogram_of_intervals_lengths.cpp | 4 +- .../plot_persistence_Betti_numbers.cpp | 4 +- .../plot_persistence_intervals.cpp | 11 +- .../persistence_landscapes/average_landscapes.cpp | 4 +- .../compute_distance_of_landscapes.cpp | 4 +- .../compute_scalar_product_of_landscapes.cpp | 4 +- .../persistence_landscapes/create_landscapes.cpp | 4 +- .../persistence_landscapes/plot_landscapes.cpp | 4 +- .../average_landscapes_on_grid.cpp | 4 +- .../compute_distance_of_landscapes_on_grid.cpp | 4 +- ...ompute_scalar_product_of_landscapes_on_grid.cpp | 4 +- .../create_landscapes_on_grid.cpp | 4 +- .../plot_landscapes_on_grid.cpp | 4 +- .../average_persistence_vectors.cpp | 4 +- .../compute_distance_of_persistence_vectors.cpp | 4 +- ...mpute_scalar_product_of_persistence_vectors.cpp | 4 +- .../create_persistence_vectors.cpp | 4 +- .../plot_persistence_vectors.cpp | 4 +- 66 files changed, 6284 insertions(+), 6283 deletions(-) create mode 100644 src/Gudhi_stat/doc/Persistence_representations_doc.h delete mode 100644 src/Gudhi_stat/doc/gudhi_stat_doc.h create mode 100644 src/Gudhi_stat/include/gudhi/PSSK.h create mode 100644 src/Gudhi_stat/include/gudhi/Persistence_heat_maps.h create mode 100644 src/Gudhi_stat/include/gudhi/Persistence_intervals.h create mode 100644 src/Gudhi_stat/include/gudhi/Persistence_intervals_with_distances.h create mode 100644 src/Gudhi_stat/include/gudhi/Persistence_landscape.h create mode 100644 src/Gudhi_stat/include/gudhi/Persistence_landscape_on_grid.h delete mode 100644 src/Gudhi_stat/include/gudhi/common_gudhi_stat.h create mode 100644 src/Gudhi_stat/include/gudhi/common_persistence_representations.h delete mode 100644 src/Gudhi_stat/include/gudhi/persistence_representations/PSSK.h delete mode 100644 src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_heat_maps.h delete mode 100644 src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_intervals.h delete mode 100644 src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_intervals_with_distances.h delete mode 100644 src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_landscape.h delete mode 100644 src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_landscape_on_grid.h delete mode 100644 src/Gudhi_stat/include/gudhi/persistence_representations/persistence_vectors.h create mode 100644 src/Gudhi_stat/include/gudhi/persistence_vectors.h (limited to 'src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp') diff --git a/src/Gudhi_stat/doc/Persistence_representations_doc.h b/src/Gudhi_stat/doc/Persistence_representations_doc.h new file mode 100644 index 00000000..215616a0 --- /dev/null +++ b/src/Gudhi_stat/doc/Persistence_representations_doc.h @@ -0,0 +1,202 @@ +/* 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 DOC_GUDHI_STAT_H_ +#define DOC_GUDHI_STAT_H_ + +namespace Gudhi { + +namespace Persistence_representations { + +/** \defgroup Persistence_representations Persistence_representations + * + * \author Pawel Dlotko + * + * @{ + *\section idea Idea + + *In order to perform most of the statistical tests and machine learning algorithms on a data one need to be able to perform only a very limited number of operations on them. Let us fix a representation of + * data of a type A. To perform most of the statistical and machine learning operations one need to be able to compute average of objects of type A (so that the averaged object is also of a type A), to + * compute distance between objects of a type A, to vectorize object of a type A and to compute scalar product of a pair objects of a type A. + * + *To put this statement into a context, let us assume we have two collections \f$ c_1,\ldots,c_n\f$ and \f$d_1,...,d_n\f$ of objects of a type A. We want to verify if the average of those two collections + * are different by performing a permutation test. + *First of all, we compute averages of those two collections: C average of \f$ c_1,\ldots,c_n \f$ and D average of \f$d_1,\ldots,d_n\f$. Note that both C and D are of a type A. Then we compute \f$d(C,D)\f$, + * a distance between C and D. + *Later we put the two collections into one bin: + *\f[B = \{ c_1,...,c_n,d_1,...,d_n \}\f] + *Then we shuffle B, and we divide the shuffled version of B into two classes: \f$B_1\f$ and \f$B_2\f$ (in this case, of the same cardinality). Then we compute averages \f$\hat{B_1}\f$ and \f$\hat{B_2}\f$ + * of elements in \f$B_1\f$ and \f$B_2\f$. Note that again, \f$\hat{B_1}\f$ and \f$\hat{B_2}\f$ are of a type A. + *Then we compute their distance \f$d(\hat{B_1},\hat{B_2})\f$. The procedure of shuffling and dividing the set \f$B\f$ is repeated \f$N\f$ times (where \f$N\f$ is reasonably large number). + *Then the p-value of a statement that the averages of \f$c_1,...,c_n\f$ and \f$d_1,...,d_n\f$ is approximated by the number of times \f$d(\hat{B_1},\hat{B_2}) > d(C,D)\f$ divided by \f$N\f$. + * + *The permutation test reminded above can be performed for any type A which can be averaged, and which allows for computations of distances. + * + *The Persistence\_representations contains a collection of various representations of persistent homology that implements various concepts described below: + * + *\li Concept of a representation of persistence that allows averaging (so that the average object is of the same type). + *\li Concept of representation of persistence that allows computations of distances. + *\li Concept of representation of persistence that allows computations of scalar products. + *\li Concept of representation of persistence that allows vectorization. + *\li Concept of representation of persistence that allows computations of real--valued characteristics of objects. + * + * + *At the moment an implementation of the following representations of persistence are available (further details of those representations will be discussed later): + * + *\li Exact persistence landscapes (allow averaging, computation of distances, scalar products, vectorizations and real value characteristics). + *\li Persistence landscapes on a grid (allow averaging, computation of distances scalar products, vectorizations and real value characteristics). + *\li Persistence heat maps – various representations where one put some weighted or not Gaussian kernel for each point of diagram (allow averaging, computation of distances, scalar products, + * vectorizations and real value characteristics). + *\li Persistence vectors (allow averaging, computation of distances, scalar products, vectorizations and real value characteristics). + *\li Persistence diagrams / barcodes (allow computation of distances, vectorizations and real value characteristics). + * + * + *Note that at the while functionalities like averaging, distances and scalar products are fixed, there is no canonical way of vectorizing and computing real valued characteristics of objects. Therefore the + * vectorizations and computation of real value characteristics procedures are quite likely to evolve in the furthering versions of the library. + * + *The main aim of this implementation is to be able to implement various statistical methods, both on the level of C++ and on the level of python. The methods will operate on the functionalities offered + * by concepts. That means that the statistical and ML methods will be able to operate on any representation that implement the required concept (including the ones that are not in the library at the moment). + * That gives provides a framework, that is very easy to extend, for topological statistics. + * + *Below we are discussing the representations which are currently implemented in Persistence\_representations package: + * + *\section sec_persistence_landscapes Persistence Landscapes + * Reference manual: \ref Gudhi::Persistence_representations::Persistence_landscape + *Persistence landscapes were originally proposed by Bubenik in \cite bubenik_landscapes_2015. Efficient algorithms to compute them rigorously were proposed by Bubenik and Dlotko in \cite bubenik_dlotko_landscapes_2016. The idea of + * persistence landscapes is shortly summarized in below. + * + *To begin with, suppose we are given a point \f$(b,d) \in \mathbb{R}^2\f$ in a + *persistence diagram. With this point, we associate a piecewise + *linear function \f$f_{(b,d)} : \mathbb{R} \rightarrow [0,\infty)\f$, which is + *defined as + * + * \f[f_{(b,d)}(x) = + * \left\{ \begin{array}{ccl} + * 0 & \mbox{ if } & x \not\in (b, d) \; , \\ + * x - b & \mbox{ if } & x \in \left( b, \frac{b+d}{2} + * \right] \; , \\ + * d - x & \mbox{ if } & x \in \left(\frac{b+d}{2}, + * d \right) \; . + * \end{array} \right. + *\f] + * + *A persistence landscape of the birth-death + *pairs \f$(b_i , d_i)\f$, where \f$i = 1,\ldots,m\f$, which constitute the given + *persistence diagram is the sequence of functions \f$\lambda_k : \mathbb{R} \rightarrow [0,\infty)\f$ for \f$k \in \mathbb{N}\f$, where \f$\lambda_k(x)\f$ + *denotes the \f$k^{\rm th}\f$ largest value of the numbers \f$f_{(b_i,d_i)}(x)\f$, + *for \f$i = 1, \ldots, m\f$, and we define \f$\lambda_k(x) = 0\f$ if \f$k > m\f$. + *Equivalently, this sequence of functions can be combined into a single + *function \f$L : \mathbb{N} \times \mathbb{R} \to [0,\infty)\f$ of two + *variables, if we define \f$L(k,t) = \lambda_k(t)\f$. + * + *The detailed description of algorithms used to compute persistence landscapes can be found in \cite bubenik_dlotko_landscapes_2016. + * Note that this implementation provides exact representation of landscapes. That have many advantages, but also a few drawbacks. For instance, as discussed + * in \cite bubenik_dlotko_landscapes_2016, the exact representation of landscape may be of quadratic size with respect to the input persistence diagram. It may therefore happen + * that, for very large diagrams, using this representation may be memory--prohibitive. In such a case, there are two possible ways to proceed: + * + *\li Use non exact representation on a grid described in the Section \ref sec_landscapes_on_grid. + *\li Compute just a number of initial nonzero landscapes. This option is available from C++ level. + * + * + * + *\section sec_landscapes_on_grid Persistence Landscapes on a grid + * Reference manual: \ref Gudhi::Persistence_representations::Persistence_landscape_on_grid + *This is an alternative, not--exact, representation of persistence landscapes defined in the Section \ref sec_persistence_landscapes. Unlike in the Section \ref sec_persistence_landscapes we build a + * representation of persistence landscape by sampling its values on a finite, equally distributed grid of points. + * Since, the persistence landscapes that originate from persistence diagrams have slope \f$1\f$ or \f$-1\f$, we have an estimate of a region between the grid points where the landscape cab be located. + * That allows to estimate an error make when performing various operations on landscape. Note that for average landscapes the slope is in range \f$[-1,1]\f$ and similar estimate can be used. + * + *Due to a lack of rigorous description of the algorithms to deal with this non--rigorous representaion of persistence landscapes in the literature, we are providing a short discussion of them in below. + * + *Let us assume that we want to compute persistence landscape on a interval \f$[x,y]\f$. Let us assume that we want to use \f$N\f$ grid points for that purpose. + * Then we will sample the persistence landscape on points \f$x_1 = x , x_2 = x + \frac{y-x}{N}, \ldots , x_{N} = y\f$. Persistence landscapes are represented as a vector of + * vectors of real numbers. Assume that i-th vector consist of \f$n_i\f$ numbers sorted from larger to smaller. They represent the values of the functions + \f$\lambda_1,\ldots,\lambda_{n_i}\f$ ,\f$\lambda_{n_i+1}\f$ and the functions with larger indices are then zero functions) on the i-th point of a grid, i.e. \f$x + i \frac{y-x}{N}\f$. + * + *When averaging two persistence landscapes represented by a grid we need to make sure that they are defined in a compatible grids. I.e. the intervals \f$[x,y]\f$ on which they are defined are + * the same, and the numbers of grid points \f$N\f$ are the same in both cases. If this is the case, we simply compute point-wise averages of the entries of corresponding + * vectors (In this whole section we assume that if one vector of numbers is shorter than another, we extend the shorter one with zeros so that they have the same length.) + * + *Computations of distances between two persistence landscapes on a grid is not much different than in the rigorous case. In this case, we sum up the distances between the same levels of + * corresponding landscapes. For fixed level, we approximate the landscapes between the corresponding constitutive points of landscapes by linear functions, and compute the \f$L^p\f$ distance between them. + * + *Similarly as in case of distance, when computing the scalar product of two persistence landscapes on a grid, we sum up the scalar products of corresponding levels of landscapes. For each level, + * we assume that the persistence landscape on a grid between two grid points is approximated by linear function. Therefore to compute scalar product of two corresponding levels of landscapes, + * we sum up the integrals of products of line segments for every pair of constitutive grid points. + * + *Note that for this representation we need to specify a few parameters: + * + *\li Begin and end point of a grid -- the interval \f$[x,y]\f$ (real numbers). + *\li Number of points in a grid (positive integer \f$N\f$). + * + * + *Note that the same representation is used in TDA R-package \cite Fasy_Kim_Lecci_Maria_tda. + * + *\section sec_persistence_heat_maps Persistence heat maps + * Reference manual: \ref Gudhi::Persistence_representations::Persistence heat maps + *This is a general class of discrete structures which are based on idea of placing a kernel in the points of persistence diagrams. + *This idea appeared in work by many authors over the last 15 years. As far as we know this idea was firstly described in the work of Bologna group in \cite Ferri_Frosini_comparision_sheme_1 and \cite Ferri_Frosini_comparision_sheme_2. + *Later it has been described by Colorado State University group in \cite Persistence_Images_2017. The presented paper in the first time provide a discussion of stability of the representation. + *Also, the same ideas are used in construction of two recent kernels used for machine learning: \cite Kusano_Fukumizu_Hiraoka_PWGK and \cite Reininghaus_Huber_ALL_PSSK. Both the kernel's construction uses interesting ideas to + *ensure stability of the representation with respect to Wasserstein metric. In the kernel presented in \cite Kusano_Fukumizu_Hiraoka_PWGK, a scaling function is used to multiply the Gaussian kernel in the + *way that the points close to diagonal got low weight and consequently do not have a big influence on the resulting distribution. In \cite Reininghaus_Huber_ALL_PSSK for every point \f$(b,d)\f$ two Gaussian kernels + *are added: first, with a weight 1 in a point \f$(b,d)\f$, and the second, with the weight -1 for a point \f$(b,d)\f$. In both cases, the representations are stable with respect to 1-Wasserstein distance. + * + *In Persistence\_representations package we currently implement a discretization of the distributions described above. The base of this implementation is 2-dimensional array of pixels. Each pixel have assigned a real value which + * is a sum of values of distributions induced by each point of the persistence diagram. At the moment we compute the sum of values on a center of a pixels. It can be easily extended to any other function + * (like for instance sum of integrals of the intermediate distribution on a pixel). + * + *The parameters that determine the structure are the following: + * + *\li A positive integer k determining the size of the kernel we used (we always assume that the kernels are square). + *\li A filter: in practice a square matrix of a size \f$2k+1 \times 2k+1\f$. By default, this is a discretization of N(0,1) kernel. + *\li The box \f$[x_0,x_1]\times [y_0,y_1]\f$ bounding the domain of the persistence image. + *\li Scaling function. Each Gaussian kernel at point \f$(p,q)\f$ gets multiplied by the value of this function at the point \f$(p,q)\f$. + *\li A boolean value determining if the space below diagonal should be erased or not. To be precise: when points close to diagonal are given then sometimes the kernel have support that reaches the region + *below the diagonal. If the value of this parameter is true, then the values below diagonal can be erased. + * + * + *\section sec_persistence_vectors Persistence vectors + * Reference manual: \ref Gudhi::Persistence_representations::Persistence vectors + *This is a representation of persistent homology in a form of a vector which was designed for an application in 3d graphic in \cite Carriere_Oudot_Ovsjanikov_top_signatures_3d. Below we provide a short description of this representation. + * + *Given a persistence diagram \f$D = \{ (b_i,d_i) \}\f$, for every pair of birth--death points \f$(b_1,d_1)\f$ and \f$(b_2,d_2)\f$ we compute the following three distances: + * + *\li \f$d( (b_1,d_1) , (b_2,d_2) )\f$. + *\li \f$d( (b_1,d_1) , (\frac{b_1,d_1}{2},\frac{b_1,d_1}{2}) )\f$. + *\li \f$d( (b_2,d_2) , (\frac{b_2,d_2}{2},\frac{b_2,d_2}{2}) )\f$. + * + *We pick the smallest of those and add it to a vector. The obtained vector of numbers is then sorted in decreasing order. This way we obtain a persistence vector representing the diagram. + * + *Given two persistence vectors, the computation of distances, averages and scalar products is straightforward. Average is simply a coordinate-wise average of a collection of vectors. In this section we + * assume that the vectors are extended by zeros if they are of a different size. To compute distances we compute absolute value of differences between coordinates. A scalar product is a sum of products of + * values at the corresponding positions of two vectors. + * + * \copyright GNU General Public License v3. + */ +/** @} */ // end defgroup Persistence_representations + +} // namespace Persistence_representations +} // namespace Gudhi + +#endif // Persistence_representations diff --git a/src/Gudhi_stat/doc/gudhi_stat_doc.h b/src/Gudhi_stat/doc/gudhi_stat_doc.h deleted file mode 100644 index b2162c49..00000000 --- a/src/Gudhi_stat/doc/gudhi_stat_doc.h +++ /dev/null @@ -1,202 +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 . - */ - - -#ifndef DOC_GUDHI_STAT_H_ -#define DOC_GUDHI_STAT_H_ - -namespace Gudhi { - -namespace Gudhi_stat { - -/** \defgroup Gudhi_stat Gudhi_stat - * - * \author Pawel Dlotko - * - * @{ - *\section idea Idea - - *In order to perform most of the statistical tests and machine learning algorithms on a data one need to be able to perform only a very limited number of operations on them. Let us fix a representation of - * data of a type A. To perform most of the statistical and machine learning operations one need to be able to compute average of objects of type A (so that the averaged object is also of a type A), to - * compute distance between objects of a type A, to vectorize object of a type A and to compute scalar product of a pair objects of a type A. - * - *To put this statement into a context, let us assume we have two collections \f$ c_1,\ldots,c_n\f$ and \f$d_1,...,d_n\f$ of objects of a type A. We want to verify if the average of those two collections - * are different by performing a permutation test. - *First of all, we compute averages of those two collections: C average of \f$ c_1,\ldots,c_n \f$ and D average of \f$d_1,\ldots,d_n\f$. Note that both C and D are of a type A. Then we compute \f$d(C,D)\f$, - * a distance between C and D. - *Later we put the two collections into one bin: - *\f[B = \{ c_1,...,c_n,d_1,...,d_n \}\f] - *Then we shuffle B, and we divide the shuffled version of B into two classes: \f$B_1\f$ and \f$B_2\f$ (in this case, of the same cardinality). Then we compute averages \f$\hat{B_1}\f$ and \f$\hat{B_2}\f$ - * of elements in \f$B_1\f$ and \f$B_2\f$. Note that again, \f$\hat{B_1}\f$ and \f$\hat{B_2}\f$ are of a type A. - *Then we compute their distance \f$d(\hat{B_1},\hat{B_2})\f$. The procedure of shuffling and dividing the set \f$B\f$ is repeated \f$N\f$ times (where \f$N\f$ is reasonably large number). - *Then the p-value of a statement that the averages of \f$c_1,...,c_n\f$ and \f$d_1,...,d_n\f$ is approximated by the number of times \f$d(\hat{B_1},\hat{B_2}) > d(C,D)\f$ divided by \f$N\f$. - * - *The permutation test reminded above can be performed for any type A which can be averaged, and which allows for computations of distances. - * - *The Gudhi\_stat contains a collection of various representations of persistent homology that implements various concepts described below: - * - *\li Concept of a representation of persistence that allows averaging (so that the average object is of the same type). - *\li Concept of representation of persistence that allows computations of distances. - *\li Concept of representation of persistence that allows computations of scalar products. - *\li Concept of representation of persistence that allows vectorization. - *\li Concept of representation of persistence that allows computations of real--valued characteristics of objects. - * - * - *At the moment an implementation of the following representations of persistence are available (further details of those representations will be discussed later): - * - *\li Exact persistence landscapes (allow averaging, computation of distances, scalar products, vectorizations and real value characteristics). - *\li Persistence landscapes on a grid (allow averaging, computation of distances scalar products, vectorizations and real value characteristics). - *\li Persistence heat maps – various representations where one put some weighted or not Gaussian kernel for each point of diagram (allow averaging, computation of distances, scalar products, - * vectorizations and real value characteristics). - *\li Persistence vectors (allow averaging, computation of distances, scalar products, vectorizations and real value characteristics). - *\li Persistence diagrams / barcodes (allow computation of distances, vectorizations and real value characteristics). - * - * - *Note that at the while functionalities like averaging, distances and scalar products are fixed, there is no canonical way of vectorizing and computing real valued characteristics of objects. Therefore the - * vectorizations and computation of real value characteristics procedures are quite likely to evolve in the furthering versions of the library. - * - *The main aim of this implementation is to be able to implement various statistical methods, both on the level of C++ and on the level of python. The methods will operate on the functionalities offered - * by concepts. That means that the statistical and ML methods will be able to operate on any representation that implement the required concept (including the ones that are not in the library at the moment). - * That gives provides a framework, that is very easy to extend, for topological statistics. - * - *Below we are discussing the representations which are currently implemented in Gudhi\_stat: - * - *\section sec_persistence_landscapes Persistence Landscapes - * Reference manual: \ref Gudhi::Gudhi_stat::Persistence_landscape - *Persistence landscapes were originally proposed by Bubenik in \cite bubenik_landscapes_2015. Efficient algorithms to compute them rigorously were proposed by Bubenik and Dlotko in \cite bubenik_dlotko_landscapes_2016. The idea of - * persistence landscapes is shortly summarized in below. - * - *To begin with, suppose we are given a point \f$(b,d) \in \mathbb{R}^2\f$ in a - *persistence diagram. With this point, we associate a piecewise - *linear function \f$f_{(b,d)} : \mathbb{R} \rightarrow [0,\infty)\f$, which is - *defined as - * - * \f[f_{(b,d)}(x) = - * \left\{ \begin{array}{ccl} - * 0 & \mbox{ if } & x \not\in (b, d) \; , \\ - * x - b & \mbox{ if } & x \in \left( b, \frac{b+d}{2} - * \right] \; , \\ - * d - x & \mbox{ if } & x \in \left(\frac{b+d}{2}, - * d \right) \; . - * \end{array} \right. - *\f] - * - *A persistence landscape of the birth-death - *pairs \f$(b_i , d_i)\f$, where \f$i = 1,\ldots,m\f$, which constitute the given - *persistence diagram is the sequence of functions \f$\lambda_k : \mathbb{R} \rightarrow [0,\infty)\f$ for \f$k \in \mathbb{N}\f$, where \f$\lambda_k(x)\f$ - *denotes the \f$k^{\rm th}\f$ largest value of the numbers \f$f_{(b_i,d_i)}(x)\f$, - *for \f$i = 1, \ldots, m\f$, and we define \f$\lambda_k(x) = 0\f$ if \f$k > m\f$. - *Equivalently, this sequence of functions can be combined into a single - *function \f$L : \mathbb{N} \times \mathbb{R} \to [0,\infty)\f$ of two - *variables, if we define \f$L(k,t) = \lambda_k(t)\f$. - * - *The detailed description of algorithms used to compute persistence landscapes can be found in \cite bubenik_dlotko_landscapes_2016. - * Note that this implementation provides exact representation of landscapes. That have many advantages, but also a few drawbacks. For instance, as discussed - * in \cite bubenik_dlotko_landscapes_2016, the exact representation of landscape may be of quadratic size with respect to the input persistence diagram. It may therefore happen - * that, for very large diagrams, using this representation may be memory--prohibitive. In such a case, there are two possible ways to proceed: - * - *\li Use non exact representation on a grid described in the Section \ref sec_landscapes_on_grid. - *\li Compute just a number of initial nonzero landscapes. This option is available from C++ level. - * - * - * - *\section sec_landscapes_on_grid Persistence Landscapes on a grid - * Reference manual: \ref Gudhi::Gudhi_stat::Persistence_landscape_on_grid - *This is an alternative, not--exact, representation of persistence landscapes defined in the Section \ref sec_persistence_landscapes. Unlike in the Section \ref sec_persistence_landscapes we build a - * representation of persistence landscape by sampling its values on a finite, equally distributed grid of points. - * Since, the persistence landscapes that originate from persistence diagrams have slope \f$1\f$ or \f$-1\f$, we have an estimate of a region between the grid points where the landscape cab be located. - * That allows to estimate an error make when performing various operations on landscape. Note that for average landscapes the slope is in range \f$[-1,1]\f$ and similar estimate can be used. - * - *Due to a lack of rigorous description of the algorithms to deal with this non--rigorous representaion of persistence landscapes in the literature, we are providing a short discussion of them in below. - * - *Let us assume that we want to compute persistence landscape on a interval \f$[x,y]\f$. Let us assume that we want to use \f$N\f$ grid points for that purpose. - * Then we will sample the persistence landscape on points \f$x_1 = x , x_2 = x + \frac{y-x}{N}, \ldots , x_{N} = y\f$. Persistence landscapes are represented as a vector of - * vectors of real numbers. Assume that i-th vector consist of \f$n_i\f$ numbers sorted from larger to smaller. They represent the values of the functions - \f$\lambda_1,\ldots,\lambda_{n_i}\f$ ,\f$\lambda_{n_i+1}\f$ and the functions with larger indices are then zero functions) on the i-th point of a grid, i.e. \f$x + i \frac{y-x}{N}\f$. - * - *When averaging two persistence landscapes represented by a grid we need to make sure that they are defined in a compatible grids. I.e. the intervals \f$[x,y]\f$ on which they are defined are - * the same, and the numbers of grid points \f$N\f$ are the same in both cases. If this is the case, we simply compute point-wise averages of the entries of corresponding - * vectors (In this whole section we assume that if one vector of numbers is shorter than another, we extend the shorter one with zeros so that they have the same length.) - * - *Computations of distances between two persistence landscapes on a grid is not much different than in the rigorous case. In this case, we sum up the distances between the same levels of - * corresponding landscapes. For fixed level, we approximate the landscapes between the corresponding constitutive points of landscapes by linear functions, and compute the \f$L^p\f$ distance between them. - * - *Similarly as in case of distance, when computing the scalar product of two persistence landscapes on a grid, we sum up the scalar products of corresponding levels of landscapes. For each level, - * we assume that the persistence landscape on a grid between two grid points is approximated by linear function. Therefore to compute scalar product of two corresponding levels of landscapes, - * we sum up the integrals of products of line segments for every pair of constitutive grid points. - * - *Note that for this representation we need to specify a few parameters: - * - *\li Begin and end point of a grid -- the interval \f$[x,y]\f$ (real numbers). - *\li Number of points in a grid (positive integer \f$N\f$). - * - * - *Note that the same representation is used in TDA R-package \cite Fasy_Kim_Lecci_Maria_tda. - * - *\section sec_persistence_heat_maps Persistence heat maps - * Reference manual: \ref Gudhi::Gudhi_stat::Persistence heat maps - *This is a general class of discrete structures which are based on idea of placing a kernel in the points of persistence diagrams. - *This idea appeared in work by many authors over the last 15 years. As far as we know this idea was firstly described in the work of Bologna group in \cite Ferri_Frosini_comparision_sheme_1 and \cite Ferri_Frosini_comparision_sheme_2. - *Later it has been described by Colorado State University group in \cite Persistence_Images_2017. The presented paper in the first time provide a discussion of stability of the representation. - *Also, the same ideas are used in construction of two recent kernels used for machine learning: \cite Kusano_Fukumizu_Hiraoka_PWGK and \cite Reininghaus_Huber_ALL_PSSK. Both the kernel's construction uses interesting ideas to - *ensure stability of the representation with respect to Wasserstein metric. In the kernel presented in \cite Kusano_Fukumizu_Hiraoka_PWGK, a scaling function is used to multiply the Gaussian kernel in the - *way that the points close to diagonal got low weight and consequently do not have a big influence on the resulting distribution. In \cite Reininghaus_Huber_ALL_PSSK for every point \f$(b,d)\f$ two Gaussian kernels - *are added: first, with a weight 1 in a point \f$(b,d)\f$, and the second, with the weight -1 for a point \f$(b,d)\f$. In both cases, the representations are stable with respect to 1-Wasserstein distance. - * - *In Gudhi\_stat we currently implement a discretization of the distributions described above. The base of this implementation is 2-dimensional array of pixels. Each pixel have assigned a real value which - * is a sum of values of distributions induced by each point of the persistence diagram. At the moment we compute the sum of values on a center of a pixels. It can be easily extended to any other function - * (like for instance sum of integrals of the intermediate distribution on a pixel). - * - *The parameters that determine the structure are the following: - * - *\li A positive integer k determining the size of the kernel we used (we always assume that the kernels are square). - *\li A filter: in practice a square matrix of a size \f$2k+1 \times 2k+1\f$. By default, this is a discretization of N(0,1) kernel. - *\li The box \f$[x_0,x_1]\times [y_0,y_1]\f$ bounding the domain of the persistence image. - *\li Scaling function. Each Gaussian kernel at point \f$(p,q)\f$ gets multiplied by the value of this function at the point \f$(p,q)\f$. - *\li A boolean value determining if the space below diagonal should be erased or not. To be precise: when points close to diagonal are given then sometimes the kernel have support that reaches the region - *below the diagonal. If the value of this parameter is true, then the values below diagonal can be erased. - * - * - *\section sec_persistence_vectors Persistence vectors - * Reference manual: \ref Gudhi::Gudhi_stat::Persistence vectors - *This is a representation of persistent homology in a form of a vector which was designed for an application in 3d graphic in \cite Carriere_Oudot_Ovsjanikov_top_signatures_3d. Below we provide a short description of this representation. - * - *Given a persistence diagram \f$D = \{ (b_i,d_i) \}\f$, for every pair of birth--death points \f$(b_1,d_1)\f$ and \f$(b_2,d_2)\f$ we compute the following three distances: - * - *\li \f$d( (b_1,d_1) , (b_2,d_2) )\f$. - *\li \f$d( (b_1,d_1) , (\frac{b_1,d_1}{2},\frac{b_1,d_1}{2}) )\f$. - *\li \f$d( (b_2,d_2) , (\frac{b_2,d_2}{2},\frac{b_2,d_2}{2}) )\f$. - * - *We pick the smallest of those and add it to a vector. The obtained vector of numbers is then sorted in decreasing order. This way we obtain a persistence vector representing the diagram. - * - *Given two persistence vectors, the computation of distances, averages and scalar products is straightforward. Average is simply a coordinate-wise average of a collection of vectors. In this section we - * assume that the vectors are extended by zeros if they are of a different size. To compute distances we compute absolute value of differences between coordinates. A scalar product is a sum of products of - * values at the corresponding positions of two vectors. - * - * \copyright GNU General Public License v3. - */ -/** @} */ // end defgroup Gudhi_stat - -} // namespace cubical_complex -} // namespace Gudhi - -#endif // DOC_GUDHI_STAT_H_ diff --git a/src/Gudhi_stat/example/persistence_heat_maps.cpp b/src/Gudhi_stat/example/persistence_heat_maps.cpp index 0e5f7b79..da87486d 100644 --- a/src/Gudhi_stat/example/persistence_heat_maps.cpp +++ b/src/Gudhi_stat/example/persistence_heat_maps.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include #include @@ -31,7 +31,7 @@ using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; double epsilon = 0.0000005; diff --git a/src/Gudhi_stat/example/persistence_intervals.cpp b/src/Gudhi_stat/example/persistence_intervals.cpp index 33d45485..ed5b4e34 100644 --- a/src/Gudhi_stat/example/persistence_intervals.cpp +++ b/src/Gudhi_stat/example/persistence_intervals.cpp @@ -23,14 +23,14 @@ #include -#include +#include #include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; int main( int argc , char** argv ) diff --git a/src/Gudhi_stat/example/persistence_landscape.cpp b/src/Gudhi_stat/example/persistence_landscape.cpp index 9385c408..40fb7d32 100644 --- a/src/Gudhi_stat/example/persistence_landscape.cpp +++ b/src/Gudhi_stat/example/persistence_landscape.cpp @@ -22,12 +22,12 @@ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include diff --git a/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp b/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp index d432d757..b38ac3d9 100644 --- a/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp +++ b/src/Gudhi_stat/example/persistence_landscape_on_grid.cpp @@ -22,12 +22,12 @@ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include diff --git a/src/Gudhi_stat/example/persistence_vectors.cpp b/src/Gudhi_stat/example/persistence_vectors.cpp index 9373dcf0..70163fec 100644 --- a/src/Gudhi_stat/example/persistence_vectors.cpp +++ b/src/Gudhi_stat/example/persistence_vectors.cpp @@ -22,7 +22,7 @@ -#include +#include #include @@ -32,7 +32,7 @@ #include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; diff --git a/src/Gudhi_stat/include/gudhi/PSSK.h b/src/Gudhi_stat/include/gudhi/PSSK.h new file mode 100644 index 00000000..bd142c02 --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/PSSK.h @@ -0,0 +1,181 @@ +/* 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 (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 +#ifndef PSSK_H +#define PSSK_H + +//gudhi include +#include + + +namespace Gudhi +{ +namespace Persistence_representations +{ + +/** +* This is a version of a representation presented in https://arxiv.org/abs/1412.6821 +* In that paper the authors are using the representation just to compute kernel. Over here, we extend the usability by far. +* Note that the version presented here is not exact, since we are discretizing the kernel. +* The only difference with respect to the original class is the method of creation. We have full (square) image, and for every point (p,q), we add a kernel at (p,q) and the negative kernel +* at (q,p) +**/ + +class PSSK : public Persistence_heat_maps +{ +public: + PSSK():Persistence_heat_maps(){} + + PSSK(const std::vector< std::pair< double,double > > & interval , std::vector< std::vector > filter = create_Gaussian_filter(5,1) , size_t number_of_pixels = 1000 , double min_ = -1 , double max_ = -1 ) + :Persistence_heat_maps() + { + this->construct( interval , filter , number_of_pixels , min_ , max_ ); + } + + + PSSK( const char* filename , std::vector< std::vector > filter = create_Gaussian_filter(5,1) , size_t number_of_pixels = 1000 , double min_ = -1 , double max_ = -1 , unsigned dimension = std::numeric_limits::max() ): + Persistence_heat_maps() + { + std::vector< std::pair< double , double > > intervals_; + if ( dimension == std::numeric_limits::max() ) + { + intervals_ = read_persistence_intervals_in_one_dimension_from_file( filename ); + } + else + { + intervals_ = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); + } + this->construct( intervals_ , filter , number_of_pixels , min_ , max_ ); + } + +protected: + void construct( const std::vector< std::pair >& intervals_ , + std::vector< std::vector > filter = create_Gaussian_filter(5,1), + size_t number_of_pixels = 1000 , double min_ = -1 , double max_ = -1 ); +}; + +//if min_ == max_, then the program is requested to set up the values itself based on persistence intervals +void PSSK::construct( const std::vector< std::pair >& intervals_ , + std::vector< std::vector > filter, + size_t number_of_pixels , double min_ , double max_ ) +{ + bool dbg = false; + if ( dbg ){std::cerr << "Entering construct procedure \n";getchar();} + + if ( min_ == max_ ) + { + //in this case, we want the program to set up the min_ and max_ values by itself. + min_ = std::numeric_limits::max(); + max_ = -std::numeric_limits::max(); + + + for ( size_t i = 0 ; i != intervals_.size() ; ++i ) + { + if ( intervals_[i].first < min_ )min_ = intervals_[i].first; + if ( intervals_[i].second > max_ )max_ = intervals_[i].second; + } + //now we have the structure filled in, and moreover we know min_ and max_ values of the interval, so we know the range. + + //add some more space: + min_ -= fabs(max_ - min_)/100; + max_ += fabs(max_ - min_)/100; + } + + if ( dbg ) + { + std::cerr << "min_ : " << min_ << std::endl; + std::cerr << "max_ : " << max_ << std::endl; + std::cerr << "number_of_pixels : " << number_of_pixels << std::endl; + getchar(); + } + + this->min_ = min_; + this->max_ = max_; + + + + //initialization of the structure heat_map + std::vector< std::vector > heat_map_; + for ( size_t i = 0 ; i != number_of_pixels ; ++i ) + { + std::vector v( number_of_pixels , 0 ); + heat_map_.push_back( v ); + } + this->heat_map = heat_map_; + + if (dbg)std::cerr << "Done creating of the heat map, now we will fill in the structure \n"; + + for ( size_t pt_nr = 0 ; pt_nr != intervals_.size() ; ++pt_nr ) + { + //compute the value of intervals_[pt_nr] in the grid: + int x_grid = (int)((intervals_[pt_nr].first - this->min_)/( this->max_-this->min_ )*number_of_pixels); + int y_grid = (int)((intervals_[pt_nr].second - this->min_)/( this->max_-this->min_ )*number_of_pixels); + + if ( dbg ) + { + std::cerr << "point : " << intervals_[pt_nr].first << " , " << intervals_[pt_nr].second << std::endl; + std::cerr << "x_grid : " << x_grid << std::endl; + std::cerr << "y_grid : " << y_grid << std::endl; + } + + //x_grid and y_grid gives a center of the kernel. We want to have its lower left cordner. To get this, we need to shift x_grid and y_grid by a grid diameter. + x_grid -= filter.size()/2; + y_grid -= filter.size()/2; + //note that the numbers x_grid and y_grid may be negative. + + if ( dbg ) + { + std::cerr << "After shift : \n";; + std::cerr << "x_grid : " << x_grid << std::endl; + std::cerr << "y_grid : " << y_grid << std::endl; + std::cerr << "filter.size() : " << filter.size() << std::endl; + getchar(); + } + + + for ( size_t i = 0 ; i != filter.size() ; ++i ) + { + for ( size_t j = 0 ; j != filter.size() ; ++j ) + { + //if the point (x_grid+i,y_grid+j) is the correct point in the grid. + if ( + ((x_grid+i)>=0) && (x_grid+iheat_map.size()) + && + ((y_grid+j)>=0) && (y_grid+jheat_map.size()) + ) + { + if ( dbg ){std::cerr << y_grid+j << " " << x_grid+i << std::endl;} + this->heat_map[ y_grid+j ][ x_grid+i ] += filter[i][j]; + this->heat_map[ x_grid+i ][ y_grid+j ] += -filter[i][j]; + } + } + } + + } +}//construct + + +#endif + +}//namespace Gudhi_stat +}//namespace Gudhi diff --git a/src/Gudhi_stat/include/gudhi/Persistence_heat_maps.h b/src/Gudhi_stat/include/gudhi/Persistence_heat_maps.h new file mode 100644 index 00000000..78cbed20 --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/Persistence_heat_maps.h @@ -0,0 +1,1040 @@ +/* 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 (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 Persistence_heat_maps_H +#define Persistence_heat_maps_H + +//standard include +#include +#include +#include +#include +#include +#include +#include + +//gudhi include +#include +#include + + + + +namespace Gudhi +{ +namespace Persistence_representations +{ + + +/** + * This is a simple procedure to create n by n (or 2*pixel_radius times 2*pixel_radius cubical approximation of a Gaussian kernel. +**/ +std::vector< std::vector > create_Gaussian_filter( size_t pixel_radius , double sigma ) +{ + bool dbg = false; + //we are computing the kernel mask to 2 standard deviations away from the center. We discretize it in a grid of a size 2*pixel_radius times 2*pixel_radius. + + double r = 0; + double sigma_sqr = sigma * sigma; + + // sum is for normalization + double sum = 0; + + //initialization of a kernel: + std::vector< std::vector > kernel( 2*pixel_radius +1 ); + for ( size_t i = 0 ; i != kernel.size() ; ++i ) + { + std::vector v( 2*pixel_radius +1 , 0 ); + kernel[i] = v; + } + + if ( dbg ) + { + std::cerr << "Kernel initalize \n"; + std::cerr << "pixel_radius : " << pixel_radius << std::endl; + std::cerr << "kernel.size() : " << kernel.size() << std::endl; + getchar(); + } + + for (int x = -pixel_radius; x <= (int)pixel_radius; x++) + { + for(int y = -pixel_radius; y <= (int)pixel_radius; y++) + { + double real_x = 2*sigma*x/pixel_radius; + double real_y = 2*sigma*y/pixel_radius; + r = sqrt(real_x*real_x + real_y*real_y); + kernel[x + pixel_radius][y + pixel_radius] = (exp(-(r*r)/sigma_sqr))/(3.141592 * sigma_sqr); + sum += kernel[x + pixel_radius][y + pixel_radius]; + } + } + + // normalize the kernel + for( size_t i = 0; i != kernel.size() ; ++i) + { + for( size_t j = 0; j != kernel[i].size() ; ++j) + { + kernel[i][j] /= sum; + } + + } + + if ( dbg ) + { + std::cerr << "Here is the kernel : \n"; + for( size_t i = 0; i != kernel.size() ; ++i) + { + for( size_t j = 0; j != kernel[i].size() ; ++j) + { + std::cerr << kernel[i][j] << " "; + } + std::cerr << std::endl; + } + } + return kernel; +} + + +/* +* There are various options to scale the poits depending on their location. One can for instance: +* (1) do nothing (scale all of them with the weight 1), as in the function constant_function +* (2) Scale them by the distance to the diagonal. This is implemented in function +* (3) Scale them with the square of their distance to diagonal. This is implemented in function +* (4) Scale them with +*/ + + +/** + * This is one of a scaling functions used to weight poits depending on their persistence and/or location in the diagram. + * This particular functiona is a finction which always assign value 1 to a point in the diagram. +**/ +class constant_scaling_function +{ +public: + double operator()( const std::pair< double , double >& point_in_diagram ) + { + return 1; + } +}; + + +/** + * This is one of a scaling functions used to weight poits depending on their persistence and/or location in the diagram. + * The scaling given by this function to a point (b,d) is Euclidean distance of (b,d) from diagonal. +**/ +class distance_from_diagonal_scaling +{ +public: + double operator()( const std::pair< double , double >& point_in_diagram ) + { + //(point_in_diagram.first+point_in_diagram.second)/2.0 + return sqrt( pow((point_in_diagram.first-(point_in_diagram.first+point_in_diagram.second)/2.0),2) + pow((point_in_diagram.second-(point_in_diagram.first+point_in_diagram.second)/2.0),2) ); + } +}; + +/** + * This is one of a scaling functions used to weight poits depending on their persistence and/or location in the diagram. + * The scaling given by this function to a point (b,d) is a square of Euclidean distance of (b,d) from diagonal. +**/ +class squared_distance_from_diagonal_scaling +{ +public: + double operator()( const std::pair< double , double >& point_in_diagram ) + { + return pow((point_in_diagram.first-(point_in_diagram.first+point_in_diagram.second)/2.0),2) + pow((point_in_diagram.second-(point_in_diagram.first+point_in_diagram.second)/2.0),2); + } +}; + +/** + * This is one of a scaling functions used to weight poits depending on their persistence and/or location in the diagram. + * The scaling given by this function to a point (b,d) is an arctan of a persistence of a point (i.e. arctan( b-d ). +**/ +class arc_tan_of_persistence_of_point +{ +public: + double operator()( const std::pair< double , double >& point_in_diagram ) + { + return atan( point_in_diagram.second - point_in_diagram.first ); + } +}; + +/** + * This is one of a scaling functions used to weight poits depending on their persistence and/or location in the diagram. + * This scaling function do not only depend on a point (p,d) in the diagram, but it depends on the whole diagram. + * The longest persistence pair get a scaling 1. Any other pair get a scaling belong to [0,1], which is proportional + * to the persistence of that pair. +**/ +class weight_by_setting_maximal_interval_to_have_length_one +{ +public: + weight_by_setting_maximal_interval_to_have_length_one( double len ):letngth_of_maximal_interval(len){} + double operator()( const std::pair< double , double >& point_in_diagram ) + { + return (point_in_diagram.second-point_in_diagram.first)/this->letngth_of_maximal_interval; + } +private: + double letngth_of_maximal_interval; +}; + + +/** + * This class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product +**/ +template +class Persistence_heat_maps +{ +public: + /** + * The default constructor. A scaling function from the diagonal is set up to a constant function. The image is not erased below the diagonal. The gaussian have diameter 5. + **/ + Persistence_heat_maps() + { + Scalling_of_kernels f; + this->f = f; + this->erase_below_diagonal = false; + this->min_ = this->max_ = 0; + this->set_up_parameters_for_basic_classes(); + }; + + /** + * Construction that takes at the input the following parameters: + * (1) A vector of pairs of doubles (representing persistence intervals). All other parameters are optional. They are: + * (2) a Gausian filter generated by create_Gaussian_filter filter (the default value of this vaiable is a Gaussian filter of a radius 5), + * (3) a boolean value which determines if the area of image below diagonal should, or should not be erased (it will be erased by default). + * (4) a number of pixels in each direction (set to 1000 by default). + * (5) a min x and y value of points that are to be taken into account. By default it is set to std::numeric_limits::max(), in which case the program compute the values based on the data, + * (6) a max x and y value of points that are to be taken into account. By default it is set to std::numeric_limits::max(), in which case the program compute the values based on the data. + **/ + Persistence_heat_maps( const std::vector< std::pair< double,double > > & interval , std::vector< std::vector > filter = create_Gaussian_filter(5,1) , bool erase_below_diagonal = false , size_t number_of_pixels = 1000 , double min_ = std::numeric_limits::max() , double max_ = std::numeric_limits::max() ); + + /** + * Construction that takes at the input a name of a file with persistence intervals, a filter (radius 5 by default), a scaling function (constant by default), a boolean value which determines if the area of image below diagonal should, or should not be erased (should by default). The next parameter is the number of pixels in each direction (set to 1000 by default). and min and max values of images (both set to std::numeric_limits::max() by defaulet. If this is the case, the program will pick the right values based on the data). + **/ + /** + * Construction that takes at the input the following parameters: + * (1) A a name of a file with persistence intervals. The file shold be readable by the function read_persistence_intervals_in_one_dimension_from_file. All other parameters are optional. They are: + * (2) a Gausian filter generated by create_Gaussian_filter filter (the default value of this vaiable is a Gaussian filter of a radius 5), + * (3) a boolean value which determines if the area of image below diagonal should, or should not be erased (it will be erased by default). + * (4) a number of pixels in each direction (set to 1000 by default). + * (5) a min x and y value of points that are to be taken into account. By default it is set to std::numeric_limits::max(), in which case the program compute the values based on the data, + * (6) a max x and y value of points that are to be taken into account. By default it is set to std::numeric_limits::max(), in which case the program compute the values based on the data. + **/ + Persistence_heat_maps( const char* filename , std::vector< std::vector > filter = create_Gaussian_filter(5,1), bool erase_below_diagonal = false , size_t number_of_pixels = 1000 , double min_ = std::numeric_limits::max() , double max_ = std::numeric_limits::max() , unsigned dimension = std::numeric_limits::max() ); + + + /** + * Compute a mean value of a collection of heat maps and store it in the current object. Note that all the persistence maps send in a vector to this procedure need to have the same parameters. + * If this is not the case, the program will throw an exception. + **/ + void compute_mean( const std::vector& maps ); + + /** + * Compute a median value of a collection of heat maps and store it in the current object. Note that all the persistence maps send in a vector to this procedure need to have the same parameters. + * If this is not the case, the program will throw an exception. + **/ + void compute_median( const std::vector& maps ); + + /** + * Compute a percentage of active (i.e) values above the cutoff of a collection of heat maps. + **/ + void compute_percentage_of_active( const std::vector& maps , size_t cutoff = 1 ); + + //put to file subroutine + /** + * The function outputs the perssitence image to a text file. The format as follow: + * In the first line, the values min and max of the image are stored + * In the next lines, we have the persistence images in a form of a bitmap image. + **/ + void print_to_file( const char* filename )const; + + /** + * A function that load a heat map from file to the current object (and arase qhatever was stored in the current object before). + **/ + void load_from_file( const char* filename ); + + + /** + * The procedure checks if min_, max_ and this->heat_maps sizes are the same. + **/ + inline bool check_if_the_same( const Persistence_heat_maps& second )const + { + bool dbg = false; + if ( this->heat_map.size() != second.heat_map.size() ) + { + if ( dbg )std::cerr << "this->heat_map.size() : " << this->heat_map.size() << " \n second.heat_map.size() : " << second.heat_map.size() << std::endl; + return false; + } + if ( this->min_ != second.min_ ) + { + if ( dbg )std::cerr << "this->min_ : " << this->min_ << ", second.min_ : " << second.min_ << std::endl; + return false; + } + if ( this->max_ != second.max_ ) + { + if ( dbg )std::cerr << "this->max_ : " << this->max_ << ", second.max_ : " << second.max_ << std::endl; + return false; + } + //in the other case we may assume that the persistence images are defined on the same domain. + return true; + } + + + /** + * Return minimal range value of persistent image. + **/ + inline double get_min()const{return this->min_;} + + /** + * Return maximal range value of persistent image. + **/ + inline double get_max()const{return this->max_;} + + + /** + * Operator == to check if to persistence heat maps are the same. + **/ + bool operator == ( const Persistence_heat_maps& rhs )const + { + bool dbg = false; + if ( !this->check_if_the_same(rhs) ) + { + if ( dbg )std::cerr << "The domains are not the same \n"; + return false;//in this case, the domains are not the same, so the maps cannot be the same. + } + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + { + if ( !almost_equal(this->heat_map[i][j] , rhs.heat_map[i][j]) ) + { + if ( dbg ) + { + std::cerr << "this->heat_map[" << i << "][" << j << "] = " << this->heat_map[i][j] << std::endl; + std::cerr << "rhs.heat_map[" << i << "][" << j << "] = " << rhs.heat_map[i][j] << std::endl; + } + return false; + } + } + } + return true; + } + + /** + * Operator != to check if to persistence heat maps are different. + **/ + bool operator != ( const Persistence_heat_maps& rhs )const + { + return !( (*this) == rhs ); + } + + + /** + * A function to generate a gnuplot script to vizualize the persistent image. + **/ + void plot( const char* filename )const; + + + template + friend Persistence_heat_maps operation_on_pair_of_heat_maps( const Persistence_heat_maps& first , const Persistence_heat_maps& second , Operation_type operation ) + { + //first check if the heat maps are compatible + if ( !first.check_if_the_same( second ) ) + { + std::cerr << "Sizes of the heat maps are not compatible. The program will now terminate \n"; + throw "Sizes of the heat maps are not compatible. The program will now terminate \n"; + } + Persistence_heat_maps result; + result.min_ = first.min_; + result.max_ = first.max_; + result.heat_map.reserve( first.heat_map.size() ); + for ( size_t i = 0 ; i != first.heat_map.size() ; ++i ) + { + std::vector< double > v; + v.reserve( first.heat_map[i].size() ); + for ( size_t j = 0 ; j != first.heat_map[i].size() ; ++j ) + { + v.push_back( operation( first.heat_map[i][j] , second.heat_map[i][j] ) ); + } + result.heat_map.push_back( v ); + } + return result; + }//operation_on_pair_of_heat_maps + + + /** + * Multiplication of Persistence_heat_maps by scalar (so that all values of the heat map gets multiplied by that scalar). + **/ + Persistence_heat_maps multiply_by_scalar( double scalar )const + { + Persistence_heat_maps result; + result.min_ = this->min_; + result.max_ = this->max_; + result.heat_map.reserve( this->heat_map.size() ); + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + std::vector< double > v; + v.reserve( this->heat_map[i].size() ); + for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + { + v.push_back( this->heat_map[i][j] * scalar ); + } + result.heat_map.push_back( v ); + } + return result; + } + + /** + * This function computes a sum of two objects of a type Persistence_heat_maps. + **/ + friend Persistence_heat_maps operator+( const Persistence_heat_maps& first , const Persistence_heat_maps& second ) + { + return operation_on_pair_of_heat_maps( first , second , std::plus() ); + } + /** + * This function computes a difference of two objects of a type Persistence_heat_maps. + **/ + friend Persistence_heat_maps operator-( const Persistence_heat_maps& first , const Persistence_heat_maps& second ) + { + return operation_on_pair_of_heat_maps( first , second , std::minus() ); + } + /** + * This function computes a product of an object of a type Persistence_heat_maps with real number. + **/ + friend Persistence_heat_maps operator*( double scalar , const Persistence_heat_maps& A ) + { + return A.multiply_by_scalar( scalar ); + } + /** + * This function computes a product of an object of a type Persistence_heat_maps with real number. + **/ + friend Persistence_heat_maps operator*( const Persistence_heat_maps& A , double scalar ) + { + return A.multiply_by_scalar( scalar ); + } + /** + * This function computes a product of an object of a type Persistence_heat_maps with real number. + **/ + Persistence_heat_maps operator*( double scalar ) + { + return this->multiply_by_scalar( scalar ); + } + /** + * += operator for Persistence_heat_maps. + **/ + Persistence_heat_maps operator += ( const Persistence_heat_maps& rhs ) + { + *this = *this + rhs; + return *this; + } + /** + * -= operator for Persistence_heat_maps. + **/ + Persistence_heat_maps operator -= ( const Persistence_heat_maps& rhs ) + { + *this = *this - rhs; + return *this; + } + /** + * *= operator for Persistence_heat_maps. + **/ + Persistence_heat_maps operator *= ( double x ) + { + *this = *this*x; + return *this; + } + /** + * /= operator for Persistence_heat_maps. + **/ + Persistence_heat_maps operator /= ( double x ) + { + if ( x == 0 )throw( "In operator /=, division by 0. Program terminated." ); + *this = *this * (1/x); + return *this; + } + + + //Implementations of functions for various concepts. + + /** + * This function produce a vector of doubles based on a persisence heat map. It is required in a concept Vectorized_topological_data + */ + std::vector vectorize( int number_of_function )const; + /** + * This function return the number of functions that allows vectorization of persistence heat map. It is required in a concept Vectorized_topological_data. + **/ + size_t number_of_vectorize_functions()const + { + return this->number_of_functions_for_vectorization; + } + + /** + * This function is required by the Real_valued_topological_data concept. It returns various projections od the persistence heat map to a real line. + **/ + double project_to_R( int number_of_function )const; + /** + * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. + **/ + size_t number_of_projections_to_R()const + { + return this->number_of_functions_for_projections_to_reals; + } + + /** + * A function to compute distance between persistence heat maps. + * The parameter of this function is a const reference to an object of a class Persistence_heat_maps. + * This function is required in Topological_data_with_distances concept. + * For max norm distance, set power to std::numeric_limits::max() + **/ + double distance( const Persistence_heat_maps& second_ , double power = 1)const; + + /** + * A function to compute averaged persistence heat map, based on vector of persistence heat maps. + * This function is required by Topological_data_with_averages concept. + **/ + void compute_average( const std::vector< Persistence_heat_maps* >& to_average ); + + /** + * A function to compute scalar product of persistence heat maps. + * The parameter of this functionis a const reference to an object of a class Persistence_heat_maps. + * This function is required in Topological_data_with_scalar_product concept. + **/ + double compute_scalar_product( const Persistence_heat_maps& second_ )const; + + //end of implementation of functions needed for concepts. + + + /** + * The x-range of the persistence heat map. + **/ + std::pair< double , double > get_x_range()const + { + return std::make_pair( this->min_ , this->max_ ); + } + + /** + * The y-range of the persistence heat map. + **/ + std::pair< double , double > get_y_range()const + { + return this->get_x_range(); + } + + + + +protected: + //private methods + std::vector< std::vector > check_and_initialize_maps( const std::vector& maps ); + size_t number_of_functions_for_vectorization; + size_t number_of_functions_for_projections_to_reals; + void construct( const std::vector< std::pair >& intervals_ , + std::vector< std::vector > filter = create_Gaussian_filter(5,1), + + bool erase_below_diagonal = false , size_t number_of_pixels = 1000 , double min_ = std::numeric_limits::max() , double max_ = std::numeric_limits::max() ); + + void set_up_parameters_for_basic_classes() + { + this->number_of_functions_for_vectorization = 1; + this->number_of_functions_for_projections_to_reals = 1; + } + + //data + //double (*scalling_function_with_respect_to_distance_from_diagonal)( const std::pair< double , double >& point_in_diagram ); + Scalling_of_kernels f; + bool erase_below_diagonal; + double min_; + double max_; + std::vector< std::vector< double > > heat_map; +}; + + +//if min_ == max_, then the program is requested to set up the values itself based on persistence intervals +template +void Persistence_heat_maps::construct( const std::vector< std::pair >& intervals_ , + std::vector< std::vector > filter, + bool erase_below_diagonal , size_t number_of_pixels , double min_ , double max_ ) +{ + bool dbg = false; + if ( dbg )std::cerr << "Entering construct procedure \n"; + Scalling_of_kernels f; + this->f = f; + + if ( dbg )std::cerr << "min and max passed to construct() procedure: " << min_ << " " << max_ << std::endl; + + if ( min_ == max_ ) + { + if (dbg)std::cerr << "min and max parameters will be etermined based on intervals \n"; + //in this case, we want the program to set up the min_ and max_ values by itself. + min_ = std::numeric_limits::max(); + max_ = -std::numeric_limits::max(); + + + for ( size_t i = 0 ; i != intervals_.size() ; ++i ) + { + if ( intervals_[i].first < min_ )min_ = intervals_[i].first; + if ( intervals_[i].second > max_ )max_ = intervals_[i].second; + } + //now we have the structure filled in, and moreover we know min_ and max_ values of the interval, so we know the range. + + //add some more space: + min_ -= fabs(max_ - min_)/100; + max_ += fabs(max_ - min_)/100; + } + + if ( dbg ) + { + std::cerr << "min_ : " << min_ << std::endl; + std::cerr << "max_ : " << max_ << std::endl; + std::cerr << "number_of_pixels : " << number_of_pixels << std::endl; + getchar(); + } + + this->min_ = min_; + this->max_ = max_; + + //initialization of the structure heat_map + std::vector< std::vector > heat_map_; + for ( size_t i = 0 ; i != number_of_pixels ; ++i ) + { + std::vector v( number_of_pixels , 0 ); + heat_map_.push_back( v ); + } + this->heat_map = heat_map_; + + if (dbg)std::cerr << "Done creating of the heat map, now we will fill in the structure \n"; + + for ( size_t pt_nr = 0 ; pt_nr != intervals_.size() ; ++pt_nr ) + { + //compute the value of intervals_[pt_nr] in the grid: + int x_grid = (int)((intervals_[pt_nr].first - this->min_)/( this->max_-this->min_ )*number_of_pixels); + int y_grid = (int)((intervals_[pt_nr].second - this->min_)/( this->max_-this->min_ )*number_of_pixels); + + if ( dbg ) + { + std::cerr << "point : " << intervals_[pt_nr].first << " , " << intervals_[pt_nr].second << std::endl; + std::cerr << "x_grid : " << x_grid << std::endl; + std::cerr << "y_grid : " << y_grid << std::endl; + } + + //x_grid and y_grid gives a center of the kernel. We want to have its lower left cordner. To get this, we need to shift x_grid and y_grid by a grid diameter. + x_grid -= filter.size()/2; + y_grid -= filter.size()/2; + //note that the numbers x_grid and y_grid may be negative. + + if ( dbg ) + { + std::cerr << "After shift : \n";; + std::cerr << "x_grid : " << x_grid << std::endl; + std::cerr << "y_grid : " << y_grid << std::endl; + } + + double scaling_value = this->f(intervals_[pt_nr]); + + + for ( size_t i = 0 ; i != filter.size() ; ++i ) + { + for ( size_t j = 0 ; j != filter.size() ; ++j ) + { + //if the point (x_grid+i,y_grid+j) is the correct point in the grid. + if ( + ((x_grid+i)>=0) && (x_grid+iheat_map.size()) + && + ((y_grid+j)>=0) && (y_grid+jheat_map.size()) + ) + { + if ( dbg ){std::cerr << y_grid+j << " " << x_grid+i << std::endl;} + this->heat_map[ y_grid+j ][ x_grid+i ] += scaling_value * filter[i][j]; + if ( dbg ) + { + std::cerr << "Position : (" << x_grid+i << "," << y_grid+j << ") got increased by the value : " << filter[i][j] << std::endl; + } + } + } + } + + } + + //now it remains to cut everything below diagonal if the user wants us to. + if ( erase_below_diagonal ) + { + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + for ( size_t j = i ; j != this->heat_map.size() ; ++j ) + { + this->heat_map[i][j] = 0; + } + } + } +}//construct + +template +Persistence_heat_maps::Persistence_heat_maps( const std::vector< std::pair< double,double > > & interval , + std::vector< std::vector > filter, + bool erase_below_diagonal , size_t number_of_pixels , double min_ , double max_ ) +{ + this->construct( interval , filter , erase_below_diagonal , number_of_pixels , min_ , max_ ); + this->set_up_parameters_for_basic_classes(); +} + + +template +Persistence_heat_maps::Persistence_heat_maps( const char* filename , + std::vector< std::vector > filter, + bool erase_below_diagonal , size_t number_of_pixels , double min_ , double max_ , unsigned dimension ) +{ + std::vector< std::pair< double , double > > intervals_; + if ( dimension == std::numeric_limits::max() ) + { + intervals_ = read_persistence_intervals_in_one_dimension_from_file( filename ); + } + else + { + intervals_ = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); + } + //std::cerr << "intervals_.size() : " << intervals_.size() << std::endl; + //for ( size_t i = 0 ; i != intervals_.size() ; ++i ) + //{ + // std::cerr << intervals_[i].first << " " << intervals_[i].second << std::endl; + //} + this->construct( intervals_ , filter, erase_below_diagonal , number_of_pixels , min_ , max_ ); + this->set_up_parameters_for_basic_classes(); +} + + +template +std::vector< std::vector > Persistence_heat_maps::check_and_initialize_maps( const std::vector& maps ) +{ + //checking if all the heat maps are of the same size: + for ( size_t i = 0 ; i != maps.size() ; ++i ) + { + if ( maps[i]->heat_map.size() != maps[0]->heat_map.size() ) + { + std::cerr << "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n"; + throw "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n"; + } + if ( maps[i]->heat_map[0].size() != maps[0]->heat_map[0].size() ) + { + std::cerr << "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n"; + throw "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n"; + } + } + std::vector< std::vector > heat_maps( maps[0]->heat_map.size() ); + for ( size_t i = 0 ; i != maps[0]->heat_map.size() ; ++i ) + { + std::vector v( maps[0]->heat_map[0].size() , 0 ); + heat_maps[i] = v; + } + return heat_maps; +} + +template +void Persistence_heat_maps::compute_median( const std::vector& maps ) +{ + std::vector< std::vector > heat_maps = this->check_and_initialize_maps( maps ); + + std::vector to_compute_median( maps.size() ); + for ( size_t i = 0 ; i != heat_maps.size() ; ++i ) + { + for ( size_t j = 0 ; j != heat_maps[i].size() ; ++j ) + { + for ( size_t map_no = 0 ; map_no != maps.size() ; ++map_no ) + { + to_compute_median[map_no] = maps[map_no]->heat_map[i][j]; + } + std::nth_element(to_compute_median.begin(), to_compute_median.begin() + to_compute_median.size()/2, to_compute_median.end()); + heat_maps[i][j] = to_compute_median[ to_compute_median.size()/2 ]; + } + } + this->heat_map = heat_maps; + this->min_= maps[0]->min_; + this->max_= maps[0]->max_; +} + + +template +void Persistence_heat_maps::compute_mean( const std::vector& maps ) +{ + std::vector< std::vector > heat_maps = this->check_and_initialize_maps( maps ); + for ( size_t i = 0 ; i != heat_maps.size() ; ++i ) + { + for ( size_t j = 0 ; j != heat_maps[i].size() ; ++j ) + { + double mean = 0; + for ( size_t map_no = 0 ; map_no != maps.size() ; ++map_no ) + { + mean += maps[map_no]->heat_map[i][j]; + } + heat_maps[i][j] = mean/(double)maps.size(); + } + } + this->heat_map = heat_maps; + this->min_ = maps[0]->min_; + this->max_ = maps[0]->max_; +} + + + +template +void Persistence_heat_maps::compute_percentage_of_active( const std::vector& maps , size_t cutoff ) +{ + std::vector< std::vector > heat_maps = this->check_and_initialize_maps( maps ); + + for ( size_t i = 0 ; i != heat_maps.size() ; ++i ) + { + for ( size_t j = 0 ; j != heat_maps[i].size() ; ++j ) + { + size_t number_of_active_levels = 0; + for ( size_t map_no = 0 ; map_no != maps.size() ; ++map_no ) + { + if ( maps[map_no]->heat_map[i][j] ) number_of_active_levels++; + } + if ( number_of_active_levels > cutoff ) + { + heat_maps[i][j] = number_of_active_levels; + } + else + { + heat_maps[i][j] = 0; + } + } + } + this->heat_map = heat_maps; + this->min_ = maps[0]->min_; + this->max_ = maps[0]->max_; +} + + +template +void Persistence_heat_maps::plot( const char* filename )const +{ + std::ofstream out; + std::stringstream ss; + ss << filename << "_GnuplotScript"; + + out.open( ss.str().c_str() ); + out << "plot '-' matrix with image" << std::endl; + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + { + out << this->heat_map[i][j] << " "; + } + out << std::endl; + } + out.close(); + std::cout << "Gnuplot script have been created. Open gnuplot and type load \'" << ss.str().c_str() << "\' to see the picture." << std::endl; +} + + +template +void Persistence_heat_maps::print_to_file( const char* filename )const +{ + + std::ofstream out; + out.open( filename ); + + //First we store this->min_ and this->max_ values: + out << this->min_ << " " << this->max_ << std::endl; + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + { + out << this->heat_map[i][j] << " "; + } + out << std::endl; + } + out.close(); +} + +template +void Persistence_heat_maps::load_from_file( const char* filename ) +{ + bool dbg = false; + + std::ifstream in; + in.open( filename ); + + //checking if the file exist / if it was open. + if ( !in.good() ) + { + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; + } + + //now we read the file one by one. + + + + in >> this->min_ >> this->max_; + if ( dbg ) + { + std::cerr << "Reading the following values of min and max : " << this->min_ << " , " << this->max_ << std::endl; + } + + std::string temp; + std::getline(in, temp); + + while (!in.eof()) + { + std::getline(in, temp); + std::stringstream lineSS; + lineSS << temp; + + std::vector line_of_heat_map; + while ( lineSS.good() ) + { + double point; + + lineSS >> point; + line_of_heat_map.push_back( point ); + if ( dbg ) + { + std::cout << point << " "; + } + } + if ( dbg ) + { + std::cout << std::endl; + getchar(); + } + + if ( in.good() )this->heat_map.push_back( line_of_heat_map ); + } + in.close(); + if ( dbg )std::cout << "Done \n"; +} + + +//Concretizations of virtual methods: +template +std::vector Persistence_heat_maps::vectorize( int number_of_function )const +{ + //convert this->heat_map into one large vector: + size_t size_of_result = 0; + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + size_of_result += this->heat_map[i].size(); + } + + std::vector< double > result; + result.reserve( size_of_result ); + + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + { + result.push_back( this->heat_map[i][j] ); + } + } + + return result; +} + +template +double Persistence_heat_maps::distance( const Persistence_heat_maps& second , double power )const +{ + //first we need to check if (*this) and second are defined on the same domain and have the same dimensions: + if ( !this->check_if_the_same(second) ) + { + std::cerr << "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; + throw "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; + } + + //if we are here, we know that the two persistence iomages are defined on the same domain, so we can start computing their distances: + + double distance = 0; + if ( power < std::numeric_limits::max() ) + { + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + { + distance += pow( fabs(this->heat_map[i][j] - second.heat_map[i][j]) , power ); + } + } + } + else + { + //in this case, we compute max norm distance + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + { + if ( distance < fabs(this->heat_map[i][j] - second.heat_map[i][j]) ) + { + distance = fabs(this->heat_map[i][j] - second.heat_map[i][j]); + } + } + } + } + return distance; +} + +template +double Persistence_heat_maps::project_to_R( int number_of_function )const +{ + double result = 0; + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + { + result += this->heat_map[i][j]; + } + } + return result; +} + +template +void Persistence_heat_maps::compute_average( const std::vector< Persistence_heat_maps* >& to_average ) +{ + this->compute_mean( to_average ); +} + +template +double Persistence_heat_maps::compute_scalar_product( const Persistence_heat_maps& second )const +{ + //first we need to check if (*this) and second are defined on the same domain and have the same dimensions: + if ( !this->check_if_the_same(second) ) + { + std::cerr << "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; + throw "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; + } + + //if we are here, we know that the two persistence iomages are defined on the same domain, so we can start computing their scalar product: + double scalar_prod = 0; + for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) + { + for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) + { + scalar_prod += this->heat_map[i][j]*second.heat_map[i][j]; + } + } + return scalar_prod; +} + + + + +}//namespace Gudhi_stat +}//namespace Gudhi + + +#endif diff --git a/src/Gudhi_stat/include/gudhi/Persistence_intervals.h b/src/Gudhi_stat/include/gudhi/Persistence_intervals.h new file mode 100644 index 00000000..95e6ae91 --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/Persistence_intervals.h @@ -0,0 +1,697 @@ +/* This file is part of the Gudhi hiLibrary. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Pawel Dlotko + * + * Copyright (C) 2015 INRIA (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 Persistence_intervals_H_ +#define Persistence_intervals_H_ + +//gudhi include +#include + +//standard include +#include +#include +#include +#include +#include +#include +#include + +namespace Gudhi +{ +namespace Persistence_representations +{ + +/** + * This class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data +**/ +class Persistence_intervals +{ +public: + /** + * This is a constructor of a class Persistence_intervals from a text file. Each line of the input file is supposed to contain two numbers of a type doube (or convertable to double) + * representing the birth and the death of the persistence interval. If the pairs are not sorted so that birth <= death, then the constructor will sort then that way. + * * The second parameter of a constructor is a dimension of intervals to be read from a file. If your file contains only birt-death pairs, use the default value. + **/ + Persistence_intervals( const char* filename , unsigned dimension = std::numeric_limits::max() ); + + /** + * This is a constructor of a class Persistence_intervals from a vector of pairs. Each pair is assumed to represent a persistence interval. We assume that the first elemnets of pairs + * are smaller or equal the second elements of pairs. + **/ + Persistence_intervals( const std::vector< std::pair< double,double > >& intervals ); + + /** + * This procedure returns x-range of a given persistence diagram. + **/ + std::pair< double , double > get_x_range()const + { + double min_ = std::numeric_limits::max(); + double max_ = -std::numeric_limits::max(); + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + if ( this->intervals[i].first < min_ )min_ = this->intervals[i].first; + if ( this->intervals[i].second > max_ )max_ = this->intervals[i].second; + } + return std::make_pair( min_ , max_ ); + } + + /** + * This procedure returns y-range of a given persistence diagram. + **/ + std::pair< double , double > get_y_range()const + { + double min_ = std::numeric_limits::max(); + double max_ = -std::numeric_limits::max(); + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + if ( this->intervals[i].second < min_ )min_ = this->intervals[i].second; + if ( this->intervals[i].second > max_ )max_ = this->intervals[i].second; + } + return std::make_pair( min_ , max_ ); + } + + /** + * Procedure that compute the vector of lengths of the dominant (i.e. the longest) persistence intervals. The list is truncated at the parameter of the call where_to_cut (set by default to 100). + **/ + std::vector length_of_dominant_intervals( size_t where_to_cut = 100 )const; + + + /** + * Procedure that compute the vector of the dominant (i.e. the longest) persistence intervals. The parameter of the procedure (set by default to 100) is the number of dominant intervals returned by the procedure. + **/ + std::vector< std::pair > dominant_intervals( size_t where_to_cut = 100 )const; + + /** + * Procedure to compute a histogram of interva's length. A histogram is a block plot. The number of blocks is determined by the first parameter of the function (set by default to 10). + * For the sake of argument let us assume that the length of the longest interval is 1 and the number of bins is 10. In this case the i-th block correspond to a range between i-1/10 and i10. + * The vale of a block supported at the interval is the number of persistence intervals of a length between x_0 and x_1. + **/ + std::vector< size_t > histogram_of_lengths( size_t number_of_bins = 10 )const; + + /** + * Based on a histogram of intervals lengts computed by the function histogram_of_lengths H the procedure below computes the cumulative histogram. The i-th position of the resulting histogram + * is the sume of values of H for the positions from 0 to i. + **/ + std::vector< size_t > cumulative_histogram_of_lengths( size_t number_of_bins = 10 )const; + + /** + * In this procedure we assume that each barcode is a characteristic function of a hight equal to its length. The persistence diagram is a sum of such a functions. The procedure below construct a function being a + * sum of the characteristic functions of persistence intervals. The first two parameters are the range in which the function is to be computed and the last parameter is the number of bins in + * the discretization of the interval [_min,_max]. + **/ + std::vector< double > characteristic_function_of_diagram( double x_min , double x_max , size_t number_of_bins = 10 )const; + + /** + * Cumulative version of the function characteristic_function_of_diagram + **/ + std::vector< double > cumulative_characteristic_function_of_diagram( double x_min , double x_max , size_t number_of_bins = 10 )const; + + /** + * Compute the funtion of persistence Betti numbers. The returned value is a vector of pair. First element of each pair is a place where persistence Betti numbers change. + * Second element of each pair is the value of Persistence Betti numbers at that point. + **/ + std::vector< std::pair< double , size_t > > compute_persistent_betti_numbers()const; + + /** + *This is a non optimal procedure that compute vector of distances from each point of diagram to its k-th nearest neighbor (k is a parameted of the program). The resulting vector is by default truncated to 10 + *elements (this value can be changed by using the second parameter of the program). The points are returned in order from the ones which are farthest away from their k-th nearest neighbors. + **/ + std::vector< double > k_n_n( size_t k , size_t where_to_cut = 10 )const; + + /** + * Operator that send the diagram to a stream. + **/ + friend std::ostream& operator << ( std::ostream& out , const Persistence_intervals& intervals ) + { + for ( size_t i = 0 ; i != intervals.intervals.size() ; ++i ) + { + out << intervals.intervals[i].first << " " << intervals.intervals[i].second << std::endl; + } + return out; + } + + /** + * Generating gnuplot script to plot the interval. + **/ + void plot( const char* filename , double min_x = std::numeric_limits::max() , double max_x = std::numeric_limits::max() , double min_y = std::numeric_limits::max() , double max_y = std::numeric_limits::max() ) const + { + //this program create a gnuplot script file that allows to plot persistence diagram. + std::ofstream out; + + std::ostringstream nameSS; + nameSS << filename << "_GnuplotScript"; + std::string nameStr = nameSS.str(); + out.open( nameStr ); + + std::pair min_max_values = this->get_x_range(); + if ( min_x == max_x ) + { + out << "set xrange [" << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " : " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " ]" << std::endl; + out << "set yrange [" << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " : " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " ]" << std::endl; + } + else + { + out << "set xrange [" << min_x << " : " << max_x << " ]" << std::endl; + out << "set yrange [" << min_y << " : " << max_y << " ]" << std::endl; + } + out << "plot '-' using 1:2 notitle \"" << filename << "\", \\" << std::endl; + out << " '-' using 1:2 notitle with lp" << std::endl; + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + out << this->intervals[i].first << " " << this->intervals[i].second << std::endl; + } + out << "EOF" << std::endl; + out << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " " << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << std::endl; + out << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << std::endl; + + out.close(); + + std::cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << std::endl; + } + + + + + /** + * Retun numbr of points in the diagram. + **/ + size_t size()const{return this->intervals.size();} + + /** + * Return the persistence interval at the given position. Note that intervals are not sorted with respect to their lengths. + **/ + inline std::pair< double,double > operator [](size_t i)const + { + if ( i >= this->intervals.size() )throw("Index out of range! Operator [], one_d_gaussians class\n"); + return this->intervals[i]; + } + + + + + + + + + + + + + + + + //Implementations of functions for various concepts. + /** + * This is a simple function projectig the persistence intervals to a real number. The function we use here is a sum of squared lendgths of intervals. It can be naturally interpreted as + * sum of step function, where the step hight it equal to the length of the interval. + **/ + double project_to_R( int number_of_function )const; + /** + * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. + **/ + size_t number_of_projections_to_R()const + { + return this->number_of_functions_for_projections_to_reals; + } + + /** + * Return a familly of vectors obtained from the persistence diagram. The i-th vector consist of the lenfth of i dominant persistence intervals. + **/ + std::vector vectorize( int number_of_function )const + { + return this->length_of_dominant_intervals( number_of_function ); + } + /** + * This function return the number of functions that allows vectorization of a persisence diagram. It is required in a concept Vectorized_topological_data. + **/ + size_t number_of_vectorize_functions()const + { + return this->number_of_functions_for_vectorization; + } + + //end of implementation of functions needed for concepts. + //end of implementation of functions needed for concepts. + + + + + + + + + + + + + + //For visualization use output from vectorize and build histograms. + std::vector< std::pair< double,double > > output_for_visualization() + { + return this->intervals; + } + +protected: + + void set_up_numbers_of_functions_for_vectorization_and_projections_to_reals() + { + //warning, this function can be only called after filling in the intervals vector. + this->number_of_functions_for_vectorization = this->intervals.size(); + this->number_of_functions_for_projections_to_reals = 1; + } + + std::vector< std::pair< double,double > > intervals; + size_t number_of_functions_for_vectorization; + size_t number_of_functions_for_projections_to_reals; +}; + + +Persistence_intervals::Persistence_intervals( const char* filename , unsigned dimension ) +{ + //bool dbg = false; + //ifstream in; + //in.open( filename ); + + //if ( !in.good() ) + //{ + // throw("File with the persistence diagram do not exist, the program will now terminate.\n"); + //} + + //while ( true ) + //{ + // double first; + // double second; + // in >> first >> second; + + // if ( first > second ) + // { + // double buf = first; + // first = second; + // second = buf; + // } + + // if ( in.eof() )break; + // this->intervals.push_back( std::make_pair( first,second ) ); + // if ( dbg ) + // { + // std::cerr << "Adding interval [ " << first << " , " << second << " ]\n"; + // getchar(); + // } + //} + //in.close(); + if ( dimension == std::numeric_limits::max() ) + { + this->intervals = read_persistence_intervals_in_one_dimension_from_file( filename ); + } + else + { + this->intervals = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); + } + this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); +}//Persistence_intervals + + +Persistence_intervals::Persistence_intervals( const std::vector< std::pair< double , double > >& intervals_ ):intervals(intervals_) +{ + this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); +} + + +std::vector< double > Persistence_intervals::length_of_dominant_intervals( size_t where_to_cut )const +{ + std::vector< double > result( this->intervals.size() ); + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + result[i] = this->intervals[i].second - this->intervals[i].first; + } + std::sort( result.begin() , result.end() , std::greater() ); + + + result.resize( std::min(where_to_cut,result.size()) ); + return result; +}//length_of_dominant_intervals + + + +bool compare( const std::pair< size_t , double >& first , const std::pair< size_t , double >& second ) +{ + return first.second > second.second; +} + + +std::vector< std::pair > Persistence_intervals::dominant_intervals( size_t where_to_cut )const +{ + bool dbg = false; + std::vector< std::pair< size_t , double > > position_length_vector( this->intervals.size() ); + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + position_length_vector[i] = std::make_pair( i , this->intervals[i].second - this->intervals[i].first ); + } + + std::sort( position_length_vector.begin() , position_length_vector.end() , compare ); + + std::vector< std::pair > result; + result.reserve( std::min( where_to_cut , position_length_vector.size() ) ); + + for ( size_t i = 0 ; i != std::min( where_to_cut , position_length_vector.size() ) ; ++i ) + { + result.push_back( this->intervals[ position_length_vector[i].first ] ); + if ( dbg )std::cerr << "Position : " << position_length_vector[i].first << " length : " << position_length_vector[i].second << std::endl; + } + + return result; +}//dominant_intervals + + +std::vector< size_t > Persistence_intervals::histogram_of_lengths( size_t number_of_bins )const +{ + bool dbg = false; + + if ( dbg )std::cerr << "this->intervals.size() : " << this->intervals.size() << std::endl; + //first find the length of the longest interval: + double lengthOfLongest = 0; + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + if ( (this->intervals[i].second - this->intervals[i].first) > lengthOfLongest ) + { + lengthOfLongest = this->intervals[i].second - this->intervals[i].first; + } + } + + if ( dbg ){std::cerr << "lengthOfLongest : " << lengthOfLongest << std::endl;} + + //this is a container we will use to store the resulting histogram + std::vector< size_t > result( number_of_bins + 1 , 0 ); + + //for every persistence interval in our collection. + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + //compute its length relative to the length of the dominant interval: + double relative_length_of_this_interval = (this->intervals[i].second - this->intervals[i].first)/lengthOfLongest; + + //given the relative length (between 0 and 1) compute to which bin should it contribute. + size_t position = (size_t)(relative_length_of_this_interval*number_of_bins); + + + ++result[position]; + + if ( dbg ) + { + std::cerr << "i : " << i << std::endl; + std::cerr << "Interval : [" << this->intervals[i].first << " , " << this->intervals[i].second << " ] \n"; + std::cerr << "relative_length_of_this_interval : " << relative_length_of_this_interval << std::endl; + std::cerr << "position : " << position << std::endl; + getchar(); + } + } + + + if ( dbg ){for ( size_t i = 0 ; i != result.size() ; ++i )std::cerr << result[i] << std::endl;} + return result; +} + + +std::vector< size_t > Persistence_intervals::cumulative_histogram_of_lengths( size_t number_of_bins )const +{ + std::vector< size_t > histogram = this->histogram_of_lengths( number_of_bins ); + std::vector< size_t > result( histogram.size() ); + + size_t sum = 0; + for ( size_t i = 0 ; i != histogram.size() ; ++i ) + { + sum += histogram[i]; + result[i] = sum; + } + return result; +} + + +std::vector< double > Persistence_intervals::characteristic_function_of_diagram( double x_min , double x_max , size_t number_of_bins )const +{ + bool dbg = false; + + std::vector< double > result( number_of_bins ); + std::fill( result.begin() , result.end() , 0 ); + + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + if ( dbg ) + { + std::cerr << "Interval : " << this->intervals[i].first << " , " << this->intervals[i].second << std::endl; + } + + size_t beginIt = 0; + if ( this->intervals[i].first < x_min )beginIt = 0; + if ( this->intervals[i].first >= x_max )beginIt = result.size(); + if ( ( this->intervals[i].first > x_min ) && ( this->intervals[i].first < x_max ) ) + { + beginIt = number_of_bins*(this->intervals[i].first-x_min)/(x_max - x_min); + } + + size_t endIt = 0; + if ( this->intervals[i].second < x_min )endIt = 0; + if ( this->intervals[i].second >= x_max )endIt = result.size(); + if ( ( this->intervals[i].second > x_min ) && ( this->intervals[i].second < x_max ) ) + { + endIt = number_of_bins*( this->intervals[i].second - x_min )/(x_max - x_min); + } + + if ( beginIt > endIt ){beginIt = endIt;} + + if ( dbg ) + { + std::cerr << "beginIt : " << beginIt << std::endl; + std::cerr << "endIt : " << endIt << std::endl; + } + + + for ( size_t pos = beginIt ; pos != endIt ; ++pos ) + { + result[pos] += ( (x_max - x_min)/(double)number_of_bins ) * ( this->intervals[i].second - this->intervals[i].first ); + } + //cerr << "x_max : " << x_max << " x_min : " << x_min << " , number_of_bins : " << number_of_bins << " this->intervals[i].second : " << this->intervals[i].second << " this->intervals[i].first : " << this->intervals[i].first << endl; + if ( dbg ) + { + std::cerr << "Result at this stage \n"; + for ( size_t aa = 0 ; aa != result.size() ; ++aa ) + { + std::cerr << result[aa] << " "; + } + std::cerr << std::endl; + //getchar(); + } + } + return result; +}//characteristic_function_of_diagram + + + +std::vector< double > Persistence_intervals::cumulative_characteristic_function_of_diagram( double x_min , double x_max , size_t number_of_bins )const +{ + std::vector< double > intsOfBars = this->characteristic_function_of_diagram( x_min , x_max , number_of_bins ); + std::vector< double > result( intsOfBars.size() ); + double sum = 0; + for ( size_t i = 0 ; i != intsOfBars.size() ; ++i ) + { + sum += intsOfBars[i]; + result[i] = sum; + } + return result; +}//cumulative_characteristic_function_of_diagram + + +template +bool compare_first_element_of_pair( const std::pair< T , bool >& f, const std::pair< T , bool >& s ) +{ + return (f.first < s.first); +} + + +std::vector< std::pair< double , size_t > > Persistence_intervals::compute_persistent_betti_numbers()const +{ + std::vector< std::pair< double , bool > > places_where_pbs_change( 2*this->intervals.size() ); + + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + places_where_pbs_change[2*i] = std::make_pair( this->intervals[i].first , true ); + places_where_pbs_change[2*i+1] = std::make_pair( this->intervals[i].second , false ); + } + + std::sort( places_where_pbs_change.begin() , places_where_pbs_change.end() , compare_first_element_of_pair ); + size_t pbn = 0; + std::vector< std::pair< double , size_t > > pbns( places_where_pbs_change.size() ); + for ( size_t i = 0 ; i != places_where_pbs_change.size() ; ++i ) + { + if ( places_where_pbs_change[i].second == true ) + { + ++pbn; + } + else + { + --pbn; + } + pbns[i] = std::make_pair( places_where_pbs_change[i].first , pbn ); + } + return pbns; +} + + + + + + +inline double compute_euclidean_distance( const std::pair< double,double > & f , const std::pair< double,double > & s ) +{ + return sqrt( (f.first-s.first)*(f.first-s.first) + (f.second-s.second)*(f.second-s.second) ); +} + + +std::vector< double > Persistence_intervals::k_n_n( size_t k , size_t where_to_cut )const +{ + bool dbg = false; + if ( dbg ) + { + std::cerr << "Here are the intervals : \n"; + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + std::cerr << "[ " << this->intervals[i].first << " , " << this->intervals[i].second << "] \n"; + } + getchar(); + } + + std::vector< double > result; + //compute all to all distance between point in the diagram. Also, consider points in the diagonal with the infinite multiplicity. + std::vector< std::vector< double > > distances( this->intervals.size() ); + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + std::vector aa(this->intervals.size()); + std::fill( aa.begin() , aa.end() , 0 ); + distances[i] = aa; + } + std::vector< double > distances_from_diagonal( this->intervals.size() ); + std::fill( distances_from_diagonal.begin() , distances_from_diagonal.end() , 0 ); + + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + std::vector< double > distancesFromI; + for ( size_t j = i+1 ; j != this->intervals.size() ; ++j ) + { + distancesFromI.push_back( compute_euclidean_distance( this->intervals[i] , this->intervals[j] ) ); + } + //distances.push_back( distancesFromI ); + //also add a distance from this guy to daigonal: + double distanceToDiagonal = compute_euclidean_distance( this->intervals[i] , std::make_pair( 0.5*(this->intervals[i].first + this->intervals[i].second) , 0.5*(this->intervals[i].first + this->intervals[i].second) ) ); + distances_from_diagonal[i] = distanceToDiagonal; + + if ( dbg ) + { + std::cerr << "Here are the distances form the point : [" << this->intervals[i].first << " , " << this->intervals[i].second << "] in the diagram \n"; + for ( size_t aa = 0 ; aa != distancesFromI.size() ; ++aa ) + { + std::cerr << "To : " << i+aa << " : " << distancesFromI[aa] << " "; + } + std::cerr << std::endl; + getchar(); + } + + //filling in the distances matrix: + for ( size_t j = i+1 ; j != this->intervals.size() ; ++j ) + { + distances[i][j] = distancesFromI[j-i-1]; + distances[j][i] = distancesFromI[j-i-1]; + } + } + if ( dbg ) + { + std::cerr << "Here is the distance matrix : \n"; + for ( size_t i = 0 ; i != distances.size() ; ++i ) + { + for ( size_t j = 0 ; j != distances.size() ; ++j ) + { + std::cerr << distances[i][j] << " "; + } + std::cerr << std::endl; + } + std::cerr << std::endl << std::endl << "And here are the distances to the diagonal : " << std::endl; + for ( size_t i = 0 ; i != distances_from_diagonal. size() ; ++i ) + { + std::cerr << distances_from_diagonal[i] << " "; + } + std::cerr << std::endl << std::endl; + getchar(); + } + + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + std::vector< double > distancesFromI = distances[i]; + distancesFromI.push_back( distances_from_diagonal[i] ); + + //sort it: + std::sort( distancesFromI.begin() , distancesFromI.end() , std::greater() ); + + if ( k > distancesFromI.size() ) + { + if ( dbg ) + { + std::cerr << "There are not enough neighbors in your set. We set the result to plus infty \n"; + } + result.push_back( std::numeric_limits::max() ); + } + else + { + if ( distances_from_diagonal[i] > distancesFromI[k] ) + { + if ( dbg ) + { + std::cerr << "The k-th n.n. is on a diagonal. Therefore we set up a distance to diagonal \n"; + } + result.push_back( distances_from_diagonal[i] ); + } + else + { + result.push_back( distancesFromI[k] ); + } + } + } + std::sort( result.begin() , result.end() , std::greater() ); + result.resize( std::min( result.size() , where_to_cut ) ); + + return result; +} + + +double Persistence_intervals::project_to_R( int number_of_function )const +{ + double result = 0; + + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + result += ( this->intervals[i].second - this->intervals[i].first )*( this->intervals[i].second - this->intervals[i].first ); + } + + return result; +} + + +}//namespace gudhi stat +}//namespace gudhi + +#endif diff --git a/src/Gudhi_stat/include/gudhi/Persistence_intervals_with_distances.h b/src/Gudhi_stat/include/gudhi/Persistence_intervals_with_distances.h new file mode 100644 index 00000000..60343dc1 --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/Persistence_intervals_with_distances.h @@ -0,0 +1,65 @@ +/* This file is part of the Gudhi hiLibrary. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Pawel Dlotko + * + * Copyright (C) 2015 INRIA (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 Persistence_intervals_WITH_DISTANCES_H_ +#define Persistence_intervals_WITH_DISTANCES_H_ + + +#include +#include + +namespace Gudhi +{ +namespace Persistence_representations +{ + +class Persistence_intervals_with_distances : public Persistence_intervals +{ +public: + using Persistence_intervals::Persistence_intervals; + + /** + *Computations of distance from the current persistnce diagram to the persistence diagram given as a parameter of this function. + *The last but one parameter, power, is here in case we would like to compute p=th Wasserstein distance. At the moment, this method only implement Bottleneck distance, + * which is infinity Wasserstein distance. Therefore any power which is not the default std::numeric_limits< double >::max() will be ignored and an + * exception will be thrown. + * The last parameter, tolerance, it is an additiv error of the approimation, set by default to zero. + **/ + double distance( const Persistence_intervals_with_distances& second , double power = std::numeric_limits< double >::max() , double tolerance = 0) const + { + if ( power >= std::numeric_limits< double >::max() ) + { + return Gudhi::persistence_diagram::bottleneck_distance(this->intervals, second.intervals, tolerance); + } + else + { + std::cerr << "At the moment Gudhi do not support Wasserstein distances. We only support Bottleneck distance." << std::endl; + throw "At the moment Gudhi do not support Wasserstein distances. We only support Bottleneck distance."; + } + } +}; + + +}//namespace gudhi stat +}//namespace gudhi + +#endif diff --git a/src/Gudhi_stat/include/gudhi/Persistence_landscape.h b/src/Gudhi_stat/include/gudhi/Persistence_landscape.h new file mode 100644 index 00000000..9150e507 --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/Persistence_landscape.h @@ -0,0 +1,1503 @@ +/* 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 (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 Persistence_landscapes_H +#define Persistence_landscapes_H + +//standard include +#include +#include +#include +#include +#include +#include +#include + + +//gudhi include +#include +#include + + + + +namespace Gudhi +{ +namespace Persistence_representations +{ + + + +//predeclaration +class Persistence_landscape; +template < typename operation > +Persistence_landscape operation_on_pair_of_landscapes( const Persistence_landscape& land1 , const Persistence_landscape& land2 ); + + + +/** + * A clas implementing persistence landascpes data structures. For theroretical desciritpion, please consult a paper ''Statistical topological data analysis using persistence landscapes'' by Peter Bubenik. + * For details of algorithms, please consult ''A persistence landscapes toolbox for topological statistics'' by Peter Bubenik and Pawel Dlotko. + * Persistence landscapes allow vertorization, computations of distances, computations of projections to Real, computations of averages and scalar products. Therefore they implement suitable interfaces. + * It implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product + * Note that at the moment, due to roundoff errors during the construction of persistence landscapes, elements which are different by 0.000005 are considered the same. If the scale in your persistence diagrams + * is comparable to this value, please rescale them before use this code. +**/ +class Persistence_landscape +{ +public: + /** + * Default constructor. + **/ + Persistence_landscape() + { + this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); + } + + /** + * Constructor that takes as an input a vector of birth-death pairs. + **/ + Persistence_landscape( const std::vector< std::pair< double , double > >& p ); + + /** + * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed + * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. + **/ + Persistence_landscape(const char* filename , size_t dimension = std::numeric_limits::max() ); + + + + /** + * This procedure loads a landscape from file. It erase all the data that was previously stored in this landscape. + **/ + void load_landscape_from_file( const char* filename ); + + + /** + * The procedure stores a landscape to a file. The file can be later used by a procedure load_landscape_from_file. + **/ + void print_to_file( const char* filename )const; + + + + /** + * This function compute integral of the landscape (defined formally as sum of integrals on R of all landscape functions) + **/ + double compute_integral_of_landscape()const; + + + /** + * This function compute integral of the 'level'-level of a landscape. + **/ + double compute_integral_of_a_level_of_a_landscape( size_t level )const; + + + /** + * This function compute integral of the landscape p-th power of a landscape (defined formally as sum of integrals on R of p-th powers of all landscape functions) + **/ + double compute_integral_of_landscape( double p )const;//this function compute integral of p-th power of landscape. + + + /** + * A function that computes the value of a landscape at a given point. The parameters of the function are: unsigned level and double x. + * The procedure will compute the value of the level-landscape at the point x. + **/ + double compute_value_at_a_given_point( unsigned level , double x )const; + + /** + * Writing landscape into a stream. A i-th level landscape starts with a string "lambda_i". Then the discontinuity points of the landscapes follows. + * Shall those points be joined with lines, we will obtain the i-th landscape function. + **/ + friend std::ostream& operator<<(std::ostream& out, Persistence_landscape& land ); + + template < typename operation > + friend Persistence_landscape operation_on_pair_of_landscapes( const Persistence_landscape& land1 , const Persistence_landscape& land2 ); + + + + + /** + *\private A function that compute sum of two landscapes. + **/ + friend Persistence_landscape add_two_landscapes ( const Persistence_landscape& land1 , const Persistence_landscape& land2 ) + { + return operation_on_pair_of_landscapes< std::plus >(land1,land2); + } + + /** + *\private A function that compute difference of two landscapes. + **/ + friend Persistence_landscape subtract_two_landscapes ( const Persistence_landscape& land1 , const Persistence_landscape& land2 ) + { + return operation_on_pair_of_landscapes< std::minus >(land1,land2); + } + + /** + * An operator +, that compute sum of two landscapes. + **/ + friend Persistence_landscape operator+( const Persistence_landscape& first , const Persistence_landscape& second ) + { + return add_two_landscapes( first,second ); + } + + /** + * An operator -, that compute difference of two landscapes. + **/ + friend Persistence_landscape operator-( const Persistence_landscape& first , const Persistence_landscape& second ) + { + return subtract_two_landscapes( first,second ); + } + + /** + * An operator * that allows multipilication of a landscape by a real number. + **/ + friend Persistence_landscape operator*( const Persistence_landscape& first , double con ) + { + return first.multiply_lanscape_by_real_number_not_overwrite(con); + } + + /** + * An operator * that allows multipilication of a landscape by a real number (order of parameters swapped). + **/ + friend Persistence_landscape operator*( double con , const Persistence_landscape& first ) + { + return first.multiply_lanscape_by_real_number_not_overwrite(con); + } + + /** + * Operator +=. The second parameter is persistence landscape. + **/ + Persistence_landscape operator += ( const Persistence_landscape& rhs ) + { + *this = *this + rhs; + return *this; + } + + /** + * Operator -=. The second parameter is a persistence landscape. + **/ + Persistence_landscape operator -= ( const Persistence_landscape& rhs ) + { + *this = *this - rhs; + return *this; + } + + + /** + * Operator *=. The second parameter is a real number by which the y values of all landscape functions are multiplied. The x-values remain unchanged. + **/ + Persistence_landscape operator *= ( double x ) + { + *this = *this*x; + return *this; + } + + /** + * Operator /=. The second parameter is a real number. + **/ + Persistence_landscape operator /= ( double x ) + { + if ( x == 0 )throw( "In operator /=, division by 0. Program terminated." ); + *this = *this * (1/x); + return *this; + } + + /** + * An operator to compare two persistence landscapes. + **/ + bool operator == ( const Persistence_landscape& rhs )const; + + + /** + * An operator to compare two persistence landscapes. + **/ + bool operator != ( const Persistence_landscape& rhs )const + { + return !((*this) == rhs); + } + + + /** + * Computations of maximum (y) value of landscape. + **/ + double compute_maximum()const + { + double maxValue = 0; + if ( this->land.size() ) + { + maxValue = -std::numeric_limits::max(); + for ( size_t i = 0 ; i != this->land[0].size() ; ++i ) + { + if ( this->land[0][i].second > maxValue )maxValue = this->land[0][i].second; + } + } + return maxValue; + } + + + /** + *\private Computations of minimum (y) value of landscape. + **/ + double compute_minimum()const + { + double minValue = 0; + if ( this->land.size() ) + { + minValue = std::numeric_limits::max(); + for ( size_t i = 0 ; i != this->land[0].size() ; ++i ) + { + if ( this->land[0][i].second < minValue )minValue = this->land[0][i].second; + } + } + return minValue; + } + + /** + *\private Computations of a \f$L^i\f$ norm of landscape, where i is the input parameter. + **/ + double compute_norm_of_landscape( double i ) + { + Persistence_landscape l; + if ( i < std::numeric_limits< double >::max() ) + { + return compute_distance_of_landscapes(*this,l,i); + } + else + { + return compute_max_norm_distance_of_landscapes(*this,l); + } + } + + /** + * An operator to compute the value of a landscape in the level 'level' at the argument 'x'. + **/ + double operator()(unsigned level,double x)const{return this->compute_value_at_a_given_point(level,x);} + + /** + *\private Computations of \f$L^{\infty}\f$ distance between two landscapes. + **/ + friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second ); + //friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , unsigned& nrOfLand , double&x , double& y1, double& y2 ); + + + /** + *\private Computations of \f$L^{p}\f$ distance between two landscapes. p is the parameter of the procedure. + **/ + friend double compute_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , double p ); + + + + /** + * Function to compute absolute value of a PL function. The representation of persistence landscapes allow to store general PL-function. When computing distance betwen two landscapes, we compute difference between + * them. In this case, a general PL-function with negative value can appear as a result. Then in order to compute distance, we need to take its absolute value. This is the purpose of this procedure. + **/ + Persistence_landscape abs(); + + /** + * Computes the number of landscape functions. + **/ + size_t size()const{return this->land.size(); } + + /** + * Computate maximal value of lambda-level landscape. + **/ + double find_max( unsigned lambda )const; + + /** + *\private Function to compute inner (scalar) product of two landscapes. + **/ + friend double compute_inner_product( const Persistence_landscape& l1 , const Persistence_landscape& l2 ); + + + + + + + + + + + + + + + + //Implementations of functions for various concepts. + + /** + * The number of projections to R is defined to the number of nonzero landscape functions. I-th projection is an integral of i-th landscape function over whole R. + * This function is required by the Real_valued_topological_data concept. + **/ + double project_to_R( int number_of_function )const + { + return this->compute_integral_of_a_level_of_a_landscape( (size_t)number_of_function ); + } + + /** + * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. + **/ + size_t number_of_projections_to_R()const + { + return this->number_of_functions_for_projections_to_reals; + } + + /** + * This function produce a vector of doubles based on a landscape. It is required in a concept Vectorized_topological_data + */ + std::vector vectorize( int number_of_function )const + { + //TODO, think of something smarter over here + std::vector v; + if ( (size_t)number_of_function > this->land.size() ) + { + return v; + } + v.reserve( this->land[number_of_function].size() ); + for ( size_t i = 0 ; i != this->land[number_of_function].size() ; ++i ) + { + v.push_back( this->land[number_of_function][i].second ); + } + return v; + } + /** + * This function return the number of functions that allows vectorization of persistence laandscape. It is required in a concept Vectorized_topological_data. + **/ + size_t number_of_vectorize_functions()const + { + return this->number_of_functions_for_vectorization; + } + + /** + * A function to compute averaged persistence landscape, based on vector of persistence landscapes. + * This function is required by Topological_data_with_averages concept. + **/ + void compute_average( const std::vector< Persistence_landscape* >& to_average ) + { + bool dbg = false; + + if ( dbg ){std::cerr << "to_average.size() : " << to_average.size() << std::endl;} + + std::vector< Persistence_landscape* > nextLevelMerge( to_average.size() ); + for ( size_t i = 0 ; i != to_average.size() ; ++i ) + { + nextLevelMerge[i] = to_average[i]; + } + bool is_this_first_level = true;//in the loop, we will create dynamically a unmber of intermediate complexes. We have to clean that up, but we cannot erase the initial andscapes we have + //to average. In this case, we simply check if the nextLevelMerge are the input landscapes or the ones created in that loop by usig this extra variable. + + while ( nextLevelMerge.size() != 1 ) + { + if ( dbg ){std::cerr << "nextLevelMerge.size() : " << nextLevelMerge.size() << std::endl;} + std::vector< Persistence_landscape* > nextNextLevelMerge; + nextNextLevelMerge.reserve( to_average.size() ); + for ( size_t i = 0 ; i < nextLevelMerge.size() ; i=i+2 ) + { + if ( dbg ){std::cerr << "i : " << i << std::endl;} + Persistence_landscape* l = new Persistence_landscape; + if ( i+1 != nextLevelMerge.size() ) + { + (*l) = (*nextLevelMerge[i])+(*nextLevelMerge[i+1]); + } + else + { + (*l) = *nextLevelMerge[i]; + } + nextNextLevelMerge.push_back( l ); + } + if ( dbg ){std::cerr << "After this iteration \n";getchar();} + + if ( !is_this_first_level ) + { + //deallocate the memory if the vector nextLevelMerge do not consist of the initial landscapes + for ( size_t i = 0 ; i != nextLevelMerge.size() ; ++i ) + { + delete nextLevelMerge[i]; + } + } + is_this_first_level = false; + nextLevelMerge.swap(nextNextLevelMerge); + } + (*this) = (*nextLevelMerge[0]); + (*this) *= 1/( (double)to_average.size() ); + } + + + /** + * A function to compute distance between persistence landscape. + * The parameter of this functionis a Persistence_landscape. + * This function is required in Topological_data_with_distances concept. + * For max norm distance, set power to std::numeric_limits::max() + **/ + double distance( const Persistence_landscape& second , double power = 1 )const + { + if ( power < std::numeric_limits::max() ) + { + return compute_distance_of_landscapes( *this , second , power ); + } + else + { + return compute_max_norm_distance_of_landscapes( *this , second ); + } + } + + + /** + * A function to compute scalar product of persistence landscapes. + * The parameter of this functionis a Persistence_landscape. + * This function is required in Topological_data_with_scalar_product concept. + **/ + double compute_scalar_product( const Persistence_landscape& second )const + { + return compute_inner_product( (*this) , second ); + } + //end of implementation of functions needed for concepts. + + + // + // This procedure returns x-range of a given level persistence landscape. If a default value is used, the x-range + //of 0th level landscape is given (and this range contains the ranges of all other landscapes). + // + //std::pair< double , double > get_x_range( size_t level = 0 )const + //{ + // std::pair< double , double > result; + // if ( level < this->land.size() ) + // { + // result = std::make_pair( this->land[level][1].first , this->land[level][ this->land[level].size() - 2 ].first ); + // } + // else + // { + // result = std::make_pair( 0,0 ); + // } + // return result; + //} + + /** + * This procedure returns y-range of a given level persistence landscape. If a default value is used, the y-range + * of 0th level landscape is given (and this range contains the ranges of all other landscapes). + **/ + std::pair< double , double > get_y_range( size_t level = 0 )const + { + std::pair< double , double > result; + if ( level < this->land.size() ) + { + double maxx = this->compute_maximum(); + double minn = this->compute_minimum(); + result = std::make_pair( minn , maxx ); + } + else + { + result = std::make_pair( 0,0 ); + } + return result; + } + + + + //a function used to create a gnuplot script for visualization of landscapes + void plot( const char* filename, double xRangeBegin = std::numeric_limits::max() , double xRangeEnd = std::numeric_limits::max() , + double yRangeBegin = std::numeric_limits::max() , double yRangeEnd = std::numeric_limits::max(), + int from = std::numeric_limits::max(), int to = std::numeric_limits::max() ); + + +protected: + std::vector< std::vector< std::pair > > land; + size_t number_of_functions_for_vectorization; + size_t number_of_functions_for_projections_to_reals; + + void construct_persistence_landscape_from_barcode( const std::vector< std::pair< double , double > > & p ); + Persistence_landscape multiply_lanscape_by_real_number_not_overwrite( double x )const; + void multiply_lanscape_by_real_number_overwrite( double x ); + friend double compute_maximal_distance_non_symmetric( const Persistence_landscape& pl1, const Persistence_landscape& pl2 ); + + void set_up_numbers_of_functions_for_vectorization_and_projections_to_reals() + { + //warning, this function can be only called after filling in the intervals vector. + this->number_of_functions_for_vectorization = this->land.size(); + this->number_of_functions_for_projections_to_reals = this->land.size(); + } +}; + + + + + + + + +Persistence_landscape::Persistence_landscape(const char* filename , size_t dimension) +{ + bool dbg = false; + + if ( dbg ) + { + std::cerr << "Using constructor : Persistence_landscape(char* filename)" << std::endl; + } + std::vector< std::pair< double , double > > barcode; + if ( dimension == std::numeric_limits::max() ) + { + barcode = read_persistence_intervals_in_one_dimension_from_file( filename ); + } + else + { + barcode = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); + } + this->construct_persistence_landscape_from_barcode( barcode ); + this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); +} + + +bool operatorEqualDbg = false; +bool Persistence_landscape::operator == ( const Persistence_landscape& rhs )const +{ + if ( this->land.size() != rhs.land.size() ) + { + if (operatorEqualDbg)std::cerr << "1\n"; + return false; + } + for ( size_t level = 0 ; level != this->land.size() ; ++level ) + { + if ( this->land[level].size() != rhs.land[level].size() ) + { + if (operatorEqualDbg)std::cerr << "this->land[level].size() : " << this->land[level].size() << "\n"; + if (operatorEqualDbg)std::cerr << "rhs.land[level].size() : " << rhs.land[level].size() << "\n"; + if (operatorEqualDbg)std::cerr << "2\n"; + return false; + } + for ( size_t i = 0 ; i != this->land[level].size() ; ++i ) + { + if ( !( almost_equal(this->land[level][i].first , rhs.land[level][i].first) && almost_equal(this->land[level][i].second , rhs.land[level][i].second) ) ) + { + //std::cerr<< this->land[level][i].first << " , " << rhs.land[level][i].first << " and " << this->land[level][i].second << " , " << rhs.land[level][i].second << std::endl; + if (operatorEqualDbg)std::cerr << "this->land[level][i] : " << this->land[level][i].first << " " << this->land[level][i].second << "\n"; + if (operatorEqualDbg)std::cerr << "rhs.land[level][i] : " << rhs.land[level][i].first << " " << rhs.land[level][i].second << "\n"; + if (operatorEqualDbg)std::cerr << "3\n"; + return false; + } + } + } + return true; +} + + + + +Persistence_landscape::Persistence_landscape( const std::vector< std::pair< double , double > > & p ) +{ + this->construct_persistence_landscape_from_barcode( p ); + this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); +} + + +void Persistence_landscape::construct_persistence_landscape_from_barcode( const std::vector< std::pair< double , double > > & p ) +{ + bool dbg = false; + if ( dbg ){std::cerr << "Persistence_landscape::Persistence_landscape( const std::vector< std::pair< double , double > >& p )" << std::endl;} + + //this is a general algorithm to construct persistence landscapes. + std::vector< std::pair > bars; + bars.insert( bars.begin() , p.begin() , p.end() ); + std::sort( bars.begin() , bars.end() , compare_points_sorting ); + + if (dbg) + { + std::cerr << "Bars : \n"; + for ( size_t i = 0 ; i != bars.size() ; ++i ) + { + std::cerr << bars[i].first << " " << bars[i].second << "\n"; + } + getchar(); + } + + std::vector< std::pair > characteristicPoints(p.size()); + for ( size_t i = 0 ; i != bars.size() ; ++i ) + { + characteristicPoints[i] = std::make_pair((bars[i].first+bars[i].second)/2.0 , (bars[i].second - bars[i].first)/2.0); + } + std::vector< std::vector< std::pair > > Persistence_landscape; + while ( !characteristicPoints.empty() ) + { + if(dbg) + { + for ( size_t i = 0 ; i != characteristicPoints.size() ; ++i ) + { + std::cout << "(" << characteristicPoints[i].first << " " << characteristicPoints[i].second << ")\n"; + } + std::cin.ignore(); + } + + std::vector< std::pair > lambda_n; + lambda_n.push_back( std::make_pair( -std::numeric_limits::max() , 0 ) ); + lambda_n.push_back( std::make_pair(minus_length(characteristicPoints[0]),0) ); + lambda_n.push_back( characteristicPoints[0] ); + + if (dbg) + { + std::cerr << "1 Adding to lambda_n : (" << -std::numeric_limits::max() << " " << 0 << ") , (" << minus_length(characteristicPoints[0]) << " " << 0 << ") , (" << characteristicPoints[0].first << " " << characteristicPoints[0].second << ") \n"; + } + + size_t i = 1; + std::vector< std::pair > newCharacteristicPoints; + while ( i < characteristicPoints.size() ) + { + size_t p = 1; + if ( (minus_length(characteristicPoints[i]) >= minus_length(lambda_n[lambda_n.size()-1])) && (birth_plus_deaths(characteristicPoints[i]) > birth_plus_deaths(lambda_n[lambda_n.size()-1])) ) + { + if ( minus_length(characteristicPoints[i]) < birth_plus_deaths(lambda_n[lambda_n.size()-1]) ) + { + std::pair point = std::make_pair( (minus_length(characteristicPoints[i])+birth_plus_deaths(lambda_n[lambda_n.size()-1]))/2 , (birth_plus_deaths(lambda_n[lambda_n.size()-1])-minus_length(characteristicPoints[i]))/2 ); + lambda_n.push_back( point ); + if (dbg) + { + std::cerr << "2 Adding to lambda_n : (" << point.first << " " << point.second << ")\n"; + } + + + if ( dbg ) + { + std::cerr << "characteristicPoints[i+p] : " << characteristicPoints[i+p].first << " " << characteristicPoints[i+p].second << "\n"; + std::cerr << "point : " << point.first << " " << point.second << "\n"; + getchar(); + } + + while ( (i+p < characteristicPoints.size() ) && ( almost_equal(minus_length(point),minus_length(characteristicPoints[i+p])) ) && ( birth_plus_deaths(point) <= birth_plus_deaths(characteristicPoints[i+p]) ) ) + { + newCharacteristicPoints.push_back( characteristicPoints[i+p] ); + if (dbg) + { + std::cerr << "3.5 Adding to newCharacteristicPoints : (" << characteristicPoints[i+p].first << " " << characteristicPoints[i+p].second << ")\n"; + getchar(); + } + ++p; + } + + + newCharacteristicPoints.push_back( point ); + if (dbg) + { + std::cerr << "4 Adding to newCharacteristicPoints : (" << point.first << " " << point.second << ")\n"; + } + + + while ( (i+p < characteristicPoints.size() ) && ( minus_length(point) <= minus_length(characteristicPoints[i+p]) ) && (birth_plus_deaths(point)>=birth_plus_deaths(characteristicPoints[i+p])) ) + { + newCharacteristicPoints.push_back( characteristicPoints[i+p] ); + if (dbg) + { + std::cerr << "characteristicPoints[i+p] : " << characteristicPoints[i+p].first << " " << characteristicPoints[i+p].second << "\n"; + std::cerr << "point : " << point.first << " " << point.second << "\n"; + std::cerr << "characteristicPoints[i+p] birth and death : " << minus_length(characteristicPoints[i+p]) << " , " << birth_plus_deaths(characteristicPoints[i+p]) << "\n"; + std::cerr << "point birth and death : " << minus_length(point) << " , " << birth_plus_deaths(point) << "\n"; + + std::cerr << "3 Adding to newCharacteristicPoints : (" << characteristicPoints[i+p].first << " " << characteristicPoints[i+p].second << ")\n"; + getchar(); + } + ++p; + } + + } + else + { + lambda_n.push_back( std::make_pair( birth_plus_deaths(lambda_n[lambda_n.size()-1]) , 0 ) ); + lambda_n.push_back( std::make_pair( minus_length(characteristicPoints[i]) , 0 ) ); + if (dbg) + { + std::cerr << "5 Adding to lambda_n : (" << birth_plus_deaths(lambda_n[lambda_n.size()-1]) << " " << 0 << ")\n"; + std::cerr << "5 Adding to lambda_n : (" << minus_length(characteristicPoints[i]) << " " << 0 << ")\n"; + } + } + lambda_n.push_back( characteristicPoints[i] ); + if (dbg) + { + std::cerr << "6 Adding to lambda_n : (" << characteristicPoints[i].first << " " << characteristicPoints[i].second << ")\n"; + } + } + else + { + newCharacteristicPoints.push_back( characteristicPoints[i] ); + if (dbg) + { + std::cerr << "7 Adding to newCharacteristicPoints : (" << characteristicPoints[i].first << " " << characteristicPoints[i].second << ")\n"; + } + } + i = i+p; + } + lambda_n.push_back( std::make_pair(birth_plus_deaths(lambda_n[lambda_n.size()-1]),0) ); + lambda_n.push_back( std::make_pair( std::numeric_limits::max() , 0 ) ); + + characteristicPoints = newCharacteristicPoints; + + lambda_n.erase(std::unique(lambda_n.begin(), lambda_n.end()), lambda_n.end()); + this->land.push_back( lambda_n ); + } +} + + + +//this function find maximum of lambda_n +double Persistence_landscape::find_max( unsigned lambda )const +{ + if ( this->land.size() < lambda )return 0; + double maximum = -std::numeric_limits::max(); + for ( size_t i = 0 ; i != this->land[lambda].size() ; ++i ) + { + if ( this->land[lambda][i].second > maximum )maximum = this->land[lambda][i].second; + } + return maximum; +} + + +double Persistence_landscape::compute_integral_of_landscape()const +{ + double result = 0; + for ( size_t i = 0 ; i != this->land.size() ; ++i ) + { + for ( size_t nr = 2 ; nr != this->land[i].size()-1 ; ++nr ) + { + //it suffices to compute every planar integral and then sum them ap for each lambda_n + result += 0.5*( this->land[i][nr].first - this->land[i][nr-1].first )*(this->land[i][nr].second + this->land[i][nr-1].second); + } + } + return result; +} + +double Persistence_landscape::compute_integral_of_a_level_of_a_landscape( size_t level )const +{ + double result = 0; + if ( level >= this->land.size() ) + { + //this landscape function is constantly equal 0, so is the intergral. + return result; + } + //also negative landscapes are assumed to be zero. + if ( level < 0 )return 0; + + for ( size_t nr = 2 ; nr != this->land[ level ].size()-1 ; ++nr ) + { + //it suffices to compute every planar integral and then sum them ap for each lambda_n + result += 0.5*( this->land[ level ][nr].first - this->land[ level ][nr-1].first )*(this->land[ level ][nr].second + this->land[ level ][nr-1].second); + } + + return result; +} + + +double Persistence_landscape::compute_integral_of_landscape( double p )const +{ + bool dbg = false; + double result = 0; + for ( size_t i = 0 ; i != this->land.size() ; ++i ) + { + for ( size_t nr = 2 ; nr != this->land[i].size()-1 ; ++nr ) + { + if (dbg)std::cout << "nr : " << nr << "\n"; + //In this interval, the landscape has a form f(x) = ax+b. We want to compute integral of (ax+b)^p = 1/a * (ax+b)^{p+1}/(p+1) + std::pair coef = compute_parameters_of_a_line( this->land[i][nr] , this->land[i][nr-1] ); + double a = coef.first; + double b = coef.second; + + if (dbg)std::cout << "(" << this->land[i][nr].first << "," << this->land[i][nr].second << ") , " << this->land[i][nr-1].first << "," << this->land[i][nr].second << ")" << std::endl; + if ( this->land[i][nr].first == this->land[i][nr-1].first )continue; + if ( a != 0 ) + { + result += 1/(a*(p+1)) * ( pow((a*this->land[i][nr].first+b),p+1) - pow((a*this->land[i][nr-1].first+b),p+1)); + } + else + { + result += ( this->land[i][nr].first - this->land[i][nr-1].first )*( pow(this->land[i][nr].second,p) ); + } + if ( dbg ) + { + std::cout << "a : " <land. +double Persistence_landscape::compute_value_at_a_given_point( unsigned level , double x )const +{ + bool compute_value_at_a_given_pointDbg = false; + //in such a case lambda_level = 0. + if ( level > this->land.size() ) return 0; + + //we know that the points in this->land[level] are ordered according to x coordinate. Therefore, we can find the point by using bisection: + unsigned coordBegin = 1; + unsigned coordEnd = this->land[level].size()-2; + + if ( compute_value_at_a_given_pointDbg ) + { + std::cerr << "Here \n"; + std::cerr << "x : " << x << "\n"; + std::cerr << "this->land[level][coordBegin].first : " << this->land[level][coordBegin].first << "\n"; + std::cerr << "this->land[level][coordEnd].first : " << this->land[level][coordEnd].first << "\n"; + } + + //in this case x is outside the support of the landscape, therefore the value of the landscape is 0. + if ( x <= this->land[level][coordBegin].first )return 0; + if ( x >= this->land[level][coordEnd].first )return 0; + + if (compute_value_at_a_given_pointDbg)std::cerr << "Entering to the while loop \n"; + + while ( coordBegin+1 != coordEnd ) + { + if (compute_value_at_a_given_pointDbg) + { + std::cerr << "coordBegin : " << coordBegin << "\n"; + std::cerr << "coordEnd : " << coordEnd << "\n"; + std::cerr << "this->land[level][coordBegin].first : " << this->land[level][coordBegin].first << "\n"; + std::cerr << "this->land[level][coordEnd].first : " << this->land[level][coordEnd].first << "\n"; + } + + + unsigned newCord = (unsigned)floor((coordEnd+coordBegin)/2.0); + + if (compute_value_at_a_given_pointDbg) + { + std::cerr << "newCord : " << newCord << "\n"; + std::cerr << "this->land[level][newCord].first : " << this->land[level][newCord].first << "\n"; + std::cin.ignore(); + } + + if ( this->land[level][newCord].first <= x ) + { + coordBegin = newCord; + if ( this->land[level][newCord].first == x )return this->land[level][newCord].second; + } + else + { + coordEnd = newCord; + } + } + + if (compute_value_at_a_given_pointDbg) + { + std::cout << "x : " << x << " is between : " << this->land[level][coordBegin].first << " a " << this->land[level][coordEnd].first << "\n"; + std::cout << "the y coords are : " << this->land[level][coordBegin].second << " a " << this->land[level][coordEnd].second << "\n"; + std::cerr << "coordBegin : " << coordBegin << "\n"; + std::cerr << "coordEnd : " << coordEnd << "\n"; + std::cin.ignore(); + } + return function_value( this->land[level][coordBegin] , this->land[level][coordEnd] , x ); +} + +std::ostream& operator<<(std::ostream& out, Persistence_landscape& land ) +{ + for ( size_t level = 0 ; level != land.land.size() ; ++level ) + { + out << "Lambda_" << level << ":" << std::endl; + for ( size_t i = 0 ; i != land.land[level].size() ; ++i ) + { + if ( land.land[level][i].first == -std::numeric_limits::max() ) + { + out << "-inf"; + } + else + { + if ( land.land[level][i].first == std::numeric_limits::max() ) + { + out << "+inf"; + } + else + { + out << land.land[level][i].first; + } + } + out << " , " << land.land[level][i].second << std::endl; + } + } + return out; +} + + + + +void Persistence_landscape::multiply_lanscape_by_real_number_overwrite( double x ) +{ + for ( size_t dim = 0 ; dim != this->land.size() ; ++dim ) + { + for ( size_t i = 0 ; i != this->land[dim].size() ; ++i ) + { + this->land[dim][i].second *= x; + } + } +} + +bool AbsDbg = false; +Persistence_landscape Persistence_landscape::abs() +{ + Persistence_landscape result; + for ( size_t level = 0 ; level != this->land.size() ; ++level ) + { + if ( AbsDbg ){ std::cout << "level: " << level << std::endl; } + std::vector< std::pair > lambda_n; + lambda_n.push_back( std::make_pair( -std::numeric_limits::max() , 0 ) ); + for ( size_t i = 1 ; i != this->land[level].size() ; ++i ) + { + if ( AbsDbg ){std::cout << "this->land[" << level << "][" << i << "] : " << this->land[level][i].first << " " << this->land[level][i].second << std::endl;} + //if a line segment between this->land[level][i-1] and this->land[level][i] crosses the x-axis, then we have to add one landscape point t oresult + if ( (this->land[level][i-1].second)*(this->land[level][i].second) < 0 ) + { + double zero = find_zero_of_a_line_segment_between_those_two_points( this->land[level][i-1] , this->land[level][i] ); + + lambda_n.push_back( std::make_pair(zero , 0) ); + lambda_n.push_back( std::make_pair(this->land[level][i].first , fabs(this->land[level][i].second)) ); + if ( AbsDbg ) + { + std::cout << "Adding pair : (" << zero << ",0)" << std::endl; + std::cout << "In the same step adding pair : (" << this->land[level][i].first << "," << fabs(this->land[level][i].second) << ") " << std::endl; + std::cin.ignore(); + } + } + else + { + lambda_n.push_back( std::make_pair(this->land[level][i].first , fabs(this->land[level][i].second)) ); + if ( AbsDbg ) + { + std::cout << "Adding pair : (" << this->land[level][i].first << "," << fabs(this->land[level][i].second) << ") " << std::endl; + std::cin.ignore(); + } + } + } + result.land.push_back( lambda_n ); + } + return result; +} + + +Persistence_landscape Persistence_landscape::multiply_lanscape_by_real_number_not_overwrite( double x )const +{ + std::vector< std::vector< std::pair > > result(this->land.size()); + for ( size_t dim = 0 ; dim != this->land.size() ; ++dim ) + { + std::vector< std::pair > lambda_dim( this->land[dim].size() ); + for ( size_t i = 0 ; i != this->land[dim].size() ; ++i ) + { + lambda_dim[i] = std::make_pair( this->land[dim][i].first , x*this->land[dim][i].second ); + } + result[dim] = lambda_dim; + } + Persistence_landscape res; + //CHANGE + //res.land = result; + res.land.swap(result); + return res; +}//multiply_lanscape_by_real_number_overwrite + + +void Persistence_landscape::print_to_file( const char* filename )const +{ + std::ofstream write; + write.open(filename); + for ( size_t dim = 0 ; dim != this->land.size() ; ++dim ) + { + write << "#lambda_" << dim << std::endl; + for ( size_t i = 1 ; i != this->land[dim].size()-1 ; ++i ) + { + write << this->land[dim][i].first << " " << this->land[dim][i].second << std::endl; + } + } + write.close(); +} + +void Persistence_landscape::load_landscape_from_file( const char* filename ) +{ + bool dbg = false; + //removing the current content of the persistence landscape. + this->land.clear(); + + + //this constructor reads persistence landscape form a file. This file have to be created by this software beforehead + std::ifstream in; + in.open( filename ); + if ( !in.good() ) + { + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; + } + + std::string line; + std::vector< std::pair > landscapeAtThisLevel; + + bool isThisAFirsLine = true; + while ( !in.eof() ) + { + getline(in,line); + if ( !(line.length() == 0 || line[0] == '#') ) + { + std::stringstream lineSS; + lineSS << line; + double beginn, endd; + lineSS >> beginn; + lineSS >> endd; + landscapeAtThisLevel.push_back( std::make_pair( beginn , endd ) ); + if (dbg){std::cerr << "Reading a pont : " << beginn << " , " << endd << std::endl;} + } + else + { + if (dbg) + { + std::cout << "IGNORE LINE\n"; + getchar(); + } + if ( !isThisAFirsLine ) + { + landscapeAtThisLevel.push_back( std::make_pair( std::numeric_limits::max() , 0 ) ); + this->land.push_back(landscapeAtThisLevel); + std::vector< std::pair > newLevelOdLandscape; + landscapeAtThisLevel.swap(newLevelOdLandscape); + } + landscapeAtThisLevel.push_back( std::make_pair( -std::numeric_limits::max() , 0 ) ); + isThisAFirsLine = false; + } + } + if ( landscapeAtThisLevel.size() > 1 ) + { + //seems that the last line of the file is not finished with the newline sign. We need to put what we have in landscapeAtThisLevel to the constructed landscape. + landscapeAtThisLevel.push_back( std::make_pair( std::numeric_limits::max() , 0 ) ); + this->land.push_back(landscapeAtThisLevel); + } + + in.close(); +} + + +template < typename T > +Persistence_landscape operation_on_pair_of_landscapes ( const Persistence_landscape& land1 , const Persistence_landscape& land2 ) +{ + bool operation_on_pair_of_landscapesDBG = false; + if ( operation_on_pair_of_landscapesDBG ){std::cout << "operation_on_pair_of_landscapes\n";std::cin.ignore();} + Persistence_landscape result; + std::vector< std::vector< std::pair > > land( std::max( land1.land.size() , land2.land.size() ) ); + result.land = land; + T oper; + + if ( operation_on_pair_of_landscapesDBG ) + { + for ( size_t i = 0 ; i != std::min( land1.land.size() , land2.land.size() ) ; ++i ) + { + std::cerr << "land1.land[" << i << "].size() : " << land1.land[i].size() << std::endl; + std::cerr << "land2.land[" << i << "].size() : " << land2.land[i].size() << std::endl; + } + getchar(); + } + + for ( size_t i = 0 ; i != std::min( land1.land.size() , land2.land.size() ) ; ++i ) + { + std::vector< std::pair > lambda_n; + size_t p = 0; + size_t q = 0; + while ( (p+1 < land1.land[i].size()) && (q+1 < land2.land[i].size()) ) + { + if ( operation_on_pair_of_landscapesDBG ) + { + std::cerr << "p : " << p << "\n"; + std::cerr << "q : " << q << "\n"; + std::cerr << "land1.land.size() : " << land1.land.size() << std::endl; + std::cerr << "land2.land.size() : " << land2.land.size() << std::endl; + std::cerr << "land1.land[" << i << "].size() : " << land1.land[i].size() << std::endl; + std::cerr << "land2.land[" << i << "].size() : " << land2.land[i].size() << std::endl; + std::cout << "land1.land[i][p].first : " << land1.land[i][p].first << "\n"; + std::cout << "land2.land[i][q].first : " << land2.land[i][q].first << "\n"; + //getchar(); + } + + if ( land1.land[i][p].first < land2.land[i][q].first ) + { + if ( operation_on_pair_of_landscapesDBG ) + { + std::cout << "first \n"; + std::cout << " function_value(land2.land[i][q-1],land2.land[i][q],land1.land[i][p].first) : "<< function_value(land2.land[i][q-1],land2.land[i][q],land1.land[i][p].first) << "\n"; + //std::cout << "oper( " << land1.land[i][p].second <<"," << function_value(land2.land[i][q-1],land2.land[i][q],land1.land[i][p].first) << " : " << oper( land1.land[i][p].second , function_value(land2.land[i][q-1],land2.land[i][q],land1.land[i][p].first) ) << "\n"; + } + lambda_n.push_back( + std::make_pair( + land1.land[i][p].first , + oper( (double)land1.land[i][p].second , function_value(land2.land[i][q-1],land2.land[i][q],land1.land[i][p].first) ) + ) + ); + ++p; + continue; + } + if ( land1.land[i][p].first > land2.land[i][q].first ) + { + if ( operation_on_pair_of_landscapesDBG ) + { + std::cout << "Second \n"; + std::cout << "function_value("<< land1.land[i][p-1].first << " " << land1.land[i][p-1].second <<" ,"<< land1.land[i][p].first << " " << land1.land[i][p].second <<", " << land2.land[i][q].first<<" ) : " << function_value( land1.land[i][p-1] , land1.land[i][p-1] ,land2.land[i][q].first ) << "\n"; + std::cout << "oper( " << function_value( land1.land[i][p] , land1.land[i][p-1] ,land2.land[i][q].first ) <<"," << land2.land[i][q].second <<" : " << oper( land2.land[i][q].second , function_value( land1.land[i][p] , land1.land[i][p-1] ,land2.land[i][q].first ) ) << "\n"; + } + lambda_n.push_back( std::make_pair( land2.land[i][q].first , oper( function_value( land1.land[i][p] , land1.land[i][p-1] ,land2.land[i][q].first ) , land2.land[i][q].second ) ) ); + ++q; + continue; + } + if ( land1.land[i][p].first == land2.land[i][q].first ) + { + if (operation_on_pair_of_landscapesDBG)std::cout << "Third \n"; + lambda_n.push_back( std::make_pair( land2.land[i][q].first , oper( land1.land[i][p].second , land2.land[i][q].second ) ) ); + ++p;++q; + } + if (operation_on_pair_of_landscapesDBG){std::cout << "Next iteration \n";} + } + while ( (p+1 < land1.land[i].size())&&(q+1 >= land2.land[i].size()) ) + { + if (operation_on_pair_of_landscapesDBG) + { + std::cout << "New point : " << land1.land[i][p].first << " oper(land1.land[i][p].second,0) : " << oper(land1.land[i][p].second,0) << std::endl; + } + lambda_n.push_back( std::make_pair(land1.land[i][p].first , oper(land1.land[i][p].second,0) ) ); + ++p; + } + while ( (p+1 >= land1.land[i].size())&&(q+1 < land2.land[i].size()) ) + { + if (operation_on_pair_of_landscapesDBG) + { + std::cout << "New point : " << land2.land[i][q].first << " oper(0,land2.land[i][q].second) : " << oper(0,land2.land[i][q].second) << std::endl; + } + lambda_n.push_back( std::make_pair(land2.land[i][q].first , oper(0,land2.land[i][q].second) ) ); + ++q; + } + lambda_n.push_back( std::make_pair( std::numeric_limits::max() , 0 ) ); + //CHANGE + //result.land[i] = lambda_n; + result.land[i].swap(lambda_n); + } + if ( land1.land.size() > std::min( land1.land.size() , land2.land.size() ) ) + { + if (operation_on_pair_of_landscapesDBG){std::cout << "land1.land.size() > std::min( land1.land.size() , land2.land.size() )" << std::endl;} + for ( size_t i = std::min( land1.land.size() , land2.land.size() ) ; i != std::max( land1.land.size() , land2.land.size() ) ; ++i ) + { + std::vector< std::pair > lambda_n( land1.land[i] ); + for ( size_t nr = 0 ; nr != land1.land[i].size() ; ++nr ) + { + lambda_n[nr] = std::make_pair( land1.land[i][nr].first , oper( land1.land[i][nr].second , 0 ) ); + } + //CHANGE + //result.land[i] = lambda_n; + result.land[i].swap(lambda_n); + } + } + if ( land2.land.size() > std::min( land1.land.size() , land2.land.size() ) ) + { + if (operation_on_pair_of_landscapesDBG){std::cout << "( land2.land.size() > std::min( land1.land.size() , land2.land.size() ) ) " << std::endl;} + for ( size_t i = std::min( land1.land.size() , land2.land.size() ) ; i != std::max( land1.land.size() , land2.land.size() ) ; ++i ) + { + std::vector< std::pair > lambda_n( land2.land[i] ); + for ( size_t nr = 0 ; nr != land2.land[i].size() ; ++nr ) + { + lambda_n[nr] = std::make_pair( land2.land[i][nr].first , oper( 0 , land2.land[i][nr].second ) ); + } + //CHANGE + //result.land[i] = lambda_n; + result.land[i].swap(lambda_n); + } + } + if ( operation_on_pair_of_landscapesDBG ){std::cout << "operation_on_pair_of_landscapes END\n";std::cin.ignore();} + return result; +}//operation_on_pair_of_landscapes + + + +double compute_maximal_distance_non_symmetric( const Persistence_landscape& pl1, const Persistence_landscape& pl2 ) +{ + bool dbg = false; + if (dbg)std::cerr << " compute_maximal_distance_non_symmetric \n"; + //this distance is not symmetric. It compute ONLY distance between inflection points of pl1 and pl2. + double maxDist = 0; + size_t minimalNumberOfLevels = std::min( pl1.land.size() , pl2.land.size() ); + for ( size_t level = 0 ; level != minimalNumberOfLevels ; ++ level ) + { + if (dbg) + { + std::cerr << "Level : " << level << std::endl; + std::cerr << "PL1 : \n"; + for ( size_t i = 0 ; i != pl1.land[level].size() ; ++i ) + { + std::cerr << "(" <=pl2.land[level][p2Count].first) && (pl1.land[level][i].first<=pl2.land[level][p2Count+1].first) )break; + p2Count++; + } + double val = fabs( function_value( pl2.land[level][p2Count] , pl2.land[level][p2Count+1] , pl1.land[level][i].first ) - pl1.land[level][i].second); + if ( maxDist <= val )maxDist = val; + + if (dbg) + { + std::cerr << pl1.land[level][i].first <<"in [" << pl2.land[level][p2Count].first << "," << pl2.land[level][p2Count+1].first <<"] \n"; + std::cerr << "pl1[level][i].second : " << pl1.land[level][i].second << std::endl; + std::cerr << "function_value( pl2[level][p2Count] , pl2[level][p2Count+1] , pl1[level][i].first ) : " << function_value( pl2.land[level][p2Count] , pl2.land[level][p2Count+1] , pl1.land[level][i].first ) << std::endl; + std::cerr << "val : " << val << std::endl; + std::cin.ignore(); + } + } + } + + if (dbg)std::cerr << "minimalNumberOfLevels : " << minimalNumberOfLevels << std::endl; + + if ( minimalNumberOfLevels < pl1.land.size() ) + { + for ( size_t level = minimalNumberOfLevels ; level != pl1.land.size() ; ++ level ) + { + for ( size_t i = 0 ; i != pl1.land[level].size() ; ++i ) + { + if (dbg)std::cerr << "pl1[level][i].second : " << pl1.land[level][i].second << std::endl; + if ( maxDist < pl1.land[level][i].second )maxDist = pl1.land[level][i].second; + } + } + } + return maxDist; +} + + + + +double compute_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , double p ) +{ + bool dbg = false; + //This is what we want to compute: (\int_{- \infty}^{+\infty}| first-second |^p)^(1/p). We will do it one step at a time: + + //first-second : + Persistence_landscape lan = first-second; + + //| first-second |: + lan = lan.abs(); + + if ( dbg ){std::cerr << "Abs of difference ; " << lan << std::endl;getchar();} + + if ( p < std::numeric_limits::max() ) + { + //\int_{- \infty}^{+\infty}| first-second |^p + double result; + if ( p != 1 ) + { + if ( dbg )std::cerr << "Power != 1, compute integral to the power p\n"; + result = lan.compute_integral_of_landscape( (double)p ); + } + else + { + if ( dbg )std::cerr << "Power = 1, compute integral \n"; + result = lan.compute_integral_of_landscape(); + } + //(\int_{- \infty}^{+\infty}| first-second |^p)^(1/p) + return pow( result , 1/(double)p ); + } + else + { + //p == infty + if ( dbg )std::cerr << "Power = infty, compute maximum \n"; + return lan.compute_maximum(); + } +} + +double compute_max_norm_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second ) +{ + return std::max( compute_maximal_distance_non_symmetric(first,second) , compute_maximal_distance_non_symmetric(second,first) ); +} + + +bool comparePairsForMerging( std::pair< double , unsigned > first , std::pair< double , unsigned > second ) +{ + return (first.first < second.first); +} + + + + +double compute_inner_product( const Persistence_landscape& l1 , const Persistence_landscape& l2 ) +{ + bool dbg = false; + double result = 0; + + for ( size_t level = 0 ; level != std::min( l1.size() , l2.size() ) ; ++level ) + { + if ( dbg ){std::cerr << "Computing inner product for a level : " << level << std::endl;getchar();} + if ( l1.land[level].size() * l2.land[level].size() == 0 )continue; + + //endpoints of the interval on which we will compute the inner product of two locally linear functions: + double x1 = -std::numeric_limits::max(); + double x2; + if ( l1.land[level][1].first < l2.land[level][1].first ) + { + x2 = l1.land[level][1].first; + } + else + { + x2 = l2.land[level][1].first; + } + + //iterators for the landscapes l1 and l2 + size_t l1It = 0; + size_t l2It = 0; + + while ( (l1It < l1.land[level].size()-1) && (l2It < l2.land[level].size()-1) ) + { + //compute the value of a inner product on a interval [x1,x2] + + double a,b,c,d; + + if ( l1.land[level][l1It+1].first != l1.land[level][l1It].first ) + { + a = (l1.land[level][l1It+1].second - l1.land[level][l1It].second)/(l1.land[level][l1It+1].first - l1.land[level][l1It].first); + } + else + { + a = 0; + } + b = l1.land[level][l1It].second - a*l1.land[level][l1It].first; + if ( l2.land[level][l2It+1].first != l2.land[level][l2It].first ) + { + c = (l2.land[level][l2It+1].second - l2.land[level][l2It].second)/(l2.land[level][l2It+1].first - l2.land[level][l2It].first); + } + else + { + c = 0; + } + d = l2.land[level][l2It].second - c*l2.land[level][l2It].first; + + double contributionFromThisPart + = + (a*c*x2*x2*x2/3 + (a*d+b*c)*x2*x2/2 + b*d*x2) - (a*c*x1*x1*x1/3 + (a*d+b*c)*x1*x1/2 + b*d*x1); + + result += contributionFromThisPart; + + if ( dbg ) + { + std::cerr << "[l1.land[level][l1It].first,l1.land[level][l1It+1].first] : " << l1.land[level][l1It].first << " , " << l1.land[level][l1It+1].first << std::endl; + std::cerr << "[l2.land[level][l2It].first,l2.land[level][l2It+1].first] : " << l2.land[level][l2It].first << " , " << l2.land[level][l2It+1].first << std::endl; + std::cerr << "a : " << a << ", b : " << b << " , c: " << c << ", d : " << d << std::endl; + std::cerr << "x1 : " << x1 << " , x2 : " << x2 << std::endl; + std::cerr << "contributionFromThisPart : " << contributionFromThisPart << std::endl; + std::cerr << "result : " << result << std::endl; + getchar(); + } + + //we have two intervals in which functions are constant: + //[l1.land[level][l1It].first , l1.land[level][l1It+1].first] + //and + //[l2.land[level][l2It].first , l2.land[level][l2It+1].first] + //We also have an interval [x1,x2]. Since the intervals in the landscapes cover the whole R, then it is clear that x2 + //is either l1.land[level][l1It+1].first of l2.land[level][l2It+1].first or both. Lets test it. + if ( x2 == l1.land[level][l1It+1].first ) + { + if ( x2 == l2.land[level][l2It+1].first ) + { + //in this case, we increment both: + ++l2It; + if ( dbg ){std::cerr << "Incrementing both \n";} + } + else + { + if ( dbg ){std::cerr << "Incrementing first \n";} + } + ++l1It; + } + else + { + //in this case we increment l2It + ++l2It; + if ( dbg ){std::cerr << "Incrementing second \n";} + } + //Now, we shift x1 and x2: + x1 = x2; + if ( l1.land[level][l1It+1].first < l2.land[level][l2It+1].first ) + { + x2 = l1.land[level][l1It+1].first; + } + else + { + x2 = l2.land[level][l2It+1].first; + } + + } + + } + return result; +} + + +void Persistence_landscape::plot( const char* filename, double xRangeBegin , double xRangeEnd , double yRangeBegin , double yRangeEnd , int from , int to ) +{ + //this program create a gnuplot script file that allows to plot persistence diagram. + std::ofstream out; + + std::ostringstream nameSS; + nameSS << filename << "_GnuplotScript"; + std::string nameStr = nameSS.str(); + out.open( nameStr ); + + if ( (xRangeBegin != std::numeric_limits::max()) || (xRangeEnd != std::numeric_limits::max()) || (yRangeBegin != std::numeric_limits::max()) || (yRangeEnd != std::numeric_limits::max()) ) + { + out << "set xrange [" << xRangeBegin << " : " << xRangeEnd << "]" << std::endl; + out << "set yrange [" << yRangeBegin << " : " << yRangeEnd << "]" << std::endl; + } + + if ( from == std::numeric_limits::max() ){from = 0;} + if ( to == std::numeric_limits::max() ){to = this->land.size();} + + out << "plot "; + for ( size_t lambda= std::min((size_t)from,this->land.size()) ; lambda != std::min((size_t)to,this->land.size()) ; ++lambda ) + { + //out << " '-' using 1:2 title 'l" << lambda << "' with lp"; + out << " '-' using 1:2 notitle with lp"; + if ( lambda+1 != std::min((size_t)to,this->land.size()) ) + { + out << ", \\"; + } + out << std::endl; + } + + for ( size_t lambda= std::min((size_t)from,this->land.size()) ; lambda != std::min((size_t)to,this->land.size()) ; ++lambda ) + { + for ( size_t i = 1 ; i != this->land[lambda].size()-1 ; ++i ) + { + out << this->land[lambda][i].first << " " << this->land[lambda][i].second << std::endl; + } + out << "EOF" << std::endl; + } + std::cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << std::endl; +} + + + + +}//namespace gudhi stat +}//namespace gudhi + + +#endif diff --git a/src/Gudhi_stat/include/gudhi/Persistence_landscape_on_grid.h b/src/Gudhi_stat/include/gudhi/Persistence_landscape_on_grid.h new file mode 100644 index 00000000..de5c74ac --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/Persistence_landscape_on_grid.h @@ -0,0 +1,1560 @@ +/** 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 (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 Persistence_landscape_on_grid_H_ +#define Persistence_landscape_on_grid_H_ + + +//standard include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +//gudhi include + +#include +#include + + + +namespace Gudhi +{ +namespace Persistence_representations +{ + +//predeclaration +class Persistence_landscape_on_grid; +template < typename operation > +Persistence_landscape_on_grid operation_on_pair_of_landscapes_on_grid( const Persistence_landscape_on_grid& land1 , const Persistence_landscape_on_grid& land2 ); + +/** + * A clas implementing persistence landascpes by approximating them on a collection of grid points. * Persistence landscapes on grid allow vertorization, computations of distances, computations + * of projections to Real, computations of averages and scalar products. Therefore they implement suitable interfaces. + * It implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product + * Note that at the moment, due to roundoff errors during the construction of persistence landscapes on a grid, elements which are different by 0.000005 are considered the same. If the scale in your persistence diagrams + * is comparable to this value, please rescale them before use this code. +**/ + +//this class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product +class Persistence_landscape_on_grid +{ +public: + /** + * Default constructor. + **/ + Persistence_landscape_on_grid() + { + this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); + this->grid_min = this->grid_max = 0; + } + + /** + * Constructor that takes as an input a vector of birth-death pairs. + **/ + Persistence_landscape_on_grid( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_ ); + + + /** + * Constructor that takes as an input a vector of birth-death pairs, parameters of the grid and number of landscape function to be created. + **/ + Persistence_landscape_on_grid( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_ , unsigned number_of_levels_of_landscape ); + + /** + * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed + * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. The additional parameters of this procedure are: ranges of grid, resoltion of a grid + * number of landscape functions to be created and the dimension of intervals that are need to be read from a file (in case of Gudhi format files). + **/ + Persistence_landscape_on_grid(const char* filename , double grid_min_, double grid_max_ , size_t number_of_points_ , unsigned number_of_levels_of_landscape , unsigned short dimension_ = std::numeric_limits::max() ); + + /** + * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed + * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. The additional parameters of this procedure are: ranges of grid, resoltion of a grid + * and the dimension of intervals that are need to be read from a file (in case of Gudhi format files). + **/ + Persistence_landscape_on_grid(const char* filename , double grid_min_, double grid_max_ , size_t number_of_points_ , unsigned short dimension_ = std::numeric_limits::max() ); + + + /** + * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed + * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. The additional parameter is the resoution of a grid and the number of landscape + * functions to be created. The remaning parameters are calculated based on data. + **/ + Persistence_landscape_on_grid(const char* filename , size_t number_of_points , unsigned number_of_levels_of_landscape , unsigned short dimension = std::numeric_limits::max() ); + + /** + * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed + * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. The additional parameter is the resoution of a grid. The last parameter is the dimension + * of a persistence to read from the file. If your file contains only persistence pair in a single dimension, please set it up to std::numeric_limits::max(). + * The remaning parameters are calculated based on data. + **/ + Persistence_landscape_on_grid(const char* filename , size_t number_of_points , unsigned short dimension = std::numeric_limits::max() ); + + + /** + * This procedure loads a landscape from file. It erase all the data that was previously stored in this landscape. + **/ + void load_landscape_from_file( const char* filename ); + + + /** + * The procedure stores a landscape to a file. The file can be later used by a procedure load_landscape_from_file. + **/ + void print_to_file( const char* filename )const; + + + + /** + * This function compute integral of the landscape (defined formally as sum of integrals on R of all landscape functions) + **/ + double compute_integral_of_landscape()const + { + size_t maximal_level = this->number_of_nonzero_levels(); + double result = 0; + for ( size_t i = 0 ; i != maximal_level ; ++i ) + { + result += this->compute_integral_of_landscape(i); + } + return result; + } + + + /** + * This function compute integral of the 'level'-level of a landscape. + **/ + double compute_integral_of_landscape( size_t level )const + { + bool dbg = false; + double result = 0; + double dx = (this->grid_max - this->grid_min)/(double)(this->values_of_landscapes.size()-1); + + if ( dbg ) + { + std::cerr << "this->grid_max : " << this->grid_max << std::endl; + std::cerr << "this->grid_min : " << this->grid_min << std::endl; + std::cerr << "this->values_of_landscapes.size() : " << this->values_of_landscapes.size() << std::endl; + getchar(); + } + + + double previous_x = this->grid_min-dx; + double previous_y = 0; + for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) + { + double current_x = previous_x + dx; + double current_y = 0; + if ( this->values_of_landscapes[i].size() > level )current_y = this->values_of_landscapes[i][level]; + + if ( dbg ) + { + std::cerr << "this->values_of_landscapes[i].size() : " << this->values_of_landscapes[i].size() << " , level : " << level << std::endl; + if ( this->values_of_landscapes[i].size() > level )std::cerr << "this->values_of_landscapes[i][level] : " << this->values_of_landscapes[i][level] << std::endl; + std::cerr << "previous_y : " << previous_y << std::endl; + std::cerr << "current_y : " << current_y << std::endl; + std::cerr << "dx : " << dx << std::endl; + std::cerr << "0.5*dx*( previous_y + current_y ); " << 0.5*dx*( previous_y + current_y ) << std::endl; + } + + result += 0.5*dx*( previous_y + current_y ); + previous_x = current_x; + previous_y = current_y; + } + return result; + } + + /** + * This function compute integral of the landscape p-th power of a landscape (defined formally as sum of integrals on R of p-th powers of all landscape functions) + **/ + double compute_integral_of_landscape( double p )const + { + size_t maximal_level = this->number_of_nonzero_levels(); + double result = 0; + for ( size_t i = 0 ; i != maximal_level ; ++i ) + { + result += this->compute_integral_of_landscape(p,i); + } + return result; + } + + /** + * This function compute integral of the landscape p-th power of a level of a landscape (defined formally as sum of integrals on R of p-th powers of all landscape functions) + **/ + double compute_integral_of_landscape( double p , size_t level )const + { + bool dbg = false; + + double result = 0; + double dx = (this->grid_max - this->grid_min)/(double)(this->values_of_landscapes.size()-1); + double previous_x = this->grid_min; + double previous_y = 0; + if ( this->values_of_landscapes[0].size() > level )previous_y = this->values_of_landscapes[0][level]; + + if ( dbg ) + { + std::cerr << "dx : " << dx << std::endl; + std::cerr << "previous_x : " << previous_x << std::endl; + std::cerr << "previous_y : " << previous_y << std::endl; + std::cerr << "power : " << p << std::endl; + getchar(); + } + + for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) + { + double current_x = previous_x + dx; + double current_y = 0; + if ( this->values_of_landscapes[i].size() > level )current_y = this->values_of_landscapes[i][level]; + + if ( dbg )std::cerr << "current_y : " << current_y << std::endl; + + if ( current_y == previous_y )continue; + + std::pair coef = compute_parameters_of_a_line( std::make_pair( previous_x , previous_y ) , std::make_pair( current_x , current_y ) ); + double a = coef.first; + double b = coef.second; + + if ( dbg ) + { + std::cerr << "A line passing through points : (" << previous_x << "," << previous_y << ") and (" << current_x << "," << current_y << ") is : " << a << "x+" << b << std::endl; + } + + //In this interval, the landscape has a form f(x) = ax+b. We want to compute integral of (ax+b)^p = 1/a * (ax+b)^{p+1}/(p+1) + double value_to_add = 0; + if ( a != 0 ) + { + value_to_add = 1/(a*(p+1)) * ( pow((a*current_x+b),p+1) - pow((a*previous_x+b),p+1)); + } + else + { + value_to_add = ( current_x - previous_x )*( pow(b,p) ); + } + result += value_to_add; + if ( dbg ) + { + std::cerr << "Increasing result by : " << value_to_add << std::endl; + std::cerr << "restult : " << result << std::endl; + getchar(); + } + previous_x = current_x; + previous_y = current_y; + } + if ( dbg )std::cerr << "The total result is : " << result << std::endl; + return result; + } + + /** + * Writing landscape into a stream. A i-th level landscape starts with a string "lambda_i". Then the discontinuity points of the landscapes follows. + * Shall those points be joined with lines, we will obtain the i-th landscape function. + **/ + friend std::ostream& operator<<(std::ostream& out, const Persistence_landscape_on_grid& land ) + { + double dx = (land.grid_max - land.grid_min)/(double)(land.values_of_landscapes.size()-1); + double x = land.grid_min; + for ( size_t i = 0 ; i != land.values_of_landscapes.size() ; ++i ) + { + out << x << " : "; + for ( size_t j = 0 ; j != land.values_of_landscapes[i].size() ; ++j ) + { + out << land.values_of_landscapes[i][j] << " "; + } + out << std::endl; + x += dx; + } + return out; + } + + template < typename oper > + friend Persistence_landscape_on_grid operation_on_pair_of_landscapes_on_grid( const Persistence_landscape_on_grid& land1 , const Persistence_landscape_on_grid& land2 ); + + + /** + * A function that computes the value of a landscape at a given point. The parameters of the function are: unsigned level and double x. + * The procedure will compute the value of the level-landscape at the point x. + **/ + double compute_value_at_a_given_point( unsigned level , double x )const + { + bool dbg = false; + if ( (x < this->grid_min) || (x > this->grid_max) )return 0; + + //find a position of a vector closest to x: + double dx = (this->grid_max - this->grid_min)/(double)(this->values_of_landscapes.size()-1); + size_t position = size_t((x-this->grid_min)/dx); + + if ( dbg ) + { + std::cerr << "This is a procedure compute_value_at_a_given_point \n"; + std::cerr << "level : " << level << std::endl; + std::cerr << "x : " << x << std::endl; + std::cerr << "psoition : " << position << std::endl; + } + //check if we are not exacly in the grid point: + if ( almost_equal( position*dx+ this->grid_min , x) ) + { + if ( this->values_of_landscapes[position].size() < level ) + { + return this->values_of_landscapes[position][level]; + } + else + { + return 0; + } + } + //in the other case, approximate with a line: + std::pair line; + if ( (this->values_of_landscapes[position].size() > level) && (this->values_of_landscapes[position+1].size() > level) ) + { + line = compute_parameters_of_a_line( std::make_pair( position*dx+ this->grid_min , this->values_of_landscapes[position][level] ) , std::make_pair( (position+1)*dx+ this->grid_min , this->values_of_landscapes[position+1][level] ) ); + } + else + { + if ( (this->values_of_landscapes[position].size() > level) || (this->values_of_landscapes[position+1].size() > level) ) + { + if ( (this->values_of_landscapes[position].size() > level) ) + { + line = compute_parameters_of_a_line( std::make_pair( position*dx+ this->grid_min , this->values_of_landscapes[position][level] ) , std::make_pair( (position+1)*dx+ this->grid_min , 0 ) ); + } + else + { + //(this->values_of_landscapes[position+1].size() > level) + line = compute_parameters_of_a_line( std::make_pair( position*dx+ this->grid_min , 0 ) , std::make_pair( (position+1)*dx+ this->grid_min , this->values_of_landscapes[position+1][level] ) ); + } + } + else + { + return 0; + } + } + //compute the value of the linear function parametrized by line on a point x: + return line.first*x+line.second; + } + + + public: + /** + *\private A function that compute sum of two landscapes. + **/ + friend Persistence_landscape_on_grid add_two_landscapes ( const Persistence_landscape_on_grid& land1 , const Persistence_landscape_on_grid& land2 ) + { + return operation_on_pair_of_landscapes_on_grid< std::plus >(land1,land2); + } + + /** + *\private A function that compute difference of two landscapes. + **/ + friend Persistence_landscape_on_grid subtract_two_landscapes ( const Persistence_landscape_on_grid& land1 , const Persistence_landscape_on_grid& land2 ) + { + return operation_on_pair_of_landscapes_on_grid< std::minus >(land1,land2); + } + + /** + * An operator +, that compute sum of two landscapes. + **/ + friend Persistence_landscape_on_grid operator+( const Persistence_landscape_on_grid& first , const Persistence_landscape_on_grid& second ) + { + return add_two_landscapes( first,second ); + } + + /** + * An operator -, that compute difference of two landscapes. + **/ + friend Persistence_landscape_on_grid operator-( const Persistence_landscape_on_grid& first , const Persistence_landscape_on_grid& second ) + { + return subtract_two_landscapes( first,second ); + } + + /** + * An operator * that allows multipilication of a landscape by a real number. + **/ + friend Persistence_landscape_on_grid operator*( const Persistence_landscape_on_grid& first , double con ) + { + return first.multiply_lanscape_by_real_number_not_overwrite(con); + } + + /** + * An operator * that allows multipilication of a landscape by a real number (order of parameters swapped). + **/ + friend Persistence_landscape_on_grid operator*( double con , const Persistence_landscape_on_grid& first ) + { + return first.multiply_lanscape_by_real_number_not_overwrite(con); + } + + friend bool check_if_defined_on_the_same_domain( const Persistence_landscape_on_grid& land1, const Persistence_landscape_on_grid& land2 ) + { + if ( land1.values_of_landscapes.size() != land2.values_of_landscapes.size() )return false; + if ( land1.grid_min != land2.grid_min )return false; + if ( land1.grid_max != land2.grid_max )return false; + return true; + } + + /** + * Operator +=. The second parameter is persistnece landwscape. + **/ + Persistence_landscape_on_grid operator += ( const Persistence_landscape_on_grid& rhs ) + { + *this = *this + rhs; + return *this; + } + + /** + * Operator -=. The second parameter is persistnece landwscape. + **/ + Persistence_landscape_on_grid operator -= ( const Persistence_landscape_on_grid& rhs ) + { + *this = *this - rhs; + return *this; + } + + + /** + * Operator *=. The second parameter is a real number by which the y values of all landscape functions are multiplied. The x-values remain unchanged. + **/ + Persistence_landscape_on_grid operator *= ( double x ) + { + *this = *this*x; + return *this; + } + + /** + * Operator /=. The second parameter is a real number. + **/ + Persistence_landscape_on_grid operator /= ( double x ) + { + if ( x == 0 )throw( "In operator /=, division by 0. Program terminated." ); + *this = *this * (1/x); + return *this; + } + + /** + * An operator to compare two persistence landscapes. + **/ + bool operator == ( const Persistence_landscape_on_grid& rhs )const + { + bool dbg = true; + if ( this->values_of_landscapes.size() != rhs.values_of_landscapes.size() ) + { + if (dbg) std::cerr << "values_of_landscapes of incompatable sizes\n"; + return false; + } + if ( !almost_equal( this->grid_min , rhs.grid_min ) ) + { + if (dbg) std::cerr << "grid_min not equal\n"; + return false; + } + if ( !almost_equal(this->grid_max,rhs.grid_max ) ) + { + if (dbg) std::cerr << "grid_max not equal\n"; + return false; + } + for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) + { + for ( size_t aa = 0 ; aa != this->values_of_landscapes[i].size() ; ++aa ) + { + if ( !almost_equal( this->values_of_landscapes[i][aa] , rhs.values_of_landscapes[i][aa] ) ) + { + if (dbg) + { + std::cerr << "Problem in the position : " << i << " of values_of_landscapes. \n"; + std::cerr << this->values_of_landscapes[i][aa] << " " << rhs.values_of_landscapes[i][aa] << std::endl; + } + return false; + } + } + } + return true; + } + + + /** + * An operator to compare two persistence landscapes. + **/ + bool operator != ( const Persistence_landscape_on_grid& rhs )const + { + return !((*this) == rhs); + } + + + /** + * Computations of maximum (y) value of landscape. + **/ + double compute_maximum()const + { + //since the function can only be entirely positive or negative, the maximal value will be an extremal value in the arrays: + double max_value = -std::numeric_limits::max(); + for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) + { + if ( this->values_of_landscapes[i].size() ) + { + if ( this->values_of_landscapes[i][0] > max_value )max_value = this->values_of_landscapes[i][0]; + if ( this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ] > max_value )max_value = this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ]; + } + } + return max_value; + } + + /** + * Computations of minimum and maximum value of landscape. + **/ + std::pair compute_minimum_maximum()const + { + //since the function can only be entirely positive or negative, the maximal value will be an extremal value in the arrays: + double max_value = -std::numeric_limits::max(); + double min_value = 0; + for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) + { + if ( this->values_of_landscapes[i].size() ) + { + if ( this->values_of_landscapes[i][0] > max_value )max_value = this->values_of_landscapes[i][0]; + if ( this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ] > max_value )max_value = this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ]; + + if ( this->values_of_landscapes[i][0] < min_value )min_value = this->values_of_landscapes[i][0]; + if ( this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ] < min_value )min_value = this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ]; + } + } + return std::make_pair(min_value , max_value); + } + + /** + * This procedure returns x-range of a given level persistence landscape. If a default value is used, the x-range + * of 0th level landscape is given (and this range contains the ranges of all other landscapes). + **/ + std::pair< double , double > get_x_range( size_t level = 0 )const + { + return std::make_pair( this->grid_min , this->grid_max ); + //std::pair< double , double > result; + //if ( level < this->land.size() ) + //{ + // double dx = (this->grid_max - this->grid_min)/(double)this->values_of_landscapes.size(); + // size_t first_nonzero = 0; + // while ( (first_nonzero != this->values_of_landscapes.size()) && (this->values_of_landscapes[level][first_nonzero] == 0) )++first_nonzero; + // + // if ( first_nonzero == 0 ) + // { + // return std::make_pair( 0,0 );//this landscape is empty. + // } + // + // size_t last_nonzero = 0; + // while ( (last_nonzero != 0) && (this->values_of_landscapes[level][last_nonzero] == 0) )--last_nonzero; + // + // result = std::make_pair( this->grid_min +first_nonzero*dx , this->grid_max - last_nonzero*dx ); + //} + //else + //{ + // result = std::make_pair( 0,0 ); + //} + //return result; + } + + /** + * This procedure returns y-range of a persistence landscape. If a default value is used, the y-range + * of 0th level landscape is given (and this range contains the ranges of all other landscapes). + **/ + std::pair< double , double > get_y_range( size_t level = 0 )const + { + return this->compute_minimum_maximum(); + //std::pair< double , double > result; + //if ( level < this->land.size() ) + //{ + // result = this->compute_minimum_maximum() + //} + //else + //{ + // result = std::make_pair( 0,0 ); + //} + //return result; + } + + /** + * This function computes maximal lambda for which lambda-level landscape is nonzero. + **/ + size_t number_of_nonzero_levels()const + { + size_t result = 0; + for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) + { + if ( this->values_of_landscapes[i].size() > result )result = this->values_of_landscapes[i].size(); + } + return result; + } + + /** + * Computations of a \f$L^i\f$ norm of landscape, where i is the input parameter. + **/ + double compute_norm_of_landscape( double i )const + { + std::vector< std::pair< double , double > > p; + Persistence_landscape_on_grid l(p,this->grid_min,this->grid_max,this->values_of_landscapes.size()-1); + + if ( i < std::numeric_limits::max() ) + { + return compute_distance_of_landscapes_on_grid(*this,l,i); + } + else + { + return compute_max_norm_distance_of_landscapes(*this,l); + } + } + + /** + * An operator to compute the value of a landscape in the level 'level' at the argument 'x'. + **/ + double operator()(unsigned level,double x)const{return this->compute_value_at_a_given_point(level,x);} + + /** + * Computations of \f$L^{\infty}\f$ distance between two landscapes. + **/ + friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second ); + //friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second , unsigned& nrOfLand , double&x , double& y1, double& y2 ); + + + + + /** + * Function to compute absolute value of a PL function. The representation of persistence landscapes allow to store general PL-function. When computing distance betwen two landscapes, we compute difference between + * them. In this case, a general PL-function with negative value can appear as a result. Then in order to compute distance, we need to take its absolute value. This is the purpose of this procedure. + **/ + void abs() + { + for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) + { + for ( size_t j = 0 ; j != this->values_of_landscapes[i].size() ; ++j ) + { + this->values_of_landscapes[i][j] = std::abs( this->values_of_landscapes[i][j] ); + } + } + } + + /** + * Computes the number of landscape functions. + **/ + size_t size()const{return this->number_of_nonzero_levels(); } + + /** + * Computate maximal value of lambda-level landscape. + **/ + double find_max( unsigned lambda )const + { + double max_value = -std::numeric_limits::max(); + for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) + { + if ( this->values_of_landscapes[i].size() > lambda ) + { + if ( this->values_of_landscapes[i][lambda] > max_value )max_value = this->values_of_landscapes[i][lambda]; + } + } + return max_value; + } + + /** + * Function to compute inner (scalar) product of two landscapes. + **/ + friend double compute_inner_product( const Persistence_landscape_on_grid& l1 , const Persistence_landscape_on_grid& l2 ) + { + if ( !check_if_defined_on_the_same_domain(l1,l2) )throw "Landscapes are not defined on the same grid, the program will now terminate"; + size_t maximal_level = l1.number_of_nonzero_levels(); + double result = 0; + for ( size_t i = 0 ; i != maximal_level ; ++i ) + { + result += compute_inner_product(l1,l2,i); + } + return result; + } + + + + /** + * Function to compute inner (scalar) product of given levels of two landscapes. + **/ + friend double compute_inner_product( const Persistence_landscape_on_grid& l1 , const Persistence_landscape_on_grid& l2 , size_t level ) + { + bool dbg = false; + + if ( !check_if_defined_on_the_same_domain(l1,l2) )throw "Landscapes are not defined on the same grid, the program will now terminate"; + double result = 0; + + double dx = (l1.grid_max - l1.grid_min)/(double)(l1.values_of_landscapes.size()-1); + + double previous_x = l1.grid_min-dx; + double previous_y_l1 = 0; + double previous_y_l2 = 0; + for ( size_t i = 0 ; i != l1.values_of_landscapes.size() ; ++i ) + { + if ( dbg )std::cerr << "i : " << i << std::endl; + + double current_x = previous_x + dx; + double current_y_l1 = 0; + if ( l1.values_of_landscapes[i].size() > level )current_y_l1 = l1.values_of_landscapes[i][level]; + + double current_y_l2 = 0; + if ( l2.values_of_landscapes[i].size() > level )current_y_l2 = l2.values_of_landscapes[i][level]; + + if ( dbg ) + { + std::cerr << "previous_x : " << previous_x << std::endl; + std::cerr << "previous_y_l1 : " << previous_y_l1 << std::endl; + std::cerr << "current_y_l1 : " << current_y_l1 << std::endl; + std::cerr << "previous_y_l2 : " << previous_y_l2 << std::endl; + std::cerr << "current_y_l2 : " << current_y_l2 << std::endl; + } + + std::pair l1_coords = compute_parameters_of_a_line( std::make_pair( previous_x , previous_y_l1 ) , std::make_pair( current_x , current_y_l1 ) ); + std::pair l2_coords = compute_parameters_of_a_line( std::make_pair( previous_x , previous_y_l2 ) , std::make_pair( current_x , current_y_l2 ) ); + + //let us assume that the first line is of a form y = ax+b, and the second one is of a form y = cx + d. Then here are a,b,c,d: + double a = l1_coords.first; + double b = l1_coords.second; + + double c = l2_coords.first; + double d = l2_coords.second; + + if ( dbg ) + { + std::cerr << "Here are the formulas for a line: \n"; + std::cerr << "a : " << a << std::endl; + std::cerr << "b : " << b << std::endl; + std::cerr << "c : " << c << std::endl; + std::cerr << "d : " << d << std::endl; + } + + //now, to compute the inner product in this interval we need to compute the integral of (ax+b)(cx+d) = acx^2 + (ad+bc)x + bd in the interval from previous_x to current_x: + //The integal is ac/3*x^3 + (ac+bd)/2*x^2 + bd*x + + double added_value = (a*c/3*current_x*current_x*current_x + (a*d+b*c)/2*current_x*current_x + b*d*current_x)- + (a*c/3*previous_x*previous_x*previous_x + (a*d+b*c)/2*previous_x*previous_x + b*d*previous_x); + + if ( dbg ) + { + std::cerr << "Value of the integral on the left end ie : " << previous_x << " is : " << a*c/3*previous_x*previous_x*previous_x + (a*d+b*c)/2*previous_x*previous_x + b*d*previous_x << std::endl; + std::cerr << "Value of the integral on the right end i.e. : " << current_x << " is " << a*c/3*current_x*current_x*current_x + (a*d+b*c)/2*current_x*current_x + b*d*current_x << std::endl; + } + + result += added_value; + + if ( dbg ) + { + std::cerr << "added_value : " << added_value << std::endl; + std::cerr << "result : " << result << std::endl; + getchar(); + } + + + previous_x = current_x; + previous_y_l1 = current_y_l1; + previous_y_l2 = current_y_l2; + + } + return result; + } + + + /** + * Computations of \f$L^{p}\f$ distance between two landscapes on a grid. p is the parameter of the procedure. + * FIXME: Note that, due to the grid representation, the method below may give non--accurate results in case when the landscape P and Q the difference of which we want to compute + * are interxsecting. This is a consequence of a general way they are computed. In the future, an integral of absolute value of a difference of P and Q will be given as a separated + * function to fix that inaccuracy. + **/ + friend double compute_distance_of_landscapes_on_grid( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second , double p ) + { + bool dbg = false; + //This is what we want to compute: (\int_{- \infty}^{+\infty}| first-second |^p)^(1/p). We will do it one step at a time: + + if ( dbg ) + { + std::cerr << "first : " << first << std::endl; + std::cerr << "second : " << second << std::endl; + getchar(); + } + + //first-second : + Persistence_landscape_on_grid lan = first-second; + + if ( dbg ) + { + std::cerr << "Difference : " << lan << std::endl; + } + + //| first-second |: + lan.abs(); + + if ( dbg ) + { + std::cerr << "Abs : " << lan << std::endl; + } + + if ( p < std::numeric_limits< double >::max() ) + { + //\int_{- \infty}^{+\infty}| first-second |^p + double result; + if ( p != 1 ) + { + if (dbg){std::cerr << "p : " << p << std::endl; getchar();} + result = lan.compute_integral_of_landscape( (double)p ); + if (dbg){std::cerr << "integral : " << result << std::endl;getchar();} + } + else + { + result = lan.compute_integral_of_landscape(); + if (dbg){std::cerr << "integral, wihtout power : " << result << std::endl;getchar();} + } + //(\int_{- \infty}^{+\infty}| first-second |^p)^(1/p) + return pow( result , 1/(double)p ); + } + else + { + //p == infty + return lan.compute_maximum(); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + //Functions that are needed for that class to implement the concept. + + /** + * The number of projections to R is defined to the number of nonzero landscape functions. I-th projection is an integral of i-th landscape function over whole R. + * This function is required by the Real_valued_topological_data concept. + **/ + double project_to_R( int number_of_function )const + { + return this->compute_integral_of_landscape( (size_t)number_of_function ); + } + + /** + * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. + **/ + size_t number_of_projections_to_R()const + { + return number_of_functions_for_projections_to_reals; + } + + + + + /** + * This function produce a vector of doubles based on a landscape. It is required in a concept Vectorized_topological_data + */ + std::vector vectorize( int number_of_function )const + { + //TODO, think of something smarter over here + if ( ( number_of_function < 0 ) || ( (size_t)number_of_function >= this->values_of_landscapes.size() ) ) + { + throw "Wrong number of function\n"; + } + std::vector v( this->values_of_landscapes.size() ); + for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) + { + v[i] = 0; + if ( this->values_of_landscapes[i].size() > (size_t)number_of_function ) + { + v[ i ] = this->values_of_landscapes[i][number_of_function]; + } + } + return v; + } + + /** + * This function return the number of functions that allows vectorization of persistence laandscape. It is required in a concept Vectorized_topological_data. + **/ + size_t number_of_vectorize_functions()const + { + return number_of_functions_for_vectorization; + } + + + + + + /** + * A function to compute averaged persistence landscape on a grid, based on vector of persistence landscapes on grid. + * This function is required by Topological_data_with_averages concept. + **/ + void compute_average( const std::vector< Persistence_landscape_on_grid* >& to_average ) + { + + bool dbg = false; + //After execution of this procedure, the average is supposed to be in the current object. To make sure that this is the case, we need to do some cleaning first. + this->values_of_landscapes .clear(); + this->grid_min = this->grid_max = 0; + + //if there is nothing to averate, then the average is a zero landscape. + if ( to_average.size() == 0 )return; + + //now we need to check if the grids in all objects of to_average are the same: + for ( size_t i = 0 ; i != to_average.size() ; ++i ) + { + if ( !check_if_defined_on_the_same_domain(*(to_average[0]),*(to_average[i])) )throw "Two grids are not compatible"; + } + + this->values_of_landscapes = std::vector< std::vector >( (to_average[0])->values_of_landscapes.size() ); + this->grid_min = (to_average[0])->grid_min; + this->grid_max = (to_average[0])->grid_max; + + if ( dbg ) + { + std::cerr << "Computations of average. The data from the current landscape have been cleared. We are ready to do the computations. \n"; + } + + //for every point in the grid: + for ( size_t grid_point = 0 ; grid_point != (to_average[0])->values_of_landscapes.size() ; ++grid_point ) + { + + //set up a vector of the correct size: + size_t maximal_size_of_vector = 0; + for ( size_t land_no = 0 ; land_no != to_average.size() ; ++land_no ) + { + if ( (to_average[land_no])->values_of_landscapes[grid_point].size() > maximal_size_of_vector ) + maximal_size_of_vector = (to_average[land_no])->values_of_landscapes[grid_point].size(); + } + this->values_of_landscapes[grid_point] = std::vector( maximal_size_of_vector ); + + if ( dbg ) + { + std::cerr << "We are considering the point : " << grid_point << " of the grid. In this point, there are at most : " << maximal_size_of_vector << " nonzero landscape functions \n"; + } + + //and compute an arythmetic average: + for ( size_t land_no = 0 ; land_no != to_average.size() ; ++land_no ) + { + //summing: + for ( size_t i = 0 ; i != (to_average[land_no])->values_of_landscapes[grid_point].size() ; ++i ) + { + //compute the average in a smarter way. + this->values_of_landscapes[grid_point][i] += (to_average[land_no])->values_of_landscapes[grid_point][i]; + } + } + //normalizing: + for ( size_t i = 0 ; i != this->values_of_landscapes[grid_point].size() ; ++i ) + { + this->values_of_landscapes[grid_point][i] /= (double)to_average.size(); + } + } + }//compute_average + + + /** + * A function to compute distance between persistence landscape on a grid. + * The parameter of this functionis a Persistence_landscape_on_grid. + * This function is required in Topological_data_with_distances concept. + * For max norm distance, set power to std::numeric_limits::max() + **/ + double distance( const Persistence_landscape_on_grid& second , double power = 1 )const + { + if ( power < std::numeric_limits::max() ) + { + return compute_distance_of_landscapes_on_grid( *this , second , power ); + } + else + { + return compute_max_norm_distance_of_landscapes( *this , second ); + } + } + + /** + * A function to compute scalar product of persistence landscape on a grid. + * The parameter of this functionis a Persistence_landscape_on_grid. + * This function is required in Topological_data_with_scalar_product concept. + **/ + double compute_scalar_product( const Persistence_landscape_on_grid& second ) + { + return compute_inner_product( (*this) , second ); + } + + //end of implementation of functions needed for concepts. + + + + + + + + + + + + + + + + + + + + + /** + * A function that returns values of landsapes. It can be used for vizualization + **/ + std::vector< std::vector< double > > output_for_visualization()const + { + return this->values_of_landscapes; + } + + /** + * function used to create a gnuplot script for visualization of landscapes. Over here we need to specify which landscapes do we want to plot. + * In addition, the user may specify the range (min and max) where landscape is plot. The fefault values for min and max are std::numeric_limits::max(). If the procedure detect those + * values, it will determine the range so that the whole landscape is supported there. If at least one min or max value is different from std::numeric_limits::max(), then the values + * provided by the user will be used. + **/ + void plot( const char* filename , size_t from_ , size_t to_ )const + { + this->plot( filename , std::numeric_limits::max() , std::numeric_limits::max(), std::numeric_limits::max() , std::numeric_limits::max() , from_ , to_ ); + } + + /** + * function used to create a gnuplot script for visualization of landscapes. Over here we can restrict also x and y range of the landscape. + **/ + void plot( const char* filename, double min_x = std::numeric_limits::max() , double max_x = std::numeric_limits::max() , double min_y = std::numeric_limits::max() , double max_y = std::numeric_limits::max() , size_t from_ = std::numeric_limits::max(), size_t to_= std::numeric_limits::max() )const; + + +protected: + double grid_min; + double grid_max; + std::vector< std::vector< double > > values_of_landscapes; + size_t number_of_functions_for_vectorization; + size_t number_of_functions_for_projections_to_reals; + + void set_up_numbers_of_functions_for_vectorization_and_projections_to_reals() + { + //warning, this function can be only called after filling in the values_of_landscapes vector. + this->number_of_functions_for_vectorization = this->values_of_landscapes.size(); + this->number_of_functions_for_projections_to_reals = this->values_of_landscapes.size(); + } + void set_up_values_of_landscapes( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_ , unsigned number_of_levels = std::numeric_limits::max() ); + Persistence_landscape_on_grid multiply_lanscape_by_real_number_not_overwrite( double x )const; +}; + + +void Persistence_landscape_on_grid::set_up_values_of_landscapes( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_, unsigned number_of_levels ) +{ + bool dbg = false; + if ( dbg ) + { + std::cerr << "Here is the procedure : set_up_values_of_landscapes. The parameters are : grid_min_ : " << grid_min_ << ", grid_max_ : " << grid_max_ << ", number_of_points_ : " << number_of_points_ << ", number_of_levels: " << number_of_levels << std::endl; + std::cerr << "Here are the intervals at our disposal : \n"; + for ( size_t i = 0 ; i != p.size() ; ++i ) + { + std::cerr << p[i].first << " , " << p[i].second << std::endl; + } + } + + if ( (grid_min_ == std::numeric_limits::max()) || (grid_max_ == std::numeric_limits::max()) ) + { + //in this case, we need to find grid_min_ and grid_min_ based on the data. + double min = std::numeric_limits::max(); + double max = std::numeric_limits::min(); + for ( size_t i = 0 ; i != p.size() ; ++i ) + { + if ( p[i].first < min )min = p[i].first; + if ( p[i].second > max )max = p[i].second; + } + if ( grid_min_ == std::numeric_limits::max() ) + { + grid_min_ = min; + } + else + { + //in this case grid_max_ == std::numeric_limits::max() + grid_max_ = max; + } + } + + //if number_of_levels == std::numeric_limits::max(), then we will have all the nonzero values of landscapes, and will store them in a vector + //if number_of_levels != std::numeric_limits::max(), then we will use those vectors as heaps. + this->values_of_landscapes = std::vector< std::vector< double > >( number_of_points_+1 ); + + + this->grid_min = grid_min_; + this->grid_max = grid_max_; + + if ( grid_max_ <= grid_min_ ) + { + throw "Wrong parameters of grid_min and grid_max given to the procedure. THe grid have negative, or zero size. The program will now terminate.\n"; + } + + double dx = ( grid_max_ - grid_min_ )/(double)(number_of_points_); + //for every interval in the diagram: + for ( size_t int_no = 0 ; int_no != p.size() ; ++int_no ) + { + size_t grid_interval_begin = (p[int_no].first-grid_min_)/dx; + size_t grid_interval_end = (p[int_no].second-grid_min_)/dx; + size_t grid_interval_midpoint = (size_t)(0.5*(grid_interval_begin+grid_interval_end)); + + if ( dbg ) + { + std::cerr << "Considering an interval : " << p[int_no].first << "," << p[int_no].second << std::endl; + + std::cerr << "grid_interval_begin : " << grid_interval_begin << std::endl; + std::cerr << "grid_interval_end : " << grid_interval_end << std::endl; + std::cerr << "grid_interval_midpoint : " << grid_interval_midpoint << std::endl; + } + + double landscape_value = dx; + for ( size_t i = grid_interval_begin+1 ; i < grid_interval_midpoint ; ++i ) + { + if ( dbg ) + { + std::cerr << "Adding landscape value (going up) for a point : " << i << " equal : " << landscape_value << std::endl; + } + if ( number_of_levels != std::numeric_limits::max() ) + { + //we have a heap of no more that number_of_levels values. + //Note that if we are using heaps, we want to know the shortest distance in the heap. + //This is achieved by putting -distance to the heap. + if ( this->values_of_landscapes[i].size() >= number_of_levels ) + { + //in this case, the full heap is build, and we need to check if the landscape_value is not larger than the smallest element in the heap. + if ( -landscape_value < this->values_of_landscapes[i].front() ) + { + //if it is, we remove the largest value in the heap, and move on. + std::pop_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); + this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ] = -landscape_value; + std::push_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); + } + } + else + { + + //in this case we are still filling in the array. + this->values_of_landscapes[i].push_back( -landscape_value ); + if ( this->values_of_landscapes[i].size() == number_of_levels-1 ) + { + //this->values_of_landscapes[i].size() == number_of_levels + //in this case we need to create the heep. + std::make_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); + } + } + } + else + { + //we have vector of all values + this->values_of_landscapes[i].push_back( landscape_value ); + } + landscape_value += dx; + } + for ( size_t i = grid_interval_midpoint ; i <= grid_interval_end ; ++i ) + { + if ( landscape_value > 0 ) + { + if ( number_of_levels != std::numeric_limits< unsigned >::max() ) + { + //we have a heap of no more that number_of_levels values + if ( this->values_of_landscapes[i].size() >= number_of_levels ) + { + //in this case, the full heap is build, and we need to check if the landscape_value is not larger than the smallest element in the heap. + if ( -landscape_value < this->values_of_landscapes[i].front() ) + { + //if it is, we remove the largest value in the heap, and move on. + std::pop_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); + this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ] = -landscape_value; + std::push_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); + } + } + else + { + + //in this case we are still filling in the array. + this->values_of_landscapes[i].push_back( -landscape_value ); + if ( this->values_of_landscapes[i].size() == number_of_levels-1 ) + { + //this->values_of_landscapes[i].size() == number_of_levels + //in this case we need to create the heep. + std::make_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); + } + } + } + else + { + this->values_of_landscapes[i].push_back( landscape_value ); + } + + + if ( dbg ) + { + std::cerr << "AAdding landscape value (going down) for a point : " << i << " equal : " << landscape_value << std::endl; + } + } + landscape_value -= dx; + } + } + + if ( number_of_levels != std::numeric_limits< unsigned >::max() ) + { + //in this case, vectors are used as heaps. And, since we want to have the smallest element at the top of + //each heap, we store mminus distances. To get if right at the end, we need to multiply each value + //in the heap by -1 to get real vector of distances. + for ( size_t pt = 0 ; pt != this->values_of_landscapes.size() ; ++pt ) + { + //std::cerr << this->values_of_landscapes[pt].size() <values_of_landscapes[pt].size() ; ++j ) + { + this->values_of_landscapes[pt][j] *= -1; + } + } + } + + //and now we need to sort the values: + for ( size_t pt = 0 ; pt != this->values_of_landscapes.size() ; ++pt ) + { + std::sort( this->values_of_landscapes[pt].begin() , this->values_of_landscapes[pt].end() , std::greater() ); + } +}//set_up_values_of_landscapes + + + +Persistence_landscape_on_grid::Persistence_landscape_on_grid( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_ ) +{ + this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ ); +}//Persistence_landscape_on_grid + + +Persistence_landscape_on_grid::Persistence_landscape_on_grid( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_ , unsigned number_of_levels_of_landscape ) +{ + this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ , number_of_levels_of_landscape ); +} + + +Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename , double grid_min_, double grid_max_ , size_t number_of_points_ , unsigned short dimension ) +{ + std::vector< std::pair< double , double > > p; + if ( dimension == std::numeric_limits::max() ) + { + p = read_persistence_intervals_in_one_dimension_from_file( filename ); + } + else + { + p = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); + } + this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ ); +} + +Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename , double grid_min_, double grid_max_ , size_t number_of_points_, unsigned number_of_levels_of_landscape, unsigned short dimension ) +{ + std::vector< std::pair< double , double > > p; + if ( dimension == std::numeric_limits::max() ) + { + p = read_persistence_intervals_in_one_dimension_from_file( filename ); + } + else + { + p = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); + } + this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ , number_of_levels_of_landscape ); +} + +Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename , size_t number_of_points_ , unsigned short dimension ) +{ + std::vector< std::pair< double , double > > p; + if ( dimension == std::numeric_limits::max() ) + { + p = read_persistence_intervals_in_one_dimension_from_file( filename ); + } + else + { + p = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); + } + double grid_min_ = std::numeric_limits::max(); + double grid_max_ = -std::numeric_limits::max(); + for ( size_t i = 0 ; i != p.size() ; ++i ) + { + if ( p[i].first < grid_min_ )grid_min_ = p[i].first; + if ( p[i].second > grid_max_ )grid_max_ = p[i].second; + } + this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ ); +} + +Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename , size_t number_of_points_ , unsigned number_of_levels_of_landscape , unsigned short dimension ) +{ + std::vector< std::pair< double , double > > p; + if ( dimension == std::numeric_limits::max() ) + { + p = read_persistence_intervals_in_one_dimension_from_file( filename ); + } + else + { + p = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); + } + double grid_min_ = std::numeric_limits::max(); + double grid_max_ = -std::numeric_limits::max(); + for ( size_t i = 0 ; i != p.size() ; ++i ) + { + if ( p[i].first < grid_min_ )grid_min_ = p[i].first; + if ( p[i].second > grid_max_ )grid_max_ = p[i].second; + } + this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ , number_of_levels_of_landscape ); +} + + +void Persistence_landscape_on_grid::load_landscape_from_file( const char* filename ) +{ + std::ifstream in; + in.open( filename ); + //check if the file exist. + if ( !in.good() ) + { + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; + } + + size_t number_of_points_in_the_grid = 0; + in >> this->grid_min >> this->grid_max >> number_of_points_in_the_grid; + + std::vector< std::vector< double > > v(number_of_points_in_the_grid); + std::string line; + std::getline(in, line); + double number; + for ( size_t i = 0 ; i != number_of_points_in_the_grid ; ++i ) + { + //read a line of a file and convert it to a vector. + std::vector< double > vv; + std::getline(in, line); + //std::cerr << "Reading line : " << line << std::endl;getchar(); + std::istringstream stream(line); + while (stream >> number) + { + vv.push_back(number); + } + v[i] = vv; + } + this->values_of_landscapes = v; + in.close(); +} + +void Persistence_landscape_on_grid::print_to_file( const char* filename )const +{ + std::ofstream out; + out.open( filename ); + + //first we store the parameters of the grid: + out << grid_min << std::endl << grid_max << std::endl << this->values_of_landscapes.size() << std::endl; + + //and now in the following lines, the values of this->values_of_landscapes for the following arguments: + for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) + { + for ( size_t j = 0 ; j != this->values_of_landscapes[i].size() ; ++j ) + { + out << this->values_of_landscapes[i][j] << " "; + } + out << std::endl; + } + + out.close(); +} + +void Persistence_landscape_on_grid::plot( const char* filename, double min_x , double max_x , double min_y , double max_y, size_t from_ , size_t to_ )const +{ + //this program create a gnuplot script file that allows to plot persistence diagram. + std::ofstream out; + + std::ostringstream nameSS; + nameSS << filename << "_GnuplotScript"; + std::string nameStr = nameSS.str(); + out.open( nameStr ); + + if ( min_x == max_x ) + { + std::pair min_max = compute_minimum_maximum(); + out << "set xrange [" << this->grid_min << " : " << this->grid_max << "]" << std::endl; + out << "set yrange [" << min_max.first << " : " << min_max.second << "]" << std::endl; + } + else + { + out << "set xrange [" << min_x << " : " << max_x << "]" << std::endl; + out << "set yrange [" << min_y << " : " << max_y << "]" << std::endl; + } + + size_t number_of_nonzero_levels = this->number_of_nonzero_levels(); + double dx = ( this->grid_max - this->grid_min )/((double)this->values_of_landscapes.size()-1); + + + size_t from = 0; + if ( from_ != std::numeric_limits::max() ) + { + if ( from_ < number_of_nonzero_levels ) + { + from = from_; + } + else + { + return; + } + } + size_t to = number_of_nonzero_levels; + if ( to_ != std::numeric_limits::max() ) + { + if ( to_ < number_of_nonzero_levels ) + { + to = to_; + } + } + + + out << "plot "; + for ( size_t lambda= from ; lambda != to ; ++lambda ) + { + //out << " '-' using 1:2 title 'l" << lambda << "' with lp"; + out << " '-' using 1:2 notitle with lp"; + if ( lambda+1 != to ) + { + out << ", \\"; + } + out << std::endl; + } + + for ( size_t lambda = from ; lambda != to ; ++lambda ) + { + double point = this->grid_min; + for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) + { + double value = 0; + if ( this->values_of_landscapes[i].size() > lambda ) + { + value = this->values_of_landscapes[i][lambda]; + } + out << point << " " << value << std::endl; + point += dx; + } + out << "EOF" << std::endl; + } + std::cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << std::endl; +} + +template < typename T > +Persistence_landscape_on_grid operation_on_pair_of_landscapes_on_grid ( const Persistence_landscape_on_grid& land1 , const Persistence_landscape_on_grid& land2 ) +{ + //first we need to check if the domains are the same: + if ( !check_if_defined_on_the_same_domain(land1,land2) )throw "Two grids are not compatible"; + + T oper; + Persistence_landscape_on_grid result; + result.values_of_landscapes = std::vector< std::vector< double > >( land1.values_of_landscapes.size() ); + result.grid_min = land1.grid_min; + result.grid_max = land1.grid_max; + + //now we perorm the operations: + for ( size_t grid_point = 0 ; grid_point != land1.values_of_landscapes.size() ; ++grid_point ) + { + result.values_of_landscapes[grid_point] = std::vector< double >( std::max( land1.values_of_landscapes[grid_point].size() , land2.values_of_landscapes[grid_point].size() ) ); + for ( size_t lambda = 0 ; lambda != std::max( land1.values_of_landscapes[grid_point].size() , land2.values_of_landscapes[grid_point].size() ) ; ++lambda ) + { + double value1 = 0; + double value2 = 0; + if ( lambda < land1.values_of_landscapes[grid_point].size() )value1 = land1.values_of_landscapes[grid_point][lambda]; + if ( lambda < land2.values_of_landscapes[grid_point].size() )value2 = land2.values_of_landscapes[grid_point][lambda]; + result.values_of_landscapes[grid_point][lambda] = oper( value1 , value2 ); + } + } + + return result; +} + +Persistence_landscape_on_grid Persistence_landscape_on_grid::multiply_lanscape_by_real_number_not_overwrite( double x )const +{ + Persistence_landscape_on_grid result; + result.values_of_landscapes = std::vector< std::vector< double > >( this->values_of_landscapes.size() ); + result.grid_min = this->grid_min; + result.grid_max = this->grid_max; + + for ( size_t grid_point = 0 ; grid_point != this->values_of_landscapes.size() ; ++grid_point ) + { + result.values_of_landscapes[grid_point] = std::vector< double >( this->values_of_landscapes[grid_point].size() ); + for ( size_t i = 0 ; i != this->values_of_landscapes[grid_point].size() ; ++i ) + { + result.values_of_landscapes[grid_point][i] = x*this->values_of_landscapes[grid_point][i]; + } + } + + return result; +} + +double compute_max_norm_distance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second ) +{ + double result = 0; + + //first we need to check if first and second is defined on the same domain" + if ( !check_if_defined_on_the_same_domain(first, second) )throw "Two grids are not compatible"; + + for ( size_t i = 0 ; i != first.values_of_landscapes.size() ; ++i ) + { + for ( size_t j = 0 ; j != std::min( first.values_of_landscapes[i].size() , second.values_of_landscapes[i].size() ) ; ++j ) + { + if ( result < abs( first.values_of_landscapes[i][j] - second.values_of_landscapes[i][j] ) ) + { + result = abs( first.values_of_landscapes[i][j] - second.values_of_landscapes[i][j] ); + } + } + if ( first.values_of_landscapes[i].size() == std::min( first.values_of_landscapes[i].size() , second.values_of_landscapes[i].size() ) ) + { + for ( size_t j = first.values_of_landscapes[i].size() ; j != second.values_of_landscapes[i].size() ; ++j ) + { + if ( result < second.values_of_landscapes[i][j] )result = second.values_of_landscapes[i][j]; + } + } + if ( second.values_of_landscapes[i].size() == std::min( first.values_of_landscapes[i].size() , second.values_of_landscapes[i].size() ) ) + { + for ( size_t j = second.values_of_landscapes[i].size() ; j != first.values_of_landscapes[i].size() ; ++j ) + { + if ( result < first.values_of_landscapes[i][j] )result = first.values_of_landscapes[i][j]; + } + } + } + return result; +} + + + +}//namespace Gudhi_stat +}//namespace Gudhi + +#endif diff --git a/src/Gudhi_stat/include/gudhi/common_gudhi_stat.h b/src/Gudhi_stat/include/gudhi/common_gudhi_stat.h deleted file mode 100644 index 22887021..00000000 --- a/src/Gudhi_stat/include/gudhi/common_gudhi_stat.h +++ /dev/null @@ -1,154 +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 (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 common_gudhi_stat_H -#define common_gudhi_stat_H - - -namespace Gudhi -{ -namespace Gudhi_stat -{ - //this file contain an implementation of some common procedures used in Gudhi_stat. - - //double epsi = std::numeric_limits::epsilon(); -double epsi = 0.000005; - - - - - -/** - * A procedure used to compare doubles. Typically gien two doubles A and B, comparing A == B is not good idea. In this case, we use the procedure almostEqual with the epsi defined at - * the top of the file. Setting up the epsi give the user a tolerance on what should be consider equal. -**/ -inline bool almost_equal( double a , double b ) -{ - if ( fabs(a-b) < epsi ) - return true; - return false; -} - - - - -//landscapes -/** - * Extra functions needed in construction of barcodes. -**/ -double minus_length( std::pair a ) -{ - return a.first-a.second; -} -double birth_plus_deaths( std::pair a ) -{ - return a.first+a.second; -} - - -//landscapes -/** - * Given two points in R^2, the procedure compute the parameters A and B of the line y = Ax + B that crosses those two points. -**/ -std::pair compute_parameters_of_a_line( std::pair p1 , std::pair p2 ) -{ - double a = (p2.second-p1.second)/( p2.first - p1.first ); - double b = p1.second - a*p1.first; - return std::make_pair(a,b); -} - -//landscapes -/** - * This procedure given two points which lies on the opposide sides of x axis, compute x for which the line connecting those two points crosses x axis. -**/ -double find_zero_of_a_line_segment_between_those_two_points ( std::pair p1, std::pair p2 ) -{ - if ( p1.first == p2.first )return p1.first; - if ( p1.second*p2.second > 0 ) - { - std::ostringstream errMessage; - errMessage <<"In function find_zero_of_a_line_segment_between_those_two_points the agguments are: (" << p1.first << "," << p1.second << ") and (" << p2.first << "," << p2.second << "). There is no zero in line between those two points. Program terminated."; - std::string errMessageStr = errMessage.str(); - const char* err = errMessageStr.c_str(); - throw(err); - } - //we assume here, that x \in [ p1.first, p2.first ] and p1 and p2 are points between which we will put the line segment - double a = (p2.second - p1.second)/(p2.first - p1.first); - double b = p1.second - a*p1.first; - //cerr << "Line crossing points : (" << p1.first << "," << p1.second << ") oraz (" << p2.first << "," << p2.second << ") : \n"; - //cerr << "a : " << a << " , b : " << b << " , x : " << x << endl; - return -b/a; -} - - - -//landscapes -/** - * This method provides a comparision of points that is used in construction of persistence landscapes. The orderign is lexicographical for the first coordinate, and reverse-lexicographical for the - * second coordinate. -**/ -bool compare_points_sorting( std::pair f, std::pair s ) -{ - if ( f.first < s.first ) - { - return true; - } - else - {//f.first >= s.first - if ( f.first > s.first ) - { - return false; - } - else - {//f.first == s.first - if ( f.second > s.second ) - { - return true; - } - else - { - return false; - } - } - } -} - - -//landscapes -/** - * This procedure takes two points in R^2 and a double value x. It conputes the line pasing through those two points and return the value of that linear function at x. -**/ -double function_value ( std::pair p1, std::pair p2 , double x ) -{ - //we assume here, that x \in [ p1.first, p2.first ] and p1 and p2 are points between which we will put the line segment - double a = (p2.second - p1.second)/(p2.first - p1.first); - double b = p1.second - a*p1.first; - return (a*x+b); -} - - - - -}//namespace Gudhi_stat -}//namespace Gudhi - -#endif diff --git a/src/Gudhi_stat/include/gudhi/common_persistence_representations.h b/src/Gudhi_stat/include/gudhi/common_persistence_representations.h new file mode 100644 index 00000000..f223079a --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/common_persistence_representations.h @@ -0,0 +1,154 @@ +/* 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 (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 common_gudhi_stat_H +#define common_gudhi_stat_H + + +namespace Gudhi +{ +namespace Persistence_representations +{ + //this file contain an implementation of some common procedures used in Gudhi_stat. + + //double epsi = std::numeric_limits::epsilon(); +double epsi = 0.000005; + + + + + +/** + * A procedure used to compare doubles. Typically gien two doubles A and B, comparing A == B is not good idea. In this case, we use the procedure almostEqual with the epsi defined at + * the top of the file. Setting up the epsi give the user a tolerance on what should be consider equal. +**/ +inline bool almost_equal( double a , double b ) +{ + if ( fabs(a-b) < epsi ) + return true; + return false; +} + + + + +//landscapes +/** + * Extra functions needed in construction of barcodes. +**/ +double minus_length( std::pair a ) +{ + return a.first-a.second; +} +double birth_plus_deaths( std::pair a ) +{ + return a.first+a.second; +} + + +//landscapes +/** + * Given two points in R^2, the procedure compute the parameters A and B of the line y = Ax + B that crosses those two points. +**/ +std::pair compute_parameters_of_a_line( std::pair p1 , std::pair p2 ) +{ + double a = (p2.second-p1.second)/( p2.first - p1.first ); + double b = p1.second - a*p1.first; + return std::make_pair(a,b); +} + +//landscapes +/** + * This procedure given two points which lies on the opposide sides of x axis, compute x for which the line connecting those two points crosses x axis. +**/ +double find_zero_of_a_line_segment_between_those_two_points ( std::pair p1, std::pair p2 ) +{ + if ( p1.first == p2.first )return p1.first; + if ( p1.second*p2.second > 0 ) + { + std::ostringstream errMessage; + errMessage <<"In function find_zero_of_a_line_segment_between_those_two_points the agguments are: (" << p1.first << "," << p1.second << ") and (" << p2.first << "," << p2.second << "). There is no zero in line between those two points. Program terminated."; + std::string errMessageStr = errMessage.str(); + const char* err = errMessageStr.c_str(); + throw(err); + } + //we assume here, that x \in [ p1.first, p2.first ] and p1 and p2 are points between which we will put the line segment + double a = (p2.second - p1.second)/(p2.first - p1.first); + double b = p1.second - a*p1.first; + //cerr << "Line crossing points : (" << p1.first << "," << p1.second << ") oraz (" << p2.first << "," << p2.second << ") : \n"; + //cerr << "a : " << a << " , b : " << b << " , x : " << x << endl; + return -b/a; +} + + + +//landscapes +/** + * This method provides a comparision of points that is used in construction of persistence landscapes. The orderign is lexicographical for the first coordinate, and reverse-lexicographical for the + * second coordinate. +**/ +bool compare_points_sorting( std::pair f, std::pair s ) +{ + if ( f.first < s.first ) + { + return true; + } + else + {//f.first >= s.first + if ( f.first > s.first ) + { + return false; + } + else + {//f.first == s.first + if ( f.second > s.second ) + { + return true; + } + else + { + return false; + } + } + } +} + + +//landscapes +/** + * This procedure takes two points in R^2 and a double value x. It conputes the line pasing through those two points and return the value of that linear function at x. +**/ +double function_value ( std::pair p1, std::pair p2 , double x ) +{ + //we assume here, that x \in [ p1.first, p2.first ] and p1 and p2 are points between which we will put the line segment + double a = (p2.second - p1.second)/(p2.first - p1.first); + double b = p1.second - a*p1.first; + return (a*x+b); +} + + + + +}//namespace Gudhi_stat +}//namespace Gudhi + +#endif diff --git a/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h b/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h index 7d1b04c9..a19e6d60 100644 --- a/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h +++ b/src/Gudhi_stat/include/gudhi/multiplicative_bootstrap.h @@ -24,10 +24,10 @@ #define BOOTSTRAP_H //concretizations -#include -#include -#include -#include +#include +#include +#include +#include #ifdef GUDHI_USE_TBB #include diff --git a/src/Gudhi_stat/include/gudhi/persistence_representations/PSSK.h b/src/Gudhi_stat/include/gudhi/persistence_representations/PSSK.h deleted file mode 100644 index d2fd3a86..00000000 --- a/src/Gudhi_stat/include/gudhi/persistence_representations/PSSK.h +++ /dev/null @@ -1,181 +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 (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 -#ifndef PSSK_H -#define PSSK_H - -//gudhi include -#include - - -namespace Gudhi -{ -namespace Gudhi_stat -{ - -/** -* This is a version of a representation presented in https://arxiv.org/abs/1412.6821 -* In that paper the authors are using the representation just to compute kernel. Over here, we extend the usability by far. -* Note that the version presented here is not exact, since we are discretizing the kernel. -* The only difference with respect to the original class is the method of creation. We have full (square) image, and for every point (p,q), we add a kernel at (p,q) and the negative kernel -* at (q,p) -**/ - -class PSSK : public Persistence_heat_maps -{ -public: - PSSK():Persistence_heat_maps(){} - - PSSK(const std::vector< std::pair< double,double > > & interval , std::vector< std::vector > filter = create_Gaussian_filter(5,1) , size_t number_of_pixels = 1000 , double min_ = -1 , double max_ = -1 ) - :Persistence_heat_maps() - { - this->construct( interval , filter , number_of_pixels , min_ , max_ ); - } - - - PSSK( const char* filename , std::vector< std::vector > filter = create_Gaussian_filter(5,1) , size_t number_of_pixels = 1000 , double min_ = -1 , double max_ = -1 , unsigned dimension = std::numeric_limits::max() ): - Persistence_heat_maps() - { - std::vector< std::pair< double , double > > intervals_; - if ( dimension == std::numeric_limits::max() ) - { - intervals_ = read_persistence_intervals_in_one_dimension_from_file( filename ); - } - else - { - intervals_ = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); - } - this->construct( intervals_ , filter , number_of_pixels , min_ , max_ ); - } - -protected: - void construct( const std::vector< std::pair >& intervals_ , - std::vector< std::vector > filter = create_Gaussian_filter(5,1), - size_t number_of_pixels = 1000 , double min_ = -1 , double max_ = -1 ); -}; - -//if min_ == max_, then the program is requested to set up the values itself based on persistence intervals -void PSSK::construct( const std::vector< std::pair >& intervals_ , - std::vector< std::vector > filter, - size_t number_of_pixels , double min_ , double max_ ) -{ - bool dbg = false; - if ( dbg ){std::cerr << "Entering construct procedure \n";getchar();} - - if ( min_ == max_ ) - { - //in this case, we want the program to set up the min_ and max_ values by itself. - min_ = std::numeric_limits::max(); - max_ = -std::numeric_limits::max(); - - - for ( size_t i = 0 ; i != intervals_.size() ; ++i ) - { - if ( intervals_[i].first < min_ )min_ = intervals_[i].first; - if ( intervals_[i].second > max_ )max_ = intervals_[i].second; - } - //now we have the structure filled in, and moreover we know min_ and max_ values of the interval, so we know the range. - - //add some more space: - min_ -= fabs(max_ - min_)/100; - max_ += fabs(max_ - min_)/100; - } - - if ( dbg ) - { - std::cerr << "min_ : " << min_ << std::endl; - std::cerr << "max_ : " << max_ << std::endl; - std::cerr << "number_of_pixels : " << number_of_pixels << std::endl; - getchar(); - } - - this->min_ = min_; - this->max_ = max_; - - - - //initialization of the structure heat_map - std::vector< std::vector > heat_map_; - for ( size_t i = 0 ; i != number_of_pixels ; ++i ) - { - std::vector v( number_of_pixels , 0 ); - heat_map_.push_back( v ); - } - this->heat_map = heat_map_; - - if (dbg)std::cerr << "Done creating of the heat map, now we will fill in the structure \n"; - - for ( size_t pt_nr = 0 ; pt_nr != intervals_.size() ; ++pt_nr ) - { - //compute the value of intervals_[pt_nr] in the grid: - int x_grid = (int)((intervals_[pt_nr].first - this->min_)/( this->max_-this->min_ )*number_of_pixels); - int y_grid = (int)((intervals_[pt_nr].second - this->min_)/( this->max_-this->min_ )*number_of_pixels); - - if ( dbg ) - { - std::cerr << "point : " << intervals_[pt_nr].first << " , " << intervals_[pt_nr].second << std::endl; - std::cerr << "x_grid : " << x_grid << std::endl; - std::cerr << "y_grid : " << y_grid << std::endl; - } - - //x_grid and y_grid gives a center of the kernel. We want to have its lower left cordner. To get this, we need to shift x_grid and y_grid by a grid diameter. - x_grid -= filter.size()/2; - y_grid -= filter.size()/2; - //note that the numbers x_grid and y_grid may be negative. - - if ( dbg ) - { - std::cerr << "After shift : \n";; - std::cerr << "x_grid : " << x_grid << std::endl; - std::cerr << "y_grid : " << y_grid << std::endl; - std::cerr << "filter.size() : " << filter.size() << std::endl; - getchar(); - } - - - for ( size_t i = 0 ; i != filter.size() ; ++i ) - { - for ( size_t j = 0 ; j != filter.size() ; ++j ) - { - //if the point (x_grid+i,y_grid+j) is the correct point in the grid. - if ( - ((x_grid+i)>=0) && (x_grid+iheat_map.size()) - && - ((y_grid+j)>=0) && (y_grid+jheat_map.size()) - ) - { - if ( dbg ){std::cerr << y_grid+j << " " << x_grid+i << std::endl;} - this->heat_map[ y_grid+j ][ x_grid+i ] += filter[i][j]; - this->heat_map[ x_grid+i ][ y_grid+j ] += -filter[i][j]; - } - } - } - - } -}//construct - - -#endif - -}//namespace Gudhi_stat -}//namespace Gudhi diff --git a/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_heat_maps.h b/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_heat_maps.h deleted file mode 100644 index 56890267..00000000 --- a/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_heat_maps.h +++ /dev/null @@ -1,1040 +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 (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 Persistence_heat_maps_H -#define Persistence_heat_maps_H - -//standard include -#include -#include -#include -#include -#include -#include -#include - -//gudhi include -#include -#include - - - - -namespace Gudhi -{ -namespace Gudhi_stat -{ - - -/** - * This is a simple procedure to create n by n (or 2*pixel_radius times 2*pixel_radius cubical approximation of a Gaussian kernel. -**/ -std::vector< std::vector > create_Gaussian_filter( size_t pixel_radius , double sigma ) -{ - bool dbg = false; - //we are computing the kernel mask to 2 standard deviations away from the center. We discretize it in a grid of a size 2*pixel_radius times 2*pixel_radius. - - double r = 0; - double sigma_sqr = sigma * sigma; - - // sum is for normalization - double sum = 0; - - //initialization of a kernel: - std::vector< std::vector > kernel( 2*pixel_radius +1 ); - for ( size_t i = 0 ; i != kernel.size() ; ++i ) - { - std::vector v( 2*pixel_radius +1 , 0 ); - kernel[i] = v; - } - - if ( dbg ) - { - std::cerr << "Kernel initalize \n"; - std::cerr << "pixel_radius : " << pixel_radius << std::endl; - std::cerr << "kernel.size() : " << kernel.size() << std::endl; - getchar(); - } - - for (int x = -pixel_radius; x <= (int)pixel_radius; x++) - { - for(int y = -pixel_radius; y <= (int)pixel_radius; y++) - { - double real_x = 2*sigma*x/pixel_radius; - double real_y = 2*sigma*y/pixel_radius; - r = sqrt(real_x*real_x + real_y*real_y); - kernel[x + pixel_radius][y + pixel_radius] = (exp(-(r*r)/sigma_sqr))/(3.141592 * sigma_sqr); - sum += kernel[x + pixel_radius][y + pixel_radius]; - } - } - - // normalize the kernel - for( size_t i = 0; i != kernel.size() ; ++i) - { - for( size_t j = 0; j != kernel[i].size() ; ++j) - { - kernel[i][j] /= sum; - } - - } - - if ( dbg ) - { - std::cerr << "Here is the kernel : \n"; - for( size_t i = 0; i != kernel.size() ; ++i) - { - for( size_t j = 0; j != kernel[i].size() ; ++j) - { - std::cerr << kernel[i][j] << " "; - } - std::cerr << std::endl; - } - } - return kernel; -} - - -/* -* There are various options to scale the poits depending on their location. One can for instance: -* (1) do nothing (scale all of them with the weight 1), as in the function constant_function -* (2) Scale them by the distance to the diagonal. This is implemented in function -* (3) Scale them with the square of their distance to diagonal. This is implemented in function -* (4) Scale them with -*/ - - -/** - * This is one of a scaling functions used to weight poits depending on their persistence and/or location in the diagram. - * This particular functiona is a finction which always assign value 1 to a point in the diagram. -**/ -class constant_scaling_function -{ -public: - double operator()( const std::pair< double , double >& point_in_diagram ) - { - return 1; - } -}; - - -/** - * This is one of a scaling functions used to weight poits depending on their persistence and/or location in the diagram. - * The scaling given by this function to a point (b,d) is Euclidean distance of (b,d) from diagonal. -**/ -class distance_from_diagonal_scaling -{ -public: - double operator()( const std::pair< double , double >& point_in_diagram ) - { - //(point_in_diagram.first+point_in_diagram.second)/2.0 - return sqrt( pow((point_in_diagram.first-(point_in_diagram.first+point_in_diagram.second)/2.0),2) + pow((point_in_diagram.second-(point_in_diagram.first+point_in_diagram.second)/2.0),2) ); - } -}; - -/** - * This is one of a scaling functions used to weight poits depending on their persistence and/or location in the diagram. - * The scaling given by this function to a point (b,d) is a square of Euclidean distance of (b,d) from diagonal. -**/ -class squared_distance_from_diagonal_scaling -{ -public: - double operator()( const std::pair< double , double >& point_in_diagram ) - { - return pow((point_in_diagram.first-(point_in_diagram.first+point_in_diagram.second)/2.0),2) + pow((point_in_diagram.second-(point_in_diagram.first+point_in_diagram.second)/2.0),2); - } -}; - -/** - * This is one of a scaling functions used to weight poits depending on their persistence and/or location in the diagram. - * The scaling given by this function to a point (b,d) is an arctan of a persistence of a point (i.e. arctan( b-d ). -**/ -class arc_tan_of_persistence_of_point -{ -public: - double operator()( const std::pair< double , double >& point_in_diagram ) - { - return atan( point_in_diagram.second - point_in_diagram.first ); - } -}; - -/** - * This is one of a scaling functions used to weight poits depending on their persistence and/or location in the diagram. - * This scaling function do not only depend on a point (p,d) in the diagram, but it depends on the whole diagram. - * The longest persistence pair get a scaling 1. Any other pair get a scaling belong to [0,1], which is proportional - * to the persistence of that pair. -**/ -class weight_by_setting_maximal_interval_to_have_length_one -{ -public: - weight_by_setting_maximal_interval_to_have_length_one( double len ):letngth_of_maximal_interval(len){} - double operator()( const std::pair< double , double >& point_in_diagram ) - { - return (point_in_diagram.second-point_in_diagram.first)/this->letngth_of_maximal_interval; - } -private: - double letngth_of_maximal_interval; -}; - - -/** - * This class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product -**/ -template -class Persistence_heat_maps -{ -public: - /** - * The default constructor. A scaling function from the diagonal is set up to a constant function. The image is not erased below the diagonal. The gaussian have diameter 5. - **/ - Persistence_heat_maps() - { - Scalling_of_kernels f; - this->f = f; - this->erase_below_diagonal = false; - this->min_ = this->max_ = 0; - this->set_up_parameters_for_basic_classes(); - }; - - /** - * Construction that takes at the input the following parameters: - * (1) A vector of pairs of doubles (representing persistence intervals). All other parameters are optional. They are: - * (2) a Gausian filter generated by create_Gaussian_filter filter (the default value of this vaiable is a Gaussian filter of a radius 5), - * (3) a boolean value which determines if the area of image below diagonal should, or should not be erased (it will be erased by default). - * (4) a number of pixels in each direction (set to 1000 by default). - * (5) a min x and y value of points that are to be taken into account. By default it is set to std::numeric_limits::max(), in which case the program compute the values based on the data, - * (6) a max x and y value of points that are to be taken into account. By default it is set to std::numeric_limits::max(), in which case the program compute the values based on the data. - **/ - Persistence_heat_maps( const std::vector< std::pair< double,double > > & interval , std::vector< std::vector > filter = create_Gaussian_filter(5,1) , bool erase_below_diagonal = false , size_t number_of_pixels = 1000 , double min_ = std::numeric_limits::max() , double max_ = std::numeric_limits::max() ); - - /** - * Construction that takes at the input a name of a file with persistence intervals, a filter (radius 5 by default), a scaling function (constant by default), a boolean value which determines if the area of image below diagonal should, or should not be erased (should by default). The next parameter is the number of pixels in each direction (set to 1000 by default). and min and max values of images (both set to std::numeric_limits::max() by defaulet. If this is the case, the program will pick the right values based on the data). - **/ - /** - * Construction that takes at the input the following parameters: - * (1) A a name of a file with persistence intervals. The file shold be readable by the function read_persistence_intervals_in_one_dimension_from_file. All other parameters are optional. They are: - * (2) a Gausian filter generated by create_Gaussian_filter filter (the default value of this vaiable is a Gaussian filter of a radius 5), - * (3) a boolean value which determines if the area of image below diagonal should, or should not be erased (it will be erased by default). - * (4) a number of pixels in each direction (set to 1000 by default). - * (5) a min x and y value of points that are to be taken into account. By default it is set to std::numeric_limits::max(), in which case the program compute the values based on the data, - * (6) a max x and y value of points that are to be taken into account. By default it is set to std::numeric_limits::max(), in which case the program compute the values based on the data. - **/ - Persistence_heat_maps( const char* filename , std::vector< std::vector > filter = create_Gaussian_filter(5,1), bool erase_below_diagonal = false , size_t number_of_pixels = 1000 , double min_ = std::numeric_limits::max() , double max_ = std::numeric_limits::max() , unsigned dimension = std::numeric_limits::max() ); - - - /** - * Compute a mean value of a collection of heat maps and store it in the current object. Note that all the persistence maps send in a vector to this procedure need to have the same parameters. - * If this is not the case, the program will throw an exception. - **/ - void compute_mean( const std::vector& maps ); - - /** - * Compute a median value of a collection of heat maps and store it in the current object. Note that all the persistence maps send in a vector to this procedure need to have the same parameters. - * If this is not the case, the program will throw an exception. - **/ - void compute_median( const std::vector& maps ); - - /** - * Compute a percentage of active (i.e) values above the cutoff of a collection of heat maps. - **/ - void compute_percentage_of_active( const std::vector& maps , size_t cutoff = 1 ); - - //put to file subroutine - /** - * The function outputs the perssitence image to a text file. The format as follow: - * In the first line, the values min and max of the image are stored - * In the next lines, we have the persistence images in a form of a bitmap image. - **/ - void print_to_file( const char* filename )const; - - /** - * A function that load a heat map from file to the current object (and arase qhatever was stored in the current object before). - **/ - void load_from_file( const char* filename ); - - - /** - * The procedure checks if min_, max_ and this->heat_maps sizes are the same. - **/ - inline bool check_if_the_same( const Persistence_heat_maps& second )const - { - bool dbg = false; - if ( this->heat_map.size() != second.heat_map.size() ) - { - if ( dbg )std::cerr << "this->heat_map.size() : " << this->heat_map.size() << " \n second.heat_map.size() : " << second.heat_map.size() << std::endl; - return false; - } - if ( this->min_ != second.min_ ) - { - if ( dbg )std::cerr << "this->min_ : " << this->min_ << ", second.min_ : " << second.min_ << std::endl; - return false; - } - if ( this->max_ != second.max_ ) - { - if ( dbg )std::cerr << "this->max_ : " << this->max_ << ", second.max_ : " << second.max_ << std::endl; - return false; - } - //in the other case we may assume that the persistence images are defined on the same domain. - return true; - } - - - /** - * Return minimal range value of persistent image. - **/ - inline double get_min()const{return this->min_;} - - /** - * Return maximal range value of persistent image. - **/ - inline double get_max()const{return this->max_;} - - - /** - * Operator == to check if to persistence heat maps are the same. - **/ - bool operator == ( const Persistence_heat_maps& rhs )const - { - bool dbg = false; - if ( !this->check_if_the_same(rhs) ) - { - if ( dbg )std::cerr << "The domains are not the same \n"; - return false;//in this case, the domains are not the same, so the maps cannot be the same. - } - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) - { - for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) - { - if ( !almost_equal(this->heat_map[i][j] , rhs.heat_map[i][j]) ) - { - if ( dbg ) - { - std::cerr << "this->heat_map[" << i << "][" << j << "] = " << this->heat_map[i][j] << std::endl; - std::cerr << "rhs.heat_map[" << i << "][" << j << "] = " << rhs.heat_map[i][j] << std::endl; - } - return false; - } - } - } - return true; - } - - /** - * Operator != to check if to persistence heat maps are different. - **/ - bool operator != ( const Persistence_heat_maps& rhs )const - { - return !( (*this) == rhs ); - } - - - /** - * A function to generate a gnuplot script to vizualize the persistent image. - **/ - void plot( const char* filename )const; - - - template - friend Persistence_heat_maps operation_on_pair_of_heat_maps( const Persistence_heat_maps& first , const Persistence_heat_maps& second , Operation_type operation ) - { - //first check if the heat maps are compatible - if ( !first.check_if_the_same( second ) ) - { - std::cerr << "Sizes of the heat maps are not compatible. The program will now terminate \n"; - throw "Sizes of the heat maps are not compatible. The program will now terminate \n"; - } - Persistence_heat_maps result; - result.min_ = first.min_; - result.max_ = first.max_; - result.heat_map.reserve( first.heat_map.size() ); - for ( size_t i = 0 ; i != first.heat_map.size() ; ++i ) - { - std::vector< double > v; - v.reserve( first.heat_map[i].size() ); - for ( size_t j = 0 ; j != first.heat_map[i].size() ; ++j ) - { - v.push_back( operation( first.heat_map[i][j] , second.heat_map[i][j] ) ); - } - result.heat_map.push_back( v ); - } - return result; - }//operation_on_pair_of_heat_maps - - - /** - * Multiplication of Persistence_heat_maps by scalar (so that all values of the heat map gets multiplied by that scalar). - **/ - Persistence_heat_maps multiply_by_scalar( double scalar )const - { - Persistence_heat_maps result; - result.min_ = this->min_; - result.max_ = this->max_; - result.heat_map.reserve( this->heat_map.size() ); - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) - { - std::vector< double > v; - v.reserve( this->heat_map[i].size() ); - for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) - { - v.push_back( this->heat_map[i][j] * scalar ); - } - result.heat_map.push_back( v ); - } - return result; - } - - /** - * This function computes a sum of two objects of a type Persistence_heat_maps. - **/ - friend Persistence_heat_maps operator+( const Persistence_heat_maps& first , const Persistence_heat_maps& second ) - { - return operation_on_pair_of_heat_maps( first , second , std::plus() ); - } - /** - * This function computes a difference of two objects of a type Persistence_heat_maps. - **/ - friend Persistence_heat_maps operator-( const Persistence_heat_maps& first , const Persistence_heat_maps& second ) - { - return operation_on_pair_of_heat_maps( first , second , std::minus() ); - } - /** - * This function computes a product of an object of a type Persistence_heat_maps with real number. - **/ - friend Persistence_heat_maps operator*( double scalar , const Persistence_heat_maps& A ) - { - return A.multiply_by_scalar( scalar ); - } - /** - * This function computes a product of an object of a type Persistence_heat_maps with real number. - **/ - friend Persistence_heat_maps operator*( const Persistence_heat_maps& A , double scalar ) - { - return A.multiply_by_scalar( scalar ); - } - /** - * This function computes a product of an object of a type Persistence_heat_maps with real number. - **/ - Persistence_heat_maps operator*( double scalar ) - { - return this->multiply_by_scalar( scalar ); - } - /** - * += operator for Persistence_heat_maps. - **/ - Persistence_heat_maps operator += ( const Persistence_heat_maps& rhs ) - { - *this = *this + rhs; - return *this; - } - /** - * -= operator for Persistence_heat_maps. - **/ - Persistence_heat_maps operator -= ( const Persistence_heat_maps& rhs ) - { - *this = *this - rhs; - return *this; - } - /** - * *= operator for Persistence_heat_maps. - **/ - Persistence_heat_maps operator *= ( double x ) - { - *this = *this*x; - return *this; - } - /** - * /= operator for Persistence_heat_maps. - **/ - Persistence_heat_maps operator /= ( double x ) - { - if ( x == 0 )throw( "In operator /=, division by 0. Program terminated." ); - *this = *this * (1/x); - return *this; - } - - - //Implementations of functions for various concepts. - - /** - * This function produce a vector of doubles based on a persisence heat map. It is required in a concept Vectorized_topological_data - */ - std::vector vectorize( int number_of_function )const; - /** - * This function return the number of functions that allows vectorization of persistence heat map. It is required in a concept Vectorized_topological_data. - **/ - size_t number_of_vectorize_functions()const - { - return this->number_of_functions_for_vectorization; - } - - /** - * This function is required by the Real_valued_topological_data concept. It returns various projections od the persistence heat map to a real line. - **/ - double project_to_R( int number_of_function )const; - /** - * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. - **/ - size_t number_of_projections_to_R()const - { - return this->number_of_functions_for_projections_to_reals; - } - - /** - * A function to compute distance between persistence heat maps. - * The parameter of this function is a const reference to an object of a class Persistence_heat_maps. - * This function is required in Topological_data_with_distances concept. - * For max norm distance, set power to std::numeric_limits::max() - **/ - double distance( const Persistence_heat_maps& second_ , double power = 1)const; - - /** - * A function to compute averaged persistence heat map, based on vector of persistence heat maps. - * This function is required by Topological_data_with_averages concept. - **/ - void compute_average( const std::vector< Persistence_heat_maps* >& to_average ); - - /** - * A function to compute scalar product of persistence heat maps. - * The parameter of this functionis a const reference to an object of a class Persistence_heat_maps. - * This function is required in Topological_data_with_scalar_product concept. - **/ - double compute_scalar_product( const Persistence_heat_maps& second_ )const; - - //end of implementation of functions needed for concepts. - - - /** - * The x-range of the persistence heat map. - **/ - std::pair< double , double > get_x_range()const - { - return std::make_pair( this->min_ , this->max_ ); - } - - /** - * The y-range of the persistence heat map. - **/ - std::pair< double , double > get_y_range()const - { - return this->get_x_range(); - } - - - - -protected: - //private methods - std::vector< std::vector > check_and_initialize_maps( const std::vector& maps ); - size_t number_of_functions_for_vectorization; - size_t number_of_functions_for_projections_to_reals; - void construct( const std::vector< std::pair >& intervals_ , - std::vector< std::vector > filter = create_Gaussian_filter(5,1), - - bool erase_below_diagonal = false , size_t number_of_pixels = 1000 , double min_ = std::numeric_limits::max() , double max_ = std::numeric_limits::max() ); - - void set_up_parameters_for_basic_classes() - { - this->number_of_functions_for_vectorization = 1; - this->number_of_functions_for_projections_to_reals = 1; - } - - //data - //double (*scalling_function_with_respect_to_distance_from_diagonal)( const std::pair< double , double >& point_in_diagram ); - Scalling_of_kernels f; - bool erase_below_diagonal; - double min_; - double max_; - std::vector< std::vector< double > > heat_map; -}; - - -//if min_ == max_, then the program is requested to set up the values itself based on persistence intervals -template -void Persistence_heat_maps::construct( const std::vector< std::pair >& intervals_ , - std::vector< std::vector > filter, - bool erase_below_diagonal , size_t number_of_pixels , double min_ , double max_ ) -{ - bool dbg = false; - if ( dbg )std::cerr << "Entering construct procedure \n"; - Scalling_of_kernels f; - this->f = f; - - if ( dbg )std::cerr << "min and max passed to construct() procedure: " << min_ << " " << max_ << std::endl; - - if ( min_ == max_ ) - { - if (dbg)std::cerr << "min and max parameters will be etermined based on intervals \n"; - //in this case, we want the program to set up the min_ and max_ values by itself. - min_ = std::numeric_limits::max(); - max_ = -std::numeric_limits::max(); - - - for ( size_t i = 0 ; i != intervals_.size() ; ++i ) - { - if ( intervals_[i].first < min_ )min_ = intervals_[i].first; - if ( intervals_[i].second > max_ )max_ = intervals_[i].second; - } - //now we have the structure filled in, and moreover we know min_ and max_ values of the interval, so we know the range. - - //add some more space: - min_ -= fabs(max_ - min_)/100; - max_ += fabs(max_ - min_)/100; - } - - if ( dbg ) - { - std::cerr << "min_ : " << min_ << std::endl; - std::cerr << "max_ : " << max_ << std::endl; - std::cerr << "number_of_pixels : " << number_of_pixels << std::endl; - getchar(); - } - - this->min_ = min_; - this->max_ = max_; - - //initialization of the structure heat_map - std::vector< std::vector > heat_map_; - for ( size_t i = 0 ; i != number_of_pixels ; ++i ) - { - std::vector v( number_of_pixels , 0 ); - heat_map_.push_back( v ); - } - this->heat_map = heat_map_; - - if (dbg)std::cerr << "Done creating of the heat map, now we will fill in the structure \n"; - - for ( size_t pt_nr = 0 ; pt_nr != intervals_.size() ; ++pt_nr ) - { - //compute the value of intervals_[pt_nr] in the grid: - int x_grid = (int)((intervals_[pt_nr].first - this->min_)/( this->max_-this->min_ )*number_of_pixels); - int y_grid = (int)((intervals_[pt_nr].second - this->min_)/( this->max_-this->min_ )*number_of_pixels); - - if ( dbg ) - { - std::cerr << "point : " << intervals_[pt_nr].first << " , " << intervals_[pt_nr].second << std::endl; - std::cerr << "x_grid : " << x_grid << std::endl; - std::cerr << "y_grid : " << y_grid << std::endl; - } - - //x_grid and y_grid gives a center of the kernel. We want to have its lower left cordner. To get this, we need to shift x_grid and y_grid by a grid diameter. - x_grid -= filter.size()/2; - y_grid -= filter.size()/2; - //note that the numbers x_grid and y_grid may be negative. - - if ( dbg ) - { - std::cerr << "After shift : \n";; - std::cerr << "x_grid : " << x_grid << std::endl; - std::cerr << "y_grid : " << y_grid << std::endl; - } - - double scaling_value = this->f(intervals_[pt_nr]); - - - for ( size_t i = 0 ; i != filter.size() ; ++i ) - { - for ( size_t j = 0 ; j != filter.size() ; ++j ) - { - //if the point (x_grid+i,y_grid+j) is the correct point in the grid. - if ( - ((x_grid+i)>=0) && (x_grid+iheat_map.size()) - && - ((y_grid+j)>=0) && (y_grid+jheat_map.size()) - ) - { - if ( dbg ){std::cerr << y_grid+j << " " << x_grid+i << std::endl;} - this->heat_map[ y_grid+j ][ x_grid+i ] += scaling_value * filter[i][j]; - if ( dbg ) - { - std::cerr << "Position : (" << x_grid+i << "," << y_grid+j << ") got increased by the value : " << filter[i][j] << std::endl; - } - } - } - } - - } - - //now it remains to cut everything below diagonal if the user wants us to. - if ( erase_below_diagonal ) - { - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) - { - for ( size_t j = i ; j != this->heat_map.size() ; ++j ) - { - this->heat_map[i][j] = 0; - } - } - } -}//construct - -template -Persistence_heat_maps::Persistence_heat_maps( const std::vector< std::pair< double,double > > & interval , - std::vector< std::vector > filter, - bool erase_below_diagonal , size_t number_of_pixels , double min_ , double max_ ) -{ - this->construct( interval , filter , erase_below_diagonal , number_of_pixels , min_ , max_ ); - this->set_up_parameters_for_basic_classes(); -} - - -template -Persistence_heat_maps::Persistence_heat_maps( const char* filename , - std::vector< std::vector > filter, - bool erase_below_diagonal , size_t number_of_pixels , double min_ , double max_ , unsigned dimension ) -{ - std::vector< std::pair< double , double > > intervals_; - if ( dimension == std::numeric_limits::max() ) - { - intervals_ = read_persistence_intervals_in_one_dimension_from_file( filename ); - } - else - { - intervals_ = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); - } - //std::cerr << "intervals_.size() : " << intervals_.size() << std::endl; - //for ( size_t i = 0 ; i != intervals_.size() ; ++i ) - //{ - // std::cerr << intervals_[i].first << " " << intervals_[i].second << std::endl; - //} - this->construct( intervals_ , filter, erase_below_diagonal , number_of_pixels , min_ , max_ ); - this->set_up_parameters_for_basic_classes(); -} - - -template -std::vector< std::vector > Persistence_heat_maps::check_and_initialize_maps( const std::vector& maps ) -{ - //checking if all the heat maps are of the same size: - for ( size_t i = 0 ; i != maps.size() ; ++i ) - { - if ( maps[i]->heat_map.size() != maps[0]->heat_map.size() ) - { - std::cerr << "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n"; - throw "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n"; - } - if ( maps[i]->heat_map[0].size() != maps[0]->heat_map[0].size() ) - { - std::cerr << "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n"; - throw "Sizes of Persistence_heat_maps are not compatible. The program will terminate now \n"; - } - } - std::vector< std::vector > heat_maps( maps[0]->heat_map.size() ); - for ( size_t i = 0 ; i != maps[0]->heat_map.size() ; ++i ) - { - std::vector v( maps[0]->heat_map[0].size() , 0 ); - heat_maps[i] = v; - } - return heat_maps; -} - -template -void Persistence_heat_maps::compute_median( const std::vector& maps ) -{ - std::vector< std::vector > heat_maps = this->check_and_initialize_maps( maps ); - - std::vector to_compute_median( maps.size() ); - for ( size_t i = 0 ; i != heat_maps.size() ; ++i ) - { - for ( size_t j = 0 ; j != heat_maps[i].size() ; ++j ) - { - for ( size_t map_no = 0 ; map_no != maps.size() ; ++map_no ) - { - to_compute_median[map_no] = maps[map_no]->heat_map[i][j]; - } - std::nth_element(to_compute_median.begin(), to_compute_median.begin() + to_compute_median.size()/2, to_compute_median.end()); - heat_maps[i][j] = to_compute_median[ to_compute_median.size()/2 ]; - } - } - this->heat_map = heat_maps; - this->min_= maps[0]->min_; - this->max_= maps[0]->max_; -} - - -template -void Persistence_heat_maps::compute_mean( const std::vector& maps ) -{ - std::vector< std::vector > heat_maps = this->check_and_initialize_maps( maps ); - for ( size_t i = 0 ; i != heat_maps.size() ; ++i ) - { - for ( size_t j = 0 ; j != heat_maps[i].size() ; ++j ) - { - double mean = 0; - for ( size_t map_no = 0 ; map_no != maps.size() ; ++map_no ) - { - mean += maps[map_no]->heat_map[i][j]; - } - heat_maps[i][j] = mean/(double)maps.size(); - } - } - this->heat_map = heat_maps; - this->min_ = maps[0]->min_; - this->max_ = maps[0]->max_; -} - - - -template -void Persistence_heat_maps::compute_percentage_of_active( const std::vector& maps , size_t cutoff ) -{ - std::vector< std::vector > heat_maps = this->check_and_initialize_maps( maps ); - - for ( size_t i = 0 ; i != heat_maps.size() ; ++i ) - { - for ( size_t j = 0 ; j != heat_maps[i].size() ; ++j ) - { - size_t number_of_active_levels = 0; - for ( size_t map_no = 0 ; map_no != maps.size() ; ++map_no ) - { - if ( maps[map_no]->heat_map[i][j] ) number_of_active_levels++; - } - if ( number_of_active_levels > cutoff ) - { - heat_maps[i][j] = number_of_active_levels; - } - else - { - heat_maps[i][j] = 0; - } - } - } - this->heat_map = heat_maps; - this->min_ = maps[0]->min_; - this->max_ = maps[0]->max_; -} - - -template -void Persistence_heat_maps::plot( const char* filename )const -{ - std::ofstream out; - std::stringstream ss; - ss << filename << "_GnuplotScript"; - - out.open( ss.str().c_str() ); - out << "plot '-' matrix with image" << std::endl; - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) - { - for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) - { - out << this->heat_map[i][j] << " "; - } - out << std::endl; - } - out.close(); - std::cout << "Gnuplot script have been created. Open gnuplot and type load \'" << ss.str().c_str() << "\' to see the picture." << std::endl; -} - - -template -void Persistence_heat_maps::print_to_file( const char* filename )const -{ - - std::ofstream out; - out.open( filename ); - - //First we store this->min_ and this->max_ values: - out << this->min_ << " " << this->max_ << std::endl; - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) - { - for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) - { - out << this->heat_map[i][j] << " "; - } - out << std::endl; - } - out.close(); -} - -template -void Persistence_heat_maps::load_from_file( const char* filename ) -{ - bool dbg = false; - - std::ifstream in; - in.open( filename ); - - //checking if the file exist / if it was open. - if ( !in.good() ) - { - std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; - throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; - } - - //now we read the file one by one. - - - - in >> this->min_ >> this->max_; - if ( dbg ) - { - std::cerr << "Reading the following values of min and max : " << this->min_ << " , " << this->max_ << std::endl; - } - - std::string temp; - std::getline(in, temp); - - while (!in.eof()) - { - std::getline(in, temp); - std::stringstream lineSS; - lineSS << temp; - - std::vector line_of_heat_map; - while ( lineSS.good() ) - { - double point; - - lineSS >> point; - line_of_heat_map.push_back( point ); - if ( dbg ) - { - std::cout << point << " "; - } - } - if ( dbg ) - { - std::cout << std::endl; - getchar(); - } - - if ( in.good() )this->heat_map.push_back( line_of_heat_map ); - } - in.close(); - if ( dbg )std::cout << "Done \n"; -} - - -//Concretizations of virtual methods: -template -std::vector Persistence_heat_maps::vectorize( int number_of_function )const -{ - //convert this->heat_map into one large vector: - size_t size_of_result = 0; - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) - { - size_of_result += this->heat_map[i].size(); - } - - std::vector< double > result; - result.reserve( size_of_result ); - - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) - { - for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) - { - result.push_back( this->heat_map[i][j] ); - } - } - - return result; -} - -template -double Persistence_heat_maps::distance( const Persistence_heat_maps& second , double power )const -{ - //first we need to check if (*this) and second are defined on the same domain and have the same dimensions: - if ( !this->check_if_the_same(second) ) - { - std::cerr << "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; - throw "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; - } - - //if we are here, we know that the two persistence iomages are defined on the same domain, so we can start computing their distances: - - double distance = 0; - if ( power < std::numeric_limits::max() ) - { - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) - { - for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) - { - distance += pow( fabs(this->heat_map[i][j] - second.heat_map[i][j]) , power ); - } - } - } - else - { - //in this case, we compute max norm distance - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) - { - for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) - { - if ( distance < fabs(this->heat_map[i][j] - second.heat_map[i][j]) ) - { - distance = fabs(this->heat_map[i][j] - second.heat_map[i][j]); - } - } - } - } - return distance; -} - -template -double Persistence_heat_maps::project_to_R( int number_of_function )const -{ - double result = 0; - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) - { - for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) - { - result += this->heat_map[i][j]; - } - } - return result; -} - -template -void Persistence_heat_maps::compute_average( const std::vector< Persistence_heat_maps* >& to_average ) -{ - this->compute_mean( to_average ); -} - -template -double Persistence_heat_maps::compute_scalar_product( const Persistence_heat_maps& second )const -{ - //first we need to check if (*this) and second are defined on the same domain and have the same dimensions: - if ( !this->check_if_the_same(second) ) - { - std::cerr << "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; - throw "The persistence images are of noncompatible sizes. We cannot therefore compute distance between them. The program will now terminate"; - } - - //if we are here, we know that the two persistence iomages are defined on the same domain, so we can start computing their scalar product: - double scalar_prod = 0; - for ( size_t i = 0 ; i != this->heat_map.size() ; ++i ) - { - for ( size_t j = 0 ; j != this->heat_map[i].size() ; ++j ) - { - scalar_prod += this->heat_map[i][j]*second.heat_map[i][j]; - } - } - return scalar_prod; -} - - - - -}//namespace Gudhi_stat -}//namespace Gudhi - - -#endif diff --git a/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_intervals.h b/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_intervals.h deleted file mode 100644 index 64d8c502..00000000 --- a/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_intervals.h +++ /dev/null @@ -1,697 +0,0 @@ -/* This file is part of the Gudhi hiLibrary. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Pawel Dlotko - * - * Copyright (C) 2015 INRIA (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 Persistence_intervals_H_ -#define Persistence_intervals_H_ - -//gudhi include -#include - -//standard include -#include -#include -#include -#include -#include -#include -#include - -namespace Gudhi -{ -namespace Gudhi_stat -{ - -/** - * This class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data -**/ -class Persistence_intervals -{ -public: - /** - * This is a constructor of a class Persistence_intervals from a text file. Each line of the input file is supposed to contain two numbers of a type doube (or convertable to double) - * representing the birth and the death of the persistence interval. If the pairs are not sorted so that birth <= death, then the constructor will sort then that way. - * * The second parameter of a constructor is a dimension of intervals to be read from a file. If your file contains only birt-death pairs, use the default value. - **/ - Persistence_intervals( const char* filename , unsigned dimension = std::numeric_limits::max() ); - - /** - * This is a constructor of a class Persistence_intervals from a vector of pairs. Each pair is assumed to represent a persistence interval. We assume that the first elemnets of pairs - * are smaller or equal the second elements of pairs. - **/ - Persistence_intervals( const std::vector< std::pair< double,double > >& intervals ); - - /** - * This procedure returns x-range of a given persistence diagram. - **/ - std::pair< double , double > get_x_range()const - { - double min_ = std::numeric_limits::max(); - double max_ = -std::numeric_limits::max(); - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - if ( this->intervals[i].first < min_ )min_ = this->intervals[i].first; - if ( this->intervals[i].second > max_ )max_ = this->intervals[i].second; - } - return std::make_pair( min_ , max_ ); - } - - /** - * This procedure returns y-range of a given persistence diagram. - **/ - std::pair< double , double > get_y_range()const - { - double min_ = std::numeric_limits::max(); - double max_ = -std::numeric_limits::max(); - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - if ( this->intervals[i].second < min_ )min_ = this->intervals[i].second; - if ( this->intervals[i].second > max_ )max_ = this->intervals[i].second; - } - return std::make_pair( min_ , max_ ); - } - - /** - * Procedure that compute the vector of lengths of the dominant (i.e. the longest) persistence intervals. The list is truncated at the parameter of the call where_to_cut (set by default to 100). - **/ - std::vector length_of_dominant_intervals( size_t where_to_cut = 100 )const; - - - /** - * Procedure that compute the vector of the dominant (i.e. the longest) persistence intervals. The parameter of the procedure (set by default to 100) is the number of dominant intervals returned by the procedure. - **/ - std::vector< std::pair > dominant_intervals( size_t where_to_cut = 100 )const; - - /** - * Procedure to compute a histogram of interva's length. A histogram is a block plot. The number of blocks is determined by the first parameter of the function (set by default to 10). - * For the sake of argument let us assume that the length of the longest interval is 1 and the number of bins is 10. In this case the i-th block correspond to a range between i-1/10 and i10. - * The vale of a block supported at the interval is the number of persistence intervals of a length between x_0 and x_1. - **/ - std::vector< size_t > histogram_of_lengths( size_t number_of_bins = 10 )const; - - /** - * Based on a histogram of intervals lengts computed by the function histogram_of_lengths H the procedure below computes the cumulative histogram. The i-th position of the resulting histogram - * is the sume of values of H for the positions from 0 to i. - **/ - std::vector< size_t > cumulative_histogram_of_lengths( size_t number_of_bins = 10 )const; - - /** - * In this procedure we assume that each barcode is a characteristic function of a hight equal to its length. The persistence diagram is a sum of such a functions. The procedure below construct a function being a - * sum of the characteristic functions of persistence intervals. The first two parameters are the range in which the function is to be computed and the last parameter is the number of bins in - * the discretization of the interval [_min,_max]. - **/ - std::vector< double > characteristic_function_of_diagram( double x_min , double x_max , size_t number_of_bins = 10 )const; - - /** - * Cumulative version of the function characteristic_function_of_diagram - **/ - std::vector< double > cumulative_characteristic_function_of_diagram( double x_min , double x_max , size_t number_of_bins = 10 )const; - - /** - * Compute the funtion of persistence Betti numbers. The returned value is a vector of pair. First element of each pair is a place where persistence Betti numbers change. - * Second element of each pair is the value of Persistence Betti numbers at that point. - **/ - std::vector< std::pair< double , size_t > > compute_persistent_betti_numbers()const; - - /** - *This is a non optimal procedure that compute vector of distances from each point of diagram to its k-th nearest neighbor (k is a parameted of the program). The resulting vector is by default truncated to 10 - *elements (this value can be changed by using the second parameter of the program). The points are returned in order from the ones which are farthest away from their k-th nearest neighbors. - **/ - std::vector< double > k_n_n( size_t k , size_t where_to_cut = 10 )const; - - /** - * Operator that send the diagram to a stream. - **/ - friend std::ostream& operator << ( std::ostream& out , const Persistence_intervals& intervals ) - { - for ( size_t i = 0 ; i != intervals.intervals.size() ; ++i ) - { - out << intervals.intervals[i].first << " " << intervals.intervals[i].second << std::endl; - } - return out; - } - - /** - * Generating gnuplot script to plot the interval. - **/ - void plot( const char* filename , double min_x = std::numeric_limits::max() , double max_x = std::numeric_limits::max() , double min_y = std::numeric_limits::max() , double max_y = std::numeric_limits::max() ) const - { - //this program create a gnuplot script file that allows to plot persistence diagram. - std::ofstream out; - - std::ostringstream nameSS; - nameSS << filename << "_GnuplotScript"; - std::string nameStr = nameSS.str(); - out.open( nameStr ); - - std::pair min_max_values = this->get_x_range(); - if ( min_x == max_x ) - { - out << "set xrange [" << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " : " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " ]" << std::endl; - out << "set yrange [" << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " : " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " ]" << std::endl; - } - else - { - out << "set xrange [" << min_x << " : " << max_x << " ]" << std::endl; - out << "set yrange [" << min_y << " : " << max_y << " ]" << std::endl; - } - out << "plot '-' using 1:2 notitle \"" << filename << "\", \\" << std::endl; - out << " '-' using 1:2 notitle with lp" << std::endl; - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - out << this->intervals[i].first << " " << this->intervals[i].second << std::endl; - } - out << "EOF" << std::endl; - out << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << " " << min_max_values.first - 0.1*(min_max_values.second-min_max_values.first) << std::endl; - out << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << " " << min_max_values.second + 0.1*(min_max_values.second-min_max_values.first) << std::endl; - - out.close(); - - std::cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << std::endl; - } - - - - - /** - * Retun numbr of points in the diagram. - **/ - size_t size()const{return this->intervals.size();} - - /** - * Return the persistence interval at the given position. Note that intervals are not sorted with respect to their lengths. - **/ - inline std::pair< double,double > operator [](size_t i)const - { - if ( i >= this->intervals.size() )throw("Index out of range! Operator [], one_d_gaussians class\n"); - return this->intervals[i]; - } - - - - - - - - - - - - - - - - //Implementations of functions for various concepts. - /** - * This is a simple function projectig the persistence intervals to a real number. The function we use here is a sum of squared lendgths of intervals. It can be naturally interpreted as - * sum of step function, where the step hight it equal to the length of the interval. - **/ - double project_to_R( int number_of_function )const; - /** - * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. - **/ - size_t number_of_projections_to_R()const - { - return this->number_of_functions_for_projections_to_reals; - } - - /** - * Return a familly of vectors obtained from the persistence diagram. The i-th vector consist of the lenfth of i dominant persistence intervals. - **/ - std::vector vectorize( int number_of_function )const - { - return this->length_of_dominant_intervals( number_of_function ); - } - /** - * This function return the number of functions that allows vectorization of a persisence diagram. It is required in a concept Vectorized_topological_data. - **/ - size_t number_of_vectorize_functions()const - { - return this->number_of_functions_for_vectorization; - } - - //end of implementation of functions needed for concepts. - //end of implementation of functions needed for concepts. - - - - - - - - - - - - - - //For visualization use output from vectorize and build histograms. - std::vector< std::pair< double,double > > output_for_visualization() - { - return this->intervals; - } - -protected: - - void set_up_numbers_of_functions_for_vectorization_and_projections_to_reals() - { - //warning, this function can be only called after filling in the intervals vector. - this->number_of_functions_for_vectorization = this->intervals.size(); - this->number_of_functions_for_projections_to_reals = 1; - } - - std::vector< std::pair< double,double > > intervals; - size_t number_of_functions_for_vectorization; - size_t number_of_functions_for_projections_to_reals; -}; - - -Persistence_intervals::Persistence_intervals( const char* filename , unsigned dimension ) -{ - //bool dbg = false; - //ifstream in; - //in.open( filename ); - - //if ( !in.good() ) - //{ - // throw("File with the persistence diagram do not exist, the program will now terminate.\n"); - //} - - //while ( true ) - //{ - // double first; - // double second; - // in >> first >> second; - - // if ( first > second ) - // { - // double buf = first; - // first = second; - // second = buf; - // } - - // if ( in.eof() )break; - // this->intervals.push_back( std::make_pair( first,second ) ); - // if ( dbg ) - // { - // std::cerr << "Adding interval [ " << first << " , " << second << " ]\n"; - // getchar(); - // } - //} - //in.close(); - if ( dimension == std::numeric_limits::max() ) - { - this->intervals = read_persistence_intervals_in_one_dimension_from_file( filename ); - } - else - { - this->intervals = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); - } - this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); -}//Persistence_intervals - - -Persistence_intervals::Persistence_intervals( const std::vector< std::pair< double , double > >& intervals_ ):intervals(intervals_) -{ - this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); -} - - -std::vector< double > Persistence_intervals::length_of_dominant_intervals( size_t where_to_cut )const -{ - std::vector< double > result( this->intervals.size() ); - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - result[i] = this->intervals[i].second - this->intervals[i].first; - } - std::sort( result.begin() , result.end() , std::greater() ); - - - result.resize( std::min(where_to_cut,result.size()) ); - return result; -}//length_of_dominant_intervals - - - -bool compare( const std::pair< size_t , double >& first , const std::pair< size_t , double >& second ) -{ - return first.second > second.second; -} - - -std::vector< std::pair > Persistence_intervals::dominant_intervals( size_t where_to_cut )const -{ - bool dbg = false; - std::vector< std::pair< size_t , double > > position_length_vector( this->intervals.size() ); - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - position_length_vector[i] = std::make_pair( i , this->intervals[i].second - this->intervals[i].first ); - } - - std::sort( position_length_vector.begin() , position_length_vector.end() , compare ); - - std::vector< std::pair > result; - result.reserve( std::min( where_to_cut , position_length_vector.size() ) ); - - for ( size_t i = 0 ; i != std::min( where_to_cut , position_length_vector.size() ) ; ++i ) - { - result.push_back( this->intervals[ position_length_vector[i].first ] ); - if ( dbg )std::cerr << "Position : " << position_length_vector[i].first << " length : " << position_length_vector[i].second << std::endl; - } - - return result; -}//dominant_intervals - - -std::vector< size_t > Persistence_intervals::histogram_of_lengths( size_t number_of_bins )const -{ - bool dbg = false; - - if ( dbg )std::cerr << "this->intervals.size() : " << this->intervals.size() << std::endl; - //first find the length of the longest interval: - double lengthOfLongest = 0; - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - if ( (this->intervals[i].second - this->intervals[i].first) > lengthOfLongest ) - { - lengthOfLongest = this->intervals[i].second - this->intervals[i].first; - } - } - - if ( dbg ){std::cerr << "lengthOfLongest : " << lengthOfLongest << std::endl;} - - //this is a container we will use to store the resulting histogram - std::vector< size_t > result( number_of_bins + 1 , 0 ); - - //for every persistence interval in our collection. - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - //compute its length relative to the length of the dominant interval: - double relative_length_of_this_interval = (this->intervals[i].second - this->intervals[i].first)/lengthOfLongest; - - //given the relative length (between 0 and 1) compute to which bin should it contribute. - size_t position = (size_t)(relative_length_of_this_interval*number_of_bins); - - - ++result[position]; - - if ( dbg ) - { - std::cerr << "i : " << i << std::endl; - std::cerr << "Interval : [" << this->intervals[i].first << " , " << this->intervals[i].second << " ] \n"; - std::cerr << "relative_length_of_this_interval : " << relative_length_of_this_interval << std::endl; - std::cerr << "position : " << position << std::endl; - getchar(); - } - } - - - if ( dbg ){for ( size_t i = 0 ; i != result.size() ; ++i )std::cerr << result[i] << std::endl;} - return result; -} - - -std::vector< size_t > Persistence_intervals::cumulative_histogram_of_lengths( size_t number_of_bins )const -{ - std::vector< size_t > histogram = this->histogram_of_lengths( number_of_bins ); - std::vector< size_t > result( histogram.size() ); - - size_t sum = 0; - for ( size_t i = 0 ; i != histogram.size() ; ++i ) - { - sum += histogram[i]; - result[i] = sum; - } - return result; -} - - -std::vector< double > Persistence_intervals::characteristic_function_of_diagram( double x_min , double x_max , size_t number_of_bins )const -{ - bool dbg = false; - - std::vector< double > result( number_of_bins ); - std::fill( result.begin() , result.end() , 0 ); - - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - if ( dbg ) - { - std::cerr << "Interval : " << this->intervals[i].first << " , " << this->intervals[i].second << std::endl; - } - - size_t beginIt = 0; - if ( this->intervals[i].first < x_min )beginIt = 0; - if ( this->intervals[i].first >= x_max )beginIt = result.size(); - if ( ( this->intervals[i].first > x_min ) && ( this->intervals[i].first < x_max ) ) - { - beginIt = number_of_bins*(this->intervals[i].first-x_min)/(x_max - x_min); - } - - size_t endIt = 0; - if ( this->intervals[i].second < x_min )endIt = 0; - if ( this->intervals[i].second >= x_max )endIt = result.size(); - if ( ( this->intervals[i].second > x_min ) && ( this->intervals[i].second < x_max ) ) - { - endIt = number_of_bins*( this->intervals[i].second - x_min )/(x_max - x_min); - } - - if ( beginIt > endIt ){beginIt = endIt;} - - if ( dbg ) - { - std::cerr << "beginIt : " << beginIt << std::endl; - std::cerr << "endIt : " << endIt << std::endl; - } - - - for ( size_t pos = beginIt ; pos != endIt ; ++pos ) - { - result[pos] += ( (x_max - x_min)/(double)number_of_bins ) * ( this->intervals[i].second - this->intervals[i].first ); - } - //cerr << "x_max : " << x_max << " x_min : " << x_min << " , number_of_bins : " << number_of_bins << " this->intervals[i].second : " << this->intervals[i].second << " this->intervals[i].first : " << this->intervals[i].first << endl; - if ( dbg ) - { - std::cerr << "Result at this stage \n"; - for ( size_t aa = 0 ; aa != result.size() ; ++aa ) - { - std::cerr << result[aa] << " "; - } - std::cerr << std::endl; - //getchar(); - } - } - return result; -}//characteristic_function_of_diagram - - - -std::vector< double > Persistence_intervals::cumulative_characteristic_function_of_diagram( double x_min , double x_max , size_t number_of_bins )const -{ - std::vector< double > intsOfBars = this->characteristic_function_of_diagram( x_min , x_max , number_of_bins ); - std::vector< double > result( intsOfBars.size() ); - double sum = 0; - for ( size_t i = 0 ; i != intsOfBars.size() ; ++i ) - { - sum += intsOfBars[i]; - result[i] = sum; - } - return result; -}//cumulative_characteristic_function_of_diagram - - -template -bool compare_first_element_of_pair( const std::pair< T , bool >& f, const std::pair< T , bool >& s ) -{ - return (f.first < s.first); -} - - -std::vector< std::pair< double , size_t > > Persistence_intervals::compute_persistent_betti_numbers()const -{ - std::vector< std::pair< double , bool > > places_where_pbs_change( 2*this->intervals.size() ); - - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - places_where_pbs_change[2*i] = std::make_pair( this->intervals[i].first , true ); - places_where_pbs_change[2*i+1] = std::make_pair( this->intervals[i].second , false ); - } - - std::sort( places_where_pbs_change.begin() , places_where_pbs_change.end() , compare_first_element_of_pair ); - size_t pbn = 0; - std::vector< std::pair< double , size_t > > pbns( places_where_pbs_change.size() ); - for ( size_t i = 0 ; i != places_where_pbs_change.size() ; ++i ) - { - if ( places_where_pbs_change[i].second == true ) - { - ++pbn; - } - else - { - --pbn; - } - pbns[i] = std::make_pair( places_where_pbs_change[i].first , pbn ); - } - return pbns; -} - - - - - - -inline double compute_euclidean_distance( const std::pair< double,double > & f , const std::pair< double,double > & s ) -{ - return sqrt( (f.first-s.first)*(f.first-s.first) + (f.second-s.second)*(f.second-s.second) ); -} - - -std::vector< double > Persistence_intervals::k_n_n( size_t k , size_t where_to_cut )const -{ - bool dbg = false; - if ( dbg ) - { - std::cerr << "Here are the intervals : \n"; - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - std::cerr << "[ " << this->intervals[i].first << " , " << this->intervals[i].second << "] \n"; - } - getchar(); - } - - std::vector< double > result; - //compute all to all distance between point in the diagram. Also, consider points in the diagonal with the infinite multiplicity. - std::vector< std::vector< double > > distances( this->intervals.size() ); - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - std::vector aa(this->intervals.size()); - std::fill( aa.begin() , aa.end() , 0 ); - distances[i] = aa; - } - std::vector< double > distances_from_diagonal( this->intervals.size() ); - std::fill( distances_from_diagonal.begin() , distances_from_diagonal.end() , 0 ); - - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - std::vector< double > distancesFromI; - for ( size_t j = i+1 ; j != this->intervals.size() ; ++j ) - { - distancesFromI.push_back( compute_euclidean_distance( this->intervals[i] , this->intervals[j] ) ); - } - //distances.push_back( distancesFromI ); - //also add a distance from this guy to daigonal: - double distanceToDiagonal = compute_euclidean_distance( this->intervals[i] , std::make_pair( 0.5*(this->intervals[i].first + this->intervals[i].second) , 0.5*(this->intervals[i].first + this->intervals[i].second) ) ); - distances_from_diagonal[i] = distanceToDiagonal; - - if ( dbg ) - { - std::cerr << "Here are the distances form the point : [" << this->intervals[i].first << " , " << this->intervals[i].second << "] in the diagram \n"; - for ( size_t aa = 0 ; aa != distancesFromI.size() ; ++aa ) - { - std::cerr << "To : " << i+aa << " : " << distancesFromI[aa] << " "; - } - std::cerr << std::endl; - getchar(); - } - - //filling in the distances matrix: - for ( size_t j = i+1 ; j != this->intervals.size() ; ++j ) - { - distances[i][j] = distancesFromI[j-i-1]; - distances[j][i] = distancesFromI[j-i-1]; - } - } - if ( dbg ) - { - std::cerr << "Here is the distance matrix : \n"; - for ( size_t i = 0 ; i != distances.size() ; ++i ) - { - for ( size_t j = 0 ; j != distances.size() ; ++j ) - { - std::cerr << distances[i][j] << " "; - } - std::cerr << std::endl; - } - std::cerr << std::endl << std::endl << "And here are the distances to the diagonal : " << std::endl; - for ( size_t i = 0 ; i != distances_from_diagonal. size() ; ++i ) - { - std::cerr << distances_from_diagonal[i] << " "; - } - std::cerr << std::endl << std::endl; - getchar(); - } - - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - std::vector< double > distancesFromI = distances[i]; - distancesFromI.push_back( distances_from_diagonal[i] ); - - //sort it: - std::sort( distancesFromI.begin() , distancesFromI.end() , std::greater() ); - - if ( k > distancesFromI.size() ) - { - if ( dbg ) - { - std::cerr << "There are not enough neighbors in your set. We set the result to plus infty \n"; - } - result.push_back( std::numeric_limits::max() ); - } - else - { - if ( distances_from_diagonal[i] > distancesFromI[k] ) - { - if ( dbg ) - { - std::cerr << "The k-th n.n. is on a diagonal. Therefore we set up a distance to diagonal \n"; - } - result.push_back( distances_from_diagonal[i] ); - } - else - { - result.push_back( distancesFromI[k] ); - } - } - } - std::sort( result.begin() , result.end() , std::greater() ); - result.resize( std::min( result.size() , where_to_cut ) ); - - return result; -} - - -double Persistence_intervals::project_to_R( int number_of_function )const -{ - double result = 0; - - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - result += ( this->intervals[i].second - this->intervals[i].first )*( this->intervals[i].second - this->intervals[i].first ); - } - - return result; -} - - -}//namespace gudhi stat -}//namespace gudhi - -#endif diff --git a/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_intervals_with_distances.h b/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_intervals_with_distances.h deleted file mode 100644 index 3c1d8a45..00000000 --- a/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_intervals_with_distances.h +++ /dev/null @@ -1,65 +0,0 @@ -/* This file is part of the Gudhi hiLibrary. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Pawel Dlotko - * - * Copyright (C) 2015 INRIA (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 Persistence_intervals_WITH_DISTANCES_H_ -#define Persistence_intervals_WITH_DISTANCES_H_ - - -#include -#include - -namespace Gudhi -{ -namespace Gudhi_stat -{ - -class Persistence_intervals_with_distances : public Persistence_intervals -{ -public: - using Persistence_intervals::Persistence_intervals; - - /** - *Computations of distance from the current persistnce diagram to the persistence diagram given as a parameter of this function. - *The last but one parameter, power, is here in case we would like to compute p=th Wasserstein distance. At the moment, this method only implement Bottleneck distance, - * which is infinity Wasserstein distance. Therefore any power which is not the default std::numeric_limits< double >::max() will be ignored and an - * exception will be thrown. - * The last parameter, tolerance, it is an additiv error of the approimation, set by default to zero. - **/ - double distance( const Persistence_intervals_with_distances& second , double power = std::numeric_limits< double >::max() , double tolerance = 0) const - { - if ( power >= std::numeric_limits< double >::max() ) - { - return Gudhi::persistence_diagram::bottleneck_distance(this->intervals, second.intervals, tolerance); - } - else - { - std::cerr << "At the moment Gudhi do not support Wasserstein distances. We only support Bottleneck distance." << std::endl; - throw "At the moment Gudhi do not support Wasserstein distances. We only support Bottleneck distance."; - } - } -}; - - -}//namespace gudhi stat -}//namespace gudhi - -#endif diff --git a/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_landscape.h b/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_landscape.h deleted file mode 100644 index e14771b3..00000000 --- a/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_landscape.h +++ /dev/null @@ -1,1503 +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 (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 Persistence_landscapes_H -#define Persistence_landscapes_H - -//standard include -#include -#include -#include -#include -#include -#include -#include - - -//gudhi include -#include -#include - - - - -namespace Gudhi -{ -namespace Gudhi_stat -{ - - - -//predeclaration -class Persistence_landscape; -template < typename operation > -Persistence_landscape operation_on_pair_of_landscapes( const Persistence_landscape& land1 , const Persistence_landscape& land2 ); - - - -/** - * A clas implementing persistence landascpes data structures. For theroretical desciritpion, please consult a paper ''Statistical topological data analysis using persistence landscapes'' by Peter Bubenik. - * For details of algorithms, please consult ''A persistence landscapes toolbox for topological statistics'' by Peter Bubenik and Pawel Dlotko. - * Persistence landscapes allow vertorization, computations of distances, computations of projections to Real, computations of averages and scalar products. Therefore they implement suitable interfaces. - * It implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product - * Note that at the moment, due to roundoff errors during the construction of persistence landscapes, elements which are different by 0.000005 are considered the same. If the scale in your persistence diagrams - * is comparable to this value, please rescale them before use this code. -**/ -class Persistence_landscape -{ -public: - /** - * Default constructor. - **/ - Persistence_landscape() - { - this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); - } - - /** - * Constructor that takes as an input a vector of birth-death pairs. - **/ - Persistence_landscape( const std::vector< std::pair< double , double > >& p ); - - /** - * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed - * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. - **/ - Persistence_landscape(const char* filename , size_t dimension = std::numeric_limits::max() ); - - - - /** - * This procedure loads a landscape from file. It erase all the data that was previously stored in this landscape. - **/ - void load_landscape_from_file( const char* filename ); - - - /** - * The procedure stores a landscape to a file. The file can be later used by a procedure load_landscape_from_file. - **/ - void print_to_file( const char* filename )const; - - - - /** - * This function compute integral of the landscape (defined formally as sum of integrals on R of all landscape functions) - **/ - double compute_integral_of_landscape()const; - - - /** - * This function compute integral of the 'level'-level of a landscape. - **/ - double compute_integral_of_a_level_of_a_landscape( size_t level )const; - - - /** - * This function compute integral of the landscape p-th power of a landscape (defined formally as sum of integrals on R of p-th powers of all landscape functions) - **/ - double compute_integral_of_landscape( double p )const;//this function compute integral of p-th power of landscape. - - - /** - * A function that computes the value of a landscape at a given point. The parameters of the function are: unsigned level and double x. - * The procedure will compute the value of the level-landscape at the point x. - **/ - double compute_value_at_a_given_point( unsigned level , double x )const; - - /** - * Writing landscape into a stream. A i-th level landscape starts with a string "lambda_i". Then the discontinuity points of the landscapes follows. - * Shall those points be joined with lines, we will obtain the i-th landscape function. - **/ - friend std::ostream& operator<<(std::ostream& out, Persistence_landscape& land ); - - template < typename operation > - friend Persistence_landscape operation_on_pair_of_landscapes( const Persistence_landscape& land1 , const Persistence_landscape& land2 ); - - - - - /** - *\private A function that compute sum of two landscapes. - **/ - friend Persistence_landscape add_two_landscapes ( const Persistence_landscape& land1 , const Persistence_landscape& land2 ) - { - return operation_on_pair_of_landscapes< std::plus >(land1,land2); - } - - /** - *\private A function that compute difference of two landscapes. - **/ - friend Persistence_landscape subtract_two_landscapes ( const Persistence_landscape& land1 , const Persistence_landscape& land2 ) - { - return operation_on_pair_of_landscapes< std::minus >(land1,land2); - } - - /** - * An operator +, that compute sum of two landscapes. - **/ - friend Persistence_landscape operator+( const Persistence_landscape& first , const Persistence_landscape& second ) - { - return add_two_landscapes( first,second ); - } - - /** - * An operator -, that compute difference of two landscapes. - **/ - friend Persistence_landscape operator-( const Persistence_landscape& first , const Persistence_landscape& second ) - { - return subtract_two_landscapes( first,second ); - } - - /** - * An operator * that allows multipilication of a landscape by a real number. - **/ - friend Persistence_landscape operator*( const Persistence_landscape& first , double con ) - { - return first.multiply_lanscape_by_real_number_not_overwrite(con); - } - - /** - * An operator * that allows multipilication of a landscape by a real number (order of parameters swapped). - **/ - friend Persistence_landscape operator*( double con , const Persistence_landscape& first ) - { - return first.multiply_lanscape_by_real_number_not_overwrite(con); - } - - /** - * Operator +=. The second parameter is persistence landscape. - **/ - Persistence_landscape operator += ( const Persistence_landscape& rhs ) - { - *this = *this + rhs; - return *this; - } - - /** - * Operator -=. The second parameter is a persistence landscape. - **/ - Persistence_landscape operator -= ( const Persistence_landscape& rhs ) - { - *this = *this - rhs; - return *this; - } - - - /** - * Operator *=. The second parameter is a real number by which the y values of all landscape functions are multiplied. The x-values remain unchanged. - **/ - Persistence_landscape operator *= ( double x ) - { - *this = *this*x; - return *this; - } - - /** - * Operator /=. The second parameter is a real number. - **/ - Persistence_landscape operator /= ( double x ) - { - if ( x == 0 )throw( "In operator /=, division by 0. Program terminated." ); - *this = *this * (1/x); - return *this; - } - - /** - * An operator to compare two persistence landscapes. - **/ - bool operator == ( const Persistence_landscape& rhs )const; - - - /** - * An operator to compare two persistence landscapes. - **/ - bool operator != ( const Persistence_landscape& rhs )const - { - return !((*this) == rhs); - } - - - /** - * Computations of maximum (y) value of landscape. - **/ - double compute_maximum()const - { - double maxValue = 0; - if ( this->land.size() ) - { - maxValue = -std::numeric_limits::max(); - for ( size_t i = 0 ; i != this->land[0].size() ; ++i ) - { - if ( this->land[0][i].second > maxValue )maxValue = this->land[0][i].second; - } - } - return maxValue; - } - - - /** - *\private Computations of minimum (y) value of landscape. - **/ - double compute_minimum()const - { - double minValue = 0; - if ( this->land.size() ) - { - minValue = std::numeric_limits::max(); - for ( size_t i = 0 ; i != this->land[0].size() ; ++i ) - { - if ( this->land[0][i].second < minValue )minValue = this->land[0][i].second; - } - } - return minValue; - } - - /** - *\private Computations of a \f$L^i\f$ norm of landscape, where i is the input parameter. - **/ - double compute_norm_of_landscape( double i ) - { - Persistence_landscape l; - if ( i < std::numeric_limits< double >::max() ) - { - return compute_distance_of_landscapes(*this,l,i); - } - else - { - return compute_max_norm_distance_of_landscapes(*this,l); - } - } - - /** - * An operator to compute the value of a landscape in the level 'level' at the argument 'x'. - **/ - double operator()(unsigned level,double x)const{return this->compute_value_at_a_given_point(level,x);} - - /** - *\private Computations of \f$L^{\infty}\f$ distance between two landscapes. - **/ - friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second ); - //friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , unsigned& nrOfLand , double&x , double& y1, double& y2 ); - - - /** - *\private Computations of \f$L^{p}\f$ distance between two landscapes. p is the parameter of the procedure. - **/ - friend double compute_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , double p ); - - - - /** - * Function to compute absolute value of a PL function. The representation of persistence landscapes allow to store general PL-function. When computing distance betwen two landscapes, we compute difference between - * them. In this case, a general PL-function with negative value can appear as a result. Then in order to compute distance, we need to take its absolute value. This is the purpose of this procedure. - **/ - Persistence_landscape abs(); - - /** - * Computes the number of landscape functions. - **/ - size_t size()const{return this->land.size(); } - - /** - * Computate maximal value of lambda-level landscape. - **/ - double find_max( unsigned lambda )const; - - /** - *\private Function to compute inner (scalar) product of two landscapes. - **/ - friend double compute_inner_product( const Persistence_landscape& l1 , const Persistence_landscape& l2 ); - - - - - - - - - - - - - - - - //Implementations of functions for various concepts. - - /** - * The number of projections to R is defined to the number of nonzero landscape functions. I-th projection is an integral of i-th landscape function over whole R. - * This function is required by the Real_valued_topological_data concept. - **/ - double project_to_R( int number_of_function )const - { - return this->compute_integral_of_a_level_of_a_landscape( (size_t)number_of_function ); - } - - /** - * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. - **/ - size_t number_of_projections_to_R()const - { - return this->number_of_functions_for_projections_to_reals; - } - - /** - * This function produce a vector of doubles based on a landscape. It is required in a concept Vectorized_topological_data - */ - std::vector vectorize( int number_of_function )const - { - //TODO, think of something smarter over here - std::vector v; - if ( (size_t)number_of_function > this->land.size() ) - { - return v; - } - v.reserve( this->land[number_of_function].size() ); - for ( size_t i = 0 ; i != this->land[number_of_function].size() ; ++i ) - { - v.push_back( this->land[number_of_function][i].second ); - } - return v; - } - /** - * This function return the number of functions that allows vectorization of persistence laandscape. It is required in a concept Vectorized_topological_data. - **/ - size_t number_of_vectorize_functions()const - { - return this->number_of_functions_for_vectorization; - } - - /** - * A function to compute averaged persistence landscape, based on vector of persistence landscapes. - * This function is required by Topological_data_with_averages concept. - **/ - void compute_average( const std::vector< Persistence_landscape* >& to_average ) - { - bool dbg = false; - - if ( dbg ){std::cerr << "to_average.size() : " << to_average.size() << std::endl;} - - std::vector< Persistence_landscape* > nextLevelMerge( to_average.size() ); - for ( size_t i = 0 ; i != to_average.size() ; ++i ) - { - nextLevelMerge[i] = to_average[i]; - } - bool is_this_first_level = true;//in the loop, we will create dynamically a unmber of intermediate complexes. We have to clean that up, but we cannot erase the initial andscapes we have - //to average. In this case, we simply check if the nextLevelMerge are the input landscapes or the ones created in that loop by usig this extra variable. - - while ( nextLevelMerge.size() != 1 ) - { - if ( dbg ){std::cerr << "nextLevelMerge.size() : " << nextLevelMerge.size() << std::endl;} - std::vector< Persistence_landscape* > nextNextLevelMerge; - nextNextLevelMerge.reserve( to_average.size() ); - for ( size_t i = 0 ; i < nextLevelMerge.size() ; i=i+2 ) - { - if ( dbg ){std::cerr << "i : " << i << std::endl;} - Persistence_landscape* l = new Persistence_landscape; - if ( i+1 != nextLevelMerge.size() ) - { - (*l) = (*nextLevelMerge[i])+(*nextLevelMerge[i+1]); - } - else - { - (*l) = *nextLevelMerge[i]; - } - nextNextLevelMerge.push_back( l ); - } - if ( dbg ){std::cerr << "After this iteration \n";getchar();} - - if ( !is_this_first_level ) - { - //deallocate the memory if the vector nextLevelMerge do not consist of the initial landscapes - for ( size_t i = 0 ; i != nextLevelMerge.size() ; ++i ) - { - delete nextLevelMerge[i]; - } - } - is_this_first_level = false; - nextLevelMerge.swap(nextNextLevelMerge); - } - (*this) = (*nextLevelMerge[0]); - (*this) *= 1/( (double)to_average.size() ); - } - - - /** - * A function to compute distance between persistence landscape. - * The parameter of this functionis a Persistence_landscape. - * This function is required in Topological_data_with_distances concept. - * For max norm distance, set power to std::numeric_limits::max() - **/ - double distance( const Persistence_landscape& second , double power = 1 )const - { - if ( power < std::numeric_limits::max() ) - { - return compute_distance_of_landscapes( *this , second , power ); - } - else - { - return compute_max_norm_distance_of_landscapes( *this , second ); - } - } - - - /** - * A function to compute scalar product of persistence landscapes. - * The parameter of this functionis a Persistence_landscape. - * This function is required in Topological_data_with_scalar_product concept. - **/ - double compute_scalar_product( const Persistence_landscape& second )const - { - return compute_inner_product( (*this) , second ); - } - //end of implementation of functions needed for concepts. - - - // - // This procedure returns x-range of a given level persistence landscape. If a default value is used, the x-range - //of 0th level landscape is given (and this range contains the ranges of all other landscapes). - // - //std::pair< double , double > get_x_range( size_t level = 0 )const - //{ - // std::pair< double , double > result; - // if ( level < this->land.size() ) - // { - // result = std::make_pair( this->land[level][1].first , this->land[level][ this->land[level].size() - 2 ].first ); - // } - // else - // { - // result = std::make_pair( 0,0 ); - // } - // return result; - //} - - /** - * This procedure returns y-range of a given level persistence landscape. If a default value is used, the y-range - * of 0th level landscape is given (and this range contains the ranges of all other landscapes). - **/ - std::pair< double , double > get_y_range( size_t level = 0 )const - { - std::pair< double , double > result; - if ( level < this->land.size() ) - { - double maxx = this->compute_maximum(); - double minn = this->compute_minimum(); - result = std::make_pair( minn , maxx ); - } - else - { - result = std::make_pair( 0,0 ); - } - return result; - } - - - - //a function used to create a gnuplot script for visualization of landscapes - void plot( const char* filename, double xRangeBegin = std::numeric_limits::max() , double xRangeEnd = std::numeric_limits::max() , - double yRangeBegin = std::numeric_limits::max() , double yRangeEnd = std::numeric_limits::max(), - int from = std::numeric_limits::max(), int to = std::numeric_limits::max() ); - - -protected: - std::vector< std::vector< std::pair > > land; - size_t number_of_functions_for_vectorization; - size_t number_of_functions_for_projections_to_reals; - - void construct_persistence_landscape_from_barcode( const std::vector< std::pair< double , double > > & p ); - Persistence_landscape multiply_lanscape_by_real_number_not_overwrite( double x )const; - void multiply_lanscape_by_real_number_overwrite( double x ); - friend double compute_maximal_distance_non_symmetric( const Persistence_landscape& pl1, const Persistence_landscape& pl2 ); - - void set_up_numbers_of_functions_for_vectorization_and_projections_to_reals() - { - //warning, this function can be only called after filling in the intervals vector. - this->number_of_functions_for_vectorization = this->land.size(); - this->number_of_functions_for_projections_to_reals = this->land.size(); - } -}; - - - - - - - - -Persistence_landscape::Persistence_landscape(const char* filename , size_t dimension) -{ - bool dbg = false; - - if ( dbg ) - { - std::cerr << "Using constructor : Persistence_landscape(char* filename)" << std::endl; - } - std::vector< std::pair< double , double > > barcode; - if ( dimension == std::numeric_limits::max() ) - { - barcode = read_persistence_intervals_in_one_dimension_from_file( filename ); - } - else - { - barcode = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); - } - this->construct_persistence_landscape_from_barcode( barcode ); - this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); -} - - -bool operatorEqualDbg = false; -bool Persistence_landscape::operator == ( const Persistence_landscape& rhs )const -{ - if ( this->land.size() != rhs.land.size() ) - { - if (operatorEqualDbg)std::cerr << "1\n"; - return false; - } - for ( size_t level = 0 ; level != this->land.size() ; ++level ) - { - if ( this->land[level].size() != rhs.land[level].size() ) - { - if (operatorEqualDbg)std::cerr << "this->land[level].size() : " << this->land[level].size() << "\n"; - if (operatorEqualDbg)std::cerr << "rhs.land[level].size() : " << rhs.land[level].size() << "\n"; - if (operatorEqualDbg)std::cerr << "2\n"; - return false; - } - for ( size_t i = 0 ; i != this->land[level].size() ; ++i ) - { - if ( !( almost_equal(this->land[level][i].first , rhs.land[level][i].first) && almost_equal(this->land[level][i].second , rhs.land[level][i].second) ) ) - { - //std::cerr<< this->land[level][i].first << " , " << rhs.land[level][i].first << " and " << this->land[level][i].second << " , " << rhs.land[level][i].second << std::endl; - if (operatorEqualDbg)std::cerr << "this->land[level][i] : " << this->land[level][i].first << " " << this->land[level][i].second << "\n"; - if (operatorEqualDbg)std::cerr << "rhs.land[level][i] : " << rhs.land[level][i].first << " " << rhs.land[level][i].second << "\n"; - if (operatorEqualDbg)std::cerr << "3\n"; - return false; - } - } - } - return true; -} - - - - -Persistence_landscape::Persistence_landscape( const std::vector< std::pair< double , double > > & p ) -{ - this->construct_persistence_landscape_from_barcode( p ); - this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); -} - - -void Persistence_landscape::construct_persistence_landscape_from_barcode( const std::vector< std::pair< double , double > > & p ) -{ - bool dbg = false; - if ( dbg ){std::cerr << "Persistence_landscape::Persistence_landscape( const std::vector< std::pair< double , double > >& p )" << std::endl;} - - //this is a general algorithm to construct persistence landscapes. - std::vector< std::pair > bars; - bars.insert( bars.begin() , p.begin() , p.end() ); - std::sort( bars.begin() , bars.end() , compare_points_sorting ); - - if (dbg) - { - std::cerr << "Bars : \n"; - for ( size_t i = 0 ; i != bars.size() ; ++i ) - { - std::cerr << bars[i].first << " " << bars[i].second << "\n"; - } - getchar(); - } - - std::vector< std::pair > characteristicPoints(p.size()); - for ( size_t i = 0 ; i != bars.size() ; ++i ) - { - characteristicPoints[i] = std::make_pair((bars[i].first+bars[i].second)/2.0 , (bars[i].second - bars[i].first)/2.0); - } - std::vector< std::vector< std::pair > > Persistence_landscape; - while ( !characteristicPoints.empty() ) - { - if(dbg) - { - for ( size_t i = 0 ; i != characteristicPoints.size() ; ++i ) - { - std::cout << "(" << characteristicPoints[i].first << " " << characteristicPoints[i].second << ")\n"; - } - std::cin.ignore(); - } - - std::vector< std::pair > lambda_n; - lambda_n.push_back( std::make_pair( -std::numeric_limits::max() , 0 ) ); - lambda_n.push_back( std::make_pair(minus_length(characteristicPoints[0]),0) ); - lambda_n.push_back( characteristicPoints[0] ); - - if (dbg) - { - std::cerr << "1 Adding to lambda_n : (" << -std::numeric_limits::max() << " " << 0 << ") , (" << minus_length(characteristicPoints[0]) << " " << 0 << ") , (" << characteristicPoints[0].first << " " << characteristicPoints[0].second << ") \n"; - } - - size_t i = 1; - std::vector< std::pair > newCharacteristicPoints; - while ( i < characteristicPoints.size() ) - { - size_t p = 1; - if ( (minus_length(characteristicPoints[i]) >= minus_length(lambda_n[lambda_n.size()-1])) && (birth_plus_deaths(characteristicPoints[i]) > birth_plus_deaths(lambda_n[lambda_n.size()-1])) ) - { - if ( minus_length(characteristicPoints[i]) < birth_plus_deaths(lambda_n[lambda_n.size()-1]) ) - { - std::pair point = std::make_pair( (minus_length(characteristicPoints[i])+birth_plus_deaths(lambda_n[lambda_n.size()-1]))/2 , (birth_plus_deaths(lambda_n[lambda_n.size()-1])-minus_length(characteristicPoints[i]))/2 ); - lambda_n.push_back( point ); - if (dbg) - { - std::cerr << "2 Adding to lambda_n : (" << point.first << " " << point.second << ")\n"; - } - - - if ( dbg ) - { - std::cerr << "characteristicPoints[i+p] : " << characteristicPoints[i+p].first << " " << characteristicPoints[i+p].second << "\n"; - std::cerr << "point : " << point.first << " " << point.second << "\n"; - getchar(); - } - - while ( (i+p < characteristicPoints.size() ) && ( almost_equal(minus_length(point),minus_length(characteristicPoints[i+p])) ) && ( birth_plus_deaths(point) <= birth_plus_deaths(characteristicPoints[i+p]) ) ) - { - newCharacteristicPoints.push_back( characteristicPoints[i+p] ); - if (dbg) - { - std::cerr << "3.5 Adding to newCharacteristicPoints : (" << characteristicPoints[i+p].first << " " << characteristicPoints[i+p].second << ")\n"; - getchar(); - } - ++p; - } - - - newCharacteristicPoints.push_back( point ); - if (dbg) - { - std::cerr << "4 Adding to newCharacteristicPoints : (" << point.first << " " << point.second << ")\n"; - } - - - while ( (i+p < characteristicPoints.size() ) && ( minus_length(point) <= minus_length(characteristicPoints[i+p]) ) && (birth_plus_deaths(point)>=birth_plus_deaths(characteristicPoints[i+p])) ) - { - newCharacteristicPoints.push_back( characteristicPoints[i+p] ); - if (dbg) - { - std::cerr << "characteristicPoints[i+p] : " << characteristicPoints[i+p].first << " " << characteristicPoints[i+p].second << "\n"; - std::cerr << "point : " << point.first << " " << point.second << "\n"; - std::cerr << "characteristicPoints[i+p] birth and death : " << minus_length(characteristicPoints[i+p]) << " , " << birth_plus_deaths(characteristicPoints[i+p]) << "\n"; - std::cerr << "point birth and death : " << minus_length(point) << " , " << birth_plus_deaths(point) << "\n"; - - std::cerr << "3 Adding to newCharacteristicPoints : (" << characteristicPoints[i+p].first << " " << characteristicPoints[i+p].second << ")\n"; - getchar(); - } - ++p; - } - - } - else - { - lambda_n.push_back( std::make_pair( birth_plus_deaths(lambda_n[lambda_n.size()-1]) , 0 ) ); - lambda_n.push_back( std::make_pair( minus_length(characteristicPoints[i]) , 0 ) ); - if (dbg) - { - std::cerr << "5 Adding to lambda_n : (" << birth_plus_deaths(lambda_n[lambda_n.size()-1]) << " " << 0 << ")\n"; - std::cerr << "5 Adding to lambda_n : (" << minus_length(characteristicPoints[i]) << " " << 0 << ")\n"; - } - } - lambda_n.push_back( characteristicPoints[i] ); - if (dbg) - { - std::cerr << "6 Adding to lambda_n : (" << characteristicPoints[i].first << " " << characteristicPoints[i].second << ")\n"; - } - } - else - { - newCharacteristicPoints.push_back( characteristicPoints[i] ); - if (dbg) - { - std::cerr << "7 Adding to newCharacteristicPoints : (" << characteristicPoints[i].first << " " << characteristicPoints[i].second << ")\n"; - } - } - i = i+p; - } - lambda_n.push_back( std::make_pair(birth_plus_deaths(lambda_n[lambda_n.size()-1]),0) ); - lambda_n.push_back( std::make_pair( std::numeric_limits::max() , 0 ) ); - - characteristicPoints = newCharacteristicPoints; - - lambda_n.erase(std::unique(lambda_n.begin(), lambda_n.end()), lambda_n.end()); - this->land.push_back( lambda_n ); - } -} - - - -//this function find maximum of lambda_n -double Persistence_landscape::find_max( unsigned lambda )const -{ - if ( this->land.size() < lambda )return 0; - double maximum = -std::numeric_limits::max(); - for ( size_t i = 0 ; i != this->land[lambda].size() ; ++i ) - { - if ( this->land[lambda][i].second > maximum )maximum = this->land[lambda][i].second; - } - return maximum; -} - - -double Persistence_landscape::compute_integral_of_landscape()const -{ - double result = 0; - for ( size_t i = 0 ; i != this->land.size() ; ++i ) - { - for ( size_t nr = 2 ; nr != this->land[i].size()-1 ; ++nr ) - { - //it suffices to compute every planar integral and then sum them ap for each lambda_n - result += 0.5*( this->land[i][nr].first - this->land[i][nr-1].first )*(this->land[i][nr].second + this->land[i][nr-1].second); - } - } - return result; -} - -double Persistence_landscape::compute_integral_of_a_level_of_a_landscape( size_t level )const -{ - double result = 0; - if ( level >= this->land.size() ) - { - //this landscape function is constantly equal 0, so is the intergral. - return result; - } - //also negative landscapes are assumed to be zero. - if ( level < 0 )return 0; - - for ( size_t nr = 2 ; nr != this->land[ level ].size()-1 ; ++nr ) - { - //it suffices to compute every planar integral and then sum them ap for each lambda_n - result += 0.5*( this->land[ level ][nr].first - this->land[ level ][nr-1].first )*(this->land[ level ][nr].second + this->land[ level ][nr-1].second); - } - - return result; -} - - -double Persistence_landscape::compute_integral_of_landscape( double p )const -{ - bool dbg = false; - double result = 0; - for ( size_t i = 0 ; i != this->land.size() ; ++i ) - { - for ( size_t nr = 2 ; nr != this->land[i].size()-1 ; ++nr ) - { - if (dbg)std::cout << "nr : " << nr << "\n"; - //In this interval, the landscape has a form f(x) = ax+b. We want to compute integral of (ax+b)^p = 1/a * (ax+b)^{p+1}/(p+1) - std::pair coef = compute_parameters_of_a_line( this->land[i][nr] , this->land[i][nr-1] ); - double a = coef.first; - double b = coef.second; - - if (dbg)std::cout << "(" << this->land[i][nr].first << "," << this->land[i][nr].second << ") , " << this->land[i][nr-1].first << "," << this->land[i][nr].second << ")" << std::endl; - if ( this->land[i][nr].first == this->land[i][nr-1].first )continue; - if ( a != 0 ) - { - result += 1/(a*(p+1)) * ( pow((a*this->land[i][nr].first+b),p+1) - pow((a*this->land[i][nr-1].first+b),p+1)); - } - else - { - result += ( this->land[i][nr].first - this->land[i][nr-1].first )*( pow(this->land[i][nr].second,p) ); - } - if ( dbg ) - { - std::cout << "a : " <land. -double Persistence_landscape::compute_value_at_a_given_point( unsigned level , double x )const -{ - bool compute_value_at_a_given_pointDbg = false; - //in such a case lambda_level = 0. - if ( level > this->land.size() ) return 0; - - //we know that the points in this->land[level] are ordered according to x coordinate. Therefore, we can find the point by using bisection: - unsigned coordBegin = 1; - unsigned coordEnd = this->land[level].size()-2; - - if ( compute_value_at_a_given_pointDbg ) - { - std::cerr << "Here \n"; - std::cerr << "x : " << x << "\n"; - std::cerr << "this->land[level][coordBegin].first : " << this->land[level][coordBegin].first << "\n"; - std::cerr << "this->land[level][coordEnd].first : " << this->land[level][coordEnd].first << "\n"; - } - - //in this case x is outside the support of the landscape, therefore the value of the landscape is 0. - if ( x <= this->land[level][coordBegin].first )return 0; - if ( x >= this->land[level][coordEnd].first )return 0; - - if (compute_value_at_a_given_pointDbg)std::cerr << "Entering to the while loop \n"; - - while ( coordBegin+1 != coordEnd ) - { - if (compute_value_at_a_given_pointDbg) - { - std::cerr << "coordBegin : " << coordBegin << "\n"; - std::cerr << "coordEnd : " << coordEnd << "\n"; - std::cerr << "this->land[level][coordBegin].first : " << this->land[level][coordBegin].first << "\n"; - std::cerr << "this->land[level][coordEnd].first : " << this->land[level][coordEnd].first << "\n"; - } - - - unsigned newCord = (unsigned)floor((coordEnd+coordBegin)/2.0); - - if (compute_value_at_a_given_pointDbg) - { - std::cerr << "newCord : " << newCord << "\n"; - std::cerr << "this->land[level][newCord].first : " << this->land[level][newCord].first << "\n"; - std::cin.ignore(); - } - - if ( this->land[level][newCord].first <= x ) - { - coordBegin = newCord; - if ( this->land[level][newCord].first == x )return this->land[level][newCord].second; - } - else - { - coordEnd = newCord; - } - } - - if (compute_value_at_a_given_pointDbg) - { - std::cout << "x : " << x << " is between : " << this->land[level][coordBegin].first << " a " << this->land[level][coordEnd].first << "\n"; - std::cout << "the y coords are : " << this->land[level][coordBegin].second << " a " << this->land[level][coordEnd].second << "\n"; - std::cerr << "coordBegin : " << coordBegin << "\n"; - std::cerr << "coordEnd : " << coordEnd << "\n"; - std::cin.ignore(); - } - return function_value( this->land[level][coordBegin] , this->land[level][coordEnd] , x ); -} - -std::ostream& operator<<(std::ostream& out, Persistence_landscape& land ) -{ - for ( size_t level = 0 ; level != land.land.size() ; ++level ) - { - out << "Lambda_" << level << ":" << std::endl; - for ( size_t i = 0 ; i != land.land[level].size() ; ++i ) - { - if ( land.land[level][i].first == -std::numeric_limits::max() ) - { - out << "-inf"; - } - else - { - if ( land.land[level][i].first == std::numeric_limits::max() ) - { - out << "+inf"; - } - else - { - out << land.land[level][i].first; - } - } - out << " , " << land.land[level][i].second << std::endl; - } - } - return out; -} - - - - -void Persistence_landscape::multiply_lanscape_by_real_number_overwrite( double x ) -{ - for ( size_t dim = 0 ; dim != this->land.size() ; ++dim ) - { - for ( size_t i = 0 ; i != this->land[dim].size() ; ++i ) - { - this->land[dim][i].second *= x; - } - } -} - -bool AbsDbg = false; -Persistence_landscape Persistence_landscape::abs() -{ - Persistence_landscape result; - for ( size_t level = 0 ; level != this->land.size() ; ++level ) - { - if ( AbsDbg ){ std::cout << "level: " << level << std::endl; } - std::vector< std::pair > lambda_n; - lambda_n.push_back( std::make_pair( -std::numeric_limits::max() , 0 ) ); - for ( size_t i = 1 ; i != this->land[level].size() ; ++i ) - { - if ( AbsDbg ){std::cout << "this->land[" << level << "][" << i << "] : " << this->land[level][i].first << " " << this->land[level][i].second << std::endl;} - //if a line segment between this->land[level][i-1] and this->land[level][i] crosses the x-axis, then we have to add one landscape point t oresult - if ( (this->land[level][i-1].second)*(this->land[level][i].second) < 0 ) - { - double zero = find_zero_of_a_line_segment_between_those_two_points( this->land[level][i-1] , this->land[level][i] ); - - lambda_n.push_back( std::make_pair(zero , 0) ); - lambda_n.push_back( std::make_pair(this->land[level][i].first , fabs(this->land[level][i].second)) ); - if ( AbsDbg ) - { - std::cout << "Adding pair : (" << zero << ",0)" << std::endl; - std::cout << "In the same step adding pair : (" << this->land[level][i].first << "," << fabs(this->land[level][i].second) << ") " << std::endl; - std::cin.ignore(); - } - } - else - { - lambda_n.push_back( std::make_pair(this->land[level][i].first , fabs(this->land[level][i].second)) ); - if ( AbsDbg ) - { - std::cout << "Adding pair : (" << this->land[level][i].first << "," << fabs(this->land[level][i].second) << ") " << std::endl; - std::cin.ignore(); - } - } - } - result.land.push_back( lambda_n ); - } - return result; -} - - -Persistence_landscape Persistence_landscape::multiply_lanscape_by_real_number_not_overwrite( double x )const -{ - std::vector< std::vector< std::pair > > result(this->land.size()); - for ( size_t dim = 0 ; dim != this->land.size() ; ++dim ) - { - std::vector< std::pair > lambda_dim( this->land[dim].size() ); - for ( size_t i = 0 ; i != this->land[dim].size() ; ++i ) - { - lambda_dim[i] = std::make_pair( this->land[dim][i].first , x*this->land[dim][i].second ); - } - result[dim] = lambda_dim; - } - Persistence_landscape res; - //CHANGE - //res.land = result; - res.land.swap(result); - return res; -}//multiply_lanscape_by_real_number_overwrite - - -void Persistence_landscape::print_to_file( const char* filename )const -{ - std::ofstream write; - write.open(filename); - for ( size_t dim = 0 ; dim != this->land.size() ; ++dim ) - { - write << "#lambda_" << dim << std::endl; - for ( size_t i = 1 ; i != this->land[dim].size()-1 ; ++i ) - { - write << this->land[dim][i].first << " " << this->land[dim][i].second << std::endl; - } - } - write.close(); -} - -void Persistence_landscape::load_landscape_from_file( const char* filename ) -{ - bool dbg = false; - //removing the current content of the persistence landscape. - this->land.clear(); - - - //this constructor reads persistence landscape form a file. This file have to be created by this software beforehead - std::ifstream in; - in.open( filename ); - if ( !in.good() ) - { - std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; - throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; - } - - std::string line; - std::vector< std::pair > landscapeAtThisLevel; - - bool isThisAFirsLine = true; - while ( !in.eof() ) - { - getline(in,line); - if ( !(line.length() == 0 || line[0] == '#') ) - { - std::stringstream lineSS; - lineSS << line; - double beginn, endd; - lineSS >> beginn; - lineSS >> endd; - landscapeAtThisLevel.push_back( std::make_pair( beginn , endd ) ); - if (dbg){std::cerr << "Reading a pont : " << beginn << " , " << endd << std::endl;} - } - else - { - if (dbg) - { - std::cout << "IGNORE LINE\n"; - getchar(); - } - if ( !isThisAFirsLine ) - { - landscapeAtThisLevel.push_back( std::make_pair( std::numeric_limits::max() , 0 ) ); - this->land.push_back(landscapeAtThisLevel); - std::vector< std::pair > newLevelOdLandscape; - landscapeAtThisLevel.swap(newLevelOdLandscape); - } - landscapeAtThisLevel.push_back( std::make_pair( -std::numeric_limits::max() , 0 ) ); - isThisAFirsLine = false; - } - } - if ( landscapeAtThisLevel.size() > 1 ) - { - //seems that the last line of the file is not finished with the newline sign. We need to put what we have in landscapeAtThisLevel to the constructed landscape. - landscapeAtThisLevel.push_back( std::make_pair( std::numeric_limits::max() , 0 ) ); - this->land.push_back(landscapeAtThisLevel); - } - - in.close(); -} - - -template < typename T > -Persistence_landscape operation_on_pair_of_landscapes ( const Persistence_landscape& land1 , const Persistence_landscape& land2 ) -{ - bool operation_on_pair_of_landscapesDBG = false; - if ( operation_on_pair_of_landscapesDBG ){std::cout << "operation_on_pair_of_landscapes\n";std::cin.ignore();} - Persistence_landscape result; - std::vector< std::vector< std::pair > > land( std::max( land1.land.size() , land2.land.size() ) ); - result.land = land; - T oper; - - if ( operation_on_pair_of_landscapesDBG ) - { - for ( size_t i = 0 ; i != std::min( land1.land.size() , land2.land.size() ) ; ++i ) - { - std::cerr << "land1.land[" << i << "].size() : " << land1.land[i].size() << std::endl; - std::cerr << "land2.land[" << i << "].size() : " << land2.land[i].size() << std::endl; - } - getchar(); - } - - for ( size_t i = 0 ; i != std::min( land1.land.size() , land2.land.size() ) ; ++i ) - { - std::vector< std::pair > lambda_n; - size_t p = 0; - size_t q = 0; - while ( (p+1 < land1.land[i].size()) && (q+1 < land2.land[i].size()) ) - { - if ( operation_on_pair_of_landscapesDBG ) - { - std::cerr << "p : " << p << "\n"; - std::cerr << "q : " << q << "\n"; - std::cerr << "land1.land.size() : " << land1.land.size() << std::endl; - std::cerr << "land2.land.size() : " << land2.land.size() << std::endl; - std::cerr << "land1.land[" << i << "].size() : " << land1.land[i].size() << std::endl; - std::cerr << "land2.land[" << i << "].size() : " << land2.land[i].size() << std::endl; - std::cout << "land1.land[i][p].first : " << land1.land[i][p].first << "\n"; - std::cout << "land2.land[i][q].first : " << land2.land[i][q].first << "\n"; - //getchar(); - } - - if ( land1.land[i][p].first < land2.land[i][q].first ) - { - if ( operation_on_pair_of_landscapesDBG ) - { - std::cout << "first \n"; - std::cout << " function_value(land2.land[i][q-1],land2.land[i][q],land1.land[i][p].first) : "<< function_value(land2.land[i][q-1],land2.land[i][q],land1.land[i][p].first) << "\n"; - //std::cout << "oper( " << land1.land[i][p].second <<"," << function_value(land2.land[i][q-1],land2.land[i][q],land1.land[i][p].first) << " : " << oper( land1.land[i][p].second , function_value(land2.land[i][q-1],land2.land[i][q],land1.land[i][p].first) ) << "\n"; - } - lambda_n.push_back( - std::make_pair( - land1.land[i][p].first , - oper( (double)land1.land[i][p].second , function_value(land2.land[i][q-1],land2.land[i][q],land1.land[i][p].first) ) - ) - ); - ++p; - continue; - } - if ( land1.land[i][p].first > land2.land[i][q].first ) - { - if ( operation_on_pair_of_landscapesDBG ) - { - std::cout << "Second \n"; - std::cout << "function_value("<< land1.land[i][p-1].first << " " << land1.land[i][p-1].second <<" ,"<< land1.land[i][p].first << " " << land1.land[i][p].second <<", " << land2.land[i][q].first<<" ) : " << function_value( land1.land[i][p-1] , land1.land[i][p-1] ,land2.land[i][q].first ) << "\n"; - std::cout << "oper( " << function_value( land1.land[i][p] , land1.land[i][p-1] ,land2.land[i][q].first ) <<"," << land2.land[i][q].second <<" : " << oper( land2.land[i][q].second , function_value( land1.land[i][p] , land1.land[i][p-1] ,land2.land[i][q].first ) ) << "\n"; - } - lambda_n.push_back( std::make_pair( land2.land[i][q].first , oper( function_value( land1.land[i][p] , land1.land[i][p-1] ,land2.land[i][q].first ) , land2.land[i][q].second ) ) ); - ++q; - continue; - } - if ( land1.land[i][p].first == land2.land[i][q].first ) - { - if (operation_on_pair_of_landscapesDBG)std::cout << "Third \n"; - lambda_n.push_back( std::make_pair( land2.land[i][q].first , oper( land1.land[i][p].second , land2.land[i][q].second ) ) ); - ++p;++q; - } - if (operation_on_pair_of_landscapesDBG){std::cout << "Next iteration \n";} - } - while ( (p+1 < land1.land[i].size())&&(q+1 >= land2.land[i].size()) ) - { - if (operation_on_pair_of_landscapesDBG) - { - std::cout << "New point : " << land1.land[i][p].first << " oper(land1.land[i][p].second,0) : " << oper(land1.land[i][p].second,0) << std::endl; - } - lambda_n.push_back( std::make_pair(land1.land[i][p].first , oper(land1.land[i][p].second,0) ) ); - ++p; - } - while ( (p+1 >= land1.land[i].size())&&(q+1 < land2.land[i].size()) ) - { - if (operation_on_pair_of_landscapesDBG) - { - std::cout << "New point : " << land2.land[i][q].first << " oper(0,land2.land[i][q].second) : " << oper(0,land2.land[i][q].second) << std::endl; - } - lambda_n.push_back( std::make_pair(land2.land[i][q].first , oper(0,land2.land[i][q].second) ) ); - ++q; - } - lambda_n.push_back( std::make_pair( std::numeric_limits::max() , 0 ) ); - //CHANGE - //result.land[i] = lambda_n; - result.land[i].swap(lambda_n); - } - if ( land1.land.size() > std::min( land1.land.size() , land2.land.size() ) ) - { - if (operation_on_pair_of_landscapesDBG){std::cout << "land1.land.size() > std::min( land1.land.size() , land2.land.size() )" << std::endl;} - for ( size_t i = std::min( land1.land.size() , land2.land.size() ) ; i != std::max( land1.land.size() , land2.land.size() ) ; ++i ) - { - std::vector< std::pair > lambda_n( land1.land[i] ); - for ( size_t nr = 0 ; nr != land1.land[i].size() ; ++nr ) - { - lambda_n[nr] = std::make_pair( land1.land[i][nr].first , oper( land1.land[i][nr].second , 0 ) ); - } - //CHANGE - //result.land[i] = lambda_n; - result.land[i].swap(lambda_n); - } - } - if ( land2.land.size() > std::min( land1.land.size() , land2.land.size() ) ) - { - if (operation_on_pair_of_landscapesDBG){std::cout << "( land2.land.size() > std::min( land1.land.size() , land2.land.size() ) ) " << std::endl;} - for ( size_t i = std::min( land1.land.size() , land2.land.size() ) ; i != std::max( land1.land.size() , land2.land.size() ) ; ++i ) - { - std::vector< std::pair > lambda_n( land2.land[i] ); - for ( size_t nr = 0 ; nr != land2.land[i].size() ; ++nr ) - { - lambda_n[nr] = std::make_pair( land2.land[i][nr].first , oper( 0 , land2.land[i][nr].second ) ); - } - //CHANGE - //result.land[i] = lambda_n; - result.land[i].swap(lambda_n); - } - } - if ( operation_on_pair_of_landscapesDBG ){std::cout << "operation_on_pair_of_landscapes END\n";std::cin.ignore();} - return result; -}//operation_on_pair_of_landscapes - - - -double compute_maximal_distance_non_symmetric( const Persistence_landscape& pl1, const Persistence_landscape& pl2 ) -{ - bool dbg = false; - if (dbg)std::cerr << " compute_maximal_distance_non_symmetric \n"; - //this distance is not symmetric. It compute ONLY distance between inflection points of pl1 and pl2. - double maxDist = 0; - size_t minimalNumberOfLevels = std::min( pl1.land.size() , pl2.land.size() ); - for ( size_t level = 0 ; level != minimalNumberOfLevels ; ++ level ) - { - if (dbg) - { - std::cerr << "Level : " << level << std::endl; - std::cerr << "PL1 : \n"; - for ( size_t i = 0 ; i != pl1.land[level].size() ; ++i ) - { - std::cerr << "(" <=pl2.land[level][p2Count].first) && (pl1.land[level][i].first<=pl2.land[level][p2Count+1].first) )break; - p2Count++; - } - double val = fabs( function_value( pl2.land[level][p2Count] , pl2.land[level][p2Count+1] , pl1.land[level][i].first ) - pl1.land[level][i].second); - if ( maxDist <= val )maxDist = val; - - if (dbg) - { - std::cerr << pl1.land[level][i].first <<"in [" << pl2.land[level][p2Count].first << "," << pl2.land[level][p2Count+1].first <<"] \n"; - std::cerr << "pl1[level][i].second : " << pl1.land[level][i].second << std::endl; - std::cerr << "function_value( pl2[level][p2Count] , pl2[level][p2Count+1] , pl1[level][i].first ) : " << function_value( pl2.land[level][p2Count] , pl2.land[level][p2Count+1] , pl1.land[level][i].first ) << std::endl; - std::cerr << "val : " << val << std::endl; - std::cin.ignore(); - } - } - } - - if (dbg)std::cerr << "minimalNumberOfLevels : " << minimalNumberOfLevels << std::endl; - - if ( minimalNumberOfLevels < pl1.land.size() ) - { - for ( size_t level = minimalNumberOfLevels ; level != pl1.land.size() ; ++ level ) - { - for ( size_t i = 0 ; i != pl1.land[level].size() ; ++i ) - { - if (dbg)std::cerr << "pl1[level][i].second : " << pl1.land[level][i].second << std::endl; - if ( maxDist < pl1.land[level][i].second )maxDist = pl1.land[level][i].second; - } - } - } - return maxDist; -} - - - - -double compute_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second , double p ) -{ - bool dbg = false; - //This is what we want to compute: (\int_{- \infty}^{+\infty}| first-second |^p)^(1/p). We will do it one step at a time: - - //first-second : - Persistence_landscape lan = first-second; - - //| first-second |: - lan = lan.abs(); - - if ( dbg ){std::cerr << "Abs of difference ; " << lan << std::endl;getchar();} - - if ( p < std::numeric_limits::max() ) - { - //\int_{- \infty}^{+\infty}| first-second |^p - double result; - if ( p != 1 ) - { - if ( dbg )std::cerr << "Power != 1, compute integral to the power p\n"; - result = lan.compute_integral_of_landscape( (double)p ); - } - else - { - if ( dbg )std::cerr << "Power = 1, compute integral \n"; - result = lan.compute_integral_of_landscape(); - } - //(\int_{- \infty}^{+\infty}| first-second |^p)^(1/p) - return pow( result , 1/(double)p ); - } - else - { - //p == infty - if ( dbg )std::cerr << "Power = infty, compute maximum \n"; - return lan.compute_maximum(); - } -} - -double compute_max_norm_distance_of_landscapes( const Persistence_landscape& first, const Persistence_landscape& second ) -{ - return std::max( compute_maximal_distance_non_symmetric(first,second) , compute_maximal_distance_non_symmetric(second,first) ); -} - - -bool comparePairsForMerging( std::pair< double , unsigned > first , std::pair< double , unsigned > second ) -{ - return (first.first < second.first); -} - - - - -double compute_inner_product( const Persistence_landscape& l1 , const Persistence_landscape& l2 ) -{ - bool dbg = false; - double result = 0; - - for ( size_t level = 0 ; level != std::min( l1.size() , l2.size() ) ; ++level ) - { - if ( dbg ){std::cerr << "Computing inner product for a level : " << level << std::endl;getchar();} - if ( l1.land[level].size() * l2.land[level].size() == 0 )continue; - - //endpoints of the interval on which we will compute the inner product of two locally linear functions: - double x1 = -std::numeric_limits::max(); - double x2; - if ( l1.land[level][1].first < l2.land[level][1].first ) - { - x2 = l1.land[level][1].first; - } - else - { - x2 = l2.land[level][1].first; - } - - //iterators for the landscapes l1 and l2 - size_t l1It = 0; - size_t l2It = 0; - - while ( (l1It < l1.land[level].size()-1) && (l2It < l2.land[level].size()-1) ) - { - //compute the value of a inner product on a interval [x1,x2] - - double a,b,c,d; - - if ( l1.land[level][l1It+1].first != l1.land[level][l1It].first ) - { - a = (l1.land[level][l1It+1].second - l1.land[level][l1It].second)/(l1.land[level][l1It+1].first - l1.land[level][l1It].first); - } - else - { - a = 0; - } - b = l1.land[level][l1It].second - a*l1.land[level][l1It].first; - if ( l2.land[level][l2It+1].first != l2.land[level][l2It].first ) - { - c = (l2.land[level][l2It+1].second - l2.land[level][l2It].second)/(l2.land[level][l2It+1].first - l2.land[level][l2It].first); - } - else - { - c = 0; - } - d = l2.land[level][l2It].second - c*l2.land[level][l2It].first; - - double contributionFromThisPart - = - (a*c*x2*x2*x2/3 + (a*d+b*c)*x2*x2/2 + b*d*x2) - (a*c*x1*x1*x1/3 + (a*d+b*c)*x1*x1/2 + b*d*x1); - - result += contributionFromThisPart; - - if ( dbg ) - { - std::cerr << "[l1.land[level][l1It].first,l1.land[level][l1It+1].first] : " << l1.land[level][l1It].first << " , " << l1.land[level][l1It+1].first << std::endl; - std::cerr << "[l2.land[level][l2It].first,l2.land[level][l2It+1].first] : " << l2.land[level][l2It].first << " , " << l2.land[level][l2It+1].first << std::endl; - std::cerr << "a : " << a << ", b : " << b << " , c: " << c << ", d : " << d << std::endl; - std::cerr << "x1 : " << x1 << " , x2 : " << x2 << std::endl; - std::cerr << "contributionFromThisPart : " << contributionFromThisPart << std::endl; - std::cerr << "result : " << result << std::endl; - getchar(); - } - - //we have two intervals in which functions are constant: - //[l1.land[level][l1It].first , l1.land[level][l1It+1].first] - //and - //[l2.land[level][l2It].first , l2.land[level][l2It+1].first] - //We also have an interval [x1,x2]. Since the intervals in the landscapes cover the whole R, then it is clear that x2 - //is either l1.land[level][l1It+1].first of l2.land[level][l2It+1].first or both. Lets test it. - if ( x2 == l1.land[level][l1It+1].first ) - { - if ( x2 == l2.land[level][l2It+1].first ) - { - //in this case, we increment both: - ++l2It; - if ( dbg ){std::cerr << "Incrementing both \n";} - } - else - { - if ( dbg ){std::cerr << "Incrementing first \n";} - } - ++l1It; - } - else - { - //in this case we increment l2It - ++l2It; - if ( dbg ){std::cerr << "Incrementing second \n";} - } - //Now, we shift x1 and x2: - x1 = x2; - if ( l1.land[level][l1It+1].first < l2.land[level][l2It+1].first ) - { - x2 = l1.land[level][l1It+1].first; - } - else - { - x2 = l2.land[level][l2It+1].first; - } - - } - - } - return result; -} - - -void Persistence_landscape::plot( const char* filename, double xRangeBegin , double xRangeEnd , double yRangeBegin , double yRangeEnd , int from , int to ) -{ - //this program create a gnuplot script file that allows to plot persistence diagram. - std::ofstream out; - - std::ostringstream nameSS; - nameSS << filename << "_GnuplotScript"; - std::string nameStr = nameSS.str(); - out.open( nameStr ); - - if ( (xRangeBegin != std::numeric_limits::max()) || (xRangeEnd != std::numeric_limits::max()) || (yRangeBegin != std::numeric_limits::max()) || (yRangeEnd != std::numeric_limits::max()) ) - { - out << "set xrange [" << xRangeBegin << " : " << xRangeEnd << "]" << std::endl; - out << "set yrange [" << yRangeBegin << " : " << yRangeEnd << "]" << std::endl; - } - - if ( from == std::numeric_limits::max() ){from = 0;} - if ( to == std::numeric_limits::max() ){to = this->land.size();} - - out << "plot "; - for ( size_t lambda= std::min((size_t)from,this->land.size()) ; lambda != std::min((size_t)to,this->land.size()) ; ++lambda ) - { - //out << " '-' using 1:2 title 'l" << lambda << "' with lp"; - out << " '-' using 1:2 notitle with lp"; - if ( lambda+1 != std::min((size_t)to,this->land.size()) ) - { - out << ", \\"; - } - out << std::endl; - } - - for ( size_t lambda= std::min((size_t)from,this->land.size()) ; lambda != std::min((size_t)to,this->land.size()) ; ++lambda ) - { - for ( size_t i = 1 ; i != this->land[lambda].size()-1 ; ++i ) - { - out << this->land[lambda][i].first << " " << this->land[lambda][i].second << std::endl; - } - out << "EOF" << std::endl; - } - std::cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << std::endl; -} - - - - -}//namespace gudhi stat -}//namespace gudhi - - -#endif diff --git a/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_landscape_on_grid.h b/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_landscape_on_grid.h deleted file mode 100644 index 2e1fb56d..00000000 --- a/src/Gudhi_stat/include/gudhi/persistence_representations/Persistence_landscape_on_grid.h +++ /dev/null @@ -1,1560 +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 (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 Persistence_landscape_on_grid_H_ -#define Persistence_landscape_on_grid_H_ - - -//standard include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -//gudhi include - -#include -#include - - - -namespace Gudhi -{ -namespace Gudhi_stat -{ - -//predeclaration -class Persistence_landscape_on_grid; -template < typename operation > -Persistence_landscape_on_grid operation_on_pair_of_landscapes_on_grid( const Persistence_landscape_on_grid& land1 , const Persistence_landscape_on_grid& land2 ); - -/** - * A clas implementing persistence landascpes by approximating them on a collection of grid points. * Persistence landscapes on grid allow vertorization, computations of distances, computations - * of projections to Real, computations of averages and scalar products. Therefore they implement suitable interfaces. - * It implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product - * Note that at the moment, due to roundoff errors during the construction of persistence landscapes on a grid, elements which are different by 0.000005 are considered the same. If the scale in your persistence diagrams - * is comparable to this value, please rescale them before use this code. -**/ - -//this class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product -class Persistence_landscape_on_grid -{ -public: - /** - * Default constructor. - **/ - Persistence_landscape_on_grid() - { - this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); - this->grid_min = this->grid_max = 0; - } - - /** - * Constructor that takes as an input a vector of birth-death pairs. - **/ - Persistence_landscape_on_grid( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_ ); - - - /** - * Constructor that takes as an input a vector of birth-death pairs, parameters of the grid and number of landscape function to be created. - **/ - Persistence_landscape_on_grid( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_ , unsigned number_of_levels_of_landscape ); - - /** - * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed - * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. The additional parameters of this procedure are: ranges of grid, resoltion of a grid - * number of landscape functions to be created and the dimension of intervals that are need to be read from a file (in case of Gudhi format files). - **/ - Persistence_landscape_on_grid(const char* filename , double grid_min_, double grid_max_ , size_t number_of_points_ , unsigned number_of_levels_of_landscape , unsigned short dimension_ = std::numeric_limits::max() ); - - /** - * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed - * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. The additional parameters of this procedure are: ranges of grid, resoltion of a grid - * and the dimension of intervals that are need to be read from a file (in case of Gudhi format files). - **/ - Persistence_landscape_on_grid(const char* filename , double grid_min_, double grid_max_ , size_t number_of_points_ , unsigned short dimension_ = std::numeric_limits::max() ); - - - /** - * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed - * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. The additional parameter is the resoution of a grid and the number of landscape - * functions to be created. The remaning parameters are calculated based on data. - **/ - Persistence_landscape_on_grid(const char* filename , size_t number_of_points , unsigned number_of_levels_of_landscape , unsigned short dimension = std::numeric_limits::max() ); - - /** - * Constructor that reads persistence intervals from file and creates persistence landscape. The format of the input file is the following: in each line we put birth-death pair. Last line is assumed - * to be empty. Even if the points within a line are not ordered, they will be ordered while the input is read. The additional parameter is the resoution of a grid. The last parameter is the dimension - * of a persistence to read from the file. If your file contains only persistence pair in a single dimension, please set it up to std::numeric_limits::max(). - * The remaning parameters are calculated based on data. - **/ - Persistence_landscape_on_grid(const char* filename , size_t number_of_points , unsigned short dimension = std::numeric_limits::max() ); - - - /** - * This procedure loads a landscape from file. It erase all the data that was previously stored in this landscape. - **/ - void load_landscape_from_file( const char* filename ); - - - /** - * The procedure stores a landscape to a file. The file can be later used by a procedure load_landscape_from_file. - **/ - void print_to_file( const char* filename )const; - - - - /** - * This function compute integral of the landscape (defined formally as sum of integrals on R of all landscape functions) - **/ - double compute_integral_of_landscape()const - { - size_t maximal_level = this->number_of_nonzero_levels(); - double result = 0; - for ( size_t i = 0 ; i != maximal_level ; ++i ) - { - result += this->compute_integral_of_landscape(i); - } - return result; - } - - - /** - * This function compute integral of the 'level'-level of a landscape. - **/ - double compute_integral_of_landscape( size_t level )const - { - bool dbg = false; - double result = 0; - double dx = (this->grid_max - this->grid_min)/(double)(this->values_of_landscapes.size()-1); - - if ( dbg ) - { - std::cerr << "this->grid_max : " << this->grid_max << std::endl; - std::cerr << "this->grid_min : " << this->grid_min << std::endl; - std::cerr << "this->values_of_landscapes.size() : " << this->values_of_landscapes.size() << std::endl; - getchar(); - } - - - double previous_x = this->grid_min-dx; - double previous_y = 0; - for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) - { - double current_x = previous_x + dx; - double current_y = 0; - if ( this->values_of_landscapes[i].size() > level )current_y = this->values_of_landscapes[i][level]; - - if ( dbg ) - { - std::cerr << "this->values_of_landscapes[i].size() : " << this->values_of_landscapes[i].size() << " , level : " << level << std::endl; - if ( this->values_of_landscapes[i].size() > level )std::cerr << "this->values_of_landscapes[i][level] : " << this->values_of_landscapes[i][level] << std::endl; - std::cerr << "previous_y : " << previous_y << std::endl; - std::cerr << "current_y : " << current_y << std::endl; - std::cerr << "dx : " << dx << std::endl; - std::cerr << "0.5*dx*( previous_y + current_y ); " << 0.5*dx*( previous_y + current_y ) << std::endl; - } - - result += 0.5*dx*( previous_y + current_y ); - previous_x = current_x; - previous_y = current_y; - } - return result; - } - - /** - * This function compute integral of the landscape p-th power of a landscape (defined formally as sum of integrals on R of p-th powers of all landscape functions) - **/ - double compute_integral_of_landscape( double p )const - { - size_t maximal_level = this->number_of_nonzero_levels(); - double result = 0; - for ( size_t i = 0 ; i != maximal_level ; ++i ) - { - result += this->compute_integral_of_landscape(p,i); - } - return result; - } - - /** - * This function compute integral of the landscape p-th power of a level of a landscape (defined formally as sum of integrals on R of p-th powers of all landscape functions) - **/ - double compute_integral_of_landscape( double p , size_t level )const - { - bool dbg = false; - - double result = 0; - double dx = (this->grid_max - this->grid_min)/(double)(this->values_of_landscapes.size()-1); - double previous_x = this->grid_min; - double previous_y = 0; - if ( this->values_of_landscapes[0].size() > level )previous_y = this->values_of_landscapes[0][level]; - - if ( dbg ) - { - std::cerr << "dx : " << dx << std::endl; - std::cerr << "previous_x : " << previous_x << std::endl; - std::cerr << "previous_y : " << previous_y << std::endl; - std::cerr << "power : " << p << std::endl; - getchar(); - } - - for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) - { - double current_x = previous_x + dx; - double current_y = 0; - if ( this->values_of_landscapes[i].size() > level )current_y = this->values_of_landscapes[i][level]; - - if ( dbg )std::cerr << "current_y : " << current_y << std::endl; - - if ( current_y == previous_y )continue; - - std::pair coef = compute_parameters_of_a_line( std::make_pair( previous_x , previous_y ) , std::make_pair( current_x , current_y ) ); - double a = coef.first; - double b = coef.second; - - if ( dbg ) - { - std::cerr << "A line passing through points : (" << previous_x << "," << previous_y << ") and (" << current_x << "," << current_y << ") is : " << a << "x+" << b << std::endl; - } - - //In this interval, the landscape has a form f(x) = ax+b. We want to compute integral of (ax+b)^p = 1/a * (ax+b)^{p+1}/(p+1) - double value_to_add = 0; - if ( a != 0 ) - { - value_to_add = 1/(a*(p+1)) * ( pow((a*current_x+b),p+1) - pow((a*previous_x+b),p+1)); - } - else - { - value_to_add = ( current_x - previous_x )*( pow(b,p) ); - } - result += value_to_add; - if ( dbg ) - { - std::cerr << "Increasing result by : " << value_to_add << std::endl; - std::cerr << "restult : " << result << std::endl; - getchar(); - } - previous_x = current_x; - previous_y = current_y; - } - if ( dbg )std::cerr << "The total result is : " << result << std::endl; - return result; - } - - /** - * Writing landscape into a stream. A i-th level landscape starts with a string "lambda_i". Then the discontinuity points of the landscapes follows. - * Shall those points be joined with lines, we will obtain the i-th landscape function. - **/ - friend std::ostream& operator<<(std::ostream& out, const Persistence_landscape_on_grid& land ) - { - double dx = (land.grid_max - land.grid_min)/(double)(land.values_of_landscapes.size()-1); - double x = land.grid_min; - for ( size_t i = 0 ; i != land.values_of_landscapes.size() ; ++i ) - { - out << x << " : "; - for ( size_t j = 0 ; j != land.values_of_landscapes[i].size() ; ++j ) - { - out << land.values_of_landscapes[i][j] << " "; - } - out << std::endl; - x += dx; - } - return out; - } - - template < typename oper > - friend Persistence_landscape_on_grid operation_on_pair_of_landscapes_on_grid( const Persistence_landscape_on_grid& land1 , const Persistence_landscape_on_grid& land2 ); - - - /** - * A function that computes the value of a landscape at a given point. The parameters of the function are: unsigned level and double x. - * The procedure will compute the value of the level-landscape at the point x. - **/ - double compute_value_at_a_given_point( unsigned level , double x )const - { - bool dbg = false; - if ( (x < this->grid_min) || (x > this->grid_max) )return 0; - - //find a position of a vector closest to x: - double dx = (this->grid_max - this->grid_min)/(double)(this->values_of_landscapes.size()-1); - size_t position = size_t((x-this->grid_min)/dx); - - if ( dbg ) - { - std::cerr << "This is a procedure compute_value_at_a_given_point \n"; - std::cerr << "level : " << level << std::endl; - std::cerr << "x : " << x << std::endl; - std::cerr << "psoition : " << position << std::endl; - } - //check if we are not exacly in the grid point: - if ( almost_equal( position*dx+ this->grid_min , x) ) - { - if ( this->values_of_landscapes[position].size() < level ) - { - return this->values_of_landscapes[position][level]; - } - else - { - return 0; - } - } - //in the other case, approximate with a line: - std::pair line; - if ( (this->values_of_landscapes[position].size() > level) && (this->values_of_landscapes[position+1].size() > level) ) - { - line = compute_parameters_of_a_line( std::make_pair( position*dx+ this->grid_min , this->values_of_landscapes[position][level] ) , std::make_pair( (position+1)*dx+ this->grid_min , this->values_of_landscapes[position+1][level] ) ); - } - else - { - if ( (this->values_of_landscapes[position].size() > level) || (this->values_of_landscapes[position+1].size() > level) ) - { - if ( (this->values_of_landscapes[position].size() > level) ) - { - line = compute_parameters_of_a_line( std::make_pair( position*dx+ this->grid_min , this->values_of_landscapes[position][level] ) , std::make_pair( (position+1)*dx+ this->grid_min , 0 ) ); - } - else - { - //(this->values_of_landscapes[position+1].size() > level) - line = compute_parameters_of_a_line( std::make_pair( position*dx+ this->grid_min , 0 ) , std::make_pair( (position+1)*dx+ this->grid_min , this->values_of_landscapes[position+1][level] ) ); - } - } - else - { - return 0; - } - } - //compute the value of the linear function parametrized by line on a point x: - return line.first*x+line.second; - } - - - public: - /** - *\private A function that compute sum of two landscapes. - **/ - friend Persistence_landscape_on_grid add_two_landscapes ( const Persistence_landscape_on_grid& land1 , const Persistence_landscape_on_grid& land2 ) - { - return operation_on_pair_of_landscapes_on_grid< std::plus >(land1,land2); - } - - /** - *\private A function that compute difference of two landscapes. - **/ - friend Persistence_landscape_on_grid subtract_two_landscapes ( const Persistence_landscape_on_grid& land1 , const Persistence_landscape_on_grid& land2 ) - { - return operation_on_pair_of_landscapes_on_grid< std::minus >(land1,land2); - } - - /** - * An operator +, that compute sum of two landscapes. - **/ - friend Persistence_landscape_on_grid operator+( const Persistence_landscape_on_grid& first , const Persistence_landscape_on_grid& second ) - { - return add_two_landscapes( first,second ); - } - - /** - * An operator -, that compute difference of two landscapes. - **/ - friend Persistence_landscape_on_grid operator-( const Persistence_landscape_on_grid& first , const Persistence_landscape_on_grid& second ) - { - return subtract_two_landscapes( first,second ); - } - - /** - * An operator * that allows multipilication of a landscape by a real number. - **/ - friend Persistence_landscape_on_grid operator*( const Persistence_landscape_on_grid& first , double con ) - { - return first.multiply_lanscape_by_real_number_not_overwrite(con); - } - - /** - * An operator * that allows multipilication of a landscape by a real number (order of parameters swapped). - **/ - friend Persistence_landscape_on_grid operator*( double con , const Persistence_landscape_on_grid& first ) - { - return first.multiply_lanscape_by_real_number_not_overwrite(con); - } - - friend bool check_if_defined_on_the_same_domain( const Persistence_landscape_on_grid& land1, const Persistence_landscape_on_grid& land2 ) - { - if ( land1.values_of_landscapes.size() != land2.values_of_landscapes.size() )return false; - if ( land1.grid_min != land2.grid_min )return false; - if ( land1.grid_max != land2.grid_max )return false; - return true; - } - - /** - * Operator +=. The second parameter is persistnece landwscape. - **/ - Persistence_landscape_on_grid operator += ( const Persistence_landscape_on_grid& rhs ) - { - *this = *this + rhs; - return *this; - } - - /** - * Operator -=. The second parameter is persistnece landwscape. - **/ - Persistence_landscape_on_grid operator -= ( const Persistence_landscape_on_grid& rhs ) - { - *this = *this - rhs; - return *this; - } - - - /** - * Operator *=. The second parameter is a real number by which the y values of all landscape functions are multiplied. The x-values remain unchanged. - **/ - Persistence_landscape_on_grid operator *= ( double x ) - { - *this = *this*x; - return *this; - } - - /** - * Operator /=. The second parameter is a real number. - **/ - Persistence_landscape_on_grid operator /= ( double x ) - { - if ( x == 0 )throw( "In operator /=, division by 0. Program terminated." ); - *this = *this * (1/x); - return *this; - } - - /** - * An operator to compare two persistence landscapes. - **/ - bool operator == ( const Persistence_landscape_on_grid& rhs )const - { - bool dbg = true; - if ( this->values_of_landscapes.size() != rhs.values_of_landscapes.size() ) - { - if (dbg) std::cerr << "values_of_landscapes of incompatable sizes\n"; - return false; - } - if ( !almost_equal( this->grid_min , rhs.grid_min ) ) - { - if (dbg) std::cerr << "grid_min not equal\n"; - return false; - } - if ( !almost_equal(this->grid_max,rhs.grid_max ) ) - { - if (dbg) std::cerr << "grid_max not equal\n"; - return false; - } - for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) - { - for ( size_t aa = 0 ; aa != this->values_of_landscapes[i].size() ; ++aa ) - { - if ( !almost_equal( this->values_of_landscapes[i][aa] , rhs.values_of_landscapes[i][aa] ) ) - { - if (dbg) - { - std::cerr << "Problem in the position : " << i << " of values_of_landscapes. \n"; - std::cerr << this->values_of_landscapes[i][aa] << " " << rhs.values_of_landscapes[i][aa] << std::endl; - } - return false; - } - } - } - return true; - } - - - /** - * An operator to compare two persistence landscapes. - **/ - bool operator != ( const Persistence_landscape_on_grid& rhs )const - { - return !((*this) == rhs); - } - - - /** - * Computations of maximum (y) value of landscape. - **/ - double compute_maximum()const - { - //since the function can only be entirely positive or negative, the maximal value will be an extremal value in the arrays: - double max_value = -std::numeric_limits::max(); - for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) - { - if ( this->values_of_landscapes[i].size() ) - { - if ( this->values_of_landscapes[i][0] > max_value )max_value = this->values_of_landscapes[i][0]; - if ( this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ] > max_value )max_value = this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ]; - } - } - return max_value; - } - - /** - * Computations of minimum and maximum value of landscape. - **/ - std::pair compute_minimum_maximum()const - { - //since the function can only be entirely positive or negative, the maximal value will be an extremal value in the arrays: - double max_value = -std::numeric_limits::max(); - double min_value = 0; - for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) - { - if ( this->values_of_landscapes[i].size() ) - { - if ( this->values_of_landscapes[i][0] > max_value )max_value = this->values_of_landscapes[i][0]; - if ( this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ] > max_value )max_value = this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ]; - - if ( this->values_of_landscapes[i][0] < min_value )min_value = this->values_of_landscapes[i][0]; - if ( this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ] < min_value )min_value = this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ]; - } - } - return std::make_pair(min_value , max_value); - } - - /** - * This procedure returns x-range of a given level persistence landscape. If a default value is used, the x-range - * of 0th level landscape is given (and this range contains the ranges of all other landscapes). - **/ - std::pair< double , double > get_x_range( size_t level = 0 )const - { - return std::make_pair( this->grid_min , this->grid_max ); - //std::pair< double , double > result; - //if ( level < this->land.size() ) - //{ - // double dx = (this->grid_max - this->grid_min)/(double)this->values_of_landscapes.size(); - // size_t first_nonzero = 0; - // while ( (first_nonzero != this->values_of_landscapes.size()) && (this->values_of_landscapes[level][first_nonzero] == 0) )++first_nonzero; - // - // if ( first_nonzero == 0 ) - // { - // return std::make_pair( 0,0 );//this landscape is empty. - // } - // - // size_t last_nonzero = 0; - // while ( (last_nonzero != 0) && (this->values_of_landscapes[level][last_nonzero] == 0) )--last_nonzero; - // - // result = std::make_pair( this->grid_min +first_nonzero*dx , this->grid_max - last_nonzero*dx ); - //} - //else - //{ - // result = std::make_pair( 0,0 ); - //} - //return result; - } - - /** - * This procedure returns y-range of a persistence landscape. If a default value is used, the y-range - * of 0th level landscape is given (and this range contains the ranges of all other landscapes). - **/ - std::pair< double , double > get_y_range( size_t level = 0 )const - { - return this->compute_minimum_maximum(); - //std::pair< double , double > result; - //if ( level < this->land.size() ) - //{ - // result = this->compute_minimum_maximum() - //} - //else - //{ - // result = std::make_pair( 0,0 ); - //} - //return result; - } - - /** - * This function computes maximal lambda for which lambda-level landscape is nonzero. - **/ - size_t number_of_nonzero_levels()const - { - size_t result = 0; - for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) - { - if ( this->values_of_landscapes[i].size() > result )result = this->values_of_landscapes[i].size(); - } - return result; - } - - /** - * Computations of a \f$L^i\f$ norm of landscape, where i is the input parameter. - **/ - double compute_norm_of_landscape( double i )const - { - std::vector< std::pair< double , double > > p; - Persistence_landscape_on_grid l(p,this->grid_min,this->grid_max,this->values_of_landscapes.size()-1); - - if ( i < std::numeric_limits::max() ) - { - return compute_distance_of_landscapes_on_grid(*this,l,i); - } - else - { - return compute_max_norm_distance_of_landscapes(*this,l); - } - } - - /** - * An operator to compute the value of a landscape in the level 'level' at the argument 'x'. - **/ - double operator()(unsigned level,double x)const{return this->compute_value_at_a_given_point(level,x);} - - /** - * Computations of \f$L^{\infty}\f$ distance between two landscapes. - **/ - friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second ); - //friend double compute_max_norm_distance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second , unsigned& nrOfLand , double&x , double& y1, double& y2 ); - - - - - /** - * Function to compute absolute value of a PL function. The representation of persistence landscapes allow to store general PL-function. When computing distance betwen two landscapes, we compute difference between - * them. In this case, a general PL-function with negative value can appear as a result. Then in order to compute distance, we need to take its absolute value. This is the purpose of this procedure. - **/ - void abs() - { - for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) - { - for ( size_t j = 0 ; j != this->values_of_landscapes[i].size() ; ++j ) - { - this->values_of_landscapes[i][j] = std::abs( this->values_of_landscapes[i][j] ); - } - } - } - - /** - * Computes the number of landscape functions. - **/ - size_t size()const{return this->number_of_nonzero_levels(); } - - /** - * Computate maximal value of lambda-level landscape. - **/ - double find_max( unsigned lambda )const - { - double max_value = -std::numeric_limits::max(); - for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) - { - if ( this->values_of_landscapes[i].size() > lambda ) - { - if ( this->values_of_landscapes[i][lambda] > max_value )max_value = this->values_of_landscapes[i][lambda]; - } - } - return max_value; - } - - /** - * Function to compute inner (scalar) product of two landscapes. - **/ - friend double compute_inner_product( const Persistence_landscape_on_grid& l1 , const Persistence_landscape_on_grid& l2 ) - { - if ( !check_if_defined_on_the_same_domain(l1,l2) )throw "Landscapes are not defined on the same grid, the program will now terminate"; - size_t maximal_level = l1.number_of_nonzero_levels(); - double result = 0; - for ( size_t i = 0 ; i != maximal_level ; ++i ) - { - result += compute_inner_product(l1,l2,i); - } - return result; - } - - - - /** - * Function to compute inner (scalar) product of given levels of two landscapes. - **/ - friend double compute_inner_product( const Persistence_landscape_on_grid& l1 , const Persistence_landscape_on_grid& l2 , size_t level ) - { - bool dbg = false; - - if ( !check_if_defined_on_the_same_domain(l1,l2) )throw "Landscapes are not defined on the same grid, the program will now terminate"; - double result = 0; - - double dx = (l1.grid_max - l1.grid_min)/(double)(l1.values_of_landscapes.size()-1); - - double previous_x = l1.grid_min-dx; - double previous_y_l1 = 0; - double previous_y_l2 = 0; - for ( size_t i = 0 ; i != l1.values_of_landscapes.size() ; ++i ) - { - if ( dbg )std::cerr << "i : " << i << std::endl; - - double current_x = previous_x + dx; - double current_y_l1 = 0; - if ( l1.values_of_landscapes[i].size() > level )current_y_l1 = l1.values_of_landscapes[i][level]; - - double current_y_l2 = 0; - if ( l2.values_of_landscapes[i].size() > level )current_y_l2 = l2.values_of_landscapes[i][level]; - - if ( dbg ) - { - std::cerr << "previous_x : " << previous_x << std::endl; - std::cerr << "previous_y_l1 : " << previous_y_l1 << std::endl; - std::cerr << "current_y_l1 : " << current_y_l1 << std::endl; - std::cerr << "previous_y_l2 : " << previous_y_l2 << std::endl; - std::cerr << "current_y_l2 : " << current_y_l2 << std::endl; - } - - std::pair l1_coords = compute_parameters_of_a_line( std::make_pair( previous_x , previous_y_l1 ) , std::make_pair( current_x , current_y_l1 ) ); - std::pair l2_coords = compute_parameters_of_a_line( std::make_pair( previous_x , previous_y_l2 ) , std::make_pair( current_x , current_y_l2 ) ); - - //let us assume that the first line is of a form y = ax+b, and the second one is of a form y = cx + d. Then here are a,b,c,d: - double a = l1_coords.first; - double b = l1_coords.second; - - double c = l2_coords.first; - double d = l2_coords.second; - - if ( dbg ) - { - std::cerr << "Here are the formulas for a line: \n"; - std::cerr << "a : " << a << std::endl; - std::cerr << "b : " << b << std::endl; - std::cerr << "c : " << c << std::endl; - std::cerr << "d : " << d << std::endl; - } - - //now, to compute the inner product in this interval we need to compute the integral of (ax+b)(cx+d) = acx^2 + (ad+bc)x + bd in the interval from previous_x to current_x: - //The integal is ac/3*x^3 + (ac+bd)/2*x^2 + bd*x - - double added_value = (a*c/3*current_x*current_x*current_x + (a*d+b*c)/2*current_x*current_x + b*d*current_x)- - (a*c/3*previous_x*previous_x*previous_x + (a*d+b*c)/2*previous_x*previous_x + b*d*previous_x); - - if ( dbg ) - { - std::cerr << "Value of the integral on the left end ie : " << previous_x << " is : " << a*c/3*previous_x*previous_x*previous_x + (a*d+b*c)/2*previous_x*previous_x + b*d*previous_x << std::endl; - std::cerr << "Value of the integral on the right end i.e. : " << current_x << " is " << a*c/3*current_x*current_x*current_x + (a*d+b*c)/2*current_x*current_x + b*d*current_x << std::endl; - } - - result += added_value; - - if ( dbg ) - { - std::cerr << "added_value : " << added_value << std::endl; - std::cerr << "result : " << result << std::endl; - getchar(); - } - - - previous_x = current_x; - previous_y_l1 = current_y_l1; - previous_y_l2 = current_y_l2; - - } - return result; - } - - - /** - * Computations of \f$L^{p}\f$ distance between two landscapes on a grid. p is the parameter of the procedure. - * FIXME: Note that, due to the grid representation, the method below may give non--accurate results in case when the landscape P and Q the difference of which we want to compute - * are interxsecting. This is a consequence of a general way they are computed. In the future, an integral of absolute value of a difference of P and Q will be given as a separated - * function to fix that inaccuracy. - **/ - friend double compute_distance_of_landscapes_on_grid( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second , double p ) - { - bool dbg = false; - //This is what we want to compute: (\int_{- \infty}^{+\infty}| first-second |^p)^(1/p). We will do it one step at a time: - - if ( dbg ) - { - std::cerr << "first : " << first << std::endl; - std::cerr << "second : " << second << std::endl; - getchar(); - } - - //first-second : - Persistence_landscape_on_grid lan = first-second; - - if ( dbg ) - { - std::cerr << "Difference : " << lan << std::endl; - } - - //| first-second |: - lan.abs(); - - if ( dbg ) - { - std::cerr << "Abs : " << lan << std::endl; - } - - if ( p < std::numeric_limits< double >::max() ) - { - //\int_{- \infty}^{+\infty}| first-second |^p - double result; - if ( p != 1 ) - { - if (dbg){std::cerr << "p : " << p << std::endl; getchar();} - result = lan.compute_integral_of_landscape( (double)p ); - if (dbg){std::cerr << "integral : " << result << std::endl;getchar();} - } - else - { - result = lan.compute_integral_of_landscape(); - if (dbg){std::cerr << "integral, wihtout power : " << result << std::endl;getchar();} - } - //(\int_{- \infty}^{+\infty}| first-second |^p)^(1/p) - return pow( result , 1/(double)p ); - } - else - { - //p == infty - return lan.compute_maximum(); - } - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //Functions that are needed for that class to implement the concept. - - /** - * The number of projections to R is defined to the number of nonzero landscape functions. I-th projection is an integral of i-th landscape function over whole R. - * This function is required by the Real_valued_topological_data concept. - **/ - double project_to_R( int number_of_function )const - { - return this->compute_integral_of_landscape( (size_t)number_of_function ); - } - - /** - * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. - **/ - size_t number_of_projections_to_R()const - { - return number_of_functions_for_projections_to_reals; - } - - - - - /** - * This function produce a vector of doubles based on a landscape. It is required in a concept Vectorized_topological_data - */ - std::vector vectorize( int number_of_function )const - { - //TODO, think of something smarter over here - if ( ( number_of_function < 0 ) || ( (size_t)number_of_function >= this->values_of_landscapes.size() ) ) - { - throw "Wrong number of function\n"; - } - std::vector v( this->values_of_landscapes.size() ); - for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) - { - v[i] = 0; - if ( this->values_of_landscapes[i].size() > (size_t)number_of_function ) - { - v[ i ] = this->values_of_landscapes[i][number_of_function]; - } - } - return v; - } - - /** - * This function return the number of functions that allows vectorization of persistence laandscape. It is required in a concept Vectorized_topological_data. - **/ - size_t number_of_vectorize_functions()const - { - return number_of_functions_for_vectorization; - } - - - - - - /** - * A function to compute averaged persistence landscape on a grid, based on vector of persistence landscapes on grid. - * This function is required by Topological_data_with_averages concept. - **/ - void compute_average( const std::vector< Persistence_landscape_on_grid* >& to_average ) - { - - bool dbg = false; - //After execution of this procedure, the average is supposed to be in the current object. To make sure that this is the case, we need to do some cleaning first. - this->values_of_landscapes .clear(); - this->grid_min = this->grid_max = 0; - - //if there is nothing to averate, then the average is a zero landscape. - if ( to_average.size() == 0 )return; - - //now we need to check if the grids in all objects of to_average are the same: - for ( size_t i = 0 ; i != to_average.size() ; ++i ) - { - if ( !check_if_defined_on_the_same_domain(*(to_average[0]),*(to_average[i])) )throw "Two grids are not compatible"; - } - - this->values_of_landscapes = std::vector< std::vector >( (to_average[0])->values_of_landscapes.size() ); - this->grid_min = (to_average[0])->grid_min; - this->grid_max = (to_average[0])->grid_max; - - if ( dbg ) - { - std::cerr << "Computations of average. The data from the current landscape have been cleared. We are ready to do the computations. \n"; - } - - //for every point in the grid: - for ( size_t grid_point = 0 ; grid_point != (to_average[0])->values_of_landscapes.size() ; ++grid_point ) - { - - //set up a vector of the correct size: - size_t maximal_size_of_vector = 0; - for ( size_t land_no = 0 ; land_no != to_average.size() ; ++land_no ) - { - if ( (to_average[land_no])->values_of_landscapes[grid_point].size() > maximal_size_of_vector ) - maximal_size_of_vector = (to_average[land_no])->values_of_landscapes[grid_point].size(); - } - this->values_of_landscapes[grid_point] = std::vector( maximal_size_of_vector ); - - if ( dbg ) - { - std::cerr << "We are considering the point : " << grid_point << " of the grid. In this point, there are at most : " << maximal_size_of_vector << " nonzero landscape functions \n"; - } - - //and compute an arythmetic average: - for ( size_t land_no = 0 ; land_no != to_average.size() ; ++land_no ) - { - //summing: - for ( size_t i = 0 ; i != (to_average[land_no])->values_of_landscapes[grid_point].size() ; ++i ) - { - //compute the average in a smarter way. - this->values_of_landscapes[grid_point][i] += (to_average[land_no])->values_of_landscapes[grid_point][i]; - } - } - //normalizing: - for ( size_t i = 0 ; i != this->values_of_landscapes[grid_point].size() ; ++i ) - { - this->values_of_landscapes[grid_point][i] /= (double)to_average.size(); - } - } - }//compute_average - - - /** - * A function to compute distance between persistence landscape on a grid. - * The parameter of this functionis a Persistence_landscape_on_grid. - * This function is required in Topological_data_with_distances concept. - * For max norm distance, set power to std::numeric_limits::max() - **/ - double distance( const Persistence_landscape_on_grid& second , double power = 1 )const - { - if ( power < std::numeric_limits::max() ) - { - return compute_distance_of_landscapes_on_grid( *this , second , power ); - } - else - { - return compute_max_norm_distance_of_landscapes( *this , second ); - } - } - - /** - * A function to compute scalar product of persistence landscape on a grid. - * The parameter of this functionis a Persistence_landscape_on_grid. - * This function is required in Topological_data_with_scalar_product concept. - **/ - double compute_scalar_product( const Persistence_landscape_on_grid& second ) - { - return compute_inner_product( (*this) , second ); - } - - //end of implementation of functions needed for concepts. - - - - - - - - - - - - - - - - - - - - - /** - * A function that returns values of landsapes. It can be used for vizualization - **/ - std::vector< std::vector< double > > output_for_visualization()const - { - return this->values_of_landscapes; - } - - /** - * function used to create a gnuplot script for visualization of landscapes. Over here we need to specify which landscapes do we want to plot. - * In addition, the user may specify the range (min and max) where landscape is plot. The fefault values for min and max are std::numeric_limits::max(). If the procedure detect those - * values, it will determine the range so that the whole landscape is supported there. If at least one min or max value is different from std::numeric_limits::max(), then the values - * provided by the user will be used. - **/ - void plot( const char* filename , size_t from_ , size_t to_ )const - { - this->plot( filename , std::numeric_limits::max() , std::numeric_limits::max(), std::numeric_limits::max() , std::numeric_limits::max() , from_ , to_ ); - } - - /** - * function used to create a gnuplot script for visualization of landscapes. Over here we can restrict also x and y range of the landscape. - **/ - void plot( const char* filename, double min_x = std::numeric_limits::max() , double max_x = std::numeric_limits::max() , double min_y = std::numeric_limits::max() , double max_y = std::numeric_limits::max() , size_t from_ = std::numeric_limits::max(), size_t to_= std::numeric_limits::max() )const; - - -protected: - double grid_min; - double grid_max; - std::vector< std::vector< double > > values_of_landscapes; - size_t number_of_functions_for_vectorization; - size_t number_of_functions_for_projections_to_reals; - - void set_up_numbers_of_functions_for_vectorization_and_projections_to_reals() - { - //warning, this function can be only called after filling in the values_of_landscapes vector. - this->number_of_functions_for_vectorization = this->values_of_landscapes.size(); - this->number_of_functions_for_projections_to_reals = this->values_of_landscapes.size(); - } - void set_up_values_of_landscapes( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_ , unsigned number_of_levels = std::numeric_limits::max() ); - Persistence_landscape_on_grid multiply_lanscape_by_real_number_not_overwrite( double x )const; -}; - - -void Persistence_landscape_on_grid::set_up_values_of_landscapes( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_, unsigned number_of_levels ) -{ - bool dbg = false; - if ( dbg ) - { - std::cerr << "Here is the procedure : set_up_values_of_landscapes. The parameters are : grid_min_ : " << grid_min_ << ", grid_max_ : " << grid_max_ << ", number_of_points_ : " << number_of_points_ << ", number_of_levels: " << number_of_levels << std::endl; - std::cerr << "Here are the intervals at our disposal : \n"; - for ( size_t i = 0 ; i != p.size() ; ++i ) - { - std::cerr << p[i].first << " , " << p[i].second << std::endl; - } - } - - if ( (grid_min_ == std::numeric_limits::max()) || (grid_max_ == std::numeric_limits::max()) ) - { - //in this case, we need to find grid_min_ and grid_min_ based on the data. - double min = std::numeric_limits::max(); - double max = std::numeric_limits::min(); - for ( size_t i = 0 ; i != p.size() ; ++i ) - { - if ( p[i].first < min )min = p[i].first; - if ( p[i].second > max )max = p[i].second; - } - if ( grid_min_ == std::numeric_limits::max() ) - { - grid_min_ = min; - } - else - { - //in this case grid_max_ == std::numeric_limits::max() - grid_max_ = max; - } - } - - //if number_of_levels == std::numeric_limits::max(), then we will have all the nonzero values of landscapes, and will store them in a vector - //if number_of_levels != std::numeric_limits::max(), then we will use those vectors as heaps. - this->values_of_landscapes = std::vector< std::vector< double > >( number_of_points_+1 ); - - - this->grid_min = grid_min_; - this->grid_max = grid_max_; - - if ( grid_max_ <= grid_min_ ) - { - throw "Wrong parameters of grid_min and grid_max given to the procedure. THe grid have negative, or zero size. The program will now terminate.\n"; - } - - double dx = ( grid_max_ - grid_min_ )/(double)(number_of_points_); - //for every interval in the diagram: - for ( size_t int_no = 0 ; int_no != p.size() ; ++int_no ) - { - size_t grid_interval_begin = (p[int_no].first-grid_min_)/dx; - size_t grid_interval_end = (p[int_no].second-grid_min_)/dx; - size_t grid_interval_midpoint = (size_t)(0.5*(grid_interval_begin+grid_interval_end)); - - if ( dbg ) - { - std::cerr << "Considering an interval : " << p[int_no].first << "," << p[int_no].second << std::endl; - - std::cerr << "grid_interval_begin : " << grid_interval_begin << std::endl; - std::cerr << "grid_interval_end : " << grid_interval_end << std::endl; - std::cerr << "grid_interval_midpoint : " << grid_interval_midpoint << std::endl; - } - - double landscape_value = dx; - for ( size_t i = grid_interval_begin+1 ; i < grid_interval_midpoint ; ++i ) - { - if ( dbg ) - { - std::cerr << "Adding landscape value (going up) for a point : " << i << " equal : " << landscape_value << std::endl; - } - if ( number_of_levels != std::numeric_limits::max() ) - { - //we have a heap of no more that number_of_levels values. - //Note that if we are using heaps, we want to know the shortest distance in the heap. - //This is achieved by putting -distance to the heap. - if ( this->values_of_landscapes[i].size() >= number_of_levels ) - { - //in this case, the full heap is build, and we need to check if the landscape_value is not larger than the smallest element in the heap. - if ( -landscape_value < this->values_of_landscapes[i].front() ) - { - //if it is, we remove the largest value in the heap, and move on. - std::pop_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); - this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ] = -landscape_value; - std::push_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); - } - } - else - { - - //in this case we are still filling in the array. - this->values_of_landscapes[i].push_back( -landscape_value ); - if ( this->values_of_landscapes[i].size() == number_of_levels-1 ) - { - //this->values_of_landscapes[i].size() == number_of_levels - //in this case we need to create the heep. - std::make_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); - } - } - } - else - { - //we have vector of all values - this->values_of_landscapes[i].push_back( landscape_value ); - } - landscape_value += dx; - } - for ( size_t i = grid_interval_midpoint ; i <= grid_interval_end ; ++i ) - { - if ( landscape_value > 0 ) - { - if ( number_of_levels != std::numeric_limits< unsigned >::max() ) - { - //we have a heap of no more that number_of_levels values - if ( this->values_of_landscapes[i].size() >= number_of_levels ) - { - //in this case, the full heap is build, and we need to check if the landscape_value is not larger than the smallest element in the heap. - if ( -landscape_value < this->values_of_landscapes[i].front() ) - { - //if it is, we remove the largest value in the heap, and move on. - std::pop_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); - this->values_of_landscapes[i][ this->values_of_landscapes[i].size()-1 ] = -landscape_value; - std::push_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); - } - } - else - { - - //in this case we are still filling in the array. - this->values_of_landscapes[i].push_back( -landscape_value ); - if ( this->values_of_landscapes[i].size() == number_of_levels-1 ) - { - //this->values_of_landscapes[i].size() == number_of_levels - //in this case we need to create the heep. - std::make_heap (this->values_of_landscapes[i].begin(),this->values_of_landscapes[i].end()); - } - } - } - else - { - this->values_of_landscapes[i].push_back( landscape_value ); - } - - - if ( dbg ) - { - std::cerr << "AAdding landscape value (going down) for a point : " << i << " equal : " << landscape_value << std::endl; - } - } - landscape_value -= dx; - } - } - - if ( number_of_levels != std::numeric_limits< unsigned >::max() ) - { - //in this case, vectors are used as heaps. And, since we want to have the smallest element at the top of - //each heap, we store mminus distances. To get if right at the end, we need to multiply each value - //in the heap by -1 to get real vector of distances. - for ( size_t pt = 0 ; pt != this->values_of_landscapes.size() ; ++pt ) - { - //std::cerr << this->values_of_landscapes[pt].size() <values_of_landscapes[pt].size() ; ++j ) - { - this->values_of_landscapes[pt][j] *= -1; - } - } - } - - //and now we need to sort the values: - for ( size_t pt = 0 ; pt != this->values_of_landscapes.size() ; ++pt ) - { - std::sort( this->values_of_landscapes[pt].begin() , this->values_of_landscapes[pt].end() , std::greater() ); - } -}//set_up_values_of_landscapes - - - -Persistence_landscape_on_grid::Persistence_landscape_on_grid( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_ ) -{ - this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ ); -}//Persistence_landscape_on_grid - - -Persistence_landscape_on_grid::Persistence_landscape_on_grid( const std::vector< std::pair< double , double > >& p , double grid_min_ , double grid_max_ , size_t number_of_points_ , unsigned number_of_levels_of_landscape ) -{ - this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ , number_of_levels_of_landscape ); -} - - -Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename , double grid_min_, double grid_max_ , size_t number_of_points_ , unsigned short dimension ) -{ - std::vector< std::pair< double , double > > p; - if ( dimension == std::numeric_limits::max() ) - { - p = read_persistence_intervals_in_one_dimension_from_file( filename ); - } - else - { - p = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); - } - this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ ); -} - -Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename , double grid_min_, double grid_max_ , size_t number_of_points_, unsigned number_of_levels_of_landscape, unsigned short dimension ) -{ - std::vector< std::pair< double , double > > p; - if ( dimension == std::numeric_limits::max() ) - { - p = read_persistence_intervals_in_one_dimension_from_file( filename ); - } - else - { - p = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); - } - this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ , number_of_levels_of_landscape ); -} - -Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename , size_t number_of_points_ , unsigned short dimension ) -{ - std::vector< std::pair< double , double > > p; - if ( dimension == std::numeric_limits::max() ) - { - p = read_persistence_intervals_in_one_dimension_from_file( filename ); - } - else - { - p = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); - } - double grid_min_ = std::numeric_limits::max(); - double grid_max_ = -std::numeric_limits::max(); - for ( size_t i = 0 ; i != p.size() ; ++i ) - { - if ( p[i].first < grid_min_ )grid_min_ = p[i].first; - if ( p[i].second > grid_max_ )grid_max_ = p[i].second; - } - this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ ); -} - -Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename , size_t number_of_points_ , unsigned number_of_levels_of_landscape , unsigned short dimension ) -{ - std::vector< std::pair< double , double > > p; - if ( dimension == std::numeric_limits::max() ) - { - p = read_persistence_intervals_in_one_dimension_from_file( filename ); - } - else - { - p = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); - } - double grid_min_ = std::numeric_limits::max(); - double grid_max_ = -std::numeric_limits::max(); - for ( size_t i = 0 ; i != p.size() ; ++i ) - { - if ( p[i].first < grid_min_ )grid_min_ = p[i].first; - if ( p[i].second > grid_max_ )grid_max_ = p[i].second; - } - this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ , number_of_levels_of_landscape ); -} - - -void Persistence_landscape_on_grid::load_landscape_from_file( const char* filename ) -{ - std::ifstream in; - in.open( filename ); - //check if the file exist. - if ( !in.good() ) - { - std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; - throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; - } - - size_t number_of_points_in_the_grid = 0; - in >> this->grid_min >> this->grid_max >> number_of_points_in_the_grid; - - std::vector< std::vector< double > > v(number_of_points_in_the_grid); - std::string line; - std::getline(in, line); - double number; - for ( size_t i = 0 ; i != number_of_points_in_the_grid ; ++i ) - { - //read a line of a file and convert it to a vector. - std::vector< double > vv; - std::getline(in, line); - //std::cerr << "Reading line : " << line << std::endl;getchar(); - std::istringstream stream(line); - while (stream >> number) - { - vv.push_back(number); - } - v[i] = vv; - } - this->values_of_landscapes = v; - in.close(); -} - -void Persistence_landscape_on_grid::print_to_file( const char* filename )const -{ - std::ofstream out; - out.open( filename ); - - //first we store the parameters of the grid: - out << grid_min << std::endl << grid_max << std::endl << this->values_of_landscapes.size() << std::endl; - - //and now in the following lines, the values of this->values_of_landscapes for the following arguments: - for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) - { - for ( size_t j = 0 ; j != this->values_of_landscapes[i].size() ; ++j ) - { - out << this->values_of_landscapes[i][j] << " "; - } - out << std::endl; - } - - out.close(); -} - -void Persistence_landscape_on_grid::plot( const char* filename, double min_x , double max_x , double min_y , double max_y, size_t from_ , size_t to_ )const -{ - //this program create a gnuplot script file that allows to plot persistence diagram. - std::ofstream out; - - std::ostringstream nameSS; - nameSS << filename << "_GnuplotScript"; - std::string nameStr = nameSS.str(); - out.open( nameStr ); - - if ( min_x == max_x ) - { - std::pair min_max = compute_minimum_maximum(); - out << "set xrange [" << this->grid_min << " : " << this->grid_max << "]" << std::endl; - out << "set yrange [" << min_max.first << " : " << min_max.second << "]" << std::endl; - } - else - { - out << "set xrange [" << min_x << " : " << max_x << "]" << std::endl; - out << "set yrange [" << min_y << " : " << max_y << "]" << std::endl; - } - - size_t number_of_nonzero_levels = this->number_of_nonzero_levels(); - double dx = ( this->grid_max - this->grid_min )/((double)this->values_of_landscapes.size()-1); - - - size_t from = 0; - if ( from_ != std::numeric_limits::max() ) - { - if ( from_ < number_of_nonzero_levels ) - { - from = from_; - } - else - { - return; - } - } - size_t to = number_of_nonzero_levels; - if ( to_ != std::numeric_limits::max() ) - { - if ( to_ < number_of_nonzero_levels ) - { - to = to_; - } - } - - - out << "plot "; - for ( size_t lambda= from ; lambda != to ; ++lambda ) - { - //out << " '-' using 1:2 title 'l" << lambda << "' with lp"; - out << " '-' using 1:2 notitle with lp"; - if ( lambda+1 != to ) - { - out << ", \\"; - } - out << std::endl; - } - - for ( size_t lambda = from ; lambda != to ; ++lambda ) - { - double point = this->grid_min; - for ( size_t i = 0 ; i != this->values_of_landscapes.size() ; ++i ) - { - double value = 0; - if ( this->values_of_landscapes[i].size() > lambda ) - { - value = this->values_of_landscapes[i][lambda]; - } - out << point << " " << value << std::endl; - point += dx; - } - out << "EOF" << std::endl; - } - std::cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << std::endl; -} - -template < typename T > -Persistence_landscape_on_grid operation_on_pair_of_landscapes_on_grid ( const Persistence_landscape_on_grid& land1 , const Persistence_landscape_on_grid& land2 ) -{ - //first we need to check if the domains are the same: - if ( !check_if_defined_on_the_same_domain(land1,land2) )throw "Two grids are not compatible"; - - T oper; - Persistence_landscape_on_grid result; - result.values_of_landscapes = std::vector< std::vector< double > >( land1.values_of_landscapes.size() ); - result.grid_min = land1.grid_min; - result.grid_max = land1.grid_max; - - //now we perorm the operations: - for ( size_t grid_point = 0 ; grid_point != land1.values_of_landscapes.size() ; ++grid_point ) - { - result.values_of_landscapes[grid_point] = std::vector< double >( std::max( land1.values_of_landscapes[grid_point].size() , land2.values_of_landscapes[grid_point].size() ) ); - for ( size_t lambda = 0 ; lambda != std::max( land1.values_of_landscapes[grid_point].size() , land2.values_of_landscapes[grid_point].size() ) ; ++lambda ) - { - double value1 = 0; - double value2 = 0; - if ( lambda < land1.values_of_landscapes[grid_point].size() )value1 = land1.values_of_landscapes[grid_point][lambda]; - if ( lambda < land2.values_of_landscapes[grid_point].size() )value2 = land2.values_of_landscapes[grid_point][lambda]; - result.values_of_landscapes[grid_point][lambda] = oper( value1 , value2 ); - } - } - - return result; -} - -Persistence_landscape_on_grid Persistence_landscape_on_grid::multiply_lanscape_by_real_number_not_overwrite( double x )const -{ - Persistence_landscape_on_grid result; - result.values_of_landscapes = std::vector< std::vector< double > >( this->values_of_landscapes.size() ); - result.grid_min = this->grid_min; - result.grid_max = this->grid_max; - - for ( size_t grid_point = 0 ; grid_point != this->values_of_landscapes.size() ; ++grid_point ) - { - result.values_of_landscapes[grid_point] = std::vector< double >( this->values_of_landscapes[grid_point].size() ); - for ( size_t i = 0 ; i != this->values_of_landscapes[grid_point].size() ; ++i ) - { - result.values_of_landscapes[grid_point][i] = x*this->values_of_landscapes[grid_point][i]; - } - } - - return result; -} - -double compute_max_norm_distance_of_landscapes( const Persistence_landscape_on_grid& first, const Persistence_landscape_on_grid& second ) -{ - double result = 0; - - //first we need to check if first and second is defined on the same domain" - if ( !check_if_defined_on_the_same_domain(first, second) )throw "Two grids are not compatible"; - - for ( size_t i = 0 ; i != first.values_of_landscapes.size() ; ++i ) - { - for ( size_t j = 0 ; j != std::min( first.values_of_landscapes[i].size() , second.values_of_landscapes[i].size() ) ; ++j ) - { - if ( result < abs( first.values_of_landscapes[i][j] - second.values_of_landscapes[i][j] ) ) - { - result = abs( first.values_of_landscapes[i][j] - second.values_of_landscapes[i][j] ); - } - } - if ( first.values_of_landscapes[i].size() == std::min( first.values_of_landscapes[i].size() , second.values_of_landscapes[i].size() ) ) - { - for ( size_t j = first.values_of_landscapes[i].size() ; j != second.values_of_landscapes[i].size() ; ++j ) - { - if ( result < second.values_of_landscapes[i][j] )result = second.values_of_landscapes[i][j]; - } - } - if ( second.values_of_landscapes[i].size() == std::min( first.values_of_landscapes[i].size() , second.values_of_landscapes[i].size() ) ) - { - for ( size_t j = second.values_of_landscapes[i].size() ; j != first.values_of_landscapes[i].size() ; ++j ) - { - if ( result < first.values_of_landscapes[i][j] )result = first.values_of_landscapes[i][j]; - } - } - } - return result; -} - - - -}//namespace Gudhi_stat -}//namespace Gudhi - -#endif diff --git a/src/Gudhi_stat/include/gudhi/persistence_representations/persistence_vectors.h b/src/Gudhi_stat/include/gudhi/persistence_representations/persistence_vectors.h deleted file mode 100644 index d56f92c4..00000000 --- a/src/Gudhi_stat/include/gudhi/persistence_representations/persistence_vectors.h +++ /dev/null @@ -1,775 +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 (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 Vector_distances_in_diagram_H -#define Vector_distances_in_diagram_H - -#include -#include -#include -#include -#include - -//gudhi include -#include -#include -#include - - -namespace Gudhi -{ -namespace Gudhi_stat -{ - -/* -template -struct Euclidean_distance -{ - double operator() ( const std::pair< T,T >& f , const std::pair& s ) - { - return sqrt( (f.first-s.first)*(f.first-s.first) + (f.second-s.second)*(f.second-s.second) ); - } - double operator() ( const std::vector< T >& f , const std::vector < T >& s ) - { - if ( f.size() != s.size() ) - { - std::cerr << "Not compatible points dimensions in the procedure to compute Euclidean distance. The program will now terminate. \n"; - std::cout << f.size() << " , " << s.size() << std::endl; - throw "Not compatible points dimensions in the procedure to compute Euclidean distance. The program will now terminate. \n"; - } - double result = 0; - for ( size_t i = 0 ; i != f.size() ; ++i ) - { - result += ( f[i]-s[i] )*( f[i]-s[i] ); - } - return sqrt( result ); - } -}; -* */ - -template -struct Maximum_distance -{ - double operator() ( const std::pair< T,T >& f , const std::pair& s ) - { - return std::max( fabs( f.first - s.first ) , fabs( f.second - s.second ) ); - } -}; - - - - -/** -* This is an implementation of idea presented in the paper 'Stable Topological Signatures for Points on 3D Shapes' by -* M. Carriere, S. Y. Oudot and M. Ovsjanikov published in Computer Graphics Forum (proc. SGP 2015). -* The parameter of the class is the class that computes distance used to construct the vectors. The typical function is -* either Eucludean of maximum (Manhattan) distance. -* This class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product -* -**/ - -template -class Vector_distances_in_diagram -{ -public: - /** - * The default constructor. - **/ - Vector_distances_in_diagram(){}; - - /** - * The constructor that takes as an input a multiset of persistence intervals (given as vector of birth-death pairs). The second parameter is the desiered length of the output vectors. - **/ - Vector_distances_in_diagram( const std::vector< std::pair< double , double > >& intervals , size_t where_to_cut ); - - /** - * The constructor taking as an input a file with birth-death pairs. The second parameter is the desiered length of the output vectors. - **/ - Vector_distances_in_diagram( const char* filename , size_t where_to_cut , unsigned dimension = std::numeric_limits::max() ); - - - /** - * Writing to a stream. - **/ - template - friend std::ostream& operator << ( std::ostream& out , const Vector_distances_in_diagram& d ) - { - for ( size_t i = 0 ; i != std::min( d.sorted_vector_of_distances.size() , d.where_to_cut) ; ++i ) - { - out << d.sorted_vector_of_distances[i] << " "; - } - return out; - } - - /** - * This procedure gives the value of a vector on a given position. - **/ - inline double vector_in_position( size_t position )const - { - if ( position >= this->sorted_vector_of_distances.size() )throw("Wrong position in accessing Vector_distances_in_diagram::sorted_vector_of_distances\n"); - return this->sorted_vector_of_distances[position]; - } - - /** - * Return a size of a vector. - **/ - inline size_t size()const{return this->sorted_vector_of_distances.size();} - - /** - * Write a vector to a file. - **/ - void write_to_file( const char* filename )const; - - /** - * Write a vector to a file. - **/ - void print_to_file( const char* filename )const - { - this->write_to_file( filename ); - } - - /** - * Loading a vector to a file. - **/ - void load_from_file( const char* filename ); - - /** - * Comparision operators: - **/ - bool operator == ( const Vector_distances_in_diagram& second )const - { - if ( this->sorted_vector_of_distances.size() != second.sorted_vector_of_distances.size() )return false; - for ( size_t i = 0 ; i != this->sorted_vector_of_distances.size() ; ++i ) - { - if ( !almost_equal(this->sorted_vector_of_distances[i] , second.sorted_vector_of_distances[i]) )return false; - } - return true; - } - - bool operator != ( const Vector_distances_in_diagram& second )const - { - return !( *this == second ); - } - - - - - //Implementations of functions for various concepts. - /** - * Compute projection to real numbers of persistence vector. This function is required by the Real_valued_topological_data concept - **/ - double project_to_R( int number_of_function )const; - /** - * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. - **/ - size_t number_of_projections_to_R()const - { - return this->number_of_functions_for_projections_to_reals; - } - - /** - * Compute a vectorization of a persistent vectors. It is required in a concept Vectorized_topological_data. - **/ - std::vector vectorize( int number_of_function )const; - /** - * This function return the number of functions that allows vectorization of a persisence vector. It is required in a concept Vectorized_topological_data. - **/ - size_t number_of_vectorize_functions()const - { - return this->number_of_functions_for_vectorization; - } - - /** - * Compute a average of two persistent vectors. This function is required by Topological_data_with_averages concept. - **/ - void compute_average( const std::vector< Vector_distances_in_diagram* >& to_average ); - - /** - * Compute a distance of two persistent vectors. This function is required in Topological_data_with_distances concept. - * For max norm distance, set power to std::numeric_limits::max() - **/ - double distance( const Vector_distances_in_diagram& second , double power = 1)const; - - /** - * Compute a scalar product of two persistent vectors. This function is required in Topological_data_with_scalar_product concept. - **/ - double compute_scalar_product( const Vector_distances_in_diagram& second )const; - //end of implementation of functions needed for concepts. - - - - - - - - - - - - - - - - - - - /** - * For visualization use output from vectorize and build histograms. - **/ - std::vector< double > output_for_visualization()const - { - return this->sorted_vector_of_distances; - } - - - /** - * Create a gnuplot script to vizualize the data structure. - **/ - void plot( const char* filename )const - { - std::stringstream gnuplot_script; - gnuplot_script << filename << "_GnuplotScript"; - std::ofstream out; - out.open( gnuplot_script.str().c_str() ); - out << "set style data histogram" << std::endl; - out << "set style histogram cluster gap 1" << std::endl; - out << "set style fill solid border -1" << std::endl; - out << "plot '-' notitle" << std::endl; - for ( size_t i = 0 ; i != this->sorted_vector_of_distances.size() ; ++i ) - { - out << this->sorted_vector_of_distances[i] << std::endl; - } - out < get_x_range()const - { - return std::make_pair( 0 , this->sorted_vector_of_distances.size() ); - } - - /** - * The y-range of the persistence vector. - **/ - std::pair< double , double > get_y_range()const - { - if ( this->sorted_vector_of_distances.size() == 0 )return std::make_pair(0,0); - return std::make_pair( this->sorted_vector_of_distances[0] , 0); - } - - //arythmetic operations: - template < typename Operation_type > - friend Vector_distances_in_diagram operation_on_pair_of_vectors( const Vector_distances_in_diagram& first , const Vector_distances_in_diagram& second , Operation_type opertion ) - { - Vector_distances_in_diagram result; - //Operation_type operation; - result.sorted_vector_of_distances.reserve(std::max( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ); - for ( size_t i = 0 ; i != std::min( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ; ++i ) - { - result.sorted_vector_of_distances.push_back( opertion( first.sorted_vector_of_distances[i] , second.sorted_vector_of_distances[i]) ); - } - if ( first.sorted_vector_of_distances.size() == std::min( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ) - { - for ( size_t i = std::min( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ; - i != std::max( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ; ++i ) - { - result.sorted_vector_of_distances.push_back( opertion(0,second.sorted_vector_of_distances[i]) ); - } - } - else - { - for ( size_t i = std::min( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ; - i != std::max( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ; ++i ) - { - result.sorted_vector_of_distances.push_back( opertion(first.sorted_vector_of_distances[i],0) ); - } - } - return result; - }//operation_on_pair_of_vectors - - /** - * This function implements an operation of multiplying Vector_distances_in_diagram by a scalar. - **/ - Vector_distances_in_diagram multiply_by_scalar( double scalar )const - { - Vector_distances_in_diagram result; - result.sorted_vector_of_distances.reserve( this->sorted_vector_of_distances.size() ); - for ( size_t i = 0 ; i != this->sorted_vector_of_distances.size() ; ++i ) - { - result.sorted_vector_of_distances.push_back( scalar * this->sorted_vector_of_distances[i] ); - } - return result; - }//multiply_by_scalar - - - - /** - * This function computes a sum of two objects of a type Vector_distances_in_diagram. - **/ - friend Vector_distances_in_diagram operator+( const Vector_distances_in_diagram& first , const Vector_distances_in_diagram& second ) - { - return operation_on_pair_of_vectors( first , second , std::plus() ); - } - /** - * This function computes a difference of two objects of a type Vector_distances_in_diagram. - **/ - friend Vector_distances_in_diagram operator-( const Vector_distances_in_diagram& first , const Vector_distances_in_diagram& second ) - { - return operation_on_pair_of_vectors( first , second , std::minus() ); - } - /** - * This function computes a product of an object of a type Vector_distances_in_diagram with real number. - **/ - friend Vector_distances_in_diagram operator*( double scalar , const Vector_distances_in_diagram& A ) - { - return A.multiply_by_scalar( scalar ); - } - /** - * This function computes a product of an object of a type Vector_distances_in_diagram with real number. - **/ - friend Vector_distances_in_diagram operator*( const Vector_distances_in_diagram& A , double scalar ) - { - return A.multiply_by_scalar( scalar ); - } - /** - * This function computes a product of an object of a type Vector_distances_in_diagram with real number. - **/ - Vector_distances_in_diagram operator*( double scalar ) - { - return this->multiply_by_scalar( scalar ); - } - /** - * += operator for Vector_distances_in_diagram. - **/ - Vector_distances_in_diagram operator += ( const Vector_distances_in_diagram& rhs ) - { - *this = *this + rhs; - return *this; - } - /** - * -= operator for Vector_distances_in_diagram. - **/ - Vector_distances_in_diagram operator -= ( const Vector_distances_in_diagram& rhs ) - { - *this = *this - rhs; - return *this; - } - /** - * *= operator for Vector_distances_in_diagram. - **/ - Vector_distances_in_diagram operator *= ( double x ) - { - *this = *this*x; - return *this; - } - /** - * /= operator for Vector_distances_in_diagram. - **/ - Vector_distances_in_diagram operator /= ( double x ) - { - if ( x == 0 )throw( "In operator /=, division by 0. Program terminated." ); - *this = *this * (1/x); - return *this; - } - - -private: - std::vector< std::pair< double , double > > intervals; - std::vector< double > sorted_vector_of_distances; - size_t number_of_functions_for_vectorization; - size_t number_of_functions_for_projections_to_reals; - size_t where_to_cut; - - void compute_sorted_vector_of_distances_via_heap( size_t where_to_cut ); - void compute_sorted_vector_of_distances_via_vector_sorting( size_t where_to_cut ); - - Vector_distances_in_diagram( const std::vector< double >& sorted_vector_of_distances_ ):sorted_vector_of_distances(sorted_vector_of_distances_) - { - this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); - } - - void set_up_numbers_of_functions_for_vectorization_and_projections_to_reals() - { - //warning, this function can be only called after filling in the intervals vector. - this->number_of_functions_for_vectorization = this->sorted_vector_of_distances.size(); - this->number_of_functions_for_projections_to_reals = this->sorted_vector_of_distances.size(); - } -}; - - -template -Vector_distances_in_diagram::Vector_distances_in_diagram( const std::vector< std::pair< double,double > >& intervals_ , size_t where_to_cut_ ):where_to_cut(where_to_cut_) -{ - std::vector< std::pair< double,double > > i( intervals_ ); - this->intervals = i; - //this->compute_sorted_vector_of_distances_via_heap( where_to_cut ); - this->compute_sorted_vector_of_distances_via_vector_sorting(where_to_cut); - this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); -} - -template -Vector_distances_in_diagram::Vector_distances_in_diagram( const char* filename , size_t where_to_cut , unsigned dimension ):where_to_cut(where_to_cut) -{ - std::vector< std::pair< double , double > > intervals; - if ( dimension == std::numeric_limits::max() ) - { - intervals = read_persistence_intervals_in_one_dimension_from_file( filename ); - } - else - { - intervals = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); - } - this->intervals = intervals; - this->compute_sorted_vector_of_distances_via_heap( where_to_cut ); - //this->compute_sorted_vector_of_distances_via_vector_sorting( where_to_cut ); - set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); -} - -template < typename F> -void Vector_distances_in_diagram::compute_sorted_vector_of_distances_via_heap( size_t where_to_cut ) -{ - - bool dbg = false; - if ( dbg ) - { - std::cerr << "Here are the intervals : \n"; - for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) - { - std::cerr << this->intervals[i].first << " , " << this->intervals[i].second <intervals.size() * ( this->intervals.size() - 1 ) + this->intervals.size())); - - std::vector< double > heap( where_to_cut , std::numeric_limits::max() ); - std::make_heap (heap.begin(),heap.end()); - F f; - - //for every pair of points in the diagram, compute the minimum of their distance, and distance of those points from diagonal - for ( size_t i = 0 ; i < this->intervals.size() ; ++i ) - { - for ( size_t j = i+1 ; j < this->intervals.size() ; ++j ) - { - double value = std::min( - f( this->intervals[i] , this->intervals[j] ), - std::min( - f( this->intervals[i] , std::make_pair( 0.5*(this->intervals[i].first+this->intervals[i].second) , 0.5*(this->intervals[i].first+this->intervals[i].second) ) ), - f( this->intervals[j] , std::make_pair( 0.5*(this->intervals[j].first+this->intervals[j].second) , 0.5*(this->intervals[j].first+this->intervals[j].second) ) ) - ) - ); - - if ( dbg ) - { - std::cerr << "Value : " << value <intervals.size() ; ++i ) - { - double value = f( this->intervals[i] , std::make_pair( 0.5*(this->intervals[i].first+this->intervals[i].second) , 0.5*(this->intervals[i].first+this->intervals[i].second) ) ); - if ( -value < heap.front() ) - { - //std::cerr << "Replacing : " << heap.front() << " with : " << -value <::max() ) - { - heap[i] = 0; - } - else - { - heap[i] *= -1; - } - } - - if ( dbg ) - { - std::cerr << "This is the heap after all the operations :\n"; - for ( size_t i = 0 ; i != heap.size() ; ++i ) - { - std::cout << heap[i] << " "; - } - std::cout <sorted_vector_of_distances = heap; -} - - - - -template < typename F> -void Vector_distances_in_diagram::compute_sorted_vector_of_distances_via_vector_sorting( size_t where_to_cut ) -{ - std::vector< double > distances; - distances.reserve( (size_t)(0.5 * this->intervals.size() * ( this->intervals.size() - 1 ) + this->intervals.size()) ); - F f; - - //for every pair of points in the diagram, compute the minimum of their distance, and distance of those points from diagonal - for ( size_t i = 0 ; i < this->intervals.size() ; ++i ) - { - //add distance of i-th point in the diagram from the diagonal to the distances vector - distances.push_back( f( this->intervals[i] , std::make_pair( 0.5*(this->intervals[i].first+this->intervals[i].second) , 0.5*(this->intervals[i].first+this->intervals[i].second) ) ) ); - for ( size_t j = i+1 ; j < this->intervals.size() ; ++j ) - { - double value = std::min( - f( this->intervals[i] , this->intervals[j] ), - std::min( - f( this->intervals[i] , std::make_pair( 0.5*(this->intervals[i].first+this->intervals[i].second) , 0.5*(this->intervals[i].first+this->intervals[i].second) ) ), - f( this->intervals[j] , std::make_pair( 0.5*(this->intervals[j].first+this->intervals[j].second) , 0.5*(this->intervals[j].first+this->intervals[j].second) ) ) - ) - ); - distances.push_back( value ); - - } - } - std::sort( distances.begin() , distances.end() , std::greater() ); - if ( distances.size() > where_to_cut )distances.resize( where_to_cut ); - - this->sorted_vector_of_distances = distances; -} - - - -//Implementations of functions for various concepts. -template -double Vector_distances_in_diagram::project_to_R( int number_of_function )const -{ - if ( (size_t)number_of_function > this->number_of_functions_for_projections_to_reals )throw "Wrong index of a function in a method Vector_distances_in_diagram::project_to_R"; - if ( number_of_function < 0 )throw "Wrong index of a function in a method Vector_distances_in_diagram::project_to_R"; - - double result = 0; - for ( size_t i = 0 ; i != (size_t)number_of_function ; ++i ) - { - result += sorted_vector_of_distances[i]; - } - return result; -} - -template -void Vector_distances_in_diagram::compute_average( const std::vector< Vector_distances_in_diagram* >& to_average ) -{ - - if ( to_average.size() == 0 ) - { - (*this) = Vector_distances_in_diagram(); - return; - } - - size_t maximal_length_of_vector = 0; - for ( size_t i = 0 ; i != to_average.size() ; ++i ) - { - if ( to_average[i]->sorted_vector_of_distances.size() > maximal_length_of_vector ) - { - maximal_length_of_vector = to_average[i]->sorted_vector_of_distances.size(); - } - } - - std::vector< double > av( maximal_length_of_vector , 0 ); - for ( size_t i = 0 ; i != to_average.size() ; ++i ) - { - for ( size_t j = 0 ; j != to_average[i]->sorted_vector_of_distances.size() ; ++j ) - { - av[j] += to_average[i]->sorted_vector_of_distances[j]; - } - } - - for ( size_t i = 0 ; i != maximal_length_of_vector ; ++i ) - { - av[i] /= (double)to_average.size(); - } - this->sorted_vector_of_distances = av; - this->where_to_cut = av.size(); -} - -template -double Vector_distances_in_diagram::distance( const Vector_distances_in_diagram& second_ , double power )const -{ - bool dbg = false; - - if ( dbg ) - { - std::cerr << "Entering double Vector_distances_in_diagram::distance( const Abs_Topological_data_with_distances* second , double power ) procedure \n"; - std::cerr << "Power : " << power << std::endl; - std::cerr << "This : " << *this << std::endl; - std::cerr << "second : " << second_ << std::endl; - } - - - double result = 0; - for ( size_t i = 0 ; i != std::min(this->sorted_vector_of_distances.size(), second_.sorted_vector_of_distances.size()) ; ++i ) - { - if ( power == 1 ) - { - if ( dbg ) - { - std::cerr << "|" << this->sorted_vector_of_distances[i] << " - " << second_.sorted_vector_of_distances[i] << " | : " << fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) <sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ); - } - else - { - if ( power < std::numeric_limits::max() ) - { - result += std::pow( fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) , power ); - } - else - { - //nax morm - if ( result < fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) )result = fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ); - } - if ( dbg ) - { - std::cerr << "| " << this->sorted_vector_of_distances[i] << " - " << second_.sorted_vector_of_distances[i] << " : " << fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) <sorted_vector_of_distances.size() != second_.sorted_vector_of_distances.size() ) - { - if ( this->sorted_vector_of_distances.size() > second_.sorted_vector_of_distances.size() ) - { - for ( size_t i = second_.sorted_vector_of_distances.size() ; i != this->sorted_vector_of_distances.size() ; ++i ) - { - result += fabs( this->sorted_vector_of_distances[i] ); - } - } - else - { - //this->sorted_vector_of_distances.size() < second_.sorted_vector_of_distances.size() - for ( size_t i = this->sorted_vector_of_distances.size() ; i != second_.sorted_vector_of_distances.size() ; ++i ) - { - result += fabs( second_.sorted_vector_of_distances[i] ); - } - } - } - - - if ( power != 1 ) - { - result = std::pow( result , (1.0/power) ); - } - return result; -} - -template < typename F> -std::vector Vector_distances_in_diagram::vectorize( int number_of_function )const -{ - if ( (size_t)number_of_function > this->number_of_functions_for_vectorization )throw "Wrong index of a function in a method Vector_distances_in_diagram::vectorize"; - if ( number_of_function < 0 )throw "Wrong index of a function in a method Vector_distances_in_diagram::vectorize"; - - std::vector< double > result( std::min( (size_t)number_of_function , this->sorted_vector_of_distances.size() ) ); - for ( size_t i = 0 ; i != std::min( (size_t)number_of_function , this->sorted_vector_of_distances.size() ) ; ++i ) - { - result[i] = this->sorted_vector_of_distances[i]; - } - return result; -} - - -template < typename F> -void Vector_distances_in_diagram::write_to_file( const char* filename )const -{ - std::ofstream out; - out.open( filename ); - - for ( size_t i = 0 ; i != this->sorted_vector_of_distances.size() ; ++i ) - { - out << this->sorted_vector_of_distances[i] << " "; - } - - out.close(); -} - -template < typename F> -void Vector_distances_in_diagram::load_from_file( const char* filename ) -{ - std::ifstream in; - in.open( filename ); - //check if the file exist. - if ( !in.good() ) - { - std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; - throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; - } - - double number; - while ( true ) - { - in >> number; - if ( in.eof() )break; - this->sorted_vector_of_distances.push_back(number); - } - in.close(); -} - -template < typename F> -double Vector_distances_in_diagram::compute_scalar_product( const Vector_distances_in_diagram& second_vector )const -{ - double result = 0; - for ( size_t i = 0 ; i != std::min(this->sorted_vector_of_distances.size(),second_vector.sorted_vector_of_distances.size()) ; ++i ) - { - result += this->sorted_vector_of_distances[i] * second_vector.sorted_vector_of_distances[i]; - } - return result; -} - - - - - -}//namespace Gudhi_stat -}//namespace Gudhi - - -#endif // Vector_distances_in_diagram_H diff --git a/src/Gudhi_stat/include/gudhi/persistence_vectors.h b/src/Gudhi_stat/include/gudhi/persistence_vectors.h new file mode 100644 index 00000000..9ed32fc1 --- /dev/null +++ b/src/Gudhi_stat/include/gudhi/persistence_vectors.h @@ -0,0 +1,775 @@ +/* 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 (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 Vector_distances_in_diagram_H +#define Vector_distances_in_diagram_H + +#include +#include +#include +#include +#include + +//gudhi include +#include +#include +#include + + +namespace Gudhi +{ +namespace Persistence_representations +{ + +/* +template +struct Euclidean_distance +{ + double operator() ( const std::pair< T,T >& f , const std::pair& s ) + { + return sqrt( (f.first-s.first)*(f.first-s.first) + (f.second-s.second)*(f.second-s.second) ); + } + double operator() ( const std::vector< T >& f , const std::vector < T >& s ) + { + if ( f.size() != s.size() ) + { + std::cerr << "Not compatible points dimensions in the procedure to compute Euclidean distance. The program will now terminate. \n"; + std::cout << f.size() << " , " << s.size() << std::endl; + throw "Not compatible points dimensions in the procedure to compute Euclidean distance. The program will now terminate. \n"; + } + double result = 0; + for ( size_t i = 0 ; i != f.size() ; ++i ) + { + result += ( f[i]-s[i] )*( f[i]-s[i] ); + } + return sqrt( result ); + } +}; +* */ + +template +struct Maximum_distance +{ + double operator() ( const std::pair< T,T >& f , const std::pair& s ) + { + return std::max( fabs( f.first - s.first ) , fabs( f.second - s.second ) ); + } +}; + + + + +/** +* This is an implementation of idea presented in the paper 'Stable Topological Signatures for Points on 3D Shapes' by +* M. Carriere, S. Y. Oudot and M. Ovsjanikov published in Computer Graphics Forum (proc. SGP 2015). +* The parameter of the class is the class that computes distance used to construct the vectors. The typical function is +* either Eucludean of maximum (Manhattan) distance. +* This class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances, Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product +* +**/ + +template +class Vector_distances_in_diagram +{ +public: + /** + * The default constructor. + **/ + Vector_distances_in_diagram(){}; + + /** + * The constructor that takes as an input a multiset of persistence intervals (given as vector of birth-death pairs). The second parameter is the desiered length of the output vectors. + **/ + Vector_distances_in_diagram( const std::vector< std::pair< double , double > >& intervals , size_t where_to_cut ); + + /** + * The constructor taking as an input a file with birth-death pairs. The second parameter is the desiered length of the output vectors. + **/ + Vector_distances_in_diagram( const char* filename , size_t where_to_cut , unsigned dimension = std::numeric_limits::max() ); + + + /** + * Writing to a stream. + **/ + template + friend std::ostream& operator << ( std::ostream& out , const Vector_distances_in_diagram& d ) + { + for ( size_t i = 0 ; i != std::min( d.sorted_vector_of_distances.size() , d.where_to_cut) ; ++i ) + { + out << d.sorted_vector_of_distances[i] << " "; + } + return out; + } + + /** + * This procedure gives the value of a vector on a given position. + **/ + inline double vector_in_position( size_t position )const + { + if ( position >= this->sorted_vector_of_distances.size() )throw("Wrong position in accessing Vector_distances_in_diagram::sorted_vector_of_distances\n"); + return this->sorted_vector_of_distances[position]; + } + + /** + * Return a size of a vector. + **/ + inline size_t size()const{return this->sorted_vector_of_distances.size();} + + /** + * Write a vector to a file. + **/ + void write_to_file( const char* filename )const; + + /** + * Write a vector to a file. + **/ + void print_to_file( const char* filename )const + { + this->write_to_file( filename ); + } + + /** + * Loading a vector to a file. + **/ + void load_from_file( const char* filename ); + + /** + * Comparision operators: + **/ + bool operator == ( const Vector_distances_in_diagram& second )const + { + if ( this->sorted_vector_of_distances.size() != second.sorted_vector_of_distances.size() )return false; + for ( size_t i = 0 ; i != this->sorted_vector_of_distances.size() ; ++i ) + { + if ( !almost_equal(this->sorted_vector_of_distances[i] , second.sorted_vector_of_distances[i]) )return false; + } + return true; + } + + bool operator != ( const Vector_distances_in_diagram& second )const + { + return !( *this == second ); + } + + + + + //Implementations of functions for various concepts. + /** + * Compute projection to real numbers of persistence vector. This function is required by the Real_valued_topological_data concept + **/ + double project_to_R( int number_of_function )const; + /** + * The function gives the number of possible projections to R. This function is required by the Real_valued_topological_data concept. + **/ + size_t number_of_projections_to_R()const + { + return this->number_of_functions_for_projections_to_reals; + } + + /** + * Compute a vectorization of a persistent vectors. It is required in a concept Vectorized_topological_data. + **/ + std::vector vectorize( int number_of_function )const; + /** + * This function return the number of functions that allows vectorization of a persisence vector. It is required in a concept Vectorized_topological_data. + **/ + size_t number_of_vectorize_functions()const + { + return this->number_of_functions_for_vectorization; + } + + /** + * Compute a average of two persistent vectors. This function is required by Topological_data_with_averages concept. + **/ + void compute_average( const std::vector< Vector_distances_in_diagram* >& to_average ); + + /** + * Compute a distance of two persistent vectors. This function is required in Topological_data_with_distances concept. + * For max norm distance, set power to std::numeric_limits::max() + **/ + double distance( const Vector_distances_in_diagram& second , double power = 1)const; + + /** + * Compute a scalar product of two persistent vectors. This function is required in Topological_data_with_scalar_product concept. + **/ + double compute_scalar_product( const Vector_distances_in_diagram& second )const; + //end of implementation of functions needed for concepts. + + + + + + + + + + + + + + + + + + + /** + * For visualization use output from vectorize and build histograms. + **/ + std::vector< double > output_for_visualization()const + { + return this->sorted_vector_of_distances; + } + + + /** + * Create a gnuplot script to vizualize the data structure. + **/ + void plot( const char* filename )const + { + std::stringstream gnuplot_script; + gnuplot_script << filename << "_GnuplotScript"; + std::ofstream out; + out.open( gnuplot_script.str().c_str() ); + out << "set style data histogram" << std::endl; + out << "set style histogram cluster gap 1" << std::endl; + out << "set style fill solid border -1" << std::endl; + out << "plot '-' notitle" << std::endl; + for ( size_t i = 0 ; i != this->sorted_vector_of_distances.size() ; ++i ) + { + out << this->sorted_vector_of_distances[i] << std::endl; + } + out < get_x_range()const + { + return std::make_pair( 0 , this->sorted_vector_of_distances.size() ); + } + + /** + * The y-range of the persistence vector. + **/ + std::pair< double , double > get_y_range()const + { + if ( this->sorted_vector_of_distances.size() == 0 )return std::make_pair(0,0); + return std::make_pair( this->sorted_vector_of_distances[0] , 0); + } + + //arythmetic operations: + template < typename Operation_type > + friend Vector_distances_in_diagram operation_on_pair_of_vectors( const Vector_distances_in_diagram& first , const Vector_distances_in_diagram& second , Operation_type opertion ) + { + Vector_distances_in_diagram result; + //Operation_type operation; + result.sorted_vector_of_distances.reserve(std::max( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ); + for ( size_t i = 0 ; i != std::min( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ; ++i ) + { + result.sorted_vector_of_distances.push_back( opertion( first.sorted_vector_of_distances[i] , second.sorted_vector_of_distances[i]) ); + } + if ( first.sorted_vector_of_distances.size() == std::min( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ) + { + for ( size_t i = std::min( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ; + i != std::max( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ; ++i ) + { + result.sorted_vector_of_distances.push_back( opertion(0,second.sorted_vector_of_distances[i]) ); + } + } + else + { + for ( size_t i = std::min( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ; + i != std::max( first.sorted_vector_of_distances.size() , second.sorted_vector_of_distances.size() ) ; ++i ) + { + result.sorted_vector_of_distances.push_back( opertion(first.sorted_vector_of_distances[i],0) ); + } + } + return result; + }//operation_on_pair_of_vectors + + /** + * This function implements an operation of multiplying Vector_distances_in_diagram by a scalar. + **/ + Vector_distances_in_diagram multiply_by_scalar( double scalar )const + { + Vector_distances_in_diagram result; + result.sorted_vector_of_distances.reserve( this->sorted_vector_of_distances.size() ); + for ( size_t i = 0 ; i != this->sorted_vector_of_distances.size() ; ++i ) + { + result.sorted_vector_of_distances.push_back( scalar * this->sorted_vector_of_distances[i] ); + } + return result; + }//multiply_by_scalar + + + + /** + * This function computes a sum of two objects of a type Vector_distances_in_diagram. + **/ + friend Vector_distances_in_diagram operator+( const Vector_distances_in_diagram& first , const Vector_distances_in_diagram& second ) + { + return operation_on_pair_of_vectors( first , second , std::plus() ); + } + /** + * This function computes a difference of two objects of a type Vector_distances_in_diagram. + **/ + friend Vector_distances_in_diagram operator-( const Vector_distances_in_diagram& first , const Vector_distances_in_diagram& second ) + { + return operation_on_pair_of_vectors( first , second , std::minus() ); + } + /** + * This function computes a product of an object of a type Vector_distances_in_diagram with real number. + **/ + friend Vector_distances_in_diagram operator*( double scalar , const Vector_distances_in_diagram& A ) + { + return A.multiply_by_scalar( scalar ); + } + /** + * This function computes a product of an object of a type Vector_distances_in_diagram with real number. + **/ + friend Vector_distances_in_diagram operator*( const Vector_distances_in_diagram& A , double scalar ) + { + return A.multiply_by_scalar( scalar ); + } + /** + * This function computes a product of an object of a type Vector_distances_in_diagram with real number. + **/ + Vector_distances_in_diagram operator*( double scalar ) + { + return this->multiply_by_scalar( scalar ); + } + /** + * += operator for Vector_distances_in_diagram. + **/ + Vector_distances_in_diagram operator += ( const Vector_distances_in_diagram& rhs ) + { + *this = *this + rhs; + return *this; + } + /** + * -= operator for Vector_distances_in_diagram. + **/ + Vector_distances_in_diagram operator -= ( const Vector_distances_in_diagram& rhs ) + { + *this = *this - rhs; + return *this; + } + /** + * *= operator for Vector_distances_in_diagram. + **/ + Vector_distances_in_diagram operator *= ( double x ) + { + *this = *this*x; + return *this; + } + /** + * /= operator for Vector_distances_in_diagram. + **/ + Vector_distances_in_diagram operator /= ( double x ) + { + if ( x == 0 )throw( "In operator /=, division by 0. Program terminated." ); + *this = *this * (1/x); + return *this; + } + + +private: + std::vector< std::pair< double , double > > intervals; + std::vector< double > sorted_vector_of_distances; + size_t number_of_functions_for_vectorization; + size_t number_of_functions_for_projections_to_reals; + size_t where_to_cut; + + void compute_sorted_vector_of_distances_via_heap( size_t where_to_cut ); + void compute_sorted_vector_of_distances_via_vector_sorting( size_t where_to_cut ); + + Vector_distances_in_diagram( const std::vector< double >& sorted_vector_of_distances_ ):sorted_vector_of_distances(sorted_vector_of_distances_) + { + this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); + } + + void set_up_numbers_of_functions_for_vectorization_and_projections_to_reals() + { + //warning, this function can be only called after filling in the intervals vector. + this->number_of_functions_for_vectorization = this->sorted_vector_of_distances.size(); + this->number_of_functions_for_projections_to_reals = this->sorted_vector_of_distances.size(); + } +}; + + +template +Vector_distances_in_diagram::Vector_distances_in_diagram( const std::vector< std::pair< double,double > >& intervals_ , size_t where_to_cut_ ):where_to_cut(where_to_cut_) +{ + std::vector< std::pair< double,double > > i( intervals_ ); + this->intervals = i; + //this->compute_sorted_vector_of_distances_via_heap( where_to_cut ); + this->compute_sorted_vector_of_distances_via_vector_sorting(where_to_cut); + this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); +} + +template +Vector_distances_in_diagram::Vector_distances_in_diagram( const char* filename , size_t where_to_cut , unsigned dimension ):where_to_cut(where_to_cut) +{ + std::vector< std::pair< double , double > > intervals; + if ( dimension == std::numeric_limits::max() ) + { + intervals = read_persistence_intervals_in_one_dimension_from_file( filename ); + } + else + { + intervals = read_persistence_intervals_in_one_dimension_from_file( filename , dimension ); + } + this->intervals = intervals; + this->compute_sorted_vector_of_distances_via_heap( where_to_cut ); + //this->compute_sorted_vector_of_distances_via_vector_sorting( where_to_cut ); + set_up_numbers_of_functions_for_vectorization_and_projections_to_reals(); +} + +template < typename F> +void Vector_distances_in_diagram::compute_sorted_vector_of_distances_via_heap( size_t where_to_cut ) +{ + + bool dbg = false; + if ( dbg ) + { + std::cerr << "Here are the intervals : \n"; + for ( size_t i = 0 ; i != this->intervals.size() ; ++i ) + { + std::cerr << this->intervals[i].first << " , " << this->intervals[i].second <intervals.size() * ( this->intervals.size() - 1 ) + this->intervals.size())); + + std::vector< double > heap( where_to_cut , std::numeric_limits::max() ); + std::make_heap (heap.begin(),heap.end()); + F f; + + //for every pair of points in the diagram, compute the minimum of their distance, and distance of those points from diagonal + for ( size_t i = 0 ; i < this->intervals.size() ; ++i ) + { + for ( size_t j = i+1 ; j < this->intervals.size() ; ++j ) + { + double value = std::min( + f( this->intervals[i] , this->intervals[j] ), + std::min( + f( this->intervals[i] , std::make_pair( 0.5*(this->intervals[i].first+this->intervals[i].second) , 0.5*(this->intervals[i].first+this->intervals[i].second) ) ), + f( this->intervals[j] , std::make_pair( 0.5*(this->intervals[j].first+this->intervals[j].second) , 0.5*(this->intervals[j].first+this->intervals[j].second) ) ) + ) + ); + + if ( dbg ) + { + std::cerr << "Value : " << value <intervals.size() ; ++i ) + { + double value = f( this->intervals[i] , std::make_pair( 0.5*(this->intervals[i].first+this->intervals[i].second) , 0.5*(this->intervals[i].first+this->intervals[i].second) ) ); + if ( -value < heap.front() ) + { + //std::cerr << "Replacing : " << heap.front() << " with : " << -value <::max() ) + { + heap[i] = 0; + } + else + { + heap[i] *= -1; + } + } + + if ( dbg ) + { + std::cerr << "This is the heap after all the operations :\n"; + for ( size_t i = 0 ; i != heap.size() ; ++i ) + { + std::cout << heap[i] << " "; + } + std::cout <sorted_vector_of_distances = heap; +} + + + + +template < typename F> +void Vector_distances_in_diagram::compute_sorted_vector_of_distances_via_vector_sorting( size_t where_to_cut ) +{ + std::vector< double > distances; + distances.reserve( (size_t)(0.5 * this->intervals.size() * ( this->intervals.size() - 1 ) + this->intervals.size()) ); + F f; + + //for every pair of points in the diagram, compute the minimum of their distance, and distance of those points from diagonal + for ( size_t i = 0 ; i < this->intervals.size() ; ++i ) + { + //add distance of i-th point in the diagram from the diagonal to the distances vector + distances.push_back( f( this->intervals[i] , std::make_pair( 0.5*(this->intervals[i].first+this->intervals[i].second) , 0.5*(this->intervals[i].first+this->intervals[i].second) ) ) ); + for ( size_t j = i+1 ; j < this->intervals.size() ; ++j ) + { + double value = std::min( + f( this->intervals[i] , this->intervals[j] ), + std::min( + f( this->intervals[i] , std::make_pair( 0.5*(this->intervals[i].first+this->intervals[i].second) , 0.5*(this->intervals[i].first+this->intervals[i].second) ) ), + f( this->intervals[j] , std::make_pair( 0.5*(this->intervals[j].first+this->intervals[j].second) , 0.5*(this->intervals[j].first+this->intervals[j].second) ) ) + ) + ); + distances.push_back( value ); + + } + } + std::sort( distances.begin() , distances.end() , std::greater() ); + if ( distances.size() > where_to_cut )distances.resize( where_to_cut ); + + this->sorted_vector_of_distances = distances; +} + + + +//Implementations of functions for various concepts. +template +double Vector_distances_in_diagram::project_to_R( int number_of_function )const +{ + if ( (size_t)number_of_function > this->number_of_functions_for_projections_to_reals )throw "Wrong index of a function in a method Vector_distances_in_diagram::project_to_R"; + if ( number_of_function < 0 )throw "Wrong index of a function in a method Vector_distances_in_diagram::project_to_R"; + + double result = 0; + for ( size_t i = 0 ; i != (size_t)number_of_function ; ++i ) + { + result += sorted_vector_of_distances[i]; + } + return result; +} + +template +void Vector_distances_in_diagram::compute_average( const std::vector< Vector_distances_in_diagram* >& to_average ) +{ + + if ( to_average.size() == 0 ) + { + (*this) = Vector_distances_in_diagram(); + return; + } + + size_t maximal_length_of_vector = 0; + for ( size_t i = 0 ; i != to_average.size() ; ++i ) + { + if ( to_average[i]->sorted_vector_of_distances.size() > maximal_length_of_vector ) + { + maximal_length_of_vector = to_average[i]->sorted_vector_of_distances.size(); + } + } + + std::vector< double > av( maximal_length_of_vector , 0 ); + for ( size_t i = 0 ; i != to_average.size() ; ++i ) + { + for ( size_t j = 0 ; j != to_average[i]->sorted_vector_of_distances.size() ; ++j ) + { + av[j] += to_average[i]->sorted_vector_of_distances[j]; + } + } + + for ( size_t i = 0 ; i != maximal_length_of_vector ; ++i ) + { + av[i] /= (double)to_average.size(); + } + this->sorted_vector_of_distances = av; + this->where_to_cut = av.size(); +} + +template +double Vector_distances_in_diagram::distance( const Vector_distances_in_diagram& second_ , double power )const +{ + bool dbg = false; + + if ( dbg ) + { + std::cerr << "Entering double Vector_distances_in_diagram::distance( const Abs_Topological_data_with_distances* second , double power ) procedure \n"; + std::cerr << "Power : " << power << std::endl; + std::cerr << "This : " << *this << std::endl; + std::cerr << "second : " << second_ << std::endl; + } + + + double result = 0; + for ( size_t i = 0 ; i != std::min(this->sorted_vector_of_distances.size(), second_.sorted_vector_of_distances.size()) ; ++i ) + { + if ( power == 1 ) + { + if ( dbg ) + { + std::cerr << "|" << this->sorted_vector_of_distances[i] << " - " << second_.sorted_vector_of_distances[i] << " | : " << fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) <sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ); + } + else + { + if ( power < std::numeric_limits::max() ) + { + result += std::pow( fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) , power ); + } + else + { + //nax morm + if ( result < fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) )result = fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ); + } + if ( dbg ) + { + std::cerr << "| " << this->sorted_vector_of_distances[i] << " - " << second_.sorted_vector_of_distances[i] << " : " << fabs( this->sorted_vector_of_distances[i] - second_.sorted_vector_of_distances[i] ) <sorted_vector_of_distances.size() != second_.sorted_vector_of_distances.size() ) + { + if ( this->sorted_vector_of_distances.size() > second_.sorted_vector_of_distances.size() ) + { + for ( size_t i = second_.sorted_vector_of_distances.size() ; i != this->sorted_vector_of_distances.size() ; ++i ) + { + result += fabs( this->sorted_vector_of_distances[i] ); + } + } + else + { + //this->sorted_vector_of_distances.size() < second_.sorted_vector_of_distances.size() + for ( size_t i = this->sorted_vector_of_distances.size() ; i != second_.sorted_vector_of_distances.size() ; ++i ) + { + result += fabs( second_.sorted_vector_of_distances[i] ); + } + } + } + + + if ( power != 1 ) + { + result = std::pow( result , (1.0/power) ); + } + return result; +} + +template < typename F> +std::vector Vector_distances_in_diagram::vectorize( int number_of_function )const +{ + if ( (size_t)number_of_function > this->number_of_functions_for_vectorization )throw "Wrong index of a function in a method Vector_distances_in_diagram::vectorize"; + if ( number_of_function < 0 )throw "Wrong index of a function in a method Vector_distances_in_diagram::vectorize"; + + std::vector< double > result( std::min( (size_t)number_of_function , this->sorted_vector_of_distances.size() ) ); + for ( size_t i = 0 ; i != std::min( (size_t)number_of_function , this->sorted_vector_of_distances.size() ) ; ++i ) + { + result[i] = this->sorted_vector_of_distances[i]; + } + return result; +} + + +template < typename F> +void Vector_distances_in_diagram::write_to_file( const char* filename )const +{ + std::ofstream out; + out.open( filename ); + + for ( size_t i = 0 ; i != this->sorted_vector_of_distances.size() ; ++i ) + { + out << this->sorted_vector_of_distances[i] << " "; + } + + out.close(); +} + +template < typename F> +void Vector_distances_in_diagram::load_from_file( const char* filename ) +{ + std::ifstream in; + in.open( filename ); + //check if the file exist. + if ( !in.good() ) + { + std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n"; + throw "The file from which you are trying to read the persistence landscape do not exist. The program will now terminate \n"; + } + + double number; + while ( true ) + { + in >> number; + if ( in.eof() )break; + this->sorted_vector_of_distances.push_back(number); + } + in.close(); +} + +template < typename F> +double Vector_distances_in_diagram::compute_scalar_product( const Vector_distances_in_diagram& second_vector )const +{ + double result = 0; + for ( size_t i = 0 ; i != std::min(this->sorted_vector_of_distances.size(),second_vector.sorted_vector_of_distances.size()) ; ++i ) + { + result += this->sorted_vector_of_distances[i] * second_vector.sorted_vector_of_distances[i]; + } + return result; +} + + + + + +}//namespace Gudhi_stat +}//namespace Gudhi + + +#endif // Vector_distances_in_diagram_H diff --git a/src/Gudhi_stat/include/gudhi/read_persistence_from_file.h b/src/Gudhi_stat/include/gudhi/read_persistence_from_file.h index 5042826c..39b3ca7b 100644 --- a/src/Gudhi_stat/include/gudhi/read_persistence_from_file.h +++ b/src/Gudhi_stat/include/gudhi/read_persistence_from_file.h @@ -34,7 +34,7 @@ namespace Gudhi { -namespace Gudhi_stat +namespace Persistence_representations { diff --git a/src/Gudhi_stat/include/gudhi/topological_process.h b/src/Gudhi_stat/include/gudhi/topological_process.h index 03edbb85..ee8478ed 100644 --- a/src/Gudhi_stat/include/gudhi/topological_process.h +++ b/src/Gudhi_stat/include/gudhi/topological_process.h @@ -25,19 +25,19 @@ //concretizations -#include -#include -#include -#include +#include +#include +#include +#include #include #include //extras -#include +#include namespace Gudhi { -namespace Gudhi_stat +namespace Persistence_representations { diff --git a/src/Gudhi_stat/test/persistence_heat_maps_test.cpp b/src/Gudhi_stat/test/persistence_heat_maps_test.cpp index fb094912..c7b36688 100644 --- a/src/Gudhi_stat/test/persistence_heat_maps_test.cpp +++ b/src/Gudhi_stat/test/persistence_heat_maps_test.cpp @@ -26,14 +26,14 @@ #define BOOST_TEST_MODULE "gudhi_stat" #include #include -#include +#include #include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; diff --git a/src/Gudhi_stat/test/persistence_intervals_test.cpp b/src/Gudhi_stat/test/persistence_intervals_test.cpp index 4fb73da1..dae270ed 100644 --- a/src/Gudhi_stat/test/persistence_intervals_test.cpp +++ b/src/Gudhi_stat/test/persistence_intervals_test.cpp @@ -26,14 +26,14 @@ #define BOOST_TEST_MODULE "gudhi_stat" #include #include -#include "gudhi/persistence_representations/Persistence_intervals.h" +#include "gudhi/Persistence_intervals.h" #include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; double epsilon = 0.0000005; diff --git a/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp b/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp index 54fb2b84..e935cb97 100644 --- a/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp +++ b/src/Gudhi_stat/test/persistence_lanscapes_on_grid_test.cpp @@ -26,14 +26,14 @@ #define BOOST_TEST_MODULE "gudhi_stat" #include #include -#include +#include #include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; double epsilon = 0.0000005; diff --git a/src/Gudhi_stat/test/persistence_lanscapes_test.cpp b/src/Gudhi_stat/test/persistence_lanscapes_test.cpp index 266be4de..684c50ff 100644 --- a/src/Gudhi_stat/test/persistence_lanscapes_test.cpp +++ b/src/Gudhi_stat/test/persistence_lanscapes_test.cpp @@ -26,14 +26,14 @@ #define BOOST_TEST_MODULE "gudhi_stat" #include #include -#include +#include #include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; double epsilon = 0.0000005; diff --git a/src/Gudhi_stat/test/read_persistence_from_file_test.cpp b/src/Gudhi_stat/test/read_persistence_from_file_test.cpp index c0e988bf..d4dc7f89 100644 --- a/src/Gudhi_stat/test/read_persistence_from_file_test.cpp +++ b/src/Gudhi_stat/test/read_persistence_from_file_test.cpp @@ -33,7 +33,7 @@ using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; diff --git a/src/Gudhi_stat/test/vector_representation_test.cpp b/src/Gudhi_stat/test/vector_representation_test.cpp index c3b15d05..2c1ef1f8 100644 --- a/src/Gudhi_stat/test/vector_representation_test.cpp +++ b/src/Gudhi_stat/test/vector_representation_test.cpp @@ -21,8 +21,8 @@ */ -#include -#include +#include +#include #include #define BOOST_TEST_DYN_LINK @@ -35,7 +35,7 @@ using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; diff --git a/src/Gudhi_stat/utilities/Hausdorff_subsampling.cpp b/src/Gudhi_stat/utilities/Hausdorff_subsampling.cpp index d716b3b8..44de1029 100644 --- a/src/Gudhi_stat/utilities/Hausdorff_subsampling.cpp +++ b/src/Gudhi_stat/utilities/Hausdorff_subsampling.cpp @@ -24,10 +24,11 @@ #include #include #include -#include +#include using namespace Gudhi; +using namespace Gudhi::Persistence_representations; using namespace Gudhi::Gudhi_stat; diff --git a/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp b/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp index 9bd6c89e..a2ca93a9 100644 --- a/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp +++ b/src/Gudhi_stat/utilities/Landscape_bootstrap.cpp @@ -23,9 +23,9 @@ //stat part: #include #include -#include +#include #include -#include +#include //persistence part: #include #include @@ -34,8 +34,9 @@ #include - -using Persistence_landscape = Gudhi::Gudhi_stat::Persistence_landscape; +using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; +using Persistence_landscape = Gudhi::Persistence_representations::Persistence_landscape; typedef int Vertex_handle; //typedef double Filtration_value; @@ -157,7 +158,7 @@ int main( int argc , char** argv ) std::cout << "Now we will read points from the file : " << filename << " and then perform " << number_of_repetitions_of_bootstrap << " times the bootstrap on it by choosing subsample of a size " << size_of_subsample << std::endl; - std::vector< std::vector< double > > points = Gudhi::Gudhi_stat::read_numbers_from_file_line_by_line( filename ); + std::vector< std::vector< double > > points = Gudhi::Persistence_representations::read_numbers_from_file_line_by_line( filename ); std::cout << "Read : " << points.size() << " points.\n"; diff --git a/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp b/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp index 7ee389f8..8949fba1 100644 --- a/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp +++ b/src/Gudhi_stat/utilities/Multiplicative_bootstrap.cpp @@ -24,10 +24,11 @@ #include #include #include -#include +#include using namespace Gudhi; using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; diff --git a/src/Gudhi_stat/utilities/permutation_test.cpp b/src/Gudhi_stat/utilities/permutation_test.cpp index 62cd3f10..e974b311 100644 --- a/src/Gudhi_stat/utilities/permutation_test.cpp +++ b/src/Gudhi_stat/utilities/permutation_test.cpp @@ -22,12 +22,13 @@ #include -#include +#include #include #include using namespace Gudhi; using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; int main( int argc , char** argv ) { diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp index 901f1a03..2d221d27 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/average_persistence_heat_maps.cpp @@ -22,12 +22,12 @@ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp index e4f5fca6..d3e6f322 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp @@ -21,12 +21,12 @@ */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp index cdeba692..edbf16c1 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp @@ -21,12 +21,12 @@ */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp index e99b829a..cac81495 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps.cpp @@ -22,12 +22,12 @@ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp index b98fc3f7..aa887c9c 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_arctan_of_their_persistence.cpp @@ -22,12 +22,12 @@ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp index 351cfd6f..aa13d786 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_distance_from_diagonal.cpp @@ -21,12 +21,12 @@ */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp index 59966855..46258329 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_persistence_heat_maps_weighted_by_squared_distance_from_diagonal.cpp @@ -21,12 +21,12 @@ */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp index dfab5cdb..6aab42f7 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/create_pssk.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp b/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp index 59b14fe8..5a4776ff 100644 --- a/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp +++ b/src/Gudhi_stat/utilities/persistence_heat_maps/plot_persistence_heat_map.cpp @@ -21,12 +21,12 @@ */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp b/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp index 291bd557..2e0d680f 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include #include @@ -32,7 +32,7 @@ using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; int main( int argc , char** argv ) diff --git a/src/Gudhi_stat/utilities/persistence_intervals/compute_bottleneck_distance.cpp b/src/Gudhi_stat/utilities/persistence_intervals/compute_bottleneck_distance.cpp index 43929695..19e49bbb 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/compute_bottleneck_distance.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/compute_bottleneck_distance.cpp @@ -20,13 +20,13 @@ * along with this program. If not, see . */ -#include +#include #include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp b/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp index 281902fe..c099befc 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/compute_number_of_dominant_intervals.cpp @@ -23,14 +23,14 @@ #include -#include +#include #include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; int main( int argc , char** argv ) diff --git a/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp b/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp index 994c6913..b2cbac70 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/plot_histogram_of_intervals_lengths.cpp @@ -23,14 +23,14 @@ #include -#include +#include #include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; int main( int argc , char** argv ) diff --git a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numbers.cpp b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numbers.cpp index 21ba06f4..e20f85c0 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numbers.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_Betti_numbers.cpp @@ -23,14 +23,14 @@ #include -#include +#include #include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; int main( int argc , char** argv ) diff --git a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp index 95c0cf1f..ed03459b 100644 --- a/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp +++ b/src/Gudhi_stat/utilities/persistence_intervals/plot_persistence_intervals.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include #include @@ -31,7 +31,7 @@ using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; double epsilon = 0.0000005; @@ -39,7 +39,7 @@ double epsilon = 0.0000005; int main( int argc , char** argv ) { - if ( argc != 2 ) + if ( argc < 2 ) { std::cout << "To run this program, please provide the name of a file with persistence diagram \n"; std::cout << "The second optional parameter of a program is the dimension of the persistence that is to be used. If your file contains only birth-death pairs, you can skip this parameter\n"; @@ -54,10 +54,7 @@ int main( int argc , char** argv ) if ( dim >= 0 ) { dimension = (unsigned)dim; - } - - - + } std::vector< std::pair< double , double > > intervals = read_persistence_intervals_in_one_dimension_from_file( argv[1] , dimension ); Persistence_intervals b( intervals ); b.plot( argv[1] ); diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp index 2a50acd8..1e0caa30 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/average_landscapes.cpp @@ -22,12 +22,12 @@ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp index 0b16ac26..85954cb2 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/compute_distance_of_landscapes.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp index 16a15174..02b729b2 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/compute_scalar_product_of_landscapes.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp index 040ccc95..b85c8644 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/create_landscapes.cpp @@ -20,11 +20,11 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp b/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp index aad8e147..b79a689d 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes/plot_landscapes.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp index d3851734..10d9e7ac 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp index 29c37159..4ecbd548 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp index 326e5587..342613b4 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp @@ -21,12 +21,12 @@ */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp index 6dbb70c4..a033362c 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp index b5687ea2..700b2f1f 100644 --- a/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp +++ b/src/Gudhi_stat/utilities/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp index 245676cd..126a0bf7 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/average_persistence_vectors.cpp @@ -21,12 +21,12 @@ */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp index feba2429..3320defd 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/compute_distance_of_persistence_vectors.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp index 775f4913..3f6e9c6c 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp index 7f0492c6..fd8b544c 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/create_persistence_vectors.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include diff --git a/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp b/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp index c642d22d..f52e6044 100644 --- a/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp +++ b/src/Gudhi_stat/utilities/persistence_vectors/plot_persistence_vectors.cpp @@ -20,12 +20,12 @@ * along with this program. If not, see . */ -#include +#include using namespace Gudhi; -using namespace Gudhi::Gudhi_stat; +using namespace Gudhi::Persistence_representations; #include #include -- cgit v1.2.3