I'm trying to generate a weighted graph from the inverse of a given matrix.
data is my matrix.
data
array([[0. , 0.69, 0.65, 0.69, 0.64, 0.63, 0.7 ],
[0. , 0. , 0.72, 0.63, 0.87, 0.75, 0.78],
[0. , 0. , 0. , 0.7 , 0.72, 0.63, 0.71],
[0. , 0. , 0. , 0. , 0.68, 0.61, 0.66],
[0. , 0. , 0. , 0. , 0. , 0.78, 0.81],
[0. , 0. , 0. , 0. , 0. , 0. , 0.83],
[0. , 0. , 0. , 0. , 0. , 0. , 0. ]])
inv_mat is the inverse of data
inv_mat = 1.0/data
inv_mat
array([[ inf, 1.44927536, 1.53846154, 1.44927536, 1.5625 ,
1.58730159, 1.42857143],
[ inf, inf, 1.38888889, 1.58730159, 1.14942529,
1.33333333, 1.28205128],
[ inf, inf, inf, 1.42857143, 1.38888889,
1.58730159, 1.4084507 ],
[ inf, inf, inf, inf, 1.47058824,
1.63934426, 1.51515152],
[ inf, inf, inf, inf, inf,
1.28205128, 1.2345679 ],
[ inf, inf, inf, inf, inf,
inf, 1.20481928],
[ inf, inf, inf, inf, inf,
inf, inf]])
When I try to generate a networkx graph using the matrix data, I get the correct edge weights as shown in the matrix. But, when I do it on the inverse, inv_mat, all the edge weights become 'inf'.
G = nx.from_numpy_matrix(np.matrix(inv_mat))
G.edges(data=True)
EdgeDataView([(0, 0, {'weight': inf}), (0, 1, {'weight': inf}), (0, 2, {'weight': inf}), (0, 3, {'weight': inf}), (0, 4, {'weight': inf}), (0, 5, {'weight': inf}), (0, 6, {'weight': inf}), (1, 1, {'weight': inf}), (1, 2, {'weight': inf}), (1, 3, {'weight': inf}), (1, 4, {'weight': inf}), (1, 5, {'weight': inf}), (1, 6, {'weight': inf}), (2, 2, {'weight': inf}), (2, 3, {'weight': inf}), (2, 4, {'weight': inf}), (2, 5, {'weight': inf}), (2, 6, {'weight': inf}), (3, 3, {'weight': inf}), (3, 4, {'weight': inf}), (3, 5, {'weight': inf}), (3, 6, {'weight': inf}), (4, 4, {'weight': inf}), (4, 5, {'weight': inf}), (4, 6, {'weight': inf}), (5, 5, {'weight': inf}), (5, 6, {'weight': inf}), (6, 6, {'weight': inf})])
Any idea why this is happening? I want G to have the edge weights as indicated by inv_mat.
Could someone help me get rid of this problem?
CodePudding user response:
There's two problems here :
- the matrix you provided isn't inversible. It is a triangular matrix with zeros on its diagonal. So it's a singular matrix that can't be inversed.
- The operation
1.0/datadoesn't compute the inverse of a matrix but a new matrix where every coefficient is inversed :1 / [[1, 2],[3, 4]] = [[1/1, 1/2], [1/3, 1/4]]. This is not matrix inversion.
To inverse a matrix you can use :
import numpy as np
x = np.array([[1,2],[3,4]])
y = np.linalg.inv(x)
It will raise a numpy.linalg.LinAlgError with your example since your matrix can't be inversed, as shown below :
import numpy as np
data = np.array(
[
[0.0, 0.69, 0.65, 0.69, 0.64, 0.63, 0.7],
[0.0, 0.0, 0.72, 0.63, 0.87, 0.75, 0.78],
[0.0, 0.0, 0.0, 0.7, 0.72, 0.63, 0.71],
[0.0, 0.0, 0.0, 0.0, 0.68, 0.61, 0.66],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.78, 0.81],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.83],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
]
)
np.linalg.inv(data)
When runned :
Traceback (most recent call last):
Traceback (most recent call last):
File "/home/quentin/gdrive/dev/python/stackoverflow_answers/weighted_from_matrix.py", line 14, in <module>
np.linalg.inv(data)
File "<__array_function__ internals>", line 180, in inv
File "/usr/lib/python3.10/site-packages/numpy/linalg/linalg.py", line 545, in inv
ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
File "/usr/lib/python3.10/site-packages/numpy/linalg/linalg.py", line 88, in _raise_linalgerror_singular
raise LinAlgError("Singular matrix")
numpy.linalg.LinAlgError: Singular matrix
CodePudding user response:
1.0/0 = inf
you can divide by only non-zero elements to avoid this issue
inv_mat=data
for i in range(inv_mat.shape[0]-1):
inv_mat[i,i 1:] = 1.0/inv_mat[i,i 1:]
