// File: /workspace/github_cpp_makefile_star2_O2/maramire[P]SP_PSO/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;
    
    /* Save items data */
    Item_vector items;

    /* Open Instance File */

    /* Define number of items to pack */
    int n_items = 0; 
    int strip_width = 0;
    int 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;

    /* Swarm of particles */
    Swarm swarm;

    /* 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);

    /* Declare global best particle */

    Particle gbest;
    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;
    float omega = 1.2;
    float c1 = 2.05;
    float c2 = 2.05;
    float omega_max = 1.2;
    float omega_min = 0.7;

    float velocity_max = (n_items)/2;
    float velocity_min = -(n_items)/2;
    float current_velocity = 0;


    random_device rd;
    mt19937 gen(rd());
    uniform_real_distribution<> dis(0, 1);//uniform distribution between 0 and 1

    while (iter<MAX_ITER)
    {

        iter++;
        //cout << gbest.fitness << endl;
        
        /* Update velocity and position with results */
        for (int p = 0; p < N_PARTICLES; p++)
        {
            vector<float> new_permutation(n_items);
            iota(begin(new_permutation), end(new_permutation), 1);

            for (int i = 0; i < swarm[p].permutation.size(); i++)
            {
            
                float r1 = dis(gen);
                float r2 = dis(gen);

                float pfactor = swarm[p].pbest[i] - swarm[p].permutation[i];
                float gfactor = gbest.permutation[i] - swarm[p].permutation[i];                

                current_velocity = omega*swarm[p].permutation[i] + r1*c1*pfactor + r2*c2*gfactor;

                if (current_velocity < velocity_min)
                {
                    current_velocity = velocity_min;

                }else if(current_velocity > velocity_max)
                {
                    current_velocity = velocity_max;
                }

                swarm[p].velocity[i] = current_velocity;
            
                new_permutation[i] = swarm[p].permutation[i] + swarm[p].velocity[i];
                
            }

            /* Discretize position */
            vector<float> assignments = new_permutation;
            sort(assignments.begin(),assignments.end());

            for (int i = 0; i < new_permutation.size(); i++)
            {
                for (int j = 0; j < assignments.size(); j++)
                {
                    if (new_permutation[j]==assignments[i])
                    {
                        swarm[p].permutation[i] = j+1;
                    }   
                }
            }

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

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

            if (swarm[p].fitness < swarm[p].pbest_fitness)
            {
                swarm[p].pbest = swarm[p].permutation;
                swarm[p].pbest_fitness = swarm[p].fitness;
            }
            
            if (swarm[p].pbest_fitness < gbest.fitness)
            {
                gbest.fitness = swarm[p].pbest_fitness;
                gbest.permutation = swarm[p].pbest;
            }

        }
        
        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);


    //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(); */


    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2898, %rsp           # imm = 0x2898
movq %rsi, %rbx
callq 0x2030
movq %rax, %r15
movq 0x72d9(%rip), %rdi      # 0x9fd8
leaq 0x342e(%rip), %rsi      # 0x6134
callq 0x2170
movq %rax, %rdi
callq 0x20c0
andq $0x0, -0x90(%rbp)
xorps %xmm0, %xmm0
andl $0x0, -0x44(%rbp)
movaps %xmm0, -0xa0(%rbp)
andl $0x0, -0x40(%rbp)
andl $0x0, -0x3c(%rbp)
movq 0x8(%rbx), %rsi
leaq -0x160(%rbp), %rdi
leaq -0x1538(%rbp), %rdx
callq 0x38f2
movq 0x7289(%rip), %rdi      # 0x9fd8
leaq 0x33e5(%rip), %rsi      # 0x613b
callq 0x2170
movq %rax, %rdi
callq 0x20c0
leaq -0x180(%rbp), %rdi
leaq -0x160(%rbp), %rsi
callq 0x21d0
leaq -0x180(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
leaq -0x40(%rbp), %rdx
leaq -0x3c(%rbp), %rcx
leaq -0x44(%rbp), %r8
callq 0x23fa
leaq -0x180(%rbp), %rdi
callq 0x20b0
leaq -0x160(%rbp), %rbx
pushq $0x2e
popq %rsi
pushq $-0x1
popq %rdx
movq %rbx, %rdi
callq 0x2290
movq %rax, %r14
leal -0x1(%rax), %edx
pushq $0x2f
popq %rsi
movq %rbx, %rdi
callq 0x2290
leal 0x1(%rax), %edx
notl %eax
addl %eax, %r14d
leaq -0x1a0(%rbp), %rdi
movq %rbx, %rsi
movq %r14, %rcx
callq 0x21a0
movq %r15, -0xc0(%rbp)
movq 0x71e9(%rip), %rdi      # 0x9fd8
leaq 0x335b(%rip), %rsi      # 0x6151
callq 0x2170
movl -0x44(%rbp), %ebx
movq %rax, %rdi
movl %ebx, %esi
callq 0x2260
movq %rax, %rdi
callq 0x20c0
movq 0x71c1(%rip), %rdi      # 0x9fd8
leaq 0x3348(%rip), %rsi      # 0x6166
callq 0x2170
movl -0x40(%rbp), %esi
movq %rax, %rdi
movl %esi, -0x30(%rbp)
callq 0x2260
movq %rax, %rdi
callq 0x20c0
movq 0x7198(%rip), %rdi      # 0x9fd8
leaq 0x3330(%rip), %rsi      # 0x6177
callq 0x2170
movl -0x3c(%rbp), %esi
movq %rax, %rdi
movl %esi, -0x2c(%rbp)
callq 0x2260
movq %rax, %rdi
callq 0x20c0
movslq %ebx, %rax
movq %rax, -0xc8(%rbp)
xorps %xmm0, %xmm0
leaq -0x60(%rbp), %r14
movaps %xmm0, (%r14)
andq $0x0, 0x10(%r14)
xorl %r12d, %r12d
leaq -0xa0(%rbp), %r15
leaq -0x1538(%rbp), %r13
xorl %edi, %edi
cmpq $0xa50, %r12            # imm = 0xA50
je 0x2ef6
movl %ebx, %edi
movq %r14, %rsi
callq 0x2576
movl -0x2c(%rbp), %eax
movl %eax, -0x1538(%rbp)
movl -0x30(%rbp), %eax
movl %eax, -0x1534(%rbp)
andq $0x0, -0x1530(%rbp)
movq -0x60(%rbp), %rcx
addq %r12, %rcx
movq %r15, %rdi
movq %r13, %rsi
callq 0x29a2
movq -0x60(%rbp), %rsi
leaq (%rsi,%r12), %rdi
addq $0x20, %rdi
addq %r12, %rsi
callq 0x35de
movq -0x60(%rbp), %rdi
movl 0x18(%rdi,%r12), %eax
movl %eax, 0x38(%rdi,%r12)
addq $0x58, %r12
jmp 0x2e8f
xorps %xmm0, %xmm0
andq $0x0, -0x130(%rbp)
movaps %xmm0, -0x140(%rbp)
andq $0x0, -0x110(%rbp)
movaps %xmm0, -0x120(%rbp)
andq $0x0, -0xf0(%rbp)
movaps %xmm0, -0x100(%rbp)
movl -0x2c(%rbp), %eax
movl %eax, -0x128(%rbp)
movq -0x58(%rbp), %rsi
leaq -0xb4f(%rip), %rdx      # 0x23eb
callq 0x4cfe
movq -0x60(%rbp), %rsi
movl 0x18(%rsi), %eax
cmpl -0x128(%rbp), %eax
jge 0x2f5d
leaq -0x140(%rbp), %rdi
movl %eax, 0x18(%rdi)
callq 0x35de
pushq $0x2
popq %rcx
movl %ebx, %eax
cltd
idivl %ecx
movl %eax, %r14d
pushq $-0x2
popq %rcx
movl %ebx, %eax
cltd
idivl %ecx
movl %eax, %ebx
leaq -0x1538(%rbp), %rdi
callq 0x340c
leaq -0x1538(%rbp), %rdi
callq 0x21e0
movl %eax, %esi
leaq -0x28c0(%rbp), %rdi
callq 0x4462
cvtsi2ss %r14d, %xmm0
movss %xmm0, -0x34(%rbp)
cvtsi2ss %ebx, %xmm0
movss %xmm0, -0x64(%rbp)
leaq -0x1b0(%rbp), %r13
andq $0x0, (%r13)
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, 0x8(%r13)
xorl %ebx, %ebx
movss 0x3071(%rip), %xmm0     # 0x6040
leaq -0x28c0(%rbp), %r15
movss %xmm0, -0x38(%rbp)
cmpl $0x2bc, %ebx            # imm = 0x2BC
je 0x323b
incl %ebx
xorl %r12d, %r12d
movq %rbx, -0xd0(%rbp)
cmpq $0x1e, %r12
je 0x3222
leaq -0x80(%rbp), %rdi
movq -0xc8(%rbp), %rsi
leaq -0xb8(%rbp), %rdx
callq 0x392e
movq -0x80(%rbp), %rdi
movq -0x78(%rbp), %rsi
pushq $0x1
popq %rdx
callq 0x397f
imulq $0x58, %r12, %rbx
xorl %r14d, %r14d
movq -0x60(%rbp), %rax
movq 0x8(%rax,%rbx), %rcx
subq (%rax,%rbx), %rcx
sarq $0x2, %rcx
cmpq %r14, %rcx
jbe 0x3103
movq %r13, %rdi
movq %r15, %rsi
callq 0x399a
movsd %xmm0, -0xd8(%rbp)
movq %r13, %rdi
movq %r15, %rsi
callq 0x399a
cvtsd2ss -0xd8(%rbp), %xmm2
movq -0x60(%rbp), %rax
movq (%rax,%rbx), %rcx
movq 0x20(%rax,%rbx), %rdx
movl (%rdx,%r14,4), %edx
movl (%rcx,%r14,4), %ecx
subl %ecx, %edx
cvtsi2ss %edx, %xmm3
cvtsd2ss %xmm0, %xmm1
movq -0x140(%rbp), %rdx
movl (%rdx,%r14,4), %edx
subl %ecx, %edx
cvtsi2ss %edx, %xmm4
cvtsi2ss %ecx, %xmm0
movss 0x2f9d(%rip), %xmm5     # 0x6044
mulss %xmm5, %xmm2
mulss %xmm3, %xmm2
movss -0x38(%rbp), %xmm3
mulss %xmm0, %xmm3
addss %xmm2, %xmm3
mulss %xmm5, %xmm1
mulss %xmm4, %xmm1
addss %xmm3, %xmm1
movss -0x64(%rbp), %xmm2
ucomiss %xmm1, %xmm2
ja 0x30e0
ucomiss -0x34(%rbp), %xmm1
movaps %xmm1, %xmm2
jbe 0x30e0
movss -0x34(%rbp), %xmm2
addq %rbx, %rax
movq 0x40(%rax), %rax
movss %xmm2, (%rax,%r14,4)
addss %xmm2, %xmm0
movq -0x80(%rbp), %rax
movss %xmm0, (%rax,%r14,4)
incq %r14
jmp 0x302b
leaq -0xb8(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x39a8
movq -0xb8(%rbp), %rdi
movq -0xb0(%rbp), %rsi
callq 0x58f6
movq -0x80(%rbp), %rax
movq -0x78(%rbp), %rcx
subq %rax, %rcx
sarq $0x2, %rcx
movq -0xb8(%rbp), %rdx
movq -0xb0(%rbp), %rsi
subq %rdx, %rsi
sarq $0x2, %rsi
xorl %edi, %edi
cmpq %rcx, %rdi
je 0x3183
movq -0x60(%rbp), %r8
addq %rbx, %r8
xorl %r9d, %r9d
cmpq %r9, %rsi
je 0x317e
movss (%rax,%r9,4), %xmm0
ucomiss (%rdx,%rdi,4), %xmm0
jne 0x3179
jp 0x3179
movq (%r8), %r10
leal 0x1(%r9), %r11d
movl %r11d, (%r10,%rdi,4)
incq %r9
jmp 0x315b
incq %rdi
jmp 0x314c
movl -0x2c(%rbp), %eax
movl %eax, -0xe8(%rbp)
movl -0x30(%rbp), %eax
movl %eax, -0xe4(%rbp)
andq $0x0, -0xe0(%rbp)
movq -0x60(%rbp), %rcx
addq %rbx, %rcx
leaq -0xa0(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
callq 0x29a2
movq -0x60(%rbp), %rsi
movl 0x38(%rsi,%rbx), %eax
cmpl %eax, 0x18(%rsi,%rbx)
jge 0x31dd
addq %rbx, %rsi
leaq 0x20(%rsi), %rdi
callq 0x35de
movq -0x60(%rbp), %rsi
movl 0x18(%rsi,%rbx), %eax
movl %eax, 0x38(%rsi,%rbx)
cmpl -0x128(%rbp), %eax
jge 0x31fe
movl %eax, -0x128(%rbp)
addq %rbx, %rsi
addq $0x20, %rsi
leaq -0x140(%rbp), %rdi
callq 0x35de
leaq -0xb8(%rbp), %rdi
callq 0x4424
leaq -0x80(%rbp), %rdi
callq 0x4424
incq %r12
movq -0xd0(%rbp), %rbx
jmp 0x2ff3
cvtsi2ss %ebx, %xmm0
mulss 0x2e1a(%rip), %xmm0     # 0x6048
addss 0x2e0a(%rip), %xmm0     # 0x6040
jmp 0x2fd6
leaq -0x80(%rbp), %rsi
movl -0x2c(%rbp), %eax
movl %eax, (%rsi)
movl -0x30(%rbp), %eax
movl %eax, 0x4(%rsi)
andq $0x0, 0x8(%rsi)
leaq -0xa0(%rbp), %rdi
leaq -0x140(%rbp), %rcx
callq 0x29a2
movq 0x6d6f(%rip), %rdi      # 0x9fd8
leaq 0x2f21(%rip), %rsi      # 0x6191
callq 0x2170
movl -0x128(%rbp), %esi
movq %rax, %rdi
callq 0x2260
movq %rax, %rdi
callq 0x20c0
callq 0x2030
movq %rax, %rbx
movq 0x6d3e(%rip), %rdi      # 0x9fd8
leaq 0x2f0e(%rip), %rsi      # 0x61af
callq 0x2170
movq -0xc0(%rbp), %rcx
subq %rcx, %rbx
cvtsi2sd %rbx, %xmm0
divsd 0x2d9b(%rip), %xmm0     # 0x6058
movq %rax, %rdi
callq 0x2210
leaq 0x2ef2(%rip), %rsi      # 0x61be
movq %rax, %rdi
callq 0x2170
movq 0x6cfd(%rip), %rdi      # 0x9fd8
callq 0x20c0
leaq -0x1538(%rbp), %rdi
callq 0x3822
leaq -0x140(%rbp), %rdi
callq 0x3836
leaq -0x60(%rbp), %rdi
callq 0x3a00
leaq -0x1a0(%rbp), %rdi
callq 0x20b0
leaq -0x160(%rbp), %rdi
callq 0x20b0
leaq -0xa0(%rbp), %rdi
callq 0x4cae
xorl %eax, %eax
addq $0x2898, %rsp           # imm = 0x2898
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x334e
jmp 0x3355
movq %rax, %rbx
leaq -0x180(%rbp), %rdi
jmp 0x33ba
movq %rax, %rbx
jmp 0x33cb
movq %rax, %rbx
jmp 0x339e
jmp 0x336e
movq %rax, %rbx
jmp 0x33bf
jmp 0x336e
jmp 0x336e
movq %rax, %rbx
jmp 0x33b3
jmp 0x3365
movq %rax, %rbx
jmp 0x33aa
jmp 0x3386
jmp 0x3373
movq %rax, %rbx
jmp 0x3392
movq %rax, %rbx
leaq -0xb8(%rbp), %rdi
callq 0x4424
jmp 0x3389
jmp 0x3386
movq %rax, %rbx
leaq -0x80(%rbp), %rdi
callq 0x4424
leaq -0x1538(%rbp), %rdi
callq 0x3822
leaq -0x140(%rbp), %rdi
callq 0x3836
leaq -0x60(%rbp), %rdi
callq 0x3a00
leaq -0x1a0(%rbp), %rdi
callq 0x20b0
leaq -0x160(%rbp), %rdi
callq 0x20b0
leaq -0xa0(%rbp), %rdi
callq 0x4cae
movq %rbx, %rdi
callq 0x2270
nop