1. 问题描述
给定n个工厂和m个顾客,开工厂需要一定的费用,一个工厂有一定的容量限制,每个顾客也有一定的需求,而每个顾客要选取某个工厂也需要一定的分配费用,现在要求找出一个分配方案,把顾客分配给不同的工厂,然后在可以满足所有顾客需求的前提下让所有的花费(开工厂的花费和分配的花费)最小。
问题分析:
2. 解决思路
设集合 I = { 1, … , m } 是所有Facilities
集合 J = { 1, …, n } 是所有Customers
对于每个Customer 都有一个 demand, ,只能被一个facility提供
对于每个Facility 都有一个 capacity, ,是该facility最多能提供的容量
对于每个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 |