Persistence_graph.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: Francois Godi
4 *
5 * Copyright (C) 2015 Inria
6 *
7 * Modification(s):
8 * - YYYY/MM Author: Description of the modification
9 */
10
11#ifndef PERSISTENCE_GRAPH_H_
12#define PERSISTENCE_GRAPH_H_
13
14#include <gudhi/Internal_point.h>
15
16#ifdef GUDHI_USE_TBB
17#include <tbb/parallel_sort.h>
18#endif
19
20#include <vector>
21#include <algorithm>
22#include <limits> // for numeric_limits
23#include <cmath>
24
25namespace Gudhi {
26
27namespace persistence_diagram {
28
34class Persistence_graph {
35public:
37 template<typename Persistence_diagram1, typename Persistence_diagram2>
38 Persistence_graph(const Persistence_diagram1& diag1, const Persistence_diagram2& diag2, double e);
40 bool on_the_u_diagonal(int u_point_index) const;
42 bool on_the_v_diagonal(int v_point_index) const;
44 int corresponding_point_in_u(int v_point_index) const;
46 int corresponding_point_in_v(int u_point_index) const;
48 double distance(int u_point_index, int v_point_index) const;
50 int size() const;
52 double bottleneck_alive() const;
54 std::vector<double> sorted_distances() const;
56 double max_dist_to_diagonal() const;
58 Internal_point get_u_point(int u_point_index) const;
60 Internal_point get_v_point(int v_point_index) const;
61
62private:
63 std::vector<Internal_point> u;
64 std::vector<Internal_point> v;
65 double b_alive;
66};
67
68template<typename Persistence_diagram1, typename Persistence_diagram2>
69Persistence_graph::Persistence_graph(const Persistence_diagram1 &diag1,
70 const Persistence_diagram2 &diag2, double e)
71 : u(), v(), b_alive(0.) {
72 std::vector<double> u_alive;
73 std::vector<double> v_alive;
74 std::vector<double> u_nalive;
75 std::vector<double> v_nalive;
76 int u_inf = 0;
77 int v_inf = 0;
78 double inf = std::numeric_limits<double>::infinity();
79 double neginf = -inf;
80
81 for (auto it = std::begin(diag1); it != std::end(diag1); ++it) {
82 if (std::get<0>(*it) != inf && std::get<1>(*it) != neginf){
83 if (std::get<0>(*it) == neginf && std::get<1>(*it) == inf)
84 u_inf++;
85 else if (std::get<0>(*it) == neginf)
86 u_nalive.push_back(std::get<1>(*it));
87 else if (std::get<1>(*it) == inf)
88 u_alive.push_back(std::get<0>(*it));
89 else if (std::get<1>(*it) - std::get<0>(*it) > e)
90 u.push_back(Internal_point(std::get<0>(*it), std::get<1>(*it), u.size()));
91 }
92 }
93 for (auto it = std::begin(diag2); it != std::end(diag2); ++it) {
94 if (std::get<0>(*it) != inf && std::get<1>(*it) != neginf){
95 if (std::get<0>(*it) == neginf && std::get<1>(*it) == inf)
96 v_inf++;
97 else if (std::get<0>(*it) == neginf)
98 v_nalive.push_back(std::get<1>(*it));
99 else if (std::get<1>(*it) == inf)
100 v_alive.push_back(std::get<0>(*it));
101 else if (std::get<1>(*it) - std::get<0>(*it) > e)
102 v.push_back(Internal_point(std::get<0>(*it), std::get<1>(*it), v.size()));
103 }
104 }
105 if (u.size() < v.size())
106 swap(u, v);
107
108 if (u_alive.size() != v_alive.size() || u_nalive.size() != v_nalive.size() || u_inf != v_inf) {
109 b_alive = std::numeric_limits<double>::infinity();
110 } else {
111 std::sort(u_alive.begin(), u_alive.end());
112 std::sort(v_alive.begin(), v_alive.end());
113 std::sort(u_nalive.begin(), u_nalive.end());
114 std::sort(v_nalive.begin(), v_nalive.end());
115 for (auto it_u = u_alive.cbegin(), it_v = v_alive.cbegin(); it_u != u_alive.cend(); ++it_u, ++it_v)
116 b_alive = (std::max)(b_alive, std::fabs(*it_u - *it_v));
117 for (auto it_u = u_nalive.cbegin(), it_v = v_nalive.cbegin(); it_u != u_nalive.cend(); ++it_u, ++it_v)
118 b_alive = (std::max)(b_alive, std::fabs(*it_u - *it_v));
119 }
120}
121
122inline bool Persistence_graph::on_the_u_diagonal(int u_point_index) const {
123 return u_point_index >= static_cast<int> (u.size());
124}
125
126inline bool Persistence_graph::on_the_v_diagonal(int v_point_index) const {
127 return v_point_index >= static_cast<int> (v.size());
128}
129
130inline int Persistence_graph::corresponding_point_in_u(int v_point_index) const {
131 return on_the_v_diagonal(v_point_index) ?
132 v_point_index - static_cast<int> (v.size()) : v_point_index + static_cast<int> (u.size());
133}
134
135inline int Persistence_graph::corresponding_point_in_v(int u_point_index) const {
136 return on_the_u_diagonal(u_point_index) ?
137 u_point_index - static_cast<int> (u.size()) : u_point_index + static_cast<int> (v.size());
138}
139
140inline double Persistence_graph::distance(int u_point_index, int v_point_index) const {
141 if (on_the_u_diagonal(u_point_index) && on_the_v_diagonal(v_point_index))
142 return 0.;
143 Internal_point p_u = get_u_point(u_point_index);
144 Internal_point p_v = get_v_point(v_point_index);
145 return (std::max)(std::fabs(p_u.x() - p_v.x()), std::fabs(p_u.y() - p_v.y()));
146}
147
148inline int Persistence_graph::size() const {
149 return static_cast<int> (u.size() + v.size());
150}
151
152inline double Persistence_graph::bottleneck_alive() const {
153 return b_alive;
154}
155
156inline std::vector<double> Persistence_graph::sorted_distances() const {
157 std::vector<double> distances;
158 distances.push_back(0.); // for empty diagrams
159 for (int u_point_index = 0; u_point_index < size(); ++u_point_index) {
160 distances.push_back(distance(u_point_index, corresponding_point_in_v(u_point_index)));
161 for (int v_point_index = 0; v_point_index < size(); ++v_point_index)
162 distances.push_back(distance(u_point_index, v_point_index));
163 }
164#ifdef GUDHI_USE_TBB
165 tbb::parallel_sort(distances.begin(), distances.end());
166#else
167 std::sort(distances.begin(), distances.end());
168#endif
169 return distances;
170}
171
172inline Internal_point Persistence_graph::get_u_point(int u_point_index) const {
173 if (!on_the_u_diagonal(u_point_index))
174 return u.at(u_point_index);
175 Internal_point projector = v.at(corresponding_point_in_v(u_point_index));
176 double m = (projector.x() + projector.y()) / 2.;
177 return Internal_point(m, m, u_point_index);
178}
179
180inline Internal_point Persistence_graph::get_v_point(int v_point_index) const {
181 if (!on_the_v_diagonal(v_point_index))
182 return v.at(v_point_index);
183 Internal_point projector = u.at(corresponding_point_in_u(v_point_index));
184 double m = (projector.x() + projector.y()) / 2.;
185 return Internal_point(m, m, v_point_index);
186}
187
188inline double Persistence_graph::max_dist_to_diagonal() const {
189 double max = 0.;
190 for (auto& p : u)
191 max = (std::max)(max, p.y() - p.x());
192 for (auto& p : v)
193 max = (std::max)(max, p.y() - p.x());
194 return max / 2;
195}
196
197} // namespace persistence_diagram
198
199} // namespace Gudhi
200
201#endif // PERSISTENCE_GRAPH_H_
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14