#=========================================================
There were 20 warnings (use warnings() to see them)
# PREAMBLE
#=========================================================

# load the plotting library
suppressMessages(library(ggplot2))
library(gridExtra)
library(tikzDevice)


theme_set(theme_bw())

options(scipen=999)  # turn-off scientific notation like 1e+48

# size of point for scatterplots
POINT_SIZE = 0.5
#POINT_SIZE = 1

# timeout
TIMEOUT = params$timeout
TIMEOUT_VAL = 1.05 * TIMEOUT

TIME_MIN = 0.01 # seconds

# FUNCTIONS
read_file <- function(file) {
  filename = paste0(file)
  df <- read.csv2(filename,
                  header=TRUE,
                  sep=";",
                  dec=",",
                  comment.char="",
                  strip.white=TRUE,
                  stringsAsFactors=FALSE)
  
  
  return(df)
}

plot_scatter_log <- function(df, xlab, ylab, xstring=xlab, ystring=ylab) {
  pscat <- ggplot(df, aes_string(x=xlab, y=ylab)) +
    geom_point(size=POINT_SIZE) +
    geom_abline(size=0.1) +
    geom_vline(size=0.1, xintercept=TIMEOUT_VAL, linetype="dashed") +
    geom_hline(size=0.1, yintercept=TIMEOUT_VAL, linetype="dashed") +
    scale_x_log10() +
    scale_y_log10() +
    theme(axis.text.y = element_text(angle = 90, hjust = 0.5)) +
    #coord_fixed(xlim = c(TIME_MIN, TIMEOUT_VAL), ylim = c(0.1, TIMEOUT_VAL)) +
    coord_fixed(xlim = c(TIME_MIN, TIMEOUT_VAL), ylim = c(TIME_MIN, TIMEOUT_VAL)) +

    labs(
      #title="Title",
      #subtitle="Subtitle",
      x=xstring,
      y=ystring)
  return(pscat)
}

make_tikz <- function(file, picture, width=2.5, height=2.5) {
  font_size <- 1
  tikz(file=file, onefile=T, width=width, height=height)
  plot(picture)
  garbage <- dev.off()
}
df <- read_file(params$file_cmp)

######################### SANITIZE ###############################
tools.times <- c("re2g", "cad", "grep", "srm", "dot.net")
tools.matches <- c("re2g.matches", "cad.matches", "grep.matches", "srm.matches", "dot.net.matches")

# change the type of columns other than the name
for (i in tools.times) {
  df[,i] <- sub(",", ".", df[,i])
  suppressWarnings(df[,i] <- as.numeric(df[,i]))
}

for (i in tools.matches) {
  suppressWarnings(df[,i] <- as.integer(df[,i]))
}

# get rid of extremal values
df[tools.times][is.na(df[tools.times])] <- TIMEOUT_VAL
#df[is.na(df)] <- TIMEOUT_VAL
#df[df == 0.00] <- TIME_MIN
df[,tools.times][df[,tools.times] == 0] <- TIME_MIN

# clean the data
#df_new <- df[df$Lines != "ERROR WHILE CONVERTING TO DCA.",]
#print(paste0("Removing ", nrow(df) - nrow(df_new), " lines due to converting to DCA error"))
#df <- df_new



############################## COUNTING TIMEOUTS #######################
timeouts.re2 <- nrow(df[df$re2g == TIMEOUT_VAL,])
timeouts.ca <- nrow(df[df$cad == TIMEOUT_VAL,])
timeouts.grep <- nrow(df[df$grep == TIMEOUT_VAL,])
timeouts.srm <- nrow(df[df$srm == TIMEOUT_VAL,])
timeouts.dot.net <- nrow(df[df$dot.net == TIMEOUT_VAL,])
timeouts.re2.and.ca <- nrow(df[df$cad == TIMEOUT_VAL & df$re2g == TIMEOUT_VAL,])

These are results of the experiments for Counting Set Automata:

File results-10-05-2020/table-ALL.csv
Timeout 300 s
Benchmarks 4315
Timeouts CA 0
Timeouts RE2 25
Timeouts SRM 25
Timeouts grep 239
Timeouts .NET 42
df

Sanity checks

df$inconsistent <- df$re2g.matches != df$grep.matches | df$re2g.matches != df$srm.matches | df$re2g.matches != df$dot.net.matches | df$re2g.matches != df$cad.matches

df$grep.re2.mismatch <- !is.na(df$re2g.matches) & !is.na(df$grep.matches) & df$re2g.matches != df$grep.matches
df_grep_re2_mismatch <- df[df$grep.re2.mismatch,]

df$re2.ca.mismatch <- !is.na(df$re2g.matches) & !is.na(df$cad.matches) & df$re2g.matches != df$cad.matches
df_re2_ca_mismatch <- df[df$re2.ca.mismatch,]
grep and RE2 mismatched 1110
CA and RE2 mismatched 103

RE2 and CA mismatches

df_re2_ca_mismatch

Scatter Plots


plot.and.tikz <- function(df, xlab, ylab, xstring=xlab, ystring=ylab) {
  pic <- plot_scatter_log(df, xlab, ylab, xstring, ystring)
  make_tikz(paste0("figs/", xlab, "-vs-", ylab, ".tikz"), pic, width=4, height=4)
  pic
}

plot1 <- plot.and.tikz(df, "re2g", "cad", xstring="RE2 [s]", ystring="CA [s]")
plot2 <- plot.and.tikz(df, "grep", "cad", xstring="grep [s]", ystring="CA [s]")
plot3 <- plot.and.tikz(df, "srm", "cad", xstring="SRM [s]", ystring="CA [s]")
plot4 <- plot.and.tikz(df, "dot.net", "cad", xstring=".NET [s]", ystring="CA [s]")
plot5 <- plot.and.tikz(df, "srm", "re2g")
plot6 <- plot.and.tikz(df, "grep", "re2g")
plot7 <- plot.and.tikz(df, "dot.net", "re2g")
plot8 <- plot.and.tikz(df, "srm", "grep")
plot9 <- plot.and.tikz(df, "dot.net", "grep")
plot10 <- plot.and.tikz(df, "dot.net", "srm")



grid.arrange(plot1, plot2, ncol = 2)

grid.arrange(plot3, plot4, ncol = 2)

grid.arrange(plot5, plot6, ncol = 2)

grid.arrange(plot7, plot8, ncol = 2)

grid.arrange(plot9, plot10, ncol = 2)

Histograms

hist1 <- ggplot(df, aes(x=re2g)) +
  geom_histogram(color="blue", fill="lightblue") +
  scale_y_log10()

hist2 <- ggplot(df, aes(x=cad)) + 
  geom_histogram(color="blue", fill="lightblue") +
  scale_y_log10()

hist3 <- ggplot(df, aes(x=srm)) + 
  geom_histogram(color="blue", fill="lightblue") +
  scale_y_log10()

hist4 <- ggplot(df, aes(x=grep)) + 
  geom_histogram(color="blue", fill="lightblue") +
  scale_y_log10()

hist5 <- ggplot(df, aes(x=dot.net)) + 
  geom_histogram(color="blue", fill="lightblue") +
  scale_y_log10()

grid.arrange(hist1, hist2, ncol = 2)

grid.arrange(hist3, hist4, ncol = 2)

grid.arrange(hist5, ncol = 2)

NA
NA

Finding winners

df$min <-pmin(df$grep, df$srm, df$re2g, df$dot.net, df$cad)
df$enemy.min <- pmin(df$grep, df$srm, df$re2g, df$dot.net)

winners.grep <- nrow(df[df$min == df$grep,])
winners.re2 <- nrow(df[df$min == df$re2g,])
winners.ca <- nrow(df[df$min == df$cad,])
winners.srm <- nrow(df[df$min == df$srm,])
winners.dot.net <- nrow(df[df$min == df$dot.net,])
Winner
CA 32
RE2 3759
SRM 7
grep 1736
.NET 64
plot.and.tikz(df, "enemy.min", "cad", xstring="best enemy", ystring="CA [s]")

How much we are better than RE2

df$re2.vs.ca <- df$re2g / df$cad
Warning messages:
1: In readChar(file, size, TRUE) : truncating string with embedded nuls
2: In readChar(file, size, TRUE) : truncating string with embedded nuls
3: In readChar(file, size, TRUE) : truncating string with embedded nuls
4: In readChar(file, size, TRUE) : truncating string with embedded nuls
5: In readChar(file, size, TRUE) : truncating string with embedded nuls
6: In readChar(file, size, TRUE) : truncating string with embedded nuls
7: In readChar(file, size, TRUE) : truncating string with embedded nuls
8: In readChar(file, size, TRUE) : truncating string with embedded nuls
9: In readChar(file, size, TRUE) : truncating string with embedded nuls
10: In readChar(file, size, TRUE) : truncating string with embedded nuls
df_sorted <- df[order(df$re2.vs.ca, decreasing=TRUE),]

df_sorted[,c("src", "pattern", "file", "re2g", "cad", "re2.vs.ca")]

Experiments with increasing counter value

big <- read_file(params$file_big)
big$re2g <- sub(",", ".", big$re2g)
big$re2g <- as.numeric(big$re2g)
NAs introduced by coercion
big

together <- big[, c("Counter", "re2g")]
names(together)[2] <- "time"
together$approach <- "re2g"

tmp <- big[, c("Counter", "ca")]
names(tmp)[2] <- "time"
tmp$approach <- "ca"

together <- rbind(together, tmp)

big_plot <- ggplot(data=together, aes(x=Counter, y=time, colour=approach)) +
  geom_line() +
  xlim(NA,1250) +
  theme(legend.position = c(.05, .95),
        legend.justification = c("left", "top"),
        #legend.box.background = element_rect(color="black", size=0.5),
        legend.box.just = "right",
        legend.margin = margin(1, 1, 1, 1),
        legend.title = element_blank()) +
  labs(
      #title="Title",
      #subtitle="Subtitle",
      x="$k$",
      y="time [s]")
        

  # geom_line(data = big, aes(x = Counter, y = re2g), color = "red") +
  # geom_line(data = big, aes(x = Counter, y = ca), color = "blue") +
  # xlab('counter value') +
  # ylab('time [s]')

make_tikz(paste0("figs/big_plot.tikz"), big_plot, width=2.7, height=2.7)

plot(big_plot)

# Information about DCAs

df_dcas = read.csv2(params$file_dca,
                  header=TRUE,
                  sep="\t",
                  dec=".",
                  comment.char="",
                  quote="",
                  strip.white=TRUE,
                  stringsAsFactors=FALSE)

# sanitize
df_dcas$timeouts.classical[is.na(df_dcas$timeouts.classical)] <- 0

#df_dcas
tms.classical <- df_dcas[df_dcas$timeouts.classical == 1,]
compute_timeouts <- function(df, col) {
  tmp <- df[df[, col] == TIMEOUT_VAL,]
  tmp
}
LS0tCnRpdGxlOiAiQ250LVNldC1NYXRhIEFuYWx5c2lzIgpwYXJhbXM6CiAgI2ZpbGVfY21wOiBkYXRhL3Jlc3VsdHMtMjMtMDQtMjAyMC5jc3YKICAjZmlsZV9jbXA6IHJlc3VsdHMtMDUtMDUtMjAyMC9iZXR3ZWVuL3Jlc3VsdHMuY3N2CiAgI2ZpbGVfY21wOiByZXN1bHRzLTA5LTA1LTIwMjAvYmV0d2Vlbi9SRVNVTFRTLUFMTC1iZXR3ZWVuLmNzdgogIGZpbGVfY21wOiByZXN1bHRzLTEwLTA1LTIwMjAvdGFibGUtQUxMLmNzdgogIGZpbGVfYmlnOiByZXN1bHRzLTA1LTA1LTIwMjAvdGFibGUtYmlnLTI1MDM2MTAyLmNzdgogIGZpbGVfZGNhOiBEQ0FzL3Jlc3VsdHMtdHJhbnNsYXRpb24udHN2CiAgdGltZW91dDogMzAwICMgc2Vjb25kcwpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKYGBge3J9CiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyBQUkVBTUJMRQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojIGxvYWQgdGhlIHBsb3R0aW5nIGxpYnJhcnkKc3VwcHJlc3NNZXNzYWdlcyhsaWJyYXJ5KGdncGxvdDIpKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeSh0aWt6RGV2aWNlKQoKCnRoZW1lX3NldCh0aGVtZV9idygpKQoKb3B0aW9ucyhzY2lwZW49OTk5KSAgIyB0dXJuLW9mZiBzY2llbnRpZmljIG5vdGF0aW9uIGxpa2UgMWUrNDgKCiMgc2l6ZSBvZiBwb2ludCBmb3Igc2NhdHRlcnBsb3RzClBPSU5UX1NJWkUgPSAwLjUKI1BPSU5UX1NJWkUgPSAxCgojIHRpbWVvdXQKVElNRU9VVCA9IHBhcmFtcyR0aW1lb3V0ClRJTUVPVVRfVkFMID0gMS4wNSAqIFRJTUVPVVQKClRJTUVfTUlOID0gMC4wMSAjIHNlY29uZHMKCiMgRlVOQ1RJT05TCnJlYWRfZmlsZSA8LSBmdW5jdGlvbihmaWxlKSB7CiAgZmlsZW5hbWUgPSBwYXN0ZTAoZmlsZSkKICBkZiA8LSByZWFkLmNzdjIoZmlsZW5hbWUsCiAgICAgICAgICAgICAgICAgIGhlYWRlcj1UUlVFLAogICAgICAgICAgICAgICAgICBzZXA9IjsiLAogICAgICAgICAgICAgICAgICBkZWM9IiwiLAogICAgICAgICAgICAgICAgICBjb21tZW50LmNoYXI9IiIsCiAgICAgICAgICAgICAgICAgIHN0cmlwLndoaXRlPVRSVUUsCiAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCiAgCiAgCiAgcmV0dXJuKGRmKQp9CgpwbG90X3NjYXR0ZXJfbG9nIDwtIGZ1bmN0aW9uKGRmLCB4bGFiLCB5bGFiLCB4c3RyaW5nPXhsYWIsIHlzdHJpbmc9eWxhYikgewogIHBzY2F0IDwtIGdncGxvdChkZiwgYWVzX3N0cmluZyh4PXhsYWIsIHk9eWxhYikpICsKICAgIGdlb21fcG9pbnQoc2l6ZT1QT0lOVF9TSVpFKSArCiAgICBnZW9tX2FibGluZShzaXplPTAuMSkgKwogICAgZ2VvbV92bGluZShzaXplPTAuMSwgeGludGVyY2VwdD1USU1FT1VUX1ZBTCwgbGluZXR5cGU9ImRhc2hlZCIpICsKICAgIGdlb21faGxpbmUoc2l6ZT0wLjEsIHlpbnRlcmNlcHQ9VElNRU9VVF9WQUwsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMC41KSkgKwogICAgI2Nvb3JkX2ZpeGVkKHhsaW0gPSBjKFRJTUVfTUlOLCBUSU1FT1VUX1ZBTCksIHlsaW0gPSBjKDAuMSwgVElNRU9VVF9WQUwpKSArCiAgICBjb29yZF9maXhlZCh4bGltID0gYyhUSU1FX01JTiwgVElNRU9VVF9WQUwpLCB5bGltID0gYyhUSU1FX01JTiwgVElNRU9VVF9WQUwpKSArCgogICAgbGFicygKICAgICAgI3RpdGxlPSJUaXRsZSIsCiAgICAgICNzdWJ0aXRsZT0iU3VidGl0bGUiLAogICAgICB4PXhzdHJpbmcsCiAgICAgIHk9eXN0cmluZykKICByZXR1cm4ocHNjYXQpCn0KCm1ha2VfdGlreiA8LSBmdW5jdGlvbihmaWxlLCBwaWN0dXJlLCB3aWR0aD0yLjUsIGhlaWdodD0yLjUpIHsKICBmb250X3NpemUgPC0gMQogIHRpa3ooZmlsZT1maWxlLCBvbmVmaWxlPVQsIHdpZHRoPXdpZHRoLCBoZWlnaHQ9aGVpZ2h0KQogIHBsb3QocGljdHVyZSkKICBnYXJiYWdlIDwtIGRldi5vZmYoKQp9CmBgYAoKYGBge3J9CmRmIDwtIHJlYWRfZmlsZShwYXJhbXMkZmlsZV9jbXApCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIFNBTklUSVpFICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKdG9vbHMudGltZXMgPC0gYygicmUyZyIsICJjYWQiLCAiZ3JlcCIsICJzcm0iLCAiZG90Lm5ldCIpCnRvb2xzLm1hdGNoZXMgPC0gYygicmUyZy5tYXRjaGVzIiwgImNhZC5tYXRjaGVzIiwgImdyZXAubWF0Y2hlcyIsICJzcm0ubWF0Y2hlcyIsICJkb3QubmV0Lm1hdGNoZXMiKQoKIyBjaGFuZ2UgdGhlIHR5cGUgb2YgY29sdW1ucyBvdGhlciB0aGFuIHRoZSBuYW1lCmZvciAoaSBpbiB0b29scy50aW1lcykgewogIGRmWyxpXSA8LSBzdWIoIiwiLCAiLiIsIGRmWyxpXSkKICBzdXBwcmVzc1dhcm5pbmdzKGRmWyxpXSA8LSBhcy5udW1lcmljKGRmWyxpXSkpCn0KCmZvciAoaSBpbiB0b29scy5tYXRjaGVzKSB7CiAgc3VwcHJlc3NXYXJuaW5ncyhkZlssaV0gPC0gYXMuaW50ZWdlcihkZlssaV0pKQp9CgojIGdldCByaWQgb2YgZXh0cmVtYWwgdmFsdWVzCmRmW3Rvb2xzLnRpbWVzXVtpcy5uYShkZlt0b29scy50aW1lc10pXSA8LSBUSU1FT1VUX1ZBTAojZGZbaXMubmEoZGYpXSA8LSBUSU1FT1VUX1ZBTAojZGZbZGYgPT0gMC4wMF0gPC0gVElNRV9NSU4KZGZbLHRvb2xzLnRpbWVzXVtkZlssdG9vbHMudGltZXNdID09IDBdIDwtIFRJTUVfTUlOCgojIGNsZWFuIHRoZSBkYXRhCiNkZl9uZXcgPC0gZGZbZGYkTGluZXMgIT0gIkVSUk9SIFdISUxFIENPTlZFUlRJTkcgVE8gRENBLiIsXQojcHJpbnQocGFzdGUwKCJSZW1vdmluZyAiLCBucm93KGRmKSAtIG5yb3coZGZfbmV3KSwgIiBsaW5lcyBkdWUgdG8gY29udmVydGluZyB0byBEQ0EgZXJyb3IiKSkKI2RmIDwtIGRmX25ldwoKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgQ09VTlRJTkcgVElNRU9VVFMgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKdGltZW91dHMucmUyIDwtIG5yb3coZGZbZGYkcmUyZyA9PSBUSU1FT1VUX1ZBTCxdKQp0aW1lb3V0cy5jYSA8LSBucm93KGRmW2RmJGNhZCA9PSBUSU1FT1VUX1ZBTCxdKQp0aW1lb3V0cy5ncmVwIDwtIG5yb3coZGZbZGYkZ3JlcCA9PSBUSU1FT1VUX1ZBTCxdKQp0aW1lb3V0cy5zcm0gPC0gbnJvdyhkZltkZiRzcm0gPT0gVElNRU9VVF9WQUwsXSkKdGltZW91dHMuZG90Lm5ldCA8LSBucm93KGRmW2RmJGRvdC5uZXQgPT0gVElNRU9VVF9WQUwsXSkKdGltZW91dHMucmUyLmFuZC5jYSA8LSBucm93KGRmW2RmJGNhZCA9PSBUSU1FT1VUX1ZBTCAmIGRmJHJlMmcgPT0gVElNRU9VVF9WQUwsXSkKYGBgCgpUaGVzZSBhcmUgcmVzdWx0cyBvZiB0aGUgZXhwZXJpbWVudHMgZm9yIENvdW50aW5nIFNldCBBdXRvbWF0YToKCnwgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfAp8LS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tOnwKfCAqKkZpbGUqKiAgICAgICAgICAgIHwgYHIgcGFyYW1zJGZpbGVfY21wYCB8CnwgKipUaW1lb3V0KiogICAgICAgICB8IGByIFRJTUVPVVRgIHMgICAgICAgfAp8ICoqQmVuY2htYXJrcyoqICAgICAgfCBgciBucm93KGRmKWAgICAgICAgIHwKfCAqKlRpbWVvdXRzIENBKiogICAgIHwgYHIgdGltZW91dHMuY2FgICAgICB8CnwgKipUaW1lb3V0cyBSRTIqKiAgICB8IGByIHRpbWVvdXRzLnJlMmAgICAgfAp8ICoqVGltZW91dHMgU1JNKiogICAgfCBgciB0aW1lb3V0cy5zcm1gICAgIHwgCnwgKipUaW1lb3V0cyBncmVwKiogICAgfCBgciB0aW1lb3V0cy5ncmVwYCAgfAp8ICoqVGltZW91dHMgLk5FVCoqICAgIHwgYHIgdGltZW91dHMuZG90Lm5ldGAgIHwKCgpgYGB7cn0KZGYKYGBgCgojIFNhbml0eSBjaGVja3MKCmBgYHtyfQpkZiRpbmNvbnNpc3RlbnQgPC0gZGYkcmUyZy5tYXRjaGVzICE9IGRmJGdyZXAubWF0Y2hlcyB8IGRmJHJlMmcubWF0Y2hlcyAhPSBkZiRzcm0ubWF0Y2hlcyB8IGRmJHJlMmcubWF0Y2hlcyAhPSBkZiRkb3QubmV0Lm1hdGNoZXMgfCBkZiRyZTJnLm1hdGNoZXMgIT0gZGYkY2FkLm1hdGNoZXMKCmRmJGdyZXAucmUyLm1pc21hdGNoIDwtICFpcy5uYShkZiRyZTJnLm1hdGNoZXMpICYgIWlzLm5hKGRmJGdyZXAubWF0Y2hlcykgJiBkZiRyZTJnLm1hdGNoZXMgIT0gZGYkZ3JlcC5tYXRjaGVzCmRmX2dyZXBfcmUyX21pc21hdGNoIDwtIGRmW2RmJGdyZXAucmUyLm1pc21hdGNoLF0KCmRmJHJlMi5jYS5taXNtYXRjaCA8LSAhaXMubmEoZGYkcmUyZy5tYXRjaGVzKSAmICFpcy5uYShkZiRjYWQubWF0Y2hlcykgJiBkZiRyZTJnLm1hdGNoZXMgIT0gZGYkY2FkLm1hdGNoZXMKZGZfcmUyX2NhX21pc21hdGNoIDwtIGRmW2RmJHJlMi5jYS5taXNtYXRjaCxdCgpgYGAKCnwgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS06fAp8ICoqZ3JlcCBhbmQgUkUyIG1pc21hdGNoZWQqKiB8IGByIG5yb3coZGZfZ3JlcF9yZTJfbWlzbWF0Y2gpYCB8CnwgKipDQSBhbmQgUkUyIG1pc21hdGNoZWQqKiAgIHwgYHIgbnJvdyhkZl9yZTJfY2FfbWlzbWF0Y2gpYCAgIHwKCiMjIFJFMiBhbmQgQ0EgbWlzbWF0Y2hlcwpgYGB7cn0KZGZfcmUyX2NhX21pc21hdGNoCmBgYAoKCgojIFNjYXR0ZXIgUGxvdHMKCmBgYHtyfQoKcGxvdC5hbmQudGlreiA8LSBmdW5jdGlvbihkZiwgeGxhYiwgeWxhYiwgeHN0cmluZz14bGFiLCB5c3RyaW5nPXlsYWIpIHsKICBwaWMgPC0gcGxvdF9zY2F0dGVyX2xvZyhkZiwgeGxhYiwgeWxhYiwgeHN0cmluZywgeXN0cmluZykKICBtYWtlX3Rpa3oocGFzdGUwKCJmaWdzLyIsIHhsYWIsICItdnMtIiwgeWxhYiwgIi50aWt6IiksIHBpYywgd2lkdGg9NCwgaGVpZ2h0PTQpCiAgcGljCn0KCnBsb3QxIDwtIHBsb3QuYW5kLnRpa3ooZGYsICJyZTJnIiwgImNhZCIsIHhzdHJpbmc9IlJFMiBbc10iLCB5c3RyaW5nPSJDQSBbc10iKQpwbG90MiA8LSBwbG90LmFuZC50aWt6KGRmLCAiZ3JlcCIsICJjYWQiLCB4c3RyaW5nPSJncmVwIFtzXSIsIHlzdHJpbmc9IkNBIFtzXSIpCnBsb3QzIDwtIHBsb3QuYW5kLnRpa3ooZGYsICJzcm0iLCAiY2FkIiwgeHN0cmluZz0iU1JNIFtzXSIsIHlzdHJpbmc9IkNBIFtzXSIpCnBsb3Q0IDwtIHBsb3QuYW5kLnRpa3ooZGYsICJkb3QubmV0IiwgImNhZCIsIHhzdHJpbmc9Ii5ORVQgW3NdIiwgeXN0cmluZz0iQ0EgW3NdIikKcGxvdDUgPC0gcGxvdC5hbmQudGlreihkZiwgInNybSIsICJyZTJnIikKcGxvdDYgPC0gcGxvdC5hbmQudGlreihkZiwgImdyZXAiLCAicmUyZyIpCnBsb3Q3IDwtIHBsb3QuYW5kLnRpa3ooZGYsICJkb3QubmV0IiwgInJlMmciKQpwbG90OCA8LSBwbG90LmFuZC50aWt6KGRmLCAic3JtIiwgImdyZXAiKQpwbG90OSA8LSBwbG90LmFuZC50aWt6KGRmLCAiZG90Lm5ldCIsICJncmVwIikKcGxvdDEwIDwtIHBsb3QuYW5kLnRpa3ooZGYsICJkb3QubmV0IiwgInNybSIpCgoKCmdyaWQuYXJyYW5nZShwbG90MSwgcGxvdDIsIG5jb2wgPSAyKQpncmlkLmFycmFuZ2UocGxvdDMsIHBsb3Q0LCBuY29sID0gMikKZ3JpZC5hcnJhbmdlKHBsb3Q1LCBwbG90NiwgbmNvbCA9IDIpCmdyaWQuYXJyYW5nZShwbG90NywgcGxvdDgsIG5jb2wgPSAyKQpncmlkLmFycmFuZ2UocGxvdDksIHBsb3QxMCwgbmNvbCA9IDIpCmBgYAoKCiMgSGlzdG9ncmFtcwoKYGBge3J9Cmhpc3QxIDwtIGdncGxvdChkZiwgYWVzKHg9cmUyZykpICsKICBnZW9tX2hpc3RvZ3JhbShjb2xvcj0iYmx1ZSIsIGZpbGw9ImxpZ2h0Ymx1ZSIpICsKICBzY2FsZV95X2xvZzEwKCkKCmhpc3QyIDwtIGdncGxvdChkZiwgYWVzKHg9Y2FkKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShjb2xvcj0iYmx1ZSIsIGZpbGw9ImxpZ2h0Ymx1ZSIpICsKICBzY2FsZV95X2xvZzEwKCkKCmhpc3QzIDwtIGdncGxvdChkZiwgYWVzKHg9c3JtKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShjb2xvcj0iYmx1ZSIsIGZpbGw9ImxpZ2h0Ymx1ZSIpICsKICBzY2FsZV95X2xvZzEwKCkKCmhpc3Q0IDwtIGdncGxvdChkZiwgYWVzKHg9Z3JlcCkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oY29sb3I9ImJsdWUiLCBmaWxsPSJsaWdodGJsdWUiKSArCiAgc2NhbGVfeV9sb2cxMCgpCgpoaXN0NSA8LSBnZ3Bsb3QoZGYsIGFlcyh4PWRvdC5uZXQpKSArIAogIGdlb21faGlzdG9ncmFtKGNvbG9yPSJibHVlIiwgZmlsbD0ibGlnaHRibHVlIikgKwogIHNjYWxlX3lfbG9nMTAoKQoKZ3JpZC5hcnJhbmdlKGhpc3QxLCBoaXN0MiwgbmNvbCA9IDIpCmdyaWQuYXJyYW5nZShoaXN0MywgaGlzdDQsIG5jb2wgPSAyKQpncmlkLmFycmFuZ2UoaGlzdDUsIG5jb2wgPSAyKQoKCmBgYAoKIyBGaW5kaW5nIHdpbm5lcnMKCmBgYHtyfQpkZiRtaW4gPC1wbWluKGRmJGdyZXAsIGRmJHNybSwgZGYkcmUyZywgZGYkZG90Lm5ldCwgZGYkY2FkKQpkZiRlbmVteS5taW4gPC0gcG1pbihkZiRncmVwLCBkZiRzcm0sIGRmJHJlMmcsIGRmJGRvdC5uZXQpCgp3aW5uZXJzLmdyZXAgPC0gbnJvdyhkZltkZiRtaW4gPT0gZGYkZ3JlcCxdKQp3aW5uZXJzLnJlMiA8LSBucm93KGRmW2RmJG1pbiA9PSBkZiRyZTJnLF0pCndpbm5lcnMuY2EgPC0gbnJvdyhkZltkZiRtaW4gPT0gZGYkY2FkLF0pCndpbm5lcnMuc3JtIDwtIG5yb3coZGZbZGYkbWluID09IGRmJHNybSxdKQp3aW5uZXJzLmRvdC5uZXQgPC0gbnJvdyhkZltkZiRtaW4gPT0gZGYkZG90Lm5ldCxdKQpgYGAKCnwgKipXaW5uZXIqKiAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfAp8LS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tOnwKfCAqKkNBKiogICAgIHwgYHIgd2lubmVycy5jYWAgICAgIHwKfCAqKlJFMioqICAgIHwgYHIgd2lubmVycy5yZTJgICAgIHwKfCAqKlNSTSoqICAgIHwgYHIgd2lubmVycy5zcm1gICAgIHwgCnwgKipncmVwKiogICAgfCBgciB3aW5uZXJzLmdyZXBgICB8CnwgKiouTkVUKiogICAgfCBgciB3aW5uZXJzLmRvdC5uZXRgICB8CgpgYGB7cn0KcGxvdC5hbmQudGlreihkZiwgImVuZW15Lm1pbiIsICJjYWQiLCB4c3RyaW5nPSJiZXN0IGVuZW15IiwgeXN0cmluZz0iQ0EgW3NdIikKYGBgCgojIEhvdyBtdWNoIHdlIGFyZSBiZXR0ZXIgdGhhbiBSRTIKCmBgYHtyfQpkZiRyZTIudnMuY2EgPC0gZGYkcmUyZyAvIGRmJGNhZApkZl9zb3J0ZWQgPC0gZGZbb3JkZXIoZGYkcmUyLnZzLmNhLCBkZWNyZWFzaW5nPVRSVUUpLF0KCmRmX3NvcnRlZFssYygic3JjIiwgInBhdHRlcm4iLCAiZmlsZSIsICJyZTJnIiwgImNhZCIsICJyZTIudnMuY2EiKV0KYGBgCgoKIyBFeHBlcmltZW50cyB3aXRoIGluY3JlYXNpbmcgY291bnRlciB2YWx1ZQoKYGBge3J9CmJpZyA8LSByZWFkX2ZpbGUocGFyYW1zJGZpbGVfYmlnKQpiaWckcmUyZyA8LSBzdWIoIiwiLCAiLiIsIGJpZyRyZTJnKQpiaWckcmUyZyA8LSBhcy5udW1lcmljKGJpZyRyZTJnKQoKYmlnCmBgYAoKCmBgYHtyfQoKdG9nZXRoZXIgPC0gYmlnWywgYygiQ291bnRlciIsICJyZTJnIildCm5hbWVzKHRvZ2V0aGVyKVsyXSA8LSAidGltZSIKdG9nZXRoZXIkYXBwcm9hY2ggPC0gInJlMmciCgp0bXAgPC0gYmlnWywgYygiQ291bnRlciIsICJjYSIpXQpuYW1lcyh0bXApWzJdIDwtICJ0aW1lIgp0bXAkYXBwcm9hY2ggPC0gImNhIgoKdG9nZXRoZXIgPC0gcmJpbmQodG9nZXRoZXIsIHRtcCkKCmJpZ19wbG90IDwtIGdncGxvdChkYXRhPXRvZ2V0aGVyLCBhZXMoeD1Db3VudGVyLCB5PXRpbWUsIGNvbG91cj1hcHByb2FjaCkpICsKICBnZW9tX2xpbmUoKSArCiAgeGxpbShOQSwxMjUwKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYyguMDUsIC45NSksCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKCJsZWZ0IiwgInRvcCIpLAogICAgICAgICNsZWdlbmQuYm94LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3I9ImJsYWNrIiwgc2l6ZT0wLjUpLAogICAgICAgIGxlZ2VuZC5ib3guanVzdCA9ICJyaWdodCIsCiAgICAgICAgbGVnZW5kLm1hcmdpbiA9IG1hcmdpbigxLCAxLCAxLCAxKSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKAogICAgICAjdGl0bGU9IlRpdGxlIiwKICAgICAgI3N1YnRpdGxlPSJTdWJ0aXRsZSIsCiAgICAgIHg9IiRrJCIsCiAgICAgIHk9InRpbWUgW3NdIikKICAgICAgICAKCiAgIyBnZW9tX2xpbmUoZGF0YSA9IGJpZywgYWVzKHggPSBDb3VudGVyLCB5ID0gcmUyZyksIGNvbG9yID0gInJlZCIpICsKICAjIGdlb21fbGluZShkYXRhID0gYmlnLCBhZXMoeCA9IENvdW50ZXIsIHkgPSBjYSksIGNvbG9yID0gImJsdWUiKSArCiAgIyB4bGFiKCdjb3VudGVyIHZhbHVlJykgKwogICMgeWxhYigndGltZSBbc10nKQoKbWFrZV90aWt6KHBhc3RlMCgiZmlncy9iaWdfcGxvdC50aWt6IiksIGJpZ19wbG90LCB3aWR0aD0yLjcsIGhlaWdodD0yLjcpCgpwbG90KGJpZ19wbG90KQpgYGAKCgpgYGB7cn0KIyBJbmZvcm1hdGlvbiBhYm91dCBEQ0FzCgpkZl9kY2FzID0gcmVhZC5jc3YyKHBhcmFtcyRmaWxlX2RjYSwKICAgICAgICAgICAgICAgICAgaGVhZGVyPVRSVUUsCiAgICAgICAgICAgICAgICAgIHNlcD0iXHQiLAogICAgICAgICAgICAgICAgICBkZWM9Ii4iLAogICAgICAgICAgICAgICAgICBjb21tZW50LmNoYXI9IiIsCiAgICAgICAgICAgICAgICAgIHF1b3RlPSIiLAogICAgICAgICAgICAgICAgICBzdHJpcC53aGl0ZT1UUlVFLAogICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQoKIyBzYW5pdGl6ZQpkZl9kY2FzJHRpbWVvdXRzLmNsYXNzaWNhbFtpcy5uYShkZl9kY2FzJHRpbWVvdXRzLmNsYXNzaWNhbCldIDwtIDAKCiNkZl9kY2FzCmBgYAoKYGBge3J9CnRtcy5jbGFzc2ljYWwgPC0gZGZfZGNhc1tkZl9kY2FzJHRpbWVvdXRzLmNsYXNzaWNhbCA9PSAxLF0KYGBgCgoKCmBgYHtyfQpjb21wdXRlX3RpbWVvdXRzIDwtIGZ1bmN0aW9uKGRmLCBjb2wpIHsKICB0bXAgPC0gZGZbZGZbLCBjb2xdID09IFRJTUVPVVRfVkFMLF0KICB0bXAKfQoKYGBgCgo=