简体   繁体   English

更优雅的方法从元组列表生成邻接矩阵

[英]More elegant way to generate adjacency matrix from list of tuples

Suppose we start with a "friendship" graph represented by a list of tuples, 假设我们从一个由元组列表表示的“友谊”图开始,

friendships = [(0, 1), (0, 2), (1, 2), (1, 3), (2,
3), (3, 4),(4, 5), (5, 6), (5, 7), (6, 8), (7, 8), (8, 9)]

where element 0 is a friend of 1 (and hence 1 is a friend of 0). 其中元素0是1的朋友(因此1是0的朋友)。

I want to construct the adjacency matrix from scratch in a way that will always work for this type of tuple representation. 我想从头开始构建邻接矩阵,这种方式总是适用于这种类型的元组表示。

I have the following (repulsive) Python code: 我有以下(令人厌恶的)Python代码:

def make_matrix(num_rows,num_cols,entry_fn):
    return [[entry_fn(i,j)
             for j in range(num_cols)]
            for i in range(num_rows)]
def adjacency(connections):
    new=connections+[(x[1],x[0]) for x in connections]
    elements=list(set([x[0] for x in connections]+ [x[1] for x in connections]))
    def test(i,j):
        if (elements[i],elements[j]) in new:
            return 1
        else: return 0
    return make_matrix(len(elements),len(elements),test)

I know that it is inefficient and very ugly. 我知道这是低效率和非常丑陋的。 Is there a smarter way to solve this problem? 有没有更聪明的方法来解决这个问题? The output for the example list that I gave above should be 我上面给出的示例列表的输出应该是

[[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [1, 0, 1, 1, 0, 0, 0, 0, 0, 0],
 [1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
 [0, 1, 1, 0, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 0, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 0, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 0]]

update: as per one of the answers, I have the following possible solution, although I don't know if it's any better 更新:根据其中一个答案,我有以下可能的解决方案,虽然我不知道它是否更好

def adj(connections):
    ##step 1
    temp=(set(elem[0] for elem in connections).union(
        set(elem[1] for elem in connections)))
    n=max(temp)+1
    ans=[]
    ##step 2
    for i,_ in enumerate(temp):
        ans.append([])
        for j,_ in enumerate(temp):
            ans[i].append(0)
    ##step 3
    for pair in connections:
        ans[pair[0]][pair[1]]=1
        ans[pair[1]][pair[0]]=1
    return ans

My algorithm would be something like this: 我的算法是这样的:

  1. Find the maximum vertex id. 找到最大顶点id。 Call this n . 调用此n
  2. Create an n+1 by n+1 array of zeros. 创建一个n+1n+1的零数组。 Call this M . 叫这个M
  3. For each pair x, y in the input list, set M[x][y] = 1 对于输入列表中的每对x, y ,设置M[x][y] = 1

To come up with this solution, I first thought of step 3. With the given input, this seems the most straightforward way to populate the adjacency matrix. 为了得出这个解决方案,我首先想到了第3步。使用给定的输入,这似乎是填充邻接矩阵的最直接的方法。 However, it requires a 2D array of a fixed size. 但是,它需要固定大小的2D阵列。 So the problem is how do I figure out n for step 2. From there it doesn't take much thought to figure out step 1 is what is needed. 所以问题是我如何计算出第2步的n 。从那里不需要花太多时间去弄清楚步骤1是什么需要。

The details are left as an exercise for the reader. 详细信息留给读者练习。

I am not much of a Python programmer, but something like... 我不是一个Python程序员,但是像...

def to_adjacency_matrix(pairs):
  size = 1 + max(map(max, pairs))
  a = [[0 for j in range(size)] for i in range(size)]
  for i, j in pairs:
    a[i][j] = a[j][i] = 1
  return a

If you want short and easy-readable solution (and you are planning to work with graph later) I recommend you to use networkx library. 如果您想要简短易读的解决方案(并且您计划稍后使用图表),我建议您使用networkx库。 Your problem can be solved with pair of lines: 你的问题可以用一对线来解决:

import networkx as nx
G = nx.Graph()
G.add_edges_from(friendships)
nx.to_numpy_matrix(G)

which will return numpy matrix: 这将返回numpy矩阵:

matrix([[0., 1., 1., 0., 0., 0., 0., 0., 0., 0.],
        [1., 0., 1., 1., 0., 0., 0., 0., 0., 0.],
        [1., 1., 0., 1., 0., 0., 0., 0., 0., 0.],
        [0., 1., 1., 0., 1., 0., 0., 0., 0., 0.],
        [0., 0., 0., 1., 0., 1., 0., 0., 0., 0.],
        [0., 0., 0., 0., 1., 0., 1., 1., 0., 0.],
        [0., 0., 0., 0., 0., 1., 0., 0., 1., 0.],
        [0., 0., 0., 0., 0., 1., 0., 0., 1., 0.],
        [0., 0., 0., 0., 0., 0., 1., 1., 0., 1.],
        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.]])

or 要么

nx.adjacency_matrix(G)

which will return scipy sparse matrix: 这将返回scipy稀疏矩阵:

<10x10 sparse matrix of type '<class 'numpy.int64'>'
    with 24 stored elements in Compressed Sparse Row format>

I would do: 我会做:

import numpy as np

def adjacency(connections):
    n_people = max(sum(connections, ())) + 1
    mat = np.zeros((n_people, n_people), dtype='int')
    for friend1, friend2 in connections:
        mat[friend1, friend2] = 1
        mat[friend2, friend1] = 1
    return mat

and if by "from scratch" you mean that you don't want to use numpy: 如果“从头开始”你的意思是你不想使用numpy:

def adjacency(connections):
    n_people = max(sum(connections, ())) + 1
    mat = [[0 for _ in range(n_people)] for _ in range(n_people)]
    for friend1, friend2 in connections:
        mat[friend1][friend2] = 1
        mat[friend2][friend1] = 1
    return mat

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM