// File: /workspace/github_cpp_makefile_star2_O3/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 0x78047(%rip), %rsi     # 0xfef72
movq %r14, %rdi
callq 0x22250
testl %eax, %eax
je 0x86ff1
leaq 0x6b047(%rip), %rsi     # 0xf1f89
movq %r14, %rdi
callq 0x22250
testl %eax, %eax
je 0x86f65
leaq 0xa6fa6(%rip), %rsi     # 0x12defb
movq %r14, %rdi
callq 0x22250
testl %eax, %eax
jne 0x871b0
cmpl $0x3, 0x1614(%rbx)
jb 0x87183
movq 0xef02f(%rip), %r14     # 0x175fa8
leaq 0x77d8c(%rip), %rsi     # 0xfed0c
movl $0x35, %edx
movq %r14, %rdi
callq 0x22ab0
movl 0x13e8(%rbx), %esi
decl %esi
movq %r14, %rdi
callq 0x22650
movq %rax, %r14
leaq 0x77d9b(%rip), %rsi     # 0xfed42
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 0x87183
cmpb $0x1, 0x16f8(%rbx)
jne 0x87183
movq 0x1ac8(%rbx), %rax
movsd 0x20(%rax), %xmm0
movsd 0x1d90(%rbx), %xmm1
movapd %xmm0, %xmm2
subsd %xmm1, %xmm2
andpd 0x70c2e(%rip), %xmm2    # 0xf7c50
cvtss2sd 0x16a4(%rbx), %xmm3
cvtss2sd 0x16a8(%rbx), %xmm4
mulsd %xmm0, %xmm4
addsd %xmm3, %xmm4
ucomisd %xmm2, %xmm4
jbe 0x87137
cmpl $0x3, 0x1614(%rbx)
jb 0x8708f
movq 0xeef54(%rip), %r14     # 0x175fa8
leaq 0x77c32(%rip), %rsi     # 0xfec8d
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 0x87183
jp 0x87183
movsd 0x1d88(%rbx), %xmm0
movsd %xmm0, 0x8(%rsp)
movq %rbx, %rdi
callq 0x8738c
movl 0x15b8(%rbx), %eax
xorpd %xmm1, %xmm1
xorpd %xmm0, %xmm0
testl %eax, %eax
je 0x8712c
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 0x87124
cmpl $0x1, %eax
je 0x87151
xorpd %xmm2, %xmm2
jmp 0x87159
movl $0x0, 0x1d80(%rbx)
ucomisd %xmm0, %xmm1
jbe 0x87183
movsd %xmm0, 0x1d90(%rbx)
jmp 0x87183
movsd 0x71197(%rip), %xmm2    # 0xf82f0
mulsd %xmm2, %xmm0
ucomisd %xmm1, %xmm0
jb 0x87169
sqrtsd %xmm0, %xmm0
jmp 0x8716e
callq 0x22790
xorps %xmm1, %xmm1
cvtss2sd 0x16a4(%rbx), %xmm1
ucomisd %xmm0, %xmm1
ja 0x8735b
movl 0x161c(%rbx), %eax
testl %eax, %eax
je 0x871b0
cmpl %eax, 0x13e8(%rbx)
jbe 0x871b0
movq 0xeee0c(%rip), %rbx     # 0x175fa8
leaq 0x77b36(%rip), %rsi     # 0xfecd9
movl $0x32, %edx
movq %rbx, %rdi
jmp 0x87321
movl 0x1d84(%rbx), %eax
cmpq %rax, 0x1680(%rbx)
jbe 0x87214
cmpq $0x0, 0x1bf8(%rbx)
je 0x871e6
xorps %xmm0, %xmm0
cvtss2sd 0x1624(%rbx), %xmm0
movq 0x1be8(%rbx), %rax
ucomisd 0x20(%rax), %xmm0
jae 0x872b6
cmpq $0x0, 0x1ad8(%rbx)
je 0x8720d
xorps %xmm0, %xmm0
cvtss2sd 0x1624(%rbx), %xmm0
movq 0x1ac8(%rbx), %rax
ucomisd 0x20(%rax), %xmm0
jae 0x872b6
xorl %ebp, %ebp
jmp 0x87350
movb $0x1, %bpl
cmpl $0x3, 0x1614(%rbx)
jb 0x87350
movq 0xeed7d(%rip), %r14     # 0x175fa8
leaq 0x77b1d(%rip), %rsi     # 0xfed4f
movl $0x24, %edx
movq %r14, %rdi
callq 0x22ab0
movl 0x1d84(%rbx), %esi
movq %r14, %rdi
callq 0x22650
movq %rax, %r14
leaq 0x77b1d(%rip), %rsi     # 0xfed74
movl $0x18, %edx
movq %rax, %rdi
callq 0x22ab0
movq 0x1680(%rbx), %rsi
movq %r14, %rdi
callq 0x22650
movq %rax, %rbx
leaq 0x70b1a(%rip), %rsi     # 0xf7d97
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 0x87350
movq 0xeeceb(%rip), %r14     # 0x175fa8
leaq 0x77ac9(%rip), %rsi     # 0xfed8d
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 0x77ac2(%rip), %rsi     # 0xfedb1
movl $0x15, %edx
movq %rax, %rdi
callq 0x22ab0
xorps %xmm0, %xmm0
cvtss2sd 0x1624(%rbx), %xmm0
movq %r14, %rdi
callq 0x23060
movq %rax, %rbx
leaq 0x70a7e(%rip), %rsi     # 0xf7d97
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 0x87350
movq 0xeec3a(%rip), %rbx     # 0x175fa8
leaq 0x77938(%rip), %rsi     # 0xfecad
movl $0x2b, %edx
movq %rbx, %rdi
callq 0x22ab0
movq %rbx, %rdi
callq 0x22430
jmp 0x87350