web-dev-qa-db-ja.com

Pythonの隣接行列

重みを考慮して、Pythonで隣接行列を作成する方法に関する明確な説明はありません。比較的簡単に作成できると思います。

次のマトリックスがあります...

   1   2   3   4   5   6
1  0   15  0   7   10  0
2  15  0   9   11  0   9
3  0   9   0   0   12  7
4  7   11  0   0   8   14
5  10  0   12  8   0   8
6  0   9   7   14  8   0

1から6までの数字は頂点で、その中の数字は隣接する各頂点間の重みです。たとえば、エッジ1-2の重みは15です。

これをどのようにPythonに実装しますか?私が提供したものを必ずしも使用する必要はなく、単純な例が必要です。

隣接リストの作成方法を知っています...

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'}]}

しかし、隣接行列が必要です。

8
Bolboa

隣接行列を格納するための最も一般的で最も単純な概念は、2D配列を使用することだと思います。これは、pythonがネストされたリストに対応します

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

値が読み取り専用の場合、代わりにネストされたタプルを使用できます:)

もちろん、マトリックスを対称にすることで、辞書を使用したり、クラスを記述して__getattr__を再定義したりして、アクセス時間とストレージをより効率的にすることができます。

2
enpenax

私はこのようなPythonの2D構造のタプルキーが好きです。

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

上記のソリューションで中間データ構造が削除されるため、概念的には最も明確だと思います。それにもかかわらず、その中間データ構造(内部リストまたは行/列)は、行または列のいずれかの構造にアクセスする場合に役立ちます。

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

ただし、セル単位のデータアクセスがあなたのゲームである場合、表現を単純にするために以下を打ち負かすことは困難です。

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

必要に応じて並べ替えます。

 # (1, 1), (1, 2)...
 for (x, y), value in sorted(matrix.iteritems()):
       # act on cell
4
jwilner

これにより、「隣接リスト」(実際にはリストではなく、dict)が真の行列に変換されます。

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)

graphの形式は、networkxでの使用には特に便利ではありません。)networkxは、グラフとその隣接行列に対するあらゆる種類の操作をサポートしているため、形式はあなたにとって非常に役立つはずです。 Pythonインデックスを使用するようにグラフをシフトしました(つまり、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.]])
2
dbliss

前述のように、Pythonでマトリックスを処理する標準的な方法は、 NumPy を使用することです。隣接関係リストから隣接関係マトリックスを単に読み取る関数を次に示します。(ノードの暗黙的な順序付けは、パラメーター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()
_

この場合、weighted_adjmatrix(graph, nodes=list('123456'))はNumPy配列を提供します

_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]])
_

通常のリストが必要な場合は、メソッドtolist()を呼び出すことができます。

1
egnha