运筹系列93:VRP精确算法

1. MTZ模型

MTZ是Miller-Tucker-Zemlin inequalities的缩写。除了定义是否用到边 x i j x_{ij} xij外,还需要定义一个 u i u_i ui用来表示此时车辆的当前载货量。注意这里x变量需要定义为有向。
这里定义为pickup问题,代码为:

using JuMP, HiGHSk = 3 # number of vehicles
N = 11 # number of points, 0 as depot
Q = 4 # vehicle capacity
q = ones(Int,N);q[1]=0 # demand
CVRP = Model(HiGHS.Optimizer)
set_silent(CVRP)
@variable(CVRP,x[1:N,1:N],Bin)
@variable(CVRP,u[1:N],lower_bound = 0, upper_bound = Q)
# 约束1:出度约束
for i in 2:N@constraint(CVRP, sum(x[i,1:i-1]) + sum(x[i,i+1:N]) == 1)@constraint(CVRP, sum(x[1:i-1,i]) + sum(x[i+1:N,i]) == 1)
end
@constraint(CVRP, sum(x[1,1:N]) == k)
# 约束2:流量约束。若存在i->j,则u_j-u_i==q_j;否则u_j-q_j和u_i没有关系。此外,需要有u_j-q_j>=0
for i=2:N, j=[2:i-1;i+1:N]@constraint(CVRP,u[i] - u[j] + Q*x[i,j] <= Q-q[j])
end
for i in 2:N@constraint(CVRP,q[i] <= u[i] <= Q)
end@objective(CVRP,Min, sum(x[i,j]*distmat[i,j] for i=1:N,j=1:N))
@time optimize!(CVRP)

MTZ的求解速度不快,10个点3辆车都需要3秒左右时间。

2. 分支定界法

使用Two-index vehicle flow formulations。按照tsp的方式使用行生成法速度极慢(cut的效率太低),因此考虑使用branch-and-cut直接求解。需要cut的主要有2个:1)容量约束;2)subtour约束。如下例子:

using TSPLIB,JuMP, HiGHS, Distances
N = 13
Q = 4
k = 3
m = Model(HiGHS.Optimizer)
set_silent(m)
@variable(m, x[1:N,1:N]>=0,Bin)
@objective(m, Min, sum(x[i,j]*distmat[i,j] for i=1:N,j=1:N))
@constraint(m, x[1,1] == 0)
@constraint(m, sum(x[1,j] for j in 2:N) == k)
@constraint(m, sum(x[j,1] for j in 2:N) == k)
for i=2:N for j in 1:N;@constraint(m, x[i,j]+x[j,i] <= 1);end@constraint(m, sum(x[i,j] for j in 1:N) == 1)@constraint(m, sum(x[j,i] for j in 1:N) == 1)
end
optimize!(m)
draw_vrp(x)

在这里插入图片描述

接下来定义寻找tour的函数,以及branch and cut的代码:

# find all subtours
function tours(x)g = JuMP.value.(x)# 第一步,找到所有从1出发的tourabnormal_paths = []paths = []path = [1]left = collect(1:N)while truev, idx = findmax(g[path[end],left])if v==0breakelseg[left[idx],path[end]]=0g[path[end],left[idx]]=0push!(path,left[idx])endif path[end]==1if length(path)>Q+2;push!(abnormal_paths,path);endpush!(paths,path)path = [1]setdiff!(left,path[2:end-1])endend# 第二步,找到所有孤立的环(subtour)left = collect(1:N)for path in paths;setdiff!(left,path);endwhile length(left)>0   path = [left[1]]while truev, idx = findmax(g[path[end],left])if idx == 1breakelseg[left[idx],path[end]]=0g[path[end],left[idx]]=0push!(path,left[idx])endendsetdiff!(left,path)push!(paths,path)push!(abnormal_paths,path)endreturn paths,abnormal_paths
endpaths,abnormal_paths = tours(x)
while length(abnormal_paths) > 0for path in pathss = setdiff(path,1)sn = setdiff(2:N,s)@constraint(m, sum(x[i,j] for i in s, j in setdiff(1:N,s)) >= ceil(length(s)/Q))@constraint(m, sum(x[i,j] for i in sn, j in setdiff(1:N,sn)) >= ceil(length(sn)/Q))endoptimize!(m)paths,abnormal_paths = tours(x)
end
draw_vrp(x)

在这里插入图片描述

3. set-partitioning方法

方法很直观,把所有的子路径用TSP问题求解(使用Concorde库),然后用set-partitioning方法选择最合适的几条路线组合成VRP的结果。

using JuMP, HiGHS, Combinatorics, Concorde k = 3
N = 13 #34
Q = 4 #13function getRoutes(k,N,Q)Qm = N-1-(k-1)*Qroute_dists = Dict()# 求解所有子路径的最优解for q in Qm:Qfor c in combinations(2:N,q)c_index_tour,c_tour_length = Concorde.solve_tsp(floor.(Int,distmat[[1;c],[1;c]].*100)) c_tour = [1;c][c_index_tour]route_dists[c_tour] = c_tour_lengthendendroute_dists
end
@time route_dists = getRoutes(k,N,Q);
CVRP = Model(HiGHS.Optimizer)
set_silent(CVRP)
routes = collect(keys(route_dists))
route_dists = collect(values(route_dists))
rn = length(routes)
@variable(CVRP,x[1:rn],Bin)
@objective(CVRP,Min, sum(x[i]*route_dists[i] for i in 1:rn))
a = zeros(Int,rn,N)
for i in 1:rn,j in routes[i];a[i,j]=1;end
for j in 2:N;@constraint(CVRP,sum(x[i]*a[i,j] for i in 1:rn)==1);end
@constraint(CVRP,sum(x)==k)
@time optimize!(CVRP)
rs = routes[findall(x->x>0.1,value.(x))]
plt.figure(figsize=(10,7)) 
plt.scatter(pos[1:N,1],pos[1:N,2],c="red")
for i in 1:N;plt.text(pos[i,1], pos[i,2], i);end
for r in rsl = pos[[r;1],:]PyPlot.plot(l[:,1], l[:,2], color="b")
end

在这里插入图片描述

4. 关于测试数据

测试案例可参考 http://vrp.atd-lab.inf.puc-rio.br/index.php/en/。
我们这里用的数据为:

pos = [121.472641	31.231707
123.429092	41.796768
125.324501	43.886841
126.642464	45.756966
116.405289	39.904987
117.190186	39.125595
111.75199	40.84149
106.23248	38.48644
112.549248	37.857014
114.502464	38.045475
117.000923	36.675808
113.665413	34.757977
108.948021	34.263161
114.298569	30.584354
118.76741	32.041546
117.283043	31.861191
112.982277	28.19409
115.892151	28.676493
120.15358	30.287458
119.306236	26.075302
113.28064	23.125177
121.520076	25.030724
110.19989	20.04422
108.320007	22.82402
106.504959	29.533155
102.71225	25.040609
106.713478	26.578342
104.065735	30.659462
103.83417	36.06138
101.77782	36.61729
91.1145	29.64415
87.61688	43.82663
114.16546	22.27534
113.54913	22.19875];function dis(i,j)A = pos[i,:];B = pos[j,:]sqrt(sum((A-B).^2))
endfunction drawTree(t,n)plt.figure(figsize=(10,7)) plt.scatter(pos[1:n,1],pos[1:n,2],c="red")for i in 1:n;plt.text(pos[i,1], pos[i,2], i);endfor i in 1:length(t)l = pos[collect(t[i]),:]PyPlot.plot(l[:,1], l[:,2], color="b")end
endfunction draw_vrp(x)xv = value.(x)t = []for i in 1:size(x)[1],j in 1:size(x)[1]if xv[i,j]>0.1;push!(t,(i,j));endenddrawTree(t,size(x)[1])
end

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

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

相关文章

windows下载jdk并安装步骤(保姆级教程)

一、下载jdk 下载地址: https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 二、双击下载好的jdk 更改安装目录然后点击下一步 然后会弹出jre的安装&#xff0c;需要选择路径&#xff08;注意&#xff1a;这里的路径必须跟前面的jdk在…

将huggingface的大模型转换为safetensor格式

很多huggingface的大语言模型都是pytorch的格式&#xff0c;但是mindie需要safetensor格式&#xff0c;另外mindieservice加载原始的baichuan2-13b的模型出错&#xff0c;后来排查是bfloat16数据格式的问题&#xff0c;所以这次转换要一次性转为float16的格式。 上代码&#x…

计算机网络:如何隐藏真实的IP和MAC地址?

目录 一、什么是MAC地址二、什么是IP地址三、如何隐藏真实的MAC地址四、如何隐藏真实的IP地址 一、什么是MAC地址 MAC地址&#xff0c;全称为媒体访问控制地址&#xff08;Media Access Control Address&#xff09;&#xff0c;是一种用于网络通信的唯一标识符。它是由IEEE 8…

PLC网关如何选择?plc网关作用-天拓四方

一、PLC网关在工业自动化领域的重要性和作用 PLC网关在工业自动化领域的重要性和作用不言而喻。作为工业自动化系统的重要组成部分&#xff0c;PLC网关起到了关键的桥梁作用&#xff0c;实现了PLC与其他设备、系统之间的数据传输和通信。 首先&#xff0c;PLC网关的重要性体现…

最像人声的语音合成模型-ChatTTS

目录 写在前面 一、使用ChatTTS 二、优点 三、局限 写在前面 最像人声的AI来了&#xff01;语音开源天花板ChatTTS火速出圈&#xff0c;3天就斩获9k个star。截至发稿前&#xff0c;已经25.9k个star了。这是专门为对话场景设计的语音生成模型&#xff0c;用于LLM助手对话任务…

搭建抖音微短剧系统:源码部署与巨量广告回传全解析

在数字化浪潮中&#xff0c;抖音微短剧已成为内容创作的新宠。想要搭建一个高效的抖音微短剧系统&#xff0c;并实现与巨量广告的有效回传吗&#xff1f;本文将为您详细解析源码部署与广告回传的关键步骤。 一、源码部署&#xff1a;构建短剧系统的基石 源码是软件开发的起点…

vscode远程连接Ubantu

一、首先用VM虚拟机打开一个Linux系统 二、打开VScode 在扩展里安装 安装后&#xff0c;打开Linux查看IP地址 在VScode 中新建连接主机 输入linux_nameip地址 -A 然后输入Linux的登录密码 就可以远程操控 Linux了 可以在终端中远程控制Linux 点击左上角的打开文件夹可以很…

什么是 Azure OpenAI?

目录 一、说明 二、什么是 Azure OpenAI 2.1 网络结构 2.2 、为什么使用 Azure OpenAI 2.3 如何使用 Azure OpenAI 三、从哪里开始 Azure OpenAI 之旅 3.1 关于 Azure OpenAI&#xff0c;我还需要了解什么 3.2 RBAC 权限和角色 3.3 演示 1&#xff1a;在公共数据上应用…

聚合项目学习

首先建立一个总的工程目录&#xff0c;里边后期会有我们的父工程、基础工程(继承父工程)、业务工程&#xff08;依赖基础工程&#xff09;等模块 1、在总工程目录中&#xff08;open一个空的文件夹&#xff09;&#xff0c;首先建立一个父工程模块&#xff08;通过spring init…

4面体空间内直链4点结构分布与占比

在30个点的4面体空间内取4个点&#xff0c;有30*29*28*27/2427405种取法&#xff0c;要求得到的4个点必须在直链上。只有144个结构符合要求&#xff0c;在平移操作下不重合的结构有36个。 这36个结构可以按照旋转对称性进一步分成3组0&#xff0c;1&#xff0c;4&#xff0c;每…

Anisble Playbook

文章目录 一、Playbook简介三种常见的数据格式Playbook特点YAML语言介绍 二、Playbook核心组件host组件remote_user组件task列表和action组件gather_factsHandlers notifyignore_errors 三、playbook命令playbook命令tags 标签 四、Playbook中的变量setup模块中的变量Playbook命…

vue3 【提效】自动路由(含自定义路由) unplugin-vue-router 实用教程

不再需要为每一个路由编写冗长的 routes 配置啦&#xff0c;新建文件便可自动生成路由&#xff01; 使用方法 1. 安装 unplugin-vue-router npm i -D unplugin-vue-router2. 修改 vite 配置 vite.config.ts import VueRouter from unplugin-vue-router/viteplugins 中加入 V…

【Redis一】Redis配置与优化

目录 一.关系型数据库与非关系型数据库 1.关系型数据库 2.非关系型数据库 3.二者区别 4.非关系型数据库产生背景 5.NoSQL与SQL数据记录对比 关系型数据库 非关系型数据库 二.Redis相关概述 1.简介 2.五大数据类型 3.优缺点 3.1.优点 3.2.缺点 4.使用场景 5.采用…

苹果应用Testflight上架完整步聚

1.全部选中下图内容,包含iPhone与iPad屏幕所有旋转方向 2. 准备App图标,一定要有152和167这个尺寸,不然后提交不过 3.1024这个尺寸的的图像不能有透明层,不然提交不通过 4.选中编译设备为Any iOS Device[arm64] 5.选择Product下的Archive进行生成 6.在弹出的窗口中选择Test…

Python之三大基本库——Numpy(2)

接着上次的内容接着讲&#xff0c;连续号都续上哈 七、numpu中random的随机生成函数 以下总结的是比较常用到的函数&#xff1a; 下面分别介绍一下不用的用法&#xff1a; 首先导入创建函数 import numpy as np np.random.seed(666)1、 rand(d0,d1,d2,...,dn)&#xff1a;返…

JavaWeb系列三: JavaScript学习 下

文章目录 js数组定义方式数组遍历 js函数函数入门函数使用方式使用方式一使用方式二 函数注意事项函数练习题 定义对象使用object定义使用{}定义 事件onload事件onclick事件失去焦点事件内容发生改变事件表单提交事件静态注册动态注册表单作业 dom对象文档对象模型document对象…

边缘计算VNC智能盒子如何助力HMI设备实现二次开发?

HMI&#xff08;Human-Machine Interface&#xff09;又称人机界面&#xff0c;是用户与机器之间交互和通信的媒介。今天带你了解智能盒子如何助力HMI设备实现二次开发&#xff1f; HMI设备被广泛应用在工业自动化中&#xff0c;具有显示设备信息&#xff0c;实时监测&#xf…

python爬虫--scrapy框架

Scrapy 一 介绍 Scrapy简介 1.Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架&#xff0c;用途非常广泛2.框架的力量&#xff0c;用户只需要定制开发几个模块就可以轻松的实现一个爬虫&#xff0c;用来抓取网页内容以及各种图片&#xff0c;非…

GPT-5对普通人有何影响

这篇文章对ChatGPT的使用方法和提问技巧进行了讨论&#xff0c;重点强调了背景信息和具体提问的重要性。文章清晰地传达了如何提高ChatGPT回答的质量&#xff0c;以及个人在使用ChatGPT时的体会和建议。然而&#xff0c;文章在逻辑组织和表达方面还有一些可以改进的地方&#x…

静态库和动态库

1、编译过程 1.预处理&#xff1a;解释并展开源程序当中的所有的预处理指令&#xff0c;此时生成 *.i 文件。 2.编译&#xff1a;词法和语法的分析&#xff0c;生成对应硬件平台的汇编语言文件&#xff0c;此时生成 *.s 文件。 3.汇编&#xff1a;将汇编语言文件翻译为对应处理…