// File: cauimsouza[P]rikudo-solver/src/rikudo_solver/graph.cpp
// Function: Graph::unique_sol(int, int, std::basic_ofstream<char, std::char_traits<char>>&)
void Graph::unique_sol(int first, int last, std::ofstream &ofile){
    construct_sat(first, last);
    solve_sat();
    auto orig_path = read_sol();

    if(orig_path.empty()){
        write_min_cons(orig_path, orig_path, -1, ofile);
        return;
    }

    std::string ban = create_ban(orig_path);
    int n_vars, n_clauses;
    extend_sat(ban, n_vars, n_clauses);

    recopy(n_vars, n_clauses);
    solve_sat();
    auto extra_path = read_sol();
    if(extra_path.empty()){
        write_min_cons(orig_path, extra_path, -1, ofile);
        return;
    }
    
    std::vector<int> cons = create_cons(n_vertices);

    
    int lo = 0; // adding until lo-1 constraints will always produce solution
    int hi = cons.size() - 1; // adding hi or more will not produce more solutions
    while(lo < hi){
        int mid = lo + (hi-lo)/2;

        recopy(n_vars, n_clauses + mid + 1);
        add_cons(orig_path, cons, mid);
        solve_sat();
        auto extra_path = read_sol();  

        if(extra_path.empty()){
            hi = mid;
        }
        else{
            lo = mid + 1;
        }
    }

    // in the end we have lo == hi
    write_min_cons(orig_path, cons, lo, ofile);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x160, %rsp            # imm = 0x160
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movq %rcx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x140(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0x138(%rbp)
movl -0x10(%rbp), %eax
movl %eax, -0x134(%rbp)
xorps %xmm0, %xmm0
movaps %xmm0, -0x150(%rbp)
movaps %xmm0, -0x30(%rbp)
movq $0x0, -0x20(%rbp)
leaq -0x30(%rbp), %rdi
movq %rdi, -0x130(%rbp)
callq 0x4490
movaps -0x150(%rbp), %xmm0
movaps %xmm0, -0x50(%rbp)
movq $0x0, -0x40(%rbp)
leaq -0x50(%rbp), %rdi
movq %rdi, -0x128(%rbp)
callq 0x4490
movq -0x140(%rbp), %rdi
movl -0x138(%rbp), %esi
movl -0x134(%rbp), %edx
movq -0x130(%rbp), %rcx
movq -0x128(%rbp), %r8
callq 0x7c80
jmp 0xa1c7
leaq -0x50(%rbp), %rdi
callq 0x45a0
leaq -0x30(%rbp), %rdi
callq 0x45a0
movq -0x140(%rbp), %rdi
callq 0x8910
movq -0x140(%rbp), %rdi
callq 0x8320
movq %rax, %rsi
leaq -0x78(%rbp), %rdi
callq 0x5370
leaq -0x78(%rbp), %rdi
callq 0xb810
testb $0x1, %al
jne 0xa20c
jmp 0xa26a
movq -0x140(%rbp), %rdi
movq -0x18(%rbp), %r8
leaq -0x78(%rbp), %rdx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movq %rdx, %rsi
callq 0xa570
jmp 0xa22a
movl $0x1, -0x7c(%rbp)
jmp 0xa52a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x45a0
leaq -0x30(%rbp), %rdi
callq 0x45a0
jmp 0xa55d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xa554
movq -0x140(%rbp), %rsi
leaq -0xa0(%rbp), %rdi
leaq -0x78(%rbp), %rdx
callq 0x8ee0
jmp 0xa283
leaq -0xc8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x30e0
jmp 0xa298
movq -0x140(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
leaq -0xa4(%rbp), %rdx
leaq -0xa8(%rbp), %rcx
callq 0x90a0
jmp 0xa2bb
leaq -0xc8(%rbp), %rdi
callq 0x3170
movq -0x140(%rbp), %rdi
movl -0xa4(%rbp), %esi
movl -0xa8(%rbp), %edx
callq 0x94b0
jmp 0xa2e1
movq -0x140(%rbp), %rdi
callq 0x8910
jmp 0xa2ef
movq -0x140(%rbp), %rdi
callq 0x8320
movq %rax, -0x158(%rbp)
jmp 0xa304
movq -0x158(%rbp), %rsi
leaq -0xe0(%rbp), %rdi
callq 0x5370
jmp 0xa319
leaq -0xe0(%rbp), %rdi
callq 0xb810
testb $0x1, %al
jne 0xa32b
jmp 0xa398
movq -0x140(%rbp), %rdi
movq -0x18(%rbp), %r8
leaq -0x78(%rbp), %rsi
leaq -0xe0(%rbp), %rdx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
callq 0xa570
jmp 0xa34d
movl $0x1, -0x7c(%rbp)
jmp 0xa512
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xa548
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x3170
jmp 0xa548
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xa53c
movq -0x140(%rbp), %rsi
movl (%rsi), %edx
leaq -0xf8(%rbp), %rdi
callq 0xa750
jmp 0xa3af
movl $0x0, -0xfc(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x5460
subq $0x1, %rax
movl %eax, -0x100(%rbp)
movl -0xfc(%rbp), %eax
cmpl -0x100(%rbp), %eax
jge 0xa4dc
movq -0x140(%rbp), %rdi
movl -0xfc(%rbp), %eax
movl -0x100(%rbp), %ecx
subl %eax, %ecx
movl %ecx, %edx
shrl $0x1f, %edx
addl %edx, %ecx
sarl %ecx
addl %ecx, %eax
movl %eax, -0x104(%rbp)
movl -0xa4(%rbp), %esi
movl -0xa8(%rbp), %edx
movl -0x104(%rbp), %eax
movl %eax, %ecx
movl %edx, %eax
leal 0x1(%rax,%rcx), %edx
callq 0x94b0
jmp 0xa428
movq -0x140(%rbp), %rdi
movl -0x104(%rbp), %ecx
leaq -0x78(%rbp), %rsi
leaq -0xf8(%rbp), %rdx
callq 0xa8e0
jmp 0xa447
movq -0x140(%rbp), %rdi
callq 0x8910
jmp 0xa455
movq -0x140(%rbp), %rdi
callq 0x8320
movq %rax, -0x160(%rbp)
jmp 0xa46a
movq -0x160(%rbp), %rsi
leaq -0x120(%rbp), %rdi
callq 0x5370
jmp 0xa47f
leaq -0x120(%rbp), %rdi
callq 0xb810
testb $0x1, %al
jne 0xa491
jmp 0xa4bc
movl -0x104(%rbp), %eax
movl %eax, -0x100(%rbp)
jmp 0xa4cb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x43e0
jmp 0xa53c
movl -0x104(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xfc(%rbp)
leaq -0x120(%rbp), %rdi
callq 0x43e0
jmp 0xa3cf
movq -0x140(%rbp), %rdi
movl -0xfc(%rbp), %ecx
movq -0x18(%rbp), %r8
leaq -0x78(%rbp), %rsi
leaq -0xf8(%rbp), %rdx
callq 0xa570
jmp 0xa4ff
leaq -0xf8(%rbp), %rdi
callq 0x43e0
movl $0x0, -0x7c(%rbp)
leaq -0xe0(%rbp), %rdi
callq 0x43e0
leaq -0xa0(%rbp), %rdi
callq 0x3170
leaq -0x78(%rbp), %rdi
callq 0x43e0
addq $0x160, %rsp            # imm = 0x160
popq %rbp
retq
leaq -0xe0(%rbp), %rdi
callq 0x43e0
leaq -0xa0(%rbp), %rdi
callq 0x3170
leaq -0x78(%rbp), %rdi
callq 0x43e0
movq -0x58(%rbp), %rdi
callq 0x3400
nopw %cs:(%rax,%rax)