I've been trying to calculate graph properties of any given graph using the networkx package and numpy in python. However, when I calculate the eigenvalues of a graph laplacian, it seems that numpy and networkx return different eigenvalues. Why is this happening?
import numpy as np
import networkx as nx
#function to normalize laplacian matrix
def symm_norm_laplacian(Lmat):
Drootmat = np.zeros(shape=(len(Lmat),len(Lmat)))
for i in range(0,len(Lmat)):
Drootmat[i,i] = 1/np.sqrt(Lmat[i,i])
return Drootmat @ Lmat @ Drootmat
#build simple graph
nodeids = np.array([0,1,2,3,4,5])
parentids = np.array([1,0,0,0,3,3])
G = nx.Graph()
#add nodes
for j in range(0,len(nodeids)):
G.add_node(nodeids[j])
#add edges
G.add_edge(0,1)
G.add_edge(0,2)
G.add_edge(1,2)
G.add_edge(4,5)
G.add_edge(4,3)
G.add_edge(4,0)
G.add_edge(3,5)
#get Laplacian matrix
LapMat = np.array(nx.laplacian_matrix(G).toarray())
#calculations through numpy
NormLapMat_np = symm_norm_laplacian(LapMat)
eval_np, evec_np = np.linalg.eigh(NormLapMat_np)
sortindex = np.argsort(eval_np)
print('numpy eigenvalues:',eval_np[sortindex])
#calculations through networkx
eval_nx = nx.laplacian_spectrum(G)
print('networkx eigenvalues:',eval_nx)
The output I get is:
numpy eigenvalues: [1.10622686e-16 2.04666355e-01 1.16666667e+00 1.50000000e+00
1.50000000e+00 1.62866698e+00]
networkx eigenvals: [-6.25317335e-16 4.38447187e-01 3.00000000e+00 3.00000000e+00
3.00000000e+00 4.56155281e+00]
When I run:
import numpy as np
print('numpy version:',np.__version__)
import networkx as nx
print('networkx version:',nx.__version__)
output is:
numpy version: 2.2.3
networkx version: 3.4.2
and python3 version is 3.12.2
It's driving me nuts trying to work out why the eigenvalues are so different. Could it be my specific machine (MacBook Pro M3 Max)?
You're performing a symmetric normalization on the Laplacian matrix when using NumPy
, but not when using NetworkX's
built-in function.
With NumPy
, you're calculating a normalized Laplacian matrix using your custom symm_norm_laplacian()
function
With NetworkX
, you're getting the unnormalized Laplacian spectrum directly with nx.laplacian_spectrum(G)
Example output with different methods:
--- YOUR CODE ---
NumPy eigenvalues (normalized): [-3.48799941e-16 2.04666355e-01 1.16666667e+00 1.50000000e+00
1.50000000e+00 1.62866698e+00]
NetworkX eigenvalues (unnormalized): [-1.25718377e-16 4.38447187e-01 3.00000000e+00 3.00000000e+00
3.00000000e+00 4.56155281e+00]
--- BOTH UNNORMALIZED ---
NumPy unnormalized eigenvalues: [-1.25718377e-16 4.38447187e-01 3.00000000e+00 3.00000000e+00
3.00000000e+00 4.56155281e+00]
NetworkX unnormalized eigenvalues: [-1.25718377e-16 4.38447187e-01 3.00000000e+00 3.00000000e+00
3.00000000e+00 4.56155281e+00]
Max difference: 0.0
--- BOTH NORMALIZED ---
NumPy custom normalized eigenvalues: [-5.55574672e-17 2.04666355e-01 1.16666667e+00 1.50000000e+00
1.50000000e+00 1.62866698e+00]
NetworkX normalized eigenvalues: [-5.55574672e-17 2.04666355e-01 1.16666667e+00 1.50000000e+00
1.50000000e+00 1.62866698e+00]