What is the meaning of warning .c:348 in eigen_centrality?

Program:

if (!require(igraph)) q()
igraph_version()

# -x^3 + 1/4x + 1/2
mg <- matrix(c(0, 0, 0.5, 1, 0, 0, 0.5, 1, 0), ncol=3)
g <- graph_from_adjacency_matrix(
  mg,
  mode = c("directed"),
  weighted = TRUE,
  diag = TRUE,
  add.colnames = NULL,
  add.rownames = NA
)

eigen_centrality(
  g,
  directed = TRUE,
  scale = TRUE,
  weights = NULL,
  options = arpack_defaults
)

gives the following warning:

Warning message:
In eigen_centrality(g, directed = TRUE, scale = TRUE, weights = NULL, :
: At core/centrality/centrality_other.c:348 : Weighted directed graph in eigenvector centrality.

And how to interpret the result: 0.5566931 0.6198144 1.0000000 ?

Thanks for pointing out this confusing message. This should be improved. I am in fact not sure why it was added (over 12 years ago) but the likely reason is that eigenvector centrality is not well-defined for all inputs, and directed graphs can be problematic. Generally, people use hub and authority scores in directed graphs.

Eigenvector centrality is usually justified through the Perron-Frobenius theorem. In short, this guarantees that there is a unique non-negative solution to the problem if the graph is strongly connected and all weights are positive. Most directed networks you will come across are not strongly connected, and eigenvector centrality may not be meaningful. For example, there may be more than one solution to the problem, but igraph will only return one (without warning) or may fail entirely.

The documentation states:

Eigenvector centrality scores correspond to the values of the first eigenvector of the graph adjacency matrix.

This is well defined but only unique if the graph is strongly connected as in this example (from Edmund Landau in Über Preisverteilung bei Spielturnieren) as you pointed out.

The result I expect is:

> pev <- Re(eigen(g[])$vector[,1])  # Principle/first eigenvalue
> pev / pev[3]  # normalize
[1] 1.796322 1.113386 1.000000

However the result from eigen_centrality in this example is different, e.g.

[1] 0.5566931 0.6198144 1.0000000

Which result is correct?

igraph computes the left eigenvalue, i.e. the score of a vertex is proportional to the sum of the scores of vertices pointing to it (not the vertices it points to). With eigen you computed the right eigenvalue.

There is more extensive documentation here:

https://igraph.org/c/html/latest/igraph-Structural.html#igraph_eigenvector_centrality

If I am right I have to reverse the arrows of the graph to get the right eigenvector of the graph.

Unfortunately this does not seem to work as is shown in the following code:

> tg <- g %>% get.edgelist %>% .[, 2:1] %>% graph_from_edgelist(directed=TRUE) # transpose graph
> ec <- 
+ eigen_centrality(
+   tg,
+   directed = TRUE,
+   scale = TRUE,
+   weights = NULL,
+   options = arpack_defaults
+ )$vector
> ec <- ec / ec[3]
> ec
[1] 1.3247180 0.7548777 1.0000000

After recreating the graph with reversed edges, you did not transfer the original weights.

There’s ongoing work to add a function for reversing edges without losing attributes, as well as for adding a mode argument to eigen_centrality():

Vote for these issues to indicate your interest, then we might resolve them sooner.

Thanks for pointing this out.

tg <- g %>% get.edgelist %>% .[, 2:1] %>% graph_from_edgelist(directed=TRUE) # transpose graph
E(tg)$weight <- E(g)$weight
tg <- permute(tg, match(V(tg)$name, V(g)$name)) # restore original order of vertices
identical(V(tg)$name, V(sg)$name)

 ec <- 
  eigen_centrality(
   tg,
   directed = TRUE,
   scale = TRUE,
   weights = NULL,
   options = arpack_defaults
)$vector

Warning message:
In eigen_centrality(tg, directed = TRUE, scale = TRUE, weights = NULL,  :
  At core/centrality/centrality_other.c:348 : Weighted directed graph in eigenvector centrality.
> ec / ec[3]
[1] 1.796322 1.113386 1.000000
> 

Which is correct indeed.

Transpose(g) would be a nice name for a function to reverse edges.
See Transpose graph - Wikipedia