Getting R

To install R just follow the instructions available at http://cran.r-project.org

Getting RStudio

RStudio is the most popular Integrated Development Environment (IDE) for R that is developed by the company of the same name. While having RStudio is not a requirement for using netdiffuseR, it is highly recommended.

To get RStudio just visit https://www.rstudio.com/products/rstudio/download/.

Getting netdiffuseR

netdiffuseR has two different versions: the development version (available at https://github.com/USCCANA/netdiffuseR), and the stable version (available on https://cran.r-project.org/package=netdiffuseR). You can get either of the two but it is significantly easier to get the stable version (and we recommend to do so)

CRAN version

For this version just go to your R console and type:

install.packages("netdiffuseR")

Github version

For the github version you will need to have installed the devtools R package which allows to build netdiffuseR from source1. This can be done in the following steps:

install.packages("devtools") # If you don't have devtools already!
devtools::install_github("USCCANA/netdiffuseR")

A gentle Quick n’ Dirty Introduction to R

Some common tasks in R

  1. Getting help (and reading the manual) is THE MOST IMPORTANT thing you should know about. For example, if you want to read the manual (help file) of the read.csv function, you can type either of these:

    ?read.csv
    ?"read.csv"
    help(read.csv)
    help("read.csv")

    If you are not fully aware of what is the name of the function, you can always use the fuzzy search

    help.search("linear regression")
    ??"linear regression"
  2. In R you can create new objects by either using the assign operator (<-) or the equal sign =, for example, the following 2 are equivalent:

    a <- 1
    a =  1

    Historically the assign operator is the most common used.

  3. R has several type of objects, the most basic structures in R are vectors, matrix, list, data.frame. Here is an example creating several of these (each line is enclosed with parenthesis so that R prints the resulting element):

    (a_vector     <- 1:9)
    ## [1] 1 2 3 4 5 6 7 8 9
    (another_vect <- c(1, 2, 3, 4, 5, 6, 7, 8, 9))
    ## [1] 1 2 3 4 5 6 7 8 9
    (a_string_vec <- c("I", "like", "netdiffuseR"))
    ## [1] "I"           "like"        "netdiffuseR"
    (a_matrix     <- matrix(a_vector, ncol = 3))
    ##      [,1] [,2] [,3]
    ## [1,]    1    4    7
    ## [2,]    2    5    8
    ## [3,]    3    6    9
    (a_string_mat <- matrix(letters[1:9], ncol=3)) # Matrices can be of strings too
    ##      [,1] [,2] [,3]
    ## [1,] "a"  "d"  "g" 
    ## [2,] "b"  "e"  "h" 
    ## [3,] "c"  "f"  "i"
    (another_mat  <- cbind(1:4, 11:14)) # The `cbind` operator does "column bind"
    ##      [,1] [,2]
    ## [1,]    1   11
    ## [2,]    2   12
    ## [3,]    3   13
    ## [4,]    4   14
    (another_mat2 <- rbind(1:4, 11:14)) # The `rbind` operator does "row bind"
    ##      [,1] [,2] [,3] [,4]
    ## [1,]    1    2    3    4
    ## [2,]   11   12   13   14
    (a_string_mat <- matrix(letters[1:9], ncol = 3))
    ##      [,1] [,2] [,3]
    ## [1,] "a"  "d"  "g" 
    ## [2,] "b"  "e"  "h" 
    ## [3,] "c"  "f"  "i"
    (a_list       <- list(a_vector, a_matrix))
    ## [[1]]
    ## [1] 1 2 3 4 5 6 7 8 9
    ## 
    ## [[2]]
    ##      [,1] [,2] [,3]
    ## [1,]    1    4    7
    ## [2,]    2    5    8
    ## [3,]    3    6    9
    (another_list <- list(my_vec = a_vector, my_mat = a_matrix)) # same but with names!
    ## $my_vec
    ## [1] 1 2 3 4 5 6 7 8 9
    ## 
    ## $my_mat
    ##      [,1] [,2] [,3]
    ## [1,]    1    4    7
    ## [2,]    2    5    8
    ## [3,]    3    6    9
    # Data frames can have multiple types of elements, it is a collection of lists
    (a_data_frame <- data.frame(x = 1:10, y = letters[1:10]))
    ##     x y
    ## 1   1 a
    ## 2   2 b
    ## 3   3 c
    ## 4   4 d
    ## 5   5 e
    ## 6   6 f
    ## 7   7 g
    ## 8   8 h
    ## 9   9 i
    ## 10 10 j
  4. Depending on the type of object, we can access to its components using indexing:

    a_vector[1:3] # First 3 elements
    ## [1] 1 2 3
    a_string_vec[3] # Third element
    ## [1] "netdiffuseR"
    a_matrix[1:2, 1:2] # A sub matrix
    ##      [,1] [,2]
    ## [1,]    1    4
    ## [2,]    2    5
    a_matrix[,3] # Third column
    ## [1] 7 8 9
    a_matrix[3,] # Third row
    ## [1] 3 6 9
    a_string_mat[1:6] # First 6 elements of the matrix. R stores matrices by column.
    ## [1] "a" "b" "c" "d" "e" "f"
    # These three are equivalent
    another_list[[1]]
    ## [1] 1 2 3 4 5 6 7 8 9
    another_list$my_vec
    ## [1] 1 2 3 4 5 6 7 8 9
    another_list[["my_vec"]]
    ## [1] 1 2 3 4 5 6 7 8 9
    # Data frames are just like lists
    a_data_frame[[1]]
    ##  [1]  1  2  3  4  5  6  7  8  9 10
    a_data_frame[,1]
    ##  [1]  1  2  3  4  5  6  7  8  9 10
    a_data_frame[["x"]]
    ##  [1]  1  2  3  4  5  6  7  8  9 10
    a_data_frame$x
    ##  [1]  1  2  3  4  5  6  7  8  9 10
  5. Control-flow statements

    # The oldfashion forloop
    for (i in 1:10) {
      print(paste("I'm step", i, "/", 10))
    }
    ## [1] "I'm step 1 / 10"
    ## [1] "I'm step 2 / 10"
    ## [1] "I'm step 3 / 10"
    ## [1] "I'm step 4 / 10"
    ## [1] "I'm step 5 / 10"
    ## [1] "I'm step 6 / 10"
    ## [1] "I'm step 7 / 10"
    ## [1] "I'm step 8 / 10"
    ## [1] "I'm step 9 / 10"
    ## [1] "I'm step 10 / 10"
    # A nice ifelse
    
    for (i in 1:10) {
    
      if (i %% 2) # Modulus operand
        print(paste("I'm step", i, "/", 10, "(and I'm odd)"))
      else
        print(paste("I'm step", i, "/", 10, "(and I'm even)"))
    
    }
    ## [1] "I'm step 1 / 10 (and I'm odd)"
    ## [1] "I'm step 2 / 10 (and I'm even)"
    ## [1] "I'm step 3 / 10 (and I'm odd)"
    ## [1] "I'm step 4 / 10 (and I'm even)"
    ## [1] "I'm step 5 / 10 (and I'm odd)"
    ## [1] "I'm step 6 / 10 (and I'm even)"
    ## [1] "I'm step 7 / 10 (and I'm odd)"
    ## [1] "I'm step 8 / 10 (and I'm even)"
    ## [1] "I'm step 9 / 10 (and I'm odd)"
    ## [1] "I'm step 10 / 10 (and I'm even)"
    # A while
    i <- 10
    while (i > 0) {
      print(paste("I'm step", i, "/", 10))
      i <- i - 1
    }
    ## [1] "I'm step 10 / 10"
    ## [1] "I'm step 9 / 10"
    ## [1] "I'm step 8 / 10"
    ## [1] "I'm step 7 / 10"
    ## [1] "I'm step 6 / 10"
    ## [1] "I'm step 5 / 10"
    ## [1] "I'm step 4 / 10"
    ## [1] "I'm step 3 / 10"
    ## [1] "I'm step 2 / 10"
    ## [1] "I'm step 1 / 10"
  6. R has a very nice set of pseudo random number generation functions. In general, distribution functions have the following name structure:
    1. Random Number Generation: r[name-of-the-distribution], e.g. rnorm for normal, runif for uniform.
    2. Density function: d[name-of-the-distribution], e.g. dnorm for normal, dunif for uniform.
    3. Cumulative Distribution Function (CDF): p[name-of-the-distribution], e.g. pnorm for normal, punif for uniform.
    4. Inverse (quantile) function: q[name-of-the-distribution], e.g. qnorm for the normal, qunif for the uniform.

    Here are some examples:

    # To ensure reproducibility
    set.seed(1231)
    
    # 100,000 Unif(0,1) numbers
    x <- runif(1e5)
    hist(x)

    # 100,000 N(0,1) numbers
    x <- rnorm(1e5)
    hist(x)

    # 100,000 N(10,25) numbers
    x <- rnorm(1e5, mean = 10, sd = 5)
    hist(x)

    # 100,000 Poisson(5) numbers
    x <- rpois(1e5, lambda = 5)
    hist(x)

    # 100,000 rexp(5) numbers
    x <- rexp(1e5, 5)
    hist(x)

    More distributions available at ??Distributions.

For a nice intro to R, take a look at “The Art of R Programming” by Norman Matloff. For more advanced users, take a look at “Advanced R” by Hadley Wickham.


  1. Building an R package from source means that you will use R CMD INSTALL utility on the command line of your operating system. Depending on the R package, it may require having a C/C++ compiler such as gcc g++ or clang. This makes installing packages from source code a bit harder, that’s why we recommend getting the CRAN version which is already compiled and ready for your operating system.

LS0tCmF1dGhvcjogIkdlb3JnZSBHLiBWZWdhIFlvbiIKLS0tCgojIEdldHRpbmcgUgoKVG8gaW5zdGFsbCBSIGp1c3QgZm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgYXZhaWxhYmxlIGF0IGh0dHA6Ly9jcmFuLnItcHJvamVjdC5vcmcKCiMgR2V0dGluZyBSU3R1ZGlvCgpSU3R1ZGlvIGlzIHRoZSBtb3N0IHBvcHVsYXIgSW50ZWdyYXRlZCBEZXZlbG9wbWVudCBFbnZpcm9ubWVudCAoSURFKSBmb3IgUiB0aGF0IGlzIGRldmVsb3BlZCBieSB0aGUgY29tcGFueSBvZiB0aGUgc2FtZSBuYW1lLiBXaGlsZSBoYXZpbmcgUlN0dWRpbyBpcyBub3QgYSByZXF1aXJlbWVudCBmb3IgdXNpbmcgbmV0ZGlmZnVzZVIsIGl0IGlzIGhpZ2hseSByZWNvbW1lbmRlZC4KClRvIGdldCBSU3R1ZGlvIGp1c3QgdmlzaXQgaHR0cHM6Ly93d3cucnN0dWRpby5jb20vcHJvZHVjdHMvcnN0dWRpby9kb3dubG9hZC8uCgojIEdldHRpbmcgbmV0ZGlmZnVzZVIKCmBuZXRkaWZmdXNlUmAgaGFzIHR3byBkaWZmZXJlbnQgdmVyc2lvbnM6IHRoZSBkZXZlbG9wbWVudCB2ZXJzaW9uIChhdmFpbGFibGUgYXQgaHR0cHM6Ly9naXRodWIuY29tL1VTQ0NBTkEvbmV0ZGlmZnVzZVIpLCBhbmQgdGhlIHN0YWJsZSB2ZXJzaW9uIChhdmFpbGFibGUgb24gaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvcGFja2FnZT1uZXRkaWZmdXNlUikuIFlvdSBjYW4gZ2V0IGVpdGhlciBvZiB0aGUgdHdvIGJ1dCBpdCBpcyBzaWduaWZpY2FudGx5IGVhc2llciB0byBnZXQgdGhlIHN0YWJsZSB2ZXJzaW9uIChhbmQgd2UgcmVjb21tZW5kIHRvIGRvIHNvKQoKIyMgQ1JBTiB2ZXJzaW9uCgpGb3IgdGhpcyB2ZXJzaW9uIGp1c3QgZ28gdG8geW91ciBSIGNvbnNvbGUgYW5kIHR5cGU6CgpgYGByCmluc3RhbGwucGFja2FnZXMoIm5ldGRpZmZ1c2VSIikKYGBgCgojIyBHaXRodWIgdmVyc2lvbgoKRm9yIHRoZSBnaXRodWIgdmVyc2lvbiB5b3Ugd2lsbCBuZWVkIHRvIGhhdmUgaW5zdGFsbGVkIHRoZSBbYGRldnRvb2xzYF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvcGFja2FnZT1kZXZ0b29scykgUiBwYWNrYWdlIHdoaWNoIGFsbG93cyB0byBidWlsZCBuZXRkaWZmdXNlUiBmcm9tIHNvdXJjZVteYnVpbGRuZXRkaWZmdXNlUl0uIFRoaXMgY2FuIGJlIGRvbmUgaW4gdGhlIGZvbGxvd2luZyBzdGVwczoKClteYnVpbGRuZXRkaWZmdXNlUl06IEJ1aWxkaW5nIGFuIFIgcGFja2FnZSBmcm9tIHNvdXJjZSBtZWFucyB0aGF0IHlvdSB3aWxsIHVzZSBgUiBDTUQgSU5TVEFMTGAgdXRpbGl0eSBvbiB0aGUgY29tbWFuZCBsaW5lIG9mIHlvdXIgb3BlcmF0aW5nIHN5c3RlbS4gRGVwZW5kaW5nIG9uIHRoZSBSIHBhY2thZ2UsIGl0IG1heSByZXF1aXJlIGhhdmluZyBhIEMvQysrIGNvbXBpbGVyIHN1Y2ggYXMgZ2NjIGcrKyBvciBjbGFuZy4gVGhpcyBtYWtlcyBpbnN0YWxsaW5nIHBhY2thZ2VzIGZyb20gc291cmNlIGNvZGUgYSBiaXQgaGFyZGVyLCB0aGF0J3Mgd2h5IHdlIHJlY29tbWVuZCBnZXR0aW5nIHRoZSBDUkFOIHZlcnNpb24gd2hpY2ggaXMgYWxyZWFkeSBjb21waWxlZCBhbmQgcmVhZHkgZm9yIHlvdXIgb3BlcmF0aW5nIHN5c3RlbS4KCmBgYHIKaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKSAjIElmIHlvdSBkb24ndCBoYXZlIGRldnRvb2xzIGFscmVhZHkhCmRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiVVNDQ0FOQS9uZXRkaWZmdXNlUiIpCmBgYAoKIyBBIH5+Z2VudGxlfn4gUXVpY2sgbicgRGlydHkgSW50cm9kdWN0aW9uIHRvIFIKClNvbWUgY29tbW9uIHRhc2tzIGluIFIKCjAuICBHZXR0aW5nIGhlbHAgKGFuZCByZWFkaW5nIHRoZSBtYW51YWwpIGlzICpUSEUgTU9TVCBJTVBPUlRBTlQqIHRoaW5nIHlvdSBzaG91bGQga25vdyBhYm91dC4gRm9yIGV4YW1wbGUsIGlmIHlvdSB3YW50IHRvIHJlYWQgdGhlIG1hbnVhbCAoaGVscCBmaWxlKSBvZiB0aGUgYHJlYWQuY3N2YCBmdW5jdGlvbiwgeW91IGNhbiB0eXBlIGVpdGhlciBvZiB0aGVzZToKICAgIGBgYHIKICAgID9yZWFkLmNzdgogICAgPyJyZWFkLmNzdiIKICAgIGhlbHAocmVhZC5jc3YpCiAgICBoZWxwKCJyZWFkLmNzdiIpCiAgICBgYGAKICAgIElmIHlvdSBhcmUgbm90IGZ1bGx5IGF3YXJlIG9mIHdoYXQgaXMgdGhlIG5hbWUgb2YgdGhlIGZ1bmN0aW9uLCB5b3UgY2FuIGFsd2F5cyB1c2UgdGhlICpmdXp6eSBzZWFyY2gqCiAgICBgYGByCiAgICBoZWxwLnNlYXJjaCgibGluZWFyIHJlZ3Jlc3Npb24iKQogICAgPz8ibGluZWFyIHJlZ3Jlc3Npb24iCiAgICBgYGAKICAgIAogICAgCgoxLiAgSW4gUiB5b3UgY2FuIGNyZWF0ZSBuZXcgb2JqZWN0cyBieSBlaXRoZXIgdXNpbmcgdGhlIGFzc2lnbiBvcGVyYXRvciAoYDwtYCkgb3IgdGhlIGVxdWFsIHNpZ24gYD1gLCBmb3IgZXhhbXBsZSwgdGhlIGZvbGxvd2luZyAyIGFyZSBlcXVpdmFsZW50OgogICAgYGBgcgogICAgYSA8LSAxCiAgICBhID0gIDEKICAgIGBgYAogICAgSGlzdG9yaWNhbGx5IHRoZSBhc3NpZ24gb3BlcmF0b3IgaXMgdGhlIG1vc3QgY29tbW9uIHVzZWQuCgoyLiAgUiBoYXMgc2V2ZXJhbCB0eXBlIG9mIG9iamVjdHMsIHRoZSBtb3N0IGJhc2ljIHN0cnVjdHVyZXMgaW4gUiBhcmUgYHZlY3RvcnNgLCBgbWF0cml4YCwgYGxpc3RgLCBgZGF0YS5mcmFtZWAuIEhlcmUgaXMgYW4gZXhhbXBsZSBjcmVhdGluZyBzZXZlcmFsIG9mIHRoZXNlIChlYWNoIGxpbmUgaXMgZW5jbG9zZWQgd2l0aCBwYXJlbnRoZXNpcyBzbyB0aGF0IFIgcHJpbnRzIHRoZSByZXN1bHRpbmcgZWxlbWVudCk6CiAgICBgYGB7ciBjcmVhdGluZ30KICAgIChhX3ZlY3RvciAgICAgPC0gMTo5KQogICAgKGFub3RoZXJfdmVjdCA8LSBjKDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDkpKQogICAgKGFfc3RyaW5nX3ZlYyA8LSBjKCJJIiwgImxpa2UiLCAibmV0ZGlmZnVzZVIiKSkKICAgIChhX21hdHJpeCAgICAgPC0gbWF0cml4KGFfdmVjdG9yLCBuY29sID0gMykpCiAgICAoYV9zdHJpbmdfbWF0IDwtIG1hdHJpeChsZXR0ZXJzWzE6OV0sIG5jb2w9MykpICMgTWF0cmljZXMgY2FuIGJlIG9mIHN0cmluZ3MgdG9vCiAgICAoYW5vdGhlcl9tYXQgIDwtIGNiaW5kKDE6NCwgMTE6MTQpKSAjIFRoZSBgY2JpbmRgIG9wZXJhdG9yIGRvZXMgImNvbHVtbiBiaW5kIgogICAgKGFub3RoZXJfbWF0MiA8LSByYmluZCgxOjQsIDExOjE0KSkgIyBUaGUgYHJiaW5kYCBvcGVyYXRvciBkb2VzICJyb3cgYmluZCIKICAgIChhX3N0cmluZ19tYXQgPC0gbWF0cml4KGxldHRlcnNbMTo5XSwgbmNvbCA9IDMpKQogICAgKGFfbGlzdCAgICAgICA8LSBsaXN0KGFfdmVjdG9yLCBhX21hdHJpeCkpCiAgICAoYW5vdGhlcl9saXN0IDwtIGxpc3QobXlfdmVjID0gYV92ZWN0b3IsIG15X21hdCA9IGFfbWF0cml4KSkgIyBzYW1lIGJ1dCB3aXRoIG5hbWVzIQogICAgIyBEYXRhIGZyYW1lcyBjYW4gaGF2ZSBtdWx0aXBsZSB0eXBlcyBvZiBlbGVtZW50cywgaXQgaXMgYSBjb2xsZWN0aW9uIG9mIGxpc3RzCiAgICAoYV9kYXRhX2ZyYW1lIDwtIGRhdGEuZnJhbWUoeCA9IDE6MTAsIHkgPSBsZXR0ZXJzWzE6MTBdKSkKICAgIGBgYAogICAgCjMuICBEZXBlbmRpbmcgb24gdGhlIHR5cGUgb2Ygb2JqZWN0LCB3ZSBjYW4gYWNjZXNzIHRvIGl0cyBjb21wb25lbnRzIHVzaW5nIGluZGV4aW5nOgogICAgYGBge3IgaW5kZXhpbmd9CiAgICBhX3ZlY3RvclsxOjNdICMgRmlyc3QgMyBlbGVtZW50cwogICAgYV9zdHJpbmdfdmVjWzNdICMgVGhpcmQgZWxlbWVudAogICAgYV9tYXRyaXhbMToyLCAxOjJdICMgQSBzdWIgbWF0cml4CiAgICBhX21hdHJpeFssM10gIyBUaGlyZCBjb2x1bW4KICAgIGFfbWF0cml4WzMsXSAjIFRoaXJkIHJvdwogICAgYV9zdHJpbmdfbWF0WzE6Nl0gIyBGaXJzdCA2IGVsZW1lbnRzIG9mIHRoZSBtYXRyaXguIFIgc3RvcmVzIG1hdHJpY2VzIGJ5IGNvbHVtbi4KICAgIAogICAgIyBUaGVzZSB0aHJlZSBhcmUgZXF1aXZhbGVudAogICAgYW5vdGhlcl9saXN0W1sxXV0KICAgIGFub3RoZXJfbGlzdCRteV92ZWMKICAgIGFub3RoZXJfbGlzdFtbIm15X3ZlYyJdXQogICAgCiAgICAjIERhdGEgZnJhbWVzIGFyZSBqdXN0IGxpa2UgbGlzdHMKICAgIGFfZGF0YV9mcmFtZVtbMV1dCiAgICBhX2RhdGFfZnJhbWVbLDFdCiAgICBhX2RhdGFfZnJhbWVbWyJ4Il1dCiAgICBhX2RhdGFfZnJhbWUkeAogICAgYGBgCiAgICAKNC4gIENvbnRyb2wtZmxvdyBzdGF0ZW1lbnRzCiAgICBgYGB7ciBjb250cm9sLWZsb3d9CiAgICAjIFRoZSBvbGRmYXNoaW9uIGZvcmxvb3AKICAgIGZvciAoaSBpbiAxOjEwKSB7CiAgICAgIHByaW50KHBhc3RlKCJJJ20gc3RlcCIsIGksICIvIiwgMTApKQogICAgfQogICAgCiAgICAjIEEgbmljZSBpZmVsc2UKICAgIAogICAgZm9yIChpIGluIDE6MTApIHsKICAgICAgCiAgICAgIGlmIChpICUlIDIpICMgTW9kdWx1cyBvcGVyYW5kCiAgICAgICAgcHJpbnQocGFzdGUoIkknbSBzdGVwIiwgaSwgIi8iLCAxMCwgIihhbmQgSSdtIG9kZCkiKSkKICAgICAgZWxzZQogICAgICAgIHByaW50KHBhc3RlKCJJJ20gc3RlcCIsIGksICIvIiwgMTAsICIoYW5kIEknbSBldmVuKSIpKQogICAgICAKICAgIH0KICAgIAogICAgIyBBIHdoaWxlCiAgICBpIDwtIDEwCiAgICB3aGlsZSAoaSA+IDApIHsKICAgICAgcHJpbnQocGFzdGUoIkknbSBzdGVwIiwgaSwgIi8iLCAxMCkpCiAgICAgIGkgPC0gaSAtIDEKICAgIH0KICAgIGBgYAoKNS4gIFIgaGFzIGEgdmVyeSBuaWNlIHNldCBvZiBwc2V1ZG8gcmFuZG9tIG51bWJlciBnZW5lcmF0aW9uIGZ1bmN0aW9ucy4gSW4gZ2VuZXJhbCwgZGlzdHJpYnV0aW9uIGZ1bmN0aW9ucyBoYXZlIHRoZSBmb2xsb3dpbmcgbmFtZSBzdHJ1Y3R1cmU6CiAgICBhLiAgUmFuZG9tIE51bWJlciBHZW5lcmF0aW9uOiBgcltuYW1lLW9mLXRoZS1kaXN0cmlidXRpb25dYCwgZS5nLiBgcm5vcm1gIGZvciBub3JtYWwsIGBydW5pZmAgZm9yIHVuaWZvcm0uCiAgICBiLiAgRGVuc2l0eSBmdW5jdGlvbjogYGRbbmFtZS1vZi10aGUtZGlzdHJpYnV0aW9uXWAsIGUuZy4gYGRub3JtYCBmb3Igbm9ybWFsLCBgZHVuaWZgIGZvciB1bmlmb3JtLgogICAgYy4gIEN1bXVsYXRpdmUgRGlzdHJpYnV0aW9uIEZ1bmN0aW9uIChDREYpOiBgcFtuYW1lLW9mLXRoZS1kaXN0cmlidXRpb25dYCwgZS5nLiBgcG5vcm1gIGZvciBub3JtYWwsIGBwdW5pZmAgZm9yIHVuaWZvcm0uCiAgICBkLiAgSW52ZXJzZSAocXVhbnRpbGUpIGZ1bmN0aW9uOiBgcVtuYW1lLW9mLXRoZS1kaXN0cmlidXRpb25dYCwgZS5nLiBgcW5vcm1gIGZvciB0aGUgbm9ybWFsLCBgcXVuaWZgIGZvciB0aGUgdW5pZm9ybS4KICAgIAogICAgSGVyZSBhcmUgc29tZSBleGFtcGxlczoKICAgICAKICAgIGBgYHtyIHJhbmRvbS1udW1iZXJzfQogICAgIyBUbyBlbnN1cmUgcmVwcm9kdWNpYmlsaXR5CiAgICBzZXQuc2VlZCgxMjMxKQogICAgCiAgICAjIDEwMCwwMDAgVW5pZigwLDEpIG51bWJlcnMKICAgIHggPC0gcnVuaWYoMWU1KQogICAgaGlzdCh4KQogICAgCiAgICAjIDEwMCwwMDAgTigwLDEpIG51bWJlcnMKICAgIHggPC0gcm5vcm0oMWU1KQogICAgaGlzdCh4KQogICAgCiAgICAjIDEwMCwwMDAgTigxMCwyNSkgbnVtYmVycwogICAgeCA8LSBybm9ybSgxZTUsIG1lYW4gPSAxMCwgc2QgPSA1KQogICAgaGlzdCh4KQogICAgCiAgICAjIDEwMCwwMDAgUG9pc3Nvbig1KSBudW1iZXJzCiAgICB4IDwtIHJwb2lzKDFlNSwgbGFtYmRhID0gNSkKICAgIGhpc3QoeCkKICAgIAogICAgIyAxMDAsMDAwIHJleHAoNSkgbnVtYmVycwogICAgeCA8LSByZXhwKDFlNSwgNSkKICAgIGhpc3QoeCkKICAgIGBgYAogICAgCiAgICBNb3JlIGRpc3RyaWJ1dGlvbnMgYXZhaWxhYmxlIGF0IGA/P0Rpc3RyaWJ1dGlvbnNgLgoKRm9yIGEgbmljZSBpbnRybyB0byBSLCB0YWtlIGEgbG9vayBhdCBbIlRoZSBBcnQgb2YgUiBQcm9ncmFtbWluZyIgYnkgTm9ybWFuIE1hdGxvZmZdKGh0dHBzOi8vbm9zdGFyY2guY29tL2FydG9mci5odG0pLiBGb3IgbW9yZSBhZHZhbmNlZCB1c2VycywgdGFrZSBhIGxvb2sgYXQgWyJBZHZhbmNlZCBSIiBieSBIYWRsZXkgV2lja2hhbV0oaHR0cDovL2Fkdi1yLmhhZC5jby5uei8pLgogICAgCiAgICAKCg==

University of Southern California
Center for Applied Network Analysis (CANA)