// File: GAStudyGroup[P]GPX2/src/main.cpp
// Function: GA()
void GA() {
    Population pop;
    bool foundBestWithoutGA = true;

    ofstream *logFile{Log::initLogFile()};  

    Log::printHeader(*logFile);

    auto start = std::chrono::high_resolution_clock::now();

    GAUtils::init(pop);
    AntMap::initMap();
    AntMap::updatePheromoneMap(pop.getBestTour());

    // cout<<"tour size "<<Globals::TOUR_SIZE<<endl;
    // antColony.printPheromoneMap();

    // Population tmpPop = antColony.run();
    // cout<<"Size of return pop "<<tmpPop.getPopulation().size()<<" Best fitness of run 0 "<<tmpPop.bestFitness()<<endl;
    // antColony.printPheromoneMap();

    auto finishInitPop = std::chrono::high_resolution_clock::now();

    Log::printTime(*logFile,"Population created in:",
                    std::chrono::duration<double,std::milli> (finishInitPop - start).count()); 

    auto startGA = std::chrono::high_resolution_clock::now();

    int i{0}, firstBestFitness{pop.bestFitness()};
    *logFile << "\nFirst fitness " << firstBestFitness << endl;
    while(GAUtils::stop(pop,*logFile)){
        foundBestWithoutGA = false;
        i++;
        pop = GAUtils::generateNewPopulation(pop);
        // AntMap::printPheromoneMap();
        *logFile << "gen " << i << " best fitness " << pop.bestFitness() << endl;
        
    }

    if(foundBestWithoutGA){
        *logFile << "Found best without GA" << endl;
        cout << "Found best without GA" << endl;
    }

    auto finishGA = std::chrono::high_resolution_clock::now();
    Log::printTime(*logFile,"GA execution time:",
                    std::chrono::duration<double,std::milli> (finishGA - startGA).count()); 

    auto finish = std::chrono::high_resolution_clock::now();
    Log::printTime(*logFile,"Total execution time:",
                    std::chrono::duration<double,std::milli> (finish - start).count()); 

    Log::printFooter(*logFile,pop,i,firstBestFitness);

    (*logFile).close();
    delete logFile;
    AntMap::deleteMap();
}

// Assembly:
subq $0x208, %rsp            # imm = 0x208
leaq 0x1f0(%rsp), %rdi
callq 0x19220
movb $0x1, 0x1ef(%rsp)
callq 0x15ff0
movq %rax, 0xd8(%rsp)
jmp 0x8a9b
movq 0xd8(%rsp), %rax
movq %rax, 0x1e0(%rsp)
movq 0x1e0(%rsp), %rdi
callq 0x166a0
jmp 0x8aba
callq 0x6090
movq %rax, 0x1c8(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0xa930
jmp 0x8ad6
callq 0x4f980
jmp 0x8add
leaq 0x1f0(%rsp), %rdi
callq 0x19330
movq %rax, 0xd0(%rsp)
jmp 0x8af4
movq 0xd0(%rsp), %rdi
callq 0x4f5f0
jmp 0x8b03
callq 0x6090
movq %rax, 0x1c0(%rsp)
movq 0x1e0(%rsp), %rax
movq %rax, 0xc0(%rsp)
leaq 0x19f(%rsp), %rdi
movq %rdi, 0xc8(%rsp)
callq 0x6860
movq 0xc8(%rsp), %rdx
leaq 0x6b4cc(%rip), %rsi     # 0x74010
leaq 0x1a0(%rsp), %rdi
callq 0x92b0
jmp 0x8b53
leaq 0x1c0(%rsp), %rdi
leaq 0x1c8(%rsp), %rsi
callq 0x9370
movq %rax, 0xb8(%rsp)
jmp 0x8b72
movq 0xb8(%rsp), %rax
movq %rax, 0x188(%rsp)
leaq 0x190(%rsp), %rdi
leaq 0x188(%rsp), %rsi
callq 0x93c0
jmp 0x8b99
leaq 0x190(%rsp), %rdi
callq 0x9400
movsd %xmm0, 0xb0(%rsp)
jmp 0x8bb1
movsd 0xb0(%rsp), %xmm0
movq 0xc0(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
callq 0x17030
jmp 0x8bd1
leaq 0x1a0(%rsp), %rdi
callq 0x6988
leaq 0x19f(%rsp), %rdi
callq 0x6520
callq 0x6090
movq %rax, 0x180(%rsp)
movl $0x0, 0x17c(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x19240
movl %eax, 0xac(%rsp)
jmp 0x8c19
movl 0xac(%rsp), %eax
movl %eax, 0x178(%rsp)
movq 0x1e0(%rsp), %rdi
leaq 0x6b3f1(%rip), %rsi     # 0x74027
callq 0x64a0
movq %rax, 0xa0(%rsp)
jmp 0x8c45
movq 0xa0(%rsp), %rdi
movl 0x178(%rsp), %esi
callq 0x6820
movq %rax, 0x98(%rsp)
jmp 0x8c63
movq 0x98(%rsp), %rdi
movq 0x932de(%rip), %rsi     # 0x9bf50
callq 0x6500
jmp 0x8c79
jmp 0x8c7b
movq 0x1e0(%rsp), %rsi
leaq 0x1f0(%rsp), %rdi
callq 0xacb0
movb %al, 0x97(%rsp)
jmp 0x8c99
movb 0x97(%rsp), %al
testb $0x1, %al
jne 0x8ca9
jmp 0x8df5
movb $0x0, 0x1ef(%rsp)
movl 0x17c(%rsp), %eax
incl %eax
movl %eax, 0x17c(%rsp)
leaq 0x160(%rsp), %rdi
leaq 0x1f0(%rsp), %rsi
callq 0xb610
jmp 0x8cd8
leaq 0x1f0(%rsp), %rdi
leaq 0x160(%rsp), %rsi
movq %rsi, 0x80(%rsp)
callq 0x9410
movq 0x80(%rsp), %rdi
callq 0x9440
movq 0x1e0(%rsp), %rdi
leaq 0x6b326(%rip), %rsi     # 0x74037
callq 0x64a0
movq %rax, 0x88(%rsp)
jmp 0x8d20
movq 0x88(%rsp), %rdi
movl 0x17c(%rsp), %esi
callq 0x6820
movq %rax, 0x78(%rsp)
jmp 0x8d3b
movq 0x78(%rsp), %rdi
leaq 0x6b2f5(%rip), %rsi     # 0x7403c
callq 0x64a0
movq %rax, 0x70(%rsp)
jmp 0x8d53
leaq 0x1f0(%rsp), %rdi
callq 0x19240
movl %eax, 0x6c(%rsp)
jmp 0x8d66
movl 0x6c(%rsp), %esi
movq 0x70(%rsp), %rdi
callq 0x6820
movq %rax, 0x60(%rsp)
jmp 0x8d7b
movq 0x60(%rsp), %rdi
movq 0x931c9(%rip), %rsi     # 0x9bf50
callq 0x6500
jmp 0x8d8e
jmp 0x8c7b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1d8(%rsp)
movl %eax, 0x1d4(%rsp)
jmp 0x90f4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1d8(%rsp)
movl %eax, 0x1d4(%rsp)
jmp 0x8de3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1d8(%rsp)
movl %eax, 0x1d4(%rsp)
leaq 0x1a0(%rsp), %rdi
callq 0x6988
leaq 0x19f(%rsp), %rdi
callq 0x6520
jmp 0x90f4
testb $0x1, 0x1ef(%rsp)
je 0x8e5c
movq 0x1e0(%rsp), %rdi
leaq 0x6b23d(%rip), %rsi     # 0x7404b
callq 0x64a0
movq %rax, 0x58(%rsp)
jmp 0x8e1a
movq 0x58(%rsp), %rdi
movq 0x9312a(%rip), %rsi     # 0x9bf50
callq 0x6500
jmp 0x8e2d
movq 0x93164(%rip), %rdi     # 0x9bf98
leaq 0x6b210(%rip), %rsi     # 0x7404b
callq 0x64a0
movq %rax, 0x50(%rsp)
jmp 0x8e47
movq 0x50(%rsp), %rdi
movq 0x930fd(%rip), %rsi     # 0x9bf50
callq 0x6500
jmp 0x8e5a
jmp 0x8e5c
callq 0x6090
movq %rax, 0x158(%rsp)
movq 0x1e0(%rsp), %rax
movq %rax, 0x40(%rsp)
leaq 0x137(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x6860
movq 0x48(%rsp), %rdx
leaq 0x6b1cd(%rip), %rsi     # 0x74061
leaq 0x138(%rsp), %rdi
callq 0x92b0
jmp 0x8ea3
leaq 0x158(%rsp), %rdi
leaq 0x180(%rsp), %rsi
callq 0x9370
movq %rax, 0x38(%rsp)
jmp 0x8ebf
movq 0x38(%rsp), %rax
movq %rax, 0x120(%rsp)
leaq 0x128(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0x93c0
jmp 0x8ee3
leaq 0x128(%rsp), %rdi
callq 0x9400
movsd %xmm0, 0x30(%rsp)
jmp 0x8ef8
movsd 0x30(%rsp), %xmm0
movq 0x40(%rsp), %rdi
leaq 0x138(%rsp), %rsi
callq 0x17030
jmp 0x8f12
leaq 0x138(%rsp), %rdi
callq 0x6988
leaq 0x137(%rsp), %rdi
callq 0x6520
callq 0x6090
movq %rax, 0x118(%rsp)
movq 0x1e0(%rsp), %rax
movq %rax, 0x20(%rsp)
leaq 0xf7(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x6860
movq 0x28(%rsp), %rdx
leaq 0x6b110(%rip), %rsi     # 0x74074
leaq 0xf8(%rsp), %rdi
callq 0x92b0
jmp 0x8f73
leaq 0x118(%rsp), %rdi
leaq 0x1c8(%rsp), %rsi
callq 0x9370
movq %rax, 0x18(%rsp)
jmp 0x8f8f
movq 0x18(%rsp), %rax
movq %rax, 0xe0(%rsp)
leaq 0xe8(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x93c0
jmp 0x8fb3
leaq 0xe8(%rsp), %rdi
callq 0x9400
movsd %xmm0, 0x10(%rsp)
jmp 0x8fc8
movsd 0x10(%rsp), %xmm0
movq 0x20(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0x17030
jmp 0x8fe2
leaq 0xf8(%rsp), %rdi
callq 0x6988
leaq 0xf7(%rsp), %rdi
callq 0x6520
movq 0x1e0(%rsp), %rdi
movl 0x17c(%rsp), %edx
movl 0x178(%rsp), %ecx
leaq 0x1f0(%rsp), %rsi
callq 0x16d20
jmp 0x9021
movq 0x1e0(%rsp), %rdi
callq 0x66d0
jmp 0x9030
movq 0x1e0(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x904e
movq 0x8(%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
callq 0x4fb40
jmp 0x9055
leaq 0x1f0(%rsp), %rdi
callq 0x9440
addq $0x208, %rsp            # imm = 0x208
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1d8(%rsp)
movl %eax, 0x1d4(%rsp)
jmp 0x90a1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1d8(%rsp)
movl %eax, 0x1d4(%rsp)
leaq 0x138(%rsp), %rdi
callq 0x6988
leaq 0x137(%rsp), %rdi
callq 0x6520
jmp 0x90f4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1d8(%rsp)
movl %eax, 0x1d4(%rsp)
jmp 0x90e7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1d8(%rsp)
movl %eax, 0x1d4(%rsp)
leaq 0xf8(%rsp), %rdi
callq 0x6988
leaq 0xf7(%rsp), %rdi
callq 0x6520
leaq 0x1f0(%rsp), %rdi
callq 0x9440
movq 0x1d8(%rsp), %rdi
callq 0x6850
nop