Python 约束网络最大流

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

很久以前,我根据一篇我再也找不到的学术论文中描述的算法编写了下面的Python模块(非常抱歉没有学分、引用等,但我忘了在脚本注释中提到源代码)

基本上,它允许通过使用基于Edmonds-Karp算法的最大流方法,仅知道其边缘(行和列总和)和链路存在的概率(该部分似乎仅部分实现,如果根本没有实现的话)来重建二部网络:

# 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)