Home > Net >  Python - weighted graph from matrix
Python - weighted graph from matrix

Time:01-08

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 :

  1. 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.
  2. The operation 1.0/data doesn'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:]
  •  Tags:  
  • Related