58 "MergeTreeBarycenter");
60#ifdef TTK_ENABLE_OPENMP4
128 template <
class dataType>
130 std::vector<ftm::FTMTree_MT *> &trees2,
131 std::vector<std::vector<double>> &distanceMatrix,
132 bool useDoubleInput =
false,
133 bool isFirstInput =
true) {
134 distanceMatrix.clear();
135 distanceMatrix.resize(trees.size(), std::vector<double>(trees.size(), 0));
136#ifdef TTK_ENABLE_OPENMP4
137#pragma omp parallel for schedule(dynamic) \
138 num_threads(this->threadNumber_) if(parallelize_)
140 for(
unsigned int i = 0; i < trees.size(); ++i)
141 for(
unsigned int j = i + 1; j < trees.size(); ++j) {
142 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching;
144 computeOneDistance<dataType>(trees[i], trees2[j], matching, distance,
145 useDoubleInput, isFirstInput);
146 distanceMatrix[i][j] = distance;
147 distanceMatrix[j][i] = distance;
151 template <
class dataType>
153 std::vector<std::vector<double>> &distanceMatrix,
154 bool useDoubleInput =
false,
155 bool isFirstInput =
true) {
156 getDistanceMatrix<dataType>(
157 trees, trees, distanceMatrix, useDoubleInput, isFirstInput);
160 template <
class dataType>
162 std::vector<ftm::FTMTree_MT *> &trees,
163 unsigned int barycenterMaximumNumberOfPairs,
164 double sizeLimitPercent,
166 mTreesLimited.resize(trees.size());
167 for(
unsigned int i = 0; i < trees.size(); ++i) {
168 mTreesLimited[i] = ftm::copyMergeTree<dataType>(trees[i]);
170 barycenterMaximumNumberOfPairs, sizeLimitPercent);
171 ftm::cleanMergeTree<dataType>(mTreesLimited[i]);
175 template <
class dataType>
177 std::vector<ftm::FTMTree_MT *> &trees,
178 std::vector<std::vector<double>> &distanceMatrix,
179 unsigned int barycenterMaximumNumberOfPairs,
180 double sizeLimitPercent,
181 bool useDoubleInput =
false,
182 bool isFirstInput =
true) {
183 std::vector<ftm::MergeTree<dataType>> mTreesLimited;
184 getSizeLimitedTrees<dataType>(
185 trees, barycenterMaximumNumberOfPairs, sizeLimitPercent, mTreesLimited);
186 std::vector<ftm::FTMTree_MT *> treesLimited;
187 ftm::mergeTreeToFTMTree<dataType>(mTreesLimited, treesLimited);
188 getDistanceMatrix<dataType>(
189 trees, treesLimited, distanceMatrix, useDoubleInput, isFirstInput);
192 template <
class dataType>
194 std::vector<ftm::FTMTree_MT *> &trees,
195 std::vector<std::vector<double>> &distanceMatrix,
196 unsigned int barycenterMaximumNumberOfPairs,
197 double sizeLimitPercent,
198 bool useDoubleInput =
false,
199 bool isFirstInput =
true) {
200 if(barycenterMaximumNumberOfPairs <= 0 and sizeLimitPercent <= 0.0)
201 getDistanceMatrix<dataType>(
202 trees, distanceMatrix, useDoubleInput, isFirstInput);
204 getSizeLimitedDistanceMatrix<dataType>(
205 trees, distanceMatrix, barycenterMaximumNumberOfPairs,
206 sizeLimitPercent, useDoubleInput, isFirstInput);
209 template <
class dataType>
211 std::vector<ftm::FTMTree_MT *> &trees2,
212 unsigned int barycenterMaximumNumberOfPairs,
213 double sizeLimitPercent,
214 bool distMinimizer =
true) {
215 std::vector<std::vector<double>> distanceMatrix, distanceMatrix2;
216 bool const useDoubleInput = (trees2.size() != 0);
217 getParametrizedDistanceMatrix<dataType>(trees, distanceMatrix,
218 barycenterMaximumNumberOfPairs,
219 sizeLimitPercent, useDoubleInput);
220 if(trees2.size() != 0)
221 getParametrizedDistanceMatrix<dataType>(
222 trees2, distanceMatrix2, barycenterMaximumNumberOfPairs,
223 sizeLimitPercent, useDoubleInput,
false);
227 = distMinimizer ? std::numeric_limits<dataType>::max() : 0;
228 std::vector<int> sizes(trees.size());
229 for(
unsigned int i = 0; i < trees.size(); ++i) {
231 for(
unsigned int j = 0; j < distanceMatrix[i].size(); ++j)
232 value += (not useDoubleInput ? distanceMatrix[i][j]
234 distanceMatrix2[i][j]));
235 if((distMinimizer and value < bestValue)
236 or (not distMinimizer and value > bestValue)) {
241 sizes[i] *= (distMinimizer) ? 1 : -1;
244 std::random_device rd;
245 std::default_random_engine generator(rd());
246 std::discrete_distribution<int> distribution(
247 sizes.begin(), sizes.end());
248 bestIndex = distribution(generator);
253 template <
class dataType>
255 std::vector<ftm::FTMTree_MT *> &trees2,
256 double sizeLimitPercent,
257 bool distMinimizer =
true) {
258 return getBestInitTreeIndex<dataType>(trees, trees2,
260 sizeLimitPercent, distMinimizer);
263 template <
class dataType>
265 bool distMinimizer =
true) {
266 std::vector<ftm::FTMTree_MT *> trees2;
267 return getBestInitTreeIndex<dataType>(
272 template <
class dataType>
275 bool distMinimizer =
true) {
277 = getBestInitTreeIndex<dataType>(trees, distMinimizer);
278 baryTree = ftm::copyMergeTree<dataType>(trees[bestIndex],
true);
285 template <
class dataType>
291 std::vector<dataType> &newScalarsVector,
292 std::vector<std::tuple<ftm::idNode, ftm::idNode, int>> &nodesToProcess,
296 std::queue<std::tuple<ftm::idNode, ftm::idNode>> queue;
297 queue.emplace(nodeId2, nodeId1);
298 nodesToProcess.emplace_back(nodeId2, nodeId1, i);
299 while(!queue.empty()) {
300 auto queueTuple = queue.front();
304 newScalarsVector.push_back(
306 newScalarsVector.push_back(tree2->
getValue<dataType>(node));
308 std::vector<ftm::idNode> children;
310 for(
auto child : children) {
311 queue.emplace(child, nodeCpt + 1);
312 nodesToProcess.emplace_back(child, nodeCpt + 1, i);
320 template <
class dataType>
324 std::vector<std::tuple<ftm::idNode, ftm::idNode, int>> &nodesToProcess,
325 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode>>>
330 nodesProcessed.
clear();
331 nodesProcessed.resize(noTrees);
332 for(
auto processTuple : nodesToProcess) {
333 ftm::idNode const parent = std::get<1>(processTuple);
335 int const index = std::get<2>(processTuple);
336 nodesProcessed[index].emplace_back(
337 nodeTree1 + 1, std::get<0>(processTuple));
347 template <
class dataType>
351 std::vector<std::tuple<ftm::idNode, ftm::idNode, int>> &nodesToProcess,
352 std::vector<dataType> &newScalarsVector,
353 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode>>>
359 = ftm::createEmptyMergeTree<dataType>(newScalarsVector.size());
360 ftm::setTreeScalars<dataType>(mTreeNew, newScalarsVector);
367 addNodes<dataType>(mTreeNew, noTrees, nodesToProcess, nodesProcessed);
373 template <
class dataType>
375 std::vector<ftm::FTMTree_MT *> &trees,
377 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
385 std::vector<std::vector<ftm::idNode>> matrixMatchings(trees.size());
387 for(
unsigned int i = 0; i < matchings.size(); ++i) {
388 auto matching = matchings[i];
389 matrixMatchings[i].resize(trees[i]->getNumberOfNodes(),
390 std::numeric_limits<ftm::idNode>::max());
391 for(
auto match : matching) {
392 matrixMatchings[i][std::get<1>(match)] = std::get<0>(match);
393 baryMatched[std::get<0>(match)] =
true;
398 std::vector<std::vector<ftm::idNode>> nodesToAdd(trees.size());
399 for(
unsigned int i = 0; i < trees.size(); ++i) {
401 std::queue<ftm::idNode> queue;
403 while(!queue.empty()) {
406 bool processChildren =
true;
408 if(matrixMatchings[i][node]
409 == std::numeric_limits<ftm::idNode>::max()) {
411 processChildren =
false;
412 nodesToAdd[i].push_back(node);
417 "barycenter with keepSubtree_=true is not implemented yet");
420 if(processChildren) {
421 std::vector<ftm::idNode> children;
422 trees[i]->getChildren(node, children);
423 for(
auto child : children)
424 if(not(trees[i]->isThereOnlyOnePersistencePair()
425 and trees[i]->isLeaf(child)))
426 queue.emplace(child);
431 bool foundRootNotMatched =
false;
432 for(
unsigned int i = 0; i < trees.size(); ++i)
434 matrixMatchings[i][trees[i]->getRoot()]);
435 if(foundRootNotMatched)
436 printWrn(
"[updateBarycenterTreeStructure] an input tree has its root "
441 if(not baryMatched[i])
447 std::vector<std::tuple<ftm::idNode, ftm::idNode, int>> nodesToProcess;
448 std::vector<dataType> newScalarsVector;
449 ftm::getTreeScalars<dataType>(baryMergeTree, newScalarsVector);
450 for(
unsigned int i = 0; i < nodesToAdd.size(); ++i) {
451 for(
auto node : nodesToAdd[i]) {
453 = matrixMatchings[i][trees[i]->getParentSafe(node)];
454 if(matchings[i].size() == 0)
455 parent = baryTreeRoot;
459 and matchings[i].size() != 0) {
460 std::stringstream ss;
461 ss << trees[i]->getParentSafe(node) <<
" _ " << node;
463 printMsg(trees[i]->printTree().str());
464 printMsg(trees[i]->printPairsFromTree<dataType>(
true).str());
466 std::stringstream ss2;
467 ss2 <<
"parent " << parent;
472 std::vector<dataType> addedScalars;
473 nodeCpt = getNodesAndScalarsToAdd<dataType>(
474 baryMergeTree, parent, trees[i], node, addedScalars,
475 nodesToProcess, nodeCpt, i);
476 newScalarsVector.insert(
477 newScalarsVector.end(), addedScalars.begin(), addedScalars.end());
481 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode>>>
483 updateNodesAndScalars<dataType>(baryMergeTree, trees.size(),
484 nodesToProcess, newScalarsVector,
486 for(
unsigned int i = 0; i < matchings.size(); ++i) {
487 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
489 for(
auto tup : nodesProcessed[i])
490 nodesProcessedT.emplace_back(
491 std::get<0>(tup), std::get<1>(tup), -1);
492 matchings[i].insert(matchings[i].
end(), nodesProcessedT.begin(),
493 nodesProcessedT.end());
499 printErr(
"barycenter with keepSubtree_=true is not implemented yet");
503 template <
class dataType>
504 std::tuple<dataType, dataType>
506 std::tuple<dataType, dataType> birthDeath;
509 birthDeath = getNormalizedBirthDeath<dataType>(tree1, nodeId1);
516 template <
class dataType>
517 std::tuple<dataType, dataType>
520 std::vector<dataType> &newScalarsVector,
521 std::vector<ftm::FTMTree_MT *> &trees,
522 std::vector<ftm::idNode> &nodes,
523 std::vector<double> &alphas) {
525 dataType mu_max = getMinMaxLocalFromVector<dataType>(
526 baryTree, nodeId, newScalarsVector,
false);
527 dataType mu_min = getMinMaxLocalFromVector<dataType>(
528 baryTree, nodeId, newScalarsVector);
529 dataType newBirth = 0, newDeath = 0;
532 dataType tempBirth = 0, tempDeath = 0;
534 for(
unsigned int i = 0; i < trees.size(); ++i)
535 if(nodes[i] != std::numeric_limits<ftm::idNode>::max())
536 alphaSum += alphas[i];
537 for(
unsigned int i = 0; i < trees.size(); ++i) {
539 if(nodes[i] != std::numeric_limits<ftm::idNode>::max()) {
541 = getParametrizedBirthDeath<dataType>(trees[i], nodes[i]);
542 dataType tTempBirth = 0, tTempDeath = 0;
543 tTempBirth += std::get<0>(iBirthDeath);
544 tTempDeath += std::get<1>(iBirthDeath);
545 tempBirth += tTempBirth * alphas[i] / alphaSum;
546 tempDeath += tTempDeath * alphas[i] / alphaSum;
549 dataType
const projec = (tempBirth + tempDeath) / 2;
552 for(
unsigned int i = 0; i < trees.size(); ++i) {
553 dataType iBirth = projec, iDeath = projec;
555 if(nodes[i] != std::numeric_limits<ftm::idNode>::max()) {
557 = getParametrizedBirthDeath<dataType>(trees[i], nodes[i]);
558 iBirth = std::get<0>(iBirthDeath);
559 iDeath = std::get<1>(iBirthDeath);
561 newBirth += alphas[i] * iBirth;
562 newDeath += alphas[i] * iDeath;
567 volatile dataType tempBirthT = newBirth * (mu_max - mu_min);
568 volatile dataType tempDeathT = newDeath * (mu_max - mu_min);
569 newBirth = tempBirthT + mu_min;
570 newDeath = tempDeathT + mu_min;
573 return std::make_tuple(newBirth, newDeath);
576 template <
class dataType>
577 std::tuple<dataType, dataType>
583 std::vector<dataType> &newScalarsVector) {
585 dataType mu_max = getMinMaxLocalFromVector<dataType>(
586 baryTree, nodeB, newScalarsVector,
false);
588 = getMinMaxLocalFromVector<dataType>(baryTree, nodeB, newScalarsVector);
590 auto birthDeath = getParametrizedBirthDeath<dataType>(tree, nodeId);
591 dataType newBirth = std::get<0>(birthDeath);
592 dataType newDeath = std::get<1>(birthDeath);
593 dataType
const projec = (newBirth + newDeath) / 2;
595 newBirth = alpha * newBirth + (1 - alpha) * projec;
596 newDeath = alpha * newDeath + (1 - alpha) * projec;
601 volatile dataType tempBirthT = newBirth * (mu_max - mu_min);
602 volatile dataType tempDeathT = newDeath * (mu_max - mu_min);
603 newBirth = tempBirthT + mu_min;
604 newDeath = tempDeathT + mu_min;
607 return std::make_tuple(newBirth, newDeath);
610 template <
class dataType>
612 std::vector<ftm::FTMTree_MT *> &trees,
614 std::vector<double> &alphas,
615 unsigned int indexAddedNodes,
616 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
619 bool const isJT = baryTree->
isJoinTree<dataType>();
624 std::vector<std::vector<ftm::idNode>> baryMatching(
626 std::vector<ftm::idNode>(
627 trees.size(), std::numeric_limits<ftm::idNode>::max()));
629 for(
unsigned int i = 0; i < matchings.size(); ++i) {
630 auto matching = matchings[i];
631 for(
auto match : matching) {
632 baryMatching[std::get<0>(match)][i] = std::get<1>(match);
633 if(std::get<0>(match)
635 nodesAddedTree[std::get<0>(match)] = i;
642 std::queue<ftm::idNode> queue;
644 while(!queue.empty()) {
647 std::tuple<dataType, dataType> newBirthDeath;
648 if(node < indexAddedNodes) {
650 = interpolation<dataType>(baryMergeTree, node, newScalarsVector,
651 trees, baryMatching[node], alphas);
653 int const i = nodesAddedTree[node];
655 newBirthDeath = interpolationAdded<dataType>(
656 trees[i], nodeT, alphas[i], baryMergeTree, node, newScalarsVector);
659 = (isJT ? std::get<1>(newBirthDeath) : std::get<0>(newBirthDeath));
660 dataType nodeOriginScalar
661 = (isJT ? std::get<0>(newBirthDeath) : std::get<1>(newBirthDeath));
662 newScalarsVector[node] = nodeScalar;
665 std::vector<ftm::idNode> children;
667 for(
auto child : children)
668 queue.emplace(child);
673 dataType mergedRootOriginScalar = 0.0;
674 for(
unsigned int i = 0; i < trees.size(); ++i)
675 mergedRootOriginScalar += trees[i]->getValue<dataType>(
676 trees[i]->getMergedRootOrigin<dataType>());
677 mergedRootOriginScalar /= trees.size();
678 newScalarsVector[mergedRootOrigin] = mergedRootOriginScalar;
681 setTreeScalars(baryMergeTree, newScalarsVector);
683 std::vector<ftm::idNode> deletedNodesT;
684 persistenceThresholding<dataType>(
685 &(baryMergeTree.
tree), 0, deletedNodesT);
687 ftm::cleanMergeTree<dataType>(baryMergeTree);
690 template <
class dataType>
692 std::vector<ftm::FTMTree_MT *> &trees,
694 std::vector<double> &alphas,
695 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
698 updateBarycenterTreeStructure<dataType>(trees, baryMergeTree, matchings);
699 updateBarycenterTreeScalars<dataType>(
700 trees, baryMergeTree, alphas, indexAddedNodes, matchings);
706 template <
class dataType>
710 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matching,
712 bool useDoubleInput =
false,
713 bool isFirstInput =
true) {
736 = mergeTreeDistance.
computeDistance<dataType>(baryTree, tree, matching);
737 std::stringstream ss, ss2;
738 ss <<
"distance tree : " << distance;
740 ss2 <<
"distance²tree : " << distance * distance;
747 template <
class dataType>
751 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matching,
753 bool useDoubleInput =
false,
754 bool isFirstInput =
true) {
755 computeOneDistance<dataType>(tree, &(baryMergeTree.
tree), matching,
756 distance, useDoubleInput, isFirstInput);
759 template <
class dataType>
763 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matching,
765 bool useDoubleInput =
false,
766 bool isFirstInput =
true) {
767 computeOneDistance<dataType>(&(baryMergeTree.
tree), baryMergeTree2,
768 matching, distance, useDoubleInput,
772 template <
class dataType>
774 std::vector<ftm::FTMTree_MT *> &trees,
776 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
778 std::vector<dataType> &distances,
779 bool useDoubleInput =
false,
780 bool isFirstInput =
true) {
783 useDoubleInput, isFirstInput);
786 useDoubleInput, isFirstInput);
789 template <
class dataType>
791 std::vector<ftm::FTMTree_MT *> &trees,
793 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
795 std::vector<dataType> &distances,
796 bool useDoubleInput =
false,
797 bool isFirstInput =
true) {
798#ifdef TTK_ENABLE_OPENMP4
799#pragma omp parallel num_threads(this->threadNumber_) \
800 shared(baryMergeTree) if(parallelize_)
802#pragma omp single nowait
805 useDoubleInput, isFirstInput);
806#ifdef TTK_ENABLE_OPENMP4
811 template <
class dataType>
813 std::vector<ftm::FTMTree_MT *> &trees,
815 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
817 std::vector<dataType> &distances,
818 bool useDoubleInput =
false,
819 bool isFirstInput =
true) {
820 for(
unsigned int i = 0; i < trees.size(); ++i)
821#ifdef TTK_ENABLE_OPENMP4
822#pragma omp task firstprivate(i)
UNTIED() \
823 shared(baryMergeTree, matchings, distances)
825 computeOneDistance<dataType>(trees[i], baryMergeTree, matchings[i],
826 distances[i], useDoubleInput,
828#ifdef TTK_ENABLE_OPENMP4
836 template <
class dataType>
840 std::vector<ftm::FTMTree_MT *> &oriTrees,
842 std::vector<std::vector<ftm::idNode>> &deletedNodes) {
843 deletedNodes.clear();
844 deletedNodes.resize(oriTrees.size());
845 unsigned int noTreesUnscaled = 0;
848 for(
unsigned int i = 0; i < oriTrees.size(); ++i) {
849 double persistenceThreshold = 50.0;
850 if(iterationNumber != -1) {
852 int const noPairs = mergeTrees[i].tree.getRealNumberOfNodes();
855 std::vector<std::tuple<ftm::idNode, ftm::idNode, dataType>> pairs;
856 oriTrees[i]->getPersistencePairsFromTree<dataType>(
860 double const multiplier
864 int const decrement = multiplier * pairs.size() / 10;
865 int thresholdIndex = pairs.size() - noPairs - std::max(decrement, 2);
866 thresholdIndex = std::max(thresholdIndex, 0);
867 const double persistence = std::get<2>(pairs[thresholdIndex]);
869 = persistence / std::get<2>(pairs.back()) * 100.0;
870 if(thresholdIndex == 0) {
871 persistenceThreshold = 0.;
875 if(persistenceThreshold != 0.) {
877 = ftm::copyMergeTree<dataType>(oriTrees[i]);
878 persistenceThresholding<dataType>(
879 &(mt.
tree), persistenceThreshold, deletedNodes[i]);
880 if(mergeTrees.size() == 0)
881 mergeTrees.resize(oriTrees.size());
883 trees[i] = &(mt.
tree);
885 trees[i] = oriTrees[i];
891 return noTreesUnscaled;
894 template <
class dataType>
896 std::vector<ftm::FTMTree_MT *> &oriTrees,
897 std::vector<std::vector<ftm::idNode>> &deletedNodes,
898 std::vector<dataType> &distances) {
899 for(
unsigned int i = 0; i < oriTrees.size(); ++i)
900 for(
auto node : deletedNodes[i])
901 distances[i] += deleteCost<dataType>(oriTrees[i], node);
907 template <
class dataType>
909 std::vector<ftm::FTMTree_MT *> &trees,
911 std::vector<double> &alphas,
912 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
914 bool finalAsgnDoubleInput =
false,
915 bool finalAsgnFirstInput =
true) {
921 std::vector<ftm::FTMTree_MT *> oriTrees;
922 std::vector<ftm::MergeTree<dataType>> scaledMergeTrees;
923 std::vector<std::vector<ftm::idNode>> deletedNodes;
925 oriTrees.insert(oriTrees.end(), trees.begin(), trees.end());
926 persistenceScaling<dataType>(
927 trees, scaledMergeTrees, oriTrees, -1, deletedNodes);
928 std::vector<ftm::idNode> deletedNodesT;
929 persistenceThresholding<dataType>(baryTree, 50, deletedNodesT);
931 bool treesUnscaled =
false;
937 bool converged =
false;
938 dataType frechetEnergy = -1;
939 dataType minFrechet = std::numeric_limits<dataType>::max();
942 while(not converged) {
946 std::stringstream ss;
947 ss <<
"Iteration " << NoIteration;
951 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
952 matchings(trees.size());
953 std::vector<dataType> distances(trees.size(), -1);
955 assignment<dataType>(trees, baryMergeTree, matchings, distances);
956 Timer t_addDeletedNodes;
958 addScaledDeletedNodesCost<dataType>(
959 oriTrees, deletedNodes, distances);
961 auto t_assignment_time
968 updateBarycenterTree<dataType>(trees, baryMergeTree, alphas, matchings);
970 baryTree = &(baryMergeTree.
tree);
975 dataType currentFrechetEnergy = 0;
976 for(
unsigned int i = 0; i < trees.size(); ++i)
977 currentFrechetEnergy += alphas[i] * distances[i] * distances[i];
979 = std::abs((
double)(frechetEnergy - currentFrechetEnergy));
980 converged = (frechetDiff <=
tol_);
982 frechetEnergy = currentFrechetEnergy;
983 tol_ = frechetEnergy / 125.0;
985 std::stringstream ss4;
990 ss4 <<
"Frechet energy : " << frechetEnergy;
993 minFrechet = std::min(minFrechet, frechetEnergy);
995 cptBlocked = (minFrechet < frechetEnergy) ? cptBlocked + 1 : 0;
996 converged = (cptBlocked >= 10);
1001 unsigned int const noTreesUnscaled = persistenceScaling<dataType>(
1002 trees, scaledMergeTrees, oriTrees, NoIteration, deletedNodes);
1003 treesUnscaled = (noTreesUnscaled == oriTrees.size());
1011 std::vector<dataType> distances(trees.size(), -1);
1012 assignment<dataType>(trees, baryMergeTree, finalMatchings, distances,
1013 finalAsgnDoubleInput, finalAsgnFirstInput);
1014 for(
auto dist : distances)
1016 dataType currentFrechetEnergy = 0;
1017 for(
unsigned int i = 0; i < trees.size(); ++i)
1018 currentFrechetEnergy += alphas[i] * distances[i] * distances[i];
1020 std::stringstream ss, ss2;
1021 ss <<
"Frechet energy : " << currentFrechetEnergy;
1029 verifyBarycenterTwoTrees<dataType>(
1030 trees, baryMergeTree, finalMatchings, distances);
1034 scaledMergeTrees.clear();
1036 trees.insert(trees.end(), oriTrees.begin(), oriTrees.end());
1040 template <
class dataType>
1043 std::vector<double> &alphas,
1044 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
1047 bool finalAsgnDoubleInput =
false,
1048 bool finalAsgnFirstInput =
true) {
1052 for(
unsigned int i = 0; i < trees.size(); ++i)
1061 std::vector<ftm::FTMTree_MT *> treesT;
1062 ftm::mergeTreeToFTMTree<dataType>(trees, treesT);
1063 initBarycenterTree<dataType>(treesT, baryMergeTree);
1066 computeBarycenter<dataType>(treesT, baryMergeTree, alphas, finalMatchings,
1067 finalAsgnDoubleInput, finalAsgnFirstInput);
1071 std::vector<int>
const allRealNodes(trees.size());
1072 for(
unsigned int i = 0; i < trees.size(); ++i) {
1073 postprocessingPipeline<dataType>(treesT[i]);
1077 postprocessingPipeline<dataType>(&(baryMergeTree.
tree));
1078 for(
unsigned int i = 0; i < trees.size(); ++i) {
1079 convertBranchDecompositionMatching<dataType>(
1080 &(baryMergeTree.
tree), treesT[i], finalMatchings[i]);
1085 template <
class dataType>
1088 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
1091 bool finalAsgnDoubleInput =
false,
1092 bool finalAsgnFirstInput =
true) {
1093 std::vector<double> alphas;
1094 if(trees.size() != 2) {
1095 for(
unsigned int i = 0; i < trees.size(); ++i)
1096 alphas.push_back(1.0 / trees.size());
1098 alphas.push_back(
alpha_);
1099 alphas.push_back(1 -
alpha_);
1102 execute<dataType>(trees, alphas, finalMatchings, baryMergeTree,
1103 finalAsgnDoubleInput, finalAsgnFirstInput);
1109 template <
class dataType>
1111 std::vector<ftm::FTMTree_MT *> &trees,
1115 unsigned int const newNoNodes = metric * percent / 100.0;
1116 keepMostImportantPairs<dataType>(&(bary.
tree), newNoNodes, useBD);
1120 and noNodesAfter > 3) {
1121 std::cout <<
"metric = " << metric << std::endl;
1122 std::cout <<
"newNoNodes = " << newNoNodes << std::endl;
1123 std::cout <<
"noNodesAfter = " << noNodesAfter << std::endl;
1127 template <
class dataType>
1129 std::vector<ftm::FTMTree_MT *> &trees,
1130 unsigned int barycenterMaximumNumberOfPairs,
1132 bool useBD =
true) {
1133 if(barycenterMaximumNumberOfPairs > 0)
1134 keepMostImportantPairs<dataType>(
1135 &(bary.
tree), barycenterMaximumNumberOfPairs, useBD);
1139 template <
class dataType>
1141 std::vector<ftm::FTMTree_MT *> &trees,
1143 bool useBD =
true) {
1147 template <
class dataType>
1149 std::vector<ftm::FTMTree_MT *> &trees,
1150 bool useBD =
true) {
1158 template <
class dataType>
1164 auto tup = fixMergedRootOrigin<dataType>(tree);
1165 int maxIndex = std::get<0>(tup);
1166 dataType oldOriginValue = std::get<1>(tup);
1170 std::vector<dataType> newScalarsVector;
1171 ftm::getTreeScalars<dataType>(tree, newScalarsVector);
1173 if((isJT and tree->
getValue<dataType>(maxIndex) > oldOriginValue)
1175 and tree->
getValue<dataType>(maxIndex) < oldOriginValue)) {
1176 newScalarsVector[treeRoot] = newScalarsVector[maxIndex];
1177 newScalarsVector[maxIndex] = oldOriginValue;
1179 newScalarsVector[treeRoot] = oldOriginValue;
1180 setTreeScalars(barycenter, newScalarsVector);
1191 std::stringstream ss;
1192 ss <<
"Barycenter number of nodes : " << noNodes <<
" / " << noNodesT;
1199 template <
class dataType>
1201 std::vector<ftm::FTMTree_MT *> &trees,
1203 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
1205 std::vector<dataType> distances) {
1206 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching;
1209 if(distance != (distances[0] + distances[1])) {
1210 std::stringstream ss, ss2, ss3, ss4;
1211 ss <<
"distance T1 T2 : " << distance;
1213 ss2 <<
"distance T1 T' T2 : " << distances[0] + distances[1];
1215 ss3 <<
"distance T1 T' : " << distances[0];
1217 ss4 <<
"distance T' T2 : " << distances[1];
1222 auto baryTree = &(baryMergeTree.
tree);
1223 std::vector<std::vector<ftm::idNode>> baryMatched(
1224 baryTree->getNumberOfNodes(),
1225 std::vector<ftm::idNode>(
1226 trees.size(), std::numeric_limits<ftm::idNode>::max()));
1227 for(
unsigned int i = 0; i < finalMatchings.size(); ++i)
1228 for(
auto match : finalMatchings[i])
1229 baryMatched[std::get<0>(match)][i] = std::get<1>(match);
1231 std::queue<ftm::idNode> queue;
1232 queue.emplace(baryTree->getRoot());
1233 while(!queue.empty()) {
1234 auto node = queue.front();
1236 std::vector<dataType> costs(trees.size());
1237 for(
unsigned int i = 0; i < trees.size(); ++i)
1238 if(baryMatched[node][i] != std::numeric_limits<ftm::idNode>::max())
1239 costs[i] = relabelCost<dataType>(
1240 baryTree, node, trees[i], baryMatched[node][i]);
1242 costs[i] = deleteCost<dataType>(baryTree, node);
1244 if(baryMatched[node][0] != std::numeric_limits<ftm::idNode>::max()
1245 and baryMatched[node][1] != std::numeric_limits<ftm::idNode>::max())
1246 cost = relabelCost<dataType>(
1247 trees[0], baryMatched[node][0], trees[1], baryMatched[node][1]);
1248 else if(baryMatched[node][0] == std::numeric_limits<ftm::idNode>::max())
1249 cost = deleteCost<dataType>(trees[1], baryMatched[node][1]);
1250 else if(baryMatched[node][1] == std::numeric_limits<ftm::idNode>::max())
1251 cost = deleteCost<dataType>(trees[0], baryMatched[node][0]);
1254 costs[0] = std::sqrt(costs[0]);
1255 costs[1] = std::sqrt(costs[1]);
1256 cost = std::sqrt(cost);
1257 if(std::abs((
double)(costs[0] - costs[1])) > 1e-7) {
1259 std::stringstream ss, ss2, ss3, ss4;
1260 ss <<
"cost T' T0 : " << costs[0];
1262 ss2 <<
"cost T' T1 : " << costs[1];
1264 ss3 <<
"cost T0 T1 : " << cost;
1266 ss4 <<
"cost T0 T' T1 : " << costs[0] + costs[1];
1268 if(std::abs((
double)((costs[0] + costs[1]) - cost)) > 1e-7) {
1269 std::stringstream ss5;
1271 << std::abs((
double)((costs[0] + costs[1]) - cost));
1274 std::stringstream ss6;
1275 ss6 <<
"diff2 : " << std::abs((
double)(costs[0] - costs[1]));
1279 for(
unsigned int i = 0; i < 2; ++i)
1280 if(baryMatched[node][i]
1281 != std::numeric_limits<ftm::idNode>::max()) {
1283 trees[i]->printNode2<dataType>(baryMatched[node][i]).str());
1285 ->printNode2<dataType>(
1286 trees[i]->getParentSafe(baryMatched[node][i]))
1290 std::vector<ftm::idNode> children;
1291 baryTree->getChildren(node, children);
1292 for(
auto child : children)
1293 queue.emplace(child);
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
virtual int setThreadNumber(const int threadNumber)
Minimalist debugging class.
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)
ftm::idNode getNodesAndScalarsToAdd(ftm::MergeTree< dataType > &ttkNotUsed(mTree1), ftm::idNode nodeId1, ftm::FTMTree_MT *tree2, ftm::idNode nodeId2, std::vector< dataType > &newScalarsVector, std::vector< std::tuple< ftm::idNode, ftm::idNode, int > > &nodesToProcess, ftm::idNode nodeCpt, int i)
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 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 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 limitSizePercent(ftm::MergeTree< dataType > &bary, std::vector< ftm::FTMTree_MT * > &trees, double percent, bool useBD)
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)
void setNodePerTask(int npt)
bool normalizedWasserstein_
double mixDistances(dataType distance1, dataType distance2)
double getSizeLimitMetric(std::vector< ftm::FTMTree_MT * > &trees)
void printTreesStats(std::vector< ftm::FTMTree_MT * > &trees)
void printMatching(std::vector< MatchingType > &matchings)
std::vector< std::vector< int > > treesNodeCorr_
void setKeepSubtree(bool keepSubtree)
double mixDistancesMinMaxPairWeight(bool isFirstInput)
bool branchDecomposition_
dataType computeDistance(ftm::FTMTree_MT *tree1, ftm::FTMTree_MT *tree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &outputMatching)
void setPreprocess(bool preproc)
void setPostprocess(bool postproc)
void setMinMaxPairWeight(double weight)
void setIsCalled(bool ic)
const scalarType & getValue(SimplexId nodeId) const
bool isNodeIdInconsistent(idNode nodeId)
idNode getNumberOfNodes() const
void setParent(idNode nodeId, idNode newParentNodeId)
std::tuple< dataType, dataType > getBirthDeath(idNode nodeId)
idNode getMergedRootOrigin()
void getChildren(idNode nodeId, std::vector< idNode > &res)
void deleteNode(idNode nodeId)
idNode makeNode(SimplexId vertexId, SimplexId linked=nullVertex)
int getRealNumberOfNodes()
bool isNodeAlone(idNode nodeId)
void copyMergeTreeStructure(FTMTree_MT *tree)
Node * getNode(idNode nodeId)
void setOrigin(SimplexId linked)
SimplexId getOrigin() const
unsigned int idNode
Node index in vect_nodes_.
T end(std::pair< T, T > &p)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)