// File: /workspace/github_cpp_makefile_star2_O2/maramire[P]SP_PSO/parallel_main.cpp
// Function: main
int main(int argc, const char *argv[]) 
{


    /* Taking algorithm time performance! */
    auto t1 = chrono::high_resolution_clock::now(); 

    cout << "Start!"<<endl;

    /* Open Instance File */

    /* Define number of items to pack */
    n_items = 0; 
    strip_width = 0;
    max_height = 0;

    string filepath = argv[1];
    cout << "-> Opening instances!"<<endl;
    openInstance(filepath, items, strip_width, max_height, n_items);

    
    unsigned int a = filepath.rfind('.');
    unsigned int b = filepath.rfind('/',a-1);
    string name = filepath.substr(b+1,a-b-1);
    
    

    cout << "-> Number of items: " << n_items << endl;
    cout << "-> Strip width: " << strip_width << endl;
    cout << "-> Upper bound computed: "  << max_height << endl;

    

    
    /* Initialize particles */
    for(int i=0; i<N_PARTICLES; i++){
        //unsigned seed = i+1;
        particle_init(n_items, swarm);

        /* Initialize strip */
        Strip s = {};
        s.height = max_height;
        s.width = strip_width;

        s.x_position = 0;
        s.y_position = 0;
    
        /* Evaluate each particle */
        HR(items,s,n_items,swarm[i]); 

        swarm[i].pbest = swarm[i].permutation;
        swarm[i].pbest_fitness = swarm[i].fitness;

    } 

    //showSwarm(swarm);

    gbest.fitness = max_height;


    /* Select best position */
    sort(swarm.begin(), swarm.end(), compareByFitness);
    
    if (swarm[0].fitness < gbest.fitness)
    {
        gbest.fitness = swarm[0].fitness;
        gbest.permutation = swarm[0].permutation;
    }

    int iter = 0;
    
    c1 = 2.05;
    c2 = 2.05;
    omega_max = 1.2;
    omega_min = 0.7;
    omega = 1.2;

    velocity_max = (n_items)/2;
    velocity_min = -(n_items)/2;
    

    /* create threads */
    long i;
    void *status;
    pthread_attr_t attr; 
    pthread_mutex_init(&mutex, NULL);

    /* Create threads to perform  */
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    

    while (iter<MAX_ITER)
    {

        iter++;
        for(i=0; i<N_PARTICLES; i++){
            
            pthread_create(&threads[i], &attr, particle_function, (void *)i);

        } 
        pthread_attr_destroy(&attr);

        /* Join here */

        /* Wait on the other threads */
        for(i=0; i<N_PARTICLES; i++)
        {
            pthread_join(threads[i], &status);
        }

        omega = (omega_max)-((omega_max-omega_min)/MAX_ITER)*iter;

    }
    
    

    //showSwarm(swarm);
    //showRectangles(items);

    //showPermutation(gbest);

    Strip s = {};
    s.height = max_height;
    s.width = strip_width;

    s.x_position = 0;
    s.y_position = 0;

    HR(items,s,n_items,gbest); 
    cout << "-> Fitness of best solution: " << gbest.fitness << endl;
    
    showRectangles(items);
    showPermutation(gbest.permutation);

    //cout << "-> End!" << endl;

    auto t2 = chrono::high_resolution_clock::now(); 
    chrono::duration<double> time_span = (t2 - t1);
    cout << "-> It took me " << time_span.count() << " seconds.";
    cout << endl;

/*     ofstream myfile;
    myfile.open ("Results/"+name+".csv", fstream::app);
    myfile << gbest.fitness << "," << time_span.count() << endl;
    myfile.close(); */

    pthread_mutex_destroy(&mutex);
    pthread_exit(NULL);
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xf8, %rsp
movq %rsi, %rbx
callq 0x2030
movq %rax, %r15
movq 0x7ee0(%rip), %r14      # 0xafd8
leaq 0x402d(%rip), %rsi      # 0x712c
movq %r14, %rdi
callq 0x2190
movq %rax, %rdi
callq 0x20c0
andl $0x0, 0x8252(%rip)      # 0xb368
andl $0x0, 0x826b(%rip)      # 0xb388
andl $0x0, 0x8268(%rip)      # 0xb38c
movq 0x8(%rbx), %rsi
leaq -0xe8(%rbp), %rdi
leaq -0xa0(%rbp), %rdx
callq 0x3bde
leaq 0x3ff1(%rip), %rsi      # 0x7133
movq %r14, %rdi
callq 0x2190
movq %rax, %rdi
callq 0x20c0
leaq -0xc8(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
callq 0x2220
leaq 0x8224(%rip), %rsi      # 0xb390
leaq 0x8215(%rip), %rdx      # 0xb388
leaq 0x8212(%rip), %rcx      # 0xb38c
leaq 0x81e7(%rip), %r8       # 0xb368
leaq -0xc8(%rbp), %rdi
callq 0x252a
leaq -0xc8(%rbp), %rdi
callq 0x20b0
leaq -0xe8(%rbp), %r14
pushq $0x2e
popq %rsi
pushq $-0x1
popq %rdx
movq %r14, %rdi
callq 0x2330
movq %rax, %rbx
leal -0x1(%rax), %edx
pushq $0x2f
popq %rsi
movq %r14, %rdi
callq 0x2330
leal 0x1(%rax), %edx
notl %eax
addl %eax, %ebx
leaq -0x108(%rbp), %rdi
movq %r14, %rsi
movq %rbx, %rcx
callq 0x21c0
movq 0x7df9(%rip), %rdi      # 0xafd8
leaq 0x3f63(%rip), %rsi      # 0x7149
callq 0x2190
movl 0x8177(%rip), %esi      # 0xb368
movq %rax, %rdi
callq 0x22e0
movq %rax, %rdi
callq 0x20c0
movq 0x7dd0(%rip), %rdi      # 0xafd8
leaq 0x3f4f(%rip), %rsi      # 0x715e
callq 0x2190
movl 0x816e(%rip), %esi      # 0xb388
movq %rax, %rdi
callq 0x22e0
movq %rax, %rdi
callq 0x20c0
movq 0x7da7(%rip), %rdi      # 0xafd8
leaq 0x3f37(%rip), %rsi      # 0x716f
callq 0x2190
movl 0x8149(%rip), %esi      # 0xb38c
movq %rax, %rdi
callq 0x22e0
movq %rax, %rdi
callq 0x20c0
movq %r15, -0x30(%rbp)
xorl %ebx, %ebx
leaq 0x7fd0(%rip), %r14      # 0xb230
leaq 0x8129(%rip), %r15      # 0xb390
leaq -0xa0(%rbp), %r12
cmpq $0xa50, %rbx            # imm = 0xA50
je 0x32e6
movl 0x80eb(%rip), %edi      # 0xb368
movq %r14, %rsi
callq 0x26a6
movl 0x8101(%rip), %eax      # 0xb38c
movl %eax, -0xa0(%rbp)
movl 0x80f1(%rip), %eax      # 0xb388
movl %eax, -0x9c(%rbp)
andq $0x0, -0x98(%rbp)
movq 0x7f84(%rip), %rcx      # 0xb230
addq %rbx, %rcx
movq %r15, %rdi
movq %r12, %rsi
callq 0x2ad2
movq 0x7f6f(%rip), %rsi      # 0xb230
leaq (%rsi,%rbx), %rdi
addq $0x20, %rdi
addq %rbx, %rsi
callq 0x3822
movq 0x7f58(%rip), %rax      # 0xb230
movl 0x18(%rax,%rbx), %ecx
movl %ecx, 0x38(%rax,%rbx)
addq $0x58, %rbx
jmp 0x326e
movl 0x80a0(%rip), %eax      # 0xb38c
movl %eax, 0x7efe(%rip)      # 0xb1f0
movq 0x7f37(%rip), %rdi      # 0xb230
movq 0x7f38(%rip), %rsi      # 0xb238
leaq -0xdec(%rip), %rdx      # 0x251b
callq 0x5577
movq 0x7f1d(%rip), %rsi      # 0xb230
movl 0x18(%rsi), %eax
cmpl 0x7ed4(%rip), %eax      # 0xb1f0
jge 0x3330
movl %eax, 0x7ecc(%rip)      # 0xb1f0
leaq 0x7ead(%rip), %rdi      # 0xb1d8
callq 0x3822
movl $0x40033333, %eax       # imm = 0x40033333
movl %eax, 0x8035(%rip)      # 0xb370
movl %eax, 0x8033(%rip)      # 0xb374
movl $0x3f99999a, %eax       # imm = 0x3F99999A
movl %eax, 0x802c(%rip)      # 0xb378
movl $0x3f333333, 0x8026(%rip) # imm = 0x3F333333
movl %eax, 0x8010(%rip)      # 0xb36c
movl 0x8006(%rip), %ecx      # 0xb368
pushq $0x2
popq %rsi
movl %ecx, %eax
cltd
idivl %esi
cvtsi2ss %eax, %xmm0
movss %xmm0, 0x800a(%rip)     # 0xb380
pushq $-0x2
popq %rsi
movl %ecx, %eax
cltd
idivl %esi
cvtsi2ss %eax, %xmm0
movss %xmm0, 0x7ffa(%rip)     # 0xb384
leaq 0x7faf(%rip), %rdi      # 0xb340
xorl %r13d, %r13d
xorl %esi, %esi
callq 0x2260
leaq -0xa0(%rbp), %rbx
movq %rbx, %rdi
callq 0x2200
movq %rbx, %rdi
xorl %esi, %esi
callq 0x2210
leaq 0x7e95(%rip), %r14      # 0xb250
leaq -0xa8(%rbp), %r15
leaq -0x5c0(%rip), %r12      # 0x2e09
movq %r13, -0x38(%rbp)
cmpl $0x2bc, %r13d           # imm = 0x2BC
je 0x3468
movq %r14, %r13
xorl %ebx, %ebx
cmpq $0x1e, %rbx
je 0x3403
movq %r13, %rdi
leaq -0xa0(%rbp), %rsi
movq %r12, %rdx
movq %rbx, %rcx
callq 0x2320
incq %rbx
addq $0x8, %r13
jmp 0x33df
movq -0x38(%rbp), %r13
incl %r13d
leaq -0xa0(%rbp), %rdi
callq 0x22c0
xorl %ebx, %ebx
cmpq $0xf0, %rbx
je 0x3433
movq (%rbx,%r14), %rdi
movq %r15, %rsi
callq 0x2170
addq $0x8, %rbx
jmp 0x3418
movss 0x7f3d(%rip), %xmm0     # 0xb378
movaps %xmm0, %xmm1
subss 0x7f36(%rip), %xmm1     # 0xb37c
cvtsi2ss %r13d, %xmm2
divss 0x3bed(%rip), %xmm1     # 0x7040
mulss %xmm2, %xmm1
addss %xmm0, %xmm1
movss %xmm1, 0x7f09(%rip)     # 0xb36c
jmp 0x33c9
movl 0x7f1e(%rip), %eax      # 0xb38c
leaq -0x118(%rbp), %rsi
movl %eax, (%rsi)
movl 0x7f0b(%rip), %eax      # 0xb388
movl %eax, 0x4(%rsi)
andq $0x0, 0x8(%rsi)
leaq 0x7f04(%rip), %rdi      # 0xb390
leaq 0x7d45(%rip), %rcx      # 0xb1d8
callq 0x2ad2
movq 0x7b39(%rip), %rdi      # 0xafd8
leaq 0x3ce3(%rip), %rsi      # 0x7189
callq 0x2190
movl 0x7d3f(%rip), %esi      # 0xb1f0
movq %rax, %rdi
callq 0x22e0
movq %rax, %rdi
callq 0x20c0
leaq 0x7ec8(%rip), %rsi      # 0xb390
leaq -0x68(%rbp), %rdi
callq 0x3c1a
leaq -0x68(%rbp), %rdi
callq 0x2bf1
leaq -0x68(%rbp), %rdi
callq 0x3e0a
leaq 0x7cee(%rip), %rsi      # 0xb1d8
leaq -0x50(%rbp), %rdi
callq 0x3ab4
leaq -0x50(%rbp), %rdi
callq 0x28af
leaq -0x50(%rbp), %rdi
callq 0x3d24
callq 0x2030
movq %rax, %rbx
movq 0x7ac4(%rip), %rdi      # 0xafd8
leaq 0x3c8c(%rip), %rsi      # 0x71a7
callq 0x2190
subq -0x30(%rbp), %rbx
cvtsi2sd %rbx, %xmm0
divsd 0x3b1f(%rip), %xmm0     # 0x7050
movq %rax, %rdi
callq 0x2280
leaq 0x3c76(%rip), %rsi      # 0x71b6
movq %rax, %rdi
callq 0x2190
movq 0x7a89(%rip), %rdi      # 0xafd8
callq 0x20c0
leaq 0x7de5(%rip), %rdi      # 0xb340
callq 0x21e0
xorl %edi, %edi
callq 0x2300
jmp 0x358d
movq %rax, %rbx
leaq -0x50(%rbp), %rdi
callq 0x3d24
jmp 0x3590
movq %rax, %rbx
leaq -0x68(%rbp), %rdi
callq 0x3e0a
jmp 0x3590
jmp 0x358d
jmp 0x358d
jmp 0x358d
jmp 0x358d
movq %rax, %rbx
leaq -0x108(%rbp), %rdi
jmp 0x35a5
jmp 0x35ac
movq %rax, %rbx
leaq -0xc8(%rbp), %rdi
callq 0x20b0
jmp 0x35af
movq %rax, %rbx
leaq -0xe8(%rbp), %rdi
callq 0x20b0
movq %rbx, %rdi
callq 0x22f0
nop