This document will attempt to demonstrate the five behaviors caused
by epistasis described in the lecture.
Griffing effect
The below script will show how additive-by-additive epistasis
contributes to response to selection in an unselected population and how
this response diminishes in subsequent generations. After several
generations of crossings, response to selection is more similar to
standard breeders equation.
# Response expected from standard breeders equation
selInt(p=0.1) * varA(pop) / sqrt(varP(pop))
Trait1
Trait1 1.402761
“Conversion” of epistatic variance
This script will show how additive genetic variance can increase due
to epistatic effects. This property is due to drift, so the experiment
will be performed using populations of two different sizes. This example
comes from the AlphaSimR_Examples repository on GitHub.


Hybrid depression
This script will show how epistasis can contribute to hybrid
depression. Hybrid depression is when the mean of the hybrid is less the
two parental populations. The simulation will create favorable
conditions for this phenomenon by breeding two population separately in
the presence of strong epistasis and the absence of dominance. Favorable
epistatic combinations will build up in each population that will only
partially be transmitted to the hybrids.
founderPop = runMacs(nInd=200, nChr=10, segSites=1000,
split=100, inbred=TRUE)
SP = SimParam$
new(founderPop[1:100])$
addTraitAE(1000, relAA=1)$
setVarE(H2=1)
A = newPop(founderPop[1:100])
B = newPop(founderPop[101:200])
A = makeDH( randCross(A, 1000) )
B = makeDH( randCross(B, 1000) )
F1 = randCross2(A, B, nCrosses=10000)
# Create variable for midparent and F1 means
meanMidPar = meanF1 = numeric(20)
meanMidPar[1] = (meanG(A)+meanG(B))/2
meanF1[1] = meanG(F1)
# Reciprical recurrent selection
for(i in 2:20){
A = makeDH( selectCross(A, nInd=100, nCrosses=1000) )
B = makeDH( selectCross(B, nInd=100, nCrosses=1000) )
F1 = randCross2(A, B, nCrosses=10000)
meanMidPar[i] = (meanG(A)+meanG(B))/2
meanF1[i] = meanG(F1)
}
# Plot midparent (black) and F1 (red) means over time
plot(1:20, meanMidPar, type="l",
xlab="Generation",
ylab="Genetic Value")
lines(1:20, meanF1, col="red")

Hybrid depression
The below script will attempt (and fail) to show heterosis due to
epistatic interactions. It is similar to the above script, but uses
reciprocal recurrent selection to attempt to build favorable epistatic
interaction between the populations.
founderPop = runMacs(nInd=200, nChr=10, segSites=1000,
split=100, inbred=TRUE)
SP = SimParam$
new(founderPop[1:100])$
addTraitAE(1000, relAA=1)$
setVarE(H2=1)
A = newPop(founderPop[1:100])
B = newPop(founderPop[101:200])
A = makeDH( randCross(A, 1000) )
B = makeDH( randCross(B, 1000) )
F1 = randCross2(A, B, nCrosses=10000)
# Create variable for midparent and F1 means
meanMidPar = meanF1 = numeric(20)
meanMidPar[1] = (meanG(A)+meanG(B))/2
meanF1[1] = meanG(F1)
# Reciprocal recurrent selection using random testers
for(i in 2:20){
A = setPhenoGCA(A, testers=B[sample(1000,10)], inbred=TRUE)
B = setPhenoGCA(B, testers=A[sample(1000,10)], inbred=TRUE)
A = makeDH( selectCross(A, nInd=100, nCrosses=1000) )
B = makeDH( selectCross(B, nInd=100, nCrosses=1000) )
F1 = randCross2(A, B, nCrosses=10000)
meanMidPar[i] = (meanG(A)+meanG(B))/2
meanF1[i] = meanG(F1)
}
# Plot midparent (black) and F1 (red) means over time
plot(1:20, meanMidPar, type="l",
xlab="Generation",
ylab="Genetic Value")
lines(1:20, meanF1, col="red")

Epistatic decay
This script will show how stabilizing selection on component traits
can explain progeny means being below the midparent values for elite
parents. This script also shows how complex epistasis can be modeled
using nonlinear interactions between component traits.
# Function for modeling epistasis as one component trait under
# directional selection and the rest under stabilizing selection.
specialSelect = function(X){
Y = X[,1] - rowSums( abs(X[,-1]) )
}
founderPop = quickHaplo(nInd=1000, nChr=10, segSites=1000,
inbred=TRUE)
# Simulating multiple traits to serve as component traits
SP = SimParam$
new(founderPop)$
addTraitA(1000,
mean = c(100, rep(0,10)),
var = rep(1,11),
corA = diag(11))$
setVarE(H2 = rep(1,11))
pop = newPop(founderPop)
hist(specialSelect( gv(pop) ),
main = "Histogram of Special Trait",
xlab = "Special Trait")
# Five generations of breeding
for(i in 1:5){
pop = selectCross(pop, nInd=100, nCrosses=1000,
trait=specialSelect)
pop = makeDH(pop)
}
# Select parents and make biparental crosses
parents = selectInd(pop, nInd=3, trait=specialSelect)
progeny12 = makeCross(parents, crossPlan=cbind(1,2))
progeny12 = makeDH(progeny12, nDH=100)
progeny13 = makeCross(parents, crossPlan=cbind(1,3))
progeny13 = makeDH(progeny13, nDH=100)
progeny23 = makeCross(parents, crossPlan=cbind(2,3))
progeny23 = makeDH(progeny23, nDH=100)
# Measure GV
gvPar = specialSelect(gv(parents))
gvProg12 = specialSelect(gv(progeny12))
gvProg13 = specialSelect(gv(progeny13))
gvProg23 = specialSelect(gv(progeny23))
# Measure difference between midparent and progeny mean
mean(gvPar[1:2]) - mean(gvProg12)
mean(gvPar[c(1,3)]) - mean(gvProg13)
mean(gvPar[2:3]) - mean(gvProg23)
LS0tCnRpdGxlOiAiUXVhbnRpdGF0aXZlIEdlbmV0aWNzOiBFcGlzdGF0aWMgRWZmZWN0cyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBkb2N1bWVudCB3aWxsIGF0dGVtcHQgdG8gZGVtb25zdHJhdGUgdGhlIGZpdmUgYmVoYXZpb3JzIGNhdXNlZCBieSBlcGlzdGFzaXMgZGVzY3JpYmVkIGluIHRoZSBsZWN0dXJlLgoKCiMjIEdyaWZmaW5nIGVmZmVjdAoKVGhlIGJlbG93IHNjcmlwdCB3aWxsIHNob3cgaG93IGFkZGl0aXZlLWJ5LWFkZGl0aXZlIGVwaXN0YXNpcyBjb250cmlidXRlcyB0byByZXNwb25zZSB0byBzZWxlY3Rpb24gaW4gYW4gdW5zZWxlY3RlZCBwb3B1bGF0aW9uIGFuZCBob3cgdGhpcyByZXNwb25zZSBkaW1pbmlzaGVzIGluIHN1YnNlcXVlbnQgZ2VuZXJhdGlvbnMuIEFmdGVyIHNldmVyYWwgZ2VuZXJhdGlvbnMgb2YgY3Jvc3NpbmdzLCByZXNwb25zZSB0byBzZWxlY3Rpb24gaXMgbW9yZSBzaW1pbGFyIHRvIHN0YW5kYXJkIGJyZWVkZXJzIGVxdWF0aW9uLgoKYGBge3J9CmxpYnJhcnkoQWxwaGFTaW1SKQoKZm91bmRlclBvcCA9IHF1aWNrSGFwbG8obkluZD0xMDAwLCBuQ2hyPTEwLCBzZWdTaXRlcz0xMDAwKQoKIyBTZXR0aW5nIGEgdHJhaXQgd2l0aCBzdHJvbmcgZXBpc3Rhc2lzClNQID0gU2ltUGFyYW0kCiAgbmV3KGZvdW5kZXJQb3ApJAogIGFkZFRyYWl0QUUoMTAwMCwgcmVsQUE9MSkkCiAgc2V0VmFyRShIMj0xKQoKcG9wID0gbmV3UG9wKGZvdW5kZXJQb3ApCgp2YXJBKHBvcCkKdmFyQUEocG9wKQoKcG9wMiA9IHNlbGVjdENyb3NzKHBvcCwgbkluZD0xMDAsIG5Dcm9zc2VzPTEwMDApCgojIE9ic2VydmVkIHJlc3BvbnNlIHRvIHNlbGVjdGlvbgptZWFuRyhwb3AyKSAtIG1lYW5HKHBvcCkKCiMgUmVzcG9uc2UgZXhwZWN0ZWQgZnJvbSBzdGFuZGFyZCBicmVlZGVycyBlcXVhdGlvbgpzZWxJbnQocD0wLjEpICogdmFyQShwb3ApIC8gc3FydCh2YXJQKHBvcCkpCgojIFJlc3BvbnNlIGV4cGVjdGVkIGZyb20gdGhlIEdyaWZmaW5nIGVmZmVjdCBhbmQgbm8gcHJpb3Igc2VsZWN0aW9uCnNlbEludChwPTAuMSkgKiAodmFyQShwb3ApICsgMC41KnZhckFBKHBvcCkpIC8gc3FydCh2YXJQKHBvcCkpCgojIFJlcGVhdCBtZWFzdXJlbWVudCBhZnRlciBtdWx0aXBsZSByb3VuZHMgb2Ygc2VsZWN0aW9uCmZvcihpIGluIDE6MTApewogIHBvcCA9IHNlbGVjdENyb3NzKHBvcCwgbkluZD0xMDAsIG5Dcm9zc2VzPTEwMDApCn0KCnBvcDIgPSBzZWxlY3RDcm9zcyhwb3AsIG5JbmQ9MTAwLCBuQ3Jvc3Nlcz0xMDAwKQoKIyBPYnNlcnZlZCByZXNwb25zZSB0byBzZWxlY3Rpb24KbWVhbkcocG9wMikgLSBtZWFuRyhwb3ApCgojIFJlc3BvbnNlIGV4cGVjdGVkIGZyb20gc3RhbmRhcmQgYnJlZWRlcnMgZXF1YXRpb24gLSBvYnNlcnZlZCByZXNwb25zZSBtb3JlIHNpbWlsYXIgdG8gdGhpcwpzZWxJbnQocD0wLjEpICogdmFyQShwb3ApIC8gc3FydCh2YXJQKHBvcCkpCgojIFJlc3BvbnNlIGV4cGVjdGVkIGZyb20gdGhlIEdyaWZmaW5nIGVmZmVjdCBhbmQgbm8gcHJpb3Igc2VsZWN0aW9uCnNlbEludChwPTAuMSkgKiAodmFyQShwb3ApICsgMC41KnZhckFBKHBvcCkpIC8gc3FydCh2YXJQKHBvcCkpCmBgYAoKIyMgIkNvbnZlcnNpb24iIG9mIGVwaXN0YXRpYyB2YXJpYW5jZQoKVGhpcyBzY3JpcHQgd2lsbCBzaG93IGhvdyBhZGRpdGl2ZSBnZW5ldGljIHZhcmlhbmNlIGNhbiBpbmNyZWFzZSBkdWUgdG8gZXBpc3RhdGljIGVmZmVjdHMuIFRoaXMgcHJvcGVydHkgaXMgZHVlIHRvIGRyaWZ0LCBzbyB0aGUgZXhwZXJpbWVudCB3aWxsIGJlIHBlcmZvcm1lZCB1c2luZyBwb3B1bGF0aW9ucyBvZiB0d28gZGlmZmVyZW50IHNpemVzLiBUaGlzIGV4YW1wbGUgY29tZXMgZnJvbSB0aGUgQWxwaGFTaW1SX0V4YW1wbGVzIHJlcG9zaXRvcnkgb24gR2l0SHViLgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCiMjIFVzZXIgc2V0IHZhcmlhbmNlcwojIFZhckEgPSAxLCBhbHdheXMKVmFyRCA9IDEgClZhckFBID0gMQpWYXJFID0gMQpuID0gMTAwMCAjIFBvcHVsYXRpb24gc2l6ZSwgbXVzdCBiZSBkaXZpc2libGUgYnkgMTAKIyBOb3RlIHRoYXQgY29udmVyc2lvbiBpcyBkdWUgdG8gZHJpZnQsIHNvIGl0IG9jY3VycwojIHNvb25lciBpbiBzbWFsbGVyIHBvcHVsYXRpb25zCgojIyBTaW11bGF0aW9uCmZvdW5kZXJQb3AgPSBxdWlja0hhcGxvKG5JbmQ9bixuQ2hyPTEwLHNlZ1NpdGVzPTEwMCkKClNQID0gU2ltUGFyYW0kCiAgbmV3KGZvdW5kZXJQb3ApJAogIGFkZFRyYWl0QURFKDEwMCwgdmFyREQ9VmFyRCoyLCByZWxBQT1WYXJBQSkkCiAgc2V0VmFyRSh2YXJFPVZhckUpCgpwb3AgPSBuZXdQb3AoZm91bmRlclBvcCkKTUVBTiA9IFZBUkcgPSBWQVJBID0gVkFSRCA9IFZBUkFBID0gbnVtZXJpYygxMDEpCgp0bXAgPSBnZW5QYXJhbShwb3ApCk1FQU5bMV0gPSB0bXAkbXUKVkFSR1sxXSA9IHRtcCR2YXJHClZBUkFbMV0gPSB0bXAkdmFyQQpWQVJEWzFdID0gdG1wJHZhckQKVkFSQUFbMV0gPSB0bXAkdmFyQUEKCmZvcihpIGluIDI6MTAxKXsKICBwb3AgPSBzZWxlY3RDcm9zcyhwb3AsbiowLjEsbkNyb3NzZXM9bikKICB0bXAgPSBnZW5QYXJhbShwb3ApCiAgTUVBTltpXSA9IHRtcCRtdQogIFZBUkdbaV0gPSB0bXAkdmFyRwogIFZBUkFbaV0gPSB0bXAkdmFyQQogIFZBUkRbaV0gPSB0bXAkdmFyRAogIFZBUkFBW2ldID0gdG1wJHZhckFBCn0KCmRmID0gZGF0YS5mcmFtZShDeWNsZT1yZXAoMDoxMDAsNCksCiAgICAgICAgICAgICAgICBTb3VyY2U9cmVwKGMoIlZnIiwiVmEiLCJWZCIsIlZhYSIpLGVhY2g9MTAxKSwKICAgICAgICAgICAgICAgIFZhcmlhbmNlPWMoVkFSRyxWQVJBLFZBUkQsVkFSQUEpKQoKZ2dwbG90KGRmLGFlcyh4PUN5Y2xlLCB5PVZhcmlhbmNlLCBjb2xvcj1Tb3VyY2UpKSsKICBnZW9tX2xpbmUobGluZXdpZHRoPTEpKwogIGd1aWRlcyhhbHBoYT0ibm9uZSIpKwogIHRoZW1lX2J3KCkKCmRmMiA9IGRhdGEuZnJhbWUoQ3ljbGU9MDoxMDAsCiAgICAgICAgICAgICAgICAgTWVhbj1NRUFOKQoKZ2dwbG90KGRmMixhZXMoeD1DeWNsZSx5PU1lYW4pKSsKICBnZW9tX2xpbmUobGluZXdpZHRoPTEpKwogIGd1aWRlcyhhbHBoYT0ibm9uZSIpKwogIHRoZW1lX2J3KCkKCgojIyMgUmVydW5uaW5nIHRoZSBzaW11bGF0aW9uIHdpdGggYSBzbWFsbGVyIHBvcHVsYXRpb24KCiMjIFVzZXIgc2V0IHZhcmlhbmNlcwojIFZhckEgPSAxLCBhbHdheXMKVmFyRCA9IDEgClZhckFBID0gMQpWYXJFID0gMQpuID0gMTAwICMgUG9wdWxhdGlvbiBzaXplLCBtdXN0IGJlIGRpdmlzaWJsZSBieSAxMAojIE5vdGUgdGhhdCBjb252ZXJzaW9uIGlzIGR1ZSB0byBkcmlmdCwgc28gaXQgb2NjdXJzCiMgc29vbmVyIGluIHNtYWxsZXIgcG9wdWxhdGlvbnMKCiMjIFNpbXVsYXRpb24KZm91bmRlclBvcCA9IHF1aWNrSGFwbG8obkluZD1uLG5DaHI9MTAsc2VnU2l0ZXM9MTAwKQoKU1AgPSBTaW1QYXJhbSQKICBuZXcoZm91bmRlclBvcCkkCiAgYWRkVHJhaXRBREUoMTAwLCB2YXJERD1WYXJEKjIsIHJlbEFBPVZhckFBKSQKICBzZXRWYXJFKHZhckU9VmFyRSkKCnBvcCA9IG5ld1BvcChmb3VuZGVyUG9wKQpNRUFOID0gVkFSRyA9IFZBUkEgPSBWQVJEID0gVkFSQUEgPSBudW1lcmljKDEwMSkKCnRtcCA9IGdlblBhcmFtKHBvcCkKTUVBTlsxXSA9IHRtcCRtdQpWQVJHWzFdID0gdG1wJHZhckcKVkFSQVsxXSA9IHRtcCR2YXJBClZBUkRbMV0gPSB0bXAkdmFyRApWQVJBQVsxXSA9IHRtcCR2YXJBQQoKZm9yKGkgaW4gMjoxMDEpewogIHBvcCA9IHNlbGVjdENyb3NzKHBvcCxuKjAuMSxuQ3Jvc3Nlcz1uKQogIHRtcCA9IGdlblBhcmFtKHBvcCkKICBNRUFOW2ldID0gdG1wJG11CiAgVkFSR1tpXSA9IHRtcCR2YXJHCiAgVkFSQVtpXSA9IHRtcCR2YXJBCiAgVkFSRFtpXSA9IHRtcCR2YXJECiAgVkFSQUFbaV0gPSB0bXAkdmFyQUEKfQoKZGYgPSBkYXRhLmZyYW1lKEN5Y2xlPXJlcCgwOjEwMCw0KSwKICAgICAgICAgICAgICAgIFNvdXJjZT1yZXAoYygiVmciLCJWYSIsIlZkIiwiVmFhIiksZWFjaD0xMDEpLAogICAgICAgICAgICAgICAgVmFyaWFuY2U9YyhWQVJHLFZBUkEsVkFSRCxWQVJBQSkpCgpnZ3Bsb3QoZGYsYWVzKHg9Q3ljbGUsIHk9VmFyaWFuY2UsIGNvbG9yPVNvdXJjZSkpKwogIGdlb21fbGluZShsaW5ld2lkdGg9MSkrCiAgZ3VpZGVzKGFscGhhPSJub25lIikrCiAgdGhlbWVfYncoKQoKZGYyID0gZGF0YS5mcmFtZShDeWNsZT0wOjEwMCwKICAgICAgICAgICAgICAgICBNZWFuPU1FQU4pCgpnZ3Bsb3QoZGYyLGFlcyh4PUN5Y2xlLHk9TWVhbikpKwogIGdlb21fbGluZShsaW5ld2lkdGg9MSkrCiAgZ3VpZGVzKGFscGhhPSJub25lIikrCiAgdGhlbWVfYncoKQpgYGAKCgojIyBIeWJyaWQgZGVwcmVzc2lvbgoKVGhpcyBzY3JpcHQgd2lsbCBzaG93IGhvdyBlcGlzdGFzaXMgY2FuIGNvbnRyaWJ1dGUgdG8gaHlicmlkIGRlcHJlc3Npb24uIEh5YnJpZCBkZXByZXNzaW9uIGlzIHdoZW4gdGhlIG1lYW4gb2YgdGhlIGh5YnJpZCBpcyBsZXNzIHRoZSB0d28gcGFyZW50YWwgcG9wdWxhdGlvbnMuIFRoZSBzaW11bGF0aW9uIHdpbGwgY3JlYXRlIGZhdm9yYWJsZSBjb25kaXRpb25zIGZvciB0aGlzIHBoZW5vbWVub24gYnkgYnJlZWRpbmcgdHdvIHBvcHVsYXRpb24gc2VwYXJhdGVseSBpbiB0aGUgcHJlc2VuY2Ugb2Ygc3Ryb25nIGVwaXN0YXNpcyBhbmQgdGhlIGFic2VuY2Ugb2YgZG9taW5hbmNlLiBGYXZvcmFibGUgZXBpc3RhdGljIGNvbWJpbmF0aW9ucyB3aWxsIGJ1aWxkIHVwIGluIGVhY2ggcG9wdWxhdGlvbiB0aGF0IHdpbGwgb25seSBwYXJ0aWFsbHkgYmUgdHJhbnNtaXR0ZWQgdG8gdGhlIGh5YnJpZHMuCgoKYGBge3J9CmZvdW5kZXJQb3AgPSBydW5NYWNzKG5JbmQ9MjAwLCBuQ2hyPTEwLCBzZWdTaXRlcz0xMDAwLAogICAgICAgICAgICAgICAgICAgICBzcGxpdD0xMDAsIGluYnJlZD1UUlVFKQoKU1AgPSBTaW1QYXJhbSQKICBuZXcoZm91bmRlclBvcFsxOjEwMF0pJAogIGFkZFRyYWl0QUUoMTAwMCwgcmVsQUE9MSkkCiAgc2V0VmFyRShIMj0xKQoKQSA9IG5ld1BvcChmb3VuZGVyUG9wWzE6MTAwXSkKQiA9IG5ld1BvcChmb3VuZGVyUG9wWzEwMToyMDBdKQoKQSA9IG1ha2VESCggcmFuZENyb3NzKEEsIDEwMDApICkKQiA9IG1ha2VESCggcmFuZENyb3NzKEIsIDEwMDApICkKRjEgPSByYW5kQ3Jvc3MyKEEsIEIsIG5Dcm9zc2VzPTEwMDAwKQoKIyBDcmVhdGUgdmFyaWFibGUgZm9yIG1pZHBhcmVudCBhbmQgRjEgbWVhbnMKbWVhbk1pZFBhciA9IG1lYW5GMSA9IG51bWVyaWMoMjApCgptZWFuTWlkUGFyWzFdID0gKG1lYW5HKEEpK21lYW5HKEIpKS8yCm1lYW5GMVsxXSA9IG1lYW5HKEYxKQoKIyBSZWNpcHJpY2FsIHJlY3VycmVudCBzZWxlY3Rpb24KZm9yKGkgaW4gMjoyMCl7CiAgQSA9IG1ha2VESCggc2VsZWN0Q3Jvc3MoQSwgbkluZD0xMDAsIG5Dcm9zc2VzPTEwMDApICkKICBCID0gbWFrZURIKCBzZWxlY3RDcm9zcyhCLCBuSW5kPTEwMCwgbkNyb3NzZXM9MTAwMCkgKQogIEYxID0gcmFuZENyb3NzMihBLCBCLCBuQ3Jvc3Nlcz0xMDAwMCkKICAKICBtZWFuTWlkUGFyW2ldID0gKG1lYW5HKEEpK21lYW5HKEIpKS8yCiAgbWVhbkYxW2ldID0gbWVhbkcoRjEpCn0KCiMgUGxvdCBtaWRwYXJlbnQgKGJsYWNrKSBhbmQgRjEgKHJlZCkgbWVhbnMgb3ZlciB0aW1lCnBsb3QoMToyMCwgbWVhbk1pZFBhciwgdHlwZT0ibCIsCiAgICAgeGxhYj0iR2VuZXJhdGlvbiIsCiAgICAgeWxhYj0iR2VuZXRpYyBWYWx1ZSIpCmxpbmVzKDE6MjAsIG1lYW5GMSwgY29sPSJyZWQiKQpgYGAKCgojIyBIeWJyaWQgZGVwcmVzc2lvbgoKVGhlIGJlbG93IHNjcmlwdCB3aWxsIGF0dGVtcHQgKGFuZCBmYWlsKSB0byBzaG93IGhldGVyb3NpcyBkdWUgdG8gZXBpc3RhdGljIGludGVyYWN0aW9ucy4gSXQgaXMgc2ltaWxhciB0byB0aGUgYWJvdmUgc2NyaXB0LCBidXQgdXNlcyByZWNpcHJvY2FsIHJlY3VycmVudCBzZWxlY3Rpb24gdG8gYXR0ZW1wdCB0byBidWlsZCBmYXZvcmFibGUgZXBpc3RhdGljIGludGVyYWN0aW9uIGJldHdlZW4gdGhlIHBvcHVsYXRpb25zLgoKYGBge3J9CmZvdW5kZXJQb3AgPSBydW5NYWNzKG5JbmQ9MjAwLCBuQ2hyPTEwLCBzZWdTaXRlcz0xMDAwLAogICAgICAgICAgICAgICAgICAgICBzcGxpdD0xMDAsIGluYnJlZD1UUlVFKQoKU1AgPSBTaW1QYXJhbSQKICBuZXcoZm91bmRlclBvcFsxOjEwMF0pJAogIGFkZFRyYWl0QUUoMTAwMCwgcmVsQUE9MSkkCiAgc2V0VmFyRShIMj0xKQoKQSA9IG5ld1BvcChmb3VuZGVyUG9wWzE6MTAwXSkKQiA9IG5ld1BvcChmb3VuZGVyUG9wWzEwMToyMDBdKQoKQSA9IG1ha2VESCggcmFuZENyb3NzKEEsIDEwMDApICkKQiA9IG1ha2VESCggcmFuZENyb3NzKEIsIDEwMDApICkKRjEgPSByYW5kQ3Jvc3MyKEEsIEIsIG5Dcm9zc2VzPTEwMDAwKQoKIyBDcmVhdGUgdmFyaWFibGUgZm9yIG1pZHBhcmVudCBhbmQgRjEgbWVhbnMKbWVhbk1pZFBhciA9IG1lYW5GMSA9IG51bWVyaWMoMjApCgptZWFuTWlkUGFyWzFdID0gKG1lYW5HKEEpK21lYW5HKEIpKS8yCm1lYW5GMVsxXSA9IG1lYW5HKEYxKQoKIyBSZWNpcHJvY2FsIHJlY3VycmVudCBzZWxlY3Rpb24gdXNpbmcgcmFuZG9tIHRlc3RlcnMKZm9yKGkgaW4gMjoyMCl7CiAgQSA9IHNldFBoZW5vR0NBKEEsIHRlc3RlcnM9QltzYW1wbGUoMTAwMCwxMCldLCBpbmJyZWQ9VFJVRSkKICBCID0gc2V0UGhlbm9HQ0EoQiwgdGVzdGVycz1BW3NhbXBsZSgxMDAwLDEwKV0sIGluYnJlZD1UUlVFKQogIAogIEEgPSBtYWtlREgoIHNlbGVjdENyb3NzKEEsIG5JbmQ9MTAwLCBuQ3Jvc3Nlcz0xMDAwKSApCiAgQiA9IG1ha2VESCggc2VsZWN0Q3Jvc3MoQiwgbkluZD0xMDAsIG5Dcm9zc2VzPTEwMDApICkKICBGMSA9IHJhbmRDcm9zczIoQSwgQiwgbkNyb3NzZXM9MTAwMDApCiAgCiAgbWVhbk1pZFBhcltpXSA9IChtZWFuRyhBKSttZWFuRyhCKSkvMgogIG1lYW5GMVtpXSA9IG1lYW5HKEYxKQp9CgojIFBsb3QgbWlkcGFyZW50IChibGFjaykgYW5kIEYxIChyZWQpIG1lYW5zIG92ZXIgdGltZQpwbG90KDE6MjAsIG1lYW5NaWRQYXIsIHR5cGU9ImwiLAogICAgIHhsYWI9IkdlbmVyYXRpb24iLAogICAgIHlsYWI9IkdlbmV0aWMgVmFsdWUiKQpsaW5lcygxOjIwLCBtZWFuRjEsIGNvbD0icmVkIikKYGBgCgojIyBFcGlzdGF0aWMgZGVjYXkKClRoaXMgc2NyaXB0IHdpbGwgc2hvdyBob3cgc3RhYmlsaXppbmcgc2VsZWN0aW9uIG9uIGNvbXBvbmVudCB0cmFpdHMgY2FuIGV4cGxhaW4gcHJvZ2VueSBtZWFucyBiZWluZyBiZWxvdyB0aGUgbWlkcGFyZW50IHZhbHVlcyBmb3IgZWxpdGUgcGFyZW50cy4gVGhpcyBzY3JpcHQgYWxzbyBzaG93cyBob3cgY29tcGxleCBlcGlzdGFzaXMgY2FuIGJlIG1vZGVsZWQgdXNpbmcgbm9ubGluZWFyIGludGVyYWN0aW9ucyBiZXR3ZWVuIGNvbXBvbmVudCB0cmFpdHMuCgoKCmBgYHtyfQojIEZ1bmN0aW9uIGZvciBtb2RlbGluZyBlcGlzdGFzaXMgYXMgb25lIGNvbXBvbmVudCB0cmFpdCB1bmRlcgojIGRpcmVjdGlvbmFsIHNlbGVjdGlvbiBhbmQgdGhlIHJlc3QgdW5kZXIgc3RhYmlsaXppbmcgc2VsZWN0aW9uLgpzcGVjaWFsU2VsZWN0ID0gZnVuY3Rpb24oWCl7CiAgWSA9IFhbLDFdIC0gcm93U3VtcyggYWJzKFhbLC0xXSkgKQp9Cgpmb3VuZGVyUG9wID0gcXVpY2tIYXBsbyhuSW5kPTEwMDAsIG5DaHI9MTAsIHNlZ1NpdGVzPTEwMDAsIAogICAgICAgICAgICAgICAgICAgICAgICBpbmJyZWQ9VFJVRSkKCiMgU2ltdWxhdGluZyBtdWx0aXBsZSB0cmFpdHMgdG8gc2VydmUgYXMgY29tcG9uZW50IHRyYWl0cwpTUCA9IFNpbVBhcmFtJAogIG5ldyhmb3VuZGVyUG9wKSQKICBhZGRUcmFpdEEoMTAwMCwgCiAgICAgICAgICAgIG1lYW4gPSBjKDEwMCwgcmVwKDAsMTApKSwKICAgICAgICAgICAgdmFyID0gcmVwKDEsMTEpLAogICAgICAgICAgICBjb3JBID0gZGlhZygxMSkpJAogIHNldFZhckUoSDIgPSByZXAoMSwxMSkpCgpwb3AgPSBuZXdQb3AoZm91bmRlclBvcCkKCmhpc3Qoc3BlY2lhbFNlbGVjdCggZ3YocG9wKSApLAogICAgIG1haW4gPSAiSGlzdG9ncmFtIG9mIFNwZWNpYWwgVHJhaXQiLAogICAgIHhsYWIgPSAiU3BlY2lhbCBUcmFpdCIpCgojIEZpdmUgZ2VuZXJhdGlvbnMgb2YgYnJlZWRpbmcKZm9yKGkgaW4gMTo1KXsKICBwb3AgPSBzZWxlY3RDcm9zcyhwb3AsIG5JbmQ9MTAwLCBuQ3Jvc3Nlcz0xMDAwLAogICAgICAgICAgICAgICAgICAgIHRyYWl0PXNwZWNpYWxTZWxlY3QpCiAgcG9wID0gbWFrZURIKHBvcCkKfQoKIyBTZWxlY3QgcGFyZW50cyBhbmQgbWFrZSBiaXBhcmVudGFsIGNyb3NzZXMKcGFyZW50cyA9IHNlbGVjdEluZChwb3AsIG5JbmQ9MywgdHJhaXQ9c3BlY2lhbFNlbGVjdCkKCnByb2dlbnkxMiA9IG1ha2VDcm9zcyhwYXJlbnRzLCBjcm9zc1BsYW49Y2JpbmQoMSwyKSkKcHJvZ2VueTEyID0gbWFrZURIKHByb2dlbnkxMiwgbkRIPTEwMCkKCnByb2dlbnkxMyA9IG1ha2VDcm9zcyhwYXJlbnRzLCBjcm9zc1BsYW49Y2JpbmQoMSwzKSkKcHJvZ2VueTEzID0gbWFrZURIKHByb2dlbnkxMywgbkRIPTEwMCkKCnByb2dlbnkyMyA9IG1ha2VDcm9zcyhwYXJlbnRzLCBjcm9zc1BsYW49Y2JpbmQoMiwzKSkKcHJvZ2VueTIzID0gbWFrZURIKHByb2dlbnkyMywgbkRIPTEwMCkKCiMgTWVhc3VyZSBHVgpndlBhciA9IHNwZWNpYWxTZWxlY3QoZ3YocGFyZW50cykpCmd2UHJvZzEyID0gc3BlY2lhbFNlbGVjdChndihwcm9nZW55MTIpKQpndlByb2cxMyA9IHNwZWNpYWxTZWxlY3QoZ3YocHJvZ2VueTEzKSkKZ3ZQcm9nMjMgPSBzcGVjaWFsU2VsZWN0KGd2KHByb2dlbnkyMykpCgojIE1lYXN1cmUgZGlmZmVyZW5jZSBiZXR3ZWVuIG1pZHBhcmVudCBhbmQgcHJvZ2VueSBtZWFuCm1lYW4oZ3ZQYXJbMToyXSkgLSBtZWFuKGd2UHJvZzEyKQptZWFuKGd2UGFyW2MoMSwzKV0pIC0gbWVhbihndlByb2cxMykKbWVhbihndlBhclsyOjNdKSAtIG1lYW4oZ3ZQcm9nMjMpCgpgYGAKCg==