TTK
Loading...
Searching...
No Matches
MergeTreeClustering.h
Go to the documentation of this file.
1
17
40
41#define treesMatchingVector \
42 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
43#define matchingVectorType std::vector<treesMatchingVector>
44
45#pragma once
46
47#include <random>
48
49// ttk common includes
50#include <Debug.h>
51
52#include "MergeTreeBarycenter.h"
53
54namespace ttk {
55
60 // TODO rename dataType2 to dataType and remove template everywhere else in
61 // this class
62 template <class dataType2>
63 class MergeTreeClustering : virtual public Debug, public MergeTreeBarycenter {
64
65 private:
66 bool parallelizeUpdate_ = true;
67
68 unsigned int noCentroids_ = 2;
69
70 // Progressive parameters
71 int noIterationC_ = 0;
72 double addDeletedNodesTime_ = 0;
73
74 // Accelerated KMeans
75 bool acceleratedInitialized_ = false;
76 std::vector<std::vector<double>> lowerBound_;
77 std::vector<double> upperBound_;
78 std::vector<int> bestCentroid_, oldBestCentroid_;
79 std::vector<double> bestDistance_;
80 std::vector<bool> recompute_;
81 std::vector<ftm::MergeTree<dataType2>> oldCentroids_, oldCentroids2_;
82
83 // Clean correspondence
84 std::vector<std::vector<int>> trees2NodeCorr_;
85
86 public:
89 "MergeTreeClustering"); // inherited from Debug: prefix will be printed
90 // at the beginning of every msg
91 }
92 ~MergeTreeClustering() override = default;
93
94 void setNoCentroids(unsigned int noCentroidsT) {
95 noCentroids_ = noCentroidsT;
96 }
97
98 void setMixtureCoefficient(double coef) {
100 }
101
102 std::vector<std::vector<int>> getTrees2NodeCorr() {
103 return trees2NodeCorr_;
104 }
105
109
110 // ------------------------------------------------------------------------
111 // Initialization
112 // ------------------------------------------------------------------------
113 // KMeans++ init
114 template <class dataType>
116 std::vector<ftm::FTMTree_MT *> &trees,
117 std::vector<ftm::FTMTree_MT *> &trees2,
118 std::vector<std::vector<ftm::MergeTree<dataType>>> &allCentroids) {
119 allCentroids.resize(
120 2, std::vector<ftm::MergeTree<dataType>>(noCentroids_));
121 std::vector<dataType> distances(
122 trees.size(), std::numeric_limits<dataType>::max());
123
124 // Manage size limited trees
125 double limitPercent = barycenterSizeLimitPercent_ / noCentroids_;
126 std::vector<ftm::MergeTree<dataType>> mTreesLimited, mTrees2Limited;
127 bool doSizeLimit
128 = (limitPercent > 0.0 or barycenterMaximumNumberOfPairs_ > 0);
129 if(doSizeLimit) {
131 trees, barycenterMaximumNumberOfPairs_, limitPercent, mTreesLimited);
132 if(trees2.size() != 0)
134 limitPercent, mTrees2Limited);
135 }
136
137 // Init centroids
138 for(unsigned int i = 0; i < noCentroids_; ++i) {
139 int bestIndex = -1;
140 if(i == 0) {
142 trees, trees2, limitPercent, false);
143 } else {
144 // Create vector of probabilities
145 double sum = 0;
146 for(auto val : distances)
147 sum += val;
148 double bestValue = std::numeric_limits<double>::lowest();
149 std::vector<double> probabilities(trees.size());
150 for(unsigned int j = 0; j < distances.size(); ++j) {
151 probabilities[j]
152 = (sum != 0 ? distances[j] / sum : 1.0 / distances.size());
153 if(probabilities[j] > bestValue) {
154 bestValue = probabilities[j];
155 bestIndex = j;
156 }
157 }
158 if(not deterministic_) {
159 std::random_device rd;
160 std::default_random_engine generator(rd());
161 std::discrete_distribution<int> distribution(
162 probabilities.begin(), probabilities.end());
163 bestIndex = distribution(generator);
164 }
165 }
166 printMsg(
167 "Init index : " + std::to_string(bestIndex), debug::Priority::DETAIL);
168 // Create new centroid
169 allCentroids[0][i]
170 = ftm::copyMergeTree<dataType>(trees[bestIndex], baseModule_ != 2);
171 limitSizeBarycenter(allCentroids[0][i], trees, limitPercent);
172 ftm::cleanMergeTree<dataType>(allCentroids[0][i]);
173 if(trees2.size() != 0) {
174 allCentroids[1][i]
175 = ftm::copyMergeTree<dataType>(trees2[bestIndex], baseModule_ != 2);
176 limitSizeBarycenter(allCentroids[1][i], trees2, limitPercent);
177 ftm::cleanMergeTree<dataType>(allCentroids[1][i]);
178 }
179
180 if(i == noCentroids_ - 1)
181 continue;
182#ifdef TTK_ENABLE_OPENMP44
183#pragma omp parallel for schedule(dynamic) shared(allCentroids) \
184 num_threads(this->threadNumber_) if(parallelize_)
185#endif
186 for(unsigned int j = 0; j < trees.size(); ++j) {
187 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching,
188 matching2;
189 dataType distanceT, distanceT2;
190 ftm::FTMTree_MT *treeToUse
191 = (doSizeLimit ? &(mTreesLimited[j].tree) : trees[j]);
192 computeOneDistance<dataType>(treeToUse, allCentroids[0][i], matching,
193 distanceT, useDoubleInput_);
194 if(trees2.size() != 0) {
195 ftm::FTMTree_MT *tree2ToUse
196 = (doSizeLimit ? &(mTrees2Limited[j].tree) : trees2[j]);
197 computeOneDistance<dataType>(tree2ToUse, allCentroids[1][i],
198 matching2, distanceT2, useDoubleInput_,
199 false);
200 distanceT = mixDistances<dataType>(distanceT, distanceT2);
201 }
202 distances[j] = std::min(distances[j], distanceT);
203 }
204 }
205 }
206
207 template <class dataType>
208 void initNewCentroid(std::vector<ftm::FTMTree_MT *> &trees,
209 ftm::MergeTree<dataType> &centroid,
210 int noNewCentroid) {
211 std::vector<std::tuple<double, int>> distancesAndIndexes(
212 bestDistance_.size());
213 for(unsigned int i = 0; i < bestDistance_.size(); ++i)
214 distancesAndIndexes[i] = std::make_tuple(-bestDistance_[i], i);
215 std::sort(distancesAndIndexes.begin(), distancesAndIndexes.end());
216 int const bestIndex = std::get<1>(distancesAndIndexes[noNewCentroid]);
217 centroid
218 = ftm::copyMergeTree<dataType>(trees[bestIndex], baseModule_ != 2);
219 limitSizeBarycenter(centroid, trees);
221 }
222
223 template <class dataType>
225 std::vector<ftm::FTMTree_MT *> &trees,
226 std::vector<ftm::MergeTree<dataType>> &centroids,
227 std::vector<ftm::FTMTree_MT *> &ttkNotUsed(trees2)) {
228 lowerBound_.clear();
229 lowerBound_.resize(
230 trees.size(), std::vector<double>(centroids.size(), 0));
231 upperBound_.clear();
232 upperBound_.resize(trees.size(), std::numeric_limits<double>::max());
233 bestCentroid_.clear();
234 bestCentroid_.resize(trees.size(), -1);
235 oldBestCentroid_.clear();
236 oldBestCentroid_.resize(trees.size(), -1);
237 bestDistance_.clear();
238 bestDistance_.resize(trees.size(), std::numeric_limits<double>::max());
239 recompute_.clear();
240 recompute_.resize(trees.size(), true);
241 }
242
243 template <class dataType>
244 void
245 initAcceleratedKMeans(std::vector<ftm::FTMTree_MT *> &trees,
246 std::vector<ftm::MergeTree<dataType>> &centroids,
247 std::vector<ftm::FTMTree_MT *> &trees2,
248 std::vector<ftm::MergeTree<dataType>> &centroids2) {
249 acceleratedInitialized_ = true;
250 std::vector<std::tuple<int, int>> assignmentC;
251 std::vector<dataType> bestDistanceT(
252 trees.size(), std::numeric_limits<dataType>::max());
254 trees, centroids, assignmentC, bestDistanceT, trees2, centroids2);
255 for(unsigned int i = 0; i < bestDistanceT.size(); ++i)
256 bestDistance_[i] = bestDistanceT[i];
257 for(auto asgn : assignmentC)
258 bestCentroid_[std::get<1>(asgn)] = std::get<0>(asgn);
259 for(unsigned int i = 0; i < bestDistance_.size(); ++i)
260 upperBound_[i] = bestDistance_[i];
261 }
262
263 template <class dataType>
264 void copyCentroids(std::vector<ftm::MergeTree<dataType>> &centroids,
265 std::vector<ftm::MergeTree<dataType>> &oldCentroids) {
266 oldCentroids.clear();
267 for(unsigned int i = 0; i < centroids.size(); ++i)
268 oldCentroids.push_back(ftm::copyMergeTree<dataType>(centroids[i]));
269 }
270
271 // ------------------------------------------------------------------------
272 // Assignment
273 // ------------------------------------------------------------------------
274 template <class dataType>
276 std::vector<ftm::FTMTree_MT *> &trees,
277 std::vector<ftm::MergeTree<dataType>> &centroids,
278 std::vector<std::tuple<int, int>> &assignmentC,
279 std::vector<dataType> &bestDistanceT,
280 std::vector<ftm::FTMTree_MT *> &trees2,
281 std::vector<ftm::MergeTree<dataType>> &centroids2) {
282 if(not acceleratedInitialized_) {
283 initAcceleratedKMeans<dataType>(trees, centroids, trees2, centroids2);
284 } else {
285 // Compute distance between old and new corresponding centroids
286 std::vector<dataType> distanceShift(centroids.size()),
287 distanceShift2(centroids2.size());
288#ifdef TTK_ENABLE_OPENMP4
289#pragma omp parallel for schedule(dynamic) \
290 shared(centroids, centroids2, oldCentroids_, oldCentroids2_) \
291 num_threads(this->threadNumber_) if(parallelize_)
292#endif
293 for(unsigned int i = 0; i < centroids.size(); ++i) {
294 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching,
295 matching2;
296 computeOneDistance<dataType>(centroids[i], oldCentroids_[i], matching,
297 distanceShift[i], useDoubleInput_);
298 if(trees2.size() != 0) {
299 computeOneDistance<dataType>(centroids2[i], oldCentroids2_[i],
300 matching2, distanceShift2[i],
301 useDoubleInput_, false);
302 distanceShift[i]
303 = mixDistances<dataType>(distanceShift[i], distanceShift2[i]);
304 }
305 }
306
307 // Step 5
308 for(unsigned int i = 0; i < trees.size(); ++i)
309 for(unsigned int c = 0; c < centroids.size(); ++c)
310 lowerBound_[i][c]
311 = std::max(lowerBound_[i][c] - distanceShift[c], 0.0);
312
313 // Step 6
314 for(unsigned int i = 0; i < trees.size(); ++i) {
315 upperBound_[i] = upperBound_[i] + distanceShift[bestCentroid_[i]];
316 recompute_[i] = true;
317 }
318 }
319
320 // Step 1
321 std::vector<std::vector<double>> centroidsDistance, centroidsDistance2;
323 centroids, centroidsDistance, useDoubleInput_);
324 if(trees2.size() != 0) {
326 centroids2, centroidsDistance2, useDoubleInput_, false);
327 mixDistancesMatrix(centroidsDistance, centroidsDistance2);
328 }
329 std::vector<double> centroidScore(
330 centroids.size(), std::numeric_limits<double>::max());
331 for(unsigned int i = 0; i < centroids.size(); ++i)
332 for(unsigned int j = i + 1; j < centroids.size(); ++j) {
333 if(0.5 * centroidsDistance[i][j] < centroidScore[i])
334 centroidScore[i] = 0.5 * centroidsDistance[i][j];
335 if(0.5 * centroidsDistance[i][j] < centroidScore[j])
336 centroidScore[j] = 0.5 * centroidsDistance[i][j];
337 }
338
339 // Step 2
340 std::vector<bool> identified(trees.size());
341 for(unsigned int i = 0; i < trees.size(); ++i)
342 identified[i] = (upperBound_[i] <= centroidScore[bestCentroid_[i]]);
343
344 // Step 3
345#ifdef TTK_ENABLE_OPENMP4
346#pragma omp parallel for schedule(dynamic) shared(centroids, centroids2) \
347 num_threads(this->threadNumber_) if(parallelize_)
348#endif
349 for(unsigned int i = 0; i < trees.size(); ++i)
350 for(unsigned int c = 0; c < centroids.size(); ++c) {
351 if(not identified[i] and (int) c != bestCentroid_[i]
352 and upperBound_[i] > lowerBound_[i][c]
353 and upperBound_[i]
354 > 0.5 * centroidsDistance[bestCentroid_[i]][c]) {
355 // Step 3a
356 if(recompute_[i]) {
357 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
358 matching, matching2;
359 dataType distance, distance2;
361 centroids[bestCentroid_[i]],
362 matching, distance, useDoubleInput_);
363 if(trees2.size() != 0) {
365 trees2[i], centroids2[bestCentroid_[i]], matching2, distance2,
366 useDoubleInput_, false);
367 distance = mixDistances<dataType>(distance, distance2);
368 }
369 recompute_[i] = false;
370 lowerBound_[i][bestCentroid_[i]] = distance;
371 upperBound_[i] = distance;
372 bestDistance_[i] = distance;
373 } else {
374 bestDistance_[i] = upperBound_[i];
375 }
376 // Step 3b
377 if(bestDistance_[i] > lowerBound_[i][c]
378 and bestDistance_[i]
379 > 0.5 * centroidsDistance[bestCentroid_[i]][c]) {
380 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
381 matching, matching2;
382 dataType distance, distance2;
384 trees[i], centroids[c], matching, distance, useDoubleInput_);
385 if(trees2.size() != 0) {
386 computeOneDistance<dataType>(trees2[i], centroids2[c],
387 matching2, distance2,
388 useDoubleInput_, false);
389 distance = mixDistances<dataType>(distance, distance2);
390 }
391 lowerBound_[i][c] = distance;
392 if(distance < bestDistance_[i]) {
393 bestCentroid_[i] = c;
394 upperBound_[i] = distance;
395 bestDistance_[i] = distance;
396 }
397 }
398 }
399 }
400
401 // Copy centroids for next step
402 copyCentroids<dataType>(centroids, oldCentroids_);
403 if(trees2.size() != 0)
404 copyCentroids<dataType>(centroids2, oldCentroids2_);
405
406 // Manage output
407 for(unsigned int i = 0; i < bestDistance_.size(); ++i)
408 bestDistanceT[i] = bestDistance_[i];
409 for(unsigned int i = 0; i < bestCentroid_.size(); ++i)
410 assignmentC.emplace_back(bestCentroid_[i], i);
411 }
412
413 template <class dataType>
414 void
415 assignmentCentroids(std::vector<ftm::FTMTree_MT *> &trees,
416 std::vector<ftm::MergeTree<dataType>> &centroids,
417 std::vector<std::tuple<int, int>> &assignmentC,
418 std::vector<dataType> &bestDistanceT,
419 std::vector<ftm::FTMTree_MT *> &trees2,
420 std::vector<ftm::MergeTree<dataType>> &centroids2) {
421 oldBestCentroid_ = bestCentroid_;
423 trees, centroids, assignmentC, bestDistanceT, trees2, centroids2);
424 }
425
426 template <class dataType>
428 std::vector<ftm::FTMTree_MT *> &trees,
429 std::vector<ftm::MergeTree<dataType>> &centroids,
430 matchingVectorType &matchingsC,
431 std::vector<std::tuple<int, int>> &assignmentC,
432 std::vector<dataType> &bestDistanceT,
433 std::vector<ftm::FTMTree_MT *> &trees2,
434 std::vector<ftm::MergeTree<dataType>> &centroids2,
435 matchingVectorType &matchingsC2) {
436 int noC = centroids.size();
437 std::vector<std::vector<ftm::FTMTree_MT *>> assignedTrees(noC),
438 assignedTrees2(noC);
439 std::vector<std::vector<int>> assignedTreesIndex(noC);
440
441 for(auto asgn : assignmentC) {
442 assignedTreesIndex[std::get<0>(asgn)].push_back(std::get<1>(asgn));
443 assignedTrees[std::get<0>(asgn)].push_back(trees[std::get<1>(asgn)]);
444 if(trees2.size() != 0)
445 assignedTrees2[std::get<0>(asgn)].push_back(
446 trees2[std::get<1>(asgn)]);
447 }
448
449#ifdef TTK_ENABLE_OPENMP4
450#pragma omp parallel for schedule(dynamic) shared(centroids, centroids2) \
451 num_threads(this->threadNumber_) if(parallelize_)
452#endif
453 for(unsigned int i = 0; i < centroids.size(); ++i) {
454 std::vector<dataType> distances(assignedTrees[i].size(), 0);
455 std::vector<dataType> distances2(assignedTrees[i].size(), 0);
456 treesMatchingVector matching(trees.size()), matching2(trees2.size());
457 std::vector<std::vector<std::pair<std::pair<ftm::idNode, ftm::idNode>,
458 std::pair<ftm::idNode, ftm::idNode>>>>
459 matching_path(trees.size());
460 if(baseModule_ == 2) {
462 assignedTrees[i], centroids[i], matching, matching_path, distances);
463 matchingsC[i] = matching;
464 } else {
465 assignment<dataType>(assignedTrees[i], centroids[i], matching,
466 matching_path, distances, useDoubleInput_);
467 matchingsC[i] = matching;
468 if(trees2.size() != 0) {
469 assignment<dataType>(assignedTrees2[i], centroids2[i], matching2,
470 matching_path, distances2, useDoubleInput_,
471 false);
472 matchingsC2[i] = matching2;
473 for(unsigned int j = 0; j < assignedTreesIndex[i].size(); ++j)
474 distances[j]
475 = mixDistances<dataType>(distances[j], distances2[j]);
476 }
477 }
478 for(unsigned int j = 0; j < assignedTreesIndex[i].size(); ++j) {
479 int const index = assignedTreesIndex[i][j];
480 bestDistanceT[index] = distances[j];
481 }
482 }
483 }
484
485 template <class dataType>
487 std::vector<ftm::FTMTree_MT *> &trees,
488 std::vector<ftm::MergeTree<dataType>> &centroids,
489 std::vector<std::tuple<int, int>> &assignmentC,
490 std::vector<dataType> &bestDistanceT,
491 std::vector<ftm::FTMTree_MT *> &trees2,
492 std::vector<ftm::MergeTree<dataType>> &centroids2) {
493 std::vector<int> bestCentroidT(trees.size(), -1);
494
495#ifdef TTK_ENABLE_OPENMP4
496#pragma omp parallel for schedule(dynamic) shared(centroids, centroids2) \
497 num_threads(this->threadNumber_) if(parallelize_)
498#endif
499 for(unsigned int i = 0; i < trees.size(); ++i) {
500 for(unsigned int j = 0; j < centroids.size(); ++j) {
501 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching;
502 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching2;
503 dataType distance, distance2;
505 trees[i], centroids[j], matching, distance, useDoubleInput_);
506 if(trees2.size() != 0) {
507 computeOneDistance<dataType>(trees2[i], centroids2[j], matching2,
508 distance2, useDoubleInput_, false);
509 distance = mixDistances<dataType>(distance, distance2);
510 }
511 if(distance < bestDistanceT[i]) {
512 bestDistanceT[i] = distance;
513 bestDistance_[i] = distance;
514 bestCentroidT[i] = j;
515 bestCentroid_[i] = j;
516 }
517 }
518 }
519
520 for(unsigned int i = 0; i < bestCentroidT.size(); ++i)
521 assignmentC.emplace_back(bestCentroidT[i], i);
522 }
523
524 template <class dataType>
526 std::vector<ftm::MergeTree<dataType>> &centroids,
527 std::vector<std::vector<double>> &distanceMatrix,
528 bool useDoubleInput = false,
529 bool isFirstInput = true) {
530 std::vector<ftm::FTMTree_MT *> trees(centroids.size());
531 for(size_t i = 0; i < centroids.size(); ++i) {
532 trees[i] = &(centroids[i].tree);
533 }
535 trees, distanceMatrix, useDoubleInput, isFirstInput);
536 }
537
539 std::vector<int> &nodeCorr,
540 std::vector<int> &assignedTreesIndex) {
541 for(int const i : assignedTreesIndex) {
542 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> newMatching;
543 for(auto tup : matchingT[i])
544 newMatching.emplace_back(
545 nodeCorr[std::get<0>(tup)], std::get<1>(tup), std::get<2>(tup));
546 matchingT[i] = newMatching;
547 }
548 }
549
550 // ------------------------------------------------------------------------
551 // Update
552 // ------------------------------------------------------------------------
553 bool samePreviousAssignment(int clusterId) {
554 for(unsigned int i = 0; i < bestCentroid_.size(); ++i)
555 if(bestCentroid_[i] == clusterId
556 and bestCentroid_[i] != oldBestCentroid_[i])
557 return false;
558 return true;
559 }
560
561 template <class dataType>
562 bool updateCentroids(std::vector<ftm::FTMTree_MT *> &trees,
563 std::vector<ftm::MergeTree<dataType>> &centroids,
564 std::vector<double> &alphas,
565 std::vector<std::tuple<int, int>> &assignmentC) {
566 bool oneCentroidUpdated = false;
567 int noC = centroids.size();
568 std::vector<std::vector<ftm::FTMTree_MT *>> assignedTrees(noC);
569 std::vector<std::vector<int>> assignedTreesIndex(noC);
570 std::vector<std::vector<double>> assignedAlphas(noC);
571
572 for(auto asgn : assignmentC) {
573 assignedTrees[std::get<0>(asgn)].push_back(trees[std::get<1>(asgn)]);
574 assignedTreesIndex[std::get<0>(asgn)].push_back(std::get<1>(asgn));
575 assignedAlphas[std::get<0>(asgn)].push_back(alphas[std::get<1>(asgn)]);
576 }
577
578 int cpt = 0;
579 std::vector<int> noNewCentroid(centroids.size(), -1);
580 for(unsigned int i = 0; i < centroids.size(); ++i)
581 if(assignedTrees[i].size() == 0) {
582 noNewCentroid[i] = cpt;
583 ++cpt;
584 }
585
586#ifdef TTK_ENABLE_OPENMP4
587#pragma omp parallel num_threads(this->threadNumber_) \
588 shared(centroids) if(parallelize_ and parallelizeUpdate_)
589 {
590#pragma omp single nowait
591 {
592#endif
593 for(unsigned int i = 0; i < centroids.size(); ++i) {
594#ifdef TTK_ENABLE_OPENMP4
595#pragma omp task firstprivate(i) shared(centroids)
596 {
597#endif
598 if(assignedTrees[i].size() == 0) {
599 // Init new centroid if no trees are assigned to it
601 trees, centroids[i], noNewCentroid[i]);
602 for(unsigned int t = 0; t < trees.size(); ++t)
603 lowerBound_[t][i] = 0;
604 } else if(assignedTrees[i].size() == 1) {
605 centroids[i] = ftm::copyMergeTree<dataType>(
606 assignedTrees[i][0], baseModule_ != 2);
607 limitSizeBarycenter(centroids[i], assignedTrees[i]);
608 ftm::cleanMergeTree<dataType>(centroids[i]);
609 } else if(not samePreviousAssignment(i)) {
610 // Do not update if same previous assignment
611 // And compute barycenter of the assigned trees otherwise
612 oneCentroidUpdated = true;
613 double alphasSum = 0;
614 for(unsigned int j = 0; j < assignedAlphas[i].size(); ++j)
615 alphasSum += assignedAlphas[i][j];
616 for(unsigned int j = 0; j < assignedAlphas[i].size(); ++j)
617 assignedAlphas[i][j] /= alphasSum;
618 treesMatchingVector matching(assignedTrees[i].size());
620 assignedTrees[i], centroids[i], assignedAlphas[i], matching);
621 std::vector<ftm::idNode> deletedNodesT;
623 &(centroids[i].tree), 0, deletedNodesT);
624 ftm::cleanMergeTree<dataType>(centroids[i]);
625 }
626#ifdef TTK_ENABLE_OPENMP4
627 } // pragma omp task
628#endif
629 }
630#ifdef TTK_ENABLE_OPENMP4
631#pragma omp taskwait
632 } // pragma omp single nowait
633 } // pragma omp parallel
634#endif
635 return oneCentroidUpdated;
636 }
637
638 template <class dataType>
640 std::vector<ftm::FTMTree_MT *> &trees,
641 ftm::MergeTree<dataType> &baryMergeTree,
642 std::vector<double> &alphas,
643 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
644 &finalMatchings) {
645 MergeTreeBarycenter mergeTreeBary;
646
647 mergeTreeBary.setDebugLevel(std::min(debugLevel_, 1));
648 mergeTreeBary.setBaseModule(this->baseModule_);
649 // mergeTreeBary.setProgressiveComputation(false);
651 mergeTreeBary.setIsCalled(true);
652 mergeTreeBary.setThreadNumber(this->threadNumber_);
653 mergeTreeBary.setDistanceSquaredRoot(true); // squared root
654 mergeTreeBary.setDeterministic(deterministic_);
655 mergeTreeBary.setTol(tol_);
659
660 if(baseModule_ == 2) {
661 mergeTreeBary.setPathMetric(this->pathMetric_);
662 mergeTreeBary.setBranchDecomposition(false);
663 mergeTreeBary.setNormalizedWasserstein(false);
664 mergeTreeBary.setKeepSubtree(false);
665 // mergeTreeBary.setUseMinMaxPair(true);
666 mergeTreeBary.setAddNodes(false);
667 mergeTreeBary.setPostprocess(false);
668 } else {
669 mergeTreeBary.setBranchDecomposition(true);
671 // mergeTreeBary.setNormalizedWassersteinReg(normalizedWassersteinReg_);
672 // mergeTreeBary.setRescaledWasserstein(rescaledWasserstein_);
673 mergeTreeBary.setKeepSubtree(keepSubtree_);
675 }
676
677 std::vector<std::vector<std::pair<std::pair<ftm::idNode, ftm::idNode>,
678 std::pair<ftm::idNode, ftm::idNode>>>>
679 finalMatchings_path(trees.size());
680 mergeTreeBary.computeBarycenter<dataType>(
681 trees, baryMergeTree, alphas, finalMatchings, finalMatchings_path);
682
683 addDeletedNodesTime_ += mergeTreeBary.getAddDeletedNodesTime();
684
685 if(baseModule_ == 2) {
686 ftm::FTMTree_MT *baryTree = &(baryMergeTree.tree);
687 for(ftm::idNode node = 0; node < baryTree->getNumberOfNodes(); node++) {
688 baryTree->getNode(node)->setOrigin(-1);
689 }
690 preprocessTree<dataType>(baryTree, false);
691 }
692 }
693
694 // ------------------------------------------------------------------------
695 // Main Functions
696 // ------------------------------------------------------------------------
697 template <class dataType>
698 void computeCentroids(std::vector<ftm::FTMTree_MT *> &trees,
699 std::vector<ftm::MergeTree<dataType>> &centroids,
700 matchingVectorType &outputMatching,
701 std::vector<double> &alphas,
702 std::vector<int> &clusteringAssignment,
703 std::vector<ftm::FTMTree_MT *> &trees2,
704 std::vector<ftm::MergeTree<dataType>> &centroids2,
705 matchingVectorType &outputMatching2) {
706 Timer t_clust;
707
708 printCentroidsStats(centroids, centroids2);
709
710 // Run
711 int noCentroidsT = centroids.size();
712 bool converged = false;
713 dataType inertia = -1;
714 dataType minInertia = std::numeric_limits<dataType>::max();
715 int cptBlocked = 0;
716 noIterationC_ = 0;
717 std::vector<std::tuple<int, int>> assignmentC;
718 std::vector<dataType> bestDistanceT(
719 trees.size(), std::numeric_limits<dataType>::max());
720 while(not converged) {
721 ++noIterationC_;
722
724 std::stringstream ssIter;
725 ssIter << "Iteration " << noIterationC_;
726 printMsg(ssIter.str());
727
728 // --- Assignment
729 Timer t_assignment;
731 trees, centroids, assignmentC, bestDistanceT, trees2, centroids2);
732 auto t_assignment_time = t_assignment.getElapsedTime();
733 printMsg("Assignment", 1, t_assignment_time, this->threadNumber_);
734
735 // --- Update
736 Timer t_update;
737 bool trees1Updated = true, trees2Updated = true;
738 trees1Updated
739 = updateCentroids<dataType>(trees, centroids, alphas, assignmentC);
740 if(trees2.size() != 0)
741 trees2Updated = updateCentroids<dataType>(
742 trees2, centroids2, alphas, assignmentC);
743 auto t_update_time = t_update.getElapsedTime();
744 printMsg("Update", 1, t_update_time, this->threadNumber_);
745 printCentroidsStats(centroids, centroids2);
746
747 // --- Check convergence
748 dataType currentInertia = 0;
749 for(auto distance : bestDistanceT)
750 currentInertia += distance * distance;
751 converged = std::abs((double)(inertia - currentInertia)) < 0.01;
752 inertia = currentInertia;
753 std::stringstream ss3;
754 ss3 << "Inertia : " << inertia;
755 printMsg(ss3.str());
756
757 minInertia = std::min(minInertia, inertia);
758 if(not converged) {
759 cptBlocked += (minInertia < inertia) ? 1 : 0;
760 converged = (cptBlocked >= 10);
761 }
762
763 // Converged if barycenters were not updated (same assignment than last
764 // iteration)
765 converged = converged or (not trees1Updated and not trees2Updated);
766
767 // --- Reset vectors
768 if(not converged) {
769 assignmentC.clear();
770 bestDistanceT.clear();
771 bestDistanceT.resize(
772 trees.size(), std::numeric_limits<dataType>::max());
773 }
774 }
775
776 // Final processing
778 printMsg("Final assignment");
779 matchingVectorType matchingsC(noCentroidsT);
780 matchingVectorType matchingsC2(noCentroidsT);
781 finalAssignmentCentroids<dataType>(trees, centroids, matchingsC,
782 assignmentC, bestDistanceT, trees2,
783 centroids2, matchingsC2);
784 for(auto dist : bestDistanceT)
785 finalDistances_.push_back(dist);
786 dataType currentInertia = 0;
787 for(auto distance : bestDistanceT)
788 currentInertia += distance * distance;
789 std::stringstream ss;
790 ss << "Inertia : " << currentInertia;
791 printMsg(ss.str());
792
793 // Manage output
794 std::vector<int> cptCentroid(centroids.size(), 0);
795 for(auto asgn : assignmentC) {
796 int const centroid = std::get<0>(asgn);
797 int const tree = std::get<1>(asgn);
798 // std::cout << centroid << " " << tree << std::endl;
799 clusteringAssignment[tree] = centroid;
800 outputMatching[centroid][tree]
801 = matchingsC[centroid][cptCentroid[centroid]];
802 if(trees2.size() != 0)
803 outputMatching2[centroid][tree]
804 = matchingsC2[centroid][cptCentroid[centroid]];
805 ++cptCentroid[centroid];
806 }
807
808 auto clusteringTime = t_clust.getElapsedTime() - addDeletedNodesTime_;
809 printMsg("Total", 1, clusteringTime, this->threadNumber_);
810 }
811
812 template <class dataType>
813 void execute(std::vector<ftm::MergeTree<dataType>> &trees,
814 matchingVectorType &outputMatching,
815 std::vector<double> &alphas,
816 std::vector<int> &clusteringAssignment,
817 std::vector<ftm::MergeTree<dataType>> &trees2,
818 matchingVectorType &outputMatching2,
819 std::vector<ftm::MergeTree<dataType>> &centroids,
820 std::vector<ftm::MergeTree<dataType>> &centroids2) {
821 // --- Preprocessing
822 // std::vector<ftm::FTMTree_MT*> oldTrees, oldTrees2;
823 treesNodeCorr_.resize(trees.size());
825 if(trees2.size() != 0) {
826 trees2NodeCorr_.resize(trees2.size());
827 preprocessingClustering<dataType>(trees2, trees2NodeCorr_, false);
828 }
829 std::vector<ftm::FTMTree_MT *> treesT;
831 std::vector<ftm::FTMTree_MT *> treesT2;
832 ftm::mergeTreeToFTMTree<dataType>(trees2, treesT2);
833 useDoubleInput_ = (trees2.size() != 0);
834
835 // --- Init centroids
836 std::vector<std::vector<ftm::MergeTree<dataType>>> allCentroids;
837 initCentroids<dataType>(treesT, treesT2, allCentroids);
838 centroids = allCentroids[0];
839 if(trees2.size() != 0)
840 centroids2 = allCentroids[1];
841 /*for(unsigned int i = 0; i < centroids.size(); ++i){
842 verifyBranchDecompositionInconsistency<dataType>(centroids[i]->tree);
843 if(trees2.size() != 0)
844 verifyBranchDecompositionInconsistency<dataType>(centroids2[i]->tree);
845 }*/
846
847 // --- Init accelerated kmeans
848 initAcceleratedKMeansVectors<dataType>(treesT, centroids, treesT2);
849
850 // --- Execute
851 computeCentroids<dataType>(treesT, centroids, outputMatching, alphas,
852 clusteringAssignment, treesT2, centroids2,
853 outputMatching2);
854
855 // --- Postprocessing
856 if(baseModule_ == 0 && postprocess_) {
857 // fixMergedRootOriginClustering<dataType>(centroids);
859 trees, centroids, outputMatching, clusteringAssignment);
860 /*if(trees2.size() != 0){
861 putBackMinMaxPair<dataType>(centroids, centroids2);
862 postprocessingClustering<dataType>(trees2, centroids2,
863 outputMatching2, clusteringAssignment);
864 }*/
865 }
866 }
867
868 template <class dataType>
869 void execute(std::vector<ftm::MergeTree<dataType>> &trees,
870 matchingVectorType &outputMatching,
871 std::vector<int> &clusteringAssignment,
872 std::vector<ftm::MergeTree<dataType>> &trees2,
873 matchingVectorType &outputMatching2,
874 std::vector<ftm::MergeTree<dataType>> &centroids,
875 std::vector<ftm::MergeTree<dataType>> &centroids2) {
876 if(trees2.size() != 0)
877 printMsg("Use join and split trees");
878
879 std::vector<double> alphas;
880 for(unsigned int i = 0; i < trees.size(); ++i)
881 alphas.push_back(1.0 / trees.size());
882
883 execute<dataType>(trees, outputMatching, alphas, clusteringAssignment,
884 trees2, outputMatching2, centroids, centroids2);
885 }
886
887 template <class dataType>
888 void execute(std::vector<ftm::MergeTree<dataType>> &trees,
889 matchingVectorType &outputMatching,
890 std::vector<int> &clusteringAssignment,
891 std::vector<ftm::MergeTree<dataType>> &centroids) {
892 std::vector<ftm::MergeTree<dataType>> trees2, centroids2;
893 matchingVectorType outputMatching2 = matchingVectorType();
894 execute<dataType>(trees, outputMatching, clusteringAssignment, trees2,
895 outputMatching2, centroids, centroids2);
896 }
897
898 // ------------------------------------------------------------------------
899 // Preprocessing
900 // ------------------------------------------------------------------------
901 template <class dataType>
903 std::vector<std::vector<int>> &nodeCorr,
904 bool useMinMaxPairT = true) {
905 for(unsigned int i = 0; i < trees.size(); ++i) {
908 useMinMaxPairT, cleanTree_, nodeCorr[i],
909 true, baseModule_ == 2);
910 if(trees.size() < 40)
911 printTreeStats(trees[i]);
912 }
913 printTreesStats(trees);
914 }
915
916 // ------------------------------------------------------------------------
917 // Postprocessing
918 // ------------------------------------------------------------------------
919 template <class dataType>
921 std::vector<ftm::MergeTree<dataType>> &centroids) {
922 for(unsigned int i = 0; i < centroids.size(); ++i)
924 }
925
926 template <class dataType>
927 void putBackMinMaxPair(std::vector<ftm::MergeTree<dataType>> &centroids,
928 std::vector<ftm::MergeTree<dataType>> &centroids2) {
929 for(unsigned int i = 0; i < centroids2.size(); ++i)
930 copyMinMaxPair(centroids[i], centroids2[i]);
931 }
932
933 template <class dataType>
934 void
936 std::vector<ftm::MergeTree<dataType>> &centroids,
937 matchingVectorType &outputMatching,
938 std::vector<int> &clusteringAssignment) {
939 for(unsigned int i = 0; i < trees.size(); ++i)
940 postprocessingPipeline<dataType>(&(trees[i].tree));
941 for(unsigned int i = 0; i < centroids.size(); ++i)
942 postprocessingPipeline<dataType>(&(centroids[i].tree));
943 for(unsigned int c = 0; c < centroids.size(); ++c)
944 for(unsigned int i = 0; i < trees.size(); ++i)
945 if(clusteringAssignment[i] == (int)c)
947 &(centroids[c].tree), &(trees[i].tree), outputMatching[c][i]);
948 }
949
950 // ------------------------------------------------------------------------
951 // Utils
952 // ------------------------------------------------------------------------
953 template <class dataType>
954 void
956 std::vector<ftm::MergeTree<dataType>> &centroids2) {
957 for(auto &centroid : centroids)
958 printBaryStats(&(centroid.tree), debug::Priority::DETAIL);
959 for(auto &centroid : centroids2)
960 printBaryStats(&(centroid.tree), debug::Priority::DETAIL);
961 }
962
963 }; // MergeTreeClustering class
964
965} // namespace ttk
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
#define matchingVectorType
#define treesMatchingVector
virtual int setThreadNumber(const int threadNumber)
Definition BaseClass.h:80
int debugLevel_
Definition Debug.h:379
void setDebugMsgPrefix(const std::string &prefix)
Definition Debug.h:364
virtual int setDebugLevel(const int &debugLevel)
Definition Debug.cpp:147
int getBestInitTreeIndex(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::FTMTree_MT * > &trees2, unsigned int barycenterMaximumNumberOfPairs, double sizeLimitPercent, bool distMinimizer=true)
void limitSizeBarycenter(ftm::MergeTree< dataType > &bary, std::vector< ftm::FTMTree_MT * > &trees, unsigned int barycenterMaximumNumberOfPairs, double percent, bool useBD=true)
void fixMergedRootOriginBarycenter(ftm::MergeTree< dataType > &barycenter)
void setAddNodes(bool addNodesT)
void getDistanceMatrix(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::FTMTree_MT * > &trees2, std::vector< std::vector< double > > &distanceMatrix, bool useDoubleInput=false, bool isFirstInput=true)
void setPostprocess(bool postproc)
unsigned int barycenterMaximumNumberOfPairs_
void setDeterministic(bool deterministicT)
void computeBarycenter(std::vector< ftm::FTMTree_MT * > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< double > &alphas, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &finalMatchings, std::vector< std::vector< std::pair< std::pair< ftm::idNode, ftm::idNode >, std::pair< ftm::idNode, ftm::idNode > > > > &finalMatchings_path, bool finalAsgnDoubleInput=false, bool finalAsgnFirstInput=true)
void computeOneDistance(ftm::FTMTree_MT *tree, ftm::FTMTree_MT *baryTree, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matching, std::vector< std::pair< std::pair< ftm::idNode, ftm::idNode >, std::pair< ftm::idNode, ftm::idNode > > > &matching_path, dataType &distance, bool useDoubleInput=false, bool isFirstInput=true)
std::vector< double > finalDistances_
void getSizeLimitedTrees(std::vector< ftm::FTMTree_MT * > &trees, unsigned int barycenterMaximumNumberOfPairs, double sizeLimitPercent, std::vector< ftm::MergeTree< dataType > > &mTreesLimited)
void printBaryStats(ftm::FTMTree_MT *baryTree, const debug::Priority &priority=debug::Priority::INFO)
void setProgressiveBarycenter(bool progressive)
void setBarycenterMaximumNumberOfPairs(unsigned int maxi)
void setBarycenterSizeLimitPercent(double percent)
void assignment(std::vector< ftm::FTMTree_MT * > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< std::vector< std::pair< std::pair< ftm::idNode, ftm::idNode >, std::pair< ftm::idNode, ftm::idNode > > > > &matchings_path, std::vector< dataType > &distances, bool useDoubleInput=false, bool isFirstInput=true)
void setBranchDecomposition(bool useBD)
void setNormalizedWasserstein(bool normalizedWasserstein)
void setDistanceSquaredRoot(bool distanceSquaredRoot)
void setAssignmentSolver(int assignmentSolver)
void convertBranchDecompositionMatching(ftm::FTMTree_MT *tree1, ftm::FTMTree_MT *tree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &outputMatching)
double mixDistances(dataType distance1, dataType distance2)
void preprocessingPipeline(ftm::MergeTree< dataType > &mTree, double epsilonTree, double epsilon2Tree, double epsilon3Tree, bool branchDecompositionT, bool useMinMaxPairT, bool cleanTreeT, double persistenceThreshold, std::vector< int > &nodeCorr, bool deleteInconsistentNodes=true, bool removeMergedSaddles=false)
void printTreesStats(std::vector< ftm::FTMTree_MT * > &trees)
void postprocessingPipeline(ftm::FTMTree_MT *tree)
void copyMinMaxPair(ftm::MergeTree< dataType > &mTree1, ftm::MergeTree< dataType > &mTree2, bool setOrigins=false)
std::vector< std::vector< int > > treesNodeCorr_
void preprocessTree(ftm::FTMTree_MT *tree, bool deleteInconsistentNodes=true)
void setKeepSubtree(bool keepSubtree)
void persistenceThresholding(ftm::FTMTree_MT *tree, double persistenceThresholdT, std::vector< ftm::idNode > &deletedNodes)
void mixDistancesMatrix(std::vector< std::vector< dataType > > &distanceMatrix, std::vector< std::vector< dataType > > &distanceMatrix2)
void computeCentroids(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::MergeTree< dataType > > &centroids, matchingVectorType &outputMatching, std::vector< double > &alphas, std::vector< int > &clusteringAssignment, std::vector< ftm::FTMTree_MT * > &trees2, std::vector< ftm::MergeTree< dataType > > &centroids2, matchingVectorType &outputMatching2)
void assignmentCentroidsNaive(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< std::tuple< int, int > > &assignmentC, std::vector< dataType > &bestDistanceT, std::vector< ftm::FTMTree_MT * > &trees2, std::vector< ftm::MergeTree< dataType > > &centroids2)
void copyCentroids(std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< ftm::MergeTree< dataType > > &oldCentroids)
void setMixtureCoefficient(double coef)
void postprocessingClustering(std::vector< ftm::MergeTree< dataType > > &trees, std::vector< ftm::MergeTree< dataType > > &centroids, matchingVectorType &outputMatching, std::vector< int > &clusteringAssignment)
void initAcceleratedKMeans(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< ftm::FTMTree_MT * > &trees2, std::vector< ftm::MergeTree< dataType > > &centroids2)
void fixMergedRootOriginClustering(std::vector< ftm::MergeTree< dataType > > &centroids)
void getCentroidsDistanceMatrix(std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< std::vector< double > > &distanceMatrix, bool useDoubleInput=false, bool isFirstInput=true)
void initAcceleratedKMeansVectors(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< ftm::FTMTree_MT * > &ttkNotUsed(trees2))
void printCentroidsStats(std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< ftm::MergeTree< dataType > > &centroids2)
void computeOneBarycenter(std::vector< ftm::FTMTree_MT * > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< double > &alphas, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &finalMatchings)
void setNoCentroids(unsigned int noCentroidsT)
void preprocessingClustering(std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< int > > &nodeCorr, bool useMinMaxPairT=true)
void finalAssignmentCentroids(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::MergeTree< dataType > > &centroids, matchingVectorType &matchingsC, std::vector< std::tuple< int, int > > &assignmentC, std::vector< dataType > &bestDistanceT, std::vector< ftm::FTMTree_MT * > &trees2, std::vector< ftm::MergeTree< dataType > > &centroids2, matchingVectorType &matchingsC2)
void execute(std::vector< ftm::MergeTree< dataType > > &trees, matchingVectorType &outputMatching, std::vector< double > &alphas, std::vector< int > &clusteringAssignment, std::vector< ftm::MergeTree< dataType > > &trees2, matchingVectorType &outputMatching2, std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< ftm::MergeTree< dataType > > &centroids2)
std::vector< std::vector< int > > getTrees2NodeCorr()
void assignmentCentroidsAccelerated(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< std::tuple< int, int > > &assignmentC, std::vector< dataType > &bestDistanceT, std::vector< ftm::FTMTree_MT * > &trees2, std::vector< ftm::MergeTree< dataType > > &centroids2)
void execute(std::vector< ftm::MergeTree< dataType > > &trees, matchingVectorType &outputMatching, std::vector< int > &clusteringAssignment, std::vector< ftm::MergeTree< dataType > > &centroids)
void putBackMinMaxPair(std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< ftm::MergeTree< dataType > > &centroids2)
bool samePreviousAssignment(int clusterId)
bool updateCentroids(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< double > &alphas, std::vector< std::tuple< int, int > > &assignmentC)
void initCentroids(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::FTMTree_MT * > &trees2, std::vector< std::vector< ftm::MergeTree< dataType > > > &allCentroids)
void execute(std::vector< ftm::MergeTree< dataType > > &trees, matchingVectorType &outputMatching, std::vector< int > &clusteringAssignment, std::vector< ftm::MergeTree< dataType > > &trees2, matchingVectorType &outputMatching2, std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< ftm::MergeTree< dataType > > &centroids2)
~MergeTreeClustering() override=default
void matchingCorrespondence(treesMatchingVector &matchingT, std::vector< int > &nodeCorr, std::vector< int > &assignedTreesIndex)
void initNewCentroid(std::vector< ftm::FTMTree_MT * > &trees, ftm::MergeTree< dataType > &centroid, int noNewCentroid)
void assignmentCentroids(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::MergeTree< dataType > > &centroids, std::vector< std::tuple< int, int > > &assignmentC, std::vector< dataType > &bestDistanceT, std::vector< ftm::FTMTree_MT * > &trees2, std::vector< ftm::MergeTree< dataType > > &centroids2)
double getElapsedTime()
Definition Timer.h:15
Node * getNode(idNode nodeId) const
Definition FTMTree_MT.h:393
idNode getNumberOfNodes() const
Definition FTMTree_MT.h:389
void setOrigin(SimplexId linked)
Definition FTMNode.h:72
MergeTree< dataType > cleanMergeTree(ftm::FTMTree_MT *tree, std::vector< int > &nodeCorr, bool useBD=true)
MergeTree< dataType > copyMergeTree(const ftm::FTMTree_MT *tree, bool doSplitMultiPersPairs=false)
void mergeTreeToFTMTree(std::vector< MergeTree< dataType > > &trees, std::vector< ftm::FTMTree_MT * > &treesT)
unsigned int idNode
Node index in vect_nodes_.
TTK base package defining the standard types.
ftm::FTMTree_MT tree
Definition FTMTree_MT.h:906
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)