TTK
Loading...
Searching...
No Matches
PathCompression.h
Go to the documentation of this file.
1
27
28#pragma once
29
30// base code includes
31#include <Triangulation.h>
32
33using ttk::SimplexId;
34
35namespace ttk {
36 namespace pcp {
37#ifdef TTK_ENABLE_64BIT_IDS
46 constexpr unsigned long long int getHash(const unsigned long long int a,
47 const unsigned long long int b) {
48 return (a * b + (a * a) + (b * b) + (a * a * a) * (b * b * b))
49 % ULONG_LONG_MAX;
50 }
51#else
60 constexpr unsigned int getHash(const unsigned int a, const unsigned int b) {
61 return (a * b + (a * a) + (b * b) + (a * a * a) * (b * b * b)) % UINT_MAX;
62 }
63#endif
64 } // namespace pcp
65 class PathCompression : public virtual Debug {
66 public:
68
75
82
96 template <typename triangulationType>
97 inline int execute(OutputSegmentation &outSegmentation,
98 const SimplexId *const orderArray,
99 const triangulationType &triangulation);
100
117 template <typename triangulationType>
118 int computePathCompression(SimplexId *const ascSegmentation,
119 SimplexId *const dscSegmentation,
120 const SimplexId *const orderArray,
121 const triangulationType &triangulation) const;
122
140 template <typename triangulationType>
142 SimplexId *const segmentation,
143 const bool computeAscending,
144 const SimplexId *const orderArray,
145 const triangulationType &triangulation) const;
146
151 inline void setComputeSegmentation(const bool doAscending,
152 const bool doDescending,
153 const bool doMorseSmale) {
154 this->ComputeAscendingSegmentation = doAscending;
155 this->ComputeDescendingSegmentation = doDescending;
156 this->ComputeMSSegmentationHash = doMorseSmale;
157 }
171 template <typename triangulationType>
172 int computeMSHash(SimplexId *const morseSmaleSegmentation,
173 const SimplexId *const ascSegmentation,
174 const SimplexId *const dscSegmentation,
175 const triangulationType &triangulation) const;
176
177 protected:
178 // Compute ascending segmentation?
180
181 // Compute descending segmentation?
183
184 // Compute Morse-Smale segmentation hash?
186 };
187} // namespace ttk
188
189template <typename triangulationType>
191 const SimplexId *const orderArray,
192 const triangulationType &triangulation) {
193 if(orderArray == nullptr)
194 return this->printErr("Input offset field pointer is null.");
195
196 Timer t;
197
198 this->printMsg("Start computing segmentations", 0.0, t.getElapsedTime(),
199 this->threadNumber_);
200
203 computePathCompression(outSegmentation.ascending_,
204 outSegmentation.descending_, orderArray,
205 triangulation);
208 outSegmentation.ascending_, true, orderArray, triangulation);
211 outSegmentation.descending_, false, orderArray, triangulation);
212 }
213
215 computeMSHash(outSegmentation.morseSmale_, outSegmentation.ascending_,
216 outSegmentation.descending_, triangulation);
217 }
218
219 this->printMsg("Data-set ("
220 + std::to_string(triangulation.getNumberOfVertices())
221 + " points) processed",
222 1.0, t.getElapsedTime(), this->threadNumber_);
223
224 return 0;
225}
226
227template <typename triangulationType>
229 SimplexId *const ascSegmentation,
230 SimplexId *const dscSegmentation,
231 const SimplexId *const orderArray,
232 const triangulationType &triangulation) const {
233
234 ttk::Timer localTimer;
235
236 const SimplexId nVertices = triangulation.getNumberOfVertices();
237 std::vector<SimplexId> lActiveVertices;
238
239#ifdef TTK_ENABLE_OPENMP
240#pragma omp parallel num_threads(threadNumber_) private(lActiveVertices)
241 {
242 lActiveVertices.reserve(std::ceil(nVertices / threadNumber_));
243
244#pragma omp for schedule(static)
245#else // TTK_ENABLE_OPENMP
246 lActiveVertices.reserve(nVertices);
247#endif // TTK_ENABLE_OPENMP
248 // find the largest and smallest neighbor for each vertex
249 for(SimplexId i = 0; i < nVertices; i++) {
250 SimplexId neighborId{0};
251 SimplexId const numNeighbors = triangulation.getVertexNeighborNumber(i);
252
253 bool hasLargerNeighbor = false;
254 SimplexId &dmi = dscSegmentation[i];
255 dmi = i;
256
257 bool hasSmallerNeighbor = false;
258 SimplexId &ami = ascSegmentation[i];
259 ami = i;
260
261 // check all neighbors
262 for(SimplexId n = 0; n < numNeighbors; n++) {
263 triangulation.getVertexNeighbor(i, n, neighborId);
264
265 if(orderArray[neighborId] < orderArray[ami]) {
266 ami = neighborId;
267 hasSmallerNeighbor = true;
268 } else if(orderArray[neighborId] > orderArray[dmi]) {
269 dmi = neighborId;
270 hasLargerNeighbor = true;
271 }
272 }
273
274 if(hasLargerNeighbor || hasSmallerNeighbor) {
275 lActiveVertices.push_back(i);
276 }
277 }
278
279 size_t lnActiveVertices = lActiveVertices.size();
280 size_t currentIndex = 0;
281
282 // compress paths until no changes occur
283 while(lnActiveVertices > 0) {
284 for(size_t i = 0; i < lnActiveVertices; i++) {
285 SimplexId const &v = lActiveVertices[i];
286 SimplexId &vDsc = dscSegmentation[v];
287 SimplexId &vAsc = ascSegmentation[v];
288
289// compress paths
290#ifdef TTK_ENABLE_OPENMP
291#pragma omp atomic read
292#endif // TTK_ENABLE_OPENMP
293 vDsc = dscSegmentation[vDsc];
294
295#ifdef TTK_ENABLE_OPENMP
296#pragma omp atomic read
297#endif // TTK_ENABLE_OPENMP
298 vAsc = ascSegmentation[vAsc];
299
300 // check if fully compressed
301 if(vDsc != dscSegmentation[vDsc] || vAsc != ascSegmentation[vAsc]) {
302 lActiveVertices[currentIndex++] = v;
303 }
304 }
305
306 lnActiveVertices = currentIndex;
307 currentIndex = 0;
308 }
309#ifdef TTK_ENABLE_OPENMP
310 }
311#endif // TTK_ENABLE_OPENMP
312
313 this->printMsg("Asc. and Desc. segmentation computed", 1.0,
314 localTimer.getElapsedTime(), this->threadNumber_,
316
317 return 0; // return success
318}
319
320template <typename triangulationType>
322 SimplexId *const segmentation,
323 const bool computeAscending,
324 const SimplexId *const orderArray,
325 const triangulationType &triangulation) const {
326
327 ttk::Timer localTimer;
328
329 const SimplexId nVertices = triangulation.getNumberOfVertices();
330 std::vector<SimplexId> lActiveVertices;
331
332#ifdef TTK_ENABLE_OPENMP
333#pragma omp parallel num_threads(threadNumber_)
334 {
335 lActiveVertices.reserve(std::ceil(nVertices / threadNumber_));
336
337#pragma omp for schedule(static)
338#else // TTK_ENABLE_OPENMP
339 lActiveVertices.reserve(nVertices);
340#endif // TTK_ENABLE_OPENMP
341 // find the largest neighbor for each vertex
342 for(SimplexId i = 0; i < nVertices; i++) {
343 SimplexId neighborId{0};
344 SimplexId const numNeighbors = triangulation.getVertexNeighborNumber(i);
345
346 bool hasLargerNeighbor = false;
347 SimplexId &mi = segmentation[i];
348 mi = i;
349
350 // check all neighbors
351 for(SimplexId n = 0; n < numNeighbors; n++) {
352 triangulation.getVertexNeighbor(i, n, neighborId);
353
354 if(computeAscending) {
355 if(orderArray[neighborId] < orderArray[mi]) {
356 mi = neighborId;
357 hasLargerNeighbor = true;
358 }
359 } else {
360 if(orderArray[neighborId] > orderArray[mi]) {
361 mi = neighborId;
362 hasLargerNeighbor = true;
363 }
364 }
365 }
366
367 if(hasLargerNeighbor) {
368 lActiveVertices.push_back(i);
369 }
370 }
371
372 size_t lnActiveVertices = lActiveVertices.size();
373 size_t currentIndex = 0;
374
375 // compress paths until no changes occur
376 while(lnActiveVertices > 0) {
377 for(size_t i = 0; i < lnActiveVertices; i++) {
378 SimplexId const &v = lActiveVertices[i];
379 SimplexId &vMan = segmentation[v];
380
381// compress paths
382#ifdef TTK_ENABLE_OPENMP
383#pragma omp atomic read
384#endif // TTK_ENABLE_OPENMP
385 vMan = segmentation[vMan];
386
387 // check if fully compressed
388 if(vMan != segmentation[vMan]) {
389 lActiveVertices[currentIndex++] = v;
390 }
391 }
392
393 lnActiveVertices = currentIndex;
394 currentIndex = 0;
395 }
396#ifdef TTK_ENABLE_OPENMP
397 }
398#endif // TTK_ENABLE_OPENMP
399
400 if(computeAscending) {
401 this->printMsg("Ascending segmentation computed", 1.0,
402 localTimer.getElapsedTime(), this->threadNumber_,
404 } else {
405 this->printMsg("Descending segmentation computed", 1.0,
406 localTimer.getElapsedTime(), this->threadNumber_,
408 }
409
410 return 0; // return success
411}
412
413template <typename triangulationType>
415 SimplexId *const morseSmaleSegmentation,
416 const SimplexId *const ascSegmentation,
417 const SimplexId *const dscSegmentation,
418 const triangulationType &triangulation) const {
419
420 ttk::Timer localTimer;
421
422 const size_t nVerts = triangulation.getNumberOfVertices();
423
424#ifdef TTK_ENABLE_OPENMP
425#pragma omp parallel for schedule(static) num_threads(threadNumber_)
426#endif // TTK_ENABLE_OPENMP
427 for(size_t i = 0; i < nVerts; ++i) {
428 morseSmaleSegmentation[i]
429 = pcp::getHash(ascSegmentation[i], dscSegmentation[i]);
430 }
431
432 this->printMsg("Morse-Smale segmentation hash computed", 1.0,
433 localTimer.getElapsedTime(), this->threadNumber_,
435
436 return 0;
437}
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
Minimalist debugging class.
Definition Debug.h:88
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
TTK processing package for the computation of Morse-Smale segmentations using Path Compression.
void preconditionTriangulation(AbstractTriangulation *const data)
int execute(OutputSegmentation &outSegmentation, const SimplexId *const orderArray, const triangulationType &triangulation)
Main function for computing the Morse-Smale complex.
int computeMSHash(SimplexId *const morseSmaleSegmentation, const SimplexId *const ascSegmentation, const SimplexId *const dscSegmentation, const triangulationType &triangulation) const
Computes a MS segmentation hash.
int computePathCompressionSingle(SimplexId *const segmentation, const bool computeAscending, const SimplexId *const orderArray, const triangulationType &triangulation) const
Compute the ascending or descending segmentation.
int computePathCompression(SimplexId *const ascSegmentation, SimplexId *const dscSegmentation, const SimplexId *const orderArray, const triangulationType &triangulation) const
Compute the ascending and descending segmentation in one run.
void setComputeSegmentation(const bool doAscending, const bool doDescending, const bool doMorseSmale)
double getElapsedTime()
Definition Timer.h:15
std::string to_string(__int128)
Definition ripserpy.cpp:99
constexpr unsigned int getHash(const unsigned int a, const unsigned int b)
Get a hash value from two keys.
The Topology ToolKit.
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
Pointers to pre-allocated segmentation point data arrays.
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)