20#define ENERGY_COMPARISON_TOLERANCE 1e-6
39 "MergeTreeAxesAlgorithmBase");
47 template <
class dataType>
51 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matching,
53 bool isCalled =
false,
54 bool useDoubleInput =
false,
55 bool isFirstInput =
true) {
73 &(tree1.
tree), &(tree2.
tree), matching);
76 template <
class dataType>
80 bool isCalled =
false,
81 bool useDoubleInput =
false,
82 bool isFirstInput =
true) {
83 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching;
84 computeOneDistance<dataType>(tree1, tree2, matching, distance, isCalled,
85 useDoubleInput, isFirstInput);
91 template <
class dataType>
95 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matching,
96 std::vector<std::vector<double>> &v) {
100 std::vector<ftm::idNode> matchingVector;
101 getMatchingVector<dataType>(barycenter, tree, matching, matchingVector);
108 = getParametrizedBirthDeath<dataType>(barycenterTree, j);
109 std::tuple<dataType, dataType> birthDeath;
110 if(matchingVector[j] != std::numeric_limits<ftm::idNode>::max()) {
112 = getParametrizedBirthDeath<dataType>(treeTree, matchingVector[j]);
115 = (std::get<0>(birthDeathBary) + std::get<1>(birthDeathBary)) / 2.0;
116 birthDeath = std::make_tuple(projec, projec);
118 v[j][0] = std::get<0>(birthDeath) - std::get<0>(birthDeathBary);
119 v[j][1] = std::get<1>(birthDeath) - std::get<1>(birthDeathBary);
123 template <
class dataType>
125 std::vector<std::vector<double>> &v,
126 std::vector<std::vector<std::vector<double>>> &vS,
127 std::vector<std::vector<std::vector<double>>> &v2s) {
129 std::vector<std::vector<double>> sumVs;
132 for(
auto &sumVi : sumVs)
140 v[i][0] = (double)rand() / RAND_MAX * newNorm * 2 - newNorm;
141 v[i][1] = (double)rand() / RAND_MAX * newNorm * 2 - newNorm;
149 v[i][0] = v[i][0] / normV * newNorm;
150 v[i][1] = v[i][1] / normV * newNorm;
154 template <
class dataType,
typename F>
161 std::vector<std::vector<double>> &v1,
162 std::vector<std::vector<double>> &v2,
163 std::vector<std::vector<double>> &trees2V1,
164 std::vector<std::vector<double>> &trees2V2,
166 std::vector<double> &inputToOriginDistances,
167 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
169 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
171 std::vector<std::vector<double>> &inputToAxesDistances,
172 std::vector<std::vector<std::vector<double>>> &vS,
173 std::vector<std::vector<std::vector<double>>> &v2s,
174 std::vector<std::vector<std::vector<double>>> &trees2Vs,
175 std::vector<std::vector<std::vector<double>>> &trees2V2s,
176 bool projectInitializedVectors,
177 F initializedVectorsProjection) {
179 bool doOffset = (newVectorOffset != 0);
181 dataType bestDistance = std::numeric_limits<dataType>::lowest();
182 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> bestMatching,
184 std::vector<std::tuple<double, unsigned int>> distancesAndIndexes(
187 for(
unsigned int i = 0; i < trees.size(); ++i) {
188 dataType distance = 0.0, distance2 = 0.0;
189 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching,
192 if(inputToOriginDistances.size() == 0) {
193 computeOneDistance<dataType>(
195 if(trees2.size() != 0) {
196 computeOneDistance<dataType>(barycenter2, trees2[i], matching2,
202 distance = inputToOriginDistances[i];
203 matching = baryMatchings[i];
204 if(trees2.size() != 0)
205 matching2 = baryMatchings2[i];
208 for(
unsigned j = 0; j < inputToAxesDistances.size(); ++j)
209 distance += inputToAxesDistances[j][i];
210 distancesAndIndexes[i] = std::make_tuple(distance, i);
212 if(distance > bestDistance) {
213 bestDistance = distance;
214 bestMatching = matching;
215 bestMatching2 = matching2;
222 std::sort(distancesAndIndexes.begin(), distancesAndIndexes.end(),
223 [](
const std::tuple<double, unsigned int> &a,
224 const std::tuple<double, unsigned int> &b) ->
bool {
225 return (std::get<0>(a) > std::get<0>(b));
231 bool foundGoodIndex =
false;
232 while(not foundGoodIndex) {
234 if(bestIndex >= 0 and bestIndex < (
int)trees.size()) {
236 if(baryMatchings.size() == 0
237 and (baryMatchings.size() == 0 or trees2.size() == 0)) {
239 computeOneDistance<dataType>(barycenter, trees[bestIndex],
240 bestMatching, distance,
false,
242 if(trees2.size() != 0)
243 computeOneDistance<dataType>(barycenter2, trees2[bestIndex],
244 bestMatching2, distance,
false,
247 bestMatching = baryMatchings[bestIndex];
248 if(trees2.size() != 0)
249 bestMatching2 = baryMatchings2[bestIndex];
254 initVectorFromMatching<dataType>(
255 barycenter, trees[bestIndex], bestMatching, v1);
257 if(trees2.size() != 0) {
258 initVectorFromMatching<dataType>(
259 barycenter2, trees2[bestIndex], bestMatching2, trees2V1);
265 if(trees2.size() != 0) {
272 if(projectInitializedVectors) {
273 initializedVectorsProjection(
274 axeNumber, barycenter, v1, v2, vS, v2s, barycenter2, trees2V1,
275 trees2V2, trees2Vs, trees2V2s, (trees2.size() != 0), 1);
283 if(not foundGoodIndex) {
285 if(i < distancesAndIndexes.size())
286 bestIndex = std::get<1>(distancesAndIndexes[i]);
292 if(foundGoodIndex and doOffset and bestIndex >= 0) {
293 bestIndex += newVectorOffset;
294 if(bestIndex >= (
int)trees.size())
296 foundGoodIndex =
false;
306 template <
class dataType>
310 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
312 std::vector<double> &finalDistances,
313 double barycenterSizeLimitPercent,
314 unsigned int barycenterMaximumNumberOfPairs,
315 bool useDoubleInput =
false,
316 bool isFirstInput =
true) {
329 barycenterMaximumNumberOfPairs);
331 matchings.resize(trees.size());
332 mergeTreeBary.
execute<dataType>(
333 trees, matchings, baryMergeTree, useDoubleInput, isFirstInput);
337 template <
class dataType>
341 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
343 std::vector<double> &finalDistances,
344 double barycenterSizeLimitPercent,
345 bool useDoubleInput =
false,
346 bool isFirstInput =
true) {
347 unsigned int const barycenterMaximumNumberOfPairs = 0;
349 barycenterSizeLimitPercent,
350 barycenterMaximumNumberOfPairs, useDoubleInput,
354 template <
class dataType>
358 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
360 std::vector<double> &finalDistances,
361 bool useDoubleInput =
false,
362 bool isFirstInput =
true) {
368 template <
class dataType>
372 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
374 std::vector<double> finalDistances;
375 computeOneBarycenter<dataType>(
376 trees, baryMergeTree, matchings, finalDistances);
379 template <
class dataType>
382 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
384 computeOneBarycenter<dataType>(trees, baryMergeTree, matchings);
390 template <
class dataType>
392 std::vector<std::vector<int>> &nodeCorr,
393 bool useMinMaxPairT =
true) {
394 nodeCorr.resize(trees.size());
395#ifdef TTK_ENABLE_OPENMP
396#pragma omp parallel for schedule(dynamic) num_threads(this->threadNumber_)
398 for(
unsigned int i = 0; i < trees.size(); ++i) {
399 preprocessingPipeline<dataType>(
402 if(trees.size() < 40)
403 printTreeStats(trees[i]);
405 if(trees.size() != 0)
409 template <
class dataType>
411 bool useMinMaxPairT =
true) {
412 std::vector<std::vector<int>> nodeCorr(trees.size());
420 template <
class dataType>
424 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matchings,
425 std::vector<ftm::idNode> &matchingVector) {
426 matchingVector.clear();
428 std::numeric_limits<ftm::idNode>::max());
429 for(
unsigned int j = 0; j < matchings.size(); ++j) {
430 auto match0 = std::get<0>(matchings[j]);
431 auto match1 = std::get<1>(matchings[j]);
434 matchingVector[match0] = match1;
439 template <
class dataType>
443 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matchings,
444 std::vector<ftm::idNode> &matchingVector) {
445 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> invMatchings(
447 for(
unsigned int i = 0; i < matchings.size(); ++i)
448 invMatchings[i] = std::make_tuple(std::get<1>(matchings[i]),
449 std::get<0>(matchings[i]),
450 std::get<2>(matchings[i]));
455 std::vector<ftm::idNode> &matchingVector,
456 std::vector<ftm::idNode> &invMatchingVector);
458 template <
class dataType>
460 std::vector<ftm::idNode> &matchingVector,
461 std::vector<ftm::idNode> &invMatchingVector) {
468 template <
class dataType>
472 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
474 std::vector<std::vector<ftm::idNode>> &matchingMatrix) {
475 matchingMatrix.clear();
476 matchingMatrix.resize(
478 std::vector<ftm::idNode>(
479 trees.size(), std::numeric_limits<ftm::idNode>::max()));
480 for(
unsigned int i = 0; i < trees.size(); ++i) {
481 std::vector<ftm::idNode> matchingVector;
482 getMatchingVector<dataType>(
483 barycenter, trees[i], matchings[i], matchingVector);
484 for(
unsigned int j = 0; j < matchingVector.size(); ++j)
485 matchingMatrix[j][i] = matchingVector[j];
489 template <
class dataType>
490 std::tuple<dataType, dataType>
492 return ttk::getParametrizedBirthDeath<dataType>(
499 template <
class dataType>
503 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
505 std::vector<std::vector<double>> &allTs,
506 std::vector<std::vector<double>> &branchesCorrelationMatrix,
507 std::vector<std::vector<double>> &persCorrelationMatrix) {
509 std::vector<double>(allTs.size(), 0.0));
510 persCorrelationMatrix = branchesCorrelationMatrix;
514 std::vector<std::vector<ftm::idNode>> matchingMatrix;
517 std::queue<ftm::idNode> queue;
519 while(!queue.empty()) {
524 std::vector<double> births(trees.size(), 0.0),
525 deaths(trees.size(), 0.0), pers(trees.size(), 0.0);
526 for(
unsigned int i = 0; i < trees.size(); ++i) {
527 auto matched = matchingMatrix[node][i];
528 std::tuple<dataType, dataType> birthDeath;
529 if(matched == std::numeric_limits<ftm::idNode>::max()) {
530 birthDeath = barycenter.
tree.template getBirthDeath<dataType>(node);
532 = (std::get<0>(birthDeath) + std::get<1>(birthDeath)) / 2.0;
533 birthDeath = std::make_tuple(projec, projec);
536 = trees[i].tree.template getBirthDeath<dataType>(matched);
537 births[i] = std::get<0>(birthDeath);
538 deaths[i] = std::get<1>(birthDeath);
539 pers[i] = deaths[i] - births[i];
543 for(
unsigned int g = 0; g < allTs.size(); ++g) {
548 if(std::isnan(birthCorr))
550 if(std::isnan(deathCorr))
552 if(std::isnan(persCorr))
556 = barycenter.
tree.template getBirthDeathNode<dataType>(node);
557 auto birthNode = std::get<0>(birthDeathNode);
558 auto deathNode = std::get<1>(birthDeathNode);
559 branchesCorrelationMatrix[birthNode][g] = birthCorr;
560 branchesCorrelationMatrix[deathNode][g] = deathCorr;
561 persCorrelationMatrix[birthNode][g] = persCorr;
562 persCorrelationMatrix[deathNode][g] = persCorr;
566 std::vector<ftm::idNode> children;
568 for(
auto child : children)
569 queue.emplace(child);
virtual int setThreadNumber(const int threadNumber)
Minimalist debugging class.
void setDebugMsgPrefix(const std::string &prefix)
virtual int setDebugLevel(const int &debugLevel)
std::vector< std::vector< int > > trees2NodeCorr_
void computeOneBarycenter(std::vector< ftm::MergeTree< dataType > > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings)
void computeOneBarycenter(std::vector< ftm::MergeTree< dataType > > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< double > &finalDistances, double barycenterSizeLimitPercent, unsigned int barycenterMaximumNumberOfPairs, bool useDoubleInput=false, bool isFirstInput=true)
std::tuple< dataType, dataType > getParametrizedBirthDeath(ftm::FTMTree_MT *tree, ftm::idNode node)
void computeOneDistance(ftm::MergeTree< dataType > &tree1, ftm::MergeTree< dataType > &tree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matching, dataType &distance, bool isCalled=false, bool useDoubleInput=false, bool isFirstInput=true)
void computeOneBarycenter(std::vector< ftm::MergeTree< dataType > > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< double > &finalDistances, double barycenterSizeLimitPercent, bool useDoubleInput=false, bool isFirstInput=true)
MergeTreeAxesAlgorithmBase()
void computeOneDistance(ftm::MergeTree< dataType > &tree1, ftm::MergeTree< dataType > &tree2, dataType &distance, bool isCalled=false, bool useDoubleInput=false, bool isFirstInput=true)
void reverseMatchingVector(unsigned int noNodes, std::vector< ftm::idNode > &matchingVector, std::vector< ftm::idNode > &invMatchingVector)
void computeOneBarycenter(std::vector< ftm::MergeTree< dataType > > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< double > &finalDistances, bool useDoubleInput=false, bool isFirstInput=true)
unsigned int numberOfAxes_
void computeOneBarycenter(std::vector< ftm::MergeTree< dataType > > &trees, ftm::MergeTree< dataType > &baryMergeTree)
void preprocessingTrees(std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< int > > &nodeCorr, bool useMinMaxPairT=true)
double barycenterSizeLimitPercent_
void getInverseMatchingVector(ftm::MergeTree< dataType > &barycenter, ftm::MergeTree< dataType > &tree, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matchings, std::vector< ftm::idNode > &matchingVector)
void getMatchingMatrix(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< std::vector< ftm::idNode > > &matchingMatrix)
void initRandomVector(ftm::MergeTree< dataType > &barycenter, std::vector< std::vector< double > > &v, std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s)
int initVectors(int axeNumber, ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, ftm::MergeTree< dataType > &barycenter2, std::vector< ftm::MergeTree< dataType > > &trees2, std::vector< std::vector< double > > &v1, std::vector< std::vector< double > > &v2, std::vector< std::vector< double > > &trees2V1, std::vector< std::vector< double > > &trees2V2, int newVectorOffset, std::vector< double > &inputToOriginDistances, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &baryMatchings, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &baryMatchings2, std::vector< std::vector< double > > &inputToAxesDistances, std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s, std::vector< std::vector< std::vector< double > > > &trees2Vs, std::vector< std::vector< std::vector< double > > > &trees2V2s, bool projectInitializedVectors, F initializedVectorsProjection)
void computeBranchesCorrelationMatrix(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &baryMatchings, std::vector< std::vector< double > > &allTs, std::vector< std::vector< double > > &branchesCorrelationMatrix, std::vector< std::vector< double > > &persCorrelationMatrix)
void preprocessingTrees(std::vector< ftm::MergeTree< dataType > > &trees, bool useMinMaxPairT=true)
void getMatchingVector(ftm::MergeTree< dataType > &barycenter, ftm::MergeTree< dataType > &tree, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matchings, std::vector< ftm::idNode > &matchingVector)
void reverseMatchingVector(ftm::MergeTree< dataType > &tree, std::vector< ftm::idNode > &matchingVector, std::vector< ftm::idNode > &invMatchingVector)
void initVectorFromMatching(ftm::MergeTree< dataType > &barycenter, ftm::MergeTree< dataType > &tree, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matching, std::vector< std::vector< double > > &v)
void setPreprocess(bool preproc)
void setPostprocess(bool postproc)
void setDeterministic(bool deterministicT)
void setBarycenterMaximumNumberOfPairs(unsigned int maxi)
void setBarycenterSizeLimitPercent(double percent)
std::vector< double > getFinalDistances()
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)
void printTreesStats(std::vector< ftm::FTMTree_MT * > &trees)
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)
idNode getNumberOfNodes() const
void getChildren(idNode nodeId, std::vector< idNode > &res)
bool isNodeAlone(idNode nodeId)
bool isVectorNullFlatten(const std::vector< std::vector< T > > &a)
T magnitudeFlatten(const std::vector< std::vector< T > > &v)
T magnitude(const T *v, const int &dimension=3)
int multiAddVectorsFlatten(const std::vector< std::vector< std::vector< T > > > &a, const std::vector< std::vector< std::vector< T > > > &b, std::vector< std::vector< T > > &out)
T corr(const T *v1, const T *v2, const int &dimension1=3, const int &dimension2=3)
unsigned int idNode
Node index in vect_nodes_.