// File: canzarlab[P]Trajan/src/BnG.cpp
// Function: GenericBnBSolver::SolveNode(BnBNode*, double, double)
bool GenericBnBSolver::SolveNode(BnBNode* node, double pgtol, double numtol)
{
    Vector x = (node->warm) ? *(node->warm) : Vector::Zero(nr_cols);

#if DEBUG == 1    
    size_t debug_node_genocnt  = 0;
    double debug_node_genotime = 0;
    debug_log << "id: " << node->debug_nodeid << endl;
    debug_log << "parent: " << node->debug_parent << endl;    
    debug_log << "depth: " << node->debug_depth << endl;
    debug_log << "best: " << -sys_ub << endl;
#endif

    if (!OnNodeStart(node)) return false;

    while(1)
    {
        SpMat A(node->rows, node->cols);
        A.setFromTriplets(node->Triplets.begin(), node->Triplets.end());
        Vector b = Vector::Ones(node->rows);       
        Vector y = Vector::Zero(node->rows);        
        Vector d = -c;                    

        BranchingJRF simpleJRF(A, b, d, x, y);
        simpleJRF.lo = node->var_lb;
        simpleJRF.hi = node->var_ub;
        AugmentedLagrangian solver(simpleJRF, 15);
        solver.setParameter("verbose", false);
        solver.setParameter("pgtol", pgtol); 
        solver.setParameter("constraintsTol", 1e-4);

        if (!OnNodeLP(node))
        { 
#if DEBUG == 1    
            debug_log << "ABORT" << endl << endl;
#endif
            return false;
        }
#if DEBUG == 1    
        Timer debug_T; debug_T.start();        
#endif      
        SolverStatus status = solver.solve();    
#if DEBUG == 1    
        debug_T.stop();
        debug_genocnt++;    
        debug_node_genocnt++;
        debug_node_genotime += debug_T.secs();
        debug_genotime += debug_T.secs();
        debug_genomin = min(debug_genomin, (double)debug_T.secs());
        debug_genomax = max(debug_genomax, (double)debug_T.secs());
        if (status == SUBOPTIMAL)
            debug_log << "SUBOPTIMAL(" << status << ")" << endl; 
        if (status == UNBOUNDED)
            debug_log << "UNBOUNDED(" << status << ")" << endl; 
        if (status == INFEASIBLE)
            debug_log << "INFEASIBLE(" << status << ")" << endl; 
        if (status == NUM_ERROR)
            debug_log << "NUM_ERROR(" << status << ")" << endl; 
#endif
        
        if (status == INFEASIBLE || CheckUB(solver.f(), numtol))
        {
#if DEBUG == 1    
            debug_log << "geno calls: " << debug_node_genocnt << endl;
            debug_log << "geno time: " << debug_node_genotime << endl;
            debug_log << "CUT: " << -solver.f() << endl << endl;
#endif
            return false;
        } 

        x = Vector::ConstMapType(solver.x(), node->cols);     

        if ((LP::cf == 1 && Add<1>(node->Triplets, x, node->rows)) || (LP::cf == 2 && (Add<1>(node->Triplets, x, node->rows) + Add<2>(node->Triplets, x, node->rows))))
            continue;
        
        node->obj = solver.f();        
        node->sol = x;

        if (!OnNodeFinish(node, true))
        {
#if DEBUG == 1    
            debug_log << "geno calls: " << debug_node_genocnt << endl;
            debug_log << "geno time: " << debug_node_genotime << endl;
            debug_log << "GREEDY CUT: " << -solver.f() << endl << endl;
#endif
            return false;
        }

        break;
    }

#if DEBUG == 1    
    debug_log << "geno calls: " << debug_node_genocnt << endl;
    debug_log << "geno time: " << debug_node_genotime << endl;
    debug_log << node->rows << " x " << node->cols << endl;
    debug_log << "lp: " << -node->obj << endl;
    size_t debug_fracs = 0;
    for (size_t i = 0; i < x.size(); ++i)
        debug_fracs += IsVarFrac(node->sol(i)) && !node->IsVarFixed(i);
    debug_log << "fracs: " << debug_fracs << endl << endl;
#endif

    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x300, %rsp            # imm = 0x300
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movsd %xmm0, -0x20(%rbp)
movsd %xmm1, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x290(%rbp)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x48(%rax)
je 0xd3706
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rsi
leaq -0x38(%rbp), %rdi
callq 0x144f0
jmp 0xd372a
movq -0x290(%rbp), %rax
movslq 0x10c(%rax), %rsi
leaq -0x50(%rbp), %rdi
callq 0x13c30
leaq -0x38(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0xaf2f0
movq -0x290(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq (%rdi), %rax
movq 0xa0(%rax), %rax
callq *%rax
movb %al, -0x291(%rbp)
jmp 0xd3749
movb -0x291(%rbp), %al
testb $0x1, %al
jne 0xd3776
jmp 0xd3755
movb $0x0, -0x1(%rbp)
movl $0x1, -0x60(%rbp)
jmp 0xd3e04
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xd3e1b
jmp 0xd3778
jmp 0xd377a
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rsi
movq 0x20(%rax), %rdx
leaq -0xa8(%rbp), %rdi
callq 0xaf0a0
jmp 0xd3794
movq -0x18(%rbp), %rdi
callq 0xaf180
movq %rax, -0xb0(%rbp)
movq -0x18(%rbp), %rdi
callq 0xaf1b0
movq %rax, -0xb8(%rbp)
leaq -0xa8(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
leaq -0xb8(%rbp), %rdx
callq 0xaf130
jmp 0xd37d0
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rsi
leaq -0xe0(%rbp), %rdi
callq 0xaf2b0
jmp 0xd37e6
leaq -0xc8(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0xaf2f0
jmp 0xd37fb
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rsi
leaq -0x108(%rbp), %rdi
callq 0x13c30
jmp 0xd3811
leaq -0xf0(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0xaf2f0
jmp 0xd3826
movq -0x290(%rbp), %rsi
addq $0xf8, %rsi
leaq -0x128(%rbp), %rdi
callq 0xaf330
jmp 0xd3842
leaq -0x118(%rbp), %rdi
leaq -0x128(%rbp), %rsi
callq 0xaf380
jmp 0xd3857
leaq -0x188(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
leaq -0xc8(%rbp), %rdx
leaq -0x118(%rbp), %rcx
leaq -0x38(%rbp), %r8
leaq -0xf0(%rbp), %r9
callq 0xcee40
jmp 0xd3885
movq -0x18(%rbp), %rsi
addq $0x28, %rsi
leaq -0x138(%rbp), %rdi
callq 0x145a0
jmp 0xd389b
movq -0x18(%rbp), %rsi
addq $0x38, %rsi
leaq -0x148(%rbp), %rdi
callq 0x145a0
jmp 0xd38b1
leaq -0x1f0(%rbp), %rdi
leaq -0x188(%rbp), %rsi
movl $0xf, %edx
callq 0x124e0
jmp 0xd38cb
leaq -0x211(%rbp), %rdi
movq %rdi, -0x2a0(%rbp)
callq 0xa7d0
movq -0x2a0(%rbp), %rdx
leaq 0x37b1e(%rip), %rsi     # 0x10b40a
leaq -0x210(%rbp), %rdi
callq 0xe9b0
jmp 0xd38fa
leaq -0x1f0(%rbp), %rdi
leaq -0x210(%rbp), %rsi
xorps %xmm0, %xmm0
callq 0x139e0
jmp 0xd3912
leaq -0x210(%rbp), %rdi
callq 0xa8d8
leaq -0x211(%rbp), %rdi
callq 0xa4c0
leaq -0x239(%rbp), %rdi
movq %rdi, -0x2a8(%rbp)
callq 0xa7d0
movq -0x2a8(%rbp), %rdx
leaq 0x37a9d(%rip), %rsi     # 0x10b3e8
leaq -0x238(%rbp), %rdi
callq 0xe9b0
jmp 0xd3959
movsd -0x20(%rbp), %xmm0
leaq -0x1f0(%rbp), %rdi
leaq -0x238(%rbp), %rsi
callq 0x139e0
jmp 0xd3973
leaq -0x238(%rbp), %rdi
callq 0xa8d8
leaq -0x239(%rbp), %rdi
callq 0xa4c0
leaq -0x261(%rbp), %rdi
movq %rdi, -0x2b0(%rbp)
callq 0xa7d0
movq -0x2b0(%rbp), %rdx
leaq 0x37a4f(%rip), %rsi     # 0x10b3fb
leaq -0x260(%rbp), %rdi
callq 0xe9b0
jmp 0xd39ba
leaq -0x1f0(%rbp), %rdi
leaq -0x260(%rbp), %rsi
movsd 0x580e0(%rip), %xmm0    # 0x12bab0
callq 0x139e0
jmp 0xd39d7
leaq -0x260(%rbp), %rdi
callq 0xa8d8
leaq -0x261(%rbp), %rdi
callq 0xa4c0
movq -0x290(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq (%rdi), %rax
movq 0xa8(%rax), %rax
callq *%rax
movb %al, -0x2b1(%rbp)
jmp 0xd3a0e
movb -0x2b1(%rbp), %al
testb $0x1, %al
jne 0xd3b39
jmp 0xd3a1e
movb $0x0, -0x1(%rbp)
movl $0x1, -0x60(%rbp)
jmp 0xd3d46
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xd3deb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xd3ddf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xd3dd3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xd3dc7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xd3dbb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xd3aa9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x210(%rbp), %rdi
callq 0xa8d8
leaq -0x211(%rbp), %rdi
callq 0xa4c0
jmp 0xd3daf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xd3ae0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x238(%rbp), %rdi
callq 0xa8d8
leaq -0x239(%rbp), %rdi
callq 0xa4c0
jmp 0xd3daf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xd3b17
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x260(%rbp), %rdi
callq 0xa8d8
leaq -0x261(%rbp), %rdi
callq 0xa4c0
jmp 0xd3daf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xd3daf
leaq -0x1f0(%rbp), %rdi
callq 0x125f0
movl %eax, -0x2b8(%rbp)
jmp 0xd3b4d
movl -0x2b8(%rbp), %eax
movl %eax, -0x268(%rbp)
cmpl $0x3, -0x268(%rbp)
je 0xd3ba9
leaq -0x1f0(%rbp), %rdi
callq 0x139c0
movsd %xmm0, -0x2c0(%rbp)
jmp 0xd3b78
movsd -0x2c0(%rbp), %xmm0
movq -0x290(%rbp), %rdi
movsd -0x28(%rbp), %xmm1
movq (%rdi), %rax
movq 0x68(%rax), %rax
callq *%rax
movb %al, -0x2c1(%rbp)
jmp 0xd3b9d
movb -0x2c1(%rbp), %al
testb $0x1, %al
jne 0xd3ba9
jmp 0xd3bb9
movb $0x0, -0x1(%rbp)
movl $0x1, -0x60(%rbp)
jmp 0xd3d46
leaq -0x1f0(%rbp), %rdi
callq 0x13980
movq %rax, -0x2d0(%rbp)
jmp 0xd3bce
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x2d8(%rbp)
leaq -0x282(%rbp), %rdi
callq 0x160e0
jmp 0xd3beb
movq -0x2d8(%rbp), %rdx
movq -0x2d0(%rbp), %rsi
leaq -0x280(%rbp), %rdi
leaq -0x282(%rbp), %rcx
callq 0x1cea0
jmp 0xd3c0e
leaq -0x38(%rbp), %rdi
leaq -0x280(%rbp), %rsi
callq 0x14740
jmp 0xd3c20
leaq 0xcd8b9(%rip), %rax     # 0x1a14e0
cmpl $0x1, (%rax)
jne 0xd3c5a
movq -0x290(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq %rsi, %rcx
addq $0x18, %rcx
leaq -0x38(%rbp), %rdx
callq 0xd92b0
movl %eax, -0x2dc(%rbp)
jmp 0xd3c4f
movl -0x2dc(%rbp), %eax
cmpl $0x0, %eax
jne 0xd3cbf
leaq 0xcd87f(%rip), %rax     # 0x1a14e0
cmpl $0x2, (%rax)
jne 0xd3cc8
movq -0x290(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq %rsi, %rcx
addq $0x18, %rcx
leaq -0x38(%rbp), %rdx
callq 0xd92b0
movl %eax, -0x2e0(%rbp)
jmp 0xd3c89
movq -0x290(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq %rsi, %rcx
addq $0x18, %rcx
leaq -0x38(%rbp), %rdx
callq 0xd92f0
movl %eax, -0x2e4(%rbp)
jmp 0xd3cac
movl -0x2e4(%rbp), %ecx
movl -0x2e0(%rbp), %eax
addl %ecx, %eax
cmpl $0x0, %eax
je 0xd3cc8
movl $0x2, -0x60(%rbp)
jmp 0xd3d46
leaq -0x1f0(%rbp), %rdi
callq 0x139c0
movsd %xmm0, -0x2f0(%rbp)
jmp 0xd3cde
movsd -0x2f0(%rbp), %xmm0
movq -0x18(%rbp), %rax
movsd %xmm0, 0x60(%rax)
movq -0x18(%rbp), %rdi
addq $0x50, %rdi
leaq -0x38(%rbp), %rsi
callq 0x145a0
jmp 0xd3d02
movq -0x290(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq (%rdi), %rax
movq 0xb0(%rax), %rax
movl $0x1, %edx
callq *%rax
movb %al, -0x2f1(%rbp)
jmp 0xd3d26
movb -0x2f1(%rbp), %al
testb $0x1, %al
jne 0xd3d3f
jmp 0xd3d32
movb $0x0, -0x1(%rbp)
movl $0x1, -0x60(%rbp)
jmp 0xd3d46
movl $0x3, -0x60(%rbp)
leaq -0x1f0(%rbp), %rdi
callq 0xaf420
leaq -0x188(%rbp), %rdi
callq 0xcef80
leaq -0x118(%rbp), %rdi
callq 0xff40
leaq -0xf0(%rbp), %rdi
callq 0xff40
leaq -0xc8(%rbp), %rdi
callq 0xff40
leaq -0xa8(%rbp), %rdi
callq 0xaf470
movl -0x60(%rbp), %eax
movl %eax, -0x2f8(%rbp)
subl $0x2, %eax
je 0xd3778
jmp 0xd3da2
movl -0x2f8(%rbp), %eax
subl $0x3, %eax
je 0xd3df9
jmp 0xd3e04
leaq -0x1f0(%rbp), %rdi
callq 0xaf420
leaq -0x188(%rbp), %rdi
callq 0xcef80
leaq -0x118(%rbp), %rdi
callq 0xff40
leaq -0xf0(%rbp), %rdi
callq 0xff40
leaq -0xc8(%rbp), %rdi
callq 0xff40
leaq -0xa8(%rbp), %rdi
callq 0xaf470
jmp 0xd3e1b
movb $0x1, -0x1(%rbp)
movl $0x1, -0x60(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xff40
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x300, %rsp            # imm = 0x300
popq %rbp
retq
leaq -0x38(%rbp), %rdi
callq 0xff40
movq -0x58(%rbp), %rdi
callq 0xa7c0
nopl (%rax)