各种类型创建图结构与adjacent matrix

前言

记录一下类型转换

1. 从edgelist创建adjacent matrix

1.1 错误方案 networkx

import networkx as nx

edgelist = [(0, 4),
 (0, 6),
 (0, 8), 
 (6, 5),
 (1, 2),
 (1, 3)]
adj = nx.adjacency_matrix(nx.from_edgelist(lis)).toarray()

print(adj)
array([[0, 1, 1, 1, 0, 0, 0, 0],
       [1, 0, 0, 0, 0, 0, 0, 0],
       [1, 0, 0, 0, 1, 0, 0, 0],
       [1, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 1, 1],
       [0, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0]])

是不是明显感觉不对。
0跟1之间明明没有边才对。

因为networkx会把传进来的node_name根据传入顺序重新编号索引
我们传入的第一条边是(0,4),结点0被编号为0,结点4被编号为1。
于是adj里就有了(0,1)相连。

问题是,我们原来存储的edge_list已经编号过了,不劳您费心重新编号啊。
此时需要更lazy的方法。

1.2 正确方案 scipy.sparse.coo_matrix

import scipy

edgelist = np.array([(0, 4),
 (0, 6),
 (0, 8), 
 (6, 5),
 (1, 2),
 (1, 3)]
 )

num_edges = len(edgelist)
num_nodes = 9
adj = scipy.sparse.coo_matrix(
    (np.ones(num_edges), (edgelist[:, 0], edgelist[:, 1])),
      shape=(num_nodes ,num_nodes),
      dtype=np.float32)

adj =adj.toarray()
print(adj)
array([[0., 0., 0., 0., 1., 0., 1., 0., 1.],
       [0., 0., 1., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 1., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)

上面这个方案没有过滤原始数据里可能存在的重复边。
如果需要考虑去重只需要加一句

rows, cols, data = zip(*set(zip(rows, cols, data)))

完整如下

import scipy
import numpy as np

edgelist = np.array([(0, 4),
 (0, 6),
 (0, 8), 
 (6, 5),
 (1, 2),
 (1, 3)]
 )


def form_adj(edgelist, num_nodes):
    num_edges = len(edgelist)

    rows = edgelist[:, 0]
    cols = edgelist[:, 1]
    data = np.ones(num_edges)

    # 去重
    rows, cols, data = zip(*set(zip(rows, cols, data)))

    adj = scipy.sparse.coo_matrix(
        (data, (rows, cols)),
        shape=(num_nodes ,num_nodes),
        dtype=np.float32)
	return adj

adj = form_adj(edgelist, num_nodes = 9)
print(adj.toarray())     

1.3 使用外部工具包

事实上edge_list是大部分开源库都支持的一种标准输入格式。

比如 torch_geometric创建图是

edgelist = np.array([(0, 4),
 (0, 6),
 (0, 8), 
 (6, 5),
 (1, 2),
 (1, 3)]
 )
 
edge_index = edgelist.T  #(e, |E|)
g = Data(edge_index=edge_index)

dgl同理也把edge_index = (2,|E|) 作为标准输入



2. 从neighbor list 邻接表 创建adjacent matrix

输入形如

[[1],
[0, 2],
[1, 3],
[2, 3]]

这种叫邻接表。

一种简单的想法是把 neighbor list 变成 edge_list 再由第一部分中介绍的 edege list 直接建图。

neigh_list =  [[1],
  [0, 2],
  [1, 3],
  [2, 3]]
  
def neighList_to_edgeList(neigh_list):
    edge_list = []
    for i in range(len(neigh_list)):
        for j in neigh_list[i]:
            edge_list.append((int(i),int(j)))
    edge_list = np.array(edge_list)
    return edge_list
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值