编写networkx插件

编写networkx插件

前言

networkx的时候发现在3.0版本支持实验性的插件支持 https://github.com/networkx/networkx/pull/6000 ,
支持替换networkx的计算后端,目前比较成熟的后端插件是graphblas https://github.com/python-graphblas/graphblas-algorithms/
通过这个插件,可以同时结合networkx
API的易用性以及graphblas的高性能。networkx插件的原理是利用了python的装饰器。
 
装饰器参考 https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584

networkx里面装饰器的核心代码在 networkx/classes/backends.py:130可以看到下面代码中,它会检查graph对象有没有 _
_networkx_plugin__ 如果有并且这个插件名已经注册在networkx,那么networkx中就会加载插件后端来进行计算。

gkpiqb

关于如何编写插件替换networkx的文档资料,网络上还是比较少,在这里记录一下编写插件的方法。

编写插件

名字

为你需要编写的插件起一个名字,networkx会用名字去调用插件,本文用nxdemo这个名字说明。

图对象

定义一个你的插件用来计算的图对象,在这个类里面,需要定义插件名字

1
2
class Graph:
__networkx_plugin__ = "nxdemo"

调度员

定义一个调度类。

调度类里面定义nx的函数名指向自定义的算法实现,例如弱联通分量的指向:

1
2
class Dispatcher:
weakly_connected_components = nx_plugin_demo.algo.weakly_connected_components

调度类里面可以接着写插件的图对象与nx的图对象转换函数

1
2
    @staticmethod
def convert_from_nx(G: nx.Graph, weight=None, name=None):
1
2
3
4
 @staticmethod


def convert_to_nx(graph):

最后在entry_points(setup.py)里面定义插件调度员位置,这里需要用到插件名字

1
2
3
4
5
6
7
8
9
10
from setuptools import setup

setup(
''''''
entry_points = {
'networkx.plugins': [
'nxdemo = nx_plugin_demo.Dispatcher:Dispatcher'
]
}
)

使用插件

执行pip安装编写的插件。

networkx依据传入图对象的类型判断使用哪种后端进行计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import networkx as nx
from nx_plugin_demo.Dispatcher import Dispatcher

G = nx.DiGraph()

# 添加节点
G.add_node(1)
G.add_node(2)
G.add_node(3)
G.add_node(4)
G.add_node(5)

# 添加边
G.add_edge(1, 2)
G.add_edge(2, 1)
G.add_edge(2, 3)
G.add_edge(3, 4)

# 转换图对象
G2 = Dispatcher.convert_from_nx(G)

# 调用自定义的弱联通分量计算
res = nx.weakly_connected_components(G2)
print(res)

# networkx原本的弱联通分量计算
res2 = list(nx.weakly_connected_components(G))
print(res2)