summaryrefslogtreecommitdiff
path: root/src/Persistence_representations/include/gudhi/Persistence_landscape_on_grid.h
diff options
context:
space:
mode:
authorvrouvrea <vrouvrea@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2017-05-30 15:52:00 +0000
committervrouvrea <vrouvrea@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2017-05-30 15:52:00 +0000
commit9d1a526de85694b5f075bb88dbd7097a40abf10a (patch)
treebbcd0cef32610d2f5e9c0209b48c58f73fbf379a /src/Persistence_representations/include/gudhi/Persistence_landscape_on_grid.h
parent2bcb3d7cb47ce71803f2464cc822346ed2e1b039 (diff)
clang format all sources
git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/persistence_representation_integration@2477 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 326d664483d6700f82be824f79a0bf5c082b4945
Diffstat (limited to 'src/Persistence_representations/include/gudhi/Persistence_landscape_on_grid.h')
-rw-r--r--src/Persistence_representations/include/gudhi/Persistence_landscape_on_grid.h2596
1 files changed, 1234 insertions, 1362 deletions
diff --git a/src/Persistence_representations/include/gudhi/Persistence_landscape_on_grid.h b/src/Persistence_representations/include/gudhi/Persistence_landscape_on_grid.h
index d663b543..64385846 100644
--- a/src/Persistence_representations/include/gudhi/Persistence_landscape_on_grid.h
+++ b/src/Persistence_representations/include/gudhi/Persistence_landscape_on_grid.h
@@ -10,7 +10,7 @@
* 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
@@ -24,8 +24,7 @@
#ifndef PERSISTENCE_LANDSCAPE_ON_GRID_H_
#define PERSISTENCE_LANDSCAPE_ON_GRID_H_
-
-//standard include
+// standard include
#include <iostream>
#include <vector>
#include <limits>
@@ -37,23 +36,19 @@
#include <functional>
#include <functional>
-
-//gudhi include
+// gudhi include
#include <gudhi/read_persistence_from_file.h>
#include <gudhi/common_persistence_representations.h>
-
-
-namespace Gudhi
-{
-namespace Persistence_representations
-{
+namespace Gudhi {
+namespace Persistence_representations {
// pre declaration
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 );
+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);
/**
* \class Persistence_landscape_on_grid Persistence_landscape_on_grid.h gudhi/Persistence_landscape_on_grid.h
@@ -72,1408 +67,1285 @@ Persistence_landscape_on_grid operation_on_pair_of_landscapes_on_grid( const Per
* 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, resolution 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<unsigned short>::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, resolution 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<unsigned short>::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 resolution of a grid and the number of landscape
- * functions to be created. The remaining 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<unsigned short>::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 resolution 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<unsigned>::max().
- * The remaining parameters are calculated based on data.
- **/
- Persistence_landscape_on_grid(const char* filename , size_t number_of_points , unsigned short dimension = std::numeric_limits<unsigned short>::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<double,double> 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 << "result : " << 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.
+// 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, resolution 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<unsigned short>::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, resolution 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<unsigned short>::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 resolution of a grid and the number of landscape
+ * functions to be created. The remaining 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<unsigned short>::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 resolution 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<unsigned>::max().
+ * The remaining parameters are calculated based on data.
**/
- 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 << "position : " << position << std::endl;
- }
- //check if we are not exactly 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<double,double> 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<double> >(land1,land2);
+ Persistence_landscape_on_grid(const char* filename, size_t number_of_points,
+ unsigned short dimension = std::numeric_limits<unsigned short>::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);
}
-
- /**
- *\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<double> >(land1,land2);
+ 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();
}
- /**
- * 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 );
+ 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;
}
-
- /**
- * 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 );
+ 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();
}
- /**
- * An operator * that allows multiplication 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);
+ 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<double, double> 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 << "result : " << 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 << "position : " << position << std::endl;
+ }
+ // check if we are not exactly 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<double, double> 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<double> >(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<double> >(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 multiplication 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 multiplication 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 persistence landscape.
+ **/
+ Persistence_landscape_on_grid operator+=(const Persistence_landscape_on_grid& rhs) {
+ *this = *this + rhs;
+ return *this;
+ }
+
+ /**
+ * Operator -=. The second parameter is persistence landscape.
+ **/
+ 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 incompatible 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<double>::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<double, double> 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<double>::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);
+ }
+
+ /**
+ * 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(); }
+
+ /**
+ * 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<double>::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);
+
+ /**
+ * Function to compute absolute value of a PL function. The representation of persistence landscapes allow to store
+ *general PL-function. When computing distance between 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(); }
+
+ /**
+ * Compute maximal value of lambda-level landscape.
+ **/
+ double find_max(unsigned lambda) const {
+ double max_value = -std::numeric_limits<double>::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<double, double> 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<double, double> 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 integral 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 i.e. : " << 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 intersecting. 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;
- /**
- * An operator * that allows multiplication 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);
+ if (dbg) {
+ std::cerr << "Difference : " << lan << std::endl;
}
- 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 persistence landscape.
- **/
- Persistence_landscape_on_grid operator += ( const Persistence_landscape_on_grid& rhs )
- {
- *this = *this + rhs;
- return *this;
+ //| first-second |:
+ lan.abs();
+
+ if (dbg) {
+ std::cerr << "Abs : " << lan << std::endl;
}
- /**
- * Operator -=. The second parameter is persistence landscape.
- **/
- Persistence_landscape_on_grid operator -= ( const Persistence_landscape_on_grid& rhs )
- {
- *this = *this - rhs;
- return *this;
+ 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, without 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.
+ * At the moment this function is not tested, since it is quite likely to be changed in the future. Given this, when
+ *using it, keep in mind that it
+ * will be most likely changed in the next versions.
+ **/
+ 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<double> 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<double> 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 landscape. 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 average, 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<double> >((to_average[0])->values_of_landscapes.size());
+ this->grid_min = (to_average[0])->grid_min;
+ this->grid_max = (to_average[0])->grid_max;
- /**
- * 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;
+ if (dbg) {
+ std::cerr << "Computations of average. The data from the current landscape have been cleared. We are ready to do "
+ "the computations. \n";
}
- /**
- * 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;
+ // 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<double>(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 arithmetic 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 function is 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<double>::max()
+ **/
+ double distance(const Persistence_landscape_on_grid& second, double power = 1) const {
+ if (power < std::numeric_limits<double>::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 function is 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 landscapes. It can be used for visualization
+ **/
+ 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 default values for min and
+ *max are std::numeric_limits<double>::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<double>::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<double>::max(), std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max(), std::numeric_limits<double>::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<double>::max(),
+ double max_x = std::numeric_limits<double>::max(), double min_y = std::numeric_limits<double>::max(),
+ double max_y = std::numeric_limits<double>::max(), size_t from_ = std::numeric_limits<size_t>::max(),
+ size_t to_ = std::numeric_limits<size_t>::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<unsigned>::max());
+ Persistence_landscape_on_grid multiply_lanscape_by_real_number_not_overwrite(double x) const;
+};
- /**
- * 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 incompatible 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<double>::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;
+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;
}
-
- /**
- * Computations of minimum and maximum value of landscape.
- **/
- std::pair<double,double> 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<double>::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);
+ }
+
+ if ((grid_min_ == std::numeric_limits<double>::max()) || (grid_max_ == std::numeric_limits<double>::max())) {
+ // in this case, we need to find grid_min_ and grid_min_ based on the data.
+ double min = std::numeric_limits<double>::max();
+ double max = std::numeric_limits<double>::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;
}
-
- /**
- * 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 );
- }
-
- /**
- * 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();
- }
-
- /**
- * 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<double>::max() )
- {
- return compute_distance_of_landscapes_on_grid(*this,l,i);
- }
- else
- {
- return compute_max_norm_distance_of_landscapes(*this,l);
- }
+ if (grid_min_ == std::numeric_limits<double>::max()) {
+ grid_min_ = min;
+ } else {
+ // in this case grid_max_ == std::numeric_limits<double>::max()
+ grid_max_ = max;
}
+ }
- /**
- * 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 );
-
-
-
- /**
- * Function to compute absolute value of a PL function. The representation of persistence landscapes allow to store general PL-function. When computing distance between 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(); }
-
- /**
- * Compute maximal value of lambda-level landscape.
- **/
- double find_max( unsigned lambda )const
- {
- double max_value = -std::numeric_limits<double>::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<double,double> 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<double,double> 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 integral 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 i.e. : " << 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 intersecting. 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, without 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.
- * At the moment this function is not tested, since it is quite likely to be changed in the future. Given this, when using it, keep in mind that it
- * will be most likely changed in the next versions.
- **/
- 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<double> 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<double> 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 landscape. 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 average, 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<double> >( (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<double>( 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 arithmetic 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 function is 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<double>::max()
- **/
- double distance( const Persistence_landscape_on_grid& second , double power = 1 )const
- {
- if ( power < std::numeric_limits<double>::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 function is 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 landscapes. It can be used for visualization
- **/
- 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 default values for min and max are std::numeric_limits<double>::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<double>::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<double>::max() , std::numeric_limits<double>::max(), std::numeric_limits<double>::max() , std::numeric_limits<double>::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<double>::max() , double max_x = std::numeric_limits<double>::max() , double min_y = std::numeric_limits<double>::max() , double max_y = std::numeric_limits<double>::max() , size_t from_ = std::numeric_limits<size_t>::max(), size_t to_= std::numeric_limits<size_t>::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<unsigned>::max() );
- Persistence_landscape_on_grid multiply_lanscape_by_real_number_not_overwrite( double x )const;
-};
+ // if number_of_levels == std::numeric_limits<size_t>::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<size_t>::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_;
-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<double>::max()) || (grid_max_ == std::numeric_limits<double>::max()) )
- {
- //in this case, we need to find grid_min_ and grid_min_ based on the data.
- double min = std::numeric_limits<double>::max();
- double max = std::numeric_limits<double>::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<double>::max() )
- {
- grid_min_ = min;
- }
- else
- {
- //in this case grid_max_ == std::numeric_limits<double>::max()
- grid_max_ = max;
- }
- }
-
- //if number_of_levels == std::numeric_limits<size_t>::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<size_t>::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<unsigned>::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 heap.
- 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 heap.
- 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 << "Adding 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 minus 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 )
- {
- for ( size_t j = 0 ; j != this->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<double>() );
- }
-}//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 );
-}
+ 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));
-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<unsigned short>::max() )
- {
- p = read_persistence_intervals_in_one_dimension_from_file( filename );
+ 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;
}
- else
- {
- p = read_persistence_intervals_in_one_dimension_from_file( filename , dimension );
+
+ 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<unsigned>::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 heap.
+ 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;
}
- this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ );
-}
+ 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 heap.
+ 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);
+ }
-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<unsigned short>::max() )
- {
- p = read_persistence_intervals_in_one_dimension_from_file( filename );
+ if (dbg) {
+ std::cerr << "Adding landscape value (going down) for a point : " << i << " equal : " << landscape_value
+ << std::endl;
+ }
+ }
+ landscape_value -= dx;
}
- else
- {
- p = read_persistence_intervals_in_one_dimension_from_file( filename , dimension );
+ }
+
+ 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 minus 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) {
+ for (size_t j = 0; j != this->values_of_landscapes[pt].size(); ++j) {
+ this->values_of_landscapes[pt][j] *= -1;
+ }
}
- this->set_up_values_of_landscapes( p , grid_min_ , grid_max_ , number_of_points_ , number_of_levels_of_landscape );
+ }
+
+ // 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<double>());
+ }
+} // 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 , size_t number_of_points_ , unsigned short dimension )
-{
- std::vector< std::pair< double , double > > p;
- if ( dimension == std::numeric_limits<unsigned short>::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<double>::max();
- double grid_max_ = -std::numeric_limits<double>::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, 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<unsigned short>::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 , 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<unsigned short>::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<double>::max();
- double grid_max_ = -std::numeric_limits<double>::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 );
+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<unsigned short>::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<unsigned short>::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<double>::max();
+ double grid_max_ = -std::numeric_limits<double>::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_);
+}
-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::istringstream stream(line);
- while (stream >> number)
- {
- vv.push_back(number);
- }
- v[i] = vv;
- }
- this->values_of_landscapes = v;
- in.close();
+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<unsigned short>::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<double>::max();
+ double grid_max_ = -std::numeric_limits<double>::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::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::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::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::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<double,double> 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<size_t>::max() )
- {
- if ( from_ < number_of_nonzero_levels )
- {
- from = from_;
- }
- else
- {
- return;
- }
- }
- size_t to = number_of_nonzero_levels;
- if ( to_ != std::numeric_limits<size_t>::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;
+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] << " ";
}
-
- 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;
+ 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<double, double> 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<size_t>::max()) {
+ if (from_ < number_of_nonzero_levels) {
+ from = from_;
+ } else {
+ return;
+ }
+ }
+ size_t to = number_of_nonzero_levels;
+ if (to_ != std::numeric_limits<size_t>::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;
}
- std::cout << "Gnuplot script to visualize persistence diagram written to the file: " << nameStr << ". Type load '" << nameStr << "' in gnuplot to visualize." << 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;
}
-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 perform 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;
+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 perform 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;
+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;
+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 Persistence_representations
-}//namespace Gudhi
+} // namespace Persistence_representations
+} // namespace Gudhi
#endif // PERSISTENCE_LANDSCAPE_ON_GRID_H_