日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

网络流最大流分配(附python源码)

發(fā)布時間:2023/12/20 python 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络流最大流分配(附python源码) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

  • 概念介紹
    • 流(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),滿足以下條件:

  • 斜對稱: f(u,v)=?f(v,u)f(u,v)=-f(v,u)f(u,v)=?f(v,u)
  • 容量約束: f(u,v)=f(u,v)f(u,v)=f(u,v)f(u,v)=f(u,v)
  • 流量守恒: ?u∈V?s,t,∑v∈Vf(u,v)=0?u \in V-{s,t}, \sum_{v \in V}{f(u,v)=0}?uV?s,t,vV?f(u,v)=0
  • 零自流量: f(u,u)=0f(u,u)=0f(u,u)=0
  • 頂點𝒗的級𝒍𝒆𝒗𝒆𝒍(𝒗):

    由源點𝑠到頂點𝑣的通路中的最少的邊數(shù)

    分級圖𝑳為(𝑽,𝑬′),其中𝑬′={(𝒖,𝒗)|𝒍𝒆𝒗𝒆𝒍(𝒗)=𝒍𝒆𝒗𝒆𝒍(𝒖)+𝟏}

    最大流最小割定理:

    對流網(wǎng)絡(luò)(G,s,t,c)(G,s,t,c)(G,s,t,c)fffGGG中的流,則下面的命題等價:

  • 存在一個容量為c(u,v)=∣f∣c(u,v)=|f|c(u,v)=f的割集S,T{S,T}S,T;
  • fffGGG中的最大流;
  • 不存在fff的增廣路徑。
  • 最大流求解

    Ford_Fullkerson方法

    根據(jù)最大流最小割定理,在尋找圖𝐺的最大流時,可以令𝐺的初始流量𝑓=0,然后重復(fù)地在𝑓的剩余圖中尋找一條增廣路徑,用該路徑的瓶頸流量來擴(kuò)張流量𝑓,直到剩余圖中不存在增廣路徑為止。

    最大容量增廣(MCA,Maximum Capacity Augmentation)

    根據(jù)Ford-Fullkerson方法求解最大流問題,不同點在于指定了增廣路徑的選取方法:搜索一條具有最大瓶頸容量的增廣路徑來加快算法運行時間(貪婪算法)。

    步驟:

  • 對所有(u,v)∈E(u,v) \in E(u,v)E, r(u,v)=c(u,v)r(u,v)=c(u,v)r(u,v)=c(u,v);
  • 對所有(u,v)∈E(u,v) \in E(u,v)E, f(u,v)=0f(u,v)=0f(u,v)=0;
  • 若剩余圖𝑅中存在增廣路徑,找出使得瓶頸流量𝛿最大的增廣路徑𝑝,轉(zhuǎn)4;不存在轉(zhuǎn)6;
  • 對所有增廣路徑ppp上的邊(u,v)∈p(u,v) \in p(u,v)p,令 r(u,v)=r(u,v)?Δr(u,v)=r(u,v)-\Deltar(u,v)=r(u,v)?Δ
  • 對所有增廣路徑ppp上的邊(u,v)∈p(u,v) \in p(u,v)p,令 f(u,v)=f(u,v)+Δf(u,v)=f(u,v)+\Deltaf(u,v)=f(u,v)+Δ,轉(zhuǎn)3;
  • 返回最大流fff
  • 最短路徑增廣(EK算法,Edmond-Karp)

    根據(jù)Ford-Fullkerson方法求解最大流問題,不同點在于指定了增廣路徑的選取方法:搜索一條具有最短路徑(邊最少)的增廣路徑來加快算法運行時間。

    步驟:

  • 對所有(u,v)∈E(u,v) \in E(u,v)E, r(u,v)=c(u,v)r(u,v)=c(u,v)r(u,v)=c(u,v);
  • 對所有(u,v)∈E(u,v) \in E(u,v)E, f(u,v)=0f(u,v)=0f(u,v)=0;
  • 按照分級圖原理,用BFS在剩余圖中搜索由𝑠到𝑡的最短路徑𝑝,轉(zhuǎn)4;不存在轉(zhuǎn)6;
  • 對所有增廣路徑ppp上的邊(u,v)∈p(u,v) \in p(u,v)p,令 r(u,v)=r(u,v)?Δr(u,v)=r(u,v)-\Deltar(u,v)=r(u,v)?Δ
  • 對所有增廣路徑ppp上的邊(u,v)∈p(u,v) \in p(u,v)p,令 f(u,v)=f(u,v)+Δf(u,v)=f(u,v)+\Deltaf(u,v)=f(u,v)+Δ,轉(zhuǎn)3;
  • 返回最大流fff
  • 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)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。