Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Common neighbors and preferential attachment score matrixes using igraph for python

Is there an efficient way to calculate the matrix score for common neighbors(CC) and preferential attachment(PA) in python? I'm using igraph to calculate score matrixes for other methods such as jaccard's coefficient (Graph.similarity_jaccard()), dice (Graph.similarity_dice) and adamic/adar (Graph.similarity_inverse_log_weighted()), but I haven't found any function to compute score matrixes for CC and PA.

Currently I'm doing:

#Preferential attachment score between nodes i and j in a graph g
len(g.neighbors(i))*len(g.neighbors(j))

#Common neighbors score between nodes i and j in a graph g
len(g.neighbors(i) and g.neighbors(j))

but I have to do this for all edges(i,j) in the network which in my case is really large.

If anyone knows any mathematical matrix operation that generates such score matrixes I'm looking for, I would appreciate as well.

like image 732
Paulo Avatar asked Jul 09 '11 03:07

Paulo


1 Answers

There is no direct function for this in igraph. However, note that len(g.neighbors(i)) is simply the degree of vertex i, so you can call g.degree(), treat it as a 1D matrix using NumPy, then multiply it with its own transpose s.t. a column vector is multiplied by a row vector from the right. This gives you the preferential attachment score matrix:

from numpy import matrix
d = matrix(g.degree())
pref_score_matrix = d.T*d

The common neighbors score is trickier using matrix notation, and I wouldn't operate with matrices anyway if your graph is really large (even with only 2000 vertices, you would have a matrix with 4 million elements). I would simply cache set representations of g.neighbors(i) for all possible values in a list, and then use that to calculate the common neighbor scores as sets can be intersected efficiently:

neisets = [set(g.neighbors(i)) for i in xrange(g.vcount())]
for v1, v2 in g.get_edgelist():
    common_neis = neisets[v1].intersection(neisets[v2])
    print "%d --> %d: %d" % (v1, v2, len(common_neis))

If you really want to stick to matrices, you can construct an n by n matrix consisting of zeros only using the zeros function from NumPy and then loop over the vertices once. Get all the neighbors of vertex v and note that any pair of neighbors of v have one neighbor in common: v itself:

from itertools import combinations
from numpy import zeros

n = g.vcount()
common_neis = zeros(n, n)
for v in xrange(g.vcount()):
    neis = g.neighbors(v)
    for u, w in combinations(neis, 2):
        # v is a common neighbor of u and w
        common_neis[u, w] += 1
        common_neis[w, u] += 1
like image 88
Tamás Avatar answered Oct 23 '22 06:10

Tamás