SciPy,从 1.4.0 开始,在 scipy.sparse.csgraph.maximum_flow 中也有一个实现,它可能更容易用作构建链的一部分(因为该包可通过 pip/conda 获得)。
它通过操纵表示图的邻接矩阵的稀疏矩阵(因此scipy.sparse)工作,因此,底层数据结构接近金属,并且算法本身在 Cython 中实现,性能应该是与例如图形工具。
不同实现在性能方面的比较始终取决于您感兴趣的最大流量图的结构,但作为一个简单的基准测试,我尝试通过 NetworkX、graph-tool 运行具有不同稀疏度的随机图,和 SciPy。它们都可以很好地使用 NumPy 数组,因此为了确保公平竞争,让我们创建方法,以便它们中的每一个都将具有形状 (密度*1000*1000, 3) 的 NumPy 数组作为输入,其行是边,其列是入射到给定边的两个顶点,以及边的容量。
import numpy as np
from scipy.sparse import rand
def make_data(density):
m = (rand(1000, 1000, density=density, format='coo', random_state=42)*100).astype(np.int32)
return np.vstack([m.row, m.col, m.data]).T
data01 = make_data(0.1)
data03 = make_data(0.3)
data05 = make_data(0.5)
有了这个,各种框架可以计算出最大流量的值如下:
import graph_tool.all as gt
from scipy.sparse import coo_matrix, csr_matrix
from scipy.sparse.csgraph import maximum_flow
import networkx as nx
def networkx_max_flow(data, primitive):
m = coo_matrix((data[:, 2], (data[:, 0], data[:, 1])))
G = nx.from_numpy_array(m.toarray(), create_using=nx.DiGraph())
return nx.maximum_flow_value(G, 0, 999, capacity='weight', flow_func=primitive)
def graph_tool_max_flow(data, primitive):
g = gt.Graph()
cap = g.new_edge_property('int')
eprops = [cap]
g.add_edge_list(data, eprops=eprops)
src, tgt = g.vertex(0), g.vertex(999)
res = primitive(g, src, tgt, cap)
res.a = cap.a - res.a
return sum(res[e] for e in tgt.in_edges())
def scipy_max_flow(data):
m = csr_matrix((data[:, 2], (data[:, 0], data[:, 1])))
return maximum_flow(m, 0, 999).flow_value
这样,IPython 基准测试的例子就变成了
%timeit networkx_max_flow(data01, nx.algorithms.flow.shortest_augmenting_path)
%timeit graph_tool_max_flow(data03, gt.push_relabel_max_flow)
%timeit scipy_max_flow(data05)
然后我看到以下结果:
+----------------------------------------------+----------------+----------------+---------------+
| Algorithm | Density: 0.1 | Density: 0.3 | Density: 0.5 |
+----------------------------------------------+----------------+----------------+---------------+
| nx.algorithms.flow.edmonds_karp | 1.07s | 3.2s | 6.39s |
| nx.algorithms.flow.preflow_push | 1.07s | 3.27s | 6.18s |
| nx.algorithms.flow.shortest_augmenting_path | 1.08s | 3.25s | 6.23s |
| gt.edmonds_karp_max_flow | 274ms | 2.84s | 10s |
| gt.push_relabel_max_flow | 71ms | 466ms | 1.42s |
| gt.boykov_kolmogorov_max_flow | 79ms | 463ms | 895ms |
| scipy.sparse.csgraph.maximum_flow | 64ms | 234ms | 580ms |
+----------------------------------------------+----------------+----------------+---------------+
同样,结果将取决于图形结构,但这至少表明 SciPy 应该为您提供与图形工具相当的性能。