// File: /workspace/github_cpp_makefile_star2_O2/Kingsford-Group[P]ghost2/src/localImprove.hpp
// Function: searchIter(Graph&, Graph&, boost::unordered::unordered_map<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, double, boost::hash<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>, std::equal_to<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>, std::allocator<std::pair<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>> const, double>>>*, boost::bimaps::bimap<boost::bimaps::unordered_set_of<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, boost::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>, boost::bimaps::unordered_set_of<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, boost::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>, mpl_::na, mpl_::na, mpl_::na>*, double, int)
int searchIter(Graph& G, Graph& H, blastmap *dists, bmap *f, double ratio, int numthreads)
{
  if(numthreads == -1) numthreads = boost::thread::hardware_concurrency();
  if(numthreads < 2) numthreads = 2;
  boost::threadpool::pool threads(numthreads);

  int totalDelt = 0;
  vector<string> hverts = H.nodes();
  int numMoves = hverts.size();
  vector<string> lefts;
  for(auto it = f->left.begin(); it != f->left.end(); it++) 
    lefts.push_back(it->first);

  move** moves = new move*[numMoves];
  int i = 0;
  for(auto it = hverts.begin(); it != hverts.end(); it++){
    auto up = f->right.find(*it);
    moves[i++] = new move(*it, up == f->right.end() ? "" : up->second);
  }

  ProgressBar pbar(lefts.size(), bclock::local_time());
  srand(time(0));
  
  for(auto it = lefts.begin(); it != lefts.end(); it++){
    string u = *it;
    string w = f->left.at(u);
    
    move *bestMove = NULL;
    bool constrained = rand() > (ratio*RAND_MAX);

    for(int threadsMade = 0, i = 0; threadsMade < numthreads; threadsMade++){
      int n = (numMoves - i)/(numthreads - threadsMade);
      auto worker = boost::bind(&calcScoresWorker, &G, &H, dists, f, u, w, moves + i, n);
      i += n;
      threads.schedule(worker);
    }
    threads.wait();

    for(int i = 0; i < numMoves; i++){
      move *m = moves[i];
      //Check if move is acceptible
      //if(m->s0 > 0 && m->s1 >= 0 && (!constrained || m->s2 >= 0)){
      if(m->s0 >= 0){
        if(!bestMove) bestMove = m;
        else if(m->s0 > bestMove->s0) bestMove = m;
        else if(m->s0 == bestMove->s0 && m->s1 > bestMove->s1) bestMove = m;
        else if(m->s0 == bestMove->s0 && m->s1 == bestMove->s1 && m->s2 > bestMove->s2) bestMove = m;
      }
    }

    if(bestMove){
      bestMove->apply(f);
      totalDelt += bestMove->s0;
      
      auto upt = f->right.find(bestMove->w);
      string up = upt == f->right.end() ? "" : upt->second;
      for(int i = 0; i < numMoves; i++)
        if(moves[i]->v == bestMove->w){moves[i]->up = up; break;}
    }
    pbar.update();
  }
  return totalDelt; 
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2e8, %rsp            # imm = 0x2E8
movq %rcx, 0x20(%rsp)
movq %rdx, 0xa0(%rsp)
movq %rsi, %r12
movq %rdi, 0x90(%rsp)
cmpl $-0x1, %r8d
jne 0x16b7a
callq 0xe6c0
movl %eax, %r8d
cmpl $0x3, %r8d
pushq $0x2
popq %rsi
cmovgel %r8d, %esi
leaq 0xa8(%rsp), %rdi
movq %rsi, 0x78(%rsp)
callq 0x190dc
leaq 0x58(%rsp), %rdi
movq %r12, %rsi
callq 0xf448
movq 0x60(%rsp), %r15
subq 0x58(%rsp), %r15
movq %r15, %rax
shrq $0x5, %rax
movq %rax, 0x38(%rsp)
xorpd %xmm0, %xmm0
leaq 0x40(%rsp), %rbx
movapd %xmm0, (%rbx)
andq $0x0, 0x10(%rbx)
movq 0x20(%rsp), %rax
leaq 0x98(%rax), %r13
movq 0x98(%rax), %rax
movq -0x8(%rax), %rax
movq 0x48(%rax), %rcx
movq (%rcx), %r14
leaq -0x40(%r14), %rcx
testq %r14, %r14
cmovneq %rcx, %r14
cmpq %rax, %r14
je 0x16c2c
movq %rbx, %rdi
movq %r14, %rsi
callq 0x186ec
movq 0x48(%r14), %rax
addq $0x40, %r14
movq (%rax), %rcx
cmpq %r14, %rcx
cmoveq %rax, %rcx
leaq -0x40(%rcx), %r14
testq %rcx, %rcx
cmoveq %rcx, %r14
movq (%r13), %rax
movq -0x8(%rax), %rax
jmp 0x16bf5
movq %r13, 0x80(%rsp)
movq %r12, 0x98(%rsp)
shlq $0x1b, %r15
movq %r15, %rax
sarq $0x1d, %rax
testq %r15, %r15
pushq $-0x1
popq %rdi
cmovnsq %rax, %rdi
callq 0xe040
movq %rax, %r13
movq 0x58(%rsp), %rbx
movq 0x20(%rsp), %rax
leaq 0xa0(%rax), %rbp
movq %r13, 0x8(%rsp)
movq %rbp, 0x30(%rsp)
cmpq 0x60(%rsp), %rbx
je 0x16d3f
movq %rbp, %rdi
movq %rbx, %rsi
callq 0x19fde
movq %rax, %r12
movl $0x98, %edi
callq 0xe560
movq %rax, %r15
leaq 0x108(%rsp), %rdi
movq %rbx, %rsi
callq 0xe7a0
movq (%rbp), %rax
movq -0x8(%rax), %rax
movq %rax, 0x18(%rsp)
cmpq %rax, %r12
je 0x16cd1
leaq 0x148(%rsp), %r14
movq %r14, %rdi
movq %r12, %rsi
callq 0xe7a0
jmp 0x16ced
leaq 0x148(%rsp), %r14
movq %r14, %rdi
leaq 0x29be5(%rip), %rsi     # 0x408c8
leaq 0x17(%rsp), %rdx
callq 0x1866e
movq %rbx, %rbp
movq %r15, %rdi
leaq 0x108(%rsp), %rsi
movq %r14, %rdx
callq 0x1a9f4
movq 0x8(%rsp), %rbx
movq %r15, (%rbx)
movq %r14, %rdi
callq 0xe290
cmpq 0x18(%rsp), %r12
leaq 0x108(%rsp), %rdi
callq 0xe290
addq $0x20, %rbp
addq $0x8, %rbx
movq %rbx, 0x8(%rsp)
movq %rbp, %rbx
movq 0x30(%rsp), %rbp
jmp 0x16c74
movq 0x40(%rsp), %r14
movq 0x48(%rsp), %rbx
callq 0x1889e
subq %r14, %rbx
shrq $0x5, %rbx
leaq 0x220(%rsp), %rdi
movl %ebx, %esi
movq %rax, %rdx
callq 0x19346
movq $0x0, 0x28(%rsp)
xorl %edi, %edi
callq 0xe4d0
movl %eax, %edi
callq 0xe510
movq 0x40(%rsp), %rsi
movq 0x38(%rsp), %rax
testl %eax, %eax
movl $0x0, %ebp
cmovgl %eax, %ebp
leaq 0x1e0(%rsp), %r12
movq %rbp, 0x70(%rsp)
movq %r13, 0x88(%rsp)
cmpq 0x48(%rsp), %rsi
je 0x17074
leaq 0xe8(%rsp), %rbx
movq %rbx, %rdi
movq %rsi, 0x18(%rsp)
callq 0xe7a0
movq 0x80(%rsp), %rdi
movq %rbx, %rsi
callq 0x1aaae
leaq 0xc8(%rsp), %rdi
movq %rax, %rsi
callq 0xe7a0
callq 0xe1b0
xorl %edx, %edx
movq 0x78(%rsp), %rax
movl %eax, %ecx
movl %eax, %ebp
subl $0x1, %ebp
jb 0x16f0a
movq 0x38(%rsp), %rax
movl %edx, 0x8(%rsp)
subl %edx, %eax
cltd
idivl %ecx
movl %eax, %ebx
leaq 0x128(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0xe7a0
leaq 0x200(%rsp), %r14
movq %r14, %rdi
leaq 0xc8(%rsp), %rsi
callq 0xe7a0
movslq 0x8(%rsp), %rax
leaq (,%rax,8), %rax
addq %r13, %rax
leaq 0x168(%rsp), %r15
movq %r15, %rdi
leaq -0x3a2(%rip), %rsi      # 0x16abd
movq 0x90(%rsp), %rdx
movq 0x98(%rsp), %rcx
movq 0xa0(%rsp), %r8
movq 0x20(%rsp), %r9
pushq %rbx
pushq %rax
pushq %r14
leaq 0x140(%rsp), %r13
pushq %r13
callq 0x1aafb
addq $0x20, %rsp
movq %r14, %rdi
callq 0xe290
movq %r13, %rdi
callq 0xe290
leaq 0x270(%rsp), %r14
movq %r14, %rdi
movq %r15, %rsi
callq 0x1abf6
movq %r12, %rdi
movq %r14, %rsi
xorl %edx, %edx
callq 0x1ac0a
leaq 0xa8(%rsp), %rdi
movq %r12, %rsi
callq 0x193d0
addl 0x8(%rsp), %ebx
movq %r12, %rdi
callq 0x194d6
leaq 0x278(%rsp), %rdi
callq 0x21c08
leaq 0x170(%rsp), %rdi
callq 0x21c08
movl %ebp, %ecx
movl %ebx, %edx
movq 0x88(%rsp), %r13
jmp 0x16df7
leaq 0xa8(%rsp), %rdi
xorl %esi, %esi
callq 0x194e6
movq 0x30(%rsp), %r14
movq 0x70(%rsp), %rbp
xorl %eax, %eax
xorl %ebx, %ebx
cmpq %rax, %rbp
je 0x16f86
movq (%r13,%rax,8), %rcx
movsd 0x80(%rcx), %xmm0
ucomisd 0x2913f(%rip), %xmm0    # 0x40080
jb 0x16f81
testq %rbx, %rbx
je 0x16f7e
ucomisd 0x80(%rbx), %xmm0
ja 0x16f7e
jne 0x16f81
jp 0x16f81
movsd 0x88(%rcx), %xmm0
ucomisd 0x88(%rbx), %xmm0
ja 0x16f7e
jne 0x16f81
jp 0x16f81
movsd 0x90(%rcx), %xmm0
ucomisd 0x90(%rbx), %xmm0
jbe 0x16f81
movq %rcx, %rbx
incq %rax
jmp 0x16f27
testq %rbx, %rbx
je 0x1703f
movq %rbx, %rdi
movq 0x20(%rsp), %rsi
callq 0x1ac56
cvtsi2sdl 0x28(%rsp), %xmm0
addsd 0x80(%rbx), %xmm0
movsd %xmm0, 0x8(%rsp)
addq $0x20, %rbx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x19fde
movq (%r14), %rcx
cmpq -0x8(%rcx), %rax
je 0x16fda
leaq 0x168(%rsp), %rdi
movq %rax, %rsi
callq 0xe7a0
jmp 0x16ff1
leaq 0x168(%rsp), %rdi
leaq 0x298df(%rip), %rsi     # 0x408c8
movq %r12, %rdx
callq 0x1866e
cvttsd2si 0x8(%rsp), %eax
movq %rax, 0x28(%rsp)
xorl %r14d, %r14d
cmpq %r14, %rbp
je 0x17032
movq (%r13,%r14,8), %rdi
addq $0x40, %rdi
movq %rbx, %rsi
callq 0x186a9
incq %r14
testb %al, %al
je 0x16fff
movq -0x8(%r13,%r14,8), %rdi
addq $0x60, %rdi
leaq 0x168(%rsp), %rsi
callq 0xe300
leaq 0x168(%rsp), %rdi
callq 0xe290
leaq 0x220(%rsp), %rdi
callq 0x107b0
leaq 0xc8(%rsp), %rdi
callq 0xe290
leaq 0xe8(%rsp), %rdi
callq 0xe290
movq 0x18(%rsp), %rsi
addq $0x20, %rsi
jmp 0x16da7
leaq 0x248(%rsp), %rdi
callq 0x216f2
leaq 0x40(%rsp), %rdi
callq 0x18718
leaq 0x58(%rsp), %rdi
callq 0x18718
leaq 0xa8(%rsp), %rdi
callq 0x1963e
movq 0x28(%rsp), %rax
addq $0x2e8, %rsp            # imm = 0x2E8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x17133
movq %rax, %rbx
jmp 0x171d5
jmp 0x17133
jmp 0x17185
movq %rax, %rbx
leaq 0x168(%rsp), %rdi
jmp 0x17195
jmp 0x170e6
jmp 0x17185
jmp 0x17185
movq %rax, %rbx
jmp 0x1710d
movq %rax, %rbx
jmp 0x171b4
movq %rax, %rbx
jmp 0x1711a
movq %rax, %rbx
leaq 0x148(%rsp), %rdi
callq 0xe290
cmpq 0x18(%rsp), %r12
leaq 0x108(%rsp), %rdi
callq 0xe290
movl $0x98, %esi
movq %r15, %rdi
callq 0xe590
jmp 0x171c1
jmp 0x17133
movq %rax, %rbx
jmp 0x171a7
movq %rax, %rbx
jmp 0x171c1
jmp 0x17185
movq %rax, %rbx
leaq 0x200(%rsp), %rdi
callq 0xe290
jmp 0x1718d
movq %rax, %rbx
jmp 0x17176
movq %rax, %rbx
jmp 0x17169
movq %rax, %rbx
leaq 0x1e0(%rsp), %rdi
callq 0x194d6
leaq 0x278(%rsp), %rdi
callq 0x21c08
leaq 0x170(%rsp), %rdi
callq 0x21c08
jmp 0x1719a
movq %rax, %rbx
jmp 0x1719a
movq %rax, %rbx
leaq 0x128(%rsp), %rdi
callq 0xe290
leaq 0xc8(%rsp), %rdi
callq 0xe290
leaq 0xe8(%rsp), %rdi
callq 0xe290
leaq 0x248(%rsp), %rdi
callq 0x216f2
leaq 0x40(%rsp), %rdi
callq 0x18718
leaq 0x58(%rsp), %rdi
callq 0x18718
leaq 0xa8(%rsp), %rdi
callq 0x1963e
movq %rbx, %rdi
callq 0xe9f0