// File: /workspace/github_cpp_makefile_star2_O2/EduBic[P]TSP-MetaheuristicSolvers/./neighborimprovement.h
// Function: FirstImprovement::execute(TSP const&, TSPSolution const&, move&)
double execute(const TSP& tsp , const TSPSolution& currSol, TSPMove& move) {
        //cout << endl << endl << "-------------- find neighbor --------------";


        double bestCostVariation = tsp.infinite;

        for ( uint a = 1 ; a < currSol.sequence.size() - 2 ; a++ ) {

            int h = currSol.sequence[a-1];
            int i = currSol.sequence[a];

            for ( uint b = a + 1 ; b < currSol.sequence.size() - 1 ; b++ ) {
                int j = currSol.sequence[b];
                int l = currSol.sequence[b+1];

                // incremental evaluation --> bestCostVariation (instead of best cost)
                double neighCostVariation = - tsp.cost[h][i] - tsp.cost[j][l]
                                            + tsp.cost[h][j] + tsp.cost[i][l];

                if (neighCostVariation < bestCostVariation ) {
                    // neighbor better of precedent neighbors
                    bestCostVariation = neighCostVariation;
                    move.from = a;
                    move.to = b;

                    double currentBestValueFound = currSol.evaluateObjectiveFunction(tsp);

                    // on first improvement exit
                    //cout << endl << "Move from " << a << " to " << b;
                    //cout << "\tNeighbor Value = " << currentBestValueFound + bestCostVariation << " - CurrentBestValue = " << currentBestValueFound;
                    if (currentBestValueFound + bestCostVariation < currentBestValueFound) {
                        //cout << "\tIt's an improvement, chose it!" << endl;
                        //cout << "------------------------" << endl;
                        return bestCostVariation;
                    }
                }
            }
        }

        //cout << endl << "------------------------------" << endl;
        return bestCostVariation;
    }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rcx, 0x10(%rsp)
movq %rsi, (%rsp)
movsd 0x20(%rsi), %xmm0
movq (%rdx), %rax
movq 0x8(%rdx), %rcx
pushq $0x1
popq %r8
movapd 0x7c3(%rip), %xmm1      # 0x72b0
movq %rdx, 0x8(%rsp)
movl %r8d, %edi
movq %rcx, %rsi
subq %rax, %rsi
sarq $0x2, %rsi
addq $-0x2, %rsi
cmpq %rdi, %rsi
jbe 0x6bfe
leal -0x1(%r8), %esi
movslq (%rax,%rsi,4), %rsi
movslq (%rax,%rdi,4), %r13
movq %r8, 0x18(%rsp)
leal 0x1(%r8), %ebp
imulq $0x18, %rsi, %rbx
imulq $0x18, %r13, %r12
movl %ebp, %r15d
movq (%rsp), %rdx
movq 0x8(%rdx), %rdx
leaq (%rdx,%rbx), %rsi
leaq (%rdx,%r12), %rdi
movl %r15d, %r8d
movq %rcx, %r9
subq %rax, %r9
sarq $0x2, %r9
decq %r9
cmpq %r8, %r9
jbe 0x6bf2
movslq (%rax,%r8,4), %r9
leal 0x1(%r8), %r15d
movslq (%rax,%r15,4), %r8
movq (%rsi), %r10
movsd (%r10,%r13,8), %xmm2
xorpd %xmm1, %xmm2
imulq $0x18, %r9, %r11
movq (%rdx,%r11), %r11
subsd (%r11,%r8,8), %xmm2
addsd (%r10,%r9,8), %xmm2
movq (%rdi), %r9
addsd (%r9,%r8,8), %xmm2
ucomisd %xmm2, %xmm0
jbe 0x6b3c
movq %rbx, %r14
movl %ebp, %ebx
movq 0x10(%rsp), %rcx
movq 0x18(%rsp), %rax
movl %eax, (%rcx)
leal -0x1(%r15), %eax
movl %eax, 0x4(%rcx)
movq 0x8(%rsp), %rbp
movq %rbp, %rdi
movq (%rsp), %rsi
movapd %xmm2, 0x20(%rsp)
callq 0x476c
movapd 0x20(%rsp), %xmm2
movapd %xmm2, %xmm1
addsd %xmm0, %xmm1
ucomisd %xmm1, %xmm0
ja 0x6bfa
movq (%rbp), %rax
movq 0x8(%rbp), %rcx
movapd %xmm2, %xmm0
movapd 0x6c8(%rip), %xmm1      # 0x72b0
movl %ebx, %ebp
movq %r14, %rbx
jmp 0x6b2c
movl %ebp, %r8d
jmp 0x6af2
movapd %xmm2, %xmm0
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop