44 int assignmentSolverID_ = 0;
45 bool squared_ =
false;
46 bool computeMapping_ =
false;
48 bool preprocess_ =
true;
49 bool saveTree_ =
false;
51 template <
class dataType>
52 inline dataType editCost_Persistence(
int n1,
60 dataType b1 = tree2->
getValue<dataType>(n2);
61 dataType d1 = tree2->
getValue<dataType>(p2);
62 d = (d1 > b1) ? (d1 - b1) : (b1 - d1);
64 dataType b1 = tree1->
getValue<dataType>(n1);
65 dataType d1 = tree1->
getValue<dataType>(p1);
66 d = (d1 > b1) ? (d1 - b1) : (b1 - d1);
68 dataType b1 = tree1->
getValue<dataType>(n1);
69 dataType d1 = tree1->
getValue<dataType>(p1);
70 dataType b2 = tree2->
getValue<dataType>(n2);
71 dataType d2 = tree2->
getValue<dataType>(p2);
72 dataType dist1 = (d1 > b1) ? (d1 - b1) : (b1 - d1);
73 dataType dist2 = (d2 > b2) ? (d2 - b2) : (b2 - d2);
74 d = (dist1 > dist2) ? (dist1 - dist2) : (dist2 - dist1);
76 return squared_ ? d * d : d;
79 template <
class dataType>
80 void traceMapping_path(
87 std::vector<std::vector<int>> &predecessors1,
88 std::vector<std::vector<int>> &predecessors2,
91 std::vector<dataType> &memT,
92 std::vector<std::pair<std::pair<ftm::idNode, ftm::idNode>,
93 std::pair<ftm::idNode, ftm::idNode>>> &mapping) {
97 std::vector<ftm::idNode> children1;
99 std::vector<ftm::idNode> children2;
101 int parent1 = predecessors1[curr1][predecessors1[curr1].size() - l1];
102 int parent2 = predecessors2[curr2][predecessors2[curr2].size() - l2];
106 size_t const dim1 = 1;
107 size_t const dim2 = (nn1 + 1) * dim1;
108 size_t const dim3 = (depth1 + 1) * dim2;
109 size_t const dim4 = (nn2 + 1) * dim3;
116 mapping.emplace_back(
117 std::make_pair(curr1, parent1), std::make_pair(curr2, parent2));
124 for(
auto child2_mb : children2) {
126 = memT[curr1 + l1 * dim2 + child2_mb * dim3 + (l2 + 1) * dim4];
127 for(
auto child2 : children2) {
128 if(child2 == child2_mb) {
131 d_ += memT[nn1 + 0 * dim2 + child2 * dim3 + 1 * dim4];
133 if(memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4] == d_) {
134 traceMapping_path(tree1, tree2, curr1, l1, child2_mb, l2 + 1,
135 predecessors1, predecessors2, depth1, depth2,
145 dataType d = std::numeric_limits<dataType>::max();
146 for(
auto child1_mb : children1) {
148 = memT[child1_mb + (l1 + 1) * dim2 + curr2 * dim3 + l2 * dim4];
149 for(
auto child1 : children1) {
150 if(child1 == child1_mb) {
153 d_ += memT[child1 + 1 * dim2 + nn2 * dim3 + 0 * dim4];
156 if(memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4] == d_) {
157 traceMapping_path(tree1, tree2, child1_mb, l1 + 1, curr2, l2,
158 predecessors1, predecessors2, depth1, depth2,
174 int child11 = children1[0];
175 int child12 = children1[1];
176 int child21 = children2[0];
177 int child22 = children2[1];
178 if(memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4]
179 == memT[child11 + 1 * dim2 + child21 * dim3 + 1 * dim4]
180 + memT[child12 + 1 * dim2 + child22 * dim3 + 1 * dim4]
181 + editCost_Persistence<dataType>(
182 curr1, parent1, curr2, parent2, tree1, tree2)) {
183 mapping.emplace_back(
184 std::make_pair(curr1, parent1), std::make_pair(curr2, parent2));
185 traceMapping_path(tree1, tree2, child11, 1, child21, 1,
186 predecessors1, predecessors2, depth1, depth2,
188 traceMapping_path(tree1, tree2, child12, 1, child22, 1,
189 predecessors1, predecessors2, depth1, depth2,
193 if(memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4]
194 == memT[child11 + 1 * dim2 + child22 * dim3 + 1 * dim4]
195 + memT[child12 + 1 * dim2 + child21 * dim3 + 1 * dim4]
196 + editCost_Persistence<dataType>(
197 curr1, parent1, curr2, parent2, tree1, tree2)) {
198 mapping.emplace_back(
199 std::make_pair(curr1, parent1), std::make_pair(curr2, parent2));
200 traceMapping_path(tree1, tree2, child11, 1, child22, 1,
201 predecessors1, predecessors2, depth1, depth2,
203 traceMapping_path(tree1, tree2, child12, 1, child21, 1,
204 predecessors1, predecessors2, depth1, depth2,
209 auto f = [&](
int r,
int c) {
214 int const l1_ = c1 == nn1 ? 0 : 1;
215 int const l2_ = c2 == nn2 ? 0 : 1;
216 return memT[c1 + l1_ * dim2 + c2 * dim3 + l2_ * dim4];
221 auto costMatrix = std::vector<std::vector<dataType>>(
222 size, std::vector<dataType>(size, 0));
223 std::vector<MatchingType> matching;
224 for(
int r = 0; r < size; r++) {
225 for(
int c = 0; c < size; c++) {
226 costMatrix[r][c] = f(r, c);
234 switch(assignmentSolverID_) {
237 assignmentSolver = &solverExhaustive;
241 assignmentSolver = &solverMunkres;
246 assignmentSolver = &solverAuction;
248 assignmentSolver->
setInput(costMatrix);
250 assignmentSolver->
run(matching);
251 dataType d_ = editCost_Persistence<dataType>(
252 curr1, parent1, curr2, parent2, tree1, tree2);
253 for(
auto m : matching)
254 d_ += std::get<2>(m);
255 if(memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4] == d_) {
256 mapping.emplace_back(
257 std::make_pair(curr1, parent1), std::make_pair(curr2, parent2));
258 for(
auto m : matching) {
260 ? children1[std::get<0>(m)]
263 ? children2[std::get<1>(m)]
265 if(n1 >= 0 && n2 >= 0)
266 traceMapping_path(tree1, tree2, n1, 1, n2, 1, predecessors1,
267 predecessors2, depth1, depth2, memT, mapping);
276 for(
auto child1_mb : children1) {
278 = memT[child1_mb + (l1 + 1) * dim2 + curr2 * dim3 + l2 * dim4];
279 for(
auto child1 : children1) {
280 if(child1 == child1_mb) {
283 d_ += memT[child1 + 1 * dim2 + nn2 * dim3 + 0 * dim4];
285 if(memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4] == d_) {
286 traceMapping_path(tree1, tree2, child1_mb, l1 + 1, curr2, l2,
287 predecessors1, predecessors2, depth1, depth2,
296 for(
auto child2_mb : children2) {
298 = memT[curr1 + l1 * dim2 + child2_mb * dim3 + (l2 + 1) * dim4];
299 for(
auto child2 : children2) {
300 if(child2 == child2_mb) {
303 d_ += memT[nn1 + 0 * dim2 + child2 * dim3 + 1 * dim4];
305 if(memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4] == d_) {
306 traceMapping_path(tree1, tree2, curr1, l1, child2_mb, l2 + 1,
307 predecessors1, predecessors2, depth1, depth2,
318 "MergeTreeDistance");
328 assignmentSolverID_ = assignmentSolver;
347 template <
class dataType>
351 std::vector<std::pair<std::pair<ftm::idNode, ftm::idNode>,
352 std::pair<ftm::idNode, ftm::idNode>>>
360 int const rootID1 = tree1->
getRoot();
361 int const rootID2 = tree2->
getRoot();
367 std::stack<int> stack;
370 while(!stack.empty()) {
371 int const nIdx = stack.top();
373 preorder1[count] = nIdx;
375 depth1 = std::max((
int)predecessors1[nIdx].size(), depth1);
376 std::vector<ftm::idNode> children;
378 for(
int const cIdx : children) {
380 predecessors1[cIdx].reserve(predecessors1[nIdx].size() + 1);
381 predecessors1[cIdx].insert(predecessors1[cIdx].
end(),
382 predecessors1[nIdx].
begin(),
383 predecessors1[nIdx].
end());
384 predecessors1[cIdx].push_back(nIdx);
389 while(!stack.empty()) {
390 int const nIdx = stack.top();
392 preorder2[count] = nIdx;
394 depth2 = std::max((
int)predecessors2[nIdx].size(), depth2);
395 std::vector<ftm::idNode> children;
397 for(
int const cIdx : children) {
399 predecessors2[cIdx].reserve(predecessors2[nIdx].size() + 1);
400 predecessors2[cIdx].insert(predecessors2[cIdx].
end(),
401 predecessors2[nIdx].
begin(),
402 predecessors2[nIdx].
end());
403 predecessors2[cIdx].push_back(nIdx);
411 size_t const dim1 = 1;
412 size_t const dim2 = (nn1 + 1) * dim1;
413 size_t const dim3 = (depth1 + 1) * dim2;
414 size_t const dim4 = (nn2 + 1) * dim3;
418 std::vector<dataType> memT((nn1 + 1) * (depth1 + 1) * (nn2 + 1)
421 memT[nn1 + 0 * dim2 + nn2 * dim3 + 0 * dim4] = 0;
422 for(
size_t i = 0; i < nn1; i++) {
423 int curr1 = preorder1[i];
424 std::vector<ftm::idNode> children1;
426 for(
size_t l = 1; l <= predecessors1[preorder1[i]].size(); l++) {
427 int parent1 = predecessors1[preorder1[i]]
428 [predecessors1[preorder1[i]].size() - l];
432 memT[curr1 + l * dim2 + nn2 * dim3 + 0 * dim4]
433 = editCost_Persistence<dataType>(
434 curr1, parent1, -1, -1, tree1, tree2);
435 for(
auto child1 : children1) {
436 memT[curr1 + l * dim2 + nn2 * dim3 + 0 * dim4]
437 += memT[child1 + 1 * dim2 + nn2 * dim3 + 0 * dim4];
441 for(
size_t j = 0; j < nn2; j++) {
442 int curr2 = preorder2[j];
443 std::vector<ftm::idNode> children2;
445 for(
size_t l = 1; l <= predecessors2[preorder2[j]].size(); l++) {
446 int parent2 = predecessors2[preorder2[j]]
447 [predecessors2[preorder2[j]].size() - l];
451 memT[nn1 + 0 * dim2 + curr2 * dim3 + l * dim4]
452 = editCost_Persistence<dataType>(
453 -1, -1, curr2, parent2, tree1, tree2);
454 for(
auto child2 : children2) {
455 memT[nn1 + 0 * dim2 + curr2 * dim3 + l * dim4]
456 += memT[nn1 + 0 * dim2 + child2 * dim3 + 1 * dim4];
461 for(
size_t i = 0; i < nn1; i++) {
462 int curr1 = preorder1[i];
463 std::vector<ftm::idNode> children1;
465 for(
size_t j = 0; j < nn2; j++) {
466 int curr2 = preorder2[j];
467 std::vector<ftm::idNode> children2;
469 for(
size_t l1 = 1; l1 <= predecessors1[preorder1[i]].size(); l1++) {
471 = predecessors1[preorder1[i]]
472 [predecessors1[preorder1[i]].size() - l1];
473 for(
size_t l2 = 1; l2 <= predecessors2[preorder2[j]].size(); l2++) {
475 = predecessors2[preorder2[j]]
476 [predecessors2[preorder2[j]].size() - l2];
486 memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4]
487 = editCost_Persistence<dataType>(
488 curr1, parent1, curr2, parent2, tree1, tree2);
494 dataType d = std::numeric_limits<dataType>::max();
495 for(
auto child2_mb : children2) {
496 dataType d_ = memT[curr1 + l1 * dim2 + child2_mb * dim3
498 for(
auto child2 : children2) {
499 if(child2 == child2_mb) {
502 d_ += memT[nn1 + 0 * dim2 + child2 * dim3 + 1 * dim4];
506 memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4] = d;
512 dataType d = std::numeric_limits<dataType>::max();
513 for(
auto child1_mb : children1) {
514 dataType d_ = memT[child1_mb + (l1 + 1) * dim2 + curr2 * dim3
516 for(
auto child1 : children1) {
517 if(child1 == child1_mb) {
520 d_ += memT[child1 + 1 * dim2 + nn2 * dim3 + 0 * dim4];
524 memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4] = d;
530 dataType d = std::numeric_limits<dataType>::max();
537 int const child11 = children1[0];
538 int const child12 = children1[1];
539 int const child21 = children2[0];
540 int const child22 = children2[1];
541 d = std::min<dataType>(
542 d, memT[child11 + 1 * dim2 + child21 * dim3 + 1 * dim4]
543 + memT[child12 + 1 * dim2 + child22 * dim3 + 1 * dim4]
544 + editCost_Persistence<dataType>(
545 curr1, parent1, curr2, parent2, tree1, tree2));
546 d = std::min<dataType>(
547 d, memT[child11 + 1 * dim2 + child22 * dim3 + 1 * dim4]
548 + memT[child12 + 1 * dim2 + child21 * dim3 + 1 * dim4]
549 + editCost_Persistence<dataType>(
550 curr1, parent1, curr2, parent2, tree1, tree2));
552 auto f = [&](
int r,
int c) {
559 int const l1_ = c1 == nn1 ? 0 : 1;
560 int const l2_ = c2 == nn2 ? 0 : 1;
561 return memT[c1 + l1_ * dim2 + c2 * dim3 + l2_ * dim4];
566 auto costMatrix = std::vector<std::vector<dataType>>(
567 size, std::vector<dataType>(size, 0));
568 std::vector<MatchingType> matching;
569 for(
int r = 0; r < size; r++) {
570 for(
int c = 0; c < size; c++) {
571 costMatrix[r][c] = f(r, c);
579 switch(assignmentSolverID_) {
582 assignmentSolver = &solverExhaustive;
586 assignmentSolver = &solverMunkres;
591 assignmentSolver = &solverAuction;
593 assignmentSolver->
setInput(costMatrix);
595 assignmentSolver->
run(matching);
596 dataType d_ = editCost_Persistence<dataType>(
597 curr1, parent1, curr2, parent2, tree1, tree2);
598 for(
auto m : matching)
599 d_ += std::get<2>(m);
606 for(
auto child1_mb : children1) {
607 dataType d_ = memT[child1_mb + (l1 + 1) * dim2 + curr2 * dim3
609 for(
auto child1 : children1) {
610 if(child1 == child1_mb) {
613 d_ += memT[child1 + 1 * dim2 + nn2 * dim3 + 0 * dim4];
621 for(
auto child2_mb : children2) {
622 dataType d_ = memT[curr1 + l1 * dim2 + child2_mb * dim3
624 for(
auto child2 : children2) {
625 if(child2 == child2_mb) {
628 d_ += memT[nn1 + 0 * dim2 + child2 * dim3 + 1 * dim4];
632 memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4] = d;
639 std::vector<ftm::idNode> children1;
641 std::vector<ftm::idNode> children2;
645 = memT[children1[0] + 1 * dim2 + children2[0] * dim3 + 1 * dim4];
647 if(computeMapping_ && outputMatching) {
649 outputMatching->clear();
650 traceMapping_path(tree1, tree2, children1[0], 1, children2[0], 1,
651 predecessors1, predecessors2, depth1, depth2, memT,
655 return squared_ ? std::sqrt(res) : res;
658 template <
class dataType>
661 std::vector<std::pair<std::pair<ftm::idNode, ftm::idNode>,
662 std::pair<ftm::idNode, ftm::idNode>>>
689 tree1 = &(mTree1Int.
tree);
690 tree2 = &(mTree2Int.
tree);
695 template <
class dataType>
699 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
704 std::vector<std::pair<std::pair<ftm::idNode, ftm::idNode>,
705 std::pair<ftm::idNode, ftm::idNode>>>
708 if(computeMapping_ && outputMatching) {
709 outputMatching->clear();
710 for(
auto m : mapping) {
711 matchedNodes[m.first.first] = m.second.first;
712 matchedNodes[m.first.second] = m.second.second;
713 matchedCost[m.first.first] = editCost_Persistence<dataType>(
714 m.first.first, m.first.second, m.second.first, m.second.second,
716 if(m.first.second == tree1->
getRoot()) {
717 matchedCost[m.first.second] = matchedCost[m.first.first];
720 for(
ftm::idNode i = 0; i < matchedNodes.size(); i++) {
721 if(matchedNodes[i] >= 0) {
722 outputMatching->emplace_back(
723 std::make_tuple(i, matchedNodes[i], matchedCost[i]));
731 template <
class dataType>
735 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> *outputMatching,
736 std::vector<std::pair<std::pair<ftm::idNode, ftm::idNode>,
737 std::pair<ftm::idNode, ftm::idNode>>>
738 *outputMatching_path) {
744 if(computeMapping_ && outputMatching) {
745 outputMatching->clear();
746 for(
auto m : *outputMatching_path) {
747 matchedNodes[m.first.first] = m.second.first;
748 matchedNodes[m.first.second] = m.second.second;
749 matchedCost[m.first.first] = editCost_Persistence<dataType>(
750 m.first.first, m.first.second, m.second.first, m.second.second,
752 if(m.first.second == tree1->
getRoot()) {
753 matchedCost[m.first.second] = matchedCost[m.first.first];
756 for(
ftm::idNode i = 0; i < matchedNodes.size(); i++) {
757 if(matchedNodes[i] >= 0) {
758 outputMatching->emplace_back(
759 std::make_tuple(i, matchedNodes[i], matchedCost[i]));
767 template <
class dataType>
770 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
795 tree1 = &(mTree1Int.
tree);
796 tree2 = &(mTree2Int.
tree);
801 template <
class dataType>
805 (std::vector<std::pair<std::pair<ftm::idNode, ftm::idNode>,
806 std::pair<ftm::idNode, ftm::idNode>>> *)
nullptr);
809 template <
class dataType>
835 tree1 = &(mTree1Int.
tree);
836 tree2 = &(mTree2Int.
tree);
840 (std::vector<std::pair<std::pair<ftm::idNode, ftm::idNode>,
841 std::pair<ftm::idNode, ftm::idNode>>> *)
nullptr);