Capacitated Facility Location Problem貪心演算法實現
阿新 • • 發佈:2018-12-30
1. 問題描述
給定n個工廠和m個顧客,開工廠需要一定的費用,一個工廠有一定的容量限制,每個顧客也有一定的需求,而每個顧客要選取某個工廠也需要一定的分配費用,現在要求找出一個分配方案,把顧客分配給不同的工廠,然後在可以滿足所有顧客需求的前提下讓所有的花費(開工廠的花費和分配的花費)最小。
問題分析:
2. 解決思路
設集合 I = { 1, … , m } 是所有Facilities
集合 J = { 1, …, n } 是所有Customers
對於每個Customer 都有一個 demand, ,只能被一個facility提供
對於每個Facility 都有一個 capacity,
對於每個Facility 都有一個 fixed cost, ,當該facility開啟的時候固定的開銷
定義 是facility j 滿足 customer i 的要求的開銷
對於每個facility i ∈ I ,定義變數
對於每個facility i ∈ I ,每個customer j ∈J, 定義變數
對於Single Source Capacitated Facility Location Problemk可以描述為如下
因為customer一般都比facility多,所以只關注customer的cost,可以制定出如下策略:
1. 遍歷所有customer,對於每一個customer,將該customer安排到所有facility的cost進行從小到大排序
2.對排序好的cost進行遍歷,假如該facility剩餘的容量滿足customer的要求,則將該customer安排到該facility
3. 程式碼實現
import random import math import matplotlib.pyplot as plt CAPACITY = [] OPENCOST = [] ASSIGNCOST = [] OPENSTATUS = [] DEMAND = [] FACNUM = 0 CUSNUM = 0 Num = 0 #讀取檔案,獲取各項變數 def init(filepath): with open(filepath, 'r') as f: global FACNUM global CUSNUM global CAPACITY global OPENCOST global ASSIGNCOST global OPENSTATUS FACNUM, CUSNUM = f.readline().strip("\n").split() FACNUM = int(FACNUM) CUSNUM = int(CUSNUM) OPENSTATUS = [0] * FACNUM for i in range(FACNUM): line = f.readline().strip("\n").split() CAPACITY.append(int(line[0])) OPENCOST.append(int(line[1])) for i in range(int(CUSNUM / 10)): line = f.readline().strip("\n").replace(' ', '').split(".") for j in range(10): DEMAND.append(int(line[j])) for i in range(CUSNUM): linetoread = int(FACNUM / 10) temp = [] for j in range(linetoread): line = f.readline().strip("\n").replace(' ', '').split(".") for k in range(10): temp.append(int(line[k])) ASSIGNCOST.append(temp) print(ASSIGNCOST) def greedy(): global CAPACITY capacity = CAPACITY.copy() openstatus = [0] * FACNUM totalcost = 0 assign = [-1] * CUSNUM assigncost = 0 opencost = 0 for cus in range(CUSNUM): facIndex = [] # the facilities may be chosen for i in range(FACNUM): if capacity[i] >= DEMAND[cus]: facIndex.append(i) # ASSIGNCOST for customer i asforeach = ASSIGNCOST[cus] # ASSIGNCOST + OPENCOST for customer i temp = [sum(x) for x in zip(asforeach, OPENCOST)] # select the min cost index sindex = facIndex[0] for i in facIndex: if temp[i] < temp[sindex]: sindex = i openstatus[sindex] = 1 capacity[sindex] = capacity[sindex] - DEMAND[cus] assign[cus] = sindex assigncost += asforeach[sindex] for i in range(FACNUM): opencost += openstatus[i] * OPENCOST[i] totalcost = assigncost + opencost print(assign) print("assignment cost: %d"%assigncost) print("opencost: %d"%opencost) print(totalcost) print("openstatus: {}".format(openstatus)) return assign
執行結果
Result | Time(s) | |
---|---|---|
p1 | 9440 | 0.000475 |
p2 | 8126 | 0.000641 |
p3 | 10126 | 0.000518 |
p4 | 12126 | 0.000599 |
p5 | 9375 | 0.000423 |
p6 | 8061 | 0.00029 |
p7 | 10061 | 0.001217 |
p8 | 12061 | 0.000298 |
p9 | 9040 | 0.000337 |
p10 | 7726 | 0.000411 |
p11 | 9726 | 0.000441 |
p12 | 11726 | 0.000364 |
p13 | 12032 | 0.001095 |
p14 | 9180 | 0.00073 |
p15 | 13180 | 0.000643 |
p16 | 17180 | 0.000682 |
p17 | 12032 | 0.000952 |
p18 | 9180 | 0.00051 |
p19 | 13180 | 0.000724 |
p20 | 17180 | 0.001145 |
p21 | 12032 | 0.001239 |
p22 | 9180 | 0.000643 |
p23 | 13180 | 0.000572 |
p24 | 17180 | 0.000571 |
p25 | 18753 | 0.003807 |
p26 | 15831 | 0.003425 |
p27 | 21031 | 0.002265 |
p28 | 26231 | 0.002439 |
p29 | 20007 | 0.002902 |
p30 | 16812 | 0.003054 |
p31 | 22212 | 0.00184 |
p32 | 27612 | 0.004533 |
p33 | 18611 | 0.002598 |
p34 | 15689 | 0.002882 |
p35 | 20889 | 0.003181 |
p36 | 26089 | 0.002619 |
p37 | 18611 | 0.004204 |
p38 | 15689 | 0.003696 |
p39 | 20889 | 0.00272 |
p40 | 26089 | 0.002611 |
p41 | 7226 | 0.000569 |
p42 | 9957 | 0.001687 |
p43 | 12448 | 0.001289 |
p44 | 7585 | 0.000704 |
p45 | 9848 | 0.000852 |
p46 | 12639 | 0.001293 |
p47 | 6634 | 0.000446 |
p48 | 9044 | 0.000963 |
p49 | 12867 | 0.001634 |
p50 | 10062 | 0.000485 |
p51 | 11175 | 0.000991 |
p52 | 10364 | 0.000545 |
p53 | 12876 | 0.001308 |
p54 | 10351 | 0.000907 |
p55 | 12383 | 0.001636 |
p56 | 23882 | 0.003144 |
p57 | 32882 | 0.004378 |
p58 | 53882 | 0.004073 |
p59 | 39121 | 0.003088 |
p60 | 23882 | 0.00407 |
p61 | 32882 | 0.003173 |
p62 | 53882 | 0.004647 |
p63 | 39121 | 0.003963 |
p64 | 23882 | 0.004642 |
p65 | 32882 | 0.002274 |
p66 | 53882 | 0.003318 |
p67 | 39671 | 0.005819 |
p68 | 23882 | 0.003292 |
p69 | 32882 | 0.003722 |
p70 | 53882 | 0.003989 |
p71 | 39121 | 0.00351 |