// File: canzarlab[P]Trajan/src/match.cpp
// Function: main
int main(int argc, char** argv)
{
    if (argc != 6)
    {
        cout << "usage: " << argv[0] << " <tree1> <map1> <tree2> <map2> <matrix>\n";
        return 0;
    }
    // load the data
    tree t1(argv[1], argv[2]);
    tree t2(argv[3], argv[4]);
    vector<vector<double>> cost_matrix = CSVReader(argv[5]).getDoubleData();

    // last row/column is deletion cost
    array2d minmatrix(t1.n + 1, t2.n + 1);

    // convert scores to integers
    const double scale = 1000;
    for (int i = 0; i < t1.n + 1; ++i)
        for (int j = 0; j < t2.n + 1; ++j)
            minmatrix(i, j) = scale * cost_matrix[i][j];

    // convert into maximization problem
    array2d maxmatrix(t1.n, t2.n);
    for (int i = 0; i < t1.n; ++i)
        for (int j = 0; j < t2.n; ++j)
            maxmatrix(i, j) = minmatrix(i, t2.n) + minmatrix(t1.n, j) - minmatrix(i, j);

    // minimization score of empty matching
    int null_score = 0;
    for (int i = 0; i < t1.n; ++i)
        null_score += minmatrix(i, t2.n);
    for (int i = 0; i < t2.n; ++i)
        null_score += minmatrix(t1.n, i);

    // compute optimal tree to tree matching
    // note: first node in topological ordering is the root
    int weight = forest_forest(t1, t2, maxmatrix, 1, 1);

    // recover the matching
    vector<pair<int, int>> matching;
    recover_matching(t1, t2, matching, 1, 1);

    // weight of recovered matching (for sanity check)
    int mweight = 0;
    for (auto [x, y] : matching)
        mweight += maxmatrix(x, y);

    // convert to minimization score
    weight = null_score - weight;
    mweight = null_score - mweight;

    // verify the matching
    assert(verify(t1, t2, matching));
    assert(weight == mweight);

    // scale back the score
    clog << weight / scale << endl;

    // print the matching
    for (auto [x, y] : matching)
        cout << t1.rm[x] << ' ' << t2.rm[y] << '\n';
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10920, %rsp          # imm = 0x10920
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x6, -0x8(%rbp)
je 0x6e4c
movq 0x271ba(%rip), %rdi     # 0x2dfd0
leaq 0x1724f(%rip), %rsi     # 0x1e06c
callq 0x42c0
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rsi
callq 0x42c0
movq %rax, %rdi
leaq 0x17239(%rip), %rsi     # 0x1e074
callq 0x42c0
movl $0x0, -0x4(%rbp)
jmp 0x7745
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
movq 0x10(%rax), %rdx
leaq -0x8368(%rbp), %rdi
callq 0x87d0
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rsi
movq 0x20(%rax), %rdx
leaq -0x106c0(%rbp), %rdi
callq 0x87d0
jmp 0x6e7e
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x10870(%rbp)
leaq -0x10749(%rbp), %rdi
movq %rdi, -0x10868(%rbp)
callq 0x44f0
movq -0x10870(%rbp), %rsi
movq -0x10868(%rbp), %rdx
leaq -0x10748(%rbp), %rdi
callq 0x91e0
jmp 0x6ebc
leaq -0x10771(%rbp), %rdi
movq %rdi, -0x10878(%rbp)
callq 0x44f0
movq -0x10878(%rbp), %rdx
leaq 0x171c0(%rip), %rsi     # 0x1e09d
leaq -0x10770(%rbp), %rdi
callq 0x91e0
jmp 0x6eeb
leaq -0x10728(%rbp), %rdi
leaq -0x10748(%rbp), %rsi
leaq -0x10770(%rbp), %rdx
callq 0x9290
jmp 0x6f07
leaq -0x106e8(%rbp), %rdi
leaq -0x10728(%rbp), %rsi
xorl %edx, %edx
movl $0x2710, %ecx           # imm = 0x2710
callq 0x154f0
jmp 0x6f23
leaq -0x10728(%rbp), %rdi
callq 0x92f0
leaq -0x10770(%rbp), %rdi
callq 0x41e0
leaq -0x10771(%rbp), %rdi
callq 0x4330
leaq -0x10748(%rbp), %rdi
callq 0x41e0
leaq -0x10749(%rbp), %rdi
callq 0x4330
movl -0x2560(%rbp), %esi
incl %esi
movl -0xa8b8(%rbp), %edx
incl %edx
leaq -0x10798(%rbp), %rdi
movl $0x80000000, %ecx       # imm = 0x80000000
callq 0x7b70
jmp 0x6f82
movsd 0x1707e(%rip), %xmm0    # 0x1e008
movsd %xmm0, -0x107a0(%rbp)
movl $0x0, -0x107a4(%rbp)
movl -0x107a4(%rbp), %eax
movl -0x2560(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jge 0x713e
movl $0x0, -0x107a8(%rbp)
movl -0x107a8(%rbp), %eax
movl -0xa8b8(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jge 0x7128
movslq -0x107a4(%rbp), %rsi
leaq -0x106e8(%rbp), %rdi
callq 0x9320
movq %rax, %rdi
movslq -0x107a8(%rbp), %rsi
callq 0x9340
movsd (%rax), %xmm0
movsd 0x17006(%rip), %xmm1    # 0x1e008
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x10884(%rbp)
movl -0x107a4(%rbp), %esi
movl -0x107a8(%rbp), %edx
leaq -0x10798(%rbp), %rdi
callq 0x7820
movq %rax, -0x10880(%rbp)
jmp 0x7031
movq -0x10880(%rbp), %rax
movl -0x10884(%rbp), %ecx
movl %ecx, (%rax)
movl -0x107a8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x107a8(%rbp)
jmp 0x6fbd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x106c8(%rbp)
movl %eax, -0x106cc(%rbp)
jmp 0x7781
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x106c8(%rbp)
movl %eax, -0x106cc(%rbp)
jmp 0x70e9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x106c8(%rbp)
movl %eax, -0x106cc(%rbp)
jmp 0x70d1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x106c8(%rbp)
movl %eax, -0x106cc(%rbp)
jmp 0x70c5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x106c8(%rbp)
movl %eax, -0x106cc(%rbp)
leaq -0x10728(%rbp), %rdi
callq 0x92f0
leaq -0x10770(%rbp), %rdi
callq 0x41e0
leaq -0x10771(%rbp), %rdi
callq 0x4330
leaq -0x10748(%rbp), %rdi
callq 0x41e0
leaq -0x10749(%rbp), %rdi
callq 0x4330
jmp 0x7775
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x106c8(%rbp)
movl %eax, -0x106cc(%rbp)
jmp 0x7769
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x106c8(%rbp)
movl %eax, -0x106cc(%rbp)
jmp 0x775d
jmp 0x712a
movl -0x107a4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x107a4(%rbp)
jmp 0x6f9c
movl -0x2560(%rbp), %esi
movl -0xa8b8(%rbp), %edx
leaq -0x107c8(%rbp), %rdi
movl $0x80000000, %ecx       # imm = 0x80000000
callq 0x7b70
jmp 0x715d
movl $0x0, -0x107cc(%rbp)
movl -0x107cc(%rbp), %eax
cmpl -0x2560(%rbp), %eax
jge 0x72a6
movl $0x0, -0x107d0(%rbp)
movl -0x107d0(%rbp), %eax
cmpl -0xa8b8(%rbp), %eax
jge 0x7290
movl -0x107cc(%rbp), %esi
movl -0xa8b8(%rbp), %edx
leaq -0x10798(%rbp), %rdi
callq 0x7820
movq %rax, -0x10890(%rbp)
jmp 0x71b6
movq -0x10890(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x1089c(%rbp)
movl -0x2560(%rbp), %esi
movl -0x107d0(%rbp), %edx
leaq -0x10798(%rbp), %rdi
callq 0x7820
movq %rax, -0x10898(%rbp)
jmp 0x71e6
movl -0x1089c(%rbp), %eax
movq -0x10898(%rbp), %rcx
movl (%rcx), %ecx
addl %ecx, %eax
movl %eax, -0x108ac(%rbp)
movl -0x107cc(%rbp), %esi
movl -0x107d0(%rbp), %edx
leaq -0x10798(%rbp), %rdi
callq 0x7820
movq %rax, -0x108a8(%rbp)
jmp 0x721e
movl -0x108ac(%rbp), %eax
movq -0x108a8(%rbp), %rcx
movl (%rcx), %ecx
subl %ecx, %eax
movl %eax, -0x108bc(%rbp)
movl -0x107cc(%rbp), %esi
movl -0x107d0(%rbp), %edx
leaq -0x107c8(%rbp), %rdi
callq 0x7820
movq %rax, -0x108b8(%rbp)
jmp 0x7256
movq -0x108b8(%rbp), %rax
movl -0x108bc(%rbp), %ecx
movl %ecx, (%rax)
movl -0x107d0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x107d0(%rbp)
jmp 0x7183
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x106c8(%rbp)
movl %eax, -0x106cc(%rbp)
jmp 0x7751
jmp 0x7292
movl -0x107cc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x107cc(%rbp)
jmp 0x7167
movl $0x0, -0x107d4(%rbp)
movl $0x0, -0x107d8(%rbp)
movl -0x107d8(%rbp), %eax
cmpl -0x2560(%rbp), %eax
jge 0x730f
movl -0x107d8(%rbp), %esi
movl -0xa8b8(%rbp), %edx
leaq -0x10798(%rbp), %rdi
callq 0x7820
movq %rax, -0x108c8(%rbp)
jmp 0x72e9
movq -0x108c8(%rbp), %rax
movl (%rax), %eax
addl -0x107d4(%rbp), %eax
movl %eax, -0x107d4(%rbp)
movl -0x107d8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x107d8(%rbp)
jmp 0x72ba
movl $0x0, -0x107dc(%rbp)
movl -0x107dc(%rbp), %eax
cmpl -0xa8b8(%rbp), %eax
jge 0x736e
movl -0x2560(%rbp), %esi
movl -0x107dc(%rbp), %edx
leaq -0x10798(%rbp), %rdi
callq 0x7820
movq %rax, -0x108d0(%rbp)
jmp 0x7348
movq -0x108d0(%rbp), %rax
movl (%rax), %eax
addl -0x107d4(%rbp), %eax
movl %eax, -0x107d4(%rbp)
movl -0x107dc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x107dc(%rbp)
jmp 0x7319
leaq -0x8368(%rbp), %rdi
leaq -0x106c0(%rbp), %rsi
leaq -0x107c8(%rbp), %rdx
movl $0x1, %r8d
movq %r8, %rcx
callq 0x50f0
movl %eax, -0x108d4(%rbp)
jmp 0x7399
movl -0x108d4(%rbp), %eax
movl %eax, -0x107e0(%rbp)
leaq -0x107f8(%rbp), %rdi
movq %rdi, -0x108e0(%rbp)
callq 0x9360
movq -0x108e0(%rbp), %rdx
leaq -0x8368(%rbp), %rdi
leaq -0x106c0(%rbp), %rsi
movl $0x1, %r8d
movq %r8, %rcx
callq 0x60f0
jmp 0x73dd
movl $0x0, -0x107fc(%rbp)
leaq -0x107f8(%rbp), %rax
movq %rax, -0x10808(%rbp)
movq -0x10808(%rbp), %rdi
callq 0x9380
movq %rax, -0x10810(%rbp)
movq -0x10808(%rbp), %rdi
callq 0x93b0
movq %rax, -0x10818(%rbp)
leaq -0x10810(%rbp), %rdi
leaq -0x10818(%rbp), %rsi
callq 0x93e0
testb $0x1, %al
jne 0x7437
jmp 0x74ea
leaq -0x10810(%rbp), %rdi
callq 0x9420
movq (%rax), %rax
movq %rax, -0x10820(%rbp)
leaq -0x10820(%rbp), %rdi
movq %rdi, -0x108f0(%rbp)
callq 0x8770
movq -0x108f0(%rbp), %rdi
movq %rax, -0x10828(%rbp)
callq 0x8790
movq %rax, -0x10830(%rbp)
movq -0x10828(%rbp), %rax
movl (%rax), %esi
movq -0x10830(%rbp), %rax
movl (%rax), %edx
leaq -0x107c8(%rbp), %rdi
callq 0x7820
movq %rax, -0x108e8(%rbp)
jmp 0x74a1
movq -0x108e8(%rbp), %rax
movl (%rax), %eax
addl -0x107fc(%rbp), %eax
movl %eax, -0x107fc(%rbp)
leaq -0x10810(%rbp), %rdi
callq 0x9440
jmp 0x741b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x106c8(%rbp)
movl %eax, -0x106cc(%rbp)
leaq -0x107f8(%rbp), %rdi
callq 0x9480
jmp 0x7751
movl -0x107d4(%rbp), %eax
movl -0x107e0(%rbp), %ecx
subl %ecx, %eax
movl %eax, -0x107e0(%rbp)
movl -0x107d4(%rbp), %eax
movl -0x107fc(%rbp), %ecx
subl %ecx, %eax
movl %eax, -0x107fc(%rbp)
leaq -0x8368(%rbp), %rdi
leaq -0x106c0(%rbp), %rsi
leaq -0x107f8(%rbp), %rdx
callq 0x69a0
movb %al, -0x108f1(%rbp)
jmp 0x7534
movb -0x108f1(%rbp), %al
testb $0x1, %al
jne 0x7540
jmp 0x7542
jmp 0x7561
leaq 0x16b56(%rip), %rdi     # 0x1e09f
leaq 0x16b68(%rip), %rsi     # 0x1e0b8
movl $0x2c8, %edx            # imm = 0x2C8
leaq 0x16b6a(%rip), %rcx     # 0x1e0c6
callq 0x41f0
movl -0x107e0(%rbp), %eax
cmpl -0x107fc(%rbp), %eax
jne 0x7571
jmp 0x7590
leaq 0x16b65(%rip), %rdi     # 0x1e0dd
leaq 0x16b39(%rip), %rsi     # 0x1e0b8
movl $0x2c9, %edx            # imm = 0x2C9
leaq 0x16b3b(%rip), %rcx     # 0x1e0c6
callq 0x41f0
cvtsi2sdl -0x107e0(%rbp), %xmm0
movsd 0x16a68(%rip), %xmm1    # 0x1e008
divsd %xmm1, %xmm0
movq 0x269f5(%rip), %rdi     # 0x2dfa0
callq 0x4560
movq %rax, -0x10900(%rbp)
jmp 0x75b9
movq -0x10900(%rbp), %rdi
movq 0x269e9(%rip), %rsi     # 0x2dfb0
callq 0x4310
jmp 0x75ce
leaq -0x107f8(%rbp), %rax
movq %rax, -0x10838(%rbp)
movq -0x10838(%rbp), %rdi
callq 0x9380
movq %rax, -0x10840(%rbp)
movq -0x10838(%rbp), %rdi
callq 0x93b0
movq %rax, -0x10848(%rbp)
leaq -0x10840(%rbp), %rdi
leaq -0x10848(%rbp), %rsi
callq 0x93e0
testb $0x1, %al
jne 0x761e
jmp 0x76fd
leaq -0x10840(%rbp), %rdi
callq 0x9420
movq (%rax), %rax
movq %rax, -0x10850(%rbp)
leaq -0x10850(%rbp), %rdi
movq %rdi, -0x10910(%rbp)
callq 0x8770
movq -0x10910(%rbp), %rdi
movq %rax, -0x10858(%rbp)
callq 0x8790
movq %rax, -0x10860(%rbp)
leaq -0x8338(%rbp), %rdi
movq -0x10858(%rbp), %rax
movslq (%rax), %rsi
callq 0x9460
movq %rax, %rsi
movq 0x2694f(%rip), %rdi     # 0x2dfd0
callq 0x42a0
movq %rax, -0x10908(%rbp)
jmp 0x768f
movq -0x10908(%rbp), %rdi
movl $0x20, %esi
callq 0x4370
movq %rax, -0x10918(%rbp)
jmp 0x76a9
leaq -0x10690(%rbp), %rdi
movq -0x10860(%rbp), %rax
movslq (%rax), %rsi
callq 0x9460
movq -0x10918(%rbp), %rdi
movq %rax, %rsi
callq 0x42a0
movq %rax, -0x10920(%rbp)
jmp 0x76d7
movq -0x10920(%rbp), %rdi
movl $0xa, %esi
callq 0x4370
jmp 0x76ea
jmp 0x76ec
leaq -0x10840(%rbp), %rdi
callq 0x9440
jmp 0x7602
leaq -0x107f8(%rbp), %rdi
callq 0x9480
leaq -0x107c8(%rbp), %rdi
callq 0x7b50
leaq -0x10798(%rbp), %rdi
callq 0x7b50
leaq -0x106e8(%rbp), %rdi
callq 0x94e0
leaq -0x106c0(%rbp), %rdi
callq 0x9540
leaq -0x8368(%rbp), %rdi
callq 0x9540
movl -0x4(%rbp), %eax
addq $0x10920, %rsp          # imm = 0x10920
popq %rbp
retq
leaq -0x107c8(%rbp), %rdi
callq 0x7b50
leaq -0x10798(%rbp), %rdi
callq 0x7b50
leaq -0x106e8(%rbp), %rdi
callq 0x94e0
leaq -0x106c0(%rbp), %rdi
callq 0x9540
leaq -0x8368(%rbp), %rdi
callq 0x9540
movq -0x106c8(%rbp), %rdi
callq 0x44e0
nopl (%rax)