library(igraph)
Random graph
n = 100
p = 1.75/n
g = sample_gnp(n, p)
coords = layout_with_fr(g)
plot(g, layout=coords, vertex.size = 3, vertex.label=NA)
Connected components
# get the components
c = components(g)
# connected?
is_connected(g)
## [1] FALSE
# number of components
c$no
## [1] 15
# size of components
c$csize
## [1] 82 1 1 1 1 3 1 2 1 2 1 1 1 1 1
table(c$csize)
##
## 1 2 3 82
## 11 2 1 1
# membeship of nodes
c$membership
## [1] 1 1 1 1 1 2 1 3 1 1 1 1 1 1 4 5 1 1 1 1 1 6 1
## [24] 1 1 1 1 7 1 8 1 1 1 1 9 1 10 11 1 1 1 1 1 1 1 1
## [47] 1 1 1 1 1 1 1 12 13 1 1 1 14 1 1 1 6 1 6 1 1 1 15
## [70] 1 10 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [93] 1 1 1 1 1 1 1 1
# get the giant component
nodes = which(c$membership == which.max(c$csize))
# color in red the nodes in the giant component
V(g)$color = "white"
V(g)[nodes]$color = "red"
plot(g, layout=coords, vertex.size = 3, vertex.label=NA)
Biconnected components
n = 100
p = 4/n
g = sample_gnp(n, p)
coords = layout_with_fr(g)
plot(g, layout=coords, vertex.size = 3, vertex.label=NA)
bc = biconnected_components(g)
# number of bicomponents
bc$no
## [1] 7
# print edges of biconnected components
bc$component_edges
## [[1]]
## + 1/187 edge from e01c769:
## [1] 4--76
##
## [[2]]
## + 1/187 edge from e01c769:
## [1] 37--81
##
## [[3]]
## + 1/187 edge from e01c769:
## [1] 68--73
##
## [[4]]
## + 1/187 edge from e01c769:
## [1] 7--18
##
## [[5]]
## + 1/187 edge from e01c769:
## [1] 77--80
##
## [[6]]
## + 1/187 edge from e01c769:
## [1] 39--44
##
## [[7]]
## + 181/187 edges from e01c769:
## [1] 12--94 53--94 92--94 5--53 8--53 8--92 23--92 54--92 62--92 22--54
## [11] 11--22 14--62 16--62 29--62 29--66 43--66 62--66 51--85 82--85 17--51
## [21] 24--51 50--88 57--88 6--57 30--57 36--57 14--99 29--99 36--99 38--99
## [31] 12--36 33--36 3--72 24--72 27--72 45--72 52--72 56--72 11--27 25--27
## [41] 3--91 49--91 62--91 78--91 87--91 58--87 5--96 11--96 12--96 29--96
## [51] 67--96 24--67 52--67 13--71 30--71 38--71 52--71 12--52 23--52 10--89
## [61] 44--89 67--89 72--89 18--95 70--95 89--95 2--78 51--78 70--78 3--42
## [71] 6--42 10--42 6--45 9--45 21--45 58--98 79--98 9--79 16--79 26--79
## [81] 33--79 55--79 59--79 73--79 14--73 36--81 40--81 41--81 43--81 30--40
## [91] 1--41 25--41 8--84 14--84 32--84 41--84 43--84 64--84 14--64 46--64
## + ... omitted several edges
# print nodes of biconnected components
bc$components
## [[1]]
## + 2/100 vertices, from e01c769:
## [1] 76 4
##
## [[2]]
## + 2/100 vertices, from e01c769:
## [1] 81 37
##
## [[3]]
## + 2/100 vertices, from e01c769:
## [1] 73 68
##
## [[4]]
## + 2/100 vertices, from e01c769:
## [1] 18 7
##
## [[5]]
## + 2/100 vertices, from e01c769:
## [1] 80 77
##
## [[6]]
## + 2/100 vertices, from e01c769:
## [1] 44 39
##
## [[7]]
## + 90/100 vertices, from e01c769:
## [1] 94 53 92 54 22 62 66 29 85 51 88 57 99 36 72 56 27 91 87 96 67 71 52
## [24] 89 95 18 70 78 3 42 45 98 79 73 81 40 41 84 64 46 55 9 75 21 76 83
## [47] 69 33 65 35 93 17 61 49 59 82 63 48 16 25 60 14 32 30 10 97 20 26 15
## [70] 47 24 5 58 43 8 74 77 86 34 44 23 50 38 19 13 6 11 12 2 1
# size of bicomponents
cl = bc$components
size = sapply(cl, length)
length(size)
## [1] 7
table(size)
## size
## 2 90
## 6 1
# highlight the largest bi-component
giant = cl[[which.max(size)]]
V(g)$color = "white"
V(g)[giant]$color = "red"
plot(g, layout=coords, vertex.label=NA, vertex.size=5)
Cohesive blocks (k-connected components)
n = 100
p = 6/n
g = sample_gnp(n, p)
coords = layout_with_fr(g)
plot(g, layout=coords, vertex.size = 3, vertex.label=NA)
# This is computationally heavy
b = cohesive_blocks(g)
# print hieararchy of blocks
print(b)
## Cohesive block structure:
## B-1 c 1, n 100
## '- B-2 c 3, n 99
## '- B-3 c 4, n 94
# plot hieararchy of blocks
plot_hierarchy(b)
# nodes from blocks
blocks(b)
## [[1]]
## + 100/100 vertices, from e137696:
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
## [18] 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
## [35] 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
## [52] 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
## [69] 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
## [86] 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
##
## [[2]]
## + 99/100 vertices, from e137696:
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
## [18] 18 19 20 21 22 23 24 26 27 28 29 30 31 32 33 34 35
## [35] 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
## [52] 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
## [69] 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
## [86] 87 88 89 90 91 92 93 94 95 96 97 98 99 100
##
## [[3]]
## + 94/100 vertices, from e137696:
## [1] 1 3 4 5 6 7 8 9 10 12 13 14 15 16 17 19 20
## [18] 22 23 24 26 27 28 29 30 31 32 33 34 35 36 37 38 39
## [35] 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
## [52] 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
## [69] 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
## [86] 92 93 94 95 96 97 98 99 100
# graphs from blocks
bg = graphs_from_cohesive_blocks(b, g)
# plot most cohesive graph
c = cohesion(b)
h = bg[[which.max(c)]]
plot(h, layout=layout_with_fr(h), vertex.size = 3, vertex.label=NA)
# connectivity of the graph
vertex_connectivity(h)
## [1] 4
Weakly and strongly connected components of directed graphs
n = 10
p = 2/n
g = sample_gnp(n, p, directed=TRUE)
coords = layout_with_fr(g)
plot(g, layout=coords, vertex.size = 6, vertex.label=NA, edge.arrow.size = 0.5, edge.curved = TRUE)
# weak components
components(g, mode="weak")
## $membership
## [1] 1 1 1 1 1 1 1 1 1 1
##
## $csize
## [1] 10
##
## $no
## [1] 1
# strong components
c = components(g, mode="strong")
nodes = which(c$membership == which.max(c$csize))
# color in red the nodes in the giant component
V(g)$color = "white"
V(g)[nodes]$color = "red"
plot(g, layout=coords, vertex.size = 6, vertex.label=NA, edge.arrow.size = 0.5, edge.curved = TRUE)
Resilience
# percolation removes nodes from a graph and computes
# the size of the giant connected component
# INPUT
# g: graph to percolate
# size: number of nodes to remove
# d: removal vector
# OUTPUT
# giant: a vector with sizes of giant components when nodes are removed
percolate = function(g, size, d) {
giant = vector()
# initial size of giant component
c = components(g)
giant[1] = max(c$csize)
names(d) = 1:length(d)
d = sort(d, decreasing=TRUE)
vital = as.integer(names(d[1:size]))
for (i in 1:size) {
c = components(delete_vertices(g, vital[1:i]))
giant[i+1] = max(c$csize)
}
return(giant)
}
# Preferential attachment graph
g = sample_pa(n = 100, m = 2, directed=FALSE)
coords = layout_with_fr(g)
plot(g, layout=coords, vertex.label=NA, vertex.size = 5)
# resilience
size = vcount(g)/2
# random
rand = percolate(g, size, d = sample(V(g), size))
# degree
deg = percolate(g, size, d = degree(g))
# pagerank
pr = percolate(g, size, d=page_rank(g)$vector)
# betweenness
bet = percolate(g, size, d = betweenness(g))
plot(0:size, deg, type = "l", col=1, xlab="Number of removed nodes", ylab="Size of giant component")
lines(0:size, pr, col=2)
lines(0:size, bet, col=3)
lines(0:size, rand, col=4)
lines(0:size, rep(vcount(g)/2, size+1), lty=2)
legend(x = "bottomleft", legend = c("deg", "pr", "btw", "rand"), lty = 1, col = 1:4)
g = sample_gnp(n=100, p=5/100)
coords = layout_with_fr(g)
plot(g, layout=coords, vertex.size = 3, vertex.label=NA)
# resilience
size = vcount(g)/2
# random
rand = percolate(g, size, d = sample(V(g), size))
# degree
deg = percolate(g, size, d = degree(g))
# pagerank
pr = percolate(g, size, d=page_rank(g)$vector)
# betweenness
bet = percolate(g, size, d = betweenness(g))
plot(0:size, deg, type = "l", col=1, xlab="Number of removed nodes", ylab="Size of giant component")
lines(0:size, pr, col=2)
lines(0:size, bet, col=3)
lines(0:size, rand, col=4)
lines(0:size, rep(vcount(g)/2, size+1), lty=2)
legend(x = "bottomleft", legend = c("deg", "pr", "btw", "rand"), lty = 1, col = 1:4)