【进阶五】Python实现SDVRP(需求拆分)常见求解算法——遗传算法(GA)

写一个用遗传算法解决VRP问题的代码 下面是一个使用 Python 实现的遗传算法解决 VRP 问题的代码示例: ``` import random import numpy as np class VRP: def init(self, num_customers, vehicle_capacity, demand, distance_matrix): self.num_customers = num_cus... 阅读详情

基于python语言,采用经典遗传算法(GA)对 需求拆分车辆路径规划问题(SDVRP) 进行求解。

往期优质资源


经过一年多的创作,目前已经成熟的代码列举如下,如有需求可私信联系,表明需要的 **问题与算法**,原创不宜,有偿获取。
VRP问题GAACOALNSDEDPSOQDPSOTSSA
CVRP√√√√√√√√
VRPTW√√√√√√√√
MDVRP√√√√√√√√
MDHVRP√√√√√√√√
MDHVRPTW√√√√√√√√
SDVRP√

1. 适用场景

  • 求解CVRP
  • 车辆类型单一
  • 车辆容量小于部分需求节点需求
  • 单一车辆基地

2. 代码调整


与CVRP问题相比,SDVRP问题允许客户需求大于车辆容量。为了使得每个客户的需求得到满足,必须派遣一辆或多辆车辆对客户进行服务,也就是需要对客户的需求进行拆分。关于如何进行拆分一般有两种方式:

  • 先验拆分策略:提前制定策略对客户的需求(尤其是大于车辆容量的客户需求)进行分解,将SDVRP问题转化为CVRP问题
  • 过程拆分策略:在车辆服务过程中对客户需求进行动态拆分

本文采用文献[1]提出的先验分割策略,表述如下:

(1)20/10/5/1拆分规则

  • m20 =max{ m ∈ Z + ∪ { 0 } ∣ 0.20 Q m < = D i m\in Z^+ \cup \{0\} | 0.20Qm <= D_i m∈Z+∪{0}∣0.20Qm<=Di​ }
  • m10 =max{ m ∈ Z + ∪ { 0 } ∣ 0.10 Q m < = D i − 0.20 Q m 20   m\in Z^+ \cup \{0\} | 0.10Qm <= D_i-0.20Qm_{20}~ m∈Z+∪{0}∣0.10Qm<=Di​−0.20Qm20​  }
  • m5 =max{ m ∈ Z + ∪ { 0 } ∣ 0.05 Q m < = D i − 0.20 Q m 20 − 0.10 Q m 10 m\in Z^+ \cup \{0\} | 0.05Qm <= D_i-0.20Qm_{20}-0.10Qm_{10} m∈Z+∪{0}∣0.05Qm<=Di​−0.20Qm20​−0.10Qm10​ }
  • m1 =max{ m ∈ Z + ∪ { 0 } ∣ 0.01 Q m < = D i − 0.20 Q m 20 − 0.10 Q m 10 − 0.05 Q m 5 m\in Z^+ \cup \{0\} | 0.01Qm <= D_i-0.20Qm_{20}-0.10Qm_{10}-0.05Qm_{5} m∈Z+∪{0}∣0.01Qm<=Di​−0.20Qm20​−0.10Qm10​−0.05Qm5​ }

(2)25/10/5/1拆分规则

  • m25 =max{ m ∈ Z + ∪ { 0 } ∣ 0.25 Q m < = D i m\in Z^+ \cup \{0\} | 0.25Qm <= D_i m∈Z+∪{0}∣0.25Qm<=Di​ }
  • m10 =max{ m ∈ Z + ∪ { 0 } ∣ 0.10 Q m < = D i − 0.25 Q m 25   m\in Z^+ \cup \{0\} | 0.10Qm <= D_i-0.25Qm_{25}~ m∈Z+∪{0}∣0.10Qm<=Di​−0.25Qm25​  }
  • m5 =max{ m ∈ Z + ∪ { 0 } ∣ 0.05 Q m < = D i − 0.25 Q m 25 − 0.10 Q m 10 m\in Z^+ \cup \{0\} | 0.05Qm <= D_i-0.25Qm_{25}-0.10Qm_{10} m∈Z+∪{0}∣0.05Qm<=Di​−0.25Qm25​−0.10Qm10​ }
  • m1 =max{ m ∈ Z + ∪ { 0 } ∣ 0.01 Q m < = D i − 0.25 Q m 25 − 0.10 Q m 10 − 0.05 Q m 5 m\in Z^+ \cup \{0\} | 0.01Qm <= D_i-0.25Qm_{25}-0.10Qm_{10}-0.05Qm_{5} m∈Z+∪{0}∣0.01Qm<=Di​−0.25Qm25​−0.10Qm10​−0.05Qm5​ }

在实现过程中,对于需求超过车辆容量的客户必须进行需求拆分,而对于未超过车辆容量的客户可以拆分也可以不拆分,这里设置了参数比例进行限制。

3. 求解结果


(1)收敛曲线
在这里插入图片描述

(2)车辆路径
在这里插入图片描述

4. 代码片段


(1)数据结构

# 数据结构:解
class Sol():
    def __init__(self):
        self.node_no_seq = None # 节点id有序排列
        self.obj = None # 目标函数
        self.fitness = None  # 适应度
        self.route_list = None # 车辆路径集合
        self.route_distance_list = None  # 车辆路径长度集合
# 数据结构:网络节点
class Node():
    def __init__(self):
        self.id = 0 # 节点id
        self.x_coord = 0 # 节点平面横坐标
        self.y_coord = 0 # 节点平面纵坐标
        self.demand = 0 # 节点需求
# 数据结构:全局参数
class Model():
    def __init__(self):
        self.best_sol = None # 全局最优解
        self.sol_list = []  # 解的集合
        self.depot = None  # 车场节点
        self.number_of_demands = 0 # 需求节点数量
        self.demand_dict = {}  # 原始节点需求集合
        self.demand_id_list = [] # 原始节点id集合
        self.distance_matrix = {}  # 原始节点id间的距离矩阵
        self.demand_id_list_ = [] # 经先验需求分割后的节点集合
        self.demand_dict_ = {} # 需求分割后的节点需求集合
        self.distance_matrix_ = {}  # 原始节点id间的距离矩阵
        self.mapping = {} # 需求分割前后的节点对应关系
        self.vehicle_cap = 80 # 车辆最大容量
        self.pc = 0.5 # 交叉概率
        self.pm = 0.2 # 变异概率
        self.n_select = 80 # 种群选择数量
        self.popsize = 100 # 种群规模
        self.split_rate = 0.5 # 控制需求分割的比例(需求超出车辆容量的除外)

(2)距离矩阵

# 初始化参数
def cal_distance_matrix(model):
    for i in model.demand_id_list:
        for j in model.demand_id_list:
            d=math.sqrt((model.demand_dict[i].x_coord-model.demand_dict[j].x_coord)**2+
                        (model.demand_dict[i].y_coord-model.demand_dict[j].y_coord)**2)
            model.distance_matrix[i,j]=d
        dist = math.sqrt((model.demand_dict[i].x_coord - model.depot.x_coord) ** 2 + (model.demand_dict[i].y_coord - model.depot.y_coord) ** 2)
        model.distance_matrix[i, model.depot.id] = dist
        model.distance_matrix[model.depot.id, i] = dist

(3)邻域搜索

# 二元锦标赛
def select_sol(model):
    sol_list=copy.deepcopy(model.sol_list)
    model.sol_list=[]
    for _ in range(model.n_select):
        f1_index=random.randint(0,len(sol_list)-1)
        f2_index=random.randint(0,len(sol_list)-1)
        f1_fit=sol_list[f1_index].fitness
        f2_fit=sol_list[f2_index].fitness
        if f1_fit<f2_fit:
            model.sol_list.append(sol_list[f2_index])
        else:
            model.sol_list.append(sol_list[f1_index])
# OX交叉
def cross_sol(model):
    sol_list=copy.deepcopy(model.sol_list)
    model.sol_list=[]
    while True:
        [f1_index,f2_index] = random.sample(range(len(sol_list)),2)
        f1 = copy.deepcopy(sol_list[f1_index])
        f2 = copy.deepcopy(sol_list[f2_index])
        if random.random() <= model.pc:
            cro1_index = random.randint(0,model.number_of_demands-1)
            cro2_index = random.randint(cro1_index,model.number_of_demands-1)
            new_c1_f = []
            new_c1_m=f1.node_no_seq[cro1_index:cro2_index+1]
            new_c1_b = []
            new_c2_f = []
            new_c2_m=f2.node_no_seq[cro1_index:cro2_index+1]
            new_c2_b = []
            for index in range(model.number_of_demands):
                if len(new_c1_f)<cro1_index:
                    if f2.node_no_seq[index] not in new_c1_m:
                        new_c1_f.append(f2.node_no_seq[index])
                else:
                    if f2.node_no_seq[index] not in new_c1_m:
                        new_c1_b.append(f2.node_no_seq[index])
            for index in range(model.number_of_demands):
                if len(new_c2_f)<cro1_index:
                    if f1.node_no_seq[index] not in new_c2_m:
                        new_c2_f.append(f1.node_no_seq[index])
                else:
                    if f1.node_no_seq[index] not in new_c2_m:
                        new_c2_b.append(f1.node_no_seq[index])
            new_c1=copy.deepcopy(new_c1_f)
            new_c1.extend(new_c1_m)
            new_c1.extend(new_c1_b)
            f1.node_no_seq=new_c1
            new_c2=copy.deepcopy(new_c2_f)
            new_c2.extend(new_c2_m)
            new_c2.extend(new_c2_b)
            f2.node_no_seq=new_c2
            model.sol_list.append(copy.deepcopy(f1))
            model.sol_list.append(copy.deepcopy(f2))
        else:
            model.sol_list.append(copy.deepcopy(f1))
            model.sol_list.append(copy.deepcopy(f2))
        if len(model.sol_list)>model.popsize:
            break
# 变异
def mu_sol(model):
    sol_list=copy.deepcopy(model.sol_list)
    model.sol_list=[]
    while True:
        f1_index = random.randint(0, len(sol_list) - 1)
        f1 = copy.deepcopy(sol_list[f1_index])
        m1_index=random.randint(0,model.number_of_demands-1)
        m2_index=random.randint(0,model.number_of_demands-1)
        if m1_index!=m2_index:
            if random.random() <= model.pm:
                node1=f1.node_no_seq[m1_index]
                f1.node_no_seq[m1_index]=f1.node_no_seq[m2_index]
                f1.node_no_seq[m2_index]=node1
            model.sol_list.append(copy.deepcopy(f1))
            if len(model.sol_list)>model.popsize:
                break

参考

【1】 A novel approach to solve the split delivery vehicle routing problem

【SDVRP】模拟退火算法求解同时取送货的车辆路径问题【含Matlab源码 2634期】 模拟退火算法求解同时取送货的车辆路径问题 完整的代码,方可运行;可提供运行操作视频!适合小白! 阅读详情

相关推荐

遗传算法求解VRP问题

解决VRP问题的一个好的途径,采用比较先进的遗传算法

组合优化问题求解算法思路的整理(VRP、SDVRP,container loading)

一、技术背景与合作的必要性 (解决合作问题现有的技术路线、挑战与不足。 拟采用的技术路线,合作引进 这种技术的有益效果(缺)。) 求解组合优化问题可以通过利用各种数学方法,寻找离散事件的最优编排、分组、次 序或筛选等。目前常用的优化算法可以分为以下四类: (1)精确算法。 精确算法是指能够求出问题最优解的算法。当问题的规模较小时,精确算法能够在可 接受的时间内得到最优解;当问题的规模较大时,精确算...

qq_32732581的博客 3万+

logisim实验——通过2个半加器实现1-bit全加器,通过4个一位全加器构成4-bit加法器(详解)

一、由异或门和与门所构成的半加器: 二、由两个半加器构成的1-bit全加器: ..

zep 1万+

蚁群算法求解需求可拆分车辆路径问题(SDVRP)

今天给大家介绍SDVRP(split delivery vehicle routing problem,需求可拆分的车辆路径问题),同时介绍蚁群优化算法求解SDVRP。话不多说,我们直接开始。传统的VRP通常假设车辆载重大于客户需求。如果车辆载重小于顾客的实际需求,就需要多辆车来服务一个顾客,由此衍生出了SDVRP。SDVRP,即需求可拆分的车辆路径问题,是车辆路径问题的变体,它在VRP的基础之上增加了一个条件:每个顾客的需求可以拆分并分配给不同的车辆配送,而不是必须由一个车辆在一条路径中满足。

eternal1995的博客 2666

Qt·DBus快速入门

DBus快速入门

m0_64560763的博客 2273

COMSOL仿真教程—激光烧蚀

本例使用二维模型,将来自激光的入射热通量模拟为金属表面上空间分布的热源,从而得到金属的烧蚀过程和瞬态温度分布。

qq_40977332的博客 2万+

【进阶六】Python实现SDVRPTW常见求解算法——遗传算法(GA)

基于python语言,采用经典遗传算法(GA)对 带硬时间窗的需求拆分车辆路径规划问题(SDVRP) 进行求解。

Better.C的博客 1547

qt实现程序密钥注册功能,MD5加密+AES加密,并实现一台电脑系统一个密钥

qt实现了一个给自己软件加密的功能。 原理是: 需要被注册的软件第一次运行的时候,在系统的注册表里面注册一个键值,如下: 这个值作为生成密钥的用户识别号,然后生成密钥文件key.db,把这个key.db文件放到软件执行目录下,即可完成软件的注册并正常使用软件。 软件第一次打开的界面及密钥生成工具软件界面如下: 将密钥生成工具软件生成的key.db放到软件执行目录下之后,软件即可正常使用,如下图: 代码使用了MD5加密 外加 AES加密, 解密和加密的核心代码如下: QSt.

weixin_43935474的博客 4130

【进阶五】Python实现SDVRP(需求拆分)常见求解算法——离散粒子群算法(DPSO)

基于python语言,采用经典离散粒子群算法(DPSO)对 需求拆分车辆路径规划问题(SDVRP) 进行求解。

Better.C的博客 1474

别再手动填数据了!Vivado里用.coe文件给ROM IP核预装数据的保姆级教程

本文详细介绍了在Vivado中使用.coe文件为ROM IP核预装数据的全流程教程,包括文件格式规范、数据转换技巧和Vivado配置指南。通过自动化数据加载,开发者可以显著提升FPGA开发效率,避免手动输入错误,适用于查找表、波形存储等多种应用场景。

weixin_33377602的博客 340

Modelsim安装教程以及管理员身份运行patch_dll.bat时找不到文件mgls.dll的解决

Modesim安装教程 Modesim版本有很多,但是安装方式大都相同,我们以modesim.10.5为例,电脑使用的是win10 64位,讲一下安装过程中的步骤以及出现问题的解决方法 一 安装 1.首先解压安装包,在解压的安装包内选择应用程序,右键选择管理员运行。 2.稍等一会,有的电脑会弹出是否允许modesim进行更改,选择 是 即可,然后出现下面的界面,点击下一步。 3.弹出此界面选择安装路径,选择安装路径,我是在D盘新建的文件夹,直接把文件夹中的路径复制在框内。文件夹名称切记不要带中文 4.

weixin_48564372的博客 1万+

【TWVRP】基于matlab模拟退火算法求解带时间窗的车辆路径规划问题【含Matlab源码 160期】

模拟退火算法求解带时间窗的车辆路径规划问题 完整代码,直接运行,适合小白!可提供运行操作视频!

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 1679

麒麟银河操作系统V10部署ffmpeg(也能用于Linux系统)

部署ffmpeg用来处理视频的各种操作,如编码解码,格式转换,剪辑,处理实时视频流,音频流,加滤镜等

zhouwenxing666的博客 9041

2. Python实现VRP常见求解算法——遗传算法(GA)

参考笔记 https://github.com/PariseC/Algorithms_for_solving_VRP 1. 适用场景 求解CVRP 车辆类型单一 车辆容量不小于需求节点最大需求 单一车辆基地 2. 问题分析 CVRP问题的解为一组满足需求节点需求的多个车辆的路径集合。假设某物理网络中共有10个顾客节点,编号为1~10,一个车辆基地,编号为0,在满足车辆容量约束与顾客节点需求约束的条件下,此问题的一个可行解可表示为:[0-1-2-0,0-3-4-5-0,0-6-7-8-0,0-9-10-0

qq_36744449的博客 4371

ThingsBoard PE专业版解决方案技术文档——温度&湿度

温湿度解决方案

weixin_67440240的博客 820

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

遗传算法求解车辆路径优化问题VRP(Python代码实现)

用了最简单的代码,没有高级的操作(比如新建类class,有很多self这样难懂的地方),相信每个人,包括小白都能看懂学会啦

weixin_43697614的博客 1万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

使用Python实现的遗传算法 附完整代码

使用Python实现的遗传算法 附完整代码

1万+

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

【进阶二】Python实现VRPTW常见求解算法——禁忌搜索(TS)

基于python语言,实现经典禁忌搜索算法(TS)对带有时间窗的车辆路径规划问题(VRPTW )进行求解。

Better.C的博客 4038

用python实现简单的遗传算法

今天整理之前写的代码,发现在做数模期间写的用python实现的遗传算法,感觉还是挺有意思的,就拿出来分享一下。 首先遗传算法是一种优化算法,通过模拟基因的优胜劣汰,进行计算(具体的算法思路什么的就不赘述了)。大致过程分为初始化编码、个体评价、选择,交叉,变异。 以目标式子 y = 10 * sin(5x) + 7 * cos(4x)为例,计算其最大值 首先是初始化,包括具

czrzchao的博客 4万+

【VRP】基于matlab遗传算法求解多车辆路径规划问题【含Matlab源码 1249期】

遗传算法求解多车辆路径规划问题 完整代码,直接运行,适合小白!可提供运行操作视频!

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 1万+

【进阶五】Python实现SDVRP(需求拆分)常见求解算法——禁忌搜索+模拟退火算法(TS+SA)

基于python语言,采用经典禁忌搜索(TS)+模拟退火(SA)对 需求拆分车辆路径规划问题(SDVRP) 进行求解。

Better.C的博客 1431

手把手带你解决车辆路径问题(VRP)---0基础入门python----遗传算法

车辆路径,python,遗传算法,适应度函数

非计算机相关专业 1467

车辆路径安排的遗传算法研究--python

车辆路径安排的遗传算法研究 1.1问题描述 1.1.1车辆路径问题 ​ 车辆路径问题(Vehicle Routing Problem-VRP)是为一些车辆(确定或不确定数量)确定访问一些客户的路径,每一客户被而且只被访问一次,且每条路径上的客户需求量之和不超过车辆的能力。目标是使总成本(如距离、时间等)为最小。有时间窗车辆路径问题(V ehicle Routing Problem with Ti...

weixin_43434802的博客 9617

【改进篇】Python实现VRP常见求解算法——遗传算法(GA)

基于python语言,实现经典遗传算法(GA)对车辆路径规划问题(CVRP)进行求解, 优化代码结构,改进Split函数

Better.C的博客 3684

(未看完)非配对接送的多次访问的车辆路径问题

DOI:10.1016/j.tre.2017.04.011 摘要 非配对接送的多次访问的车辆路径问题(或者叫做the many-to-many pickup and delivery problem (Battara et al., 2014) with multi-visit) 决策:供需配对和车辆路径 提出数学模型,采用禁忌搜索算法提出高质量的解决方案 问题背景与文献综述 解决烟草公司的工厂之间转移各种原材料运输成本问题。 问题背景 1)每个工厂使用(本地)仓库来储存原材料 2)为确保快速响.

weixin_47442524的博客 632

遗传算法--基础VRP--白话文版笔记(附逐句详细解释)

from tqdm import * # 进度条J = []pop = getpop(length, geneNum) # 初始种群# 迭代chosen_pop = choose(pop) # 选择 选择适应度值最高的前三分之一,也就是32个种群,进行下一步的交叉crossed_pop = cross(chosen_pop) # 交叉pop = mergeGenes(pop, crossed_pop) # 复制交叉至子代种群。

steal_tower69的博客 2615
上一篇: VRPSolverEasy:可求解多种VRP变体(rich vehicle routing)问题的精确算法python包
下一篇: 【进阶五】Python实现SDVRP(需求拆分)常见求解算法——蚁群算法(ACO)
Better.C
博客等级 码龄9年 1万+粉丝 72原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Better.C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值