Loading...
Searching...
No Matches
Persistence_landscape_on_grid.h
1/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2 * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3 * Author(s): Pawel Dlotko
4 *
5 * Copyright (C) 2016 Inria
6 *
7 * Modification(s):
8 * - YYYY/MM Author: Description of the modification
9 */
10
11#ifndef PERSISTENCE_LANDSCAPE_ON_GRID_H_
12#define PERSISTENCE_LANDSCAPE_ON_GRID_H_
13
14// gudhi include
15#include <gudhi/read_persistence_from_file.h>
16#include <gudhi/common_persistence_representations.h>
17
18// standard include
19#include <iostream>
20#include <vector>
21#include <limits>
22#include <fstream>
23#include <sstream>
24#include <algorithm>
25#include <cmath>
26#include <functional>
27#include <utility>
28#include <string>
29#include <cstdint>
30
31namespace Gudhi {
32namespace Persistence_representations {
33
34// pre declaration
36template <typename operation>
37Persistence_landscape_on_grid operation_on_pair_of_landscapes_on_grid(const Persistence_landscape_on_grid& land1,
39
57// this class implements the following concepts: Vectorized_topological_data, Topological_data_with_distances,
58// Real_valued_topological_data, Topological_data_with_averages, Topological_data_with_scalar_product
60 public:
65 this->set_up_numbers_of_functions_for_vectorization_and_projections_to_reals();
66 this->grid_min = this->grid_max = 0;
67 }
68
72 Persistence_landscape_on_grid(const std::vector<std::pair<double, double> >& p, double grid_min_, double grid_max_,
73 size_t number_of_points_);
74
79 Persistence_landscape_on_grid(const std::vector<std::pair<double, double> >& p, double grid_min_, double grid_max_,
80 size_t number_of_points_, unsigned number_of_levels_of_landscape);
81
90 Persistence_landscape_on_grid(const char* filename, double grid_min_, double grid_max_, size_t number_of_points_,
91 unsigned number_of_levels_of_landscape,
92 uint16_t dimension_ = std::numeric_limits<uint16_t>::max());
93
101 Persistence_landscape_on_grid(const char* filename, double grid_min_, double grid_max_, size_t number_of_points_,
102 uint16_t dimension_ = std::numeric_limits<uint16_t>::max());
103
111 Persistence_landscape_on_grid(const char* filename, size_t number_of_points, unsigned number_of_levels_of_landscape,
112 uint16_t dimension = std::numeric_limits<uint16_t>::max());
113
123 Persistence_landscape_on_grid(const char* filename, size_t number_of_points,
124 uint16_t dimension = std::numeric_limits<uint16_t>::max());
125
129 void load_landscape_from_file(const char* filename);
130
134 void print_to_file(const char* filename) const;
135
141 size_t maximal_level = this->number_of_nonzero_levels();
142 double result = 0;
143 for (size_t i = 0; i != maximal_level; ++i) {
144 result += this->compute_integral_of_landscape(i);
145 }
146 return result;
147 }
148
152 double compute_integral_of_landscape(size_t level) const {
153 bool dbg = false;
154 double result = 0;
155 double dx = (this->grid_max - this->grid_min) / static_cast<double>(this->values_of_landscapes.size() - 1);
156
157 if (dbg) {
158 std::clog << "this->grid_max : " << this->grid_max << std::endl;
159 std::clog << "this->grid_min : " << this->grid_min << std::endl;
160 std::clog << "this->values_of_landscapes.size() : " << this->values_of_landscapes.size() << std::endl;
161 getchar();
162 }
163
164 double previous_x = this->grid_min - dx;
165 double previous_y = 0;
166 for (size_t i = 0; i != this->values_of_landscapes.size(); ++i) {
167 double current_x = previous_x + dx;
168 double current_y = 0;
169 if (this->values_of_landscapes[i].size() > level) current_y = this->values_of_landscapes[i][level];
170
171 if (dbg) {
172 std::clog << "this->values_of_landscapes[i].size() : " << this->values_of_landscapes[i].size()
173 << " , level : " << level << std::endl;
174 if (this->values_of_landscapes[i].size() > level)
175 std::clog << "this->values_of_landscapes[i][level] : " << this->values_of_landscapes[i][level] << std::endl;
176 std::clog << "previous_y : " << previous_y << std::endl;
177 std::clog << "current_y : " << current_y << std::endl;
178 std::clog << "dx : " << dx << std::endl;
179 std::clog << "0.5*dx*( previous_y + current_y ); " << 0.5 * dx * (previous_y + current_y) << std::endl;
180 }
181
182 result += 0.5 * dx * (previous_y + current_y);
183 previous_x = current_x;
184 previous_y = current_y;
185 }
186 return result;
187 }
188
193 double compute_integral_of_landscape(double p) const {
194 size_t maximal_level = this->number_of_nonzero_levels();
195 double result = 0;
196 for (size_t i = 0; i != maximal_level; ++i) {
197 result += this->compute_integral_of_landscape(p, i);
198 }
199 return result;
200 }
201
206 double compute_integral_of_landscape(double p, size_t level) const {
207 bool dbg = false;
208
209 double result = 0;
210 double dx = (this->grid_max - this->grid_min) / static_cast<double>(this->values_of_landscapes.size() - 1);
211 double previous_x = this->grid_min;
212 double previous_y = 0;
213 if (this->values_of_landscapes[0].size() > level) previous_y = this->values_of_landscapes[0][level];
214
215 if (dbg) {
216 std::clog << "dx : " << dx << std::endl;
217 std::clog << "previous_x : " << previous_x << std::endl;
218 std::clog << "previous_y : " << previous_y << std::endl;
219 std::clog << "power : " << p << std::endl;
220 getchar();
221 }
222
223 for (size_t i = 0; i != this->values_of_landscapes.size(); ++i) {
224 double current_x = previous_x + dx;
225 double current_y = 0;
226 if (this->values_of_landscapes[i].size() > level) current_y = this->values_of_landscapes[i][level];
227
228 if (dbg) std::clog << "current_y : " << current_y << std::endl;
229
230 if (current_y == previous_y) continue;
231
232 std::pair<double, double> coef =
233 compute_parameters_of_a_line(std::make_pair(previous_x, previous_y), std::make_pair(current_x, current_y));
234 double a = coef.first;
235 double b = coef.second;
236
237 if (dbg) {
238 std::clog << "A line passing through points : (" << previous_x << "," << previous_y << ") and (" << current_x
239 << "," << current_y << ") is : " << a << "x+" << b << std::endl;
240 }
241
242 // In this interval, the landscape has a form f(x) = ax+b. We want to compute integral of (ax+b)^p = 1/a *
243 // (ax+b)^{p+1}/(p+1)
244 double value_to_add = 0;
245 if (a != 0) {
246 value_to_add = 1 / (a * (p + 1)) * (pow((a * current_x + b), p + 1) - pow((a * previous_x + b), p + 1));
247 } else {
248 value_to_add = (current_x - previous_x) * (pow(b, p));
249 }
250 result += value_to_add;
251 if (dbg) {
252 std::clog << "Increasing result by : " << value_to_add << std::endl;
253 std::clog << "result : " << result << std::endl;
254 getchar();
255 }
256 previous_x = current_x;
257 previous_y = current_y;
258 }
259 if (dbg) std::clog << "The total result is : " << result << std::endl;
260 return result;
261 }
262
268 friend std::ostream& operator<<(std::ostream& out, const Persistence_landscape_on_grid& land) {
269 double dx = (land.grid_max - land.grid_min) / static_cast<double>(land.values_of_landscapes.size() - 1);
270 double x = land.grid_min;
271 for (size_t i = 0; i != land.values_of_landscapes.size(); ++i) {
272 out << x << " : ";
273 for (size_t j = 0; j != land.values_of_landscapes[i].size(); ++j) {
274 out << land.values_of_landscapes[i][j] << " ";
275 }
276 out << std::endl;
277 x += dx;
278 }
279 return out;
280 }
281
282 template <typename oper>
283 friend Persistence_landscape_on_grid operation_on_pair_of_landscapes_on_grid(
285
291 double compute_value_at_a_given_point(unsigned level, double x) const {
292 bool dbg = false;
293 if ((x < this->grid_min) || (x > this->grid_max)) return 0;
294
295 // find a position of a vector closest to x:
296 double dx = (this->grid_max - this->grid_min) / static_cast<double>(this->values_of_landscapes.size() - 1);
297 size_t position = size_t((x - this->grid_min) / dx);
298
299 if (dbg) {
300 std::clog << "This is a procedure compute_value_at_a_given_point \n";
301 std::clog << "level : " << level << std::endl;
302 std::clog << "x : " << x << std::endl;
303 std::clog << "position : " << position << std::endl;
304 }
305 // check if we are not exactly in the grid point:
306 if (almost_equal(position * dx + this->grid_min, x)) {
307 if (this->values_of_landscapes[position].size() < level) {
308 return this->values_of_landscapes[position][level];
309 } else {
310 return 0;
311 }
312 }
313 // in the other case, approximate with a line:
314 std::pair<double, double> line;
315 if ((this->values_of_landscapes[position].size() > level) &&
316 (this->values_of_landscapes[position + 1].size() > level)) {
317 line = compute_parameters_of_a_line(
318 std::make_pair(position * dx + this->grid_min, this->values_of_landscapes[position][level]),
319 std::make_pair((position + 1) * dx + this->grid_min, this->values_of_landscapes[position + 1][level]));
320 } else {
321 if ((this->values_of_landscapes[position].size() > level) ||
322 (this->values_of_landscapes[position + 1].size() > level)) {
323 if ((this->values_of_landscapes[position].size() > level)) {
324 line = compute_parameters_of_a_line(
325 std::make_pair(position * dx + this->grid_min, this->values_of_landscapes[position][level]),
326 std::make_pair((position + 1) * dx + this->grid_min, 0));
327 } else {
328 line = compute_parameters_of_a_line(
329 std::make_pair(position * dx + this->grid_min, 0),
330 std::make_pair((position + 1) * dx + this->grid_min, this->values_of_landscapes[position + 1][level]));
331 }
332 } else {
333 return 0;
334 }
335 }
336 // compute the value of the linear function parametrized by line on a point x:
337 return line.first * x + line.second;
338 }
339
340 public:
345 const Persistence_landscape_on_grid& land2) {
346 return operation_on_pair_of_landscapes_on_grid<std::plus<double> >(land1, land2);
347 }
348
353 const Persistence_landscape_on_grid& land2) {
354 return operation_on_pair_of_landscapes_on_grid<std::minus<double> >(land1, land2);
355 }
356
361 const Persistence_landscape_on_grid& second) {
362 return add_two_landscapes(first, second);
363 }
364
369 const Persistence_landscape_on_grid& second) {
370 return subtract_two_landscapes(first, second);
371 }
372
377 return first.multiply_lanscape_by_real_number_not_overwrite(con);
378 }
379
384 return first.multiply_lanscape_by_real_number_not_overwrite(con);
385 }
386
387 friend bool check_if_defined_on_the_same_domain(const Persistence_landscape_on_grid& land1,
388 const Persistence_landscape_on_grid& land2) {
389 if (land1.values_of_landscapes.size() != land2.values_of_landscapes.size()) return false;
390 if (land1.grid_min != land2.grid_min) return false;
391 if (land1.grid_max != land2.grid_max) return false;
392 return true;
393 }
394
399 *this = *this + rhs;
400 return *this;
401 }
402
407 *this = *this - rhs;
408 return *this;
409 }
410
416 *this = *this * x;
417 return *this;
418 }
419
424 if (x == 0) throw("In operator /=, division by 0. Program terminated.");
425 *this = *this * (1 / x);
426 return *this;
427 }
428
433 bool dbg = true;
434 if (this->values_of_landscapes.size() != rhs.values_of_landscapes.size()) {
435 if (dbg) std::clog << "values_of_landscapes of incompatible sizes\n";
436 return false;
437 }
438 if (!almost_equal(this->grid_min, rhs.grid_min)) {
439 if (dbg) std::clog << "grid_min not equal\n";
440 return false;
441 }
442 if (!almost_equal(this->grid_max, rhs.grid_max)) {
443 if (dbg) std::clog << "grid_max not equal\n";
444 return false;
445 }
446 for (size_t i = 0; i != this->values_of_landscapes.size(); ++i) {
447 for (size_t aa = 0; aa != this->values_of_landscapes[i].size(); ++aa) {
448 if (!almost_equal(this->values_of_landscapes[i][aa], rhs.values_of_landscapes[i][aa])) {
449 if (dbg) {
450 std::clog << "Problem in the position : " << i << " of values_of_landscapes. \n";
451 std::clog << this->values_of_landscapes[i][aa] << " " << rhs.values_of_landscapes[i][aa] << std::endl;
452 }
453 return false;
454 }
455 }
456 }
457 return true;
458 }
459
463 bool operator!=(const Persistence_landscape_on_grid& rhs) const { return !((*this) == rhs); }
464
468 double compute_maximum() const {
469 // since the function can only be entirely positive or negative, the maximal value will be an extremal value in the
470 // arrays:
471 double max_value = -std::numeric_limits<double>::max();
472 for (size_t i = 0; i != this->values_of_landscapes.size(); ++i) {
473 if (this->values_of_landscapes[i].size()) {
474 if (this->values_of_landscapes[i][0] > max_value) max_value = this->values_of_landscapes[i][0];
475 if (this->values_of_landscapes[i][this->values_of_landscapes[i].size() - 1] > max_value)
476 max_value = this->values_of_landscapes[i][this->values_of_landscapes[i].size() - 1];
477 }
478 }
479 return max_value;
480 }
481
485 std::pair<double, double> compute_minimum_maximum() const {
486 // since the function can only be entirely positive or negative, the maximal value will be an extremal value in the
487 // arrays:
488 double max_value = -std::numeric_limits<double>::max();
489 double min_value = 0;
490 for (size_t i = 0; i != this->values_of_landscapes.size(); ++i) {
491 if (this->values_of_landscapes[i].size()) {
492 if (this->values_of_landscapes[i][0] > max_value) max_value = this->values_of_landscapes[i][0];
493 if (this->values_of_landscapes[i][this->values_of_landscapes[i].size() - 1] > max_value)
494 max_value = this->values_of_landscapes[i][this->values_of_landscapes[i].size() - 1];
495
496 if (this->values_of_landscapes[i][0] < min_value) min_value = this->values_of_landscapes[i][0];
497 if (this->values_of_landscapes[i][this->values_of_landscapes[i].size() - 1] < min_value)
498 min_value = this->values_of_landscapes[i][this->values_of_landscapes[i].size() - 1];
499 }
500 }
501 return std::make_pair(min_value, max_value);
502 }
503
508 std::pair<double, double> get_x_range(size_t level = 0) const {
509 return std::make_pair(this->grid_min, this->grid_max);
510 }
511
516 std::pair<double, double> get_y_range(size_t level = 0) const { return this->compute_minimum_maximum(); }
517
522 size_t result = 0;
523 for (size_t i = 0; i != this->values_of_landscapes.size(); ++i) {
524 if (this->values_of_landscapes[i].size() > result) result = this->values_of_landscapes[i].size();
525 }
526 return result;
527 }
528
532 double compute_norm_of_landscape(double i) const {
533 std::vector<std::pair<double, double> > p;
534 Persistence_landscape_on_grid l(p, this->grid_min, this->grid_max, this->values_of_landscapes.size() - 1);
535
536 if (i < std::numeric_limits<double>::max()) {
537 return compute_distance_of_landscapes_on_grid(*this, l, i);
538 } else {
540 }
541 }
542
546 double operator()(unsigned level, double x) const { return this->compute_value_at_a_given_point(level, x); }
547
552 const Persistence_landscape_on_grid& second);
553
560 void abs() {
561 for (size_t i = 0; i != this->values_of_landscapes.size(); ++i) {
562 for (size_t j = 0; j != this->values_of_landscapes[i].size(); ++j) {
563 this->values_of_landscapes[i][j] = std::abs(this->values_of_landscapes[i][j]);
564 }
565 }
566 }
567
571 size_t size() const { return this->number_of_nonzero_levels(); }
572
576 double find_max(unsigned lambda) const {
577 double max_value = -std::numeric_limits<double>::max();
578 for (size_t i = 0; i != this->values_of_landscapes.size(); ++i) {
579 if (this->values_of_landscapes[i].size() > lambda) {
580 if (this->values_of_landscapes[i][lambda] > max_value) max_value = this->values_of_landscapes[i][lambda];
581 }
582 }
583 return max_value;
584 }
585
591 if (!check_if_defined_on_the_same_domain(l1, l2))
592 throw "Landscapes are not defined on the same grid, the program will now terminate";
593 size_t maximal_level = l1.number_of_nonzero_levels();
594 double result = 0;
595 for (size_t i = 0; i != maximal_level; ++i) {
596 result += compute_inner_product(l1, l2, i);
597 }
598 return result;
599 }
600
605 size_t level) {
606 bool dbg = false;
607
608 if (!check_if_defined_on_the_same_domain(l1, l2))
609 throw "Landscapes are not defined on the same grid, the program will now terminate";
610 double result = 0;
611
612 double dx = (l1.grid_max - l1.grid_min) / static_cast<double>(l1.values_of_landscapes.size() - 1);
613
614 double previous_x = l1.grid_min - dx;
615 double previous_y_l1 = 0;
616 double previous_y_l2 = 0;
617 for (size_t i = 0; i != l1.values_of_landscapes.size(); ++i) {
618 if (dbg) std::clog << "i : " << i << std::endl;
619
620 double current_x = previous_x + dx;
621 double current_y_l1 = 0;
622 if (l1.values_of_landscapes[i].size() > level) current_y_l1 = l1.values_of_landscapes[i][level];
623
624 double current_y_l2 = 0;
625 if (l2.values_of_landscapes[i].size() > level) current_y_l2 = l2.values_of_landscapes[i][level];
626
627 if (dbg) {
628 std::clog << "previous_x : " << previous_x << std::endl;
629 std::clog << "previous_y_l1 : " << previous_y_l1 << std::endl;
630 std::clog << "current_y_l1 : " << current_y_l1 << std::endl;
631 std::clog << "previous_y_l2 : " << previous_y_l2 << std::endl;
632 std::clog << "current_y_l2 : " << current_y_l2 << std::endl;
633 }
634
635 std::pair<double, double> l1_coords = compute_parameters_of_a_line(std::make_pair(previous_x, previous_y_l1),
636 std::make_pair(current_x, current_y_l1));
637 std::pair<double, double> l2_coords = compute_parameters_of_a_line(std::make_pair(previous_x, previous_y_l2),
638 std::make_pair(current_x, current_y_l2));
639
640 // 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
641 // are a,b,c,d:
642 double a = l1_coords.first;
643 double b = l1_coords.second;
644
645 double c = l2_coords.first;
646 double d = l2_coords.second;
647
648 if (dbg) {
649 std::clog << "Here are the formulas for a line: \n";
650 std::clog << "a : " << a << std::endl;
651 std::clog << "b : " << b << std::endl;
652 std::clog << "c : " << c << std::endl;
653 std::clog << "d : " << d << std::endl;
654 }
655
656 // now, to compute the inner product in this interval we need to compute the integral of (ax+b)(cx+d) = acx^2 +
657 // (ad+bc)x + bd in the interval from previous_x to current_x:
658 // The integral is ac/3*x^3 + (ac+bd)/2*x^2 + bd*x
659
660 double added_value = (a * c / 3 * current_x * current_x * current_x +
661 (a * d + b * c) / 2 * current_x * current_x + b * d * current_x) -
662 (a * c / 3 * previous_x * previous_x * previous_x +
663 (a * d + b * c) / 2 * previous_x * previous_x + b * d * previous_x);
664
665 if (dbg) {
666 std::clog << "Value of the integral on the left end i.e. : " << previous_x << " is : "
667 << a * c / 3 * previous_x * previous_x * previous_x + (a * d + b * c) / 2 * previous_x * previous_x +
668 b * d * previous_x
669 << std::endl;
670 std::clog << "Value of the integral on the right end i.e. : " << current_x << " is "
671 << a * c / 3 * current_x * current_x * current_x + (a * d + b * c) / 2 * current_x * current_x +
672 b * d * current_x
673 << std::endl;
674 }
675
676 result += added_value;
677
678 if (dbg) {
679 std::clog << "added_value : " << added_value << std::endl;
680 std::clog << "result : " << result << std::endl;
681 getchar();
682 }
683
684 previous_x = current_x;
685 previous_y_l1 = current_y_l1;
686 previous_y_l2 = current_y_l2;
687 }
688 return result;
689 }
690
700 const Persistence_landscape_on_grid& second, double p) {
701 bool dbg = false;
702 // This is what we want to compute: (\int_{- \infty}^{+\infty}| first-second |^p)^(1/p). We will do it one step at a
703 // time:
704
705 if (dbg) {
706 std::clog << "first : " << first << std::endl;
707 std::clog << "second : " << second << std::endl;
708 getchar();
709 }
710
711 // first-second :
712 Persistence_landscape_on_grid lan = first - second;
713
714 if (dbg) {
715 std::clog << "Difference : " << lan << std::endl;
716 }
717
718 //| first-second |:
719 lan.abs();
720
721 if (dbg) {
722 std::clog << "Abs : " << lan << std::endl;
723 }
724
725 if (p < std::numeric_limits<double>::max()) {
726 // \int_{- \infty}^{+\infty}| first-second |^p
727 double result;
728 if (p != 1) {
729 if (dbg) {
730 std::clog << "p : " << p << std::endl;
731 getchar();
732 }
733 result = lan.compute_integral_of_landscape(p);
734 if (dbg) {
735 std::clog << "integral : " << result << std::endl;
736 getchar();
737 }
738 } else {
739 result = lan.compute_integral_of_landscape();
740 if (dbg) {
741 std::clog << "integral, without power : " << result << std::endl;
742 getchar();
743 }
744 }
745 // (\int_{- \infty}^{+\infty}| first-second |^p)^(1/p)
746 return pow(result, 1.0 / p);
747 } else {
748 // p == infty
749 return lan.compute_maximum();
750 }
751 }
752
753 // Functions that are needed for that class to implement the concept.
754
763 double project_to_R(int number_of_function) const {
764 return this->compute_integral_of_landscape((size_t)number_of_function);
765 }
766
771 size_t number_of_projections_to_R() const { return number_of_functions_for_projections_to_reals; }
772
777 std::vector<double> vectorize(int number_of_function) const {
778 // TODO(PD) think of something smarter over here
779 if ((number_of_function < 0) || ((size_t)number_of_function >= this->values_of_landscapes.size())) {
780 throw "Wrong number of function\n";
781 }
782 std::vector<double> v(this->values_of_landscapes.size());
783 for (size_t i = 0; i != this->values_of_landscapes.size(); ++i) {
784 v[i] = 0;
785 if (this->values_of_landscapes[i].size() > (size_t)number_of_function) {
786 v[i] = this->values_of_landscapes[i][number_of_function];
787 }
788 }
789 return v;
790 }
791
796 size_t number_of_vectorize_functions() const { return number_of_functions_for_vectorization; }
797
802 void compute_average(const std::vector<Persistence_landscape_on_grid*>& to_average) {
803 bool dbg = false;
804 // After execution of this procedure, the average is supposed to be in the current object. To make sure that this is
805 // the case, we need to do some cleaning first.
806 this->values_of_landscapes.clear();
807 this->grid_min = this->grid_max = 0;
808
809 // if there is nothing to average, then the average is a zero landscape.
810 if (to_average.size() == 0) return;
811
812 // now we need to check if the grids in all objects of to_average are the same:
813 for (size_t i = 0; i != to_average.size(); ++i) {
814 if (!check_if_defined_on_the_same_domain(*(to_average[0]), *(to_average[i])))
815 throw "Two grids are not compatible";
816 }
817
818 this->values_of_landscapes = std::vector<std::vector<double> >((to_average[0])->values_of_landscapes.size());
819 this->grid_min = (to_average[0])->grid_min;
820 this->grid_max = (to_average[0])->grid_max;
821
822 if (dbg) {
823 std::clog << "Computations of average. The data from the current landscape have been cleared. We are ready to do "
824 "the computations. \n";
825 }
826
827 // for every point in the grid:
828 for (size_t grid_point = 0; grid_point != (to_average[0])->values_of_landscapes.size(); ++grid_point) {
829 // set up a vector of the correct size:
830 size_t maximal_size_of_vector = 0;
831 for (size_t land_no = 0; land_no != to_average.size(); ++land_no) {
832 if ((to_average[land_no])->values_of_landscapes[grid_point].size() > maximal_size_of_vector)
833 maximal_size_of_vector = (to_average[land_no])->values_of_landscapes[grid_point].size();
834 }
835 this->values_of_landscapes[grid_point] = std::vector<double>(maximal_size_of_vector);
836
837 if (dbg) {
838 std::clog << "We are considering the point : " << grid_point
839 << " of the grid. In this point, there are at most : " << maximal_size_of_vector
840 << " nonzero landscape functions \n";
841 }
842
843 // and compute an arithmetic average:
844 for (size_t land_no = 0; land_no != to_average.size(); ++land_no) {
845 // summing:
846 for (size_t i = 0; i != (to_average[land_no])->values_of_landscapes[grid_point].size(); ++i) {
847 // compute the average in a smarter way.
848 this->values_of_landscapes[grid_point][i] += (to_average[land_no])->values_of_landscapes[grid_point][i];
849 }
850 }
851 // normalizing:
852 for (size_t i = 0; i != this->values_of_landscapes[grid_point].size(); ++i) {
853 this->values_of_landscapes[grid_point][i] /= static_cast<double>(to_average.size());
854 }
855 }
856 } // compute_average
857
864 double distance(const Persistence_landscape_on_grid& second, double power = 1) const {
865 if (power < std::numeric_limits<double>::max()) {
866 return compute_distance_of_landscapes_on_grid(*this, second, power);
867 } else {
868 return compute_max_norm_distance_of_landscapes(*this, second);
869 }
870 }
871
878 return compute_inner_product((*this), second);
879 }
880
881 // end of implementation of functions needed for concepts.
882
886 std::vector<std::vector<double> > output_for_visualization() const { return this->values_of_landscapes; }
887
897 void plot(const char* filename, size_t from_, size_t to_) const {
898 this->plot(filename, std::numeric_limits<double>::max(), std::numeric_limits<double>::max(),
899 std::numeric_limits<double>::max(), std::numeric_limits<double>::max(), from_, to_);
900 }
901
906 void plot(const char* filename, double min_x = std::numeric_limits<double>::max(),
907 double max_x = std::numeric_limits<double>::max(), double min_y = std::numeric_limits<double>::max(),
908 double max_y = std::numeric_limits<double>::max(), size_t from_ = std::numeric_limits<size_t>::max(),
909 size_t to_ = std::numeric_limits<size_t>::max()) const;
910
911 protected:
912 double grid_min;
913 double grid_max;
914 std::vector<std::vector<double> > values_of_landscapes;
915 size_t number_of_functions_for_vectorization;
916 size_t number_of_functions_for_projections_to_reals;
917
918 void set_up_numbers_of_functions_for_vectorization_and_projections_to_reals() {
919 // warning, this function can be only called after filling in the values_of_landscapes vector.
920 this->number_of_functions_for_vectorization = this->values_of_landscapes.size();
921 this->number_of_functions_for_projections_to_reals = this->values_of_landscapes.size();
922 }
923 void set_up_values_of_landscapes(const std::vector<std::pair<double, double> >& p, double grid_min_, double grid_max_,
924 size_t number_of_points_,
925 unsigned number_of_levels = std::numeric_limits<unsigned>::max());
926 Persistence_landscape_on_grid multiply_lanscape_by_real_number_not_overwrite(double x) const;
927};
928
929void Persistence_landscape_on_grid::set_up_values_of_landscapes(const std::vector<std::pair<double, double> >& p,
930 double grid_min_, double grid_max_,
931 size_t number_of_points_, unsigned number_of_levels) {
932 bool dbg = false;
933 if (dbg) {
934 std::clog << "Here is the procedure : set_up_values_of_landscapes. The parameters are : grid_min_ : " << grid_min_
935 << ", grid_max_ : " << grid_max_ << ", number_of_points_ : " << number_of_points_
936 << ", number_of_levels: " << number_of_levels << std::endl;
937 std::clog << "Here are the intervals at our disposal : \n";
938 for (size_t i = 0; i != p.size(); ++i) {
939 std::clog << p[i].first << " , " << p[i].second << std::endl;
940 }
941 }
942
943 if ((grid_min_ == std::numeric_limits<double>::max()) || (grid_max_ == std::numeric_limits<double>::max())) {
944 // in this case, we need to find grid_min_ and grid_min_ based on the data.
945 double min = std::numeric_limits<double>::max();
946 double max = std::numeric_limits<double>::min();
947 for (size_t i = 0; i != p.size(); ++i) {
948 if (p[i].first < min) min = p[i].first;
949 if (p[i].second > max) max = p[i].second;
950 }
951 if (grid_min_ == std::numeric_limits<double>::max()) {
952 grid_min_ = min;
953 } else {
954 // in this case grid_max_ == std::numeric_limits<double>::max()
955 grid_max_ = max;
956 }
957 }
958
959 // if number_of_levels == std::numeric_limits<size_t>::max(), then we will have all the nonzero values of landscapes,
960 // and will store them in a vector
961 // if number_of_levels != std::numeric_limits<size_t>::max(), then we will use those vectors as heaps.
962 this->values_of_landscapes = std::vector<std::vector<double> >(number_of_points_ + 1);
963
964 this->grid_min = grid_min_;
965 this->grid_max = grid_max_;
966
967 if (grid_max_ <= grid_min_) {
968 throw "Wrong parameters of grid_min and grid_max given to the procedure. The program will now terminate.\n";
969 }
970
971 double dx = (grid_max_ - grid_min_) / static_cast<double>(number_of_points_);
972 // for every interval in the diagram:
973 for (size_t int_no = 0; int_no != p.size(); ++int_no) {
974 size_t grid_interval_begin = (p[int_no].first - grid_min_) / dx;
975 size_t grid_interval_end = (p[int_no].second - grid_min_) / dx;
976 size_t grid_interval_midpoint = (size_t)(0.5 * (grid_interval_begin + grid_interval_end));
977
978 if (dbg) {
979 std::clog << "Considering an interval : " << p[int_no].first << "," << p[int_no].second << std::endl;
980
981 std::clog << "grid_interval_begin : " << grid_interval_begin << std::endl;
982 std::clog << "grid_interval_end : " << grid_interval_end << std::endl;
983 std::clog << "grid_interval_midpoint : " << grid_interval_midpoint << std::endl;
984 }
985
986 double landscape_value = dx;
987 for (size_t i = grid_interval_begin + 1; i < grid_interval_midpoint; ++i) {
988 if (dbg) {
989 std::clog << "Adding landscape value (going up) for a point : " << i << " equal : " << landscape_value
990 << std::endl;
991 }
992 if (number_of_levels != std::numeric_limits<unsigned>::max()) {
993 // we have a heap of no more that number_of_levels values.
994 // Note that if we are using heaps, we want to know the shortest distance in the heap.
995 // This is achieved by putting -distance to the heap.
996 if (this->values_of_landscapes[i].size() >= number_of_levels) {
997 // in this case, the full heap is build, and we need to check if the landscape_value is not larger than the
998 // smallest element in the heap.
999 if (-landscape_value < this->values_of_landscapes[i].front()) {
1000 // if it is, we remove the largest value in the heap, and move on.
1001 std::pop_heap(this->values_of_landscapes[i].begin(), this->values_of_landscapes[i].end());
1002 this->values_of_landscapes[i][this->values_of_landscapes[i].size() - 1] = -landscape_value;
1003 std::push_heap(this->values_of_landscapes[i].begin(), this->values_of_landscapes[i].end());
1004 }
1005 } else {
1006 // in this case we are still filling in the array.
1007 this->values_of_landscapes[i].push_back(-landscape_value);
1008 if (this->values_of_landscapes[i].size() == number_of_levels - 1) {
1009 // this->values_of_landscapes[i].size() == number_of_levels
1010 // in this case we need to create the heap.
1011 std::make_heap(this->values_of_landscapes[i].begin(), this->values_of_landscapes[i].end());
1012 }
1013 }
1014 } else {
1015 // we have vector of all values
1016 this->values_of_landscapes[i].push_back(landscape_value);
1017 }
1018 landscape_value += dx;
1019 }
1020 for (size_t i = grid_interval_midpoint; i <= grid_interval_end; ++i) {
1021 if (landscape_value > 0) {
1022 if (number_of_levels != std::numeric_limits<unsigned>::max()) {
1023 // we have a heap of no more that number_of_levels values
1024 if (this->values_of_landscapes[i].size() >= number_of_levels) {
1025 // in this case, the full heap is build, and we need to check if the landscape_value is not larger than the
1026 // smallest element in the heap.
1027 if (-landscape_value < this->values_of_landscapes[i].front()) {
1028 // if it is, we remove the largest value in the heap, and move on.
1029 std::pop_heap(this->values_of_landscapes[i].begin(), this->values_of_landscapes[i].end());
1030 this->values_of_landscapes[i][this->values_of_landscapes[i].size() - 1] = -landscape_value;
1031 std::push_heap(this->values_of_landscapes[i].begin(), this->values_of_landscapes[i].end());
1032 }
1033 } else {
1034 // in this case we are still filling in the array.
1035 this->values_of_landscapes[i].push_back(-landscape_value);
1036 if (this->values_of_landscapes[i].size() == number_of_levels - 1) {
1037 // this->values_of_landscapes[i].size() == number_of_levels
1038 // in this case we need to create the heap.
1039 std::make_heap(this->values_of_landscapes[i].begin(), this->values_of_landscapes[i].end());
1040 }
1041 }
1042 } else {
1043 this->values_of_landscapes[i].push_back(landscape_value);
1044 }
1045
1046 if (dbg) {
1047 std::clog << "Adding landscape value (going down) for a point : " << i << " equal : " << landscape_value
1048 << std::endl;
1049 }
1050 }
1051 landscape_value -= dx;
1052 }
1053 }
1054
1055 if (number_of_levels != std::numeric_limits<unsigned>::max()) {
1056 // in this case, vectors are used as heaps. And, since we want to have the smallest element at the top of
1057 // each heap, we store minus distances. To get if right at the end, we need to multiply each value
1058 // in the heap by -1 to get real vector of distances.
1059 for (size_t pt = 0; pt != this->values_of_landscapes.size(); ++pt) {
1060 for (size_t j = 0; j != this->values_of_landscapes[pt].size(); ++j) {
1061 this->values_of_landscapes[pt][j] *= -1;
1062 }
1063 }
1064 }
1065
1066 // and now we need to sort the values:
1067 for (size_t pt = 0; pt != this->values_of_landscapes.size(); ++pt) {
1068 std::sort(this->values_of_landscapes[pt].begin(), this->values_of_landscapes[pt].end(), std::greater<double>());
1069 }
1070} // set_up_values_of_landscapes
1071
1072Persistence_landscape_on_grid::Persistence_landscape_on_grid(const std::vector<std::pair<double, double> >& p,
1073 double grid_min_, double grid_max_,
1074 size_t number_of_points_) {
1075 this->set_up_values_of_landscapes(p, grid_min_, grid_max_, number_of_points_);
1076} // Persistence_landscape_on_grid
1077
1078Persistence_landscape_on_grid::Persistence_landscape_on_grid(const std::vector<std::pair<double, double> >& p,
1079 double grid_min_, double grid_max_,
1080 size_t number_of_points_,
1081 unsigned number_of_levels_of_landscape) {
1082 this->set_up_values_of_landscapes(p, grid_min_, grid_max_, number_of_points_, number_of_levels_of_landscape);
1083}
1084
1085Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename, double grid_min_, double grid_max_,
1086 size_t number_of_points_, uint16_t dimension) {
1087 std::vector<std::pair<double, double> > p;
1088 if (dimension == std::numeric_limits<uint16_t>::max()) {
1089 p = read_persistence_intervals_in_one_dimension_from_file(filename);
1090 } else {
1091 p = read_persistence_intervals_in_one_dimension_from_file(filename, dimension);
1092 }
1093 this->set_up_values_of_landscapes(p, grid_min_, grid_max_, number_of_points_);
1094}
1095
1096Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename, double grid_min_, double grid_max_,
1097 size_t number_of_points_,
1098 unsigned number_of_levels_of_landscape,
1099 uint16_t dimension) {
1100 std::vector<std::pair<double, double> > p;
1101 if (dimension == std::numeric_limits<uint16_t>::max()) {
1102 p = read_persistence_intervals_in_one_dimension_from_file(filename);
1103 } else {
1104 p = read_persistence_intervals_in_one_dimension_from_file(filename, dimension);
1105 }
1106 this->set_up_values_of_landscapes(p, grid_min_, grid_max_, number_of_points_, number_of_levels_of_landscape);
1107}
1108
1109Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename, size_t number_of_points_,
1110 uint16_t dimension) {
1111 std::vector<std::pair<double, double> > p;
1112 if (dimension == std::numeric_limits<uint16_t>::max()) {
1113 p = read_persistence_intervals_in_one_dimension_from_file(filename);
1114 } else {
1115 p = read_persistence_intervals_in_one_dimension_from_file(filename, dimension);
1116 }
1117 double grid_min_ = std::numeric_limits<double>::max();
1118 double grid_max_ = -std::numeric_limits<double>::max();
1119 for (size_t i = 0; i != p.size(); ++i) {
1120 if (p[i].first < grid_min_) grid_min_ = p[i].first;
1121 if (p[i].second > grid_max_) grid_max_ = p[i].second;
1122 }
1123 this->set_up_values_of_landscapes(p, grid_min_, grid_max_, number_of_points_);
1124}
1125
1126Persistence_landscape_on_grid::Persistence_landscape_on_grid(const char* filename, size_t number_of_points_,
1127 unsigned number_of_levels_of_landscape,
1128 uint16_t dimension) {
1129 std::vector<std::pair<double, double> > p;
1130 if (dimension == std::numeric_limits<uint16_t>::max()) {
1131 p = read_persistence_intervals_in_one_dimension_from_file(filename);
1132 } else {
1133 p = read_persistence_intervals_in_one_dimension_from_file(filename, dimension);
1134 }
1135 double grid_min_ = std::numeric_limits<double>::max();
1136 double grid_max_ = -std::numeric_limits<double>::max();
1137 for (size_t i = 0; i != p.size(); ++i) {
1138 if (p[i].first < grid_min_) grid_min_ = p[i].first;
1139 if (p[i].second > grid_max_) grid_max_ = p[i].second;
1140 }
1141 this->set_up_values_of_landscapes(p, grid_min_, grid_max_, number_of_points_, number_of_levels_of_landscape);
1142}
1143
1145 std::ifstream in;
1146 in.open(filename);
1147 // check if the file exist.
1148 if (!in.good()) {
1149 std::cerr << "The file : " << filename << " do not exist. The program will now terminate \n";
1150 throw "The persistence landscape file do not exist. The program will now terminate \n";
1151 }
1152
1153 size_t number_of_points_in_the_grid = 0;
1154 in >> this->grid_min >> this->grid_max >> number_of_points_in_the_grid;
1155
1156 std::vector<std::vector<double> > v(number_of_points_in_the_grid);
1157 std::string line;
1158 std::getline(in, line);
1159 double number;
1160 for (size_t i = 0; i != number_of_points_in_the_grid; ++i) {
1161 // read a line of a file and convert it to a vector.
1162 std::vector<double> vv;
1163 std::getline(in, line);
1164 std::istringstream stream(line);
1165 while (stream >> number) {
1166 vv.push_back(number);
1167 }
1168 v[i] = vv;
1169 }
1170 this->values_of_landscapes = v;
1171 in.close();
1172}
1173
1174void Persistence_landscape_on_grid::print_to_file(const char* filename) const {
1175 std::ofstream out;
1176 out.open(filename);
1177
1178 // first we store the parameters of the grid:
1179 out << grid_min << std::endl << grid_max << std::endl << this->values_of_landscapes.size() << std::endl;
1180
1181 // and now in the following lines, the values of this->values_of_landscapes for the following arguments:
1182 for (size_t i = 0; i != this->values_of_landscapes.size(); ++i) {
1183 for (size_t j = 0; j != this->values_of_landscapes[i].size(); ++j) {
1184 out << this->values_of_landscapes[i][j] << " ";
1185 }
1186 out << std::endl;
1187 }
1188
1189 out.close();
1190}
1191
1192void Persistence_landscape_on_grid::plot(const char* filename, double min_x, double max_x, double min_y, double max_y,
1193 size_t from_, size_t to_) const {
1194 // this program create a gnuplot script file that allows to plot persistence diagram.
1195 std::ofstream out;
1196
1197 std::ostringstream gnuplot_script;
1198 gnuplot_script << filename << "_GnuplotScript";
1199 out.open(gnuplot_script.str().c_str());
1200
1201 if (min_x == max_x) {
1202 std::pair<double, double> min_max = compute_minimum_maximum();
1203 out << "set xrange [" << this->grid_min << " : " << this->grid_max << "]" << std::endl;
1204 out << "set yrange [" << min_max.first << " : " << min_max.second << "]" << std::endl;
1205 } else {
1206 out << "set xrange [" << min_x << " : " << max_x << "]" << std::endl;
1207 out << "set yrange [" << min_y << " : " << max_y << "]" << std::endl;
1208 }
1209
1211 double dx = (this->grid_max - this->grid_min) / static_cast<double>(this->values_of_landscapes.size() - 1);
1212
1213 size_t from = 0;
1214 if (from_ != std::numeric_limits<size_t>::max()) {
1215 if (from_ < number_of_nonzero_levels) {
1216 from = from_;
1217 } else {
1218 return;
1219 }
1220 }
1221 size_t to = number_of_nonzero_levels;
1222 if (to_ != std::numeric_limits<size_t>::max()) {
1223 if (to_ < number_of_nonzero_levels) {
1224 to = to_;
1225 }
1226 }
1227
1228 out << "plot ";
1229 for (size_t lambda = from; lambda != to; ++lambda) {
1230 out << " '-' using 1:2 notitle with lp";
1231 if (lambda + 1 != to) {
1232 out << ", \\";
1233 }
1234 out << std::endl;
1235 }
1236
1237 for (size_t lambda = from; lambda != to; ++lambda) {
1238 double point = this->grid_min;
1239 for (size_t i = 0; i != this->values_of_landscapes.size(); ++i) {
1240 double value = 0;
1241 if (this->values_of_landscapes[i].size() > lambda) {
1242 value = this->values_of_landscapes[i][lambda];
1243 }
1244 out << point << " " << value << std::endl;
1245 point += dx;
1246 }
1247 out << "EOF" << std::endl;
1248 }
1249 std::clog << "To visualize, install gnuplot and type the command: gnuplot -persist -e \"load \'"
1250 << gnuplot_script.str().c_str() << "\'\"" << std::endl;
1251}
1252
1253template <typename T>
1254Persistence_landscape_on_grid operation_on_pair_of_landscapes_on_grid(const Persistence_landscape_on_grid& land1,
1255 const Persistence_landscape_on_grid& land2) {
1256 // first we need to check if the domains are the same:
1257 if (!check_if_defined_on_the_same_domain(land1, land2)) throw "Two grids are not compatible";
1258
1259 T oper;
1261 result.values_of_landscapes = std::vector<std::vector<double> >(land1.values_of_landscapes.size());
1262 result.grid_min = land1.grid_min;
1263 result.grid_max = land1.grid_max;
1264
1265 // now we perform the operations:
1266 for (size_t grid_point = 0; grid_point != land1.values_of_landscapes.size(); ++grid_point) {
1267 result.values_of_landscapes[grid_point] = std::vector<double>(
1268 std::max(land1.values_of_landscapes[grid_point].size(), land2.values_of_landscapes[grid_point].size()));
1269 for (size_t lambda = 0; lambda != std::max(land1.values_of_landscapes[grid_point].size(),
1270 land2.values_of_landscapes[grid_point].size());
1271 ++lambda) {
1272 double value1 = 0;
1273 double value2 = 0;
1274 if (lambda < land1.values_of_landscapes[grid_point].size())
1275 value1 = land1.values_of_landscapes[grid_point][lambda];
1276 if (lambda < land2.values_of_landscapes[grid_point].size())
1277 value2 = land2.values_of_landscapes[grid_point][lambda];
1278 result.values_of_landscapes[grid_point][lambda] = oper(value1, value2);
1279 }
1280 }
1281
1282 return result;
1283}
1284
1285Persistence_landscape_on_grid Persistence_landscape_on_grid::multiply_lanscape_by_real_number_not_overwrite(
1286 double x) const {
1288 result.values_of_landscapes = std::vector<std::vector<double> >(this->values_of_landscapes.size());
1289 result.grid_min = this->grid_min;
1290 result.grid_max = this->grid_max;
1291
1292 for (size_t grid_point = 0; grid_point != this->values_of_landscapes.size(); ++grid_point) {
1293 result.values_of_landscapes[grid_point] = std::vector<double>(this->values_of_landscapes[grid_point].size());
1294 for (size_t i = 0; i != this->values_of_landscapes[grid_point].size(); ++i) {
1295 result.values_of_landscapes[grid_point][i] = x * this->values_of_landscapes[grid_point][i];
1296 }
1297 }
1298
1299 return result;
1300}
1301
1302double compute_max_norm_distance_of_landscapes(const Persistence_landscape_on_grid& first,
1303 const Persistence_landscape_on_grid& second) {
1304 double result = 0;
1305
1306 // first we need to check if first and second is defined on the same domain"
1307 if (!check_if_defined_on_the_same_domain(first, second)) throw "Two grids are not compatible";
1308
1309 for (size_t i = 0; i != first.values_of_landscapes.size(); ++i) {
1310 for (size_t j = 0; j != std::min(first.values_of_landscapes[i].size(), second.values_of_landscapes[i].size());
1311 ++j) {
1312 if (result < abs(first.values_of_landscapes[i][j] - second.values_of_landscapes[i][j])) {
1313 result = abs(first.values_of_landscapes[i][j] - second.values_of_landscapes[i][j]);
1314 }
1315 }
1316 if (first.values_of_landscapes[i].size() ==
1317 std::min(first.values_of_landscapes[i].size(), second.values_of_landscapes[i].size())) {
1318 for (size_t j = first.values_of_landscapes[i].size(); j != second.values_of_landscapes[i].size(); ++j) {
1319 if (result < second.values_of_landscapes[i][j]) result = second.values_of_landscapes[i][j];
1320 }
1321 }
1322 if (second.values_of_landscapes[i].size() ==
1323 std::min(first.values_of_landscapes[i].size(), second.values_of_landscapes[i].size())) {
1324 for (size_t j = second.values_of_landscapes[i].size(); j != first.values_of_landscapes[i].size(); ++j) {
1325 if (result < first.values_of_landscapes[i][j]) result = first.values_of_landscapes[i][j];
1326 }
1327 }
1328 }
1329 return result;
1330}
1331
1332} // namespace Persistence_representations
1333} // namespace Gudhi
1334
1335#endif // PERSISTENCE_LANDSCAPE_ON_GRID_H_
A class implementing persistence landscapes by approximating them on a collection of grid points.
Definition: Persistence_landscape_on_grid.h:59
double compute_integral_of_landscape(double p, size_t level) const
Definition: Persistence_landscape_on_grid.h:206
void print_to_file(const char *filename) const
Definition: Persistence_landscape_on_grid.h:1174
bool operator!=(const Persistence_landscape_on_grid &rhs) const
Definition: Persistence_landscape_on_grid.h:463
friend Persistence_landscape_on_grid operator-(const Persistence_landscape_on_grid &first, const Persistence_landscape_on_grid &second)
Definition: Persistence_landscape_on_grid.h:368
double compute_integral_of_landscape() const
Definition: Persistence_landscape_on_grid.h:140
size_t size() const
Definition: Persistence_landscape_on_grid.h:571
std::pair< double, double > get_y_range(size_t level=0) const
Definition: Persistence_landscape_on_grid.h:516
std::vector< std::vector< double > > output_for_visualization() const
Definition: Persistence_landscape_on_grid.h:886
void load_landscape_from_file(const char *filename)
Definition: Persistence_landscape_on_grid.h:1144
Persistence_landscape_on_grid operator-=(const Persistence_landscape_on_grid &rhs)
Definition: Persistence_landscape_on_grid.h:406
std::vector< double > vectorize(int number_of_function) const
Definition: Persistence_landscape_on_grid.h:777
std::pair< double, double > compute_minimum_maximum() const
Definition: Persistence_landscape_on_grid.h:485
size_t number_of_projections_to_R() const
Definition: Persistence_landscape_on_grid.h:771
friend double compute_inner_product(const Persistence_landscape_on_grid &l1, const Persistence_landscape_on_grid &l2, size_t level)
Definition: Persistence_landscape_on_grid.h:604
Persistence_landscape_on_grid operator+=(const Persistence_landscape_on_grid &rhs)
Definition: Persistence_landscape_on_grid.h:398
double compute_scalar_product(const Persistence_landscape_on_grid &second)
Definition: Persistence_landscape_on_grid.h:877
Persistence_landscape_on_grid operator/=(double x)
Definition: Persistence_landscape_on_grid.h:423
friend Persistence_landscape_on_grid operator*(double con, const Persistence_landscape_on_grid &first)
Definition: Persistence_landscape_on_grid.h:383
friend Persistence_landscape_on_grid operator+(const Persistence_landscape_on_grid &first, const Persistence_landscape_on_grid &second)
Definition: Persistence_landscape_on_grid.h:360
friend double compute_max_norm_distance_of_landscapes(const Persistence_landscape_on_grid &first, const Persistence_landscape_on_grid &second)
Definition: Persistence_landscape_on_grid.h:1302
double find_max(unsigned lambda) const
Definition: Persistence_landscape_on_grid.h:576
double distance(const Persistence_landscape_on_grid &second, double power=1) const
Definition: Persistence_landscape_on_grid.h:864
std::pair< double, double > get_x_range(size_t level=0) const
Definition: Persistence_landscape_on_grid.h:508
friend double compute_inner_product(const Persistence_landscape_on_grid &l1, const Persistence_landscape_on_grid &l2)
Definition: Persistence_landscape_on_grid.h:589
friend Persistence_landscape_on_grid operator*(const Persistence_landscape_on_grid &first, double con)
Definition: Persistence_landscape_on_grid.h:376
friend Persistence_landscape_on_grid subtract_two_landscapes(const Persistence_landscape_on_grid &land1, const Persistence_landscape_on_grid &land2)
Definition: Persistence_landscape_on_grid.h:352
double compute_maximum() const
Definition: Persistence_landscape_on_grid.h:468
size_t number_of_nonzero_levels() const
Definition: Persistence_landscape_on_grid.h:521
void compute_average(const std::vector< Persistence_landscape_on_grid * > &to_average)
Definition: Persistence_landscape_on_grid.h:802
double compute_value_at_a_given_point(unsigned level, double x) const
Definition: Persistence_landscape_on_grid.h:291
double compute_integral_of_landscape(size_t level) const
Definition: Persistence_landscape_on_grid.h:152
bool operator==(const Persistence_landscape_on_grid &rhs) const
Definition: Persistence_landscape_on_grid.h:432
double project_to_R(int number_of_function) const
Definition: Persistence_landscape_on_grid.h:763
double compute_integral_of_landscape(double p) const
Definition: Persistence_landscape_on_grid.h:193
void plot(const char *filename, size_t from_, size_t to_) const
Definition: Persistence_landscape_on_grid.h:897
void abs()
Definition: Persistence_landscape_on_grid.h:560
friend std::ostream & operator<<(std::ostream &out, const Persistence_landscape_on_grid &land)
Definition: Persistence_landscape_on_grid.h:268
double compute_norm_of_landscape(double i) const
Definition: Persistence_landscape_on_grid.h:532
size_t number_of_vectorize_functions() const
Definition: Persistence_landscape_on_grid.h:796
friend double compute_distance_of_landscapes_on_grid(const Persistence_landscape_on_grid &first, const Persistence_landscape_on_grid &second, double p)
Definition: Persistence_landscape_on_grid.h:699
Persistence_landscape_on_grid operator*=(double x)
Definition: Persistence_landscape_on_grid.h:415
double operator()(unsigned level, double x) const
Definition: Persistence_landscape_on_grid.h:546
Persistence_landscape_on_grid()
Definition: Persistence_landscape_on_grid.h:64
friend Persistence_landscape_on_grid add_two_landscapes(const Persistence_landscape_on_grid &land1, const Persistence_landscape_on_grid &land2)
Definition: Persistence_landscape_on_grid.h:344