Python 约束网络最大流
很久以前,我根据一篇我再也找不到的学术论文中描述的算法编写了下面的Python模块(非常抱歉没有学分、引用等,但我忘了在脚本注释中提到源代码) 基本上,它允许通过使用基于Edmonds-Karp算法的最大流方法,仅知道其边缘(行和列总和)和链路存在的概率(该部分似乎仅部分实现,如果根本没有实现的话)来重建二部网络:Python 约束网络最大流,python,numpy,networkx,directed-graph,bipartite,Python,Numpy,Networkx,Directed Graph,Bipartite,很久以前,我根据一篇我再也找不到的学术论文中描述的算法编写了下面的Python模块(非常抱歉没有学分、引用等,但我忘了在脚本注释中提到源代码) 基本上,它允许通过使用基于Edmonds-Karp算法的最大流方法,仅知道其边缘(行和列总和)和链路存在的概率(该部分似乎仅部分实现,如果根本没有实现的话)来重建二部网络: # IMPORTS import numpy as np from heapq import ( heappop, heappush ) # CLASSES
# IMPORTS
import numpy as np
from heapq import (
heappop,
heappush
)
# CLASSES
class HeapPair:
def __init__(self, v1, v2):
self.v1 = v1
self.v2 = v2
def __iter__(self):
yield from [self.v1, self.v2]
def __lt__(self, other):
if self.v1 != other.v1:
return self.v1 > other.v1
return self.v2 > other.v2
def __repr__(self):
return 'HeapPair'
def __str__(self):
return str(f'({self.v1}, {self.v2})')
# FUNCTIONS
def max_flow_matrix(size: int, rows: np.ndarray, columns: np.ndarray, probabilities: np.ndarray) -> np.ndarray:
s = 0
t = (size * 2) + 1
vertices = (size * 2) + 2
e = np.zeros((vertices, size), dtype=int)
capacity = np.zeros((vertices, vertices), dtype=float)
flow = np.zeros((vertices, vertices), dtype=float)
for i in range(size):
e[s, i] = i + 1
e[t, i] = size + i + 1
e[size + i + 1, 0] = t
capacity[s, i + 1] = rows[i]
capacity[size + i + 1, t] = columns[i]
offsets = {i + 1: 1 for i in range(size * 2)}
for i in range(size):
for j in range(size):
if probabilities[i, j] > 0.0:
a = i + 1
b = size + j + 1
e[a, offsets[a]] = b
e[b, offsets[b]] = a
capacity[a, b] = np.Inf
offsets[a] += 1
offsets[b] += 1
while True:
colour = np.zeros(vertices, dtype=int)
colour[s] = 1
d = np.repeat(2 * vertices, vertices)
d[s] = 0
pred = np.repeat(-1, vertices)
Q = [HeapPair(0, s)]
while (len(Q) > 0) and (colour[t] == 0):
q, u = heappop(Q)
if colour[u] == 1:
colour[u] = 2
for v in e[u]:
if (colour[v] == 0) and (capacity[u, v] > (flow[u, v] - flow[v, u] + 1e-8):
colour[v] = 1
pred[v] = u
d[v] = d[u] + 1
heappush(Q, HeapPair(-d[v], v))
if v == t:
break
if (v > 1 + size) and (capacity[v, t] > (flow[v, t] - flow[t, v] + 1e-8):
colour[t] = 1
pred[t] = v
d[t] = d[v] + 1
break
if colour[t] == 0:
break
pos = t
flow_new = capacity[pred[pos], pos] - flow[pred[pos], pos] + flow[pos, pred[pos]]
pos = pred[pos]
while pos != s:
fmax = capacity[pred[pos], pos] - flow[pred[pos], pos] + flow[pos, pred[pos]]
if fmax < flow_new:
flow_new = fmax
pos = pred[pos]
pos = t
while pos != s:
flow[pred[pos], pos] += flow_new
pos = pred[pos]
res = np.zeros((size, size), dtype=float)
for i in range(size):
for j in range(size):
res[i, j] = flow[i + 1, size + j + 1] - flow[size + j + 1, i + 1]
return res
最近,我开始使用,因为它包含了Edmonds Karp最大流(文档)的实现,我想知道是否可以使用它获得相同的结果。这就是我迄今为止所尝试的:
import numpy as np
import networkx as nx
size = 4
r = np.array([3.0, 0.0, 1.0, 2.0])
c = np.array([2.0, 1.0, 1.0, 2.0])
p = 0.5 * _np.ones((size, size), dtype=float)
np.fill_diagonal(p, 0.0)
G = nx.DiGraph()
for n in ['source', 0, 1, 2, 3, 4, 5, 6]:
G.add_node(n, bipartite=0)
for n in [7, 8, 9, 10, 11, 12, 13, 'sink']:
G.add_node(n, bipartite=1)
for i in range(size):
G.add_edge('source', i, capacity=r[i])
G.add_edge(i + size, 'sink', capacity=c[i])
for i in range(size):
for j in range(size):
if probabilities[i, j] > 0.0:
G.add_edge(i, i + size)
R, flow_dict = nx.algorithms.flow.maximum_flow(G, 'source', 'sink', flow_func=nx.algorithms.flow.edmonds_karp)
我的发展在那里停止了。我对NetworkX这个领域的了解有点有限。我认为变量
flow\u dict
包含了我正在寻找的内容,但老实说,我不知道问题是否已正确表述,以及如何根据流数据重新组装最终网络。概率是如何考虑的?您是否试图最大化最终拾取的边的所有概率之和?如果是,则这是最小成本最大流量的实例(在NetworkX中可用为max\u flow\u min\u cost
)。概率是如何考虑的?您是否试图最大化最终拾取的边的所有概率之和?如果是,则这是最小成本最大流量的实例(在NetworkX中可用为max\u flow\u min\u cost
)。
import numpy as np
import networkx as nx
size = 4
r = np.array([3.0, 0.0, 1.0, 2.0])
c = np.array([2.0, 1.0, 1.0, 2.0])
p = 0.5 * _np.ones((size, size), dtype=float)
np.fill_diagonal(p, 0.0)
G = nx.DiGraph()
for n in ['source', 0, 1, 2, 3, 4, 5, 6]:
G.add_node(n, bipartite=0)
for n in [7, 8, 9, 10, 11, 12, 13, 'sink']:
G.add_node(n, bipartite=1)
for i in range(size):
G.add_edge('source', i, capacity=r[i])
G.add_edge(i + size, 'sink', capacity=c[i])
for i in range(size):
for j in range(size):
if probabilities[i, j] > 0.0:
G.add_edge(i, i + size)
R, flow_dict = nx.algorithms.flow.maximum_flow(G, 'source', 'sink', flow_func=nx.algorithms.flow.edmonds_karp)