Adjacency matrix in Python

后端 未结 4 740
我寻月下人不归
我寻月下人不归 2021-02-06 03:43

I cannot find any clear explanation as to how to create an adjacency matrix in Python, with weights taken into consideration. I assume it should be relatively simple to create.<

相关标签:
4条回答
  • 2021-02-06 04:13

    As mentioned previously, the standard way to deal with matrices in Python is to use NumPy. Here's a function that simply reads the adjacency matrix off of the adjacency list. (The implicit ordering of the nodes is made explicit by the parameter nodes.)

    import numpy
    
    def weighted_adjmatrix(adjlist, nodes):
        '''Returns a (weighted) adjacency matrix as a NumPy array.'''
        matrix = []
        for node in nodes:
            weights = {endnode:int(weight)
                       for w in adjlist.get(node, {})
                       for endnode, weight in w.items()}
            matrix.append([weights.get(endnode, 0) for endnode in nodes])
        matrix = numpy.array(matrix)
        return matrix + matrix.transpose()
    

    In this case, weighted_adjmatrix(graph, nodes=list('123456')) gives the NumPy array

    array([[ 0, 15,  0,  7, 10,  0],
           [15,  0,  9, 11,  0,  9],
           [ 0,  9,  0,  0, 12,  7],
           [ 7, 11,  0,  0,  8, 14],
           [10,  0, 12,  8,  0,  8],
           [ 0,  9,  7, 14,  8,  0]])
    

    If a regular list is desired, the method tolist() can be called.

    0 讨论(0)
  • 2021-02-06 04:16

    I like tupled keys for 2d structures like this in python.

    {(1, 1): 0, (3, 2): 9... }
    

    I think it's conceptually clearest since it drops the intermediary data structure in the above solution. Nonetheless, that intermediary data structure -- the inner list or row / column-- can be useful if you intend to access your structure either row or column wise.

     for x, row in enumerated(matrix, 1):
           # process whole row 
           for y in enumerate(row, 1):
                 # process cell...
    

    If cell-wise data access is your game though, it's hard to beat the following for expressive simplicity:

    for (x, y), value in matrix.iteritems():
          # act on cell
    

    Sort it if you want.

     # (1, 1), (1, 2)...
     for (x, y), value in sorted(matrix.iteritems()):
           # act on cell
    
    0 讨论(0)
  • 2021-02-06 04:28

    I think the most common and simplest concept to store an adjacency matrix is to use a 2D array, which in python corresponds to nested lists

    mat = [[0, 15, 0, 7, 10, 0], [15, 0, ...], [...], [...]]
    m[0][1]  # = 15 (weight of 1-2)
    

    If the values are read only, you can use nested tuples, instead :)

    Of course you can go as crazy as you want with that and use dictionaries or write a class and redefine __getattr__ to be more efficient on access times and storage as the matrix is symmetrical.

    0 讨论(0)
  • 2021-02-06 04:36

    This converts your "adjacency list" (really a dict, not a list) into a genuine matrix:

    import networkx as nx
    
    graph = {'1': [{'2':'15'}, {'4':'7'}, {'5':'10'}],
        '2': [{'3':'9'}, {'4':'11'}, {'6':'9'}],
        '3': [{'5':'12'}, {'6':'7'}],
        '4': [{'5':'8'}, {'6':'14'}],
        '5': [{'6':'8'}]}
    new_graph = nx.Graph()
    for source, targets in graph.iteritems():
        for inner_dict in targets:
            assert len(inner_dict) == 1
            new_graph.add_edge(int(source) - 1, int(inner_dict.keys()[0]) - 1,
                               weight=inner_dict.values()[0])
    adjacency_matrix = nx.adjacency_matrix(new_graph)
    

    (The format of your graph is not particularly convenient for use in networkx.) networkx supports all kinds of operations on graphs and their adjacency matrices, so having the graph in this format should be very helpful for you. Note also that I've shifted your graph to use Python indices (i.e., starting at 0).

    In [21]: adjacency_matrix
    Out[21]: 
    matrix([[  0.,  15.,   0.,   7.,  10.,   0.],
            [ 15.,   0.,   9.,  11.,   0.,   9.],
            [  0.,   9.,   0.,   0.,  12.,   7.],
            [  7.,  11.,   0.,   0.,   8.,  14.],
            [ 10.,   0.,  12.,   8.,   0.,   8.],
            [  0.,   9.,   7.,  14.,   8.,   0.]])
    
    0 讨论(0)
提交回复
热议问题