I have a graph whose weights are complex numbers. networkx
has a few functions for converting the graph to a matrix of edge weights, however, it doesn't seem to work for complex numbers (though the reverse conversion works fine). It seems to require either int
or float
edge weights in order to convert them into a NumPy array/matrix.
Python 3.9.7 | packaged by conda-forge | (default, Sep 29 2021, 19:20:46)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.29.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import numpy as np
In [2]: import networkx as nx
In [3]: X = np.random.normal(size=(5,5)) 1j*np.random.normal(size=(5,5))
In [4]: X
Out[4]:
array([[ 1.64351378-0.83369888j, -2.29785353-0.86089473j,
...
...
0.50504368-0.67854997j, -0.29049118-0.48822688j,
0.22752377-1.38491981j]])
In [5]: g = nx.DiGraph(X)
In [6]: for i,j in g.edges(): print(f"{(i,j)}: {g[i][j]['weight']}")
(0, 0): (1.6435137789271903-0.833698877745345j)
...
(4, 4): (0.2275237661137745-1.3849198099771993j)
# So conversion from matrix to nx.DiGraph works just fine.
# But the other way around gives an error.
In [7]: Z = nx.to_numpy_array(g, dtype=np.complex128)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-b0b717e5ec8a> in <module>
----> 1 Z = nx.to_numpy_array(g, dtype=np.complex128)
~/miniconda3/envs/coupling/lib/python3.9/site-packages/networkx/convert_matrix.py in to_numpy_array(G, nodelist, dtype, order, multigraph_weight, weight, nonedge)
1242 for v, d in nbrdict.items():
1243 try:
-> 1244 A[index[u], index[v]] = d.get(weight, 1)
1245 except KeyError:
1246 # This occurs when there are fewer desired nodes than
TypeError: can't convert complex to float
I have looked at the documentation and all it seems to say is that this works only for a simple NumPy datatype and for compound types, one should use recarrays. I don't understand recarrays well and using np.to_numpy_recarray
also yields an error.
In [8]: Z = nx.to_numpy_recarray(g, dtype=np.complex128)
...
TypeError: 'NoneType' object is not iterable
So the question is how to convert the graph into a matrix of edge weights correctly?
CodePudding user response:
Below is a quick hack that could be useful until a fix is implemented:
import networkx as nx
import numpy as np
def to_numpy_complex(G):
# create an empty array
N_size = len(G.nodes())
E = np.empty(shape=(N_size, N_size), dtype=np.complex128)
for i, j, attr in G.edges(data=True):
E[i, j] = attr.get("weight")
return E
X = np.random.normal(size=(5, 5)) 1j * np.random.normal(size=(5, 5))
g = nx.DiGraph(X)
Y = to_numpy_complex(g)
print(np.allclose(X, Y)) # True