VRPSolverEasy:支持VRP问题快速建模的精确算法Python包

news2024/11/28 2:45:24

文章目录

  • 前言
  • 一步步安装免费版
  • 主要模块介绍
    • 1. depot point
    • 2. customer point
    • 3. links
    • 4. vehicle type
  • VRPTW 算例
    • 数据说明
    • 模型建立
    • 输出求解状态及结果


前言

VRPSolverEasy 是用于车辆路径问题(VRP)的最先进的分支切割和定价算法求解器1,它的一大特点是,即使没有运筹学背景的用户,也可以直观地通过Python接口定义出VRP问题,无需知道模型是如何建立为 MIP 问题以及底层进行的线性处理,只需要通过配置好的方法,向模型中添加高度抽象的VehicleTypePoint(衍生出depotcustomer)、links 即可。

VRPSolver将VRP问题进行了高度抽象,尽管较大程度方便使用,但代价是限制了VRPSolver只能建模常见的标准的VRP变体问题,例如:

  1. 车辆带容量限制;
  2. 客户点带时间窗;
  3. 车辆不同质;
  4. 多depot发车;
  5. 客户点指定车辆资质;
  6. 时间依赖…

VRPSolver的内核是分支切割定价算法,其高效性在于对可行解最优界(下界)的优化上,而在初始可行解的寻找方面效率较低,因此由外部启发式求解器获得非常好的初始解(上界)时,VRPSolver的求解性能可以得到改善。

目前的VRPSolver仍然是proof-of-concept的代码,容易出现问题,因此建议仅用于研究、教学、测试等非生产环境。

一步步安装免费版

VRPSolverEasy有两种安装模式,一种是免费版本,直接安装VRPSolverEasy库(内嵌了COIN-OR CLP线性规划求解器),以及下载Bapcod发行版即可。另一种是学术版本,该版本使用了商业CPLEX MIP求解器,由于CPLEX可以免费用于学术目的,因此这个版本下的VRPSolverEasy也被称为学术版,该版本提高了求解性能,并提供了内置的基于MIP的启发式算法,对寻找可行的初始解非常有用。

这里我们仅介绍安装免费版的 VRPSolverEasy,操作系统默认为Windows。(学术版的安装请参考 官方文档)

(1)确认python版本及更新pip

VRPSolverEasy库要求python版本不小于 3.6,因此在开始安装前,先确认好python的版本,并建议更新 pip 库:

python -m pip install --upgrade pip

(2)安装VRPSolverEasy库

VRPSolverEasy库的安装可以直接用pip安装:

python -m pip install VRPSolverEasy

(3)安装Bapcod依赖的环境

由于内嵌的 CLP 仅是线性规划求解器,要用 B&C&P 求解MIP问题,还需安装Bapcod,由于Bapcod的底层是C++,因此要用Python接口使用,就还需下载能对该库进行编译和管理的工具CMake,该工具的官网下载地址为:Download CMake,具体的安装细节可以参考:Windows 安装CMake。在cmd控制台输入 cmake --version 即可查看CMake的版本。

接着还需安装 Bapcod 依赖的python库:

  1. Boost库版本1.76 pip install boost
  2. LEMON 库版本 1.3.1 pip install lemon

(4)申请Bapcod并替换相应文件

尽管Bapcod是免费开源的库,但是需要学术机构的电子邮箱才能下载Bapcod的源码,在 BaPCod官方网站 填写相应信息并回车进行申请。系统会自动验证该邮箱,并向该邮箱发送下载链接。

解压下载的文件,例如为 bapcod-v0.82.5,找到该文件夹下的 VRPSolverEasy 文件夹,复制该文件夹下的 Windows 文件夹到 VRPSolverEasy 库下面的 lib 文件夹中替换 Windows 即可。

主要模块介绍

关于主要模块的介绍我们截取翻译自VRPSolverEasy的技术报告1

导入VRPSolverEasy库,并通过以下命令创建模型。

import VRPSolverEasy
model = VRPSolverEasy.Model()

VRPSolverEasy库模型由四组实体对象定义:depot pointscustomer pointslinksvehicle types

1. depot point

depot 可以通过如下命令添加

model.add_depot(id=<id>, name='', service_time=0.0, tw_begin=0.0, tw_end=0.0)

添加 depot 方法的参数说明如下:

Characterization of a depot point v

2. customer point

customer 可以通过如下命令添加:

model.add_customer(id=<id>, id_customer=<id>, name ='', demand=0, penalty=0.0, service_time=0.0, tw_begin=0.0, tw_end=0.0, incompatible_vehicles=[])

添加 customer 方法的参数说明如下:

Characterization of a customer point v
不论是 depot point 还是 customer point,都应该有一个唯一的点 id,且每个 customer 都与一个或多个点相关联,其中 idid_customer 可以不同。

对于一些特殊的问题,例如同一个客户点具有不同的时间窗,且每个时间窗所兼容的车辆可能不同,常见于时间依赖的VRPTW问题,这类问题中,客户点可能会被多辆车访问(同时或者有时间前后约束),这时候为了避免与子环路消除约束相冲突,往往会创建虚拟点,在这里,如果我们要创建 customer point 的额外点,可以通过以下命令添加:

model.add_point(id=<id>, id_customer=<id>, name ='', demand=0, penalty=0.0, service_time=0.0, tw_begin=0.0, tw_end=0.0, incompatible_vehicles=[])

3. links

link 可以通过如下命令添加:

model.add_link(start_point_id=<id>, end_point_id=<id>, name='', is_directed=False, distance=0.0, time=0.0, fixed_cost=0.0)

添加 link 方法的参数说明如下:

Characterization of a link l
每一条 link 代表有向图G当中的一条弧,如果 is_directed=True,则说明该弧具有方向,只能从 start_point_idend_point_id 方向;如果 is_directed=False,则说明该弧是双向的(若不设置该参数默认为双向的)。

4. vehicle type

vehicle type 可以通过如下命令添加:

model.add_vehicle_type(id=<id>, start_point_id=-1, end_point_id=-1, name='', capacity=0, fixed_cost=0.0, var_cost_dist=0.0, var_cost_time=0.0, max_number=1, tw_begin=0.0, tw_end=0.0) 

添加 vehicle type 方法的参数说明如下:

Characterization of a vehicle type k
当车辆的开始点和结束点都为 -1 时,说明该车辆可以在任意节点处出发,和返回任意节点处。

VRPTW 算例

数据说明

如下设置 7 个节点,以第 1 个节点 Wisconsin, USAdepot point,其余节点为 customer point,除了 depot 其余节点都有大于0需求量,车辆的时间窗为 [ 0 , 5000 ] [0, 5000] [0,5000],每辆车单位距离成本为 10,节点与节点之间的距离通过欧式距离公式计算 compute_euclidean_distance

import VRPSolverEasy as vrpse
import math

def compute_euclidean_distance(x_i, x_j, y_i, y_j):
    """compute the euclidean distance between 2 points from graph"""
    return round(math.sqrt((x_i - x_j)**2 + (y_i - y_j)**2), 3)

# Data
cost_per_distance = 10
begin_time = 0
end_time = 5000
nb_point = 7

# Map with names and coordinates
coordinates = {"Wisconsin, USA": (44.50, -89.50),  # depot
               "West Virginia, USA": (39.000000, -80.500000),
               "Vermont, USA": (44.000000, -72.699997),
               "Texas, the USA": (31.000000, -100.000000),
               "South Dakota, the US": (44.500000, -100.000000),
               "Rhode Island, the US": (41.742325, -71.742332),
               "Oregon, the US": (44.000000, -120.500000)
               }

# Demands of points
demands = [0, 500, 300, 600, 658, 741, 436]

模型建立

依次建立求解车辆路径网络流问题的要素:车辆、节点、弧。要素的参数值可以自定义配置。

# Initialisation
model = vrpse.Model()

# Add vehicle type
model.add_vehicle_type(
    id=1,
    start_point_id=0,
    end_point_id=0,
    name="VEH1",
    capacity=1100,
    max_number=6,
    var_cost_dist=cost_per_distance,
    tw_end=5000)

# Add depot
model.add_depot(id=0, name="D1", tw_begin=0, tw_end=5000)

coordinates_keys = list(coordinates.keys())
# Add customers
for i in range(1, nb_point):
    model.add_customer(
        id=i,
        name=coordinates_keys[i],
        demand=demands[i],
        tw_begin=begin_time,
        tw_end=end_time)

# Add links
coordinates_values = list(coordinates.values())
for i in range(0, 7):
    for j in range(i + 1, 7):
        dist = compute_euclidean_distance(coordinates_values[i][0],
                                          coordinates_values[j][0],
                                          coordinates_values[i][1],
                                          coordinates_values[j][1])
        model.add_link(
            start_point_id=i,
            end_point_id=j,
            distance=dist,
            time=dist)

输出求解状态及结果

当建立模型后,通过以下命令即可实现求解,求解的结果都会保存在 model 的属性当中。

# solve model
model.solve()

打印模型信息可以通过以下命令,默认将模型信息保存在 instance.json 文件中。

model.export()

通过 model.status 可以返回模型的求解状态码:

状态码说明
0找到一个解并证明了最优性
1求解过程被时间限制打断,但找到了优于截断值的解
2求解器证明不存在由于截断值的解
3求解过程被时间限制打断,且没找到由于截断值的解

判断求解状态码是一种输出结果的前置判断,在该库中也可以用 model.solution.is_defined() 进行判断,后者表示找到了可行解,且解的信息会保存到模型的属性当中:

if model.solution.is_defined():
	# 打印解的目标值及方案的全部信息
    print(model.solution)
    # 仅打印路线方案
    print(model.solution.routes)
    # 仅打印目标值
    print(model.solution.value)    
    # 打印解的求解时间和上下界信息等
    print(model.statistics)

打印解的目标值及方案的全部信息如下:

Solution cost : 1479.6800000008684

Route for vehicle 1:
 ID : 0 --> 2 --> 5 --> 0
 Name : D1 --> Vermont, USA --> Rhode Island, the US --> D1
 End time : 0.0 --> 16.807 --> 19.259 --> 37.230000000000004
 Load : 0.0 --> 300.0 --> 1041.0 --> 1041.0
Total cost : 372.29999999999995

Route for vehicle 1:
 ID : 0 --> 1 --> 3 --> 0
 Name : D1 --> West Virginia, USA --> Texas, the USA --> D1
 End time : 0.0 --> 10.548 --> 31.625 --> 48.728
 Load : 0.0 --> 500.0 --> 1100.0 --> 1100.0
Total cost : 487.2800000000001

Route for vehicle 1:
 ID : 0 --> 4 --> 6 --> 0
 Name : D1 --> South Dakota, the US --> Oregon, the US --> D1
 End time : 0.0 --> 10.5 --> 31.006 --> 62.010000000000005
 Load : 0.0 --> 658.0 --> 1094.0 --> 1094.0
Total cost : 620.1

  1. N. Errami, E. Queiroga, R. Sadykov, E. Uchoa. “VRPSolverEasy: a Python library for the exact solution of a rich vehicle routing problem”, Technical report HAL-04057985, 2023. ↩︎ ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1392819.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

苹果要在iPhone上运行AI大模型?

近两年&#xff0c;人工智能&#xff08;AI&#xff09;技术已经成为各大科技公司的重点研究领域&#xff0c;苹果公司自然也不甘落后。最新消息称&#xff0c;苹果甚至打算在iPhone上直接运行AI大模型... 据苹果AI研究人员表示&#xff0c;他们发明了一种创新的闪存利用技术&a…

云服务器CVM_云主机_云计算服务器_弹性云服务器

腾讯云服务器CVM提供安全可靠的弹性计算服务&#xff0c;腾讯云明星级云服务器&#xff0c;弹性计算实时扩展或缩减计算资源&#xff0c;支持包年包月、按量计费和竞价实例计费模式&#xff0c;CVM提供多种CPU、内存、硬盘和带宽可以灵活调整的实例规格&#xff0c;提供9个9的数…

用冒泡排序谈默认参数应用

前面在调用函数提到为了将信息打印到ofil中&#xff0c;前面提到的办法是 ofstream ofil("text_out1"); void bubble_sort(vector<int> vec){ } 在file scope中定义ofil&#xff0c;这是一个不受欢迎的举动。这样比较难在其他环境重用 一般的程序编写法则是&…

本周五上海见 第二届证券基金行业先进计算技术大会暨2024低时延技术创新实践论坛(上海站)即将召开

低时延技术是证券基金期货领域业务系统的核心技术&#xff0c;是打造极速交易系统领先优势的关键&#xff0c;也是证券基金行业关注的前沿技术热点。 1月19日下午&#xff0c;第二届证券基金行业先进计算技术大会暨2024低时延技术创新实践论坛&#xff08;上海站&#xff09;即…

VL171 VL170配合LDR6020的type-c母座显示器方案

兼容基于VASEL控制引脚的10 Gbps USB3.2 Gen2和AM所有4通道视频&#xff0c;包括DP1.4 8.1 Gbps VL171配合LDR6020实现的type-c桌面显示器方案电路LDR6020是一个DRP的PD芯片&#xff0c;PD芯片与主机通讯完之后&#xff0c;通过PD芯片去控制VL171实现正反插与USB信号和DP信号的…

使用Go语言处理Excel文件的完整指南

xcel文件是广泛用于存储和处理数据的常见文件格式。在Go语言中&#xff0c;有许多库和工具可用于处理Excel文件。本文将介绍如何使用Go语言处理Excel文件&#xff0c;包括读取、写入和修改Excel文件&#xff0c;以及处理单元格、行和列等操作。无论是从头开始创建Excel文件&…

日期处理第一篇--优雅好用的Java日期工具类Joda-Time

日常开发中&#xff0c;处理时间和日期是很常见的需求。基础的java内置工具类只有Date和Calendar&#xff0c;但是这些工具类的api使用并不是很方便和强大&#xff0c;于是就诞生了Joda-Time这个专门处理日期时间的库。 简介 Joda-Time提供了Java日期处理的优雅的替代品&…

Gorm 应用开发时区问题与unique唯一索引字段数据冲突问题

文章目录 一、定义表模型时区问题1.1 time.Time 与int641.2 优势 二、unique唯一索引字段数据冲突问题 一、定义表模型时区问题 1.1 time.Time 与int64 一般情况下&#xff0c;我们在定义表模型的时候&#xff0c;会使用time.Time&#xff0c;但是会根据当前时间存储。返回给…

Javascript,到底要不要写分号?

小白随机在互联网上乱丢一些赛博垃圾&#xff0c;还望拨冗批评斧正。 要不要加分号&#xff1f; 先说结论&#xff1a;“不引起程序出错的前提下&#xff0c;加不加都可以&#xff0c;按自身习惯来。” 为什么JS可以不加分号&#xff1f; 实际上&#xff0c;行尾使用分号的风…

深度学习记录--归—化输入特征

归化 归化输入(normalizing inputs),对特征值进行一定的处理&#xff0c;可以加速神经网络训练速度 步骤 零均值化 通过x值更新让均值稳定在零附近&#xff0c;即为零均值化 归化方差 适当减小变量方差 解释 归化可以让原本狭长的数据图像变得规整&#xff0c;梯度下降的…

JavaScript基础(27)_内联样式的获取和修改、获取元素当前显示的样式

内联样式的获取和修改 获取元素的内联样式&#xff1a; 语法&#xff1a;元素.style.样式名 注意&#xff1a;通过style属性设置和读取的都是内联样式&#xff0c;无法读取样式表中的样式。 修改元素的内联样式&#xff1a; 语法&#xff1a;元素.style.样式名 样式值比如…

Apache JMeter 3.1压力测试监控服务器数据(cpu、内存、磁盘io等)

Apache JMeter 3.1压力测试 Apache JMeter 3.1压力测试监控cpu、内存情况1.下载Apache JMeter 3.11.1 添加线程组1.2 添加http请求1.3 增加http请求头设置1.4 添加csv配置1.5 添加测试结果监控配置 2. 监控插件下载3. 服务端插件下载并启动3.1 下载3.2 解压并启动3.3 增加服务器…

136基于matlab的自适应滤波算法的通信系统中微弱信号检测程序

基于matlab的自适应滤波算法的通信系统中微弱信号检测程序&#xff0c;周期信号加入随机噪声&#xff0c;进行滤波&#xff0c;输出滤波信号&#xff0c;程序已调通&#xff0c;可直接运行。 136 matlab自适应滤波算法LMS (xiaohongshu.com)

提高支撑座效率的重要性

自动化机械设备在运行过程中需要消耗大量的能源和资源&#xff0c;提高效率意味着更有效地利用这些资源&#xff0c;降低运行成本&#xff0c;而支撑座作为自动化机械设备中重要的传动元件&#xff0c;提高支撑座的效率对于自动化机械设备的可持续发展和企业的竞争力具有重要意…

2024华数杯国际赛A题B题思路及代码!

大家好&#xff0c;这里是本次华数杯国际数学建模竞赛的AB题思路代码讲解贴。 关于思路&#xff0c;可以移步我的视频讲解&#xff1a; 2024华数杯国际赛数学建模选题建议及初步思路&#xff01;_哔哩哔哩_bilibili 本篇主要讲解代码。 问题A&#xff1a;日本放射性废水 对…

Springboot+vue的智能家居系统(有报告),Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的智能家居系统&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的智能家居系统&#xff0c;采用M&#xff08;model&a…

二叉树的概念|满二叉树与完全二叉树|二叉树的性质|二叉树的存储结构

前言 在数据结构中树的用途其实并不大&#xff0c;用得更多的其实是二叉树。所以在本章我们将详细讲解二叉树。 一、二叉树的概念及结构 1、概念 一颗二叉树是结点的一个有限集合&#xff0c;该集合&#xff1a; 或者为空或者由一个根节点加上两颗&#xff08;互不相交&…

云计算入门——Linux 命令行入门

云计算入门——Linux 命令行入门 前些天发现了一个人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;最重要的屌图甚多&#xff0c;忍不住分享一下给大家。点击跳转到网站。 介绍 如今&#xff0c;我们许多人都熟悉计算机&#xff08;台式机和笔记本电…

VMware workstation安装SUSE Linux Enterprise Server 12 SP5虚拟机并配置网络

VMware workstation安装SUSE Linux Enterprise Server 12 SP5虚拟机并配置网络 SUSE Linux Enterprise Server是企业级Linux系统&#xff0c;适合企业应用。该文档适用于在VMware workstation平台安装SUSE Linux Enterprise Server虚拟机。 1.安装准备 1.1安装平台 Windows…

嵌入式-Stm32-江科大基于标准库的GPIO的八种模式

文章目录 一&#xff1a;GPIO输入输出原理二&#xff1a;GPIO基本结构三&#xff1a;GPIO位结构四&#xff1a;GPIO的八种模式道友&#xff1a;相信别人&#xff0c;更要一百倍地相信自己。 &#xff08;推荐先看文章&#xff1a;《 嵌入式-32单片机-GPIO推挽输出和开漏输出》…