21#define ENERGY_COMPARISON_TOLERANCE 1e-6
41 "MergeTreeAxesAlgorithmBase");
60 template <
class dataType>
64 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matching,
66 bool isCalled =
false,
67 bool useDoubleInput =
false,
68 bool isFirstInput =
true) {
86 &(tree1.
tree), &(tree2.
tree), matching);
89 template <
class dataType>
93 bool isCalled =
false,
94 bool useDoubleInput =
false,
95 bool isFirstInput =
true) {
96 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching;
98 useDoubleInput, isFirstInput);
104 template <
class dataType>
108 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &matching,
109 std::vector<std::vector<double>> &v) {
113 std::vector<ftm::idNode> matchingVector;
115 barycenter, tree, matching, matchingVector);
123 std::tuple<dataType, dataType> birthDeath;
124 if(matchingVector[j] != std::numeric_limits<ftm::idNode>::max()) {
129 = (std::get<0>(birthDeathBary) + std::get<1>(birthDeathBary)) / 2.0;
130 birthDeath = std::make_tuple(projec, projec);
132 v[j][0] = std::get<0>(birthDeath) - std::get<0>(birthDeathBary);
133 v[j][1] = std::get<1>(birthDeath) - std::get<1>(birthDeathBary);
137 template <
class dataType>
139 std::vector<std::vector<double>> &v,
140 std::vector<std::vector<std::vector<double>>> &vS,
141 std::vector<std::vector<std::vector<double>>> &v2s) {
143 std::vector<std::vector<double>> sumVs;
146 for(
auto &sumVi : sumVs)
154 v[i][0] = (double)rand() / RAND_MAX * newNorm * 2 - newNorm;
155 v[i][1] = (double)rand() / RAND_MAX * newNorm * 2 - newNorm;
163 v[i][0] = v[i][0] / normV * newNorm;
164 v[i][1] = v[i][1] / normV * newNorm;
168 template <
class dataType,
typename F>
175 std::vector<std::vector<double>> &v1,
176 std::vector<std::vector<double>> &v2,
177 std::vector<std::vector<double>> &trees2V1,
178 std::vector<std::vector<double>> &trees2V2,
180 std::vector<double> &inputToOriginDistances,
181 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
183 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
185 std::vector<std::vector<double>> &inputToAxesDistances,
186 std::vector<std::vector<std::vector<double>>> &vS,
187 std::vector<std::vector<std::vector<double>>> &v2s,
188 std::vector<std::vector<std::vector<double>>> &trees2Vs,
189 std::vector<std::vector<std::vector<double>>> &trees2V2s,
190 bool projectInitializedVectors,
191 F initializedVectorsProjection) {
193 bool doOffset = (newVectorOffset != 0);
195 dataType bestDistance = std::numeric_limits<dataType>::lowest();
196 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> bestMatching,
198 std::vector<std::tuple<double, unsigned int>> distancesAndIndexes(
201 for(
unsigned int i = 0; i < trees.size(); ++i) {
202 dataType distance = 0.0, distance2 = 0.0;
203 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching,
206 if(inputToOriginDistances.size() == 0) {
209 if(trees2.size() != 0) {
216 distance = inputToOriginDistances[i];
217 matching = baryMatchings[i];
218 if(trees2.size() != 0)
219 matching2 = baryMatchings2[i];
222 for(
unsigned j = 0; j < inputToAxesDistances.size(); ++j)
223 distance += inputToAxesDistances[j][i];
224 distancesAndIndexes[i] = std::make_tuple(distance, i);
226 if(distance > bestDistance) {
227 bestDistance = distance;
228 bestMatching = matching;
229 bestMatching2 = matching2;
235 std::vector<double> scores;
236 std::random_device rd;
240 scores.resize(distancesAndIndexes.size());
241 for(
unsigned int i = 0; i < distancesAndIndexes.size(); ++i)
242 scores[i] = std::get<0>(distancesAndIndexes[i]);
244 std::sort(distancesAndIndexes.begin(), distancesAndIndexes.end(),
245 [](
const std::tuple<double, unsigned int> &a,
246 const std::tuple<double, unsigned int> &b) ->
bool {
247 return (std::get<0>(a) > std::get<0>(b));
254 bool foundGoodIndex =
false;
255 while(not foundGoodIndex) {
257 if(bestIndex >= 0 and bestIndex < (
int)trees.size()) {
259 if(baryMatchings.size() == 0
260 and (baryMatchings.size() == 0 or trees2.size() == 0)) {
263 bestMatching, distance,
false,
265 if(trees2.size() != 0)
267 bestMatching2, distance,
false,
270 bestMatching = baryMatchings[bestIndex];
271 if(trees2.size() != 0)
272 bestMatching2 = baryMatchings2[bestIndex];
278 barycenter, trees[bestIndex], bestMatching, v1);
280 if(trees2.size() != 0) {
282 barycenter2, trees2[bestIndex], bestMatching2, trees2V1);
288 if(trees2.size() != 0) {
295 if(projectInitializedVectors) {
296 initializedVectorsProjection(
297 axeNumber, barycenter, v1, v2, vS, v2s, barycenter2, trees2V1,
298 trees2V2, trees2Vs, trees2V2s, (trees2.size() != 0), 1);
306 if(not foundGoodIndex) {
308 if(i >= distancesAndIndexes.size())
311 scores[bestIndex] = 0;
312 std::discrete_distribution<int> distribution(
313 scores.begin(), scores.end());
314 bestIndex = distribution(generator);
316 bestIndex = std::get<1>(distancesAndIndexes[i]);
320 if(foundGoodIndex and doOffset and bestIndex >= 0) {
321 bestIndex += newVectorOffset;
322 if(bestIndex >= (
int)trees.size())
324 foundGoodIndex =
false;
334 template <
class dataType>
338 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
340 std::vector<double> &finalDistances,
341 double barycenterSizeLimitPercent,
342 unsigned int barycenterMaximumNumberOfPairs,
343 int barycenterInitIndex,
345 bool useDoubleInput =
false,
346 bool isFirstInput =
true) {
360 barycenterMaximumNumberOfPairs);
365 matchings.resize(trees.size());
366 mergeTreeBary.
execute<dataType>(
367 trees, matchings, baryMergeTree, useDoubleInput, isFirstInput);
371 template <
class dataType>
375 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
377 std::vector<double> &finalDistances,
378 double barycenterSizeLimitPercent,
379 unsigned int barycenterMaximumNumberOfPairs,
380 bool useDoubleInput =
false,
381 bool isFirstInput =
true) {
383 barycenterSizeLimitPercent,
384 barycenterMaximumNumberOfPairs, -1,
false,
385 useDoubleInput, isFirstInput);
388 template <
class dataType>
392 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
394 std::vector<double> &finalDistances,
395 double barycenterSizeLimitPercent,
396 bool useDoubleInput =
false,
397 bool isFirstInput =
true) {
398 unsigned int const barycenterMaximumNumberOfPairs = 0;
400 barycenterSizeLimitPercent,
401 barycenterMaximumNumberOfPairs, useDoubleInput,
405 template <
class dataType>
409 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
411 std::vector<double> &finalDistances,
412 bool useDoubleInput =
false,
413 bool isFirstInput =
true) {
419 template <
class dataType>
423 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
425 std::vector<double> finalDistances;
427 trees, baryMergeTree, matchings, finalDistances);
430 template <
class dataType>
433 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
441 template <
class dataType>
443 std::vector<std::vector<int>> &nodeCorr,
444 bool useMinMaxPairT =
true) {
445 nodeCorr.resize(trees.size());
446#ifdef TTK_ENABLE_OPENMP
447#pragma omp parallel for schedule(dynamic) num_threads(this->threadNumber_)
449 for(
unsigned int i = 0; i < trees.size(); ++i) {
453 if(trees.size() < 40)
454 printTreeStats(trees[i]);
456 if(trees.size() != 0)
460 template <
class dataType>
462 bool useMinMaxPairT =
true) {
463 std::vector<std::vector<int>> nodeCorr(trees.size());
470 template <
class dataType>
471 std::tuple<dataType, dataType>
480 template <
class dataType>
484 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
486 std::vector<std::vector<double>> &allTs,
487 std::vector<std::vector<double>> &branchesCorrelationMatrix,
488 std::vector<std::vector<double>> &persCorrelationMatrix) {
490 std::vector<double>(allTs.size(), 0.0));
491 persCorrelationMatrix = branchesCorrelationMatrix;
495 std::vector<std::vector<ftm::idNode>> matchingMatrix;
497 barycenter, trees, baryMatchings, matchingMatrix);
499 std::queue<ftm::idNode> queue;
501 while(!queue.empty()) {
506 std::vector<double> births(trees.size(), 0.0),
507 deaths(trees.size(), 0.0), pers(trees.size(), 0.0);
508 for(
unsigned int i = 0; i < trees.size(); ++i) {
509 auto matched = matchingMatrix[node][i];
510 std::tuple<dataType, dataType> birthDeath;
511 if(matched == std::numeric_limits<ftm::idNode>::max()) {
512 birthDeath = barycenter.
tree.template getBirthDeath<dataType>(node);
514 = (std::get<0>(birthDeath) + std::get<1>(birthDeath)) / 2.0;
515 birthDeath = std::make_tuple(projec, projec);
518 = trees[i].tree.template getBirthDeath<dataType>(matched);
519 births[i] = std::get<0>(birthDeath);
520 deaths[i] = std::get<1>(birthDeath);
521 pers[i] = deaths[i] - births[i];
525 for(
unsigned int g = 0; g < allTs.size(); ++g) {
530 if(std::isnan(birthCorr))
532 if(std::isnan(deathCorr))
534 if(std::isnan(persCorr))
538 = barycenter.
tree.template getBirthDeathNode<dataType>(node);
539 auto birthNode = std::get<0>(birthDeathNode);
540 auto deathNode = std::get<1>(birthDeathNode);
541 branchesCorrelationMatrix[birthNode][g] = birthCorr;
542 branchesCorrelationMatrix[deathNode][g] = deathCorr;
543 persCorrelationMatrix[birthNode][g] = persCorr;
544 persCorrelationMatrix[deathNode][g] = persCorr;
548 std::vector<ftm::idNode> children;
550 for(
auto child : children)
551 queue.emplace(child);
virtual int setThreadNumber(const int threadNumber)
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 setNumberOfProjectionSteps(const unsigned int k)
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, int barycenterInitIndex, bool oneIter, 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 setBarycenterSizeLimitPercent(const double barycenterSizeLimitPercent)
void computeOneDistance(const ftm::MergeTree< dataType > &tree1, const 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, 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 setDeterministic(const bool deterministic)
void computeBranchesCorrelationMatrix(const 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 computeOneDistance(const ftm::MergeTree< dataType > &tree1, const ftm::MergeTree< dataType > &tree2, dataType &distance, bool isCalled=false, bool useDoubleInput=false, bool isFirstInput=true)
bool probabilisticVectorsInit_
void setProbabilisticVectorsInit(const bool probabilisticVectorsInit)
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 preprocessingTrees(std::vector< ftm::MergeTree< dataType > > &trees, bool useMinMaxPairT=true)
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 setBarycenterMaxIter(int barycenterMaxIter)
void setPreprocess(bool preproc)
void setPostprocess(bool postproc)
void setBarycenterInitIndex(int barycenterInitIndex)
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 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 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_
bool isPersistenceDiagram_
void setIsPersistenceDiagram(bool isPD)
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)
void getChildren(idNode nodeId, std::vector< idNode > &res) const
idNode getNumberOfNodes() const
bool isNodeAlone(idNode nodeId) const
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)
void getMatchingMatrix(const 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 getMatchingVector(const ftm::MergeTree< dataType > &barycenter, const ftm::MergeTree< dataType > &tree, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matchings, std::vector< ftm::idNode > &matchingVector)
unsigned int idNode
Node index in vect_nodes_.
TTK base package defining the standard types.
std::tuple< dataType, dataType > getParametrizedBirthDeath(ftm::FTMTree_MT *tree, ftm::idNode node, bool normalize)