// File: 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
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
cmpl $0x3, 0x1614(%rax)
jb 0xf99d2
jmp 0xf99d2
movq -0x60(%rbp), %rdi
addq $0x14c0, %rdi           # imm = 0x14C0
addq $0x20, %rdi
leaq 0xe805a(%rip), %rsi     # 0x1e1a42
callq 0x44930
testb $0x1, %al
jne 0xf99f6
jmp 0xf9c87
movq -0x60(%rbp), %rax
testb $0x1, 0x16f8(%rax)
je 0xf9c38
movq -0x60(%rbp), %rdi
addq $0x1ab0, %rdi           # imm = 0x1AB0
callq 0x122630
movq %rax, -0x18(%rbp)
leaq -0x18(%rbp), %rdi
callq 0x122660
movq %rax, %rcx
movq -0x60(%rbp), %rax
movsd (%rcx), %xmm0
subsd 0x1d90(%rax), %xmm0
callq 0x9c8a0
movq -0x60(%rbp), %rdi
movsd %xmm0, -0x68(%rbp)
movss 0x16a4(%rdi), %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, -0x70(%rbp)
movss 0x16a8(%rdi), %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, -0x78(%rbp)
addq $0x1ab0, %rdi           # imm = 0x1AB0
callq 0x122630
movq %rax, -0x20(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x122660
movsd -0x78(%rbp), %xmm0
movsd -0x70(%rbp), %xmm2
movsd -0x68(%rbp), %xmm1
movsd (%rax), %xmm3
mulsd %xmm3, %xmm0
addsd %xmm2, %xmm0
ucomisd %xmm1, %xmm0
jbe 0xf9bc4
movq -0x60(%rbp), %rax
cmpl $0x3, 0x1614(%rax)
jb 0xf9ad4
movq 0x1db497(%rip), %rdi    # 0x2d4f50
leaq 0xe7c9d(%rip), %rsi     # 0x1e175d
callq 0x2ff50
movq %rax, %rdi
movq 0x1db4f9(%rip), %rsi    # 0x2d4fc8
callq 0x30c10
movq -0x60(%rbp), %rax
movl 0x1d80(%rax), %ecx
incl %ecx
movl %ecx, 0x1d80(%rax)
movl 0x1d98(%rax), %ecx
incl %ecx
movl %ecx, 0x1d98(%rax)
movl 0x1d80(%rax), %ecx
cvtsi2sd %rcx, %xmm0
movl 0x1698(%rax), %eax
cvtsi2sd %rax, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x28(%rbp)
movsd -0x28(%rbp), %xmm0
callq 0x2f340
ucomisd -0x28(%rbp), %xmm0
jne 0xf9bc2
jp 0xf9bc2
movq -0x60(%rbp), %rdi
movsd 0x1d88(%rdi), %xmm0
movsd %xmm0, -0x30(%rbp)
callq 0xf9f80
movq -0x60(%rbp), %rdi
movsd 0x1d88(%rdi), %xmm0
subsd -0x30(%rbp), %xmm0
movsd %xmm0, -0x80(%rbp)
callq 0x121af0
movsd -0x80(%rbp), %xmm0
movq -0x60(%rbp), %rdi
movl %eax, %esi
callq 0xf9ff0
movq -0x60(%rbp), %rax
movaps %xmm0, %xmm1
movss 0x16a4(%rax), %xmm0
cvtss2sd %xmm0, %xmm0
ucomisd %xmm1, %xmm0
jbe 0xf9bc0
movq -0x60(%rbp), %rax
cmpl $0x3, 0x1614(%rax)
jb 0xf9bb7
movq 0x1db3b4(%rip), %rdi    # 0x2d4f50
leaq 0xe7bda(%rip), %rsi     # 0x1e177d
callq 0x2ff50
movq %rax, %rdi
movq 0x1db416(%rip), %rsi    # 0x2d4fc8
callq 0x30c10
movb $0x1, -0x1(%rbp)
jmp 0xf9f72
jmp 0xf9bc2
jmp 0xf9c36
movq -0x60(%rbp), %rdi
movl $0x0, 0x1d80(%rdi)
addq $0x1ab0, %rdi           # imm = 0x1AB0
callq 0x122630
movq %rax, -0x38(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x122660
movq %rax, %rcx
movq -0x60(%rbp), %rax
movsd (%rcx), %xmm1
movsd 0x1d90(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0xf9c34
movq -0x60(%rbp), %rdi
addq $0x1ab0, %rdi           # imm = 0x1AB0
callq 0x122630
movq %rax, -0x40(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x122660
movq %rax, %rcx
movq -0x60(%rbp), %rax
movsd (%rcx), %xmm0
movsd %xmm0, 0x1d90(%rax)
jmp 0xf9c36
jmp 0xf9c38
movq -0x60(%rbp), %rax
cmpl $0x0, 0x161c(%rax)
je 0xf9c82
movq -0x60(%rbp), %rcx
movl 0x13e8(%rcx), %eax
cmpl 0x161c(%rcx), %eax
jbe 0xf9c82
movq 0x1db2f2(%rip), %rdi    # 0x2d4f50
leaq 0xe7b44(%rip), %rsi     # 0x1e17a9
callq 0x2ff50
movq %rax, %rdi
movq 0x1db354(%rip), %rsi    # 0x2d4fc8
callq 0x30c10
movb $0x1, -0x1(%rbp)
jmp 0xf9f72
jmp 0xf9d7d
movq -0x60(%rbp), %rdi
addq $0x14c0, %rdi           # imm = 0x14C0
addq $0x20, %rdi
leaq 0xda741(%rip), %rsi     # 0x1d43de
callq 0x44930
testb $0x1, %al
jne 0xf9cca
movq -0x60(%rbp), %rdi
addq $0x14c0, %rdi           # imm = 0x14C0
addq $0x20, %rdi
leaq 0x11783f(%rip), %rsi    # 0x2114fb
callq 0x44930
testb $0x1, %al
jne 0xf9cca
jmp 0xf9d7b
movq -0x60(%rbp), %rax
cmpl $0x3, 0x1614(%rax)
jb 0xf9d2f
movq 0x1db272(%rip), %rdi    # 0x2d4f50
leaq 0xe7af7(%rip), %rsi     # 0x1e17dc
callq 0x2ff50
movq %rax, %rdi
movq -0x60(%rbp), %rax
movl 0x13e8(%rax), %esi
subl $0x1, %esi
callq 0x30640
movq %rax, %rdi
leaq 0xe7b09(%rip), %rsi     # 0x1e1812
callq 0x2ff50
movq %rax, %rdi
movq -0x60(%rbp), %rax
movl 0x161c(%rax), %esi
callq 0x30640
movq %rax, %rdi
movq 0x1db29e(%rip), %rsi    # 0x2d4fc8
callq 0x30c10
movq -0x60(%rbp), %rax
cmpl $0x0, 0x161c(%rax)
je 0xf9d79
movq -0x60(%rbp), %rcx
movl 0x13e8(%rcx), %eax
cmpl 0x161c(%rcx), %eax
jbe 0xf9d79
movq 0x1db1fb(%rip), %rdi    # 0x2d4f50
leaq 0xe7a4d(%rip), %rsi     # 0x1e17a9
callq 0x2ff50
movq %rax, %rdi
movq 0x1db25d(%rip), %rsi    # 0x2d4fc8
callq 0x30c10
movb $0x1, -0x1(%rbp)
jmp 0xf9f72
jmp 0xf9d7b
jmp 0xf9d7d
movq -0x60(%rbp), %rcx
movl 0x1d84(%rcx), %eax
cmpq 0x1680(%rcx), %rax
jb 0xf9e0b
movq -0x60(%rbp), %rax
cmpl $0x3, 0x1614(%rax)
jb 0xf9e02
movq 0x1db1ac(%rip), %rdi    # 0x2d4f50
leaq 0xe7a74(%rip), %rsi     # 0x1e181f
callq 0x2ff50
movq %rax, %rdi
movq -0x60(%rbp), %rax
movl 0x1d84(%rax), %esi
callq 0x30640
movq %rax, %rdi
leaq 0xe7a78(%rip), %rsi     # 0x1e1844
callq 0x2ff50
movq %rax, %rdi
movq -0x60(%rbp), %rax
movq 0x1680(%rax), %rsi
callq 0x30cf0
movq %rax, %rdi
leaq 0xe07f9(%rip), %rsi     # 0x1da5e7
callq 0x2ff50
movq %rax, %rdi
movq 0x1db1cb(%rip), %rsi    # 0x2d4fc8
callq 0x30c10
movb $0x1, -0x1(%rbp)
jmp 0xf9f72
movq -0x60(%rbp), %rdi
addq $0x1bd0, %rdi           # imm = 0x1BD0
callq 0x122680
cmpq $0x0, %rax
je 0xf9e63
movq -0x60(%rbp), %rdi
addq $0x1bd0, %rdi           # imm = 0x1BD0
callq 0x122630
movq %rax, -0x48(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x122660
movq %rax, %rcx
movq -0x60(%rbp), %rax
movsd (%rcx), %xmm1
movss 0x1624(%rax), %xmm0
cvtss2sd %xmm0, %xmm0
movb $0x1, %al
ucomisd %xmm1, %xmm0
movb %al, -0x81(%rbp)
jae 0xf9ed1
movq -0x60(%rbp), %rdi
addq $0x1ab0, %rdi           # imm = 0x1AB0
callq 0x122680
movq %rax, %rcx
xorl %eax, %eax
cmpq $0x0, %rcx
movb %al, -0x82(%rbp)
je 0xf9ec5
movq -0x60(%rbp), %rdi
addq $0x1ab0, %rdi           # imm = 0x1AB0
callq 0x122630
movq %rax, -0x50(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x122660
movq %rax, %rcx
movq -0x60(%rbp), %rax
movsd (%rcx), %xmm1
movss 0x1624(%rax), %xmm0
cvtss2sd %xmm0, %xmm0
ucomisd %xmm1, %xmm0
setae %al
movb %al, -0x82(%rbp)
movb -0x82(%rbp), %al
movb %al, -0x81(%rbp)
movb -0x81(%rbp), %al
testb $0x1, %al
jne 0xf9ee0
jmp 0xf9f6e
movq 0x1db069(%rip), %rdi    # 0x2d4f50
leaq 0xe796f(%rip), %rsi     # 0x1e185d
callq 0x2ff50
movq -0x60(%rbp), %rdi
movq %rax, -0x90(%rbp)
addq $0x1ab0, %rdi           # imm = 0x1AB0
callq 0x122630
movq %rax, -0x58(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x122660
movq -0x90(%rbp), %rdi
movsd (%rax), %xmm0
callq 0x30710
movq %rax, %rdi
leaq 0xe7950(%rip), %rsi     # 0x1e1881
callq 0x2ff50
movq %rax, %rdi
movq -0x60(%rbp), %rax
movss 0x1624(%rax), %xmm0
callq 0x30ce0
movq %rax, %rdi
leaq 0xe0693(%rip), %rsi     # 0x1da5e7
callq 0x2ff50
movq %rax, %rdi
movq 0x1db065(%rip), %rsi    # 0x2d4fc8
callq 0x30c10
movb $0x1, -0x1(%rbp)
jmp 0xf9f72
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x90, %rsp
popq %rbp
retq