The coalescent in R
library(ape)
library(phyclust)
rm(list = ls())
ms_out <- ms(nsam = 10, opts = "-T")
ms_tree_1 <- read.tree(text = ms_out)
plot(ms_tree_1)
You’ll notice that the tip labels run from s1
through s25
. Each corresponds to a different allele. That was pretty easy, but we can do a bit more. We can ask how “deep” the tree is, i.e., how far back in time we have to go to find the most recent common ancestor of all the alleles in our sample.
Branching times
branching.times(ms_tree_1)[1]
11
0.7630929
You’re probably wondering about the [1]
after branching.times()
. Well, branching.times()
returns a vector of all of the branching times in the tree.
branching.times(ms_tree_1)
11 12 13 14 15 16
0.76309287 0.08241319 0.03451869 0.31600639 0.12675099 0.12256396
17 18 19
0.10605252 0.02017499 0.02702544
The numbers 11-19 are the node numbers in the tree above.
plot(ms_tree_1)
nodelabels()
As you can see, node 11 (which is the first one in the list), is the deepest node, i.e., the most recent common ancestor of all of the alleles in our sample.
Scaling of branching times
The other thing you may be wondering is how to interpret the number 0.7630929 that corresponds to the time of the most recent common ancestor. To explain that I have to point out something that you may have missed when we called ms()
: We didn’t specify a population size. How can we get away with that, since I told you that drift always depends on the population size?
Well, remember what you know about the coalesenct process. The expected time to coalescence of all alleles is \(4N_e\). ms()
reports branching time in “coalescent units” where 1 unit equals \(4N_e\). So if branching.times(ms_tree_1)[1]
is 0.7630929 and the effective size of our population is 25, then the time (number of generations before the present) to the most recent common ancestor is 76.3092874. Notice that the time isn’t an integer the way you’d expect it to be. That’s because of an approximation that is generally used in implementing the coalescent in software. If you want to turn it into an integer, you can do this:
round(4*25*branching.times(ms_tree_1)[1])
11
76
Whether you round it or not, you’ll see that the most recent common ancestor of the alleles in our sample didn’t occur exactly 100 generations ago as we’d expect. If, however, we repeat that simulation a bunch of times, you can see that we come pretty close - on average.
library(ggplot2)
N_e = 25
c_time <- numeric(0)
for (i in 1:1000) {
ms_out <- ms(nsam = N_e, opts = "-T")
ms_tree <- read.tree(text = ms_out)
c_time[i] <- 4*N_e*branching.times(ms_tree)[1]
}
p <- ggplot(data.frame(t = c_time), aes(x = t)) +
geom_histogram(bins = 50, alpha = 0.6) +
geom_vline(xintercept = 4*N_e, linetype = "dashed", color = "red") +
theme_bw()
p
We expect a coalescence time of 100 and our observed average coalescence time is 96.0371665. Not too bad.
The coalescent with migration
What happens when we have a subdivided population so that we have several populations exchanging genes? Here’s how we simulate a finite island model with three populations, local population sizes of 10 in each population, and \(N_em = 2\).
library(tidyverse)
library(RColorBrewer)
get_pop <- function(tree, sample_sizes, k) {
idx <- as.numeric(gsub("^s(.*)$", "\\1", tree$tip.label))
cum <- 0
for (i in 1:length(sample_sizes)) {
if (idx[k] < cum + sample_sizes[i] + 1) {
retval <- i
break
} else {
cum <- cum + sample_sizes[i]
}
}
return(i)
}
tipcolors <- function(tree, sample_sizes) {
my_colors <- brewer.pal(length(sample_sizes), "Set1")
colors <- numeric(length(sample_sizes))
for (i in 1:sum(sample_sizes)) {
colors[i] <- my_colors[get_pop(tree, sample_sizes, i)]
}
return(colors)
}
## Note: sample sizes should be multiplied by 2 before calling
## island for diploid samples
##
island <- function(sample_sizes, ne_m) {
opt_string <- paste("-T -I ", length(sample_sizes), " ", sep = "")
for (i in 1:length(sample_sizes)) {
opt_string <- paste(opt_string, sample_sizes[i], " ", sep = "")
}
opt_string <- paste(opt_string, ne_m, "\n", sep = "")
ms_out <- ms(nsam = sum(sample_sizes), nreps = 1, opts = opt_string)
return(ms_out)
}
plot_island <- function(sample_sizes, ne_m) {
sample_sizes <- 2*sample_sizes
ms_out <- island(sample_sizes, ne_m)
ms_tree <- read.tree(text = ms_out)
plot(ms_tree,
show.tip.label = FALSE)
tiplabels(pch = 19, cex = 0.75,
col = tipcolors(ms_tree,
sample_sizes))
return(branching.times(ms_tree)[1])
}
time <- plot_island(sample_sizes = c(5, 5, 5), ne_m = 2)
The colors correspond to the population from which each sample was collected. plot_island()
returns the scaled time to the most recent common ancestor, 4.5826837. We are implicitly assuming that the effective population size is the same in each local population. The scaling is in terms of the product of the local effective population size and the number of populations, i.e., 1 coalescent unit = \(4N_ek\), where \(k\) is the number of populations.
Lab 7
You will be performing another set of simulations this week to compare coalescence times in two scenarios:
- A finite island model of migration.
- A one-dimensional stepping stone model of migration.
You are already familiar with the finite island model. In a one-dimensional stepping stone model, the populations are arranged in a lineary array and only those populations that are adjacent to one another can exchange migrants. If \(m\) is the migration rate, i.e., the fraction of a population composed of migrants then the fraction of population \(i\) derived from population \(i-1\) is \(\frac{m}{2}\) and the fraction of population \(i\) derived from population \(i+1\) is \(\frac{m}{2}\).
Use the functions below to explore the difference in coalescence times for finite island models and one-dimensional stepping stone models of migration, and answer the following questions:
How does the number of populations included affect the avearge time to coalescence of all alleles?
How does the migration rate affect the average time to coalescence of all alleles?
Are there consistent differences between the average time to coalescence in a finite island model and a one-dimensional stepping stone model? If there are, what might explain the difference that you see?
Hints
run_simulations()
will automatically keep the number of populations in both models the same to ensure that you can always make appropriate comparisons of the models. It will also set the local effective population size to 25, and it sets the number of replications to 1000 by default. You might want to run the function once with n_reps = 100
to get a feel for how long it will take the simulation to run on your computer before you begin the full-scale simulations
run_simulations()
returns a data frame with two columns: Model
and Time
. If you’re interested, you can use that to examine the median time to coalescence (rather than the mean) and the variance (or standard deviation) in coalescence times. You’ll notice that run_simulation()
automatically prints out the mean coalesence times for you.
## one-dimensional stepping stone
##
one_d_stepping_stone <- function(n_e, m, n_pops) {
stopifnot((m > 0) && (m < 1))
m_matrix <- diag(1 - m, nrow = n_pops)
m_matrix[1, 2] <- m
m_matrix[n_pops, n_pops - 1] <- m
for (i in 2:(n_pops - 1)) {
m_matrix[i, i - 1] <- m/2
m_matrix[i, i + 1] <- m/2
}
opt_string <- paste("-T -I ", n_pops, " ", sep = "")
for (i in 1:n_pops) {
opt_string <- paste(opt_string, 2*n_e, " ", sep = "")
}
opt_string <- paste(opt_string, "-ma", sep = "")
## transpose m_matrix before converting to vector to get vector from matrix
## by row instead of by column
##
m_vector <- 4*n_e*c(t(m_matrix))
for ( i in 1:length(m_vector)) {
opt_string <- paste(opt_string, " ", m_vector[i], sep = "")
}
ms_out <- ms(nsam = 2*n_e*n_pops, nreps = 1, opts = opt_string)
return(ms_out)
}
run_simulation <- function(n_pops, m, n_reps = 1000) {
N_e = 25
pop_sizes <- rep(N_e, n_pops)
df <- tibble(Model = NA, Time = NA)
for (i in 1:n_reps) {
ms_out <- island(pop_sizes, N_e*m)
ms_tree <- read.tree(text = ms_out)
df <- add_row(df,
Model = "Island",
Time = (4*N_e*n_pops)*branching.times(ms_tree)[1])
ms_out <- one_d_stepping_stone(N_e, m, n_pops)
ms_tree <- read.tree(text = ms_out)
df <- add_row(df,
Model = "1-d",
Time = (4*N_e*n_pops)*branching.times(ms_tree)[1])
}
df <- filter(df, !is.na(Model))
p <- ggplot(df, aes(x = Time, fill = Model)) +
geom_histogram(position = "identity", bins = n_reps/10, alpha = 0.4) +
ggtitle(paste("n_pops = ", n_pops, ", m = ", m)) +
theme_bw()
print(p)
sum <- df %>% group_by(Model) %>%
summarize(Mean_Time = mean(Time))
print(sum)
return(df)
}
LS0tCnRpdGxlOiAiRXhwbG9yaW5nIHRoZSBjb2FsZXNjZW50IgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKV2UgdXNlIGBtcygpYCBmcm9tIGBwaHljbHVzdGAgdG8gc2ltdWxhdGUgc2FtcGxlcyBmcm9tIHRoZSBjb2FsZXNjZW50IGFuZCB2YXJpb3VzIGZ1bmN0aW9ucyBmcm9tIGBhcGVgIHRvIGRpc3BsYXkgdGhlIGNvYWxlc2NlbnQgdHJlZSBhbmQgY2FsY3VsYXRlIHN0YXRpc3RpY3MgZnJvbSBpdC4gTGV0J3Mgc3RhcnQgd2l0aCBhIHJlYWxseSBzaW1wbGUgZXhhbXBsZSBvZiBjb25zdHJ1Y3RpbmcgYSBjb2FsZXNjZW50IHNhbXBsZSBvZiBzaXplIDEwLiBUaGUgYG5zYW1gIGFyZ3VtZW50IGlzIHRoZSBudW1iZXIgb2Ygc2FtcGxlcywgYW5kIHRoZSBgb3B0cyA9ICItVCJgIGFyZ3VtZW50IHRlbGwgYG1zKClgIHRvIHJldHVybiBhIGNvYWxlc2NlbnQgdHJlZS4gV2UgdGhlbiBjb252ZXJ0IGl0LCB1c2luZyBgcmVhZC50cmVlKClgIHRvIGEgZm9ybWF0IHRoYXQgd2UgY2FuIGBwbG90KClgICAKCiMjIFRoZSBjb2FsZXNjZW50IGluIGBSYAoKYGBge3J9CmxpYnJhcnkoYXBlKQpsaWJyYXJ5KHBoeWNsdXN0KQoKcm0obGlzdCA9IGxzKCkpCgptc19vdXQgPC0gbXMobnNhbSA9IDEwLCBvcHRzID0gIi1UIikKbXNfdHJlZV8xIDwtIHJlYWQudHJlZSh0ZXh0ID0gbXNfb3V0KQpwbG90KG1zX3RyZWVfMSkKYGBgCllvdSdsbCBub3RpY2UgdGhhdCB0aGUgdGlwIGxhYmVscyBydW4gZnJvbSBgczFgIHRocm91Z2ggYHMyNWAuIEVhY2ggY29ycmVzcG9uZHMgdG8gYSBkaWZmZXJlbnQgYWxsZWxlLiBUaGF0IHdhcyBwcmV0dHkgZWFzeSwgYnV0IHdlIGNhbiBkbyBhIGJpdCBtb3JlLiBXZSBjYW4gYXNrIGhvdyAiZGVlcCIgdGhlIHRyZWUgaXMsIGkuZS4sIGhvdyBmYXIgYmFjayBpbiB0aW1lIHdlIGhhdmUgdG8gZ28gdG8gZmluZCB0aGUgbW9zdCByZWNlbnQgY29tbW9uIGFuY2VzdG9yIG9mIGFsbCB0aGUgYWxsZWxlcyBpbiBvdXIgc2FtcGxlLgoKIyMjIEJyYW5jaGluZyB0aW1lcwoKYGBge3J9CmJyYW5jaGluZy50aW1lcyhtc190cmVlXzEpWzFdCmBgYAoKWW91J3JlIHByb2JhYmx5IHdvbmRlcmluZyBhYm91dCB0aGUgYFsxXWAgYWZ0ZXIgYGJyYW5jaGluZy50aW1lcygpYC4gV2VsbCwgYGJyYW5jaGluZy50aW1lcygpYCByZXR1cm5zIGEgdmVjdG9yIG9mICphbGwqIG9mIHRoZSBicmFuY2hpbmcgdGltZXMgaW4gdGhlIHRyZWUuCgpgYGB7cn0KYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWVfMSkKYGBgCgpUaGUgbnVtYmVycyAxMS0xOSBhcmUgdGhlIG5vZGUgbnVtYmVycyBpbiB0aGUgdHJlZSBhYm92ZS4KCmBgYHtyfQpwbG90KG1zX3RyZWVfMSkKbm9kZWxhYmVscygpCmBgYAoKQXMgeW91IGNhbiBzZWUsIG5vZGUgMTEgKHdoaWNoIGlzIHRoZSBmaXJzdCBvbmUgaW4gdGhlIGxpc3QpLCBpcyB0aGUgZGVlcGVzdCBub2RlLCBpLmUuLCB0aGUgbW9zdCByZWNlbnQgY29tbW9uIGFuY2VzdG9yIG9mIGFsbCBvZiB0aGUgYWxsZWxlcyBpbiBvdXIgc2FtcGxlLiAKCiMjIyBTY2FsaW5nIG9mIGJyYW5jaGluZyB0aW1lcwoKVGhlIG90aGVyIHRoaW5nIHlvdSBtYXkgYmUgd29uZGVyaW5nIGlzIGhvdyB0byBpbnRlcnByZXQgdGhlIG51bWJlciBgciBicmFuY2hpbmcudGltZXMobXNfdHJlZV8xKVsxXWAgdGhhdCBjb3JyZXNwb25kcyB0byB0aGUgdGltZSBvZiB0aGUgbW9zdCByZWNlbnQgY29tbW9uIGFuY2VzdG9yLl5bUmVtZW1iZXIgdGhhdCB3aGVuIHVzaW5nIHRoZSBjb2FsZXNjZW50LCB0aW1lIHJ1bnMgYmFja3dhcmRzLiBTbyB0aGUgdGltZSBvZiB0aGUgbW9zdCByZWNlbnQgY29tbW9uIGFuY2VzdG9yIGlzIGEgdGltZSBpbiB0aGUgcGFzdC5dIFRvIGV4cGxhaW4gdGhhdCBJIGhhdmUgdG8gcG9pbnQgb3V0IHNvbWV0aGluZyB0aGF0IHlvdSBtYXkgaGF2ZSBtaXNzZWQgd2hlbiB3ZSBjYWxsZWQgYG1zKClgOiBXZSBkaWRuJ3Qgc3BlY2lmeSBhIHBvcHVsYXRpb24gc2l6ZS4gSG93IGNhbiB3ZSBnZXQgYXdheSB3aXRoIHRoYXQsIHNpbmNlIEkgdG9sZCB5b3UgdGhhdCBkcmlmdCAqYWx3YXlzKiBkZXBlbmRzIG9uIHRoZSBwb3B1bGF0aW9uIHNpemU/CgpXZWxsLCByZW1lbWJlciB3aGF0IHlvdSBrbm93IGFib3V0IHRoZSBjb2FsZXNlbmN0IHByb2Nlc3MuIFRoZSBleHBlY3RlZCB0aW1lIHRvIGNvYWxlc2NlbmNlIG9mIGFsbCBhbGxlbGVzIGlzICQ0Tl9lJC4gYG1zKClgIHJlcG9ydHMgYnJhbmNoaW5nIHRpbWUgaW4gImNvYWxlc2NlbnQgdW5pdHMiIHdoZXJlIDEgdW5pdCBlcXVhbHMgJDROX2UkLiBTbyBpZiBgYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWVfMSlbMV1gIGlzIGByIGJyYW5jaGluZy50aW1lcyhtc190cmVlXzEpWzFdYCBhbmQgdGhlIGVmZmVjdGl2ZSBzaXplIG9mIG91ciBwb3B1bGF0aW9uIGlzIDI1LCB0aGVuIHRoZSB0aW1lIChudW1iZXIgb2YgZ2VuZXJhdGlvbnMgYmVmb3JlIHRoZSBwcmVzZW50KSB0byB0aGUgbW9zdCByZWNlbnQgY29tbW9uIGFuY2VzdG9yIGlzIGByIDQqMjUqYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWVfMSlbMV1gLiBOb3RpY2UgdGhhdCB0aGUgdGltZSBpc24ndCBhbiBpbnRlZ2VyIHRoZSB3YXkgeW91J2QgZXhwZWN0IGl0IHRvIGJlLiBUaGF0J3MgYmVjYXVzZSBvZiBhbiBhcHByb3hpbWF0aW9uIHRoYXQgaXMgZ2VuZXJhbGx5IHVzZWQgaW4gaW1wbGVtZW50aW5nIHRoZSBjb2FsZXNjZW50IGluIHNvZnR3YXJlLiBJZiB5b3Ugd2FudCB0byB0dXJuIGl0IGludG8gYW4gaW50ZWdlciwgeW91IGNhbiBkbyB0aGlzOgoKYGBge3J9CnJvdW5kKDQqMjUqYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWVfMSlbMV0pCmBgYAoKV2hldGhlciB5b3Ugcm91bmQgaXQgb3Igbm90LCB5b3UnbGwgc2VlIHRoYXQgdGhlIG1vc3QgcmVjZW50IGNvbW1vbiBhbmNlc3RvciBvZiB0aGUgYWxsZWxlcyBpbiBvdXIgc2FtcGxlIGRpZG4ndCBvY2N1ciBleGFjdGx5IDEwMCBnZW5lcmF0aW9ucyBhZ28gYXMgd2UnZCBleHBlY3QuIElmLCBob3dldmVyLCB3ZSByZXBlYXQgdGhhdCBzaW11bGF0aW9uIGEgYnVuY2ggb2YgdGltZXMsIHlvdSBjYW4gc2VlIHRoYXQgd2UgY29tZSBwcmV0dHkgY2xvc2UgLSBvbiBhdmVyYWdlLgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCk5fZSA9IDI1CgpjX3RpbWUgPC0gbnVtZXJpYygwKQpmb3IgKGkgaW4gMToxMDAwKSB7CiAgbXNfb3V0IDwtIG1zKG5zYW0gPSBOX2UsIG9wdHMgPSAiLVQiKQogIG1zX3RyZWUgPC0gcmVhZC50cmVlKHRleHQgPSBtc19vdXQpCiAgY190aW1lW2ldIDwtIDQqTl9lKmJyYW5jaGluZy50aW1lcyhtc190cmVlKVsxXQp9CnAgPC0gZ2dwbG90KGRhdGEuZnJhbWUodCA9IGNfdGltZSksIGFlcyh4ID0gdCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gNTAsIGFscGhhID0gMC42KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gNCpOX2UsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gInJlZCIpICsgCiAgdGhlbWVfYncoKQpwCmBgYAoKV2UgZXhwZWN0IGEgY29hbGVzY2VuY2UgdGltZSBvZiBgciA0Kk5fZWAgYW5kIG91ciBvYnNlcnZlZCBhdmVyYWdlIGNvYWxlc2NlbmNlIHRpbWUgaXMgYHIgbWVhbihjX3RpbWUpYC4gTm90IHRvbyBiYWQuCgojIyMgVGhlIGNvYWxlc2NlbnQgd2l0aCBtaWdyYXRpb24KCldoYXQgaGFwcGVucyB3aGVuIHdlIGhhdmUgYSBzdWJkaXZpZGVkIHBvcHVsYXRpb24gc28gdGhhdCB3ZSBoYXZlIHNldmVyYWwgcG9wdWxhdGlvbnMgZXhjaGFuZ2luZyBnZW5lcz8gSGVyZSdzIGhvdyB3ZSBzaW11bGF0ZSBhIGZpbml0ZSBpc2xhbmQgbW9kZWwgd2l0aCB0aHJlZSBwb3B1bGF0aW9ucywgbG9jYWwgcG9wdWxhdGlvbiBzaXplcyBvZiAxMCBpbiBlYWNoIHBvcHVsYXRpb24sIGFuZCAkTl9lbSA9IDIkLl5bTm90ZTogWW91J2xsIG5lZWQgdG8gaW5zdGFsbCBgUkNvbG9yQnJld2VyYCBpZiB5b3Ugd2FudCB0byBydW4gdGhpcyBjb2RlLl0KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShSQ29sb3JCcmV3ZXIpCgpnZXRfcG9wIDwtIGZ1bmN0aW9uKHRyZWUsIHNhbXBsZV9zaXplcywgaykgewogIGlkeCA8LSBhcy5udW1lcmljKGdzdWIoIl5zKC4qKSQiLCAiXFwxIiwgdHJlZSR0aXAubGFiZWwpKQogIGN1bSA8LSAwCiAgZm9yIChpIGluIDE6bGVuZ3RoKHNhbXBsZV9zaXplcykpIHsKICAgIGlmIChpZHhba10gPCBjdW0gKyBzYW1wbGVfc2l6ZXNbaV0gKyAxKSB7CiAgICAgIHJldHZhbCA8LSBpCiAgICAgIGJyZWFrCiAgICB9IGVsc2UgewogICAgICBjdW0gPC0gY3VtICsgc2FtcGxlX3NpemVzW2ldCiAgICB9CiAgfQogIHJldHVybihpKQp9Cgp0aXBjb2xvcnMgPC0gZnVuY3Rpb24odHJlZSwgc2FtcGxlX3NpemVzKSB7CiAgbXlfY29sb3JzIDwtIGJyZXdlci5wYWwobGVuZ3RoKHNhbXBsZV9zaXplcyksICJTZXQxIikKICBjb2xvcnMgPC0gbnVtZXJpYyhsZW5ndGgoc2FtcGxlX3NpemVzKSkKICBmb3IgKGkgaW4gMTpzdW0oc2FtcGxlX3NpemVzKSkgewogICAgY29sb3JzW2ldIDwtIG15X2NvbG9yc1tnZXRfcG9wKHRyZWUsIHNhbXBsZV9zaXplcywgaSldCiAgfQogIHJldHVybihjb2xvcnMpCn0KCiMjIE5vdGU6IHNhbXBsZSBzaXplcyBzaG91bGQgYmUgbXVsdGlwbGllZCBieSAyIGJlZm9yZSBjYWxsaW5nCiMjIGlzbGFuZCBmb3IgZGlwbG9pZCBzYW1wbGVzCiMjCmlzbGFuZCA8LSBmdW5jdGlvbihzYW1wbGVfc2l6ZXMsIG5lX20pIHsKICBvcHRfc3RyaW5nIDwtIHBhc3RlKCItVCAtSSAiLCBsZW5ndGgoc2FtcGxlX3NpemVzKSwgIiAiLCBzZXAgPSAiIikKICBmb3IgKGkgaW4gMTpsZW5ndGgoc2FtcGxlX3NpemVzKSkgewogICAgb3B0X3N0cmluZyA8LSBwYXN0ZShvcHRfc3RyaW5nLCBzYW1wbGVfc2l6ZXNbaV0sICIgIiwgc2VwID0gIiIpCiAgfQogIG9wdF9zdHJpbmcgPC0gcGFzdGUob3B0X3N0cmluZywgbmVfbSwgIlxuIiwgc2VwID0gIiIpCiAgbXNfb3V0IDwtIG1zKG5zYW0gPSBzdW0oc2FtcGxlX3NpemVzKSwgbnJlcHMgPSAxLCBvcHRzID0gb3B0X3N0cmluZykKICByZXR1cm4obXNfb3V0KSAgCn0KCnBsb3RfaXNsYW5kIDwtIGZ1bmN0aW9uKHNhbXBsZV9zaXplcywgbmVfbSkgewogIHNhbXBsZV9zaXplcyA8LSAyKnNhbXBsZV9zaXplcwogIG1zX291dCA8LSBpc2xhbmQoc2FtcGxlX3NpemVzLCBuZV9tKQogIG1zX3RyZWUgPC0gcmVhZC50cmVlKHRleHQgPSBtc19vdXQpCiAgcGxvdChtc190cmVlLCAKICAgICAgIHNob3cudGlwLmxhYmVsID0gRkFMU0UpCiAgdGlwbGFiZWxzKHBjaCA9IDE5LCBjZXggPSAwLjc1LCAKICAgICAgICAgICAgY29sID0gdGlwY29sb3JzKG1zX3RyZWUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX3NpemVzKSkKICByZXR1cm4oYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWUpWzFdKQp9Cgp0aW1lIDwtIHBsb3RfaXNsYW5kKHNhbXBsZV9zaXplcyA9IGMoNSwgNSwgNSksIG5lX20gPSAyKQpgYGAKVGhlIGNvbG9ycyBjb3JyZXNwb25kIHRvIHRoZSBwb3B1bGF0aW9uIGZyb20gd2hpY2ggZWFjaCBzYW1wbGUgd2FzIGNvbGxlY3RlZC4gYHBsb3RfaXNsYW5kKClgIHJldHVybnMgdGhlIHNjYWxlZCB0aW1lIHRvIHRoZSBtb3N0IHJlY2VudCBjb21tb24gYW5jZXN0b3IsIGByIHRpbWVgLiBXZSBhcmUgaW1wbGljaXRseSBhc3N1bWluZyB0aGF0IHRoZSBlZmZlY3RpdmUgcG9wdWxhdGlvbiBzaXplIGlzIHRoZSBzYW1lIGluIGVhY2ggbG9jYWwgcG9wdWxhdGlvbi5eW1RoZXJlIGlzIGEgd2F5IHRvIHJlbGF4IHRoaXMgYXNzdW1wdGlvbiwgYnV0IHdlIHdvbid0IHRha2UgYWR2YW50YWdlIG9mIGl0IGhlcmUuXSBUaGUgc2NhbGluZyBpcyBpbiB0ZXJtcyBvZiB0aGUgcHJvZHVjdCBvZiB0aGUgbG9jYWwgZWZmZWN0aXZlIHBvcHVsYXRpb24gc2l6ZSBhbmQgdGhlIG51bWJlciBvZiBwb3B1bGF0aW9ucywgaS5lLiwgMSBjb2FsZXNjZW50IHVuaXQgPSAkNE5fZWskLCB3aGVyZSAkayQgaXMgdGhlIG51bWJlciBvZiBwb3B1bGF0aW9ucy4KCiMjIExhYiA3CgpZb3Ugd2lsbCBiZSBwZXJmb3JtaW5nIGFub3RoZXIgc2V0IG9mIHNpbXVsYXRpb25zIHRoaXMgd2VlayB0byBjb21wYXJlIGNvYWxlc2NlbmNlIHRpbWVzIGluIHR3byBzY2VuYXJpb3M6CgoxLiBBIGZpbml0ZSBpc2xhbmQgbW9kZWwgb2YgbWlncmF0aW9uLgoyLiBBIG9uZS1kaW1lbnNpb25hbCBzdGVwcGluZyBzdG9uZSBtb2RlbCBvZiBtaWdyYXRpb24uCgpZb3UgYXJlIGFscmVhZHkgZmFtaWxpYXIgd2l0aCB0aGUgZmluaXRlIGlzbGFuZCBtb2RlbC4gSW4gYSBvbmUtZGltZW5zaW9uYWwgc3RlcHBpbmcgc3RvbmUgbW9kZWwsIHRoZSBwb3B1bGF0aW9ucyBhcmUgYXJyYW5nZWQgaW4gYSBsaW5lYXJ5IGFycmF5IGFuZCBvbmx5IHRob3NlIHBvcHVsYXRpb25zIHRoYXQgYXJlIGFkamFjZW50IHRvIG9uZSBhbm90aGVyIGNhbiBleGNoYW5nZSBtaWdyYW50cy4gSWYgJG0kIGlzIHRoZSBtaWdyYXRpb24gcmF0ZSwgaS5lLiwgdGhlIGZyYWN0aW9uIG9mIGEgcG9wdWxhdGlvbiBjb21wb3NlZCBvZiBtaWdyYW50cyB0aGVuIHRoZSBmcmFjdGlvbiBvZiBwb3B1bGF0aW9uICRpJCBkZXJpdmVkIGZyb20gcG9wdWxhdGlvbiAkaS0xJCBpcyAkXGZyYWN7bX17Mn0kIGFuZCB0aGUgZnJhY3Rpb24gb2YgcG9wdWxhdGlvbiAkaSQgZGVyaXZlZCBmcm9tIHBvcHVsYXRpb24gJGkrMSQgaXMgJFxmcmFje219ezJ9JC5eW05vdGU6IEZvciB0aGUgZmlyc3QgcG9wdWxhdGlvbiBpbiB0aGUgYXJyYXksIGkuZS4sIHBvcHVsYXRpb24gMSwgdGhlIGZyYWN0aW9uIG9mIHRoZSBwb3B1bGF0aW9uIGRlcml2ZWQgZnJvbSBwb3B1bGF0aW9uIDIgaXMgJG0kLiBTaW1pbGFybHksIGlmIHRoZXJlIGFyZSAkayQgcG9wdWxhdGlvbnMgaW4gdGhlIGFycnksIHRoZSBmcmFjdGlvbiBvZiBwb3B1bGF0aW9uICRrJCB0aGF0IGlzIGRlcml2ZWQgZnJvbSBwb3B1bGF0aW9uICRrLTEkIGlzICRtJC5dCgpVc2UgdGhlIGZ1bmN0aW9ucyBiZWxvdyB0byBleHBsb3JlIHRoZSBkaWZmZXJlbmNlIGluIGNvYWxlc2NlbmNlIHRpbWVzIGZvciBmaW5pdGUgaXNsYW5kIG1vZGVscyBhbmQgb25lLWRpbWVuc2lvbmFsIHN0ZXBwaW5nIHN0b25lIG1vZGVscyBvZiBtaWdyYXRpb24sIGFuZCBhbnN3ZXIgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6CgoxLiBIb3cgZG9lcyB0aGUgbnVtYmVyIG9mIHBvcHVsYXRpb25zIGluY2x1ZGVkIGFmZmVjdCB0aGUgYXZlYXJnZSB0aW1lIHRvIGNvYWxlc2NlbmNlIG9mIGFsbCBhbGxlbGVzPwoKMi4gSG93IGRvZXMgdGhlIG1pZ3JhdGlvbiByYXRlIGFmZmVjdCB0aGUgYXZlcmFnZSB0aW1lIHRvIGNvYWxlc2NlbmNlIG9mIGFsbCBhbGxlbGVzPwoKMy4gQXJlIHRoZXJlIGNvbnNpc3RlbnQgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgYXZlcmFnZSB0aW1lIHRvIGNvYWxlc2NlbmNlIGluIGEgZmluaXRlIGlzbGFuZCBtb2RlbCBhbmQgYSBvbmUtZGltZW5zaW9uYWwgc3RlcHBpbmcgc3RvbmUgbW9kZWw/IElmIHRoZXJlIGFyZSwgd2hhdCBtaWdodCBleHBsYWluIHRoZSBkaWZmZXJlbmNlIHRoYXQgeW91IHNlZT8KCiMjIyBIaW50cwoKYHJ1bl9zaW11bGF0aW9ucygpYCB3aWxsIGF1dG9tYXRpY2FsbHkga2VlcCB0aGUgbnVtYmVyIG9mIHBvcHVsYXRpb25zIGluIGJvdGggbW9kZWxzIHRoZSBzYW1lIHRvIGVuc3VyZSB0aGF0IHlvdSBjYW4gYWx3YXlzIG1ha2UgYXBwcm9wcmlhdGUgY29tcGFyaXNvbnMgb2YgdGhlIG1vZGVscy4gSXQgd2lsbCBhbHNvIHNldCB0aGUgbG9jYWwgZWZmZWN0aXZlIHBvcHVsYXRpb24gc2l6ZSB0byAyNSwgYW5kIGl0IHNldHMgdGhlIG51bWJlciBvZiByZXBsaWNhdGlvbnMgdG8gMTAwMCBieSBkZWZhdWx0LiBZb3UgbWlnaHQgd2FudCB0byBydW4gdGhlIGZ1bmN0aW9uIG9uY2Ugd2l0aCBgbl9yZXBzID0gMTAwYCB0byBnZXQgYSBmZWVsIGZvciBob3cgbG9uZyBpdCB3aWxsIHRha2UgdGhlIHNpbXVsYXRpb24gdG8gcnVuIG9uIHlvdXIgY29tcHV0ZXIgYmVmb3JlIHlvdSBiZWdpbiB0aGUgZnVsbC1zY2FsZSBzaW11bGF0aW9ucyAKCmBydW5fc2ltdWxhdGlvbnMoKWAgcmV0dXJucyBhIGRhdGEgZnJhbWVeW1dlbGwsIGFjdHVhbGx5IGEgdGliYmxlXSB3aXRoIHR3byBjb2x1bW5zOiBgTW9kZWxgIGFuZCBgVGltZWAuIElmIHlvdSdyZSBpbnRlcmVzdGVkLCB5b3UgY2FuIHVzZSB0aGF0IHRvIGV4YW1pbmUgdGhlIG1lZGlhbiB0aW1lIHRvIGNvYWxlc2NlbmNlIChyYXRoZXIgdGhhbiB0aGUgbWVhbikgYW5kIHRoZSB2YXJpYW5jZSAob3Igc3RhbmRhcmQgZGV2aWF0aW9uKSBpbiBjb2FsZXNjZW5jZSB0aW1lcy4gWW91J2xsIG5vdGljZSB0aGF0IGBydW5fc2ltdWxhdGlvbigpYCBhdXRvbWF0aWNhbGx5IHByaW50cyBvdXQgdGhlIG1lYW4gY29hbGVzZW5jZSB0aW1lcyBmb3IgeW91LgoKYGBge3J9CiMjIG9uZS1kaW1lbnNpb25hbCBzdGVwcGluZyBzdG9uZQojIwpvbmVfZF9zdGVwcGluZ19zdG9uZSA8LSBmdW5jdGlvbihuX2UsIG0sIG5fcG9wcykgewogIHN0b3BpZm5vdCgobSA+IDApICYmIChtIDwgMSkpCiAgbV9tYXRyaXggPC0gZGlhZygxIC0gbSwgbnJvdyA9IG5fcG9wcykKICBtX21hdHJpeFsxLCAyXSA8LSBtCiAgbV9tYXRyaXhbbl9wb3BzLCBuX3BvcHMgLSAxXSA8LSBtCiAgZm9yIChpIGluIDI6KG5fcG9wcyAtIDEpKSB7CiAgICBtX21hdHJpeFtpLCBpIC0gMV0gPC0gbS8yCiAgICBtX21hdHJpeFtpLCBpICsgMV0gPC0gbS8yCiAgfQogIG9wdF9zdHJpbmcgPC0gcGFzdGUoIi1UIC1JICIsIG5fcG9wcywgIiAiLCBzZXAgPSAiIikKICBmb3IgKGkgaW4gMTpuX3BvcHMpIHsKICAgIG9wdF9zdHJpbmcgPC0gcGFzdGUob3B0X3N0cmluZywgMipuX2UsICIgIiwgc2VwID0gIiIpCiAgfQogIG9wdF9zdHJpbmcgPC0gcGFzdGUob3B0X3N0cmluZywgIi1tYSIsIHNlcCA9ICIiKQogICMjIHRyYW5zcG9zZSBtX21hdHJpeCBiZWZvcmUgY29udmVydGluZyB0byB2ZWN0b3IgdG8gZ2V0IHZlY3RvciBmcm9tIG1hdHJpeAogICMjIGJ5IHJvdyBpbnN0ZWFkIG9mIGJ5IGNvbHVtbgogICMjCiAgbV92ZWN0b3IgPC0gNCpuX2UqYyh0KG1fbWF0cml4KSkKICBmb3IgKCBpIGluIDE6bGVuZ3RoKG1fdmVjdG9yKSkgewogICAgb3B0X3N0cmluZyA8LSBwYXN0ZShvcHRfc3RyaW5nLCAiICIsIG1fdmVjdG9yW2ldLCBzZXAgPSAiIikKICB9CiAgbXNfb3V0IDwtIG1zKG5zYW0gPSAyKm5fZSpuX3BvcHMsIG5yZXBzID0gMSwgb3B0cyA9IG9wdF9zdHJpbmcpCiAgcmV0dXJuKG1zX291dCkKfQoKcnVuX3NpbXVsYXRpb24gPC0gZnVuY3Rpb24obl9wb3BzLCBtLCBuX3JlcHMgPSAxMDAwKSB7CiAgTl9lID0gMjUKICBwb3Bfc2l6ZXMgPC0gcmVwKE5fZSwgbl9wb3BzKQogIGRmIDwtIHRpYmJsZShNb2RlbCA9IE5BLCBUaW1lID0gTkEpCiAgZm9yIChpIGluIDE6bl9yZXBzKSB7CiAgICBtc19vdXQgPC0gaXNsYW5kKHBvcF9zaXplcywgTl9lKm0pCiAgICBtc190cmVlIDwtIHJlYWQudHJlZSh0ZXh0ID0gbXNfb3V0KQogICAgZGYgPC0gYWRkX3JvdyhkZiwKICAgICAgICAgICAgICAgICAgTW9kZWwgPSAiSXNsYW5kIiwKICAgICAgICAgICAgICAgICAgVGltZSA9ICg0Kk5fZSpuX3BvcHMpKmJyYW5jaGluZy50aW1lcyhtc190cmVlKVsxXSkKICAgIG1zX291dCA8LSBvbmVfZF9zdGVwcGluZ19zdG9uZShOX2UsIG0sIG5fcG9wcykKICAgIG1zX3RyZWUgPC0gcmVhZC50cmVlKHRleHQgPSBtc19vdXQpCiAgICBkZiA8LSBhZGRfcm93KGRmLAogICAgICAgICAgICAgICAgICBNb2RlbCA9ICIxLWQiLAogICAgICAgICAgICAgICAgICBUaW1lID0gKDQqTl9lKm5fcG9wcykqYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWUpWzFdKQogIH0KICBkZiA8LSBmaWx0ZXIoZGYsICFpcy5uYShNb2RlbCkpCiAgcCA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gVGltZSwgZmlsbCA9IE1vZGVsKSkgKwogICAgZ2VvbV9oaXN0b2dyYW0ocG9zaXRpb24gPSAiaWRlbnRpdHkiLCBiaW5zID0gbl9yZXBzLzEwLCBhbHBoYSA9IDAuNCkgKwogICAgZ2d0aXRsZShwYXN0ZSgibl9wb3BzID0gIiwgbl9wb3BzLCAiLCBtID0gIiwgbSkpICsKICAgIHRoZW1lX2J3KCkKICBwcmludChwKQogIHN1bSA8LSBkZiAlPiUgZ3JvdXBfYnkoTW9kZWwpICU+JQogICAgc3VtbWFyaXplKE1lYW5fVGltZSA9IG1lYW4oVGltZSkpCiAgcHJpbnQoc3VtKQogIHJldHVybihkZikKfQpgYGAK