// File: /workspace/github_cpp_makefile_star2_O2/cssartori[P]ga-qap/src/geneticalgorithm.cpp
// Function: GeneticAlgorithm::run()
Solution GeneticAlgorithm::run(){
	/*Creates an objective function evaluator and a population creator*/
	ObjectiveFunction of(data);

	/*Creates random population as initial set*/
	std::vector<Solution> population = PopulationCreator::random(pop_size, data.n, of, generator);

	/*Local search object*/
	LocalSearch ls(data, of);

	/*Improves locally all the initial solutions*/
	for(size_t i=0;i<population.size();i++){
		population[i] = ls.all_pair_changes(population[i]);
	}
	/*Sorts population in increasing order*/
	sort(population.begin(), population.end());//, comp);
	/*Selects the best solution*/
	Solution best_solution = population[0];
	
	if(prints) printf("Best solution in generation 0:  %i\n", best_solution.fitness());
	
	/*Updates basic information attributes*/
	this->best_solution = best_solution;
	this->initial_solution = best_solution;
	this->iter_best = 0;
	
	/*Initialize basic variables of the GA*/
	size_t u = 1;
	size_t last_mutation = 0;
	int mutation_type = 1;
    size_t generation = 0;
	
	/*GA main loop*/
	while(generation < max_generations){
		generation++;
		std::vector<Solution> offspring;
		while(offspring.size() < pop_size*0.5){
			int except = -1;
			/*Tournament to select parents*/
			Solution p1 = tournament(population, k, except);
			Solution p2 = tournament(population, k, except);

			/*crossover of parents*/
			Solution c = crossover_opt(p1, p2, of);

			/*Evaluate c*/
			//c.set_fitness(of.eval(c));
			
			/*Run a limited local search on the new child*/
			c = ls.limited_iterated_search(c, data.n, generator);	

			offspring.push_back(c);
		}

		/*Sorts offspring in increasing order*/
		sort(offspring.begin(), offspring.end());//, comp);
		/*Inserts the best individuals from offspring in the population as long as they are better than the latter*/
		for(size_t i=0;i<offspring.size();i++){
			if(offspring[i] < population[pop_size-1-i])
				population[pop_size-1-i] = offspring[i];
		}
		
		/*Sorts population in increasing order*/
		sort(population.begin(), population.end());//, comp);
		
		/*In case population has converged*/
		if(population[0] >= best_solution && generation - last_mutation > 100 && generation - iter_best > 200 && mutation_type==1){ 
			/*First try the shift mutation approach*/
			for(size_t i=0;i<pop_size;i++){
				shift_mutation(population[i], u);
				population[i].set_fitness(of.eval(population[i]));
			}
			if(prints) printf("Mutated population with u = %li\n", u);

			u++;
			if(u > data.n){
				/*In case the shift mutation has not done the job, go to the second type*/
				u=1;
				mutation_type=2;
			}

			sort(population.begin(), population.end());//, comp);
			last_mutation = generation;
		}else if(population[0] >= best_solution && generation - last_mutation > 100 && generation - iter_best > 200 && mutation_type==2){
			/*The second approach executes several perturbations in the solutions*/
			if(prints) printf("Perturbing solutions...\n");

			std::uniform_int_distribution<int> rand_place (0,data.n-1);
			
			for(size_t i=0;i<pop_size;i++){
				for(size_t j=0;j<data.n*0.2;j++){
					int r = rand_place(generator);
					int s = rand_place(generator);
					while(r == s) r = rand_place(generator);

					population[i].set_fitness(of.eval_pair_change(population[i], r, s));
				
					int temp = population[i][r];
					population[i][r] = population[i][s];
					population[i][s] = temp;
				}
				
				/*Improves the solutions locally*/
				population[i] = ls.all_pair_changes(population[i]);
			}
			
			sort(population.begin(), population.end());//, comp);
			last_mutation = generation;
			mutation_type = 1;
		}
		
		/*If the new best solution is better than the current one*/
		if(population[0] < best_solution){
			/*Update the current best solution*/
			best_solution = population[0];
			this->best_solution = best_solution;
			this->iter_best = generation;
			u = 1;
			if(prints) printf("Best solution in generation %li:  %i\n", generation, best_solution.fitness());
		}
	}

	/*Finally, return the best solution found*/
	return best_solution;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x178, %rsp            # imm = 0x178
movq %rsi, %r14
movq %rdi, 0x8(%rsp)
movq (%rsi), %rsi
leaq 0x50(%rsp), %rbx
movq %rbx, %rdi
callq 0x34a4
movq (%r14), %rax
movq 0x10(%r14), %rsi
movq 0x30(%rax), %rdx
leaq 0x80(%r14), %r15
leaq 0x18(%rsp), %rdi
movq %rbx, %rcx
movq %r15, %r8
callq 0x3ad0
movq %r14, 0x30(%rsp)
movq (%r14), %rsi
leaq 0x88(%rsp), %rdi
movq %rbx, %rdx
callq 0x434c
xorl %r14d, %r14d
leaq 0x138(%rsp), %rbx
leaq 0xb8(%rsp), %r12
leaq 0x88(%rsp), %r13
xorl %ebp, %ebp
movq 0x18(%rsp), %rsi
movq 0x20(%rsp), %rax
movq %rax, %rcx
subq %rsi, %rcx
sarq $0x5, %rcx
cmpq %rcx, %rbp
jae 0x48af
addq %r14, %rsi
movq %rbx, %rdi
callq 0x423a
movq %r12, %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x4354
movq 0x18(%rsp), %rdi
addq %r14, %rdi
movq %r12, %rsi
callq 0x469e
movq %r12, %rdi
callq 0x280c
movq %rbx, %rdi
callq 0x280c
incq %rbp
addq $0x20, %r14
jmp 0x4854
movq %rsi, %rdi
movq %rax, %rsi
callq 0x581d
movq 0x18(%rsp), %rsi
movq 0x8(%rsp), %rdi
callq 0x423a
movq 0x30(%rsp), %r14
cmpb $0x1, 0x30(%r14)
jne 0x48ef
movq 0x8(%rsp), %rdi
callq 0x33d6
leaq 0x29c2(%rip), %rdi      # 0x72a8
movl %eax, %esi
xorl %eax, %eax
callq 0x2030
leaq 0x38(%r14), %rdi
movq %rdi, 0x80(%rsp)
movq 0x8(%rsp), %rbx
movq %rbx, %rsi
callq 0x46c0
leaq 0x58(%r14), %rdi
movq %rbx, %rsi
callq 0x46c0
andq $0x0, 0x78(%r14)
pushq $0x1
popq %rax
pushq $0x1
popq %rbp
movq $0x0, 0x10(%rsp)
movl %ebp, 0x48(%rsp)
movq $0x0, 0x38(%rsp)
movq %rax, 0x40(%rsp)
movq %r14, %rbx
movq 0x10(%rsp), %rax
cmpq 0x20(%rbx), %rax
jae 0x4edc
andq $0x0, 0x70(%rsp)
incq %rax
movq %rax, 0x10(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x60(%rsp)
xorl %edi, %edi
xorl %esi, %esi
leaq 0x18(%rsp), %r14
movq %rsi, %rax
subq %rdi, %rax
sarq $0x5, %rax
movq %rax, %xmm0
movq 0x26fe(%rip), %xmm2     # 0x7080
punpckldq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
movapd 0x2702(%rip), %xmm3     # 0x7090
subpd %xmm3, %xmm0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
movq 0x10(%rbx), %xmm0
punpckldq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
subpd %xmm3, %xmm0
movapd %xmm0, %xmm2
unpckhpd %xmm0, %xmm2            # xmm2 = xmm2[1],xmm0[1]
addsd %xmm0, %xmm2
mulsd 0x28c1(%rip), %xmm2     # 0x7280
ucomisd %xmm1, %xmm2
jbe 0x4ac5
orl $-0x1, 0x5c(%rsp)
movq 0x18(%rbx), %rcx
leaq 0xb8(%rsp), %rdi
movq %rbx, %rsi
movq %r14, %rdx
leaq 0x5c(%rsp), %r12
movq %r12, %r8
callq 0x4fac
movq 0x18(%rbx), %rcx
leaq 0x98(%rsp), %r13
movq %r13, %rdi
movq %rbx, %rsi
movq %r14, %rdx
movq %r12, %r8
callq 0x4fac
leaq 0xd8(%rsp), %r12
movq %r12, %rdi
movq %rbx, %rsi
leaq 0xb8(%rsp), %rdx
movq %r13, %rcx
leaq 0x50(%rsp), %r8
callq 0x50ac
leaq 0x118(%rsp), %r13
movq %r13, %rdi
movq %r12, %rsi
callq 0x423a
movq (%rbx), %rax
movl 0x30(%rax), %ecx
leaq 0x158(%rsp), %rbp
movq %rbp, %rdi
leaq 0x88(%rsp), %rsi
movq %r13, %rdx
movq %r15, %r8
callq 0x442e
leaq 0xd8(%rsp), %r12
movq %r12, %rdi
movq %rbp, %rsi
callq 0x469e
movq %rbp, %rdi
callq 0x280c
movq %r13, %rdi
callq 0x280c
leaq 0x60(%rsp), %rdi
movq %r12, %rsi
callq 0x3d36
movq %r12, %rdi
callq 0x280c
leaq 0x98(%rsp), %rdi
callq 0x280c
leaq 0xb8(%rsp), %rdi
callq 0x280c
movq 0x60(%rsp), %rdi
movq 0x68(%rsp), %rsi
jmp 0x496b
callq 0x581d
pushq $-0x20
popq %r12
xorl %r13d, %r13d
xorl %r14d, %r14d
movq 0x30(%rsp), %rbx
movq 0x60(%rsp), %rdi
movq 0x68(%rsp), %rax
subq %rdi, %rax
sarq $0x5, %rax
cmpq %rax, %r14
jae 0x4b35
addq %r13, %rdi
movq 0x10(%rbx), %rsi
shlq $0x5, %rsi
addq 0x18(%rsp), %rsi
addq %r12, %rsi
callq 0x33de
testb %al, %al
je 0x4b28
movq 0x60(%rsp), %rsi
addq %r13, %rsi
movq 0x10(%rbx), %rdi
shlq $0x5, %rdi
addq 0x18(%rsp), %rdi
addq %r12, %rdi
callq 0x46c0
incq %r14
addq $0x20, %r13
addq $-0x20, %r12
jmp 0x4ad9
movq 0x18(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x581d
movq 0x18(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x33fc
movq 0x10(%rsp), %r14
subq 0x38(%rsp), %r14
cmpq $0x65, %r14
setae %cl
andb %cl, %al
cmpb $0x1, %al
jne 0x4bd9
movq 0x10(%rsp), %rax
movq 0x30(%rsp), %rcx
subq 0x78(%rcx), %rax
cmpq $0xc9, %rax
jb 0x4bd9
cmpl $0x1, 0x48(%rsp)
jne 0x4bd9
xorl %r12d, %r12d
xorl %r13d, %r13d
movq 0x30(%rsp), %rbx
cmpq 0x10(%rbx), %r13
jae 0x4ddf
movq 0x18(%rsp), %rsi
addq %r12, %rsi
movq %rbx, %rdi
movq 0x40(%rsp), %rdx
callq 0x5554
movq 0x18(%rsp), %r14
addq %r12, %r14
leaq 0x50(%rsp), %rdi
movq %r14, %rsi
callq 0x34a8
movq %r14, %rdi
movl %eax, %esi
callq 0x33da
incq %r13
addq $0x20, %r12
jmp 0x4b92
movq 0x18(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x33fc
cmpq $0x65, %r14
setae %cl
andb %cl, %al
cmpb $0x1, %al
jne 0x4e51
movq 0x10(%rsp), %rax
movq 0x30(%rsp), %rbx
subq 0x78(%rbx), %rax
cmpq $0xc9, %rax
jb 0x4e51
cmpl $0x2, 0x48(%rsp)
jne 0x4e51
cmpb $0x1, 0x30(%rbx)
jne 0x4c30
leaq 0x26e8(%rip), %rdi      # 0x7313
callq 0x2200
movq (%rbx), %rax
movl 0x30(%rax), %eax
andl $0x0, 0x98(%rsp)
decl %eax
movl %eax, 0x9c(%rsp)
xorl %r12d, %r12d
cmpq 0x10(%rbx), %r12
jae 0x4e31
xorl %eax, %eax
movq %r12, 0x38(%rsp)
movq %rax, 0x48(%rsp)
movq %rax, %xmm0
movq 0x2413(%rip), %xmm2     # 0x7080
punpckldq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
movapd 0x2417(%rip), %xmm3     # 0x7090
subpd %xmm3, %xmm0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
movq (%rbx), %rax
movq 0x30(%rax), %xmm0
punpckldq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
subpd %xmm3, %xmm0
movapd %xmm0, %xmm2
unpckhpd %xmm0, %xmm2            # xmm2 = xmm2[1],xmm0[1]
addsd %xmm0, %xmm2
mulsd 0x25db(%rip), %xmm2     # 0x7288
ucomisd %xmm1, %xmm2
jbe 0x4d7b
leaq 0x98(%rsp), %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3cf2
movl %eax, %ebp
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3cf2
movl %eax, %r13d
movq 0x38(%rsp), %r12
cmpl %r13d, %ebp
jne 0x4cf3
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3cf2
movl %eax, %ebp
jmp 0x4cdf
shlq $0x5, %r12
movq 0x18(%rsp), %r14
addq %r12, %r14
movslq %ebp, %rdx
movslq %r13d, %rcx
leaq 0x50(%rsp), %rdi
movq %r14, %rsi
callq 0x3552
movq %r14, %rdi
movl %eax, %esi
callq 0x33da
movq 0x18(%rsp), %rdi
addq %r12, %rdi
movl %ebp, %esi
callq 0x33c0
movl (%rax), %r14d
movq 0x18(%rsp), %rdi
addq %r12, %rdi
movl %r13d, %esi
callq 0x33c0
movl (%rax), %ebx
movq 0x18(%rsp), %rdi
addq %r12, %rdi
movl %ebp, %esi
callq 0x33c0
movl %ebx, (%rax)
addq 0x18(%rsp), %r12
movq %r12, %rdi
movl %r13d, %esi
callq 0x33c0
movl %r14d, (%rax)
movq 0x48(%rsp), %rax
incq %rax
movq 0x30(%rsp), %rbx
movq 0x38(%rsp), %r12
jmp 0x4c5b
shlq $0x5, %r12
movq 0x18(%rsp), %rsi
addq %r12, %rsi
leaq 0xf8(%rsp), %r13
movq %r13, %rdi
callq 0x423a
leaq 0xb8(%rsp), %r14
movq %r14, %rdi
leaq 0x88(%rsp), %rsi
movq %r13, %rdx
callq 0x4354
addq 0x18(%rsp), %r12
movq %r12, %rdi
movq %r14, %rsi
callq 0x469e
movq %r14, %rdi
callq 0x280c
movq %r13, %rdi
callq 0x280c
movq 0x38(%rsp), %r12
incq %r12
jmp 0x4c4a
cmpb $0x0, 0x30(%rbx)
je 0x4df8
leaq 0x24e0(%rip), %rdi      # 0x72cc
movq 0x40(%rsp), %rsi
xorl %eax, %eax
callq 0x2030
movq 0x40(%rsp), %rcx
incq %rcx
movq (%rbx), %rax
cmpq 0x30(%rax), %rcx
pushq $0x1
popq %rax
cmovaq %rax, %rcx
movq %rcx, 0x40(%rsp)
seta %bl
movq 0x18(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x581d
xorl %eax, %eax
movb %bl, %al
incl %eax
movl %eax, 0x48(%rsp)
jmp 0x4e47
movq 0x18(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x581d
pushq $0x1
popq %rbp
movl %ebp, 0x48(%rsp)
movq 0x10(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0x18(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x33de
testb %al, %al
je 0x4ec8
movq 0x18(%rsp), %rsi
movq 0x8(%rsp), %rdi
callq 0x46c0
movq 0x80(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x46c0
movq 0x30(%rsp), %rax
movq 0x10(%rsp), %rcx
movq %rcx, 0x78(%rax)
cmpb $0x1, 0x30(%rax)
pushq $0x1
popq %rax
movq %rax, 0x40(%rsp)
jne 0x4ec8
movq 0x8(%rsp), %rdi
callq 0x33d6
leaq 0x243b(%rip), %rdi      # 0x72ed
movq 0x10(%rsp), %rsi
movl %eax, %edx
xorl %eax, %eax
callq 0x2030
pushq $0x1
popq %rax
movq %rax, 0x40(%rsp)
leaq 0x60(%rsp), %rdi
callq 0x3d72
movq 0x30(%rsp), %rbx
jmp 0x493d
leaq 0x18(%rsp), %rdi
callq 0x3d72
movq 0x8(%rsp), %rax
addq $0x178, %rsp            # imm = 0x178
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
jmp 0x4f8f
jmp 0x4f16
jmp 0x4f82
movq %rax, %rbx
leaq 0x138(%rsp), %rdi
jmp 0x4f94
movq %rax, %rbx
jmp 0x4f99
jmp 0x4f82
movq %rax, %rbx
leaq 0xf8(%rsp), %rdi
jmp 0x4f71
jmp 0x4f82
jmp 0x4f82
jmp 0x4f42
movq %rax, %rbx
leaq 0x118(%rsp), %rdi
callq 0x280c
jmp 0x4f45
movq %rax, %rbx
leaq 0xd8(%rsp), %rdi
callq 0x280c
jmp 0x4f57
movq %rax, %rbx
leaq 0x98(%rsp), %rdi
callq 0x280c
jmp 0x4f69
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
callq 0x280c
jmp 0x4f85
jmp 0x4f82
jmp 0x4f82
jmp 0x4f82
jmp 0x4f82
jmp 0x4f82
movq %rax, %rbx
leaq 0x60(%rsp), %rdi
callq 0x3d72
movq 0x8(%rsp), %rdi
callq 0x280c
leaq 0x18(%rsp), %rdi
callq 0x3d72
movq %rbx, %rdi
callq 0x2250
nop