204 int const rootID1 = tree1->
getRoot();
205 int const rootID2 = tree2->
getRoot();
211 std::stack<int> stack;
214 while(!stack.empty()) {
215 int const nIdx = stack.top();
217 preorder1[count] = nIdx;
219 depth1 = std::max((
int)predecessors1[nIdx].size(), depth1);
220 std::vector<ftm::idNode> children;
222 for(
int const cIdx : children) {
224 predecessors1[cIdx].reserve(predecessors1[nIdx].size() + 1);
225 predecessors1[cIdx].insert(predecessors1[cIdx].
end(),
226 predecessors1[nIdx].begin(),
227 predecessors1[nIdx].end());
228 predecessors1[cIdx].push_back(nIdx);
233 while(!stack.empty()) {
234 int const nIdx = stack.top();
236 preorder2[count] = nIdx;
238 depth2 = std::max((
int)predecessors2[nIdx].size(), depth2);
239 std::vector<ftm::idNode> children;
241 for(
int const cIdx : children) {
243 predecessors2[cIdx].reserve(predecessors2[nIdx].size() + 1);
244 predecessors2[cIdx].insert(predecessors2[cIdx].
end(),
245 predecessors2[nIdx].begin(),
246 predecessors2[nIdx].end());
247 predecessors2[cIdx].push_back(nIdx);
253 size_t const dim1 = 1;
254 size_t const dim2 = (nn1 + 1) * dim1;
255 size_t const dim3 = (depth1 + 1) * dim2;
256 size_t const dim4 = (nn2 + 1) * dim3;
258 std::vector<dataType> memT((nn1 + 1) * (depth1 + 1) * (nn2 + 1)
261 memT[nn1 + 0 * dim2 + nn2 * dim3 + 0 * dim4] = 0;
262 for(
size_t i = 0; i < nn1; i++) {
263 int curr1 = preorder1[i];
264 std::vector<ftm::idNode> children1;
266 for(
size_t l = 1; l <= predecessors1[preorder1[i]].size(); l++) {
267 int parent1 = predecessors1[preorder1[i]]
268 [predecessors1[preorder1[i]].size() - l];
274 memT[curr1 + l * dim2 + nn2 * dim3 + 0 * dim4]
275 = this->baseMetric_ == 0 ? editCost_Wasserstein1<dataType>(
276 curr1, parent1, -1, -1, tree1, tree2)
277 : this->baseMetric_ == 1 ? editCost_Wasserstein2<dataType>(
278 curr1, parent1, -1, -1, tree1, tree2)
279 : this->baseMetric_ == 2
280 ? editCost_Persistence<dataType>(
281 curr1, parent1, -1, -1, tree1, tree2)
282 : editCost_Shifting<dataType>(
283 curr1, parent1, -1, -1, tree1, tree2);
288 dataType c = std::numeric_limits<dataType>::max();
289 for(
auto child1_mb : children1) {
291 = memT[child1_mb + (l + 1) * dim2 + nn2 * dim3 + 0 * dim4];
292 for(
auto child1 : children1) {
293 if(child1 == child1_mb) {
296 c_ += memT[child1 + 1 * dim2 + nn2 * dim3 + 0 * dim4];
300 memT[curr1 + l * dim2 + nn2 * dim3 + 0 * dim4] = c;
304 for(
size_t j = 0; j < nn2; j++) {
305 int curr2 = preorder2[j];
306 std::vector<ftm::idNode> children2;
308 for(
size_t l = 1; l <= predecessors2[preorder2[j]].size(); l++) {
309 int parent2 = predecessors2[preorder2[j]]
310 [predecessors2[preorder2[j]].size() - l];
316 memT[nn1 + 0 * dim2 + curr2 * dim3 + l * dim4]
317 = this->baseMetric_ == 0 ? editCost_Wasserstein1<dataType>(
318 -1, -1, curr2, parent2, tree1, tree2)
319 : this->baseMetric_ == 1 ? editCost_Wasserstein2<dataType>(
320 -1, -1, curr2, parent2, tree1, tree2)
321 : this->baseMetric_ == 2
322 ? editCost_Persistence<dataType>(
323 -1, -1, curr2, parent2, tree1, tree2)
324 : editCost_Shifting<dataType>(
325 -1, -1, curr2, parent2, tree1, tree2);
330 dataType c = std::numeric_limits<dataType>::max();
331 for(
auto child2_mb : children2) {
333 = memT[nn1 + 0 * dim2 + child2_mb * dim3 + (l + 1) * dim4];
334 for(
auto child2 : children2) {
335 if(child2 == child2_mb) {
338 c_ += memT[nn1 + 0 * dim2 + child2 * dim3 + 1 * dim4];
342 memT[nn1 + 0 * dim2 + curr2 * dim3 + l * dim4] = c;
347 for(
size_t i = 0; i < nn1; i++) {
348 int curr1 = preorder1[i];
349 std::vector<ftm::idNode> children1;
351 for(
size_t j = 0; j < nn2; j++) {
352 int curr2 = preorder2[j];
353 std::vector<ftm::idNode> children2;
355 for(
size_t l1 = 1; l1 <= predecessors1[preorder1[i]].size(); l1++) {
357 = predecessors1[preorder1[i]]
358 [predecessors1[preorder1[i]].size() - l1];
359 for(
size_t l2 = 1; l2 <= predecessors2[preorder2[j]].size(); l2++) {
361 = predecessors2[preorder2[j]]
362 [predecessors2[preorder2[j]].size() - l2];
372 memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4]
373 = this->baseMetric_ == 0 ? editCost_Wasserstein1<dataType>(
374 curr1, parent1, curr2, parent2, tree1, tree2)
375 : this->baseMetric_ == 1 ? editCost_Wasserstein2<dataType>(
376 curr1, parent1, curr2, parent2, tree1, tree2)
377 : this->baseMetric_ == 2
378 ? editCost_Persistence<dataType>(
379 curr1, parent1, curr2, parent2, tree1, tree2)
380 : editCost_Shifting<dataType>(
381 curr1, parent1, curr2, parent2, tree1, tree2);
386 else if(children1.size() == 0) {
387 dataType d = std::numeric_limits<dataType>::max();
388 for(
auto child2_mb : children2) {
389 dataType d_ = memT[curr1 + l1 * dim2 + child2_mb * dim3
391 for(
auto child2 : children2) {
392 if(child2 == child2_mb) {
395 d_ += memT[nn1 + 0 * dim2 + child2 * dim3 + 1 * dim4];
399 memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4] = d;
404 else if(children2.size() == 0) {
405 dataType d = std::numeric_limits<dataType>::max();
406 for(
auto child1_mb : children1) {
407 dataType d_ = memT[child1_mb + (l1 + 1) * dim2 + curr2 * dim3
409 for(
auto child1 : children1) {
410 if(child1 == child1_mb) {
413 d_ += memT[child1 + 1 * dim2 + nn2 * dim3 + 0 * dim4];
417 memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4] = d;
423 dataType d = std::numeric_limits<dataType>::max();
428 if(children1.size() == 2 && children2.size() == 2) {
429 int const child11 = children1[0];
430 int const child12 = children1[1];
431 int const child21 = children2[0];
432 int const child22 = children2[1];
433 d = std::min<dataType>(
435 memT[child11 + (l1 + 1) * dim2 + child21 * dim3
437 + memT[child12 + 1 * dim2 + child22 * dim3 + 1 * dim4]);
438 d = std::min<dataType>(
440 memT[child12 + (l1 + 1) * dim2 + child22 * dim3
442 + memT[child11 + 1 * dim2 + child21 * dim3 + 1 * dim4]);
443 d = std::min<dataType>(
445 memT[child11 + (l1 + 1) * dim2 + child22 * dim3
447 + memT[child12 + 1 * dim2 + child21 * dim3 + 1 * dim4]);
448 d = std::min<dataType>(
450 memT[child12 + (l1 + 1) * dim2 + child21 * dim3
452 + memT[child11 + 1 * dim2 + child22 * dim3 + 1 * dim4]);
454 for(
auto child1_mb : children1) {
455 auto topo1_ = children1;
457 std::remove(topo1_.begin(), topo1_.end(), child1_mb),
459 for(
auto child2_mb : children2) {
460 auto topo2_ = children2;
462 std::remove(topo2_.begin(), topo2_.end(), child2_mb),
465 auto f = [&](
unsigned r,
unsigned c) {
466 int const c1 = r < topo1_.size() ? topo1_[r] : -1;
467 int const c2 = c < topo2_.size() ? topo2_[c] : -1;
468 return memT[c1 + 1 * dim2 + c2 * dim3 + 1 * dim4];
470 int size = std::max(topo1_.size(), topo2_.size()) + 1;
471 auto costMatrix = std::vector<std::vector<dataType>>(
472 size, std::vector<dataType>(size, 0));
473 std::vector<MatchingType> matching;
474 for(
int r = 0; r < size; r++) {
475 for(
int c = 0; c < size; c++) {
476 costMatrix[r][c] = f(r, c);
484 switch(assignmentSolverID_) {
487 assignmentSolver = &solverExhaustive;
491 assignmentSolver = &solverMunkres;
496 assignmentSolver = &solverAuction;
498 assignmentSolver->
setInput(costMatrix);
500 assignmentSolver->
run(matching);
501 dataType d_ = memT[child1_mb + (l1 + 1) * dim2
502 + child2_mb * dim3 + (l2 + 1) * dim4];
503 for(
auto m : matching)
504 d_ += std::get<2>(m);
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];
528 for(
auto child2_mb : children2) {
529 dataType d_ = memT[curr1 + l1 * dim2 + child2_mb * dim3
531 for(
auto child2 : children2) {
532 if(child2 == child2_mb) {
535 d_ += memT[nn1 + 0 * dim2 + child2 * dim3 + 1 * dim4];
539 memT[curr1 + l1 * dim2 + curr2 * dim3 + l2 * dim4] = d;
546 std::vector<ftm::idNode> children1;
548 std::vector<ftm::idNode> children2;
552 = memT[children1[0] + 1 * dim2 + children2[0] * dim3 + 1 * dim4];
554 return squared_ ? std::sqrt(res) : res;