TTK
Loading...
Searching...
No Matches
MergeTreeDistance.h
Go to the documentation of this file.
1
19
20#pragma once
21
22#include <stack>
23#include <thread>
24
25// ttk common includes
26#include <Debug.h>
27
28#include "MergeTreeBase.h"
29#include <AssignmentAuction.h>
31#include <AssignmentMunkres.h>
32#include <AssignmentSolver.h>
33
34namespace ttk {
35
40 class MergeTreeDistance : virtual public Debug, public MergeTreeBase {
41
42 private:
43 double t_assignment_time_ = 0;
44
45 bool preprocess_ = true;
46 bool postprocess_ = true;
47 bool saveTree_ = false;
48 bool onlyEmptyTreeDistance_ = false;
49
50 bool isCalled_ = false;
51
52 double auctionEpsilon_ = -1;
53 double auctionEpsilonDiviser_ = 0;
54 int auctionRound_ = -1;
55
56 double minMaxPairWeight_ = 1.0;
57
58 // Just to get some stats about run
59 // std::map<int, int> assignmentProblemSize, assignmentProblemIter;
60
61 bool testing_ = true;
62
63 // Parallel version data
64 std::vector<std::vector<ftm::idNode>> tree2LevelToNode_;
65 std::vector<int> tree1Level_, tree2Level_;
66
67 public:
70 "MergeTreeDistance"); // inherited from Debug: prefix will be printed at
71 // the beginning of every msg
72#ifdef TTK_ENABLE_OPENMP4
73 omp_set_max_active_levels(100);
74#endif
75 }
76 ~MergeTreeDistance() override = default;
77
78 void setIsCalled(bool ic) {
79 isCalled_ = ic;
80 }
81
82 void setPreprocess(bool preproc) {
83 preprocess_ = preproc;
84 }
85
86 void setPostprocess(bool postproc) {
87 postprocess_ = postproc;
88 }
89
90 void setTesting(bool test) {
91 testing_ = test;
92 }
93
94 void setSaveTree(bool save) {
95 saveTree_ = save;
96 }
97
98 void setAuctionEpsilon(double aucEpsilon) {
99 auctionEpsilon_ = aucEpsilon;
100 }
101
102 void setAuctionEpsilonDiviser(double aucEpsilonDiviser) {
103 auctionEpsilonDiviser_ = aucEpsilonDiviser;
104 }
105
106 void setAuctionNoRounds(double aucNoRounds) {
107 auctionRound_ = aucNoRounds;
108 }
109
110 void setOnlyEmptyTreeDistance(double only) {
111 onlyEmptyTreeDistance_ = only;
112 }
113
114 void setMinMaxPairWeight(double weight) {
115 minMaxPairWeight_ = weight;
116 }
117
121
122 // ------------------------------------------------------------------------
123 // Assignment Problem
124 // ------------------------------------------------------------------------
125 template <class dataType>
126 void
127 runAssignmentProblemSolver(std::vector<std::vector<dataType>> &costMatrix,
128 std::vector<MatchingType> &matchings) {
129 AssignmentSolver<dataType> *assignmentSolver;
130 AssignmentExhaustive<dataType> solverExhaustive;
131 AssignmentMunkres<dataType> solverMunkres;
132 AssignmentAuction<dataType> solverAuction;
133
134 int const nRows = costMatrix.size() - 1;
135 int const nCols = costMatrix[0].size() - 1;
136 int const max_dim = std::max(nRows, nCols);
137 int const min_dim = std::min(nRows, nCols);
138
139 int assignmentSolverID = assignmentSolverID_;
140 if((min_dim <= 2 and max_dim <= 2) or (min_dim <= 1 and max_dim <= 6))
141 assignmentSolverID = 1;
142
143 switch(assignmentSolverID) {
144 case 1:
145 solverExhaustive = AssignmentExhaustive<dataType>();
146 assignmentSolver = &solverExhaustive;
147 break;
148 case 2:
149 solverMunkres = AssignmentMunkres<dataType>();
150 assignmentSolver = &solverMunkres;
151 break;
152 case 0:
153 default:
154 solverAuction = AssignmentAuction<dataType>();
155 solverAuction.setEpsilon(auctionEpsilon_);
156 solverAuction.setEpsilonDiviserMultiplier(auctionEpsilonDiviser_);
157 solverAuction.setNumberOfRounds(auctionRound_);
158 assignmentSolver = &solverAuction;
159 }
160 assignmentSolver->setInput(costMatrix);
161 assignmentSolver->setBalanced(false);
162 assignmentSolver->run(matchings);
163 }
164
165 template <class dataType>
166 void createCostMatrix(std::vector<std::vector<dataType>> &treeTable,
167 std::vector<ftm::idNode> &children1,
168 std::vector<ftm::idNode> &children2,
169 std::vector<std::vector<dataType>> &costMatrix) {
170 unsigned int nRows = children1.size(), nCols = children2.size();
171 for(unsigned int i = 0; i < nRows; ++i) {
172 int const forestTableI = children1[i] + 1;
173 for(unsigned int j = 0; j < nCols; ++j) {
174 int const forestTableJ = children2[j] + 1;
175 // Cost of assigning i and j
176 costMatrix[i][j] = treeTable[forestTableI][forestTableJ];
177 if(tree1Level_[children1[i]] != tree2Level_[children2[j]]
178 and not keepSubtree_)
179 printErr("different levels!"); // should be impossible
180 }
181 // Cost of not assigning i
182 costMatrix[i][nCols] = treeTable[forestTableI][0];
183 }
184 for(unsigned int j = 0; j < nCols; ++j) {
185 int const forestTableJ = children2[j] + 1;
186 // Cost of not assigning j
187 costMatrix[nRows][j] = treeTable[0][forestTableJ];
188 }
189 costMatrix[nRows][nCols] = 0;
190 }
191
192 template <class dataType>
194 std::vector<MatchingType> &matchings,
195 std::vector<ftm::idNode> &children1,
196 std::vector<ftm::idNode> &children2,
197 std::vector<std::tuple<int, int>> &forestAssignment) {
198 dataType cost = 0;
199 for(const auto &mTuple : matchings) {
200 cost += std::get<2>(mTuple);
201 if(std::get<0>(mTuple) >= (int)children1.size()
202 || std::get<1>(mTuple) >= (int)children2.size())
203 continue;
204 int const tableId1 = children1[std::get<0>(mTuple)] + 1;
205 int const tableId2 = children2[std::get<1>(mTuple)] + 1;
206 forestAssignment.emplace_back(tableId1, tableId2);
207 }
208 return cost;
209 }
210
211 template <class dataType>
213 const ftm::FTMTree_MT *ttkNotUsed(tree1),
214 const ftm::FTMTree_MT *ttkNotUsed(tree2),
215 std::vector<std::vector<dataType>> &treeTable,
216 std::vector<ftm::idNode> &children1,
217 std::vector<ftm::idNode> &children2,
218 std::vector<std::tuple<int, int>> &forestAssignment) {
219 // --- Create cost matrix
220 int nRows = children1.size(), nCols = children2.size();
221 std::vector<std::vector<dataType>> costMatrix(
222 nRows + 1, std::vector<dataType>(nCols + 1));
223 createCostMatrix(treeTable, children1, children2, costMatrix);
224
225 // assignmentProblemSize[costMatrix.size()*costMatrix[0].size()]++;
226
227 // --- Solve assignment problem
228 std::vector<MatchingType> matchings;
229 runAssignmentProblemSolver(costMatrix, matchings);
230
231 // --- Postprocess matching to create output assignment
232 dataType cost = postprocessAssignment<dataType>(
233 matchings, children1, children2, forestAssignment);
234
235 return cost;
236 }
237
238 template <class dataType>
240 const ftm::FTMTree_MT *tree1,
241 const ftm::FTMTree_MT *tree2,
242 int i,
243 int j,
244 std::vector<std::vector<dataType>> &treeTable,
245 std::vector<std::vector<dataType>> &forestTable,
246 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
247 &forestBackTable,
248 std::vector<ftm::idNode> &children1,
249 std::vector<ftm::idNode> &children2) {
250 if(children1.size() != 0 && children2.size() != 0) {
251 dataType forestTerm3;
252
253 // Term 3
254 Timer t_assignment;
255 std::vector<std::tuple<int, int>> forestAssignment;
257 tree1, tree2, treeTable, children1, children2, forestAssignment);
258 if(not parallelize_)
259 t_assignment_time_ += t_assignment.getElapsedTime();
260
261 if(not keepSubtree_) {
262 // Compute table value
263 forestTable[i][j] = forestTerm3;
264 // Add backtracking information
265 forestBackTable[i][j] = forestAssignment;
266 } else {
267 dataType forestTerm1, forestTerm2;
268 std::tuple<dataType, ftm::idNode> forestCoTerm1, forestCoTerm2;
269
270 // Term 1
271 forestCoTerm1
272 = computeTerm1_2<dataType>(children2, i, forestTable, true);
273 forestTerm1 = forestTable[0][j] + std::get<0>(forestCoTerm1);
274
275 // Term2
276 forestCoTerm2
277 = computeTerm1_2<dataType>(children1, j, forestTable, false);
278 forestTerm2 = forestTable[i][0] + std::get<0>(forestCoTerm2);
279
280 // Compute table value
281 forestTable[i][j]
282 = std::min(std::min(forestTerm1, forestTerm2), forestTerm3);
283
284 // Add backtracking information
285 if(forestTable[i][j] == forestTerm3) {
286 forestBackTable[i][j] = forestAssignment;
287 } else if(forestTable[i][j] == forestTerm2) {
288 forestBackTable[i][j].push_back(
289 std::make_tuple(std::get<1>(forestCoTerm2), j));
290 } else {
291 forestBackTable[i][j].push_back(
292 std::make_tuple(i, std::get<1>(forestCoTerm1)));
293 }
294 }
295 } else {
296 // If one of the forest is empty we get back to equation 8 or 10
297 forestTable[i][j]
298 = (children1.size() == 0) ? forestTable[0][j] : forestTable[i][0];
299 }
300 }
301
302 // ------------------------------------------------------------------------
303 // Edit Distance Dynamic Programming Equations
304 // ------------------------------------------------------------------------
305 template <class dataType>
307 const ftm::FTMTree_MT *tree1,
308 ftm::idNode nodeI,
309 int i,
310 std::vector<std::vector<dataType>> &treeTable,
311 std::vector<std::vector<dataType>> &forestTable) {
312 std::vector<ftm::idNode> children;
313 tree1->getChildren(nodeI, children);
314 forestTable[i][0] = 0;
315 for(ftm::idNode const child : children)
316 forestTable[i][0] += treeTable[child + 1][0];
317 }
318
319 template <class dataType>
321 const ftm::FTMTree_MT *tree1,
322 ftm::idNode nodeI,
323 int i,
324 std::vector<std::vector<dataType>> &treeTable,
325 std::vector<std::vector<dataType>> &forestTable) {
326 treeTable[i][0] = forestTable[i][0] + deleteCost<dataType>(tree1, nodeI);
327 }
328
329 template <class dataType>
331 const ftm::FTMTree_MT *tree2,
332 ftm::idNode nodeJ,
333 int j,
334 std::vector<std::vector<dataType>> &treeTable,
335 std::vector<std::vector<dataType>> &forestTable) {
336 std::vector<ftm::idNode> children;
337 tree2->getChildren(nodeJ, children);
338 forestTable[0][j] = 0;
339 for(ftm::idNode const child : children)
340 forestTable[0][j] += treeTable[0][child + 1];
341 }
342
343 template <class dataType>
345 const ftm::FTMTree_MT *tree2,
346 ftm::idNode nodeJ,
347 int j,
348 std::vector<std::vector<dataType>> &treeTable,
349 std::vector<std::vector<dataType>> &forestTable) {
350 treeTable[0][j] = forestTable[0][j] + insertCost<dataType>(tree2, nodeJ);
351 }
352
353 // Compute first or second term of forests and subtrees distance
354 template <class dataType>
355 std::tuple<dataType, ftm::idNode>
356 computeTerm1_2(std::vector<ftm::idNode> &childrens,
357 int ind,
358 std::vector<std::vector<dataType>> &table,
359 bool computeTerm1) {
360 dataType tempMin = (childrens.size() == 0)
361 ? ((computeTerm1) ? table[ind][0] : table[0][ind])
362 : std::numeric_limits<dataType>::max();
363 ftm::idNode bestIdNode = 0;
364 for(ftm::idNode children : childrens) {
365 children += 1;
366 dataType temp;
367 if(computeTerm1) {
368 temp = table[ind][children] - table[0][children];
369 } else {
370 temp = table[children][ind] - table[children][0];
371 }
372 if(temp < tempMin) {
373 tempMin = temp;
374 bestIdNode = children;
375 }
376 }
377 return std::make_tuple(tempMin, bestIdNode);
378 }
379
380 template <class dataType>
382 const ftm::FTMTree_MT *tree1,
383 const ftm::FTMTree_MT *tree2,
384 int i,
385 int j,
386 ftm::idNode nodeI,
387 ftm::idNode nodeJ,
388 std::vector<std::vector<dataType>> &treeTable,
389 std::vector<std::vector<dataType>> &forestTable,
390 std::vector<std::vector<std::tuple<int, int>>> &treeBackTable,
391 std::vector<ftm::idNode> &children1,
392 std::vector<ftm::idNode> &children2) {
393 dataType treeTerm3;
394
395 // Term 3
396 treeTerm3
397 = forestTable[i][j] + relabelCost<dataType>(tree1, nodeI, tree2, nodeJ);
398
399 if(not keepSubtree_) {
400 // Compute table value
401 treeTable[i][j] = treeTerm3;
402 // Add backtracking information
403 treeBackTable[i][j] = std::make_tuple(i, j);
404 } else {
405 dataType treeTerm1, treeTerm2;
406 std::tuple<dataType, ftm::idNode> treeCoTerm1, treeCoTerm2;
407
408 // Term 1
409 treeCoTerm1 = computeTerm1_2<dataType>(children2, i, treeTable, true);
410 treeTerm1 = treeTable[0][j] + std::get<0>(treeCoTerm1);
411
412 // Term 2
413 treeCoTerm2 = computeTerm1_2<dataType>(children1, j, treeTable, false);
414 treeTerm2 = treeTable[i][0] + std::get<0>(treeCoTerm2);
415
416 // Compute table value
417 treeTable[i][j] = std::min(std::min(treeTerm1, treeTerm2), treeTerm3);
418
419 // Add backtracking information
420 if(treeTable[i][j] == treeTerm3) {
421 treeBackTable[i][j] = std::make_tuple(i, j);
422 } else if(treeTable[i][j] == treeTerm2) {
423 treeBackTable[i][j] = std::make_tuple(std::get<1>(treeCoTerm2), j);
424 } else {
425 treeBackTable[i][j] = std::make_tuple(i, std::get<1>(treeCoTerm1));
426 }
427 }
428 }
429
430 // --------------------------------------------------------------------------------
431 // Output Matching
432 // --------------------------------------------------------------------------------
433 template <class dataType>
435 const ftm::FTMTree_MT *tree1,
436 const ftm::FTMTree_MT *tree2,
437 std::vector<std::vector<std::tuple<int, int>>> &treeBackTable,
438 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
439 &forestBackTable,
440 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> &outputMatching,
441 int startR,
442 int startC) {
443 outputMatching.clear();
444 std::queue<std::tuple<int, int, bool>> backQueue;
445 backQueue.emplace(startR, startC, true);
446 while(!backQueue.empty()) {
447 std::tuple<int, int, bool> elem = backQueue.front();
448 backQueue.pop();
449 bool useTreeTable = std::get<2>(elem);
450 int const i = std::get<0>(elem);
451 int const j = std::get<1>(elem);
452
453 if(useTreeTable) {
454 int const tupleI = std::get<0>(treeBackTable[i][j]);
455 int const tupleJ = std::get<1>(treeBackTable[i][j]);
456 if(tupleI != 0 && tupleJ != 0) {
457 useTreeTable = (tupleI != i || tupleJ != j);
458 backQueue.emplace(tupleI, tupleJ, useTreeTable);
459 if(not useTreeTable) { // We have matched i and j
460 ftm::idNode const tree1Node = tupleI - 1;
461 ftm::idNode const tree2Node = tupleJ - 1;
462 double cost = 0;
463 dataType costT
464 = relabelCost<dataType>(tree1, tree1Node, tree2, tree2Node);
465 cost = static_cast<double>(costT);
466 outputMatching.emplace_back(tree1Node, tree2Node, cost);
467 }
468 }
469 } else {
470 for(std::tuple<int, int> forestBackElem : forestBackTable[i][j]) {
471 int const tupleI = std::get<0>(forestBackElem);
472 int const tupleJ = std::get<1>(forestBackElem);
473 if(tupleI != 0 && tupleJ != 0) {
474 useTreeTable = (tupleI != i && tupleJ != j);
475 backQueue.emplace(tupleI, tupleJ, useTreeTable);
476 }
477 }
478 }
479 }
480 }
481
482 // ------------------------------------------------------------------------
483 // Main Functions
484 // ------------------------------------------------------------------------
485 template <class dataType>
486 dataType
488 const ftm::FTMTree_MT *tree2,
489 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
490 &outputMatching) {
491 // ---------------------
492 // ----- Init dynamic programming tables
493 // --------------------
494 size_t const nRows = tree1->getNumberOfNodes() + 1;
495 size_t const nCols = tree2->getNumberOfNodes() + 1;
496 std::vector<std::vector<dataType>> treeTable(
497 nRows, std::vector<dataType>(nCols));
498 std::vector<std::vector<dataType>> forestTable(
499 nRows, std::vector<dataType>(nCols));
500
501 // Backtracking tables (output matching)
502 std::vector<std::vector<std::tuple<int, int>>> treeBackTable(
503 nRows, std::vector<std::tuple<int, int>>(nCols));
504 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
505 forestBackTable(
506 nRows, std::vector<std::vector<std::tuple<int, int>>>(nCols));
507
508 int const indR = tree1->getRoot() + 1;
509 int const indC = tree2->getRoot() + 1;
510
511 tree1->getAllNodeLevel(tree1Level_);
512 tree2->getAllNodeLevel(tree2Level_);
513 tree2->getLevelToNode(tree2LevelToNode_);
514
515 // ---------------------
516 // ----- Compute edit distance
517 // --------------------
518 computeEditDistance(tree1, tree2, treeTable, forestTable, treeBackTable,
519 forestBackTable, nRows, nCols);
520 dataType distance = treeTable[indR][indC];
521 if(onlyEmptyTreeDistance_)
522 distance = treeTable[indR][0];
524 if(not useMinMaxPair_) {
525 if(onlyEmptyTreeDistance_)
526 distance -= deleteCost<dataType>(tree1, tree1->getRoot());
527 else
528 distance -= relabelCost<dataType>(
529 tree1, tree1->getRoot(), tree2, tree2->getRoot());
530 } else {
531 if(minMaxPairWeight_ != 1.0) {
532 auto cost = relabelCost<dataType>(
533 tree1, tree1->getRoot(), tree2, tree2->getRoot());
534 distance = distance - cost + minMaxPairWeight_ * cost;
535 }
536 }
537 }
539 distance = std::sqrt(distance);
540
541 // ---------------------
542 // ----- Compute matching
543 // --------------------
544 computeMatching<dataType>(tree1, tree2, treeBackTable, forestBackTable,
545 outputMatching, indR, indC);
546
547 return distance;
548 }
549
550 template <class dataType>
552 const ftm::FTMTree_MT *tree1,
553 const ftm::FTMTree_MT *tree2,
554 std::vector<std::tuple<ftm::idNode, ftm::idNode>> &outputMatching) {
555 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
556 realOutputMatching;
557 dataType res
558 = computeDistance<dataType>(tree1, tree2, realOutputMatching);
559 for(auto tup : realOutputMatching)
560 outputMatching.emplace_back(std::get<0>(tup), std::get<1>(tup));
561 return res;
562 }
563
564 template <class dataType>
567 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
568 &outputMatching) {
569 Memory m;
570 Timer t_total;
571
572 // ---------------------
573 // ----- Testing
574 // --------------------
575 testing_ = false;
576
577 // ---------------------
578 // ----- Preprocessing
579 // --------------------
580 ftm::MergeTree<dataType> mTree1Copy;
581 ftm::MergeTree<dataType> mTree2Copy;
582 if(saveTree_) {
583 mTree1Copy = ftm::copyMergeTree<dataType>(mTree1);
584 mTree2Copy = ftm::copyMergeTree<dataType>(mTree2);
585 }
586 ftm::MergeTree<dataType> &mTree1Int = (saveTree_ ? mTree1Copy : mTree1);
587 ftm::MergeTree<dataType> &mTree2Int = (saveTree_ ? mTree2Copy : mTree2);
588 ftm::FTMTree_MT *tree1 = &(mTree1Int.tree);
589 ftm::FTMTree_MT *tree2 = &(mTree2Int.tree);
590 if(not isCalled_ and not isPersistenceDiagram_) {
593 }
594 if(preprocess_) {
595 treesNodeCorr_.resize(2);
602 }
603 tree1 = &(mTree1Int.tree);
604 tree2 = &(mTree2Int.tree);
605
606 // ---------------------
607 // ----- Compute Distance
608 // --------------------
609 dataType distance
610 = computeDistance<dataType>(tree1, tree2, outputMatching);
611
612 // ---------------------
613 // ----- Postprocessing
614 // --------------------
615 if(postprocess_) {
620 tree1, tree2, outputMatching);
621 }
622
623 // std::cout << "TIME COMP.MATCH. = " << t_match_time << std::endl;
624 printMsg("Total", 1, t_total.getElapsedTime(), this->threadNumber_,
627 std::stringstream ss2;
628 ss2 << "DISTANCE² = "
629 << (distanceSquaredRoot_ ? distance * distance : distance);
630 printMsg(ss2.str());
631 std::stringstream ss3;
632 ss3 << "DISTANCE = "
633 << (distanceSquaredRoot_ ? distance : std::sqrt(distance));
634 printMsg(ss3.str());
636 std::stringstream ss4;
637 ss4 << "MEMORY = " << m.getElapsedUsage();
638 printMsg(ss4.str());
640
641 return distance;
642 }
643
644 template <class dataType>
645 dataType execute(
648 std::vector<std::tuple<ftm::idNode, ftm::idNode>> &outputMatching) {
649 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
650 realOutputMatching;
651 dataType res = execute<dataType>(tree1, tree2, realOutputMatching);
652 for(auto tup : realOutputMatching)
653 outputMatching.emplace_back(std::get<0>(tup), std::get<1>(tup));
654 return res;
655 }
656
657 template <class dataType>
659 const ftm::FTMTree_MT *tree1,
660 const ftm::FTMTree_MT *tree2,
661 std::vector<std::vector<dataType>> &treeTable,
662 std::vector<std::vector<dataType>> &forestTable,
663 std::vector<std::vector<std::tuple<int, int>>> &treeBackTable,
664 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
665 &forestBackTable,
666 int nRows,
667 int nCols) {
668 Timer t_dyn;
669 t_assignment_time_ = 0;
670
671 if(parallelize_) {
672 parallelEditDistance(tree1, tree2, treeTable, forestTable,
673 treeBackTable, forestBackTable, nRows, nCols);
674 } else {
675 // Distance T1 to empty tree
676 classicEditDistance(tree1, tree2, true, true, tree1->getRoot(),
677 tree2->getRoot(), treeTable, forestTable,
678 treeBackTable, forestBackTable, nRows, nCols);
679 if(onlyEmptyTreeDistance_)
680 return;
681 // Distance T2 to empty tree
682 classicEditDistance(tree1, tree2, false, true, tree1->getRoot(),
683 tree2->getRoot(), treeTable, forestTable,
684 treeBackTable, forestBackTable, nRows, nCols);
685 // Distance T1 to T2
686 classicEditDistance(tree1, tree2, true, false, tree1->getRoot(),
687 tree2->getRoot(), treeTable, forestTable,
688 treeBackTable, forestBackTable, nRows, nCols);
689 }
690
691 printMsg("Dynamic programing", 1, t_dyn.getElapsedTime(),
692 this->threadNumber_, debug::LineMode::NEW,
694 if(not parallelize_)
695 printMsg("Assignment problems", 1, t_assignment_time_,
698 }
699
700 template <class dataType>
702 const ftm::FTMTree_MT *tree1,
703 const ftm::FTMTree_MT *tree2,
704 bool processTree1,
705 bool computeEmptyTree,
706 ftm::idNode nodeI,
707 ftm::idNode nodeJ,
708 std::vector<std::vector<dataType>> &treeTable,
709 std::vector<std::vector<dataType>> &forestTable,
710 std::vector<std::vector<std::tuple<int, int>>> &treeBackTable,
711 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
712 &forestBackTable,
713 int nRows,
714 int nCols) {
715 if(processTree1) {
716 std::vector<ftm::idNode> childrens;
717 tree1->getChildren(nodeI, childrens);
718 for(auto children : childrens)
719 classicEditDistance(tree1, tree2, processTree1, computeEmptyTree,
720 children, nodeJ, treeTable, forestTable,
721 treeBackTable, forestBackTable, nRows, nCols);
722 } else {
723 std::vector<ftm::idNode> childrens;
724 tree2->getChildren(nodeJ, childrens);
725 for(auto children : childrens)
726 classicEditDistance(tree1, tree2, processTree1, computeEmptyTree,
727 nodeI, children, treeTable, forestTable,
728 treeBackTable, forestBackTable, nRows, nCols);
729 }
730
731 if(processTree1) {
732 if(computeEmptyTree) {
733 int const i = nodeI + 1;
734 // --- Forest to empty tree distance
735 computeForestToEmptyDistance(tree1, nodeI, i, treeTable, forestTable);
736
737 // --- Subtree to empty tree distance
739 tree1, nodeI, i, treeTable, forestTable);
740 } else
741 classicEditDistance(tree1, tree2, false, false, nodeI,
742 tree2->getRoot(), treeTable, forestTable,
743 treeBackTable, forestBackTable, nRows, nCols);
744 } else {
745 int const j = nodeJ + 1;
746 if(computeEmptyTree) {
747 // --- Empty tree to forest distance
748 computeEmptyToForestDistance(tree2, nodeJ, j, treeTable, forestTable);
749
750 // --- Empty tree to subtree distance
752 tree2, nodeJ, j, treeTable, forestTable);
753 //}else{
754 } else if(keepSubtree_ or tree1Level_[nodeI] == tree2Level_[nodeJ]) {
755 int const i = nodeI + 1;
756 std::vector<ftm::idNode> children1;
757 tree1->getChildren(nodeI, children1);
758 std::vector<ftm::idNode> children2;
759 tree2->getChildren(nodeJ, children2);
760 // --- Forests distance
761 computeForestsDistance(tree1, tree2, i, j, treeTable, forestTable,
762 forestBackTable, children1, children2);
763
764 // --- Subtrees distance
765 computeSubtreesDistance(tree1, tree2, i, j, nodeI, nodeJ, treeTable,
766 forestTable, treeBackTable, children1,
767 children2);
768 }
769 }
770 }
771
772 // ------------------------------------------------------------------------
773 // Parallel version
774 // ------------------------------------------------------------------------
775 template <class dataType>
777 const ftm::FTMTree_MT *tree1,
778 const ftm::FTMTree_MT *tree2,
779 std::vector<std::vector<dataType>> &treeTable,
780 std::vector<std::vector<dataType>> &forestTable,
781 std::vector<std::vector<std::tuple<int, int>>> &treeBackTable,
782 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
783 &forestBackTable,
784 int ttkNotUsed(nRows),
785 int ttkNotUsed(nCols)) {
786 std::vector<int> tree1NodeChildSize, tree2NodeChildSize;
787 for(unsigned int i = 0; i < tree1->getNumberOfNodes(); ++i) {
788 std::vector<ftm::idNode> children;
789 tree1->getChildren(i, children);
790 tree1NodeChildSize.push_back(children.size());
791 }
792 for(unsigned int j = 0; j < tree2->getNumberOfNodes(); ++j) {
793 std::vector<ftm::idNode> children;
794 tree2->getChildren(j, children);
795 tree2NodeChildSize.push_back(children.size());
796 }
797
798 // Get trees data
799 std::vector<ftm::idNode> tree1Leaves;
800 tree1->getLeavesFromTree(tree1Leaves);
801 std::vector<ftm::idNode> tree2Leaves;
802 tree2->getLeavesFromTree(tree2Leaves);
803
804 // Distance T1 to empty tree
805 parallelEmptyTreeDistance_v2(tree1, true, tree1Leaves, tree1NodeChildSize,
806 treeTable, forestTable, treeBackTable,
807 forestBackTable);
808 if(onlyEmptyTreeDistance_)
809 return;
810 // Distance T2 to empty tree
811 parallelEmptyTreeDistance_v2(tree2, false, tree2Leaves,
812 tree2NodeChildSize, treeTable, forestTable,
813 treeBackTable, forestBackTable);
814 // Distance T1 to T2
815 parallelTreeDistance_v2(tree1, tree2, true, 0, tree1Leaves,
816 tree1NodeChildSize, tree2Leaves,
817 tree2NodeChildSize, treeTable, forestTable,
818 treeBackTable, forestBackTable, true);
819 }
820
821 // Forests and subtrees distances
822 template <class dataType>
824 const ftm::FTMTree_MT *tree1,
825 const ftm::FTMTree_MT *tree2,
826 bool isTree1,
827 int i,
828 std::vector<ftm::idNode> &tree1Leaves,
829 std::vector<int> &tree1NodeChildSize,
830 std::vector<ftm::idNode> &tree2Leaves,
831 std::vector<int> &tree2NodeChildSize,
832 std::vector<std::vector<dataType>> &treeTable,
833 std::vector<std::vector<dataType>> &forestTable,
834 std::vector<std::vector<std::tuple<int, int>>> &treeBackTable,
835 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
836 &forestBackTable,
837 bool firstCall = false) {
838 ftm::idNode const nodeT = -1;
839 const ftm::FTMTree_MT *treeT = (isTree1) ? tree1 : tree2;
840 std::vector<int> treeChildDone(treeT->getNumberOfNodes(), 0);
841 std::vector<bool> treeNodeDone(treeT->getNumberOfNodes(), false);
842 std::queue<ftm::idNode> treeQueue;
843
844 if(isTree1)
845 for(ftm::idNode const leaf : tree1Leaves)
846 treeQueue.emplace(leaf);
847 else if(keepSubtree_)
848 for(ftm::idNode const leaf : tree2Leaves)
849 treeQueue.emplace(leaf);
850 else if(tree1Level_[i - 1] < (int)tree2LevelToNode_.size())
851 for(ftm::idNode const node : tree2LevelToNode_[tree1Level_[i - 1]])
852 treeQueue.emplace(node);
853
854 if(not isCalled_) // and firstCall)
855 parallelTreeDistancePara(tree1, tree2, isTree1, i, tree1Leaves,
856 tree1NodeChildSize, tree2Leaves,
857 tree2NodeChildSize, treeTable, forestTable,
858 treeBackTable, forestBackTable, firstCall,
859 nodeT, treeChildDone, treeNodeDone, treeQueue);
860 else
861 parallelTreeDistanceTask(tree1, tree2, isTree1, i, tree1Leaves,
862 tree1NodeChildSize, tree2Leaves,
863 tree2NodeChildSize, treeTable, forestTable,
864 treeBackTable, forestBackTable, nodeT,
865 treeChildDone, treeNodeDone, treeQueue);
866 }
867
868 // (isCalled_=false)
869 template <class dataType>
871 const ftm::FTMTree_MT *tree1,
872 const ftm::FTMTree_MT *tree2,
873 bool isTree1,
874 int i,
875 std::vector<ftm::idNode> &tree1Leaves,
876 std::vector<int> &tree1NodeChildSize,
877 std::vector<ftm::idNode> &tree2Leaves,
878 std::vector<int> &tree2NodeChildSize,
879 std::vector<std::vector<dataType>> &treeTable,
880 std::vector<std::vector<dataType>> &forestTable,
881 std::vector<std::vector<std::tuple<int, int>>> &treeBackTable,
882 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
883 &forestBackTable,
884 bool firstCall,
885 ftm::idNode nodeT,
886 std::vector<int> &treeChildDone,
887 std::vector<bool> &treeNodeDone,
888 std::queue<ftm::idNode> &treeQueue) {
889#ifdef TTK_ENABLE_OPENMP4
890#pragma omp parallel num_threads(this->threadNumber_) if(firstCall)
891 {
892#pragma omp single nowait
893#endif
894 parallelTreeDistanceTask(tree1, tree2, isTree1, i, tree1Leaves,
895 tree1NodeChildSize, tree2Leaves,
896 tree2NodeChildSize, treeTable, forestTable,
897 treeBackTable, forestBackTable, nodeT,
898 treeChildDone, treeNodeDone, treeQueue);
899#ifdef TTK_ENABLE_OPENMP4
900 } // pragma omp parallel
901#endif
902
903 TTK_FORCE_USE(firstCall);
904 }
905
906 template <class dataType>
908 const ftm::FTMTree_MT *tree1,
909 const ftm::FTMTree_MT *tree2,
910 bool isTree1,
911 int i,
912 std::vector<ftm::idNode> &tree1Leaves,
913 std::vector<int> &tree1NodeChildSize,
914 std::vector<ftm::idNode> &tree2Leaves,
915 std::vector<int> &tree2NodeChildSize,
916 std::vector<std::vector<dataType>> &treeTable,
917 std::vector<std::vector<dataType>> &forestTable,
918 std::vector<std::vector<std::tuple<int, int>>> &treeBackTable,
919 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
920 &forestBackTable,
921 ftm::idNode nodeT,
922 std::vector<int> &treeChildDone,
923 std::vector<bool> &treeNodeDone,
924 std::queue<ftm::idNode> &treeQueue) {
925 int nodePerTask = nodePerTask_;
926 while(!treeQueue.empty()) {
927 std::queue<ftm::idNode> taskQueue;
928 nodePerTask = nodePerTask > (int)treeQueue.size() ? treeQueue.size()
929 : nodePerTask;
930 for(int j = 0; j < nodePerTask; ++j) {
931 nodeT = treeQueue.front();
932 treeQueue.pop();
933 taskQueue.emplace(nodeT);
934 }
935#ifdef TTK_ENABLE_OPENMP4
936#pragma omp task firstprivate(taskQueue, nodeT) UNTIED() \
937 shared(treeTable, forestTable, treeBackTable, forestBackTable, \
938 treeChildDone, treeNodeDone) if(isTree1)
939 {
940#endif
941 const ftm::FTMTree_MT *treeT = (isTree1) ? tree1 : tree2;
942 // while(nodeT != -1){
943 while(!taskQueue.empty()) {
944 nodeT = taskQueue.front();
945 taskQueue.pop();
946 int const t = nodeT + 1;
947 ftm::idNode const nodeI = i - 1;
948
949 if(isTree1) {
951 tree1, tree2, false, t, tree1Leaves, tree1NodeChildSize,
952 tree2Leaves, tree2NodeChildSize, treeTable, forestTable,
953 treeBackTable, forestBackTable, false);
954 //}else{
955 } else if(keepSubtree_
956 or tree1Level_[nodeI] == tree2Level_[nodeT]) {
957 int const j = nodeT + 1;
958 std::vector<ftm::idNode> children1;
959 tree1->getChildren(nodeI, children1);
960 std::vector<ftm::idNode> children2;
961 tree2->getChildren(nodeT, children2);
962 // --- Forests distance
963 computeForestsDistance(tree1, tree2, i, j, treeTable, forestTable,
964 forestBackTable, children1, children2);
965
966 // --- Subtrees distance
967 computeSubtreesDistance(tree1, tree2, i, j, nodeI, nodeT,
968 treeTable, forestTable, treeBackTable,
969 children1, children2);
970 }
971
972 if(not isTree1 and not keepSubtree_
973 and tree1Level_[nodeI] == tree2Level_[nodeT])
974 continue;
975
976 // Manage parent
977 ftm::idNode const nodeTParent = treeT->getParentSafe(nodeT);
978 int const childSize = (isTree1) ? tree1NodeChildSize[nodeTParent]
979 : tree2NodeChildSize[nodeTParent];
980 int oldTreeChildDone;
981#ifdef TTK_ENABLE_OPENMP4
982#pragma omp atomic capture
983 {
984#endif
985 oldTreeChildDone = treeChildDone[nodeTParent];
986 treeChildDone[nodeTParent]++;
987#ifdef TTK_ENABLE_OPENMP4
988 } // pragma omp atomic capture
989#endif
990 if(not treeNodeDone[nodeTParent]
991 and oldTreeChildDone + 1 == childSize) {
992 // nodeT = nodeTParent;
993 taskQueue.emplace(nodeTParent);
994 treeNodeDone[nodeTParent] = true;
995#ifdef TTK_ENABLE_OPENMP4
996#pragma omp taskyield
997#endif
998 } else
999 nodeT = -1;
1000
1001 } // while nodeI loop
1002#ifdef TTK_ENABLE_OPENMP4
1003 } // pragma omp task
1004#endif
1005 } // while treeQueue loop
1006#ifdef TTK_ENABLE_OPENMP4
1007#pragma omp taskwait
1008#endif
1009 }
1010
1011 // Subtree/Forest with empty tree distances
1012 template <class dataType>
1014 const ftm::FTMTree_MT *tree,
1015 bool isTree1,
1016 std::vector<ftm::idNode> &treeLeaves,
1017 std::vector<int> &treeNodeChildSize,
1018 std::vector<std::vector<dataType>> &treeTable,
1019 std::vector<std::vector<dataType>> &forestTable,
1020 std::vector<std::vector<std::tuple<int, int>>> &treeBackTable,
1021 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
1022 &forestBackTable) {
1023 ftm::idNode const nodeT = -1;
1024 std::vector<int> treeChildDone(tree->getNumberOfNodes(), 0);
1025 std::vector<bool> treeNodeDone(tree->getNumberOfNodes(), false);
1026 std::queue<ftm::idNode> treeQueue;
1027 for(ftm::idNode const leaf : treeLeaves)
1028 treeQueue.emplace(leaf);
1029 if(not isCalled_)
1030 parallelEmptyTreeDistancePara(tree, isTree1, treeLeaves,
1031 treeNodeChildSize, treeTable, forestTable,
1032 treeBackTable, forestBackTable, nodeT,
1033 treeChildDone, treeNodeDone, treeQueue);
1034 else
1035 parallelEmptyTreeDistanceTask(tree, isTree1, treeLeaves,
1036 treeNodeChildSize, treeTable, forestTable,
1037 treeBackTable, forestBackTable, nodeT,
1038 treeChildDone, treeNodeDone, treeQueue);
1039 }
1040
1041 template <class dataType>
1043 const ftm::FTMTree_MT *tree,
1044 bool isTree1,
1045 std::vector<ftm::idNode> &treeLeaves,
1046 std::vector<int> &treeNodeChildSize,
1047 std::vector<std::vector<dataType>> &treeTable,
1048 std::vector<std::vector<dataType>> &forestTable,
1049 std::vector<std::vector<std::tuple<int, int>>> &treeBackTable,
1050 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
1051 &forestBackTable,
1052 ftm::idNode nodeT,
1053 std::vector<int> &treeChildDone,
1054 std::vector<bool> &treeNodeDone,
1055 std::queue<ftm::idNode> &treeQueue) {
1056#ifdef TTK_ENABLE_OPENMP4
1057#pragma omp parallel num_threads(this->threadNumber_)
1058 {
1059#pragma omp single nowait
1060#endif
1061 parallelEmptyTreeDistanceTask(tree, isTree1, treeLeaves,
1062 treeNodeChildSize, treeTable, forestTable,
1063 treeBackTable, forestBackTable, nodeT,
1064 treeChildDone, treeNodeDone, treeQueue);
1065#ifdef TTK_ENABLE_OPENMP4
1066 } // pragma omp parallel
1067#endif
1068 }
1069
1070 template <class dataType>
1072 const ftm::FTMTree_MT *tree,
1073 bool isTree1,
1074 std::vector<ftm::idNode> &ttkNotUsed(treeLeaves),
1075 std::vector<int> &treeNodeChildSize,
1076 std::vector<std::vector<dataType>> &treeTable,
1077 std::vector<std::vector<dataType>> &forestTable,
1078 std::vector<std::vector<std::tuple<int, int>>> &treeBackTable,
1079 std::vector<std::vector<std::vector<std::tuple<int, int>>>>
1080 &forestBackTable,
1081 ftm::idNode nodeT,
1082 std::vector<int> &treeChildDone,
1083 std::vector<bool> &treeNodeDone,
1084 std::queue<ftm::idNode> &treeQueue) {
1085 while(!treeQueue.empty()) {
1086 nodeT = treeQueue.front();
1087 treeQueue.pop();
1088
1089#ifdef TTK_ENABLE_OPENMP4
1090#pragma omp task firstprivate(nodeT) UNTIED() \
1091 shared(treeTable, forestTable, treeBackTable, forestBackTable, \
1092 treeChildDone, treeNodeDone)
1093 {
1094#endif
1095 while((int)nodeT != -1) {
1096 if(isTree1) {
1097 int const i = nodeT + 1;
1098 // --- Forest to empty tree distance
1100 tree, nodeT, i, treeTable, forestTable);
1101
1102 // --- Subtree to empty tree distance
1104 tree, nodeT, i, treeTable, forestTable);
1105 } else {
1106 int const j = nodeT + 1;
1107 // --- Empty tree to forest distance
1109 tree, nodeT, j, treeTable, forestTable);
1110
1111 // --- Empty tree to subtree distance
1113 tree, nodeT, j, treeTable, forestTable);
1114 }
1115
1116 // Manage parent
1117 ftm::idNode const nodeTParent = tree->getParentSafe(nodeT);
1118 int oldTreeChildDone;
1119#ifdef TTK_ENABLE_OPENMP4
1120#pragma omp atomic capture
1121 {
1122#endif
1123 oldTreeChildDone = treeChildDone[nodeTParent];
1124 treeChildDone[nodeTParent]++;
1125#ifdef TTK_ENABLE_OPENMP4
1126 } // pragma omp atomic capture
1127#endif
1128 if(not treeNodeDone[nodeTParent]
1129 and oldTreeChildDone + 1 == treeNodeChildSize[nodeTParent]) {
1130 nodeT = nodeTParent;
1131 treeNodeDone[nodeTParent] = true;
1132#ifdef TTK_ENABLE_OPENMP4
1133#pragma omp taskyield
1134#endif
1135 } else
1136 nodeT = -1;
1137
1138 } // while nodeI loop
1139#ifdef TTK_ENABLE_OPENMP4
1140 } // pragma omp task
1141#endif
1142 } // while treeQueue loop
1143#ifdef TTK_ENABLE_OPENMP4
1144#pragma omp taskwait
1145#endif
1146
1147 TTK_FORCE_USE(treeBackTable);
1148 TTK_FORCE_USE(forestBackTable);
1149 }
1150
1151 // ------------------------------------------------------------------------
1152 // Utils
1153 // ------------------------------------------------------------------------
1154 void printMapIntInt(std::map<int, int> theMap) {
1155 for(auto itr = theMap.begin(); itr != theMap.end(); ++itr) {
1156 std::stringstream ss;
1157 ss << '\t' << itr->first << '\t' << itr->second;
1158 printMsg(ss.str());
1159 }
1160 printMsg("");
1161 }
1162
1163 template <class dataType>
1165 bool problem = false;
1166
1167 bool const isJT = tree->isJoinTree<dataType>();
1168 std::vector<std::tuple<ftm::idNode, ftm::idNode>> problemNodes;
1169 std::queue<ftm::idNode> queue;
1170 queue.emplace(tree->getRoot());
1171 while(!queue.empty()) {
1172 ftm::idNode const node = queue.front();
1173 queue.pop();
1174
1175 if(!tree->isRoot(node)) {
1176 bool thisProblem;
1177 if(isJT)
1178 thisProblem = tree->getValue<dataType>(node)
1179 > tree->getValue<dataType>(tree->getParentSafe(node));
1180 else
1181 thisProblem = tree->getValue<dataType>(node)
1182 < tree->getValue<dataType>(tree->getParentSafe(node));
1183
1184 if(thisProblem)
1185 problemNodes.emplace_back(node, tree->getParentSafe(node));
1186
1187 problem |= thisProblem;
1188 }
1189
1190 std::vector<ftm::idNode> children;
1191 tree->getChildren(node, children);
1192 for(auto c : children)
1193 queue.emplace(c);
1194 }
1195
1196 if(problem) {
1197 printErr("merge tree in input is not valid");
1198 for(auto tup : problemNodes) {
1199 std::stringstream ss;
1200 ss << std::get<0>(tup) << " _ " << std::get<1>(tup);
1201 printMsg(ss.str());
1202 }
1203 printMsg(tree->printTree().str());
1204 printMsg(tree->printTreeScalars<dataType>().str());
1205 }
1206 }
1207
1208 // ------------------------------------------------------------------------
1209 // Testing
1210 // ------------------------------------------------------------------------
1211 template <class dataType>
1213 ftm::FTMTree_MT *tree2) {
1214 std::vector<std::tuple<ftm::idNode, ftm::idNode, dataType>> pairs1,
1215 pairs2;
1216 tree1->getPersistencePairsFromTree(pairs1);
1217 tree2->getPersistencePairsFromTree(pairs2);
1218 std::vector<std::vector<dataType>> costMatrix(
1219 pairs1.size() + 1, std::vector<dataType>(pairs2.size() + 1));
1220 std::stringstream const ss;
1221 ss << costMatrix.size() << " _ " << costMatrix[0].size();
1222 printMsg(ss.str());
1223 for(unsigned int i = 0; i < costMatrix.size() - 1; ++i) {
1224 dataType nodeIValue = tree1->getValue<dataType>(std::get<0>(pairs1[i]));
1225 dataType nodeIOriginValue
1226 = tree1->getValue<dataType>(std::get<1>(pairs1[i]));
1227 for(unsigned int j = 0; j < costMatrix[0].size() - 1; ++j) {
1228 dataType nodeJValue
1229 = tree2->getValue<dataType>(std::get<0>(pairs2[j]));
1230 dataType nodeJOriginValue
1231 = tree2->getValue<dataType>(std::get<1>(pairs2[j]));
1232 costMatrix[i][j] = std::pow(nodeIValue - nodeJValue, 2)
1233 + std::pow(nodeIOriginValue - nodeJOriginValue, 2);
1234 }
1235 costMatrix[i][costMatrix[0].size() - 1]
1236 = 2 * std::pow(std::get<2>(pairs1[i]), 2) / (std::pow(2, 2));
1237 }
1238 for(unsigned int j = 0; j < costMatrix[0].size() - 1; ++j)
1239 costMatrix[costMatrix.size() - 1][j]
1240 = 2 * std::pow(std::get<2>(pairs2[j]), 2) / (std::pow(2, 2));
1241 std::vector<MatchingType> matchings;
1242 forestAssignmentProblemMunkres(costMatrix, matchings);
1243 dataType cost = 0;
1244 for(auto tuple : matchings)
1245 cost += std::get<2>(tuple);
1246 std::stringstream ss2;
1247 ss2 << "cost = " << cost;
1248 printMsg(ss2.str());
1249 std::stringstream ss3;
1250 ss3 << "cost sqrt = " << std::sqrt(cost);
1251 printMsg(ss3.str());
1252 }
1253
1254 }; // MergeTreeDistance class
1255
1256} // namespace ttk
#define TTK_FORCE_USE(x)
Force the compiler to use the function/method parameter.
Definition BaseClass.h:57
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
void setEpsilon(double eps)
void setEpsilonDiviserMultiplier(double div)
void setNumberOfRounds(int noRounds)
virtual int run(std::vector< MatchingType > &matchings)=0
virtual int setInput(std::vector< std::vector< dataType > > &C_)
virtual void setBalanced(bool balanced)
void setDebugMsgPrefix(const std::string &prefix)
Definition Debug.h:364
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
float getElapsedUsage()
Definition Os.h:112
dataType deleteCost(const ftm::FTMTree_MT *tree, ftm::idNode nodeId)
void convertBranchDecompositionMatching(ftm::FTMTree_MT *tree1, ftm::FTMTree_MT *tree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &outputMatching)
dataType relabelCost(const ftm::FTMTree_MT *tree1, ftm::idNode nodeId1, const ftm::FTMTree_MT *tree2, ftm::idNode nodeId2)
void preprocessingPipeline(ftm::MergeTree< dataType > &mTree, double epsilonTree, double epsilon2Tree, double epsilon3Tree, bool branchDecompositionT, bool useMinMaxPairT, bool cleanTreeT, double persistenceThreshold, std::vector< int > &nodeCorr, bool deleteInconsistentNodes=true, bool removeMergedSaddles=false)
void postprocessingPipeline(ftm::FTMTree_MT *tree)
std::vector< std::vector< int > > treesNodeCorr_
dataType insertCost(const ftm::FTMTree_MT *tree, ftm::idNode nodeId)
std::tuple< dataType, ftm::idNode > computeTerm1_2(std::vector< ftm::idNode > &childrens, int ind, std::vector< std::vector< dataType > > &table, bool computeTerm1)
void setOnlyEmptyTreeDistance(double only)
void setPreprocess(bool preproc)
void parallelTreeDistance_v2(const ftm::FTMTree_MT *tree1, const ftm::FTMTree_MT *tree2, bool isTree1, int i, std::vector< ftm::idNode > &tree1Leaves, std::vector< int > &tree1NodeChildSize, std::vector< ftm::idNode > &tree2Leaves, std::vector< int > &tree2NodeChildSize, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable, std::vector< std::vector< std::tuple< int, int > > > &treeBackTable, std::vector< std::vector< std::vector< std::tuple< int, int > > > > &forestBackTable, bool firstCall=false)
void parallelEmptyTreeDistancePara(const ftm::FTMTree_MT *tree, bool isTree1, std::vector< ftm::idNode > &treeLeaves, std::vector< int > &treeNodeChildSize, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable, std::vector< std::vector< std::tuple< int, int > > > &treeBackTable, std::vector< std::vector< std::vector< std::tuple< int, int > > > > &forestBackTable, ftm::idNode nodeT, std::vector< int > &treeChildDone, std::vector< bool > &treeNodeDone, std::queue< ftm::idNode > &treeQueue)
dataType forestAssignmentProblem(const ftm::FTMTree_MT *ttkNotUsed(tree1), const ftm::FTMTree_MT *ttkNotUsed(tree2), std::vector< std::vector< dataType > > &treeTable, std::vector< ftm::idNode > &children1, std::vector< ftm::idNode > &children2, std::vector< std::tuple< int, int > > &forestAssignment)
void runAssignmentProblemSolver(std::vector< std::vector< dataType > > &costMatrix, std::vector< MatchingType > &matchings)
void computeEditDistance(const ftm::FTMTree_MT *tree1, const ftm::FTMTree_MT *tree2, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable, std::vector< std::vector< std::tuple< int, int > > > &treeBackTable, std::vector< std::vector< std::vector< std::tuple< int, int > > > > &forestBackTable, int nRows, int nCols)
void computeMatching(const ftm::FTMTree_MT *tree1, const ftm::FTMTree_MT *tree2, std::vector< std::vector< std::tuple< int, int > > > &treeBackTable, std::vector< std::vector< std::vector< std::tuple< int, int > > > > &forestBackTable, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &outputMatching, int startR, int startC)
void setPostprocess(bool postproc)
void computeSubtreeToEmptyDistance(const ftm::FTMTree_MT *tree1, ftm::idNode nodeI, int i, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable)
void printMapIntInt(std::map< int, int > theMap)
void setAuctionEpsilonDiviser(double aucEpsilonDiviser)
void parallelEmptyTreeDistance_v2(const ftm::FTMTree_MT *tree, bool isTree1, std::vector< ftm::idNode > &treeLeaves, std::vector< int > &treeNodeChildSize, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable, std::vector< std::vector< std::tuple< int, int > > > &treeBackTable, std::vector< std::vector< std::vector< std::tuple< int, int > > > > &forestBackTable)
void classicEditDistance(const ftm::FTMTree_MT *tree1, const ftm::FTMTree_MT *tree2, bool processTree1, bool computeEmptyTree, ftm::idNode nodeI, ftm::idNode nodeJ, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable, std::vector< std::vector< std::tuple< int, int > > > &treeBackTable, std::vector< std::vector< std::vector< std::tuple< int, int > > > > &forestBackTable, int nRows, int nCols)
void parallelTreeDistancePara(const ftm::FTMTree_MT *tree1, const ftm::FTMTree_MT *tree2, bool isTree1, int i, std::vector< ftm::idNode > &tree1Leaves, std::vector< int > &tree1NodeChildSize, std::vector< ftm::idNode > &tree2Leaves, std::vector< int > &tree2NodeChildSize, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable, std::vector< std::vector< std::tuple< int, int > > > &treeBackTable, std::vector< std::vector< std::vector< std::tuple< int, int > > > > &forestBackTable, bool firstCall, ftm::idNode nodeT, std::vector< int > &treeChildDone, std::vector< bool > &treeNodeDone, std::queue< ftm::idNode > &treeQueue)
void setSaveTree(bool save)
void computeForestToEmptyDistance(const ftm::FTMTree_MT *tree1, ftm::idNode nodeI, int i, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable)
void setAuctionEpsilon(double aucEpsilon)
void computeSubtreesDistance(const ftm::FTMTree_MT *tree1, const ftm::FTMTree_MT *tree2, int i, int j, ftm::idNode nodeI, ftm::idNode nodeJ, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable, std::vector< std::vector< std::tuple< int, int > > > &treeBackTable, std::vector< ftm::idNode > &children1, std::vector< ftm::idNode > &children2)
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)
dataType execute(ftm::MergeTree< dataType > &tree1, ftm::MergeTree< dataType > &tree2, std::vector< std::tuple< ftm::idNode, ftm::idNode > > &outputMatching)
void createCostMatrix(std::vector< std::vector< dataType > > &treeTable, std::vector< ftm::idNode > &children1, std::vector< ftm::idNode > &children2, std::vector< std::vector< dataType > > &costMatrix)
void verifyMergeTreeStructure(ftm::FTMTree_MT *tree)
dataType postprocessAssignment(std::vector< MatchingType > &matchings, std::vector< ftm::idNode > &children1, std::vector< ftm::idNode > &children2, std::vector< std::tuple< int, int > > &forestAssignment)
dataType computeDistance(const ftm::FTMTree_MT *tree1, const ftm::FTMTree_MT *tree2, std::vector< std::tuple< ftm::idNode, ftm::idNode > > &outputMatching)
dataType execute(ftm::MergeTree< dataType > &mTree1, ftm::MergeTree< dataType > &mTree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &outputMatching)
void computeEmptyToForestDistance(const ftm::FTMTree_MT *tree2, ftm::idNode nodeJ, int j, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable)
void computeEmptyToSubtreeDistance(const ftm::FTMTree_MT *tree2, ftm::idNode nodeJ, int j, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable)
void classicalPersistenceAssignmentProblem(ftm::FTMTree_MT *tree1, ftm::FTMTree_MT *tree2)
void parallelTreeDistanceTask(const ftm::FTMTree_MT *tree1, const ftm::FTMTree_MT *tree2, bool isTree1, int i, std::vector< ftm::idNode > &tree1Leaves, std::vector< int > &tree1NodeChildSize, std::vector< ftm::idNode > &tree2Leaves, std::vector< int > &tree2NodeChildSize, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable, std::vector< std::vector< std::tuple< int, int > > > &treeBackTable, std::vector< std::vector< std::vector< std::tuple< int, int > > > > &forestBackTable, ftm::idNode nodeT, std::vector< int > &treeChildDone, std::vector< bool > &treeNodeDone, std::queue< ftm::idNode > &treeQueue)
void parallelEmptyTreeDistanceTask(const ftm::FTMTree_MT *tree, bool isTree1, std::vector< ftm::idNode > &ttkNotUsed(treeLeaves), std::vector< int > &treeNodeChildSize, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable, std::vector< std::vector< std::tuple< int, int > > > &treeBackTable, std::vector< std::vector< std::vector< std::tuple< int, int > > > > &forestBackTable, ftm::idNode nodeT, std::vector< int > &treeChildDone, std::vector< bool > &treeNodeDone, std::queue< ftm::idNode > &treeQueue)
void computeForestsDistance(const ftm::FTMTree_MT *tree1, const ftm::FTMTree_MT *tree2, int i, int j, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable, std::vector< std::vector< std::vector< std::tuple< int, int > > > > &forestBackTable, std::vector< ftm::idNode > &children1, std::vector< ftm::idNode > &children2)
void parallelEditDistance(const ftm::FTMTree_MT *tree1, const ftm::FTMTree_MT *tree2, std::vector< std::vector< dataType > > &treeTable, std::vector< std::vector< dataType > > &forestTable, std::vector< std::vector< std::tuple< int, int > > > &treeBackTable, std::vector< std::vector< std::vector< std::tuple< int, int > > > > &forestBackTable, int ttkNotUsed(nRows), int ttkNotUsed(nCols))
void setAuctionNoRounds(double aucNoRounds)
~MergeTreeDistance() override=default
double getElapsedTime()
Definition Timer.h:15
std::stringstream printTree(bool doPrint=true) const
const scalarType & getValue(SimplexId nodeId) const
Definition FTMTree_MT.h:339
void getChildren(idNode nodeId, std::vector< idNode > &res) const
idNode getNumberOfNodes() const
Definition FTMTree_MT.h:389
idNode getRoot() const
std::stringstream printTreeScalars(bool printNodeAlone=true, bool doPrint=true) const
idNode getParentSafe(idNode nodeId) const
void getLevelToNode(std::vector< std::vector< idNode > > &res) const
void getAllNodeLevel(std::vector< int > &res) const
void getLeavesFromTree(std::vector< idNode > &res) const
bool isRoot(idNode nodeId) const
void getPersistencePairsFromTree(std::vector< std::tuple< ftm::idNode, ftm::idNode, dataType > > &pairs, bool useBD) const
MergeTree< dataType > copyMergeTree(const ftm::FTMTree_MT *tree, bool doSplitMultiPersPairs=false)
unsigned int idNode
Node index in vect_nodes_.
TTK base package defining the standard types.
ftm::FTMTree_MT tree
Definition FTMTree_MT.h:906
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)