networkx与PyG计算度数degree时需避免的坑:自环selfloop和多重边

2023-10-29 10:10

本文主要是介绍networkx与PyG计算度数degree时需避免的坑:自环selfloop和多重边,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

networkx与PyG计算度数degree时需避免的坑:自环selfloop和多重边

  • networkx
    • 有向图的self-loop
    • 无向图self-loop
    • 多重边
  • pytorch geometric

近日需要统计图的基本性质,在使用 nxPyG自带的度数计算时,发现他们的底层逻辑是不同的,因此计算结果在一些情况下也会不同。这里做个简单的小结,也避免自己今后踩坑。

先上结论:

  • networkx在计算度数的时候,自环selfloop部分会被计算为2,多重边只计算一条。
  • PyG中度数计算不分方向,只和传入index中每个节点出现的次数有关。
    • 使用PyG中的to_undirected将有向图转化为无向图后,自环边只有一条,因此自环度数为1
    • 多重边的度数为相应为n

下面分别看一下具体的实例。

networkx

有向图的self-loop

import networkx as nx
DG = nx.DiGraph()
DG.add_edges_from([[0, 0], [0, 1], [1, 2]])
nx.draw(DG, with_labels=True)

在这里插入图片描述
分别计算degree, out_degreein_degree

DG.degree(DG.nodes())
>>> DiDegreeView({0: 3, 1: 2, 2: 1}) #节点0的度数为3,因为自环的度数是2
DG.out_degree(DG.nodes())
>>> OutDegreeView({0: 2, 1: 1, 2: 0}) #节点0的出度为2,因为自环提供了出度1
DG.in_degree(DG.nodes())
>>> InDegreeView({0: 1, 1: 1, 2: 1}) #节点0的入度为1,因为自环提供了入度1

我们可以看到节点0degree, out_degreein_degree分别为3, 2, 1,这是因为在计算度数的时候,有向图中selfloop提供了2的度数。同样都是自己指向自己,但一次是自己指向了跟自己相同的邻居,一次是跟自己相同的邻居指向了自己。其中前者是出度,后者是入度。

无向图self-loop

import networkx as nx
G = nx.Graph()
G.add_edges_from([[0, 0], [0, 1], [1, 2]])
nx.draw(G, with_labels=True)

在这里插入图片描述

G.degree(G.nodes())
DegreeView({0: 3, 1: 2, 2: 1})

其中节点0的度数仍然为3。另外对于无向图,in_degreeout_degree方法不再适用。

多重边

import networkx as nx
DG = nx.DiGraph()
DG.add_edges_from([[0, 1], [0,1], [1, 2]])
nx.draw(DG, with_labels=True)

在这里插入图片描述

DG.out_degree(DG.nodes())
>>> OutDegreeView({0: 1, 1: 1, 2: 0})

可以看到尽管有两条(0,1)边,在计算度数的时候,只会被算作一条。这是因为nx内部存储是以字典形式存储信息的,多重边对应的键是一样的,因此后来传入的信息会覆盖前面的信息。

pytorch geometric

PyG的度数计算是利用torchscatter,所以是不分方向的,只看你传进去什么样的index。下面给大家举个例子:

from torch_geometric.utils import degree
import torchedge_index = torch.tensor([[0, 0], [0, 1], [1, 2]]).T.contiguous() #传入和nx例子中相同的边
edge_index
>>> 
tensor([[0, 0, 1],[0, 1, 2]])degree(edge_index[0])
>>> tensor([2., 1.])  #传入edge_index[0]计算出度,因为节点2没有出度,所以这里出度的shape只有(2,)degree(edge_index[0], num_nodes=3)
>>> tensor([2., 1., 0.]) #指定节点个数,避免维度不同degree(edge_index[1])
>>> degree(edge_index[1]) #传入edge_index[1]计算入度

PyGedge_index[0]source,所以对degree函数传入edge_index[0]计算出度。计算的逻辑就是统计index中每个节点出现的次数。如果有节点没有出度且节点的id在尾部,可以传入节点的个数,避免返回的结果出现缺失。同理传入edge_index[1]计算入度。

如果需要计算度数,可以先对有向的edge_index做无向处理。

from torch_geometric.utils import to_undirected
edge_index = to_undirected(edge_index)
edge_index
>>> tensor([[0, 0, 1, 1, 2],    #节点0的自环边只出现一次[0, 1, 0, 2, 1]])degree(edge_index[0])
>>> tensor([2., 2., 1.])

可以看出来,to_undirected并不会重复自环边,所以后期计算自环度数时为1

因为计算的degree只和传入的index有关,所以重复边会被重复统计。

from torch_geometric.utils import degree
import torchedge_index = torch.tensor([[0, 1], [0, 1], [1, 2]]).T.contiguous() #传入和上个例子中相同的边
edge_index
>>> tensor([[0, 0, 1],[1, 1, 2]])degree(edge_index[0])
>>> tensor([2., 1.])

这篇关于networkx与PyG计算度数degree时需避免的坑:自环selfloop和多重边的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/299948

相关文章

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

XTU 1237 计算几何

题面: Magic Triangle Problem Description: Huangriq is a respectful acmer in ACM team of XTU because he brought the best place in regional contest in history of XTU. Huangriq works in a big compa

多重背包转换成0-1背包

http://acm.hdu.edu.cn/showproblem.php?pid=2191 多重背包特点: 一种物品有C个(既不是固定的1个,也不是无数个) 优化的方法: 运用神奇的二进制,进行物品拆分,转化成01背包 物品拆分,把13个相同的物品分成4组(1,2,4,6) 用这4组可以组成任意一个1~13之间的数! 原理:一个数总可以用2^

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

如何来避免FOUC

FOUC(Flash of Unstyled Content)是指在网页加载过程中,由于CSS样式加载延迟或加载顺序不当,导致页面出现短暂的无样式内容闪烁现象。为了避免FOUC,可以采取以下几种方法: 1. 优化CSS加载 内联CSS:将关键的CSS样式直接嵌入到HTML文档的<head>部分,这样可以确保在页面渲染之前样式就已经加载和应用。提前引入CSS:将CSS文件放在HTML文档的<he

计算数组的斜率,偏移,R2

模拟Excel中的R2的计算。         public bool fnCheckRear_R2(List<double[]> lRear, int iMinRear, int iMaxRear, ref double dR2)         {             bool bResult = true;             int n = 0;             dou

GPU 计算 CMPS224 2021 学习笔记 02

并行类型 (1)任务并行 (2)数据并行 CPU & GPU CPU和GPU拥有相互独立的内存空间,需要在两者之间相互传输数据。 (1)分配GPU内存 (2)将CPU上的数据复制到GPU上 (3)在GPU上对数据进行计算操作 (4)将计算结果从GPU复制到CPU上 (5)释放GPU内存 CUDA内存管理API (1)分配内存 cudaErro