// File: /workspace/github_cpp_makefile_star2_O2/richardposner[P]BioNetFit2/src/code/Swarm.cpp
// Function: Swarm::checkStopCriteria()
bool Swarm::checkStopCriteria() {
	if (options.verbosity >= 3) {
		//cout << "Checking stop criteria. Flight count is " << flightCounter_ << " and max is " << options.maxNumSimulations << endl;
		//cout << "Fittype is " << options.fitType << endl;
	}

	if (options.fitType == "pso") {
		if (options.enhancedStop) {
			// Eq 4 from Moraes et al
			// Algorithm 1 from Moraes et al
			if (abs(particleBestFitsByFit_.begin()->first - optimum_) < options.absTolerance + (options.relTolerance * particleBestFitsByFit_.begin()->first) ) {
				if (options.verbosity >= 3) {
					cout << "Incrementing permanence counter" << endl;
				}

				++permanenceCounter_;
				++inertiaUpdateCounter_;

				double quotient = ((double)permanenceCounter_ / options.nmin);
				// Check to see if quotient is a real number
				if (floor(quotient) == quotient) {
					double oldAvgPos = weightedAvgPos_;
					updateEnhancedStop();
					if ( getEuclidianNorm(weightedAvgPos_ - oldAvgPos, this->getNumFreeParams()) < options.absTolerance ) {
						// Fit finished!

						if (options.verbosity >= 3) {
							cout << "Stopped according to enhanced stop criteria" << endl;
						}
						return true;
					}
				}
			}
			else {
				permanenceCounter_ = 0;
				if (particleBestFitsByFit_.begin()->first < optimum_) {
					optimum_ = particleBestFitsByFit_.begin()->first;
				}

			}

		}

		//cout << "RAQUEL: MAX GENERATION: " << options.maxGenerations << endl;
		if (options.maxGenerations && currentGeneration > options.maxGenerations) {

			cout << "Stopped because currentGeneration > maxGenerations" << endl;
			return true;
		}
		/*
		else if (options.nmax) {
			if (abs(particleBestFitsByFit_.begin()->first - optimum_) < options.absTolerance + (options.relTolerance * particleBestFitsByFit_.begin()->first) ) {
				if (options.verbosity >= 3) {
					cout << "Incrementing permanence counter. Optimum is " << optimum_ << " and f(g) is " << particleBestFitsByFit_.begin()->first << ". Difference is " << abs(particleBestFitsByFit_.begin()->first - optimum_) << " and conditional is " << options.absTolerance + (options.relTolerance * particleBestFitsByFit_.begin()->first) << endl;
				}

				++permanenceCounter_;
				++inertiaUpdateCounter_;

				if (permanenceCounter_ >= options.nmax) {

					if (options.verbosity >= 3) {
						cout << "Stopped according to permanence > n_max" << endl;
					}
					return true;
				}
			}
			else {
				permanenceCounter_ = 0;
				if (particleBestFitsByFit_.begin()->first < optimum_) {
					optimum_ = particleBestFitsByFit_.begin()->first;
				}
			}
		}
		 */
	}//	else if ((options.fitType == "ga" || options.fitType == "de") && options.synchronicity) {
	else if ( (options.fitType == "ga" || options.fitType == "de") ) {
		if (options.verbosity >= 3) {
			cout << "Checking if we've reached max generation. Current is " << (currentGeneration - 1) << " and max is " << options.maxGenerations << endl;
		}
		if (options.maxGenerations && currentGeneration > options.maxGenerations) {
			cout << "Stopped because currentGeneration > maxGenerations" << endl;
			return true;
		}
	}

	// If we've run more than the maximum number of simulations
	if (flightCounter_ >= options.maxNumSimulations) {
		if (options.verbosity >= 3) {
			cout << "Stopped according to flightCounter (" << flightCounter_ << ") >= maxNumSimulations (" << options.maxNumSimulations << ")" << endl;
		}
		return true;
	}

	if ( (swarmBestFits_.size() && swarmBestFits_.begin()->first <= options.minFit) || (particleBestFitsByFit_.size() && particleBestFitsByFit_.begin()->first <= options.minFit) ) {
		cout << "Stopped according to swarmBestFit (" << particleBestFitsByFit_.begin()->first << ") <= options.minFit (" << options.minFit << ")" << endl;
		return true;
	}

	// TODO: Check if all particles have converged to same solution

	/*
			// TIME
			if () {
			}
	 */
	//cout << "RAQUEL: Returning FALSE to Stop Criteria." << endl;
	return false;
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
leaq 0x14e0(%rdi), %r14
leaq 0x6a193(%rip), %rsi     # 0xdd0d2
movq %r14, %rdi
callq 0x3357b
testb %al, %al
je 0x7306a
cmpb $0x1, 0x16f8(%rbx)
jne 0x730fc
movq 0x1ac8(%rbx), %rax
movsd 0x20(%rax), %xmm0
movsd 0x1d90(%rbx), %xmm1
movapd %xmm0, %xmm2
subsd %xmm1, %xmm2
andpd 0x62c20(%rip), %xmm2    # 0xd5ba0
cvtss2sd 0x16a4(%rbx), %xmm3
cvtss2sd 0x16a8(%rbx), %xmm4
mulsd %xmm0, %xmm4
addsd %xmm3, %xmm4
ucomisd %xmm2, %xmm4
jbe 0x730e7
cmpl $0x3, 0x1614(%rbx)
jb 0x72fc6
movq 0xf2fe6(%rip), %rdi     # 0x165f98
leaq 0x69e34(%rip), %rsi     # 0xdcded
callq 0x289f0
movq %rax, %rdi
callq 0x284a0
movl 0x1d80(%rbx), %eax
incl %eax
movl %eax, 0x1d80(%rbx)
incl 0x1d98(%rbx)
cvtsi2sd %rax, %xmm0
movl 0x1698(%rbx), %eax
cvtsi2sd %rax, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, (%rsp)
callq 0x29210
ucomisd (%rsp), %xmm0
jne 0x730fc
jp 0x730fc
movsd 0x1d88(%rbx), %xmm0
movsd %xmm0, (%rsp)
movq %rbx, %rdi
callq 0x7322e
movsd 0x1d88(%rbx), %xmm0
subsd (%rsp), %xmm0
movl 0x15b8(%rbx), %esi
callq 0x73270
cvtss2sd 0x16a4(%rbx), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x730fc
movb $0x1, %al
cmpl $0x3, 0x1614(%rbx)
jb 0x73226
movq 0xf2f3a(%rip), %rdi     # 0x165f98
leaq 0x69da8(%rip), %rsi     # 0xdce0d
jmp 0x73217
leaq 0x5cf38(%rip), %rsi     # 0xcffa9
movq %r14, %rdi
callq 0x3357b
testb %al, %al
jne 0x73094
leaq 0x993d7(%rip), %rsi     # 0x10c45b
movq %r14, %rdi
callq 0x3357b
testb %al, %al
je 0x73121
cmpl $0x3, 0x1614(%rbx)
jb 0x730fc
movq 0xf2ef4(%rip), %rdi     # 0x165f98
leaq 0x69dc1(%rip), %rsi     # 0xdce6c
callq 0x289f0
movl 0x13e8(%rbx), %esi
decl %esi
movq %rax, %rdi
callq 0x286e0
leaq 0x69ddb(%rip), %rsi     # 0xdcea2
movq %rax, %rdi
callq 0x289f0
movl 0x161c(%rbx), %esi
movq %rax, %rdi
callq 0x286e0
movq %rax, %rdi
callq 0x284a0
jmp 0x730fc
andl $0x0, 0x1d80(%rbx)
ucomisd %xmm0, %xmm1
jbe 0x730fc
movsd %xmm0, 0x1d90(%rbx)
movl 0x161c(%rbx), %eax
testl %eax, %eax
je 0x73121
cmpl %eax, 0x13e8(%rbx)
jbe 0x73121
movq 0xf2e83(%rip), %rdi     # 0x165f98
leaq 0x69d1d(%rip), %rsi     # 0xdce39
jmp 0x73217
movl 0x1d84(%rbx), %eax
cmpq %rax, 0x1680(%rbx)
jbe 0x73177
cmpq $0x0, 0x1bf8(%rbx)
je 0x73150
cvtss2sd 0x1624(%rbx), %xmm0
movq 0x1be8(%rbx), %rax
ucomisd 0x20(%rax), %xmm0
jae 0x731c7
cmpq $0x0, 0x1ad8(%rbx)
je 0x73170
cvtss2sd 0x1624(%rbx), %xmm0
movq 0x1ac8(%rbx), %rax
ucomisd 0x20(%rax), %xmm0
jae 0x731c7
xorl %eax, %eax
jmp 0x73226
movb $0x1, %al
cmpl $0x3, 0x1614(%rbx)
jb 0x73226
movq 0xf2e0b(%rip), %rdi     # 0x165f98
leaq 0x69d1b(%rip), %rsi     # 0xdceaf
callq 0x289f0
movl 0x1d84(%rbx), %esi
movq %rax, %rdi
callq 0x286e0
leaq 0x69d26(%rip), %rsi     # 0xdced4
movq %rax, %rdi
callq 0x289f0
movq 0x1680(%rbx), %rsi
movq %rax, %rdi
callq 0x286e0
jmp 0x7320d
movq 0xf2dca(%rip), %rdi     # 0x165f98
leaq 0x69d18(%rip), %rsi     # 0xdceed
callq 0x289f0
movq 0x1ac8(%rbx), %rcx
movsd 0x20(%rcx), %xmm0
movq %rax, %rdi
callq 0x290f0
leaq 0x69d1c(%rip), %rsi     # 0xdcf11
movq %rax, %rdi
callq 0x289f0
movss 0x1624(%rbx), %xmm0
movq %rax, %rdi
callq 0x28780
leaq 0x62ad3(%rip), %rsi     # 0xd5ce7
movq %rax, %rdi
callq 0x289f0
movq %rax, %rdi
callq 0x284a0
movb $0x1, %al
addq $0x8, %rsp
popq %rbx
popq %r14
retq