基于贪心策略、邻域搜索和遗传算法的设施分配优化问题
算法概论期末项目
文章目录
摘要
使用贪心算法、邻域搜索(不同邻域方法)和遗传算法(不同选择、变异、交叉方法),解决设施分配优化问题
1. 导言
问题重述
有一些设施,每个设施有不同的承载量,设施承载不能超过这个值
有一些顾客,每个顾客有不同的需求量
没有顾客使用的设施,不需要启动,无需维护费,否则需要维护费
把一名顾客,分配到一台设施,需要一定的调度费
尝试找到一种方案,分配每一个顾客一个设施,使总体费用尽可能最优
贪心算法
该算法不断生成随机解,并与现有最优解进行比较,如果随机解更好就替换之
邻域搜索
该算法从一个初始解出发,通过邻域函数生成解的邻域,再在邻域中 搜索出更优的解来替换当前解,通过不断的迭代过程实现解
遗传算法
该算法模拟生物遗传进化的特点,对问题进行编码,进行选择、交叉、变异操作,不断迭代寻找更优解
2. 实验过程
问题编码
我采用整数编码,即一个解是一个长度为顾客数的数组,对应顾客的数组元素就是该顾客被分配的设施
这样编码可以方便后面的邻域、变异、交叉操作
代价函数
根据题目的定义定义代价函数,即设施开放代价和用户调度代价的总和
特别地,如果一个解使一个设施超出承载量,则它的代价为最大值(MAX_NUM
)
计算代价
def get_cost(assign):
if not is_assign_valid(assign):
return MAX_NUM
cost = 0
fset = set()
for i in range(customer_num):
fset.add(assign[i])
cost += allocating_cost[assign[i]][i]
for i in range(facility_num):
if i in fset:
cost += facility_cost[i]
return cost
判断解是否合法:
def is_assign_valid(assign):
real_facility_capacity = [0] * facility_num
for i in range(customer_num):
real_facility_capacity[assign[i]] += customer_demand[i]
for i in range(facility_num):
if real_facility_capacity[i] > facility_capacity[i]:
return False
return True
数据读入
数据71个样例,三种格式,需要处理,使批处理得以运行
def get_data(index):
global facility_num
global customer_num
global facility_capacity
global facility_cost
global allocating_cost
global customer_demand
with open('Instances/p' + str(index), 'r')as f:
lines = f.read()
arr = lines.replace('.', ' ').replace(chr(0), '').replace('\n', ' ').split()
for i in range(len(arr)):
arr[i] = int(arr[i])
facility_num, customer_num = arr[0], arr[1]
facility_capacity, facility_cost = [], []
ind = 2
for i in range(facility_num):
facility_capacity.append(arr[ind])
facility_cost.append(arr[ind + 1])
ind += 2
customer_demand = []
for i in range(customer_num):
customer_demand.append(arr[ind])
ind += 1
# ac[f, c]
allocating_cost = []
for i in range(facility_num