// File: /workspace/github_cpp_makefile_star2_O1/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 %rbp
pushq %r14
pushq %rbx
subq $0x10, %rsp
movq %rdi, %rbx
leaq 0x14e0(%rdi), %r14
leaq 0x7758b(%rip), %rsi     # 0xfef02
movq %r14, %rdi
callq 0x22250
testl %eax, %eax
je 0x87a3d
leaq 0x6a61b(%rip), %rsi     # 0xf1fa9
movq %r14, %rdi
callq 0x22250
testl %eax, %eax
je 0x879b1
leaq 0xa657a(%rip), %rsi     # 0x12df1b
movq %r14, %rdi
callq 0x22250
testl %eax, %eax
jne 0x87bfc
cmpl $0x3, 0x1614(%rbx)
jb 0x87bcf
movq 0xee5cb(%rip), %r14     # 0x175f90
leaq 0x772d0(%rip), %rsi     # 0xfec9c
movl $0x35, %edx
movq %r14, %rdi
callq 0x22ab0
movl 0x13e8(%rbx), %esi
decl %esi
movq %r14, %rdi
callq 0x22650
movq %rax, %r14
leaq 0x772df(%rip), %rsi     # 0xfecd2
movl $0xc, %edx
movq %rax, %rdi
callq 0x22ab0
movl 0x161c(%rbx), %esi
movq %r14, %rdi
callq 0x22650
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x22940
movsbl %al, %esi
movq %r14, %rdi
callq 0x22050
movq %rax, %rdi
callq 0x22660
jmp 0x87bcf
cmpb $0x1, 0x16f8(%rbx)
jne 0x87bcf
movq 0x1ac8(%rbx), %rax
movsd 0x20(%rax), %xmm0
movsd 0x1d90(%rbx), %xmm1
movapd %xmm0, %xmm2
subsd %xmm1, %xmm2
andpd 0x70232(%rip), %xmm2    # 0xf7ca0
cvtss2sd 0x16a4(%rbx), %xmm3
cvtss2sd 0x16a8(%rbx), %xmm4
mulsd %xmm0, %xmm4
addsd %xmm3, %xmm4
ucomisd %xmm2, %xmm4
jbe 0x87b83
cmpl $0x3, 0x1614(%rbx)
jb 0x87adb
movq 0xee4f0(%rip), %r14     # 0x175f90
leaq 0x77176(%rip), %rsi     # 0xfec1d
movl $0x1f, %edx
movq %r14, %rdi
callq 0x22ab0
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x22940
movsbl %al, %esi
movq %r14, %rdi
callq 0x22050
movq %rax, %rdi
callq 0x22660
movl 0x1d80(%rbx), %eax
incl %eax
movl %eax, 0x1d80(%rbx)
incl 0x1d98(%rbx)
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
movl 0x1698(%rbx), %eax
xorps %xmm1, %xmm1
cvtsi2sd %rax, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x23150
ucomisd 0x8(%rsp), %xmm0
jne 0x87bcf
jp 0x87bcf
movsd 0x1d88(%rbx), %xmm0
movsd %xmm0, 0x8(%rsp)
movq %rbx, %rdi
callq 0x87dd8
movl 0x15b8(%rbx), %eax
xorpd %xmm1, %xmm1
xorpd %xmm0, %xmm0
testl %eax, %eax
je 0x87b78
movsd 0x1d88(%rbx), %xmm2
subsd 0x8(%rsp), %xmm2
mulsd %xmm2, %xmm2
leal 0x1(%rax), %edx
cmpl $0x3, %edx
movl $0x2, %ecx
cmovael %edx, %ecx
decl %ecx
addsd %xmm2, %xmm0
decl %ecx
jne 0x87b70
cmpl $0x1, %eax
je 0x87b9d
xorpd %xmm2, %xmm2
jmp 0x87ba5
movl $0x0, 0x1d80(%rbx)
ucomisd %xmm0, %xmm1
jbe 0x87bcf
movsd %xmm0, 0x1d90(%rbx)
jmp 0x87bcf
movsd 0x7076b(%rip), %xmm2    # 0xf8310
mulsd %xmm2, %xmm0
ucomisd %xmm1, %xmm0
jb 0x87bb5
sqrtsd %xmm0, %xmm0
jmp 0x87bba
callq 0x22790
xorps %xmm1, %xmm1
cvtss2sd 0x16a4(%rbx), %xmm1
ucomisd %xmm0, %xmm1
ja 0x87da7
movl 0x161c(%rbx), %eax
testl %eax, %eax
je 0x87bfc
cmpl %eax, 0x13e8(%rbx)
jbe 0x87bfc
movq 0xee3a8(%rip), %rbx     # 0x175f90
leaq 0x7707a(%rip), %rsi     # 0xfec69
movl $0x32, %edx
movq %rbx, %rdi
jmp 0x87d6d
movl 0x1d84(%rbx), %eax
cmpq %rax, 0x1680(%rbx)
jbe 0x87c60
cmpq $0x0, 0x1bf8(%rbx)
je 0x87c32
xorps %xmm0, %xmm0
cvtss2sd 0x1624(%rbx), %xmm0
movq 0x1be8(%rbx), %rax
ucomisd 0x20(%rax), %xmm0
jae 0x87d02
cmpq $0x0, 0x1ad8(%rbx)
je 0x87c59
xorps %xmm0, %xmm0
cvtss2sd 0x1624(%rbx), %xmm0
movq 0x1ac8(%rbx), %rax
ucomisd 0x20(%rax), %xmm0
jae 0x87d02
xorl %ebp, %ebp
jmp 0x87d9c
movb $0x1, %bpl
cmpl $0x3, 0x1614(%rbx)
jb 0x87d9c
movq 0xee319(%rip), %r14     # 0x175f90
leaq 0x77061(%rip), %rsi     # 0xfecdf
movl $0x24, %edx
movq %r14, %rdi
callq 0x22ab0
movl 0x1d84(%rbx), %esi
movq %r14, %rdi
callq 0x22650
movq %rax, %r14
leaq 0x77061(%rip), %rsi     # 0xfed04
movl $0x18, %edx
movq %rax, %rdi
callq 0x22ab0
movq 0x1680(%rbx), %rsi
movq %r14, %rdi
callq 0x22650
movq %rax, %rbx
leaq 0x7011e(%rip), %rsi     # 0xf7de7
movl $0x1, %edx
movq %rax, %rdi
callq 0x22ab0
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x22940
movsbl %al, %esi
movq %rbx, %rdi
callq 0x22050
movq %rax, %rdi
callq 0x22660
jmp 0x87d9c
movq 0xee287(%rip), %r14     # 0x175f90
leaq 0x7700d(%rip), %rsi     # 0xfed1d
movl $0x23, %edx
movq %r14, %rdi
callq 0x22ab0
movq 0x1ac8(%rbx), %rax
movsd 0x20(%rax), %xmm0
movq %r14, %rdi
callq 0x23060
movq %rax, %r14
leaq 0x77006(%rip), %rsi     # 0xfed41
movl $0x15, %edx
movq %rax, %rdi
callq 0x22ab0
xorps %xmm0, %xmm0
cvtss2sd 0x1624(%rbx), %xmm0
movq %r14, %rdi
callq 0x23060
movq %rax, %rbx
leaq 0x70082(%rip), %rsi     # 0xf7de7
movl $0x1, %edx
movq %rax, %rdi
callq 0x22ab0
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x22940
movsbl %al, %esi
movq %rbx, %rdi
callq 0x22050
movq %rax, %rdi
callq 0x22660
movb $0x1, %bpl
movl %ebp, %eax
addq $0x10, %rsp
popq %rbx
popq %r14
popq %rbp
retq
movb $0x1, %bpl
cmpl $0x3, 0x1614(%rbx)
jb 0x87d9c
movq 0xee1d6(%rip), %rbx     # 0x175f90
leaq 0x76e7c(%rip), %rsi     # 0xfec3d
movl $0x2b, %edx
movq %rbx, %rdi
callq 0x22ab0
movq %rbx, %rdi
callq 0x22430
jmp 0x87d9c