网络流最大流分配(附python源码)
目錄
- 概念介紹
- 流(Flow)
- 網(wǎng)絡(luò)流(Network flow)
- 流網(wǎng)絡(luò)$(G,s,t,c)$
- 頂點𝒗的級𝒍𝒆𝒗𝒆𝒍(𝒗):
- 最大流最小割定理:
- 最大流求解
- Ford_Fullkerson方法
- 最大容量增廣(MCA,Maximum Capacity Augmentation)
- 最短路徑增廣(EK算法,Edmond-Karp)
- MCA和EK算法的實現(xiàn)
- 舉例
- 源碼
- 輸出參考
概念介紹
流(Flow)
一種抽象的實體,在源點流出,通過邊輸送,在匯點被吸收,將目標(biāo)從一個地點輸送到另一個地點。網(wǎng)絡(luò)流(Network flow)
在一個每條邊都有容量(Capacity)的有向圖分配流,使一條邊的流量不會超過它的容量。流網(wǎng)絡(luò)(G,s,t,c)(G,s,t,c)(G,s,t,c)
(𝑮,𝒔,𝒕,𝒄)
𝑮→圖(𝐺𝑟𝑜𝑢𝑝) 𝒔→源點(𝑆𝑜𝑢𝑟𝑐𝑒) t→匯點(𝑡𝑎𝑟𝑔𝑒𝑡) 𝒄→容量函數(shù)(𝑐𝑎𝑝𝑎𝑐𝑖𝑡𝑦)
流量函數(shù) f(u,v)f(u,v)f(u,v)
容量函數(shù) c(u,v)c(u,v)c(u,v)
剩余容量函數(shù) r(u,v)=c(u,v)?f(u,v)r(u,v)=c(u,v)-f(u,v)r(u,v)=c(u,v)?f(u,v)
對于流量函數(shù)f(u,v)f(u,v)f(u,v),滿足以下條件:
頂點𝒗的級𝒍𝒆𝒗𝒆𝒍(𝒗):
由源點𝑠到頂點𝑣的通路中的最少的邊數(shù)
分級圖𝑳為(𝑽,𝑬′),其中𝑬′={(𝒖,𝒗)|𝒍𝒆𝒗𝒆𝒍(𝒗)=𝒍𝒆𝒗𝒆𝒍(𝒖)+𝟏}
最大流最小割定理:
對流網(wǎng)絡(luò)(G,s,t,c)(G,s,t,c)(G,s,t,c),fff是GGG中的流,則下面的命題等價:
最大流求解
Ford_Fullkerson方法
根據(jù)最大流最小割定理,在尋找圖𝐺的最大流時,可以令𝐺的初始流量𝑓=0,然后重復(fù)地在𝑓的剩余圖中尋找一條增廣路徑,用該路徑的瓶頸流量來擴(kuò)張流量𝑓,直到剩余圖中不存在增廣路徑為止。
最大容量增廣(MCA,Maximum Capacity Augmentation)
根據(jù)Ford-Fullkerson方法求解最大流問題,不同點在于指定了增廣路徑的選取方法:搜索一條具有最大瓶頸容量的增廣路徑來加快算法運行時間(貪婪算法)。
步驟:
最短路徑增廣(EK算法,Edmond-Karp)
根據(jù)Ford-Fullkerson方法求解最大流問題,不同點在于指定了增廣路徑的選取方法:搜索一條具有最短路徑(邊最少)的增廣路徑來加快算法運行時間。
步驟:
MCA和EK算法的實現(xiàn)
舉例
c(u,v)c(u,v)c(u,v)
源碼
# -*- coding: utf-8 -*- # Copyright (c) 2019 - Youpeng Hu <yoooooohu@foxmail.com> import copyclass Weighted_Gragh:def __init__(self, vertices):self.adjacent_table = {}for vertex in vertices:self.adjacent_table.update({vertex: {}})print("Weighted Gragh has been created Successfully!!!!!") print('self.adjacent_table', end=" -> \n")print(self.adjacent_table)def addNeighbor(self, source, terminal, weigh):neighbor_list = self.adjacent_table[source]neighbor_list.update({terminal: weigh})self.adjacent_table.update({source: neighbor_list})print('Add a new Neighbor\nself.adjacent_table', end=" -> \n")print(self.adjacent_table)def maxCapacityAugmentation(self, source, terminal):print('###################################')print('Max Capacity Augmentation algorithm')self.f_table = {}self.r_table = copy.deepcopy(self.adjacent_table)path = self.findMaxBottleneckDFS(source, terminal, 0, {}) while path:print('path', end=" >>>>>>>>>>>>>>\n")print(path)bottleneck = self.foundBottleneck(path, terminal)self.argumentFlow(bottleneck, path, terminal)path = self.findMaxBottleneckDFS(source, terminal, 0, {})return self.f_tabledef findMaxBottleneckDFS(self, source, terminal, level, level_table, max_bottleneck = 1000):print('(source, terminal, max_bottleneck)', end=" ->\n")print((source, terminal, max_bottleneck))level += 1for end, weight in self.r_table[source].items():if weight > 0:if level not in level_table:level_table[level] = {}if end not in level_table[level]:level_table[level][end] = {} level_table[level][end] = {source: weight}if end == terminal:return level_tableif weight >= max_bottleneck:return self.findMaxBottleneckDFS(end, terminal, level, level_table, max_bottleneck = max_bottleneck)elif weight < max_bottleneck:return self.findMaxBottleneckDFS(end, terminal, level, level_table, max_bottleneck = weight)elif weight < 0:raise ("the value of weigh have some problem")def edmondKarp(self, source, terminal):print('###################################')print('edmondKarp algorithm')self.f_table = {}self.r_table = copy.deepcopy(self.adjacent_table)path = self.findTerminalBFS([source], terminal, 0, {}, [source]) while path:print('argument table', end=" >>>>>>>>>>>>>>\n")print(path)bottleneck = self.foundBottleneck(path, terminal)self.argumentFlow(bottleneck, path, terminal)path = self.findTerminalBFS([source], terminal, 0, {}, [source])return self.f_tabledef findTerminalBFS(self, start_list, terminal, level, level_table, visited):print('(start_list, terminal, level, level_table, visited)', end=" ->\n")print((start_list, terminal, level, level_table, visited))level += 1end_list = []for start in start_list:for end, weight in self.r_table[start].items():if (weight > 0) & (end not in visited):if level not in level_table:level_table[level] = {}if end not in level_table[level]:level_table[level][end] = {}level_table[level][end] = {start: weight}if terminal == end:return level_tablevisited.append(end)end_list.append(end)elif weight < 0:raise ("the value of weight have some problem")if end_list:return self.findTerminalBFS(end_list, terminal, level, level_table, visited)def foundBottleneck(self, path, terminal):weight_list = []tmp_level = max(path.keys())print('tmp_level', end =" ->")print(tmp_level)start = terminalwhile tmp_level > 0:for start, weight in path[tmp_level][start].items():passtmp_level -= 1weight_list.append(weight) print('Bottleneck of traffic -> {}'.format(min(weight_list)))return min(weight_list)def argumentFlow(self, bottleneck, path, terminal):tmp_level = max(path.keys())end = terminalprint('path:\n', terminal, end="")while tmp_level > 0:for start, weight in path[tmp_level][end].items():passprint("->", start, weight, end="")if start not in self.f_table:self.f_table[start] = {} if end not in self.f_table[start]:self.f_table[start][end] = 0 self.f_table[start][end] += bottleneckself.r_table[start][end] -= bottlenecktmp_level -= 1end = startprint() print('self.r_table', end=" ->\n")print(self.r_table)print('self.f_table', end=" ->\n")print(self.f_table) if __name__ == '__main__':gragh = Weighted_Gragh(['s','a','b','c','d','e','f','g','h','i','j','t'])gragh.addNeighbor('s', 'a', 6)gragh.addNeighbor('s', 'c', 8)gragh.addNeighbor('a', 'b', 3)gragh.addNeighbor('a', 'd', 3)gragh.addNeighbor('b', 't', 10)gragh.addNeighbor('c', 'd', 4)gragh.addNeighbor('c', 'f', 4)gragh.addNeighbor('d', 'e', 3)gragh.addNeighbor('d', 'g', 6)gragh.addNeighbor('e', 'b', 7)gragh.addNeighbor('e', 'j', 4)gragh.addNeighbor('f', 'h', 4)gragh.addNeighbor('g', 'e', 7)gragh.addNeighbor('h', 'g', 1)gragh.addNeighbor('h', 'i', 3)gragh.addNeighbor('i', 'j', 3)gragh.addNeighbor('j', 't', 5)gragh.edmondKarp('s', 't')print('gragh.f_table for Edmond_Karp', end="->>>>>>>>>>>>>>>>>>>>>>>>>>>\n")print(gragh.f_table)print('gragh.r_table for Edmond_Karp', end="->>>>>>>>>>>>>>>>>>>>>>>>>>>\n")print(gragh.r_table) gragh.maxCapacityAugmentation('s', 't')print('gragh.f_table for maxCapacityAugmentation', end="->>>>>>>>>>>>>>>>>>>>>>>>>>>\n")print(gragh.f_table)print('gragh.r_table for maxCapacityAugmentation', end="->>>>>>>>>>>>>>>>>>>>>>>>>>>\n")print(gragh.r_table)輸出參考
無論對于MCA或EK算法,輸出的r_table
gragh.r_table {'s': {'a': 0, 'c': 0}, 'a': {'b': 0, 'd': 0}, 'b': {'t': 0}, 'c': {'d': 0, 'f': 0}, 'd': {'e': 0, 'g': 2}, 'e': {'b': 0, 'j': 3}, 'f': {'h': 0}, 'g': {'e': 2}, 'h': {'g': 0, 'i': 0}, 'i': {'j': 0}, 'j': {'t': 1}, 't': {} }最大流fmax(u,v)f_{max}(u,v)fmax?(u,v)
edited date: 2019-11-15
總結(jié)
以上是生活随笔為你收集整理的网络流最大流分配(附python源码)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JS_15作用域与作用域链
- 下一篇: websocket python爬虫_p