nx.adjacency_matrix计算邻接矩阵与真实结果不一致的解决
作者:小猪上吊ing 发布时间:2023-12-06 14:23:56
问题描述
我自己根据edgelist计算的邻接矩阵,与调用networkx.adjacency_matrix(g)返回的结果不一样,经过调试发现了问题原因以及解决办法,记录如下。
原来的代码
edgelist = [
(0, 1),
(1, 3),
(2, 4),
(1, 5),
(1, 3),
(5, 5),
(1, 3)
]
"""由于nx.MultiGraph()可累计多条重复边作为权重,所以(1,3)出现3次权重是3"""
g = nx.MultiGraph() # 无向多边图
g.add_edges_from(edgelist)
adj = sp.lil_matrix(nx.adjacency_matrix(g))
print(adj.todense())
实际运行输出
[[0 1 0 0 0 0]
[1 0 3 0 0 1]
[0 3 0 0 0 0]
[0 0 0 0 1 0]
[0 0 0 1 0 0]
[0 1 0 0 0 1]]
理论结果
[[0 1 0 0 0 0]
[1 0 0 3 0 1]
[0 0 0 0 1 0]
[0 3 0 0 0 0]
[0 0 1 0 0 0]
[0 1 0 0 0 1]]
节点id从0开始。对于边(1,3),矩阵的第二行第四列应当为权重3,可以看到实际运行输出结果中,3却出现在了第二行第三列!
调试过程
查看了networkx.adjacency_matrix()的源代码,其中有一条说明如下:
def adjacency_matrix(G, nodelist=None, weight='weight'):
"""Return adjacency matrix of G.
Parameters
----------
G : graph
A NetworkX graph
nodelist : list, optional
The rows and columns are ordered according to the nodes in nodelist.
If nodelist is None, then the ordering is produced by G.nodes().
weight : string or None, optional (default='weight')
The edge data key used to provide each value in the matrix.
If None, then each edge has weight 1.
...
...
"""
return nx.to_scipy_sparse_matrix(G, nodelist=nodelist, weight=weight)
第二个参数的说明需要格外注意!对于nodelist这个参数,说明是这样的:邻接矩阵的行和列的排序按照nodelist中节点顺序来!如果不传这个参数,默认是按照传进来的图G调用G.nodes()时返回的节点的顺序!
所以我查看了我传进去的图g的节点默认顺序是什么样的:
edgelist = [
(0, 1),
(1, 3),
(2, 4),
(1, 5),
(1, 3),
(5, 5),
(1, 3)
]
"""由于nx.MultiGraph()可累计多条重复边作为权重,所以(1,3)出现3次权重是3"""
g = nx.MultiGraph() # 无向多边图
g.add_edges_from(edgelist)
print(g.nodes())
adj = sp.lil_matrix(nx.adjacency_matrix(g))
print(adj.todense())
运行结果居然:
[0, 1, 3, 2, 4, 5]
[[0 1 0 0 0 0]
[1 0 3 0 0 1]
[0 3 0 0 0 0]
[0 0 0 0 1 0]
[0 0 0 1 0 0]
[0 1 0 0 0 1]]
图g的节点列表居然不是按照从小到大的顺序排列,id为3的节点居然是第三而不是第四位序,这就是为什么边(1,3)的权重会写在矩阵的第三列…因为矩阵第三列对应节点3!
那…为什么图g的节点列表不是排好序的,为什么是[0, 1, 3, 2, 4, 5]这个顺序?
因为:加新边sdd_edges的时候会自动加新节点!!!
边(0,1)加进去的时候,节点列表是[0,1];加边(1, 3)的时候,节点列表[0,1,3];…。所以节点默认列表的顺序,跟你加新边时候哪个节点先出现有关系。
解决方案
那么在添加新边之前,先把节点按id从小到大顺序排好同意添加,就可以了。
具体就是:在g.add_edges_from(edgelist)操作之前,先把edgelist中的节点抽取出来按顺序排好,用操作g.add_nodes_from()把节点统一添加进图g中。修改后的代码如下:
修改后的代码
edgelist = [
(0, 1),
(1, 3),
(2, 4),
(1, 5),
(1, 3),
(5, 5),
(1, 3)
]
"""由于nx.MultiGraph()可累计多条重复边作为权重,所以(1,3)出现3次权重是3"""
g = nx.MultiGraph() # 无向多边图
""" 节点id按照顺序排!!否则生成的邻接矩阵不一样 """
nodeset = sorted(set(itertools.chain(*edgelist)))
g.add_nodes_from(nodeset)
g.add_edges_from(edgelist)
print(g.nodes())
adj = sp.lil_matrix(nx.adjacency_matrix(g))
print(adj.todense())
修改代码后的运行结果
[0, 1, 2, 3, 4, 5]
[[0 1 0 0 0 0]
[1 0 0 3 0 1]
[0 0 0 0 1 0]
[0 3 0 0 0 0]
[0 0 1 0 0 0]
[0 1 0 0 0 1]]
函数说明
nodeset = sorted(set(itertools.chain(*edgelist)))这行的功能,是把edgelist中的元素展开,去重,按顺序排序。分开演示就是:
edgelist = [
(0, 1),
(1, 3),
(2, 4),
(1, 5),
(1, 3),
(5, 5),
(1, 3)
]
""" 把edgelist中的每个(a,b)元素打平成a,b """
nodes = list(itertools.chain(*edgelist))
print(nodes)
# 输出:
# [0, 1, 1, 3, 2, 4, 1, 5, 1, 3, 5, 5, 1, 3]
""" 利用set元素唯一的性质,将重复元素去重 a,a => a """
nodeset = set(nodes)
print(nodeset)
# 输出:
# {0, 1, 2, 3, 4, 5}
""" set中的元素是无序、非空、唯一的,所以对set再sorted一下,确保顺序是对的 """
nodeset = sorted(nodeset)
print(nodeset)
# 输出:
# [0, 1, 2, 3, 4, 5]
来源:https://blog.csdn.net/yingluo54/article/details/113325108


猜你喜欢
- 直方图,又称质量分布图,是一种统计报告图,由一系列高度不等的纵条或线段表示数据分布情况。用横轴表示数据类型,纵轴表示分布情况。直方图是数值数
- python框架有很多,例如:Flask,Django,FastAPI 等。本文将使用 Flask 来编写 API 接口。安装Flask首先
- 举例为大家介绍如何运用命令行实现MySQL导出导入数据库一、命令行导出数据库1.进入MySQL目录下的bin文件夹:cd MySQL中到bi
- 一、准备工作:1.建立一个 WINDOWS 用户,设置为管理员权限,并设置密码,作为发布快照文件的有效访问用户。2.在SQL SERVER下
- 在新版的Vue CLI 3中,如何导入公共less文件在文档里已经描述的很清楚了,但是在2.*的版本中,我没有查到相关的办法,网友的办法又相
- 学习Python,基本语法不是特别难,有了C的基本知识,理解比较容易。本文的主要内容是Python基础语法,学完后,能熟练使用就好。(开发环
- 1、demo第一个代码是多线程的简单使用,编写了线程如何执行函数和类。import threadingimport timeclass Cl
- 我们都知道float:left和float:right,但是否想过float:center呢?居中浮动。。。<div id="
- 本文使用TensorFlow实现最简单的线性回归模型,供大家参考,具体内容如下线性拟合y=2.7x+0.6,代码如下:import tens
- 随着 CSS3 渐入人心,Web 字体逐渐成为话题,这种即将让未来的 Web 更加丰富多彩的技术(或者说标准)拥有多种可能,虽然 .webf
- 每种语言都有自己的优势,互相结合起来各取所长程序执行起来效率更高或者说哪种实现方式较简单就用哪个,nodejs是利用子进程来调用系统命令或者
- 整理文档,搜刮出一个vue 计时器组件的代码,稍微整理精简一下做下分享。<template> <div>  
- 本文实例主要是实现爬取一个网页上的图片地址,具体如下。读取一个网页的源代码:import urllib.requestdef getHtml
- 本文实例讲述了PHP利用func_get_args和func_num_args函数实现函数重载的方法。分享给大家供大家参考。具体方法分析如下
- VBScript似乎已经成为ASP服务器端开发的首先语言,VBScript函数库丰富、而且使用起来也很容易上手,即使平时不太编程的朋友,只要
- by yemoo有时在编写网页代码时发现,img底部莫名奇妙多出大约3px的空白,无论怎么调节css都不可以,今天再次遇到此问题,网上看了一
- 想弄个截屏工具,整理一下学生错题什么的,原来用的方法是:先运行QQ,再监听键盘热键(“ctrl+alt+a”)。后来发现有些问题:需要先上Q
- 在ASP编程中,身份认证可以说是常要用到的。但怎么样才能做到认证的安全呢?表单提交页面:sub.htm  
- 知识补充表单简介(来自Mr._Dang)action:提交的地址method:提交的方式 get: 参数是在url中的,不安全,传输量比较少
- 每个JavaScript函数都有prototype属性(javascript对象没有这个属性),这个属性引用了一个对象,这个对象就是原型对象