Capacitated Facility Location Problem
问题如下
给出所有工厂的容量和开工厂的成本,所有客户的需求,以及客户分配给某个工厂的的分配成本,要求解的问题是:找出一个分配方案,使得总成本最低。
实例数据下载地址:Download: p1-p71
算法思路
思路一:贪心
容易想到的是,从每个用户的角度出发,要使得总成本最小的话,则可以每个用户选择设施的时候都贪心选择一个成本最低的设施。一开始我想的是所有设施都先不开,然后由每个用户去贪心选择,计算选择一个设施需要的成本,如果设施还没开的话,则要加上开设施的成本,最后选择成本最低的那个。但后来仔细一想,其实这样是不太符合贪心策略的,因为用户肯定会倾向于选择已经开过的设施,这样用户就不能真正选择到分配成本更低的设施,所以不能充分利用到贪心的特点。所以不应该让设施的开与不开对选择造成太大的影响,一个简单的做法就是事先决定要开哪些设施,然后在开的设施里面贪心选择。我把所有工厂都开了,然后跑出来的效果确实比一开始的想法要好。
下面是python代码实现:
首先先建立好需要用到的类。
-
设施类:
class Facility: def __init__(self): self.capacity = 0 # 总容量 self.opening_cost = 0 # 开启成本 self.rest = 0 # 剩余容量
-
用户类
class Customer: def __init__(self): self.demand = 0 # 需求量 self.assign_cost = [] # 某设备分派给用户的成本
-
系统类
class System: def __init__(self, fnum, cnum): self.fnum = fnum # 设备数量 self.cnum = cnum # 用户数量 self.facilities = [] self.status = [0] * self.fnum # 工厂状态 self.customers = [] self.assignment = [0] * self.cnum # 每个用户分配到哪个设备 self.total_cost = 0 # 总成本 self.best_assignment = [] def show(self): print('result', self.total_cost) print('status', self.status) print('assignment:', self.assignment) ...
在系统类里面添加贪心算法:
# 贪心算法
def greed(self, status):
facilities = copy.deepcopy(self.facilities)
customers = copy.deepcopy(self.customers)
total_cost = 0
self.assignment = [-1] * self.cnum
for i in range(self.fnum): # 先计算开工厂的费用
if status[i] == 1:
total_cost += facilities[i].opening_cost
for i in range(self.cnum): # 为每个用户分配一个工厂
min_cost = 999999999
for j in range(self.fnum): # 从已开的工厂中选择有足够剩余量、且费用最小的
if status[j] == 1 and facilities[j].rest >= customers[i].demand:
cost = customers