单向:纯取货/纯送货;
单配送中心:只有一个配送中心/车场;
单车型:只考虑一种车型,
需求不可拆分:客户需求只能有一辆车满足;
车辆封闭:完成配送任务的车辆需回到配送中心;
车辆充足:不限制车辆数量,即配送车辆需求均能满足;
非满载:任意客户点的需求量小于车辆最大载重;
优化目标:最小化车辆启动成本和车辆行驶成本之和;
约束条件:车辆行驶距离约束,重量约束;
已知信息:配送中心位置、客户点位置、客户点需求、车辆最大载重、车辆最大行驶距离、车辆启动成本、车辆单位距离行驶成本;
车辆启动成本 C0 =30,车辆单位距离行驶成本C1 =1
详见problem.py
同TSP问题生成方式,以客户点(编号为1,2,3…)为自然数编码(不包含配送中心0)
解码:考虑车辆载重和行驶距离约束的8客户点染色体[8,4,1,5,2,3,6,7]解码为
【0,8,4,1,0】
【0,5,2,0】
【0,3,6,7,0】
采用两点交叉、和2-opt变异
下载连接:https://download.csdn.net/download/qq_43276566/87554423(无需积分)
分为四个模块,populatioin.py、algorithm.py,problem.py 和程序运行接口run-cvrp.py
algorithm.py如下:
import datetime
import heapq
import time
import numpy as np
from matplotlib import pyplot as plt
import 路径优化.CVRP.problem as problem
from 路径优化.CVRP.population import Population
class Algorithm:
def __init__(self, problem: problem.CVRP):
self.problem = problem
np.random.seed(47)
self.currentGen = 0
self.MAXGEN = 10000
self.trace = {"obj": [], "solution": []}
pass
def mutation(self, pop):
for i in range(10, 100):
r1, r2 = np.random.randint(low=0, high=len(pop.chromMatrix[0]), size=2)
chrom = pop.chromMatrix[i]
chrom[r1], chrom[r2] = chrom[r2], chrom[r1]
pass
def crossover(self):
pass
def selection(self, pop: Population):
off = Population(self.problem)
fitV = pop.fitV
if not isinstance(fitV, np.ndarray):
fitV = np.asarray(fitV)
elites_idx = heapq.nlargest(10, range(pop.NIND), pop.fitV.__getitem__)
for i in range(0, 10):
off.chromMatrix[i] = pop.chromMatrix[elites_idx[i]]
# print(off)
ps = fitV / np.sum(fitV)
pc = np.cumsum(ps)
for i in range(10, 100):
r = np.random.random()
select = 0
for j in range(pop.NIND):
if r < pc[j]:
select = j
break
off.chromMatrix[i] = pop.chromMatrix[select]
return off
def run(self):
population = Population(self.problem)
population.initPop()
self.problem.evaluate(population)
while not self.terminated(population):
offspring = self.selection(population)
self.mutation(offspring)
self.problem.evaluate(offspring) # 计算目标函数值
population = offspring
return self.finish(population)
def terminated(self, population):
self.log(population)
if self.currentGen + 1 >= self.MAXGEN:
return True
self.currentGen += 1
return False
def log(self, pop: Population):
idx = np.argmax(pop.fitV)
self.trace["obj"].append(pop.objV[idx])
self.trace["solution"].append(pop.phenMatrix[idx])
print("obj=", pop.objV[idx])
def finish(self, pop: Population):
print("final solution:")
idx = np.argmax(pop.fitV)
routes = pop.phenMatrix[idx]
print(routes)
print("veh used:", len(routes))
self.draw(routes)
self.save(pop)
def save(self, pop: Population):
with open('final result.txt', 'a') as f:
idx = np.argmax(pop.fitV)
routes = pop.phenMatrix[idx]
f.write("veh used:%d\n" % len(routes))
f.write("%s\n" % routes)
f.write("%s\n" % pop.objV[idx])
def draw(self, routes):
customers = self.problem.customers
for route in routes:
x = []
y = []
for i in route:
x.append(customers[i].x)
y.append(customers[i].y)
plt.plot(x, y, 'o-', alpha=0.8, linewidth=0.8)
plt.xlabel('x')
plt.ylabel('y')
currentTime = datetime.datetime.strftime(datetime.datetime.now(), '%Y%m%d%H%M%S')
plt.savefig("cg" + currentTime, bbox_inches="tight")
plt.show()
本文求解结果,图左veh used:4,obj=845.52,[[0, 27, 24, 8, 22, 9, 28, 4, 18, 6, 0], [0, 29, 15, 10, 25, 5, 20, 14, 0], [0, 2, 3, 11, 19, 1, 13, 7, 12, 30, 0], [0, 23, 26, 31, 21, 17, 16, 0]]
6中博客求解结果:图右,运算结果最优解为728.1, 路径为[0, 6, 19, 11, 3, 2, 28, 4, 9, 22, 8,
27, 18, 0], [0, 24, 29, 15, 10, 25, 5, 20, 16, 14, 0], [0, 23, 17, 21,
31, 26, 30, 12, 1, 13, 7, 0]
版权声明:参考CSDN博主「_2312」原创文章进行复现,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tangshishe/article/details/116197720
https://blog.csdn.net/meiyoushui_/article/details/110367916
http://iescm.com/vrp/instances/P1CVRP.asp