Search code examples
rigrapheigenvectornode-centrality

Is eigenvector centrality in igraph wrong?


I am trying to improve my understanding of eigenvector centrality. This overview from the University of Washington was very helpful, especially when read in conjunction with this R code. However, when I use evcent(graph_from_adjacency_matrix(A)), the result differs.

The below code

    library(matrixcalc)
    library(igraph)
    
   # specify the adjacency matrix 
    A <- matrix(c(0,1,0,0,0,0,
                            1,0,1,0,0,0,
                            0,1,0,1,1,1,
                            0,0,1,0,1,0,
                            0,0,1,1,0,1,
                            0,0,1,0,1,0 ),6,6, byrow= TRUE)
    EV <- eigen(A) # compute eigenvalues and eigenvectors
    max(EV$values)  # find the maximum eigenvalue
     
    centrality <- data.frame(EV$vectors[,1]) 
    names(centrality) <- "Centrality"
    print(centrality)
     
    B <- A + diag(6)  # Add self loops
    EVB <- eigen(B) # compute eigenvalues and eigenvectors 
            # they are the same as EV(A)
     
    c <- matrix(c(2,3,5,3,4,3))  # Degree of each node + self loop
      
    ck <- function(k){
         n <- (k-2)
         B_K <- B   # B is the original adjacency matrix, w/ self-loops
               for (i in 1:n){
        B_K <- B_K%*%B  # 
        #print(B_K)
         }
        c_k <- B_K%*%c  
         return(c_k)
    }
     
    # derive EV centrality as k -> infinity
    # k = 100
ck(100)/frobenius.norm(ck(100)) # .09195198, .2487806, .58115487, .40478177, .51401731, .040478177
    
# Does igraph match?
evcent(graph_from_adjacency_matrix(A))$vector  # No: 0.1582229 0.4280856 1.0000000 0.6965127 0.8844756 0.6965127

The rank correlation is the same, but it is still bothersome that the values are not the same. What is going on?


Solution

  • The result returned by igraph is not wrong, but note that there are subtleties to defining eigenvector centrality, and not all implementations handle self-loops in the same way.


    Please see what I wrote here.

    One way to define eigenvector centrality is simply as "the leading eigenvector of the adjacency matrix". But this is imprecise without specifying what the adjacency matrix is, especially what its diagonal elements should be when there are self-loops present. Depending on application, diagonal entries of the adjacency matrix of an undirected graph are sometimes defined as the number of self-loops, and sometimes as twice the number of self-loops. igraph uses the second definition when computing eigenvector centrality. This is the source of the difference you see.

    A more intuitive definition of eigenvector centrality is that the centrality of each vertex is proportional to the sum of its neighbours centralities. Thus the details of the computation hinge on who the neighbours are. Consider a single vertex with a self-loop. It is its own neighbour, but how many times? We can traverse the self-loop in both directions, so it is reasonable to say that it is its own neighbour twice. Indeed, its degree is conventionally taken to be 2, not 1.

    You will find that different software packages treat self-loops differently when computing the eigenvector centrality. In igraph, we made a choice by looking at the intuitive interpretation of eigenvector centrality rather than rigidly following a formal definition, with no regard for the motivation behind that definition.


    Note: What I wrote about refers to how eigenvector centrality computations work internally, not to what as_adjacency_matrix() return. as_adjacency_matrix() adds one (not two) to the diagonal for each self-loop.