--- title: "Random Graphs, Social Networks and the Internet: Centrality" subtitle: "Mathematics Sin Fronteras, 2021" author: "Jose A. Sanchez & Mariana Olvera Cravioto" date: "10/14/2021" output: html_document: default pdf_document: default --- In the following, we generate visualizations of different random graph models. Furthermore, on each graph, we compare different measurements of centrality for vertices: degree centrality, closeness centrality, betweenness centrality and page rank. ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) ## Package used to save and visualize networks. library(igraph) ## Package used to visualize networks dynamically. library(networkD3) ## Package for visualizing adjacency matrices. library(plot.matrix) ## Not 100% sure of what this is for. if(!require(EnvStats)){ install.packages("EnvStats") library(EnvStats) } cbPalette <- c("#999999", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7") ######################################################### ## Paso 2: Measuring centrality: ######################################################### CentralityNames = c("Degree Centrality", "Closeness Centrality", "Betweenness Centrality", "Page-Rank") ########################### Laplacian = function(Theta){ .diag = apply(Theta, MARGIN = 1, sum) .lap = diag(.diag) - Theta } ########################### MakeConnected = function(adjsymm, n){ .Lap = Laplacian(Theta = adjsymm) .eig = eigen(.Lap) .Ncomm = sum(abs(.eig$values) < 0.001) if(.Ncomm == 1){ return(adjsymm) } .adjsymm = adjsymm .comm = kmeans(x = .eig$vectors[, -(1:(n-.Ncomm))], centers = .Ncomm) .comm = .comm$cluster .main = order(table(.comm), decreasing = TRUE)[1] for(.clust1 in (1:.Ncomm)[-.main]){ .clust2 = .main .members1 = which(.comm == .clust1) .members2 = which(.comm == .clust2) .nmemb1 = length(.members1) .nmemb2 = length(.members2) .rind1 = sample(x = 1:.nmemb1, size = 1) .rind2 = sample(x = 1:.nmemb2, size = 1) .node1 = .members1[.rind1] .node2 = .members2[.rind2] .adjsymm[.node1, .node2] = 1 .adjsymm[.node2, .node1] = 1 } return(.adjsymm) } ########################### CentralityMeasures = function(graph, n, which = 4){ .cent = NULL if( which == 1 ){ .cent = degree(graph = graph) } else if( which == 2 ){ .cent = closeness(graph = graph) } else if( which == 3 ){ .cent = betweenness(graph = graph) } else if( which == 4 ){ .cent = page.rank(graph = graph)$vector } return(.cent) } ``` ## Erdos-Renyi Model ```{r pressure, echo=FALSE, fig.width=10, fig.height = 8} set.seed(2) ######################################################### ## Step 1: create the adjacency matrix. ######################################################### n = 100 # n = total node count. c = 3 # c = average degree. p = c/n # p = connection probability. adj = matrix(0, n, n) # We create an adjacency matrix. # We start with no connections. for(.i in 2:n){ for(.j in 1:(.i-1)){ # For each pair of vertices (.i, .j): adj[.i, .j] = rbinom(1,1, p) # we add the edge with probability p´. } } adjsymm = adj + t(adj) adjsymm = MakeConnected(adjsymm = adjsymm, n = n) graph = graph_from_adjacency_matrix(adjsymm) graph = as.undirected(graph, mode = "collapse") # Specify visual parameters. V(graph)$label <- "" V(graph)$frame.color <- "white" E(graph)$arrow.mode <- 0 lw <- layout_with_fr(graph) ######################################################### ## Paso 2: Generate plots of centrality measurements. ######################################################### for(.which in 1:4){ ## Find measure of centrality: .cent = CentralityMeasures(graph = graph, n = n, which = .which) .maxcent = max(.cent) .centcol = 100 * .cent/.maxcent ## Color the vertices of the graph. colfunc <- colorRampPalette(c("orange", "red", "black")) colors = colfunc(101) V(graph)$color <- colors[.centcol + 1] V(graph)$size <- sqrt(.centcol) + 1 plot(graph, layout = lw, vertex.label.dist=1, main = CentralityNames[.which]) } ``` ## Chung-Lu Model ```{r echo=FALSE, fig.width=10, fig.height = 8} set.seed(4) ######################################################### ## Paso 1: generate graph. ######################################################### n = 100 # n = total vertex count. b = 1.5 # Generating pareto weights. alpha = 1.5 U = runif(n = n, min = 0, max = 1) w = b/( (1 - U)^(1/alpha) ) # Weights! L = sum(w) # Sum of all weights. adj = matrix(0, n, n) # We create an n x n adjacency matrix. # We start with no connections. for(.i in 2:n){ for(.j in 1:(.i-1)){ # For each pair of vertices (.i, .j): .p = min(w[.i]*w[.j]/L, 1) # a) We find the connection probability. adj[.i, .j] = rbinom(1,1, .p) # b) We include the edge in the network with probability p. } } adjsymm = adj + t(adj) adjsymm = MakeConnected(adjsymm = adjsymm, n = n) graph = graph_from_adjacency_matrix(adjsymm) # This command creates the graph object based on the adjacency matrix. graph = as.undirected(graph, mode = "collapse") # Specify visual parameters. V(graph)$label <- "" V(graph)$frame.color <- "white" E(graph)$arrow.mode <- 0 lw <- layout_with_fr(graph) ######################################################### ## Paso 2: Generate plots of centrality measurements. ######################################################### for(.which in 1:4){ ## Find measure of centrality: .cent = CentralityMeasures(graph = graph, n = n, which = .which) .maxcent = max(.cent) .centcol = 100 * .cent/.maxcent ## Color the vertices of the graph. colfunc <- colorRampPalette(c("orange", "red", "black")) colors = colfunc(101) V(graph)$color <- colors[.centcol + 1] V(graph)$size <- sqrt(.centcol) + 1 plot(graph, layout = lw, vertex.label.dist=1, main = CentralityNames[.which]) } ``` ## Intersection Model ```{r echo=FALSE, fig.width=10, fig.height = 8} set.seed(6) ######################################################### ## Paso 1: generar la grafica bipartita. ######################################################### n = 100 # Total vertex count (actores). beta = 0.5 gamma = 0.5 n2 = floor(beta*n) # Number of vertices on the bipartite opposite side (movies) b = 5 # We simulate Pareto weights. alpha = 3.5 U = runif(n = n, min = 0, max = 1) w = b/( (1 - U)^(1/alpha) ) # Weights!! L = sum(w) # Sum of weights. bip = matrix(0, ncol = n2, nrow = n) for(.i in 1:n){ for(.j in 1:n2){ # for each pair of (actor, movie): .pi = min(gamma*w[.i]/n, 1) # a) we find the connection probability. bip[.i, .j] = rbinom(n = 1, # b) We add a connection between them with probability p. size = 1, prob = .pi) } } ######################################################### ## Paso 2: Generate the adjacency matrix of actors. ######################################################### adj = matrix(0, n, n) count = 0 for(.i in 2:n){ for(.j in 1:(.i-1)){ # For each pair of actors. .iftrian = sum(bip[.i, ] * bip[.j, ]) # iftrian = "How many movies did i and j # collaborate on?" if(.iftrian > 0){ # If i and j have collaborated, connect them. adj[.i, .j] = 1 } } } adjsymm = adj + t(adj) adjsymm = MakeConnected(adjsymm = adjsymm, n = n) graph = graph_from_adjacency_matrix(adjsymm) # This command creates the graph object # based on the adjacency matrix. V(graph)$label <- "" V(graph)$frame.color <- "white" E(graph)$arrow.mode <- 0 lw <- layout_with_fr(graph) ######################################################### ## Paso 2: Generate plots of centrality measurements. ######################################################### for(.which in 1:4){ ## Find measure of centrality: .cent = CentralityMeasures(graph = graph, n = n, which = .which) .maxcent = max(.cent) .centcol = 100 * .cent/.maxcent #V(graph)$label <- round( 100 * .cent/.maxcent , digits = 2) ## Color the vertices of the graph. colfunc <- colorRampPalette(c("orange", "red", "black")) colors = colfunc(101) V(graph)$color <- colors[.centcol + 1] V(graph)$size <- sqrt(.centcol) + 1 plot(graph, layout = lw, vertex.label.dist=1, main = CentralityNames[.which]) } ```