// File: /workspace/github_c_makefile_star2_O2/waynebhayes[P]SAHap/src/Genome.cpp
// Function: SAHap::Genome::DynamicSchedule(double, double)
void Genome::DynamicSchedule(double pBad, double TARGET_MEC)
{
    //printf("pBad %ld %g\n", this->pBad.len, pBad);
#if SCHEDULE==RETREAT
/*
This schedule seems to be about right... up to 1500 SNPs. Then it fails.  Observations:
- There are a lot of magic numbers here. I think it may be possible to simplify. Ideas:
- it looks like maintaing a ration of about 10x as many 1% retreats as 95% retreats; automating that may help.
- the locations in time (fracTime and pBad) do NOT seem very flexible; you can play with what tolerances
you want at those times/pBad's, but if you shift the times or pBads too much, it all falls apart.
- decreasing the threshold (ie., tightening the tolerance) on the 1% retreats can reduce the 95% retreats,
but if you tighten it too much it never gets past 30% fracTime.
- having the first threhold too loose results in way to many 95% retreats. (ie complete restart)
- oddly, increasing the number of meta-iterations on the command line does not always help; then the retreats
are all mis-calibrated, and we never get past 30% fracTime. So again, something to automatically calibrate
them seems necessary.
- there doesn't seem to be much of a difference between optimizing MEC vs Possion. Poisson is a bit slower but
doesn't seem to give any better aswers.
- the dead-ends seem REALLY tight: sometimes you can still have 90% distance from ground truth even with the MEC
being less than a factor for two from the TARGE_MEC!!! That seems *really* strange. Is that even possible?
Perhaps the data is fucked up? It just seems so unlikely the MEC can be almost to the target while we're
still TOTALLY wrong compared to ground truth. For example, optimizing 2100SNP case, target was 614:
598k (93.4%,74s)  T 0.000  fA 0.004  pBad 0.001  MEC 850 ( Err_vs_truth 1955 Err_Pct 93.10% [2100 2100])
599k (93.6%,74s)  T 0.000  fA 0.000  pBad 0.001  MEC 851 ( Err_vs_truth 1954 Err_Pct 93.05% [2100 2100])
600k (93.8%,74s)  T 0.000  fA 0.000  pBad 0.001  MEC 852 ( Err_vs_truth 1956 Err_Pct 93.14% [2100 2100])
601k (93.9%,74s)  T 0.000  fA 0.000  pBad 0.001  MEC 852 ( Err_vs_truth 1956 Err_Pct 93.14% [2100 2100])
602k (94.1%,74s)  T 0.000  fA 0.001  pBad 0.001  MEC 852 ( Err_vs_truth 1954 Err_Pct 93.05% [2100 2100])
Retreat 94% from 94.0625% to 0.0625% because MEC is 852, too big by factor of 1.38762
We're only a factor of 1.387 above the target MEC and we're still 93% wrong compared to the ground truth??? WTF?

- again with ground truth... sometimes we converge to exactly the right ground truth yet the MEC is still large.
Again, how is that possible?  For example, here's a sequence of final lines to a good solution: (target was 268)
49k (61.3%,159s)  T 0.002  fA 0.009  pBad 0.011  MEC   264  ( Err_vs_truth     0 Err_Pct 0.00% [1000 1000])
50k (62.5%,159s)  T 0.002  fA 0.015  pBad 0.015  MEC   272  ( Err_vs_truth     0 Err_Pct 0.00% [1000 1000])
51k (63.7%,159s)  T 0.002  fA 0.011  pBad 0.009  MEC   260  ( Err_vs_truth     0 Err_Pct 0.00% [1000 1000])
How can the MEC continue to decrease while the Err_vs_truth remains exactly zero? No fucking way. There is a
unique solution---all the reads on the correct side. That solution has a fixed MEC. Can't have one change while
the other remain constant.
*/
    double retreat = 0.0;
    static double prev_retreat_frac;
    int num_meta_iters = this->maxIterations/META_ITER;
#define SMALL_RETREAT 0.01 // Let it grow with number of meta-iters? (0.01*(1+2*log(num_meta_iters)))
#define FULL_RETREAT 0.94 // this needs to be less than (1-(REPORT_INTERVAL/2)) from the next line
    if(curIteration % (REPORT_INTERVAL/2) == 0) {
	double factor = (double)windowMEC()/TARGET_MEC;
	// double factor = (double)pmec()/(TARGET_MEC == 0 ? 0.5 : TARGET_MEC);
	if(fracTime() - prev_retreat_frac > 2*SMALL_RETREAT &&
	    (((fracTime()>0.3||pBad<0.2) && factor > 16) ||   // 14 to 22 seems to work well
	     ((fracTime()>0.5||pBad<0.1) && factor >  8) )){  // quarter to half the above works well?
	    retreat = factor * SMALL_RETREAT / meanCoverage() * log(num_meta_iters);
	}
	if(fracTime()>FULL_RETREAT && factor > 1.3) {//pmec() != 0){
	    retreat = FULL_RETREAT;
	    ResetBuffers();
	}
	if(retreat > 0.0) {
	    cout << "Retreat " << 100*retreat << "% from " << 100 * fracTime();
	    this->curIteration -= retreat * this->maxIterations;
	    assert(this->curIteration>=0);
	    cout << "% to "  << 100 * fracTime() << "% because MEC is " << windowMEC();
	    cout << ", too big by a factor of " << factor << "(" << TARGET_MEC << 
			", " << windowTotalCoverage() << ")" << endl;
	    prev_retreat_frac = fracTime();
	}
    }
#elif SCHEDULE==Betz
    static double computedTdecay, LOWER=atof(getenv("LOWER")),
	ACCEPT_TARGET=atof(getenv("ACCEPT_TARGET")), PBAD_TARGET=atof(getenv("PBAD_TARGET"));
    if(!computedTdecay){
	computedTdecay = this->tDecay;
	printf("Betz values: LOWER %g ACCEPT_TARGET %g PBAD_TARGET %g\n",LOWER,ACCEPT_TARGET,PBAD_TARGET);
    }
    if(this->curIteration > this->fAccept.LENGTH) {
	this->tDecay = computedTdecay * (LOWER +
	    min(fabs(ACCEPT_TARGET-this->fAccept.getAverage()), fabs(PBAD_TARGET-this->pBad.getAverage())));
    }
#endif
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x30, %rsp
movq 0x3bd8(%rdi), %rax
movq 0x3be0(%rdi), %rcx
movl $0x2710, %esi           # imm = 0x2710
xorl %edx, %edx
divq %rsi
movq %rax, %r14
movl $0x1f4, %esi            # imm = 0x1F4
movq %rcx, %rax
xorl %edx, %edx
divq %rsi
testq %rdx, %rdx
jne 0x3b25
movq %rdi, %rbx
movapd %xmm0, (%rsp)
movaps %xmm1, 0x20(%rsp)
callq 0x2a88
movapd 0x20(%rsp), %xmm4
movdqu 0x3bd8(%rbx), %xmm1
movdqa 0x68e8(%rip), %xmm2     # 0xa050
pand %xmm1, %xmm2
por 0x68ec(%rip), %xmm2     # 0xa060
movapd %xmm0, %xmm5
psrlq $0x20, %xmm1
por 0x68eb(%rip), %xmm1     # 0xa070
subpd 0x68f3(%rip), %xmm1     # 0xa080
addpd %xmm2, %xmm1
shufpd $0x2, %xmm1, %xmm5      # xmm5 = xmm5[0],xmm1[1]
movapd %xmm4, %xmm0
unpcklpd %xmm1, %xmm0            # xmm0 = xmm0[0],xmm1[0]
divpd %xmm0, %xmm5
movapd %xmm5, %xmm6
unpckhpd %xmm5, %xmm6            # xmm6 = xmm6[1],xmm5[1]
movapd %xmm6, %xmm1
subsd 0xcada(%rip), %xmm1     # 0x10290
xorpd %xmm0, %xmm0
ucomisd 0x691e(%rip), %xmm1     # 0xa0e0
movapd %xmm5, 0x10(%rsp)
jbe 0x38b0
ucomisd 0x6922(%rip), %xmm5     # 0xa0f8
movapd (%rsp), %xmm7
jbe 0x3807
movsd 0x6903(%rip), %xmm1     # 0xa0e8
cmpltpd %xmm6, %xmm1
movsd 0x68fe(%rip), %xmm2     # 0xa0f0
movapd %xmm7, %xmm3
cmpltpd %xmm2, %xmm3
orpd %xmm1, %xmm3
movd %xmm3, %eax
testb $0x1, %al
jne 0x3835
movapd 0x6881(%rip), %xmm1     # 0xa090
cmpltpd %xmm5, %xmm1
movsd 0x68e4(%rip), %xmm2     # 0xa100
ucomisd %xmm7, %xmm2
movmskpd %xmm1, %eax
seta %cl
testb $0x1, %al
je 0x38b0
shrb %al
orb %al, %cl
je 0x38b0
movsd 0x68cb(%rip), %xmm0     # 0xa108
mulsd %xmm5, %xmm0
movsd %xmm0, (%rsp)
movq %rbx, %rdi
callq 0x2bd2
movsd (%rsp), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, (%rsp)
movl %r14d, %edi
callq 0x4845
movapd 0x10(%rsp), %xmm5
mulsd (%rsp), %xmm0
movdqu 0x3bd8(%rbx), %xmm1
movdqa 0x67d1(%rip), %xmm2     # 0xa050
pand %xmm1, %xmm2
por 0x67d5(%rip), %xmm2     # 0xa060
psrlq $0x20, %xmm1
por 0x67d8(%rip), %xmm1     # 0xa070
subpd 0x67e0(%rip), %xmm1     # 0xa080
addpd %xmm2, %xmm1
movapd %xmm1, %xmm6
unpckhpd %xmm1, %xmm6            # xmm6 = xmm6[1],xmm1[1]
divsd %xmm1, %xmm6
ucomisd 0x6858(%rip), %xmm5     # 0xa110
jbe 0x38d6
ucomisd 0x6856(%rip), %xmm6     # 0xa118
jbe 0x38d6
movq %rbx, %rdi
callq 0x32fe
movsd 0x6844(%rip), %xmm0     # 0xa118
jmp 0x38e4
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x3b25
movsd %xmm0, (%rsp)
movq 0xc6d8(%rip), %r14      # 0xffc8
leaq 0x6cb0(%rip), %rsi      # 0xa5a7
movq %r14, %rdi
callq 0x2230
movsd (%rsp), %xmm0
mulsd 0x6814(%rip), %xmm0     # 0xa120
movq %rax, %rdi
callq 0x23a0
leaq 0x6c95(%rip), %rsi      # 0xa5b0
movq %rax, %rdi
callq 0x2230
movdqu 0x3bd8(%rbx), %xmm1
movdqa %xmm1, %xmm0
pand 0x6719(%rip), %xmm0     # 0xa050
por 0x6721(%rip), %xmm0     # 0xa060
psrlq $0x20, %xmm1
por 0x6724(%rip), %xmm1     # 0xa070
subpd 0x672c(%rip), %xmm1     # 0xa080
addpd %xmm0, %xmm1
movapd %xmm1, %xmm0
unpckhpd %xmm1, %xmm0            # xmm0 = xmm0[1],xmm1[1]
divsd %xmm1, %xmm0
mulsd 0x67b4(%rip), %xmm0     # 0xa120
movq %rax, %rdi
callq 0x23a0
movsd 0x3bd8(%rbx), %xmm0
movsd 0x669c(%rip), %xmm1     # 0xa020
unpcklps %xmm1, %xmm0            # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x66a1(%rip), %xmm2     # 0xa030
subpd %xmm2, %xmm0
movapd %xmm0, %xmm3
unpckhpd %xmm0, %xmm3            # xmm3 = xmm3[1],xmm0[1]
addsd %xmm0, %xmm3
movsd 0x3be0(%rbx), %xmm0
unpcklps %xmm1, %xmm0            # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
subpd %xmm2, %xmm0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
mulsd (%rsp), %xmm3
subsd %xmm3, %xmm1
cvttsd2si %xmm1, %rax
movq %rax, %rcx
subsd 0x6755(%rip), %xmm1     # 0xa128
cvttsd2si %xmm1, %rdx
sarq $0x3f, %rcx
andq %rcx, %rdx
orq %rax, %rdx
movq %rdx, 0x3be0(%rbx)
leaq 0x6bc8(%rip), %rsi      # 0xa5b8
movq %r14, %rdi
callq 0x2230
movdqu 0x3bd8(%rbx), %xmm1
movdqa %xmm1, %xmm0
pand 0x6644(%rip), %xmm0     # 0xa050
por 0x664c(%rip), %xmm0     # 0xa060
psrlq $0x20, %xmm1
por 0x664f(%rip), %xmm1     # 0xa070
subpd 0x6657(%rip), %xmm1     # 0xa080
addpd %xmm0, %xmm1
movapd %xmm1, %xmm0
unpckhpd %xmm1, %xmm0            # xmm0 = xmm0[1],xmm1[1]
divsd %xmm1, %xmm0
mulsd 0x66df(%rip), %xmm0     # 0xa120
movq %rax, %rdi
callq 0x23a0
leaq 0x6b6e(%rip), %rsi      # 0xa5be
movq %rax, %rdi
callq 0x2230
movq %rax, %r15
movq %rbx, %rdi
callq 0x2a88
movq %r15, %rdi
callq 0x23a0
leaq 0x6b5e(%rip), %rsi      # 0xa5d0
movq %r14, %rdi
callq 0x2230
movq %rax, %rdi
movaps 0x10(%rsp), %xmm0
callq 0x23a0
leaq 0x6b5c(%rip), %rsi      # 0xa5ea
movq %rax, %rdi
callq 0x2230
movq %rax, %rdi
movaps 0x20(%rsp), %xmm0
callq 0x23a0
leaq 0x6b42(%rip), %rsi      # 0xa5ec
movq %rax, %rdi
callq 0x2230
movq %rax, %r14
movq %rbx, %rdi
callq 0x2c40
movq %r14, %rdi
callq 0x23a0
leaq 0x672b(%rip), %rsi      # 0xa1f7
movq %rax, %rdi
callq 0x2230
movq %rax, %rdi
callq 0x20f0
movdqu 0x3bd8(%rbx), %xmm0
movdqa 0x6564(%rip), %xmm1     # 0xa050
pand %xmm0, %xmm1
por 0x6568(%rip), %xmm1     # 0xa060
psrlq $0x20, %xmm0
por 0x656b(%rip), %xmm0     # 0xa070
subpd 0x6573(%rip), %xmm0     # 0xa080
addpd %xmm1, %xmm0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
divsd %xmm0, %xmm1
movsd %xmm1, 0xc76b(%rip)     # 0x10290
addq $0x30, %rsp
popq %rbx
popq %r14
popq %r15
retq
nop