【问题标题】:Is it possible to avoid return edges of igraph in a vectorized way?是否可以以矢量化方式避免 igraph 的返回边缘?
【发布时间】:2020-02-10 10:03:20
【问题描述】:

所以我正在以基本方式创建我的图表:

import igraph
import numpy as np
graph = igraph.Graph()
graph.add_vertices(np.array([0,1,2,3,4,5]))
graph.add_edges(np.array([[0,1],[1,2],[3,4],[4,5],[3,5]]))

我想知道是否可以加快将我的图形边缘转换为numpy 数组的速度?我现在正在这样做:

print(np.array([n.tuple for n in graph.es])) # prints array [[0,1],[1,2],[3,4],[4,5],[3,5]]

【问题讨论】:

  • python和numpy哪个版本?
  • 最新版本之一,Python 3.7 和numpy 1.17
  • 为什么要将列表转换为numpy 数组? igraph 不能与 numpy 一起使用,因此在传递给 add_edges 之前对其进行转换应该没有性能优势。
  • 我想知道,为什么有 3-5 而不是 1-4(仅作为一个例子)?
  • @kabanus 奇怪的问题。我只是想让我的图表不连接

标签: python numpy igraph


【解决方案1】:

将所有边转换为numpy 数组的最简单也是最快的方法如下:

edges = np.array(graph.get_edgelist())

对于具有n=1000 节点和m=5000 边的随机图,在

2.74 ms ± 561 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

在我的机器上。 的替代品

edges = np.array([n.tuple for n in graph.es])

运行速度慢了近 30%,并且需要

3.53 ms ± 542 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

在我的机器上。

【讨论】:

  • 这正是我一直在寻找的。谢谢!
  • 我不知道你到底需要什么,但请注意igraph 还具有分解连接组件中的图形的功能。 python-igraph 的最新更新,版本 0.8.0 即将发布,并且已经可以从 PyPi 下载,包括 Windows 二进制轮子。
  • 我明白了。我很高兴,因为我今天刚刚测试了它并且它对我有用,不需要来自非官方二进制文件的轮子。这也是我第一次测试decompose
【解决方案2】:

经过长时间的了解,我决定比较几种方法,获胜者是:

np.fromiter(chain(*g.get_edgelist()), np.dtype('i'), count=g.ecount()).reshape(-1, 2)

它比4x 快​​超过np.array(g.get_edgelist()) 倍!所以这里不能忽略结构化输出数组的重要性。

def edges_asarray1(g):
    return np.array(g.get_edgelist())

def edges_asarray2(g):
    return np.array([n.tuple for n in g.es])

def edges_fromiter1A(g):
    dt = np.dtype([('', np.intp)]*2)
    indices = np.fromiter(g.get_edgelist(), dt)
    indices = indices.view(np.intp).reshape(-1, 2)
    return indices

def edges_fromiter1B(g):
    index = np.fromiter(chain(*g.get_edgelist()), np.dtype('i'), count=2*g.ecount())
    return index.reshape(-1, 2)
fig = plt.figure(figsize=(10, 10))

def edges_fromiter2A(g):
    dt = np.dtype([('', np.intp)]*2)
    indices = np.fromiter(map(lambda x: x.tuple, g.es), dt)
    indices = indices.view(np.intp).reshape(-1, 2)
    return indices

def edges_fromiter2B(g):
    index = np.fromiter(chain(*map(lambda x: x.tuple, g.es)), np.dtype('i'), count=2*g.ecount())
    return index.reshape(-1, 2)

plt.grid(True, which="both")
out = perfplot.bench(
        setup = lambda x: ig.Graph.Erdos_Renyi(n=x, m=5*x),
        kernels = [edges_asarray1, edges_asarray2, edges_fromiter1A, edges_fromiter1B, edges_fromiter2A, edges_fromiter2B],
        n_range = [2 ** k for k in range(4, 21)],
        xlabel = 'n',
        title = 'testing graph with n nodes and 5*n edges',
        show_progress = True)
out.show()

【讨论】:

    猜你喜欢
    • 2021-12-15
    • 1970-01-01
    • 2011-05-24
    • 2021-02-14
    • 2022-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多