60 "MergeTreeBarycenter");
62#ifdef TTK_ENABLE_OPENMP4
63 omp_set_max_active_levels(100);
138 template <
class dataType>
140 std::vector<ftm::FTMTree_MT *> &trees2,
141 std::vector<std::vector<double>> &distanceMatrix,
142 bool useDoubleInput =
false,
143 bool isFirstInput =
true) {
144 distanceMatrix.clear();
145 distanceMatrix.resize(trees.size(), std::vector<double>(trees.size(), 0));
146#ifdef TTK_ENABLE_OPENMP4
147#pragma omp parallel for schedule(dynamic) \
148 num_threads(this->threadNumber_) if(parallelize_)
150 for(
unsigned int i = 0; i < trees.size(); ++i)
151 for(
unsigned int j = i + 1; j < trees.size(); ++j) {
152 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching;
155 useDoubleInput, isFirstInput);
156 distanceMatrix[i][j] = distance;
157 distanceMatrix[j][i] = distance;
161 template <
class dataType>
163 std::vector<std::vector<double>> &distanceMatrix,
164 bool useDoubleInput =
false,
165 bool isFirstInput =
true) {
167 trees, trees, distanceMatrix, useDoubleInput, isFirstInput);
170 template <
class dataType>
172 std::vector<ftm::FTMTree_MT *> &trees,
173 unsigned int barycenterMaximumNumberOfPairs,
174 double sizeLimitPercent,
176 mTreesLimited.resize(trees.size());
177#ifdef TTK_ENABLE_OPENMP4
178#pragma omp parallel for schedule(dynamic) \
179 num_threads(this->threadNumber_) if(parallelize_)
181 for(
unsigned int i = 0; i < trees.size(); ++i) {
184 barycenterMaximumNumberOfPairs, sizeLimitPercent);
189 template <
class dataType>
191 std::vector<ftm::FTMTree_MT *> &trees,
192 std::vector<std::vector<double>> &distanceMatrix,
193 unsigned int barycenterMaximumNumberOfPairs,
194 double sizeLimitPercent,
195 bool useDoubleInput =
false,
196 bool isFirstInput =
true) {
197 std::vector<ftm::MergeTree<dataType>> mTreesLimited;
199 trees, barycenterMaximumNumberOfPairs, sizeLimitPercent, mTreesLimited);
200 std::vector<ftm::FTMTree_MT *> treesLimited;
203 trees, treesLimited, distanceMatrix, useDoubleInput, isFirstInput);
206 template <
class dataType>
208 std::vector<ftm::FTMTree_MT *> &trees,
209 std::vector<std::vector<double>> &distanceMatrix,
210 unsigned int barycenterMaximumNumberOfPairs,
211 double sizeLimitPercent,
212 bool useDoubleInput =
false,
213 bool isFirstInput =
true) {
214 if(barycenterMaximumNumberOfPairs <= 0 and sizeLimitPercent <= 0.0)
216 trees, distanceMatrix, useDoubleInput, isFirstInput);
219 trees, distanceMatrix, barycenterMaximumNumberOfPairs,
220 sizeLimitPercent, useDoubleInput, isFirstInput);
223 template <
class dataType>
225 std::vector<ftm::FTMTree_MT *> &trees2,
226 unsigned int barycenterMaximumNumberOfPairs,
227 double sizeLimitPercent,
228 bool distMinimizer =
true) {
231 std::vector<std::vector<double>> distanceMatrix, distanceMatrix2;
232 bool const useDoubleInput = (trees2.size() != 0);
234 barycenterMaximumNumberOfPairs,
235 sizeLimitPercent, useDoubleInput);
236 if(trees2.size() != 0)
238 trees2, distanceMatrix2, barycenterMaximumNumberOfPairs,
239 sizeLimitPercent, useDoubleInput,
false);
243 = distMinimizer ? std::numeric_limits<dataType>::max() : 0;
244 std::vector<int> sizes(trees.size());
245 for(
unsigned int i = 0; i < trees.size(); ++i) {
247 for(
unsigned int j = 0; j < distanceMatrix[i].size(); ++j)
248 value += (not useDoubleInput ? distanceMatrix[i][j]
250 distanceMatrix2[i][j]));
251 if((distMinimizer and value < bestValue)
252 or (not distMinimizer and value > bestValue)) {
257 sizes[i] *= (distMinimizer) ? 1 : -1;
260 std::random_device rd;
261 std::default_random_engine generator(rd());
262 std::discrete_distribution<int> distribution(
263 sizes.begin(), sizes.end());
264 bestIndex = distribution(generator);
269 template <
class dataType>
271 std::vector<ftm::FTMTree_MT *> &trees2,
272 double sizeLimitPercent,
273 bool distMinimizer =
true) {
276 sizeLimitPercent, distMinimizer);
279 template <
class dataType>
281 bool distMinimizer =
true) {
282 std::vector<ftm::FTMTree_MT *> trees2;
288 template <
class dataType>
291 bool distMinimizer =
true) {
314 template <
class dataType>
319 std::vector<dataType> &newScalarsVector,
320 std::vector<std::tuple<ftm::idNode, ftm::idNode, int>> &nodesToProcess,
324 std::queue<std::tuple<ftm::idNode, ftm::idNode>> queue;
325 queue.emplace(nodeId2, nodeId1);
326 nodesToProcess.emplace_back(nodeId2, nodeId1, i);
327 while(!queue.empty()) {
328 auto &queueTuple = queue.front();
332 newScalarsVector.push_back(
334 newScalarsVector.push_back(tree->
getValue<dataType>(node));
336 std::vector<ftm::idNode> children;
338 for(
auto child : children) {
339 queue.emplace(child, nodeCpt + 1);
340 nodesToProcess.emplace_back(child, nodeCpt + 1, i);
348 template <
class dataType>
352 std::vector<std::tuple<ftm::idNode, ftm::idNode, int>> &nodesToProcess,
353 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode>>>
358 nodesProcessed.
clear();
359 nodesProcessed.resize(noTrees);
360 for(
auto &processTuple : nodesToProcess) {
361 ftm::idNode const parent = std::get<1>(processTuple);
363 int const index = std::get<2>(processTuple);
364 nodesProcessed[index].emplace_back(
365 nodeTree1 + 1, std::get<0>(processTuple));
375 template <
class dataType>
379 std::vector<std::tuple<ftm::idNode, ftm::idNode, int>> &nodesToProcess,
380 std::vector<dataType> &newScalarsVector,
381 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode>>>
401 template <
class dataType>
403 std::vector<ftm::FTMTree_MT *> &trees,
405 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
413 std::vector<std::vector<ftm::idNode>> matrixMatchings(trees.size());
415 for(
unsigned int i = 0; i < matchings.size(); ++i) {
416 auto &matching = matchings[i];
417 matrixMatchings[i].resize(trees[i]->getNumberOfNodes(),
418 std::numeric_limits<ftm::idNode>::max());
419 for(
auto &match : matching) {
420 matrixMatchings[i][std::get<1>(match)] = std::get<0>(match);
421 baryMatched[std::get<0>(match)] =
true;
426 std::vector<std::vector<ftm::idNode>> nodesToAdd(trees.size());
427#ifdef TTK_ENABLE_OPENMP4
428#pragma omp parallel for schedule(dynamic) \
429 num_threads(this->threadNumber_) if(parallelize_)
431 for(
unsigned int i = 0; i < trees.size(); ++i) {
433 std::queue<ftm::idNode> queue;
435 while(!queue.empty()) {
438 bool processChildren =
true;
440 if(matrixMatchings[i][node]
441 == std::numeric_limits<ftm::idNode>::max()) {
443 processChildren =
false;
444 nodesToAdd[i].push_back(node);
449 "barycenter with keepSubtree_=true is not implemented yet");
452 if(processChildren) {
453 std::vector<ftm::idNode> children;
454 trees[i]->getChildren(node, children);
455 for(
auto child : children)
456 if(not(trees[i]->isThereOnlyOnePersistencePair()
457 and trees[i]->isLeaf(child)))
458 queue.emplace(child);
463 bool foundRootNotMatched =
false;
464 for(
unsigned int i = 0; i < trees.size(); ++i)
466 matrixMatchings[i][trees[i]->getRoot()]);
467 if(foundRootNotMatched)
468 printWrn(
"[updateBarycenterTreeStructure] an input tree has its root "
473 if(not baryMatched[i])
479 std::vector<std::tuple<ftm::idNode, ftm::idNode, int>> nodesToProcess;
480 std::vector<dataType> newScalarsVector;
482 for(
unsigned int i = 0; i < nodesToAdd.size(); ++i) {
483 for(
auto node : nodesToAdd[i]) {
485 = matrixMatchings[i][trees[i]->getParentSafe(node)];
486 if(matchings[i].size() == 0)
487 parent = baryTreeRoot;
491 and matchings[i].size() != 0) {
492 std::stringstream ss;
493 ss << trees[i]->getParentSafe(node) <<
" _ " << node;
495 printMsg(trees[i]->printTree().str());
496 printMsg(trees[i]->printPairsFromTree<dataType>(
true).str());
498 std::stringstream ss2;
499 ss2 <<
"parent " << parent;
504 std::vector<dataType> addedScalars;
506 parent, trees[i], node, addedScalars, nodesToProcess, nodeCpt, i);
507 newScalarsVector.insert(
508 newScalarsVector.end(), addedScalars.begin(), addedScalars.end());
512 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode>>>
515 nodesToProcess, newScalarsVector,
517 for(
unsigned int i = 0; i < matchings.size(); ++i) {
518 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
520 for(
auto &tup : nodesProcessed[i])
521 nodesProcessedT.emplace_back(
522 std::get<0>(tup), std::get<1>(tup), -1);
523 matchings[i].insert(matchings[i].
end(), nodesProcessedT.begin(),
524 nodesProcessedT.end());
530 printErr(
"barycenter with keepSubtree_=true is not implemented yet");
534 template <
class dataType>
535 std::tuple<dataType, dataType>
537 std::tuple<dataType, dataType> birthDeath;
547 template <
class dataType>
548 std::tuple<dataType, dataType>
551 std::vector<dataType> &newScalarsVector,
552 std::vector<ftm::FTMTree_MT *> &trees,
553 std::vector<ftm::idNode> &nodes,
554 std::vector<double> &alphas) {
555 dataType newBirth = 0, newDeath = 0;
558 dataType tempBirth = 0, tempDeath = 0;
560 for(
unsigned int i = 0; i < trees.size(); ++i)
561 if(nodes[i] != std::numeric_limits<ftm::idNode>::max())
562 alphaSum += alphas[i];
563 for(
unsigned int i = 0; i < trees.size(); ++i) {
565 if(nodes[i] != std::numeric_limits<ftm::idNode>::max()) {
568 dataType tTempBirth = 0, tTempDeath = 0;
569 tTempBirth += std::get<0>(iBirthDeath);
570 tTempDeath += std::get<1>(iBirthDeath);
571 tempBirth += tTempBirth * alphas[i] / alphaSum;
572 tempDeath += tTempDeath * alphas[i] / alphaSum;
575 dataType
const projec = (tempBirth + tempDeath) / 2;
578 for(
unsigned int i = 0; i < trees.size(); ++i) {
579 dataType iBirth = projec, iDeath = projec;
581 if(nodes[i] != std::numeric_limits<ftm::idNode>::max()) {
584 iBirth = std::get<0>(iBirthDeath);
585 iDeath = std::get<1>(iBirthDeath);
587 newBirth += alphas[i] * iBirth;
588 newDeath += alphas[i] * iDeath;
593 baryTree, nodeId, newScalarsVector,
false);
595 baryTree, nodeId, newScalarsVector);
598 volatile dataType tempBirthT = newBirth * (mu_max - mu_min);
599 volatile dataType tempDeathT = newDeath * (mu_max - mu_min);
600 newBirth = tempBirthT + mu_min;
601 newDeath = tempDeathT + mu_min;
604 return std::make_tuple(newBirth, newDeath);
607 template <
class dataType>
608 std::tuple<dataType, dataType>
614 std::vector<dataType> &newScalarsVector) {
616 dataType newBirth = std::get<0>(birthDeath);
617 dataType newDeath = std::get<1>(birthDeath);
618 dataType
const projec = (newBirth + newDeath) / 2;
620 newBirth = alpha * newBirth + (1 - alpha) * projec;
621 newDeath = alpha * newDeath + (1 - alpha) * projec;
626 baryTree, nodeB, newScalarsVector,
false);
628 baryTree, nodeB, newScalarsVector);
631 volatile dataType tempBirthT = newBirth * (mu_max - mu_min);
632 volatile dataType tempDeathT = newDeath * (mu_max - mu_min);
633 newBirth = tempBirthT + mu_min;
634 newDeath = tempDeathT + mu_min;
637 return std::make_tuple(newBirth, newDeath);
640 template <
class dataType>
642 std::vector<ftm::FTMTree_MT *> &trees,
644 std::vector<double> &alphas,
645 unsigned int indexAddedNodes,
646 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
649 bool const isJT = baryTree->
isJoinTree<dataType>();
654 std::vector<std::vector<ftm::idNode>> baryMatching(
656 std::vector<ftm::idNode>(
657 trees.size(), std::numeric_limits<ftm::idNode>::max()));
658 std::vector<std::tuple<int, ftm::idNode>> nodesAddedTree(
660 for(
unsigned int i = 0; i < matchings.size(); ++i) {
661 auto &matching = matchings[i];
662 for(
auto &match : matching) {
663 if(std::get<0>(match) >= indexAddedNodes)
665 nodesAddedTree[std::get<0>(match)]
666 = std::make_tuple(i, std::get<1>(match));
668 baryMatching[std::get<0>(match)][i] = std::get<1>(match);
675 std::queue<ftm::idNode> queue;
677 while(!queue.empty()) {
680 std::tuple<dataType, dataType> newBirthDeath;
681 if(node < indexAddedNodes) {
684 trees, baryMatching[node], alphas);
686 int const i = std::get<0>(nodesAddedTree[node]);
687 ftm::idNode const nodeT = std::get<1>(nodesAddedTree[node]);
689 trees[i], nodeT, alphas[i], baryMergeTree, node, newScalarsVector);
692 = (isJT ? std::get<1>(newBirthDeath) : std::get<0>(newBirthDeath));
693 dataType nodeOriginScalar
694 = (isJT ? std::get<0>(newBirthDeath) : std::get<1>(newBirthDeath));
695 newScalarsVector[node] = nodeScalar;
698 std::vector<ftm::idNode> children;
700 for(
auto child : children)
701 queue.emplace(child);
706 dataType mergedRootOriginScalar = 0.0;
707 for(
unsigned int i = 0; i < trees.size(); ++i)
708 mergedRootOriginScalar += trees[i]->getValue<dataType>(
709 trees[i]->getMergedRootOrigin<dataType>());
710 mergedRootOriginScalar /= trees.size();
711 newScalarsVector[mergedRootOrigin] = mergedRootOriginScalar;
714 setTreeScalars(baryMergeTree, newScalarsVector);
715 std::vector<ftm::idNode> deletedNodesT;
717 &(baryMergeTree.
tree), 0, deletedNodesT);
722 template <
class dataType>
724 std::vector<ftm::FTMTree_MT *> &trees,
726 std::vector<double> &alphas,
727 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
732 trees, baryMergeTree, alphas, indexAddedNodes, matchings);
738 template <
class dataType>
742 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matching,
744 bool useDoubleInput =
false,
745 bool isFirstInput =
true) {
768 = mergeTreeDistance.
computeDistance<dataType>(baryTree, tree, matching);
769 std::stringstream ss, ss2;
770 ss <<
"distance tree : " << distance;
772 ss2 <<
"distance²tree : " << distance * distance;
779 template <
class dataType>
783 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matching,
785 bool useDoubleInput =
false,
786 bool isFirstInput =
true) {
788 distance, useDoubleInput, isFirstInput);
791 template <
class dataType>
795 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matching,
797 bool useDoubleInput =
false,
798 bool isFirstInput =
true) {
800 matching, distance, useDoubleInput,
804 template <
class dataType>
806 std::vector<ftm::FTMTree_MT *> &trees,
808 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
810 std::vector<dataType> &distances,
811 bool useDoubleInput =
false,
812 bool isFirstInput =
true) {
815 useDoubleInput, isFirstInput);
818 useDoubleInput, isFirstInput);
821 template <
class dataType>
823 std::vector<ftm::FTMTree_MT *> &trees,
825 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
827 std::vector<dataType> &distances,
828 bool useDoubleInput =
false,
829 bool isFirstInput =
true) {
830#ifdef TTK_ENABLE_OPENMP4
831#pragma omp parallel num_threads(this->threadNumber_) \
832 shared(baryMergeTree) if(parallelize_)
834#pragma omp single nowait
837 useDoubleInput, isFirstInput);
838#ifdef TTK_ENABLE_OPENMP4
843 template <
class dataType>
845 std::vector<ftm::FTMTree_MT *> &trees,
847 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
849 std::vector<dataType> &distances,
850 bool useDoubleInput =
false,
851 bool isFirstInput =
true) {
852 for(
unsigned int i = 0; i < trees.size(); ++i)
853#ifdef TTK_ENABLE_OPENMP4
854#pragma omp task firstprivate(i)
UNTIED() \
855 shared(baryMergeTree, matchings, distances)
858 distances[i], useDoubleInput,
860#ifdef TTK_ENABLE_OPENMP4
868 template <
class dataType>
872 std::vector<ftm::FTMTree_MT *> &oriTrees,
874 std::vector<std::vector<ftm::idNode>> &deletedNodes) {
875 deletedNodes.clear();
876 deletedNodes.resize(oriTrees.size());
877 unsigned int noTreesUnscaled = 0;
880 for(
unsigned int i = 0; i < oriTrees.size(); ++i) {
881 double persistenceThreshold = 50.0;
882 if(iterationNumber != -1) {
884 int const noPairs = mergeTrees[i].tree.getRealNumberOfNodes();
887 std::vector<std::tuple<ftm::idNode, ftm::idNode, dataType>> pairs;
888 oriTrees[i]->getPersistencePairsFromTree<dataType>(
892 double const multiplier
896 int const decrement = multiplier * pairs.size() / 10;
897 int thresholdIndex = pairs.size() - noPairs - std::max(decrement, 2);
898 thresholdIndex = std::max(thresholdIndex, 0);
899 const double persistence = std::get<2>(pairs[thresholdIndex]);
901 = persistence / std::get<2>(pairs.back()) * 100.0;
902 if(thresholdIndex == 0) {
903 persistenceThreshold = 0.;
907 if(persistenceThreshold != 0.) {
911 &(mt.
tree), persistenceThreshold, deletedNodes[i]);
912 if(mergeTrees.size() == 0)
913 mergeTrees.resize(oriTrees.size());
915 trees[i] = &(mt.
tree);
917 trees[i] = oriTrees[i];
923 return noTreesUnscaled;
926 template <
class dataType>
928 std::vector<ftm::FTMTree_MT *> &oriTrees,
929 std::vector<std::vector<ftm::idNode>> &deletedNodes,
930 std::vector<dataType> &distances) {
931 for(
unsigned int i = 0; i < oriTrees.size(); ++i)
932 for(
auto node : deletedNodes[i])
939 template <
class dataType>
941 std::vector<ftm::FTMTree_MT *> &trees,
943 std::vector<double> &alphas,
944 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
946 bool finalAsgnDoubleInput =
false,
947 bool finalAsgnFirstInput =
true) {
953 std::vector<ftm::FTMTree_MT *> oriTrees;
954 std::vector<ftm::MergeTree<dataType>> scaledMergeTrees;
955 std::vector<std::vector<ftm::idNode>> deletedNodes;
957 oriTrees.insert(oriTrees.end(), trees.begin(), trees.end());
959 trees, scaledMergeTrees, oriTrees, -1, deletedNodes);
960 std::vector<ftm::idNode> deletedNodesT;
963 bool treesUnscaled =
false;
969 bool converged =
false;
970 dataType frechetEnergy = -1;
971 dataType minFrechet = std::numeric_limits<dataType>::max();
974 while(not converged) {
980 std::stringstream ss;
981 ss <<
"Iteration " << NoIteration;
985 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
986 matchings(trees.size());
987 std::vector<dataType> distances(trees.size(), -1);
990 Timer t_addDeletedNodes;
993 oriTrees, deletedNodes, distances);
995 auto t_assignment_time
1004 baryTree = &(baryMergeTree.
tree);
1009 dataType currentFrechetEnergy = 0;
1010 for(
unsigned int i = 0; i < trees.size(); ++i)
1011 currentFrechetEnergy += alphas[i] * distances[i] * distances[i];
1013 = std::abs((
double)(frechetEnergy - currentFrechetEnergy));
1014 converged = (frechetDiff <=
tol_);
1016 frechetEnergy = currentFrechetEnergy;
1017 tol_ = frechetEnergy / 125.0;
1019 std::stringstream ss4;
1024 ss4 <<
"Frechet energy : " << frechetEnergy;
1027 minFrechet = std::min(minFrechet, frechetEnergy);
1029 cptBlocked = (minFrechet < frechetEnergy) ? cptBlocked + 1 : 0;
1030 converged = (cptBlocked >= 10);
1036 trees, scaledMergeTrees, oriTrees, NoIteration, deletedNodes);
1037 treesUnscaled = (noTreesUnscaled == oriTrees.size());
1045 std::vector<dataType> distances(trees.size(), -1);
1047 finalAsgnDoubleInput, finalAsgnFirstInput);
1048 for(
auto dist : distances)
1050 dataType currentFrechetEnergy = 0;
1051 for(
unsigned int i = 0; i < trees.size(); ++i)
1052 currentFrechetEnergy += alphas[i] * distances[i] * distances[i];
1054 std::stringstream ss, ss2;
1055 ss <<
"Frechet energy : " << currentFrechetEnergy;
1064 trees, baryMergeTree, finalMatchings, distances);
1068 scaledMergeTrees.clear();
1070 trees.insert(trees.end(), oriTrees.begin(), oriTrees.end());
1074 template <
class dataType>
1077 std::vector<double> &alphas,
1078 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
1081 bool finalAsgnDoubleInput =
false,
1082 bool finalAsgnFirstInput =
true) {
1086 for(
unsigned int i = 0; i < trees.size(); ++i) {
1096 std::vector<ftm::FTMTree_MT *> treesT;
1102 finalAsgnDoubleInput, finalAsgnFirstInput);
1106 std::vector<int>
const allRealNodes(trees.size());
1107 for(
unsigned int i = 0; i < trees.size(); ++i) {
1113 for(
unsigned int i = 0; i < trees.size(); ++i) {
1115 &(baryMergeTree.
tree), treesT[i], finalMatchings[i]);
1120 template <
class dataType>
1123 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
1126 bool finalAsgnDoubleInput =
false,
1127 bool finalAsgnFirstInput =
true) {
1128 std::vector<double> alphas;
1129 if(trees.size() != 2) {
1130 for(
unsigned int i = 0; i < trees.size(); ++i)
1131 alphas.push_back(1.0 / trees.size());
1133 alphas.push_back(
alpha_);
1134 alphas.push_back(1 -
alpha_);
1138 finalAsgnDoubleInput, finalAsgnFirstInput);
1144 template <
class dataType>
1146 std::vector<ftm::FTMTree_MT *> &trees,
1147 unsigned int barycenterMaximumNumberOfPairs,
1149 bool useBD =
true) {
1151 unsigned int percentMaxPairs = metric * percent / 100.0;
1153 unsigned int newNoNodes;
1154 if(barycenterMaximumNumberOfPairs > 0 and percent > 0)
1155 newNoNodes = std::min(barycenterMaximumNumberOfPairs, percentMaxPairs);
1156 else if(barycenterMaximumNumberOfPairs > 0)
1157 newNoNodes = barycenterMaximumNumberOfPairs;
1158 else if(percent > 0)
1159 newNoNodes = percentMaxPairs;
1165 template <
class dataType>
1167 std::vector<ftm::FTMTree_MT *> &trees,
1169 bool useBD =
true) {
1174 template <
class dataType>
1176 std::vector<ftm::FTMTree_MT *> &trees,
1177 bool useBD =
true) {
1185 template <
class dataType>
1192 int maxIndex = std::get<0>(tup);
1193 dataType oldOriginValue = std::get<1>(tup);
1197 std::vector<dataType> newScalarsVector;
1200 if((isJT and tree->
getValue<dataType>(maxIndex) > oldOriginValue)
1202 and tree->
getValue<dataType>(maxIndex) < oldOriginValue)) {
1203 newScalarsVector[treeRoot] = newScalarsVector[maxIndex];
1204 newScalarsVector[maxIndex] = oldOriginValue;
1206 newScalarsVector[treeRoot] = oldOriginValue;
1207 setTreeScalars(barycenter, newScalarsVector);
1218 std::stringstream ss;
1219 ss <<
"Barycenter number of nodes : " << noNodes <<
" / " << noNodesT;
1226 template <
class dataType>
1228 std::vector<ftm::FTMTree_MT *> &trees,
1230 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
1232 std::vector<dataType> distances) {
1233 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching;
1236 if(distance != (distances[0] + distances[1])) {
1237 std::stringstream ss, ss2, ss3, ss4;
1238 ss <<
"distance T1 T2 : " << distance;
1240 ss2 <<
"distance T1 T' T2 : " << distances[0] + distances[1];
1242 ss3 <<
"distance T1 T' : " << distances[0];
1244 ss4 <<
"distance T' T2 : " << distances[1];
1249 auto baryTree = &(baryMergeTree.
tree);
1250 std::vector<std::vector<ftm::idNode>> baryMatched(
1251 baryTree->getNumberOfNodes(),
1252 std::vector<ftm::idNode>(
1253 trees.size(), std::numeric_limits<ftm::idNode>::max()));
1254 for(
unsigned int i = 0; i < finalMatchings.size(); ++i)
1255 for(
auto &match : finalMatchings[i])
1256 baryMatched[std::get<0>(match)][i] = std::get<1>(match);
1258 std::queue<ftm::idNode> queue;
1259 queue.emplace(baryTree->getRoot());
1260 while(!queue.empty()) {
1261 auto node = queue.front();
1263 std::vector<dataType> costs(trees.size());
1264 for(
unsigned int i = 0; i < trees.size(); ++i)
1265 if(baryMatched[node][i] != std::numeric_limits<ftm::idNode>::max())
1267 baryTree, node, trees[i], baryMatched[node][i]);
1271 if(baryMatched[node][0] != std::numeric_limits<ftm::idNode>::max()
1272 and baryMatched[node][1] != std::numeric_limits<ftm::idNode>::max())
1274 trees[0], baryMatched[node][0], trees[1], baryMatched[node][1]);
1275 else if(baryMatched[node][0] == std::numeric_limits<ftm::idNode>::max())
1277 else if(baryMatched[node][1] == std::numeric_limits<ftm::idNode>::max())
1281 costs[0] = std::sqrt(costs[0]);
1282 costs[1] = std::sqrt(costs[1]);
1283 cost = std::sqrt(cost);
1284 if(std::abs((
double)(costs[0] - costs[1])) > 1e-7) {
1286 std::stringstream ss, ss2, ss3, ss4;
1287 ss <<
"cost T' T0 : " << costs[0];
1289 ss2 <<
"cost T' T1 : " << costs[1];
1291 ss3 <<
"cost T0 T1 : " << cost;
1293 ss4 <<
"cost T0 T' T1 : " << costs[0] + costs[1];
1295 if(std::abs((
double)((costs[0] + costs[1]) - cost)) > 1e-7) {
1296 std::stringstream ss5;
1298 << std::abs((
double)((costs[0] + costs[1]) - cost));
1301 std::stringstream ss6;
1302 ss6 <<
"diff2 : " << std::abs((
double)(costs[0] - costs[1]));
1306 for(
unsigned int i = 0; i < 2; ++i)
1307 if(baryMatched[node][i]
1308 != std::numeric_limits<ftm::idNode>::max()) {
1310 trees[i]->printNode2<dataType>(baryMatched[node][i]).str());
1312 ->printNode2<dataType>(
1313 trees[i]->getParentSafe(baryMatched[node][i]))
1317 std::vector<ftm::idNode> children;
1318 baryTree->getChildren(node, children);
1319 for(
auto child : children)
1320 queue.emplace(child);
#define UNTIED()
TTK processing package that efficiently computes the contour tree of scalar data and more (data segme...
virtual int setThreadNumber(const int threadNumber)
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
void setDebugMsgPrefix(const std::string &prefix)
virtual int setDebugLevel(const int &debugLevel)
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
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)
std::tuple< dataType, dataType > getParametrizedBirthDeath(ftm::FTMTree_MT *tree1, ftm::idNode nodeId1)
double getAddDeletedNodesTime()
void getParametrizedDistanceMatrix(std::vector< ftm::FTMTree_MT * > &trees, std::vector< std::vector< double > > &distanceMatrix, unsigned int barycenterMaximumNumberOfPairs, double sizeLimitPercent, bool useDoubleInput=false, bool isFirstInput=true)
void verifyBarycenterTwoTrees(std::vector< ftm::FTMTree_MT * > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &finalMatchings, std::vector< dataType > distances)
void computeOneDistance(ftm::FTMTree_MT *tree, ftm::FTMTree_MT *baryTree, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matching, dataType &distance, bool useDoubleInput=false, bool isFirstInput=true)
void updateNodesAndScalars(ftm::MergeTree< dataType > &mTree1, int noTrees, std::vector< std::tuple< ftm::idNode, ftm::idNode, int > > &nodesToProcess, std::vector< dataType > &newScalarsVector, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode > > > &nodesProcessed)
unsigned int persistenceScaling(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::MergeTree< dataType > > &mergeTrees, std::vector< ftm::FTMTree_MT * > &oriTrees, int iterationNumber, std::vector< std::vector< ftm::idNode > > &deletedNodes)
void fixMergedRootOriginBarycenter(ftm::MergeTree< dataType > &barycenter)
void setAddNodes(bool addNodesT)
void setIsCalled(bool ic)
void setBarycenterMaxIter(int barycenterMaxIter)
void setPreprocess(bool preproc)
void computeOneDistance(ftm::MergeTree< dataType > &baryMergeTree, ftm::MergeTree< dataType > &baryMergeTree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matching, dataType &distance, bool useDoubleInput=false, bool isFirstInput=true)
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)
double barycenterSizeLimitPercent_
void limitSizeBarycenter(ftm::MergeTree< dataType > &bary, std::vector< ftm::FTMTree_MT * > &trees, double percent, bool useBD=true)
std::tuple< dataType, dataType > interpolation(ftm::MergeTree< dataType > &baryMergeTree, ftm::idNode nodeId, std::vector< dataType > &newScalarsVector, std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::idNode > &nodes, std::vector< double > &alphas)
int getBestInitTreeIndex(std::vector< ftm::FTMTree_MT * > &trees, bool distMinimizer=true)
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, bool finalAsgnDoubleInput=false, bool finalAsgnFirstInput=true)
void assignmentPara(std::vector< ftm::FTMTree_MT * > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< dataType > &distances, bool useDoubleInput=false, bool isFirstInput=true)
void setPostprocess(bool postproc)
std::tuple< dataType, dataType > interpolationAdded(ftm::FTMTree_MT *tree, ftm::idNode nodeId, double alpha, ftm::MergeTree< dataType > &baryMergeTree, ftm::idNode nodeB, std::vector< dataType > &newScalarsVector)
unsigned int barycenterMaximumNumberOfPairs_
double progressiveSpeedDivisor_
double getAllDistanceTime()
void setBarycenterInitIndex(int barycenterInitIndex)
ftm::idNode getNodesAndScalarsToAdd(ftm::idNode nodeId1, ftm::FTMTree_MT *tree, ftm::idNode nodeId2, std::vector< dataType > &newScalarsVector, std::vector< std::tuple< ftm::idNode, ftm::idNode, int > > &nodesToProcess, ftm::idNode nodeCpt, int i)
Get information about the nodes to add in the barycenter.
void setDeterministic(bool deterministicT)
~MergeTreeBarycenter() override=default
void updateBarycenterTreeScalars(std::vector< ftm::FTMTree_MT * > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< double > &alphas, unsigned int indexAddedNodes, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings)
void addNodes(ftm::MergeTree< dataType > &mTree1, int noTrees, std::vector< std::tuple< ftm::idNode, ftm::idNode, int > > &nodesToProcess, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode > > > &nodesProcessed)
void initBarycenterTree(std::vector< ftm::FTMTree_MT * > &trees, ftm::MergeTree< dataType > &baryTree, bool distMinimizer=true)
void assignmentTask(std::vector< ftm::FTMTree_MT * > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< dataType > &distances, bool useDoubleInput=false, bool isFirstInput=true)
void execute(std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &finalMatchings, ftm::MergeTree< dataType > &baryMergeTree, bool finalAsgnDoubleInput=false, bool finalAsgnFirstInput=true)
void setProgressiveSpeedDivisor(double progSpeed)
void addScaledDeletedNodesCost(std::vector< ftm::FTMTree_MT * > &oriTrees, std::vector< std::vector< ftm::idNode > > &deletedNodes, std::vector< dataType > &distances)
void updateBarycenterTreeStructure(std::vector< ftm::FTMTree_MT * > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings)
std::vector< double > finalDistances_
bool progressiveBarycenter_
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 limitSizeBarycenter(ftm::MergeTree< dataType > &bary, std::vector< ftm::FTMTree_MT * > &trees, bool useBD=true)
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< dataType > &distances, bool useDoubleInput=false, bool isFirstInput=true)
void setBarycenterMaximumNumberOfPairs(unsigned int maxi)
double addDeletedNodesTime_
void computeOneDistance(ftm::FTMTree_MT *tree, ftm::MergeTree< dataType > &baryMergeTree, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matching, dataType &distance, bool useDoubleInput=false, bool isFirstInput=true)
void setAlpha(double alpha)
void setBarycenterSizeLimitPercent(double percent)
void getSizeLimitedDistanceMatrix(std::vector< ftm::FTMTree_MT * > &trees, std::vector< std::vector< double > > &distanceMatrix, unsigned int barycenterMaximumNumberOfPairs, double sizeLimitPercent, bool useDoubleInput=false, bool isFirstInput=true)
void updateBarycenterTree(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 > > > &matchings)
std::vector< double > getFinalDistances()
void getDistanceMatrix(std::vector< ftm::FTMTree_MT * > &trees, std::vector< std::vector< double > > &distanceMatrix, bool useDoubleInput=false, bool isFirstInput=true)
int getBestInitTreeIndex(std::vector< ftm::FTMTree_MT * > &trees, std::vector< ftm::FTMTree_MT * > &trees2, double sizeLimitPercent, bool distMinimizer=true)
void execute(std::vector< ftm::MergeTree< dataType > > &trees, std::vector< double > &alphas, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &finalMatchings, ftm::MergeTree< dataType > &baryMergeTree, bool finalAsgnDoubleInput=false, bool finalAsgnFirstInput=true)
void setBranchDecomposition(bool useBD)
void setNormalizedWasserstein(bool normalizedWasserstein)
void setDistanceSquaredRoot(bool distanceSquaredRoot)
void setAssignmentSolver(int assignmentSolver)
dataType deleteCost(const ftm::FTMTree_MT *tree, ftm::idNode nodeId)
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)
void keepMostImportantPairs(ftm::FTMTree_MT *tree, int n, bool useBD)
void setNodePerTask(int npt)
void convertBranchDecompositionMatching(ftm::FTMTree_MT *tree1, ftm::FTMTree_MT *tree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &outputMatching)
bool normalizedWasserstein_
dataType relabelCost(const ftm::FTMTree_MT *tree1, ftm::idNode nodeId1, const ftm::FTMTree_MT *tree2, ftm::idNode nodeId2)
double mixDistances(dataType distance1, dataType distance2)
double getSizeLimitMetric(std::vector< ftm::FTMTree_MT * > &trees)
void printTreesStats(std::vector< ftm::FTMTree_MT * > &trees)
void postprocessingPipeline(ftm::FTMTree_MT *tree)
void printMatching(std::vector< MatchingType > &matchings)
std::vector< std::vector< int > > treesNodeCorr_
void setKeepSubtree(bool keepSubtree)
void persistenceThresholding(ftm::FTMTree_MT *tree, double persistenceThresholdT, std::vector< ftm::idNode > &deletedNodes)
double mixDistancesMinMaxPairWeight(bool isFirstInput)
bool branchDecomposition_
std::tuple< int, dataType > fixMergedRootOrigin(ftm::FTMTree_MT *tree)
void setPreprocess(bool preproc)
void setPostprocess(bool postproc)
void setMinMaxPairWeight(double weight)
dataType computeDistance(const ftm::FTMTree_MT *tree1, const ftm::FTMTree_MT *tree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &outputMatching)
void setIsCalled(bool ic)
Node * getNode(idNode nodeId) const
const scalarType & getValue(SimplexId nodeId) const
void getChildren(idNode nodeId, std::vector< idNode > &res) const
idNode getNumberOfNodes() const
void setParent(idNode nodeId, idNode newParentNodeId)
void copyMergeTreeStructure(const FTMTree_MT *tree)
idNode getMergedRootOrigin() const
int getRealNumberOfNodes() const
void deleteNode(idNode nodeId)
std::tuple< dataType, dataType > getBirthDeath(idNode nodeId) const
bool isNodeIdInconsistent(idNode nodeId) const
idNode makeNode(SimplexId vertexId, SimplexId linked=nullVertex)
bool isNodeAlone(idNode nodeId) const
void setOrigin(SimplexId linked)
SimplexId getOrigin() const
void setTreeScalars(MergeTree< dataType > &mergeTree, std::vector< dataType > &scalarsVector)
MergeTree< dataType > cleanMergeTree(ftm::FTMTree_MT *tree, std::vector< int > &nodeCorr, bool useBD=true)
void getTreeScalars(const ftm::FTMTree_MT *tree, std::vector< dataType > &scalarsVector)
MergeTree< dataType > copyMergeTree(const ftm::FTMTree_MT *tree, bool doSplitMultiPersPairs=false)
void mergeTreeToFTMTree(std::vector< MergeTree< dataType > > &trees, std::vector< ftm::FTMTree_MT * > &treesT)
MergeTree< dataType > createEmptyMergeTree(int scalarSize)
unsigned int idNode
Node index in vect_nodes_.
TTK base package defining the standard types.
std::tuple< dataType, dataType > getNormalizedBirthDeath(const ftm::FTMTree_MT *tree, ftm::idNode nodeId, dataType newMin=0.0, dataType newMax=1.0)
dataType getMinMaxLocalFromVector(ftm::FTMTree_MT *tree, ftm::idNode nodeId, std::vector< dataType > &scalarsVector, bool getMin=true)
T end(std::pair< T, T > &p)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)