We use ms() from phyclust to simulate samples from the coalescent and various functions from ape to display the coalescent tree and calculate statistics from it. Let’s start with a really simple example of constructing a coalescent sample of size 10. The nsam argument is the number of samples, and the opts = "-T" argument tell ms() to return a coalescent tree. We then convert it, using read.tree() to a format that we can plot()

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.1 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\).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.3 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:

  1. A finite island model of migration.
  2. 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}\).4

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:

  1. How does the number of populations included affect the avearge time to coalescence of all alleles?

  2. How does the migration rate affect the average time to coalescence of all alleles?

  3. 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 frame5 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)
}

  1. Remember that when using the coalescent, time runs backwards. So the time of the most recent common ancestor is a time in the past.↩︎

  2. Note: You’ll need to install RColorBrewer if you want to run this code.↩︎

  3. There is a way to relax this assumption, but we won’t take advantage of it here.↩︎

  4. Note: For the first population in the array, i.e., population 1, the fraction of the population derived from population 2 is \(m\). Similarly, if there are \(k\) populations in the arry, the fraction of population \(k\) that is derived from population \(k-1\) is \(m\).↩︎

  5. Well, actually a tibble↩︎

LS0tCnRpdGxlOiAiRXhwbG9yaW5nIHRoZSBjb2FsZXNjZW50IgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKV2UgdXNlIGBtcygpYCBmcm9tIGBwaHljbHVzdGAgdG8gc2ltdWxhdGUgc2FtcGxlcyBmcm9tIHRoZSBjb2FsZXNjZW50IGFuZCB2YXJpb3VzIGZ1bmN0aW9ucyBmcm9tIGBhcGVgIHRvIGRpc3BsYXkgdGhlIGNvYWxlc2NlbnQgdHJlZSBhbmQgY2FsY3VsYXRlIHN0YXRpc3RpY3MgZnJvbSBpdC4gTGV0J3Mgc3RhcnQgd2l0aCBhIHJlYWxseSBzaW1wbGUgZXhhbXBsZSBvZiBjb25zdHJ1Y3RpbmcgYSBjb2FsZXNjZW50IHNhbXBsZSBvZiBzaXplIDEwLiBUaGUgYG5zYW1gIGFyZ3VtZW50IGlzIHRoZSBudW1iZXIgb2Ygc2FtcGxlcywgYW5kIHRoZSBgb3B0cyA9ICItVCJgIGFyZ3VtZW50IHRlbGwgYG1zKClgIHRvIHJldHVybiBhIGNvYWxlc2NlbnQgdHJlZS4gV2UgdGhlbiBjb252ZXJ0IGl0LCB1c2luZyBgcmVhZC50cmVlKClgIHRvIGEgZm9ybWF0IHRoYXQgd2UgY2FuIGBwbG90KClgICAKCiMjIFRoZSBjb2FsZXNjZW50IGluIGBSYAoKYGBge3J9CmxpYnJhcnkoYXBlKQpsaWJyYXJ5KHBoeWNsdXN0KQoKcm0obGlzdCA9IGxzKCkpCgptc19vdXQgPC0gbXMobnNhbSA9IDEwLCBvcHRzID0gIi1UIikKbXNfdHJlZV8xIDwtIHJlYWQudHJlZSh0ZXh0ID0gbXNfb3V0KQpwbG90KG1zX3RyZWVfMSkKYGBgCllvdSdsbCBub3RpY2UgdGhhdCB0aGUgdGlwIGxhYmVscyBydW4gZnJvbSBgczFgIHRocm91Z2ggYHMyNWAuIEVhY2ggY29ycmVzcG9uZHMgdG8gYSBkaWZmZXJlbnQgYWxsZWxlLiBUaGF0IHdhcyBwcmV0dHkgZWFzeSwgYnV0IHdlIGNhbiBkbyBhIGJpdCBtb3JlLiBXZSBjYW4gYXNrIGhvdyAiZGVlcCIgdGhlIHRyZWUgaXMsIGkuZS4sIGhvdyBmYXIgYmFjayBpbiB0aW1lIHdlIGhhdmUgdG8gZ28gdG8gZmluZCB0aGUgbW9zdCByZWNlbnQgY29tbW9uIGFuY2VzdG9yIG9mIGFsbCB0aGUgYWxsZWxlcyBpbiBvdXIgc2FtcGxlLgoKIyMjIEJyYW5jaGluZyB0aW1lcwoKYGBge3J9CmJyYW5jaGluZy50aW1lcyhtc190cmVlXzEpWzFdCmBgYAoKWW91J3JlIHByb2JhYmx5IHdvbmRlcmluZyBhYm91dCB0aGUgYFsxXWAgYWZ0ZXIgYGJyYW5jaGluZy50aW1lcygpYC4gV2VsbCwgYGJyYW5jaGluZy50aW1lcygpYCByZXR1cm5zIGEgdmVjdG9yIG9mICphbGwqIG9mIHRoZSBicmFuY2hpbmcgdGltZXMgaW4gdGhlIHRyZWUuCgpgYGB7cn0KYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWVfMSkKYGBgCgpUaGUgbnVtYmVycyAxMS0xOSBhcmUgdGhlIG5vZGUgbnVtYmVycyBpbiB0aGUgdHJlZSBhYm92ZS4KCmBgYHtyfQpwbG90KG1zX3RyZWVfMSkKbm9kZWxhYmVscygpCmBgYAoKQXMgeW91IGNhbiBzZWUsIG5vZGUgMTEgKHdoaWNoIGlzIHRoZSBmaXJzdCBvbmUgaW4gdGhlIGxpc3QpLCBpcyB0aGUgZGVlcGVzdCBub2RlLCBpLmUuLCB0aGUgbW9zdCByZWNlbnQgY29tbW9uIGFuY2VzdG9yIG9mIGFsbCBvZiB0aGUgYWxsZWxlcyBpbiBvdXIgc2FtcGxlLiAKCiMjIyBTY2FsaW5nIG9mIGJyYW5jaGluZyB0aW1lcwoKVGhlIG90aGVyIHRoaW5nIHlvdSBtYXkgYmUgd29uZGVyaW5nIGlzIGhvdyB0byBpbnRlcnByZXQgdGhlIG51bWJlciBgciBicmFuY2hpbmcudGltZXMobXNfdHJlZV8xKVsxXWAgdGhhdCBjb3JyZXNwb25kcyB0byB0aGUgdGltZSBvZiB0aGUgbW9zdCByZWNlbnQgY29tbW9uIGFuY2VzdG9yLl5bUmVtZW1iZXIgdGhhdCB3aGVuIHVzaW5nIHRoZSBjb2FsZXNjZW50LCB0aW1lIHJ1bnMgYmFja3dhcmRzLiBTbyB0aGUgdGltZSBvZiB0aGUgbW9zdCByZWNlbnQgY29tbW9uIGFuY2VzdG9yIGlzIGEgdGltZSBpbiB0aGUgcGFzdC5dIFRvIGV4cGxhaW4gdGhhdCBJIGhhdmUgdG8gcG9pbnQgb3V0IHNvbWV0aGluZyB0aGF0IHlvdSBtYXkgaGF2ZSBtaXNzZWQgd2hlbiB3ZSBjYWxsZWQgYG1zKClgOiBXZSBkaWRuJ3Qgc3BlY2lmeSBhIHBvcHVsYXRpb24gc2l6ZS4gSG93IGNhbiB3ZSBnZXQgYXdheSB3aXRoIHRoYXQsIHNpbmNlIEkgdG9sZCB5b3UgdGhhdCBkcmlmdCAqYWx3YXlzKiBkZXBlbmRzIG9uIHRoZSBwb3B1bGF0aW9uIHNpemU/CgpXZWxsLCByZW1lbWJlciB3aGF0IHlvdSBrbm93IGFib3V0IHRoZSBjb2FsZXNlbmN0IHByb2Nlc3MuIFRoZSBleHBlY3RlZCB0aW1lIHRvIGNvYWxlc2NlbmNlIG9mIGFsbCBhbGxlbGVzIGlzICQ0Tl9lJC4gYG1zKClgIHJlcG9ydHMgYnJhbmNoaW5nIHRpbWUgaW4gImNvYWxlc2NlbnQgdW5pdHMiIHdoZXJlIDEgdW5pdCBlcXVhbHMgJDROX2UkLiBTbyBpZiBgYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWVfMSlbMV1gIGlzIGByIGJyYW5jaGluZy50aW1lcyhtc190cmVlXzEpWzFdYCBhbmQgdGhlIGVmZmVjdGl2ZSBzaXplIG9mIG91ciBwb3B1bGF0aW9uIGlzIDI1LCB0aGVuIHRoZSB0aW1lIChudW1iZXIgb2YgZ2VuZXJhdGlvbnMgYmVmb3JlIHRoZSBwcmVzZW50KSB0byB0aGUgbW9zdCByZWNlbnQgY29tbW9uIGFuY2VzdG9yIGlzIGByIDQqMjUqYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWVfMSlbMV1gLiBOb3RpY2UgdGhhdCB0aGUgdGltZSBpc24ndCBhbiBpbnRlZ2VyIHRoZSB3YXkgeW91J2QgZXhwZWN0IGl0IHRvIGJlLiBUaGF0J3MgYmVjYXVzZSBvZiBhbiBhcHByb3hpbWF0aW9uIHRoYXQgaXMgZ2VuZXJhbGx5IHVzZWQgaW4gaW1wbGVtZW50aW5nIHRoZSBjb2FsZXNjZW50IGluIHNvZnR3YXJlLiBJZiB5b3Ugd2FudCB0byB0dXJuIGl0IGludG8gYW4gaW50ZWdlciwgeW91IGNhbiBkbyB0aGlzOgoKYGBge3J9CnJvdW5kKDQqMjUqYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWVfMSlbMV0pCmBgYAoKV2hldGhlciB5b3Ugcm91bmQgaXQgb3Igbm90LCB5b3UnbGwgc2VlIHRoYXQgdGhlIG1vc3QgcmVjZW50IGNvbW1vbiBhbmNlc3RvciBvZiB0aGUgYWxsZWxlcyBpbiBvdXIgc2FtcGxlIGRpZG4ndCBvY2N1ciBleGFjdGx5IDEwMCBnZW5lcmF0aW9ucyBhZ28gYXMgd2UnZCBleHBlY3QuIElmLCBob3dldmVyLCB3ZSByZXBlYXQgdGhhdCBzaW11bGF0aW9uIGEgYnVuY2ggb2YgdGltZXMsIHlvdSBjYW4gc2VlIHRoYXQgd2UgY29tZSBwcmV0dHkgY2xvc2UgLSBvbiBhdmVyYWdlLgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCk5fZSA9IDI1CgpjX3RpbWUgPC0gbnVtZXJpYygwKQpmb3IgKGkgaW4gMToxMDAwKSB7CiAgbXNfb3V0IDwtIG1zKG5zYW0gPSBOX2UsIG9wdHMgPSAiLVQiKQogIG1zX3RyZWUgPC0gcmVhZC50cmVlKHRleHQgPSBtc19vdXQpCiAgY190aW1lW2ldIDwtIDQqTl9lKmJyYW5jaGluZy50aW1lcyhtc190cmVlKVsxXQp9CnAgPC0gZ2dwbG90KGRhdGEuZnJhbWUodCA9IGNfdGltZSksIGFlcyh4ID0gdCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gNTAsIGFscGhhID0gMC42KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gNCpOX2UsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gInJlZCIpICsgCiAgdGhlbWVfYncoKQpwCmBgYAoKV2UgZXhwZWN0IGEgY29hbGVzY2VuY2UgdGltZSBvZiBgciA0Kk5fZWAgYW5kIG91ciBvYnNlcnZlZCBhdmVyYWdlIGNvYWxlc2NlbmNlIHRpbWUgaXMgYHIgbWVhbihjX3RpbWUpYC4gTm90IHRvbyBiYWQuCgojIyMgVGhlIGNvYWxlc2NlbnQgd2l0aCBtaWdyYXRpb24KCldoYXQgaGFwcGVucyB3aGVuIHdlIGhhdmUgYSBzdWJkaXZpZGVkIHBvcHVsYXRpb24gc28gdGhhdCB3ZSBoYXZlIHNldmVyYWwgcG9wdWxhdGlvbnMgZXhjaGFuZ2luZyBnZW5lcz8gSGVyZSdzIGhvdyB3ZSBzaW11bGF0ZSBhIGZpbml0ZSBpc2xhbmQgbW9kZWwgd2l0aCB0aHJlZSBwb3B1bGF0aW9ucywgbG9jYWwgcG9wdWxhdGlvbiBzaXplcyBvZiAxMCBpbiBlYWNoIHBvcHVsYXRpb24sIGFuZCAkTl9lbSA9IDIkLl5bTm90ZTogWW91J2xsIG5lZWQgdG8gaW5zdGFsbCBgUkNvbG9yQnJld2VyYCBpZiB5b3Ugd2FudCB0byBydW4gdGhpcyBjb2RlLl0KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShSQ29sb3JCcmV3ZXIpCgpnZXRfcG9wIDwtIGZ1bmN0aW9uKHRyZWUsIHNhbXBsZV9zaXplcywgaykgewogIGlkeCA8LSBhcy5udW1lcmljKGdzdWIoIl5zKC4qKSQiLCAiXFwxIiwgdHJlZSR0aXAubGFiZWwpKQogIGN1bSA8LSAwCiAgZm9yIChpIGluIDE6bGVuZ3RoKHNhbXBsZV9zaXplcykpIHsKICAgIGlmIChpZHhba10gPCBjdW0gKyBzYW1wbGVfc2l6ZXNbaV0gKyAxKSB7CiAgICAgIHJldHZhbCA8LSBpCiAgICAgIGJyZWFrCiAgICB9IGVsc2UgewogICAgICBjdW0gPC0gY3VtICsgc2FtcGxlX3NpemVzW2ldCiAgICB9CiAgfQogIHJldHVybihpKQp9Cgp0aXBjb2xvcnMgPC0gZnVuY3Rpb24odHJlZSwgc2FtcGxlX3NpemVzKSB7CiAgbXlfY29sb3JzIDwtIGJyZXdlci5wYWwobGVuZ3RoKHNhbXBsZV9zaXplcyksICJTZXQxIikKICBjb2xvcnMgPC0gbnVtZXJpYyhsZW5ndGgoc2FtcGxlX3NpemVzKSkKICBmb3IgKGkgaW4gMTpzdW0oc2FtcGxlX3NpemVzKSkgewogICAgY29sb3JzW2ldIDwtIG15X2NvbG9yc1tnZXRfcG9wKHRyZWUsIHNhbXBsZV9zaXplcywgaSldCiAgfQogIHJldHVybihjb2xvcnMpCn0KCiMjIE5vdGU6IHNhbXBsZSBzaXplcyBzaG91bGQgYmUgbXVsdGlwbGllZCBieSAyIGJlZm9yZSBjYWxsaW5nCiMjIGlzbGFuZCBmb3IgZGlwbG9pZCBzYW1wbGVzCiMjCmlzbGFuZCA8LSBmdW5jdGlvbihzYW1wbGVfc2l6ZXMsIG5lX20pIHsKICBvcHRfc3RyaW5nIDwtIHBhc3RlKCItVCAtSSAiLCBsZW5ndGgoc2FtcGxlX3NpemVzKSwgIiAiLCBzZXAgPSAiIikKICBmb3IgKGkgaW4gMTpsZW5ndGgoc2FtcGxlX3NpemVzKSkgewogICAgb3B0X3N0cmluZyA8LSBwYXN0ZShvcHRfc3RyaW5nLCBzYW1wbGVfc2l6ZXNbaV0sICIgIiwgc2VwID0gIiIpCiAgfQogIG9wdF9zdHJpbmcgPC0gcGFzdGUob3B0X3N0cmluZywgbmVfbSwgIlxuIiwgc2VwID0gIiIpCiAgbXNfb3V0IDwtIG1zKG5zYW0gPSBzdW0oc2FtcGxlX3NpemVzKSwgbnJlcHMgPSAxLCBvcHRzID0gb3B0X3N0cmluZykKICByZXR1cm4obXNfb3V0KSAgCn0KCnBsb3RfaXNsYW5kIDwtIGZ1bmN0aW9uKHNhbXBsZV9zaXplcywgbmVfbSkgewogIHNhbXBsZV9zaXplcyA8LSAyKnNhbXBsZV9zaXplcwogIG1zX291dCA8LSBpc2xhbmQoc2FtcGxlX3NpemVzLCBuZV9tKQogIG1zX3RyZWUgPC0gcmVhZC50cmVlKHRleHQgPSBtc19vdXQpCiAgcGxvdChtc190cmVlLCAKICAgICAgIHNob3cudGlwLmxhYmVsID0gRkFMU0UpCiAgdGlwbGFiZWxzKHBjaCA9IDE5LCBjZXggPSAwLjc1LCAKICAgICAgICAgICAgY29sID0gdGlwY29sb3JzKG1zX3RyZWUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX3NpemVzKSkKICByZXR1cm4oYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWUpWzFdKQp9Cgp0aW1lIDwtIHBsb3RfaXNsYW5kKHNhbXBsZV9zaXplcyA9IGMoNSwgNSwgNSksIG5lX20gPSAyKQpgYGAKVGhlIGNvbG9ycyBjb3JyZXNwb25kIHRvIHRoZSBwb3B1bGF0aW9uIGZyb20gd2hpY2ggZWFjaCBzYW1wbGUgd2FzIGNvbGxlY3RlZC4gYHBsb3RfaXNsYW5kKClgIHJldHVybnMgdGhlIHNjYWxlZCB0aW1lIHRvIHRoZSBtb3N0IHJlY2VudCBjb21tb24gYW5jZXN0b3IsIGByIHRpbWVgLiBXZSBhcmUgaW1wbGljaXRseSBhc3N1bWluZyB0aGF0IHRoZSBlZmZlY3RpdmUgcG9wdWxhdGlvbiBzaXplIGlzIHRoZSBzYW1lIGluIGVhY2ggbG9jYWwgcG9wdWxhdGlvbi5eW1RoZXJlIGlzIGEgd2F5IHRvIHJlbGF4IHRoaXMgYXNzdW1wdGlvbiwgYnV0IHdlIHdvbid0IHRha2UgYWR2YW50YWdlIG9mIGl0IGhlcmUuXSBUaGUgc2NhbGluZyBpcyBpbiB0ZXJtcyBvZiB0aGUgcHJvZHVjdCBvZiB0aGUgbG9jYWwgZWZmZWN0aXZlIHBvcHVsYXRpb24gc2l6ZSBhbmQgdGhlIG51bWJlciBvZiBwb3B1bGF0aW9ucywgaS5lLiwgMSBjb2FsZXNjZW50IHVuaXQgPSAkNE5fZWskLCB3aGVyZSAkayQgaXMgdGhlIG51bWJlciBvZiBwb3B1bGF0aW9ucy4KCiMjIExhYiA3CgpZb3Ugd2lsbCBiZSBwZXJmb3JtaW5nIGFub3RoZXIgc2V0IG9mIHNpbXVsYXRpb25zIHRoaXMgd2VlayB0byBjb21wYXJlIGNvYWxlc2NlbmNlIHRpbWVzIGluIHR3byBzY2VuYXJpb3M6CgoxLiBBIGZpbml0ZSBpc2xhbmQgbW9kZWwgb2YgbWlncmF0aW9uLgoyLiBBIG9uZS1kaW1lbnNpb25hbCBzdGVwcGluZyBzdG9uZSBtb2RlbCBvZiBtaWdyYXRpb24uCgpZb3UgYXJlIGFscmVhZHkgZmFtaWxpYXIgd2l0aCB0aGUgZmluaXRlIGlzbGFuZCBtb2RlbC4gSW4gYSBvbmUtZGltZW5zaW9uYWwgc3RlcHBpbmcgc3RvbmUgbW9kZWwsIHRoZSBwb3B1bGF0aW9ucyBhcmUgYXJyYW5nZWQgaW4gYSBsaW5lYXJ5IGFycmF5IGFuZCBvbmx5IHRob3NlIHBvcHVsYXRpb25zIHRoYXQgYXJlIGFkamFjZW50IHRvIG9uZSBhbm90aGVyIGNhbiBleGNoYW5nZSBtaWdyYW50cy4gSWYgJG0kIGlzIHRoZSBtaWdyYXRpb24gcmF0ZSwgaS5lLiwgdGhlIGZyYWN0aW9uIG9mIGEgcG9wdWxhdGlvbiBjb21wb3NlZCBvZiBtaWdyYW50cyB0aGVuIHRoZSBmcmFjdGlvbiBvZiBwb3B1bGF0aW9uICRpJCBkZXJpdmVkIGZyb20gcG9wdWxhdGlvbiAkaS0xJCBpcyAkXGZyYWN7bX17Mn0kIGFuZCB0aGUgZnJhY3Rpb24gb2YgcG9wdWxhdGlvbiAkaSQgZGVyaXZlZCBmcm9tIHBvcHVsYXRpb24gJGkrMSQgaXMgJFxmcmFje219ezJ9JC5eW05vdGU6IEZvciB0aGUgZmlyc3QgcG9wdWxhdGlvbiBpbiB0aGUgYXJyYXksIGkuZS4sIHBvcHVsYXRpb24gMSwgdGhlIGZyYWN0aW9uIG9mIHRoZSBwb3B1bGF0aW9uIGRlcml2ZWQgZnJvbSBwb3B1bGF0aW9uIDIgaXMgJG0kLiBTaW1pbGFybHksIGlmIHRoZXJlIGFyZSAkayQgcG9wdWxhdGlvbnMgaW4gdGhlIGFycnksIHRoZSBmcmFjdGlvbiBvZiBwb3B1bGF0aW9uICRrJCB0aGF0IGlzIGRlcml2ZWQgZnJvbSBwb3B1bGF0aW9uICRrLTEkIGlzICRtJC5dCgpVc2UgdGhlIGZ1bmN0aW9ucyBiZWxvdyB0byBleHBsb3JlIHRoZSBkaWZmZXJlbmNlIGluIGNvYWxlc2NlbmNlIHRpbWVzIGZvciBmaW5pdGUgaXNsYW5kIG1vZGVscyBhbmQgb25lLWRpbWVuc2lvbmFsIHN0ZXBwaW5nIHN0b25lIG1vZGVscyBvZiBtaWdyYXRpb24sIGFuZCBhbnN3ZXIgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6CgoxLiBIb3cgZG9lcyB0aGUgbnVtYmVyIG9mIHBvcHVsYXRpb25zIGluY2x1ZGVkIGFmZmVjdCB0aGUgYXZlYXJnZSB0aW1lIHRvIGNvYWxlc2NlbmNlIG9mIGFsbCBhbGxlbGVzPwoKMi4gSG93IGRvZXMgdGhlIG1pZ3JhdGlvbiByYXRlIGFmZmVjdCB0aGUgYXZlcmFnZSB0aW1lIHRvIGNvYWxlc2NlbmNlIG9mIGFsbCBhbGxlbGVzPwoKMy4gQXJlIHRoZXJlIGNvbnNpc3RlbnQgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgYXZlcmFnZSB0aW1lIHRvIGNvYWxlc2NlbmNlIGluIGEgZmluaXRlIGlzbGFuZCBtb2RlbCBhbmQgYSBvbmUtZGltZW5zaW9uYWwgc3RlcHBpbmcgc3RvbmUgbW9kZWw/IElmIHRoZXJlIGFyZSwgd2hhdCBtaWdodCBleHBsYWluIHRoZSBkaWZmZXJlbmNlIHRoYXQgeW91IHNlZT8KCiMjIyBIaW50cwoKYHJ1bl9zaW11bGF0aW9ucygpYCB3aWxsIGF1dG9tYXRpY2FsbHkga2VlcCB0aGUgbnVtYmVyIG9mIHBvcHVsYXRpb25zIGluIGJvdGggbW9kZWxzIHRoZSBzYW1lIHRvIGVuc3VyZSB0aGF0IHlvdSBjYW4gYWx3YXlzIG1ha2UgYXBwcm9wcmlhdGUgY29tcGFyaXNvbnMgb2YgdGhlIG1vZGVscy4gSXQgd2lsbCBhbHNvIHNldCB0aGUgbG9jYWwgZWZmZWN0aXZlIHBvcHVsYXRpb24gc2l6ZSB0byAyNSwgYW5kIGl0IHNldHMgdGhlIG51bWJlciBvZiByZXBsaWNhdGlvbnMgdG8gMTAwMCBieSBkZWZhdWx0LiBZb3UgbWlnaHQgd2FudCB0byBydW4gdGhlIGZ1bmN0aW9uIG9uY2Ugd2l0aCBgbl9yZXBzID0gMTAwYCB0byBnZXQgYSBmZWVsIGZvciBob3cgbG9uZyBpdCB3aWxsIHRha2UgdGhlIHNpbXVsYXRpb24gdG8gcnVuIG9uIHlvdXIgY29tcHV0ZXIgYmVmb3JlIHlvdSBiZWdpbiB0aGUgZnVsbC1zY2FsZSBzaW11bGF0aW9ucyAKCmBydW5fc2ltdWxhdGlvbnMoKWAgcmV0dXJucyBhIGRhdGEgZnJhbWVeW1dlbGwsIGFjdHVhbGx5IGEgdGliYmxlXSB3aXRoIHR3byBjb2x1bW5zOiBgTW9kZWxgIGFuZCBgVGltZWAuIElmIHlvdSdyZSBpbnRlcmVzdGVkLCB5b3UgY2FuIHVzZSB0aGF0IHRvIGV4YW1pbmUgdGhlIG1lZGlhbiB0aW1lIHRvIGNvYWxlc2NlbmNlIChyYXRoZXIgdGhhbiB0aGUgbWVhbikgYW5kIHRoZSB2YXJpYW5jZSAob3Igc3RhbmRhcmQgZGV2aWF0aW9uKSBpbiBjb2FsZXNjZW5jZSB0aW1lcy4gWW91J2xsIG5vdGljZSB0aGF0IGBydW5fc2ltdWxhdGlvbigpYCBhdXRvbWF0aWNhbGx5IHByaW50cyBvdXQgdGhlIG1lYW4gY29hbGVzZW5jZSB0aW1lcyBmb3IgeW91LgoKYGBge3J9CiMjIG9uZS1kaW1lbnNpb25hbCBzdGVwcGluZyBzdG9uZQojIwpvbmVfZF9zdGVwcGluZ19zdG9uZSA8LSBmdW5jdGlvbihuX2UsIG0sIG5fcG9wcykgewogIHN0b3BpZm5vdCgobSA+IDApICYmIChtIDwgMSkpCiAgbV9tYXRyaXggPC0gZGlhZygxIC0gbSwgbnJvdyA9IG5fcG9wcykKICBtX21hdHJpeFsxLCAyXSA8LSBtCiAgbV9tYXRyaXhbbl9wb3BzLCBuX3BvcHMgLSAxXSA8LSBtCiAgZm9yIChpIGluIDI6KG5fcG9wcyAtIDEpKSB7CiAgICBtX21hdHJpeFtpLCBpIC0gMV0gPC0gbS8yCiAgICBtX21hdHJpeFtpLCBpICsgMV0gPC0gbS8yCiAgfQogIG9wdF9zdHJpbmcgPC0gcGFzdGUoIi1UIC1JICIsIG5fcG9wcywgIiAiLCBzZXAgPSAiIikKICBmb3IgKGkgaW4gMTpuX3BvcHMpIHsKICAgIG9wdF9zdHJpbmcgPC0gcGFzdGUob3B0X3N0cmluZywgMipuX2UsICIgIiwgc2VwID0gIiIpCiAgfQogIG9wdF9zdHJpbmcgPC0gcGFzdGUob3B0X3N0cmluZywgIi1tYSIsIHNlcCA9ICIiKQogICMjIHRyYW5zcG9zZSBtX21hdHJpeCBiZWZvcmUgY29udmVydGluZyB0byB2ZWN0b3IgdG8gZ2V0IHZlY3RvciBmcm9tIG1hdHJpeAogICMjIGJ5IHJvdyBpbnN0ZWFkIG9mIGJ5IGNvbHVtbgogICMjCiAgbV92ZWN0b3IgPC0gNCpuX2UqYyh0KG1fbWF0cml4KSkKICBmb3IgKCBpIGluIDE6bGVuZ3RoKG1fdmVjdG9yKSkgewogICAgb3B0X3N0cmluZyA8LSBwYXN0ZShvcHRfc3RyaW5nLCAiICIsIG1fdmVjdG9yW2ldLCBzZXAgPSAiIikKICB9CiAgbXNfb3V0IDwtIG1zKG5zYW0gPSAyKm5fZSpuX3BvcHMsIG5yZXBzID0gMSwgb3B0cyA9IG9wdF9zdHJpbmcpCiAgcmV0dXJuKG1zX291dCkKfQoKcnVuX3NpbXVsYXRpb24gPC0gZnVuY3Rpb24obl9wb3BzLCBtLCBuX3JlcHMgPSAxMDAwKSB7CiAgTl9lID0gMjUKICBwb3Bfc2l6ZXMgPC0gcmVwKE5fZSwgbl9wb3BzKQogIGRmIDwtIHRpYmJsZShNb2RlbCA9IE5BLCBUaW1lID0gTkEpCiAgZm9yIChpIGluIDE6bl9yZXBzKSB7CiAgICBtc19vdXQgPC0gaXNsYW5kKHBvcF9zaXplcywgTl9lKm0pCiAgICBtc190cmVlIDwtIHJlYWQudHJlZSh0ZXh0ID0gbXNfb3V0KQogICAgZGYgPC0gYWRkX3JvdyhkZiwKICAgICAgICAgICAgICAgICAgTW9kZWwgPSAiSXNsYW5kIiwKICAgICAgICAgICAgICAgICAgVGltZSA9ICg0Kk5fZSpuX3BvcHMpKmJyYW5jaGluZy50aW1lcyhtc190cmVlKVsxXSkKICAgIG1zX291dCA8LSBvbmVfZF9zdGVwcGluZ19zdG9uZShOX2UsIG0sIG5fcG9wcykKICAgIG1zX3RyZWUgPC0gcmVhZC50cmVlKHRleHQgPSBtc19vdXQpCiAgICBkZiA8LSBhZGRfcm93KGRmLAogICAgICAgICAgICAgICAgICBNb2RlbCA9ICIxLWQiLAogICAgICAgICAgICAgICAgICBUaW1lID0gKDQqTl9lKm5fcG9wcykqYnJhbmNoaW5nLnRpbWVzKG1zX3RyZWUpWzFdKQogIH0KICBkZiA8LSBmaWx0ZXIoZGYsICFpcy5uYShNb2RlbCkpCiAgcCA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gVGltZSwgZmlsbCA9IE1vZGVsKSkgKwogICAgZ2VvbV9oaXN0b2dyYW0ocG9zaXRpb24gPSAiaWRlbnRpdHkiLCBiaW5zID0gbl9yZXBzLzEwLCBhbHBoYSA9IDAuNCkgKwogICAgZ2d0aXRsZShwYXN0ZSgibl9wb3BzID0gIiwgbl9wb3BzLCAiLCBtID0gIiwgbSkpICsKICAgIHRoZW1lX2J3KCkKICBwcmludChwKQogIHN1bSA8LSBkZiAlPiUgZ3JvdXBfYnkoTW9kZWwpICU+JQogICAgc3VtbWFyaXplKE1lYW5fVGltZSA9IG1lYW4oVGltZSkpCiAgcHJpbnQoc3VtKQogIHJldHVybihkZikKfQpgYGAK