TTK
Loading...
Searching...
No Matches
PairCellsWithOracle.cpp
Go to the documentation of this file.
2#include <ripser.h>
3
4#include <numeric>
5
7 const PointCloud &points,
8 MultidimensionalDiagram const &oracle,
9 bool distanceMatrix,
10 bool parallelSort)
11 : n_(distanceMatrix ? (1 + sqrt(1 + 8 * points[0].size())) / 2
12 : points.size()),
13 parallelSort_(parallelSort), oracle_(oracle) {
14 // inherited from Debug: prefix will be printed at the beginning of every msg
15 this->setDebugMsgPrefix("PairCellsWithOracle");
16
17 if(distanceMatrix)
18 compressedDM_ = points[0];
19 else {
20 const unsigned dim = points[0].size();
21 for(int i = 1; i < n_; ++i) {
22 for(int j = 0; j < i; ++j) {
23 double s = 0.;
24 for(unsigned d = 0; d < dim; ++d)
25 s += (points[i][d] - points[j][d]) * (points[i][d] - points[j][d]);
26 compressedDM_.push_back(sqrt(s));
27 }
28 }
29 }
30}
31
33 float *data,
34 int n,
35 int dim,
36 MultidimensionalDiagram const &oracle,
37 bool parallelSort)
38 : n_(n), parallelSort_(parallelSort), oracle_(oracle) {
39 // inherited from Debug: prefix will be printed at the beginning of every msg
40 this->setDebugMsgPrefix("PairCellsWithOracle");
41
42 for(int i = 1; i < n_; ++i) {
43 for(int j = 0; j < i; ++j) {
44 double s = 0.;
45 for(int d = 0; d < dim; ++d)
46 s += (data[dim * i + d] - data[dim * j + d])
47 * (data[dim * i + d] - data[dim * j + d]);
48 compressedDM_.push_back(sqrt(s));
49 }
50 }
51}
52
55 double threshold,
56 bool distanceMatrix) {
57 ripser::ripser(points, oracle, threshold, 1, distanceMatrix, false, false);
58
59 std::sort(
60 oracle[1].begin(), oracle[1].end(),
61 [](const PersistencePair &x, const PersistencePair &y) {
62 if(x.second.second == y.second.second) { // reverse co-lexicographic order
63 // to match Ripser's choice
64 Simplex const &t1 = x.second.first;
65 Simplex const &t2 = y.second.first;
66 return !std::lexicographical_compare(
67 t1.rbegin(), t1.rend(), t2.rbegin(), t2.rend());
68 } else
69 return x.second.second < y.second.second;
70 });
71}
72
74 Timer tm{};
75 for(auto const &[b, d] : oracle_[1]) {
76 if(d.second < inf)
77 bound_ = std::max(bound_, d.second);
78 }
79 printMsg("Upper bound from the PD oracle: " + std::to_string(bound_));
80 initializeWithBound();
81 printMsg("Initialized (#p=" + std::to_string(n_)
82 + ", #e=" + std::to_string(nEdges_) + ")",
83 0, tm.getElapsedTime());
84 pairCellsWithOracle();
85 printMsg("Complete", 1, tm.getElapsedTime());
86}
87
88void ttk::rpd::PairCellsWithOracle::initializeWithBound() {
89 // construct edges
90 graph_.resize(n_);
91 for(id_t i = 0; i < n_; ++i) {
92 for(id_t j = i + 1; j < n_; ++j) {
93 if(DM(i, j) <= bound_) {
94 edgeToIndex_[{i, j}] = edges_.size();
95 edges_.push_back({{i, j}, DM(i, j)});
96 graph_[i].insert(j);
97 graph_[j].insert(i);
98 }
99 }
100 }
101 nEdges_ = edges_.size();
102
103 // sort edges
104 edgesIndices_.resize(nEdges_);
105 edgesOrder_.resize(nEdges_);
106 edgesPartner_.resize(nEdges_, -1);
107 std::iota(edgesIndices_.begin(), edgesIndices_.end(), 0);
108 if(parallelSort_)
109 TTK_PSORT(globalThreadNumber_, edgesIndices_.begin(), edgesIndices_.end(),
110 [&](id_t i, id_t j) { return edges_[i] < edges_[j]; })
111 else
112 std::sort(edgesIndices_.begin(), edgesIndices_.end(),
113 [&](id_t i, id_t j) { return edges_[i] < edges_[j]; });
114 for(unsigned i = 0; i < edgesIndices_.size(); ++i)
115 edgesOrder_[edgesIndices_[i]] = i;
116}
117
118void ttk::rpd::PairCellsWithOracle::pairCellsWithOracle() {
119 for(const auto &[birth, death] : oracle_[1]) {
120 if(death.second < inf) {
121 const id_t e_id = edgeToIndex_[{birth.first[0], birth.first[1]}];
122 const id_t t_id = triangles_.size();
123 triangles_.push_back(
124 {{death.first[0], death.first[1], death.first[2]}, death.second});
125 boundaries_.push_back({edgeToIndex_[{death.first[0], death.first[1]}],
126 edgeToIndex_[{death.first[1], death.first[2]}],
127 edgeToIndex_[{death.first[0], death.first[2]}]});
128 cascadeEdges_.emplace_back();
129 trianglesPartner_.push_back(e_id);
130 edgesPartner_[e_id] = t_id;
131 eliminateBoundaryWithOracle(t_id, e_id);
132 }
133 }
134}
135
136void ttk::rpd::PairCellsWithOracle::eliminateBoundaryWithOracle(id_t t_id,
137 id_t e_id) {
138 BoundaryContainer bc(boundaries_[t_id], nEdges_);
139 id_t youngest_id = -1;
140 while(youngest_id != e_id) {
141 youngest_id = *std::max_element(
142 boundaries_[t_id].begin(), boundaries_[t_id].end(),
143 [&](id_t i, id_t j) { return edgesOrder_[i] < edgesOrder_[j]; });
144 if(youngest_id == e_id)
145 return;
146 cascadeEdges_[t_id].push_back(youngest_id);
147 if(edgesPartner_[youngest_id] != -1)
148 bc.exclusiveAddBoundary(boundaries_[edgesPartner_[youngest_id]]);
149 else {
150 const auto &[i, j] = edges_[youngest_id].e;
151 const double d = edges_[youngest_id].d;
152 for(id_t const &k : graph_[i]) {
153 if(DM(i, k) < d && DM(j, k) < d) {
154 bc.exclusiveAddBoundary({youngest_id, edgeToIndex_[std::minmax(i, k)],
155 edgeToIndex_[std::minmax(j, k)]});
156 break;
157 }
158 }
159 }
160 }
161}
162
164 std::vector<Generator1> &generators) const {
165 for(unsigned i = 0; i < triangles_.size(); ++i) {
166 EdgeSet boundary;
167 for(id_t const &e_id : boundaries_[i])
168 boundary.emplace_back(edges_[e_id].e);
169 generators.emplace_back(
170 boundary,
171 std::make_pair(edges_[trianglesPartner_[i]].d, triangles_[i].d));
172 }
173}
174
175void ttk::rpd::PairCellsWithOracle::getCascades(std::vector<Cascade> &cascades,
176 EdgeSets3 &critical) const {
177 fillRNG(critical);
178 for(auto const &c : cascadeEdges_) {
179 critical[DEATH1].emplace_back(edges_[c[0]].e);
180 Cascade cascade;
181 for(id_t const &e_id : c)
182 cascade.emplace_back(edges_[e_id].e);
183 cascades.push_back(cascade);
184 }
185}
186
188 fillRNG(critical);
189 std::set<id_t> cascadeSet;
190 for(auto const &c : cascadeEdges_) {
191 critical[DEATH1].emplace_back(edges_[c[0]].e);
192 for(unsigned i = 1; i < c.size(); ++i)
193 cascadeSet.insert(c[i]);
194 }
195 for(const id_t &e_id : cascadeSet)
196 critical[CASC1].emplace_back(edges_[e_id].e);
197}
#define TTK_PSORT(NTHREADS,...)
Parallel sort macro.
Definition OpenMP.h:46
void setDebugMsgPrefix(const std::string &prefix)
Definition Debug.h:364
void getGenerators(std::vector< Generator1 > &generators) const
PairCellsWithOracle(const PointCloud &points, MultidimensionalDiagram const &oracle, bool distanceMatrix=false, bool parallelSort=false)
void getCascades(std::vector< Cascade > &cascades, EdgeSets3 &critical) const
static void callOracle(const PointCloud &points, MultidimensionalDiagram &oracle, double threshold=inf, bool distanceMatrix=false)
void ripser(std::vector< std::vector< value_t > > points, PersistenceType &ph, value_t threshold, index_t dim_max, bool distanceMatrix, bool criticalEdgesOnly=true, bool infinitePairs=true, coefficient_t modulus=2)
Definition ripser.cpp:1136
std::array< EdgeSet, 4 > EdgeSets4
std::pair< FiltratedSimplex, FiltratedSimplex > PersistencePair
constexpr value_t inf
std::vector< std::vector< value_t > > PointCloud
std::vector< Edge > EdgeSet
std::vector< Diagram > MultidimensionalDiagram
std::array< EdgeSet, 3 > EdgeSets3
std::vector< id_t > Simplex
COMMON_EXPORTS int globalThreadNumber_
Definition BaseClass.cpp:6
T end(std::pair< T, T > &p)
Definition ripser.cpp:503
T begin(std::pair< T, T > &p)
Definition ripser.cpp:499
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)