// File: /workspace/github_cpp_makefile_star2_O2/cssartori[P]ga-qap/src/geneticalgorithm.cpp
// Function: GeneticAlgorithm::crossover_opt(Solution const&, Solution const&, ObjectiveFunction const&)
Solution GeneticAlgorithm::crossover_opt(const Solution& p1, const Solution& p2, const ObjectiveFunction& of){
	/*probability of crossover occurring*/
	std::uniform_real_distribution<double> prob(0,1);
	double pcs = prob(generator);
	if(pcs > pc){ /*if crossover does not occur, return the best parent*/
		if(p1 > p2) return p2;
		else return p1;
	}

	/*The new child*/
	std::vector<int> child(data.n, -1);
	/*Vector indicating wheter a given facility was already placed or not*/
	std::vector<bool> placed(data.n, false);	

	/*Copy equal positions from parents into child*/
	for(size_t i=0;i<data.n;i++){
		if(p1[i] == p2[i]){
			child[i] = p1[i];
			placed[p1[i]] = true;
		}
	}
	
	/*Save the equal positions stored*/
	std::vector<int> childm = child;
	std::vector<bool> placedm = placed;
	Solution *best = NULL;
	/*Tries N*0.2 times*/
    int lim = data.n*0.2;
	std::uniform_int_distribution<int> rand_place (0,data.n-1);
	
	for(int m=0;m<lim;m++){
		child = childm;
		placed = placedm;

		/*Assign the rest of the positions according to parents or randomly*/
		for(size_t i=0;i<data.n;i++){
			if(child[i] == -1){
				if(not placed[p1[i]] && not placed[p2[i]]){
					/*If none of the parents position was already placed, choose probabilistically*/
					double p = prob(generator);
					if( p < 0.5  ) child[i] = p1[i];
					else child[i] = p2[i];
				}else if(not placed[p1[i]]){
					child[i] = p1[i];
				}else if(not placed[p2[i]]){
					child[i] = p2[i];
				}else{
					/*If both positions were placed, choose another randomly*/
					int r = rand_place(generator);
					while(placed[r]) r = rand_place(generator);
					child[i] = r;
				}
			
				/*Mark this place as used*/
				placed[child[i]] = true;
			}
		}
		Solution s(child);
		s.set_fitness(of.eval(s));

		if(best == NULL){
			best = new Solution();
			*best = s;
		}else if(*best > s){
			*best = s;
		}
		
	}

	return *best;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x108, %rsp            # imm = 0x108
movq %r8, 0x38(%rsp)
movq %rcx, %r14
movq %rdx, %r12
movq %rsi, %rbx
xorpd %xmm0, %xmm0
movhpd 0x21b9(%rip), %xmm0     # xmm0 = xmm0[0],mem[0]
movq %rdi, 0x8(%rsp)
leaq 0xd0(%rsp), %rdi
movapd %xmm0, (%rdi)
leaq 0x80(%rsi), %rbp
movq %rbp, %rsi
callq 0x56b2
ucomisd 0x8(%rbx), %xmm0
jbe 0x5121
movq %r12, %rdi
movq %r14, %rsi
callq 0x33f2
testb %al, %al
je 0x549f
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
jmp 0x54aa
movq %r14, (%rsp)
movq (%rbx), %rax
movq 0x30(%rax), %rsi
leaq 0x68(%rsp), %rdx
orl $-0x1, (%rdx)
leaq 0x20(%rsp), %rdi
movq %rbx, %r14
leaq 0xa8(%rsp), %rbx
movq %rbx, %rcx
callq 0x277e
movq %r14, 0x10(%rsp)
movq (%r14), %rax
movq 0x30(%rax), %rsi
movb $0x0, (%rbx)
leaq 0x68(%rsp), %rdi
leaq 0xa8(%rsp), %rdx
leaq 0x48(%rsp), %rcx
callq 0x3c8e
xorl %ebx, %ebx
leaq 0x68(%rsp), %r14
movq %r12, %r15
movq 0x10(%rsp), %rax
movq (%rax), %rax
cmpq 0x30(%rax), %rbx
jae 0x51dc
movq %r12, %rdi
movl %ebx, %esi
callq 0x33cc
movl %eax, %r12d
movq (%rsp), %rdi
movl %ebx, %esi
callq 0x33cc
cmpl %eax, %r12d
movq %r15, %r12
jne 0x51d7
movq %r12, %rdi
movl %ebx, %esi
callq 0x33cc
movq 0x20(%rsp), %rcx
movl %eax, (%rcx,%rbx,4)
movq %r15, %r12
movq %r15, %rdi
movl %ebx, %esi
callq 0x33cc
movslq %eax, %rsi
movq %r14, %rdi
callq 0x3cfa
orq %rdx, (%rax)
incq %rbx
jmp 0x517c
leaq 0x90(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x2cde
leaq 0xa8(%rsp), %rdi
leaq 0x68(%rsp), %rsi
callq 0x56ba
movq 0x10(%rsp), %rax
movq (%rax), %rax
movq 0x30(%rax), %rax
movq %rax, %xmm0
punpckldq 0x1e67(%rip), %xmm0 # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
subpd 0x1e6f(%rip), %xmm0     # 0x7090
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
mulsd 0x2053(%rip), %xmm1     # 0x7288
cvttsd2si %xmm1, %ecx
leaq 0xe8(%rsp), %r12
andl $0x0, (%r12)
decl %eax
movl %eax, 0x4(%r12)
xorl %r14d, %r14d
testl %ecx, %ecx
cmovlel %r14d, %ecx
movl %ecx, 0x18(%rsp)
leaq 0x68(%rsp), %rbx
xorl %eax, %eax
movl %eax, 0x1c(%rsp)
cmpl 0x18(%rsp), %eax
je 0x545d
movq %r14, 0x40(%rsp)
leaq 0x20(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0x2b78
movq %rbx, %rdi
leaq 0xa8(%rsp), %rsi
callq 0x5736
xorl %r14d, %r14d
movq 0x10(%rsp), %rax
movq (%rax), %rax
cmpq 0x30(%rax), %r14
jae 0x53b6
movq 0x20(%rsp), %rax
cmpl $-0x1, (%rax,%r14,4)
jne 0x53ae
movq %r15, %rdi
movl %r14d, %esi
callq 0x33cc
movslq %eax, %rsi
movq %rbx, %rdi
callq 0x3cfa
testq %rdx, (%rax)
jne 0x52f2
movq (%rsp), %rdi
movl %r14d, %esi
callq 0x33cc
movslq %eax, %rsi
movq %rbx, %rdi
callq 0x3cfa
testq %rdx, (%rax)
je 0x5368
movq %r15, %rdi
movl %r14d, %esi
callq 0x33cc
movslq %eax, %rsi
movq %rbx, %rdi
callq 0x3cfa
movq %r15, %rdi
testq %rdx, (%rax)
je 0x535e
movq (%rsp), %rdi
movl %r14d, %esi
callq 0x33cc
movslq %eax, %rsi
movq %rbx, %rdi
callq 0x3cfa
movq (%rsp), %rdi
testq %rdx, (%rax)
je 0x535e
movq %r12, %rdi
movq %rbp, %rsi
callq 0x3cf2
movl %eax, %r13d
movslq %r13d, %rsi
movq %rbx, %rdi
callq 0x3cfa
testq %rdx, (%rax)
je 0x5397
movq %r12, %rdi
movq %rbp, %rsi
callq 0x3cf2
movl %eax, %r13d
jmp 0x533e
movl %r14d, %esi
callq 0x33cc
jmp 0x5394
leaq 0xd0(%rsp), %rdi
movq %rbp, %rsi
callq 0x56b2
movsd 0x1f00(%rip), %xmm1     # 0x7280
ucomisd %xmm0, %xmm1
movq (%rsp), %rdi
cmovaq %r15, %rdi
movl %r14d, %esi
callq 0x33cc
movl %eax, %r13d
movq 0x20(%rsp), %rax
movl %r13d, (%rax,%r14,4)
movslq %r13d, %rsi
movq %rbx, %rdi
callq 0x3cfa
orq %rdx, (%rax)
incq %r14
jmp 0x5299
leaq 0xf0(%rsp), %r14
movq %r14, %rdi
leaq 0x20(%rsp), %rsi
callq 0x2cde
leaq 0x48(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
callq 0x3380
movq %r14, %rdi
movq 0x40(%rsp), %r14
callq 0x280c
movq 0x38(%rsp), %rdi
movq %r13, %rsi
callq 0x34a8
leaq 0x48(%rsp), %rdi
movl %eax, %esi
callq 0x33da
testq %r14, %r14
je 0x5426
movq %r14, %rdi
leaq 0x48(%rsp), %rsi
callq 0x33f2
testb %al, %al
je 0x5448
movq %r14, %rdi
leaq 0x48(%rsp), %rsi
callq 0x46c0
jmp 0x5448
pushq $0x20
popq %rdi
callq 0x2170
movq %rax, %r14
movq %rax, %rdi
xorl %esi, %esi
callq 0x3344
movq %r14, %rdi
leaq 0x48(%rsp), %rsi
callq 0x46c0
leaq 0x48(%rsp), %rdi
callq 0x280c
movl 0x1c(%rsp), %eax
incl %eax
jmp 0x5261
movq 0x8(%rsp), %rdi
movq %r14, %rsi
callq 0x423a
leaq 0xa8(%rsp), %rdi
callq 0x3d62
leaq 0x90(%rsp), %rdi
callq 0x280c
leaq 0x68(%rsp), %rdi
callq 0x3d62
leaq 0x20(%rsp), %rdi
callq 0x280c
movq 0x8(%rsp), %rbx
jmp 0x54af
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x423a
movq %rbx, %rax
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x551b
movq %rax, %rbx
jmp 0x552b
jmp 0x54f5
movq %rax, %rbx
jmp 0x5542
movq %rax, %rbx
pushq $0x20
popq %rsi
movq %r14, %rdi
callq 0x2180
jmp 0x54ff
jmp 0x551b
movq %rax, %rbx
leaq 0xf0(%rsp), %rdi
jmp 0x5504
jmp 0x54f5
jmp 0x551b
movq %rax, %rbx
jmp 0x5538
jmp 0x551b
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0x280c
jmp 0x551e
jmp 0x551b
jmp 0x551b
jmp 0x551b
jmp 0x551b
jmp 0x551b
jmp 0x551b
jmp 0x551b
jmp 0x551b
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x3d62
leaq 0x90(%rsp), %rdi
callq 0x280c
leaq 0x68(%rsp), %rdi
callq 0x3d62
leaq 0x20(%rsp), %rdi
callq 0x280c
movq %rbx, %rdi
callq 0x2250