运筹系列85:求解大规模tsp问题的julia代码

1. 大规模tsp问题的挑战

数学模型和精确解法见《运筹系列65:TSP问题的精确求解法概述》和《运筹系列80:使用Julia精确求解tsp问题》:

@variable(m, x[1:n,1:n], Bin,Symmetric) # 0-1约束
@objective(model, Min, sum(x.*distmat)/2)
@constraint(model, [i = 1:n], sum(x[i, :]) == 2)
@constraint(model, [j = 1:n], sum(x[:, j]) == 2)
for subset in subsets # 防subtour约束,需要遍历所有的子集合@constraint(model,sum(x[subset[i],subset[i]])<=2*length(subset[i])-2) 
end
optimize!(m)
objective_value(model)

主要的挑战包括:

  1. 求解整数规划比较耗时,并且遍历子集难度很大,大规模问题时需要自定义高效的cut和price策略
  2. 变量数量过多,需要使用列生成方法来减少求解变量

2. 使用列生成减少求解变量

关于列生成的列子,可以参考《运筹系列8:Set partitioning问题的列生成方法》。对于tsp问题,我们使用列生成的步骤是:

  1. 首先将问题变量限制在每个点最邻近的k条边上,求解限制主问题
  2. 迭代求解子问题(sub problem)。如果目标函数最优值<0,就将新生成的列yk+1转入基变量,生成新的限制主问题进行求解。如此往复,直至子问题的目标函数≥0。

我们以u159问题为例,原始模型一共有25281个变量:

using TSPLIB, LinearAlgebra, JuMP,HiGHS,PyPlot
#读取数据
tsp = readTSPLIB(:u159)
n = tsp.dimension
distmat = [round(Int64,norm(tsp.nodes[i,:] - tsp.nodes[j,:])) for i in 1:n, j in 1:n];
for i in 1:n;distmat[i,i] = 10^9;end#完整模型
model = Model(HiGHS.Optimizer)
set_silent(model)
@variable(model, 0<=x[i in 1:n,j in js[i]]<=1)
@info "variable size:",length(x)
@objective(model, Min, sum([x[i,j]*distmat[i,j]/2 for i in 1:n for j in js[i]]))
c = @constraint(model, [i = 1:n], sum([x[i, j] for j in js[i]]) >= 2)
e = @constraint(model, [i = 1:n], sum([x[j, i] for j in js[i]]) >= 2)
optimize!(model)
@info "objective:",objective_value(model)

主问题限制在每个点最近的3条边中,此时只有604个变量,第一轮列生成后为686个变量(此时已经得到最优解了),最终经过7轮列生成迭代,变量个数为716:

# js为初始下标合集,我们将变量下标限制在这个集合内。注意需要保持对称性:
idx = Index(2)
add(idx, tsp.nodes)
c = search(idx,tsp.nodes,4)[2];
js = Vector{Vector{Int}}()
for i in 1:npush!(js,c[i,2:end])
end
for i in 1:nfor j in c[i,2:end]union!(js[j],i)end
end

求解主问题,然后找到检验数<0的列。令对偶变量 p = C B B − 1 p=C_B B^{-1} p=CBB1, 则检验数 σ = C N − p ∗ N \sigma= C_N-p*N σ=CNpN 。我们将所有检验数小于0的列进基,迭代直至an ==0,此部分完整代码如下:

an = 1
while an >0model = Model(HiGHS.Optimizer)set_silent(model)@variable(model, 0<=x[i in 1:n,j in js[i]]<=1)@info "variable size:",length(x)@objective(model, Min, sum([x[i,j]*distmat[i,j]/2 for i in 1:n for j in js[i]]))c = @constraint(model, [i = 1:n], sum([x[i, j] for j in js[i]]) >= 2)e = @constraint(model, [i = 1:n], sum([x[j, i] for j in js[i]]) >= 2)optimize!(model)@info objective_value(model)p1 = [dual(c[i]) for i in 1:n]p2 = [dual(e[i]) for i in 1:n];an = 0for i in 1:nfor j in setdiff(1:n,js[i])sigma = distmat[i,j]/2 - p1[i]-p2[j]if sigma < 0;push!(js[i],j);push!(js[j],i);an+=2;endendend@info "add size:",an
end

3. 使用行生成添加约束

我们观察att48使用lp求解后的结果:
在这里插入图片描述

有很多子环,需要添加去除环的约束。
首先添加subtour约束,去除所有的子环约束:

using Graphs
paths = strongly_connected_components(SimpleDiGraph(round.(x_val,digits = 2)))
if length(paths)>1for path in paths@constraint(model,sum(x[path,path])<=2*length(path)-2)endoptimize!(model)x_val = round.(JuMP.value.(x),digits = 2)paths = strongly_connected_components(SimpleDiGraph(x_val))
end

迭代求解,并绘制结果如下:
在这里插入图片描述

然后添加comb约束,约束介绍参见《运筹系列65:TSP问题的精确求解法概述》,julia代码参见《运筹系列80: 使用Julia精确求解tsp问题》的4.2节,求解后得到两个comb:
在这里插入图片描述
然后添加进约束,迭代求解:
在这里插入图片描述
迭代得到如下图:
在这里插入图片描述

4. 使用分枝定界求解整数规划问题

我们这里使用priority queue存储分枝节点,按照最简单的下标顺序,对所有非整数变量进行分枝。

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

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

相关文章

计算机视觉的应用13-基于SSD模型的城市道路积水识别的应用项目

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下计算机视觉的应用13-基于SSD模型的城市道路积水识别的应用项目。今年第11号台风“海葵”后部云团的影响&#xff0c;福州地区的降雨量突破了历史极值&#xff0c;多出地方存在严重的积水。城市道路积水是造成交通拥…

javaee之黑马乐优商城2

简单分析一下商品分类表的结构 先来说一下分类表与品牌表之间的关系 再来说一下分类表和品牌表与商品表之间的关系 面我们要开始就要创建sql语句了嘛&#xff0c;这里我们分析一下字段 用到的数据库是heima->tb_category这个表 现在去数据库里面创建好这张表 下面我们再去编…

Unexpected mutation of “xxxx“ prop

原因 是因为子级修改了父级的数据&#xff0c;所以eslint执行的时候报了这个错 修复方式 1 如果是弹窗等组件&#xff0c;可以根据功能进行修改&#xff0c;比如我这块用的 element ui 的 dialog&#xff0c;便可以改成这样 使用 model-value 代替 修复方式 2 新建子组件…

3种等待方式,让你学会Selenium设置自动化等待测试脚本!

一、Selenium脚本为什么要设置等待方式&#xff1f;——即他的应用背景到底是什么 应用Selenium时&#xff0c;浏览器加载过程中无法立即显示对应的页面元素从而无法进行元素操作&#xff0c;需设置一定的等待时间去等待元素的出现。&#xff08;简单来说&#xff0c;就是设置…

CTFSHOW 年CTF

1.除夕 php的弱类型&#xff0c;用小数点绕过 这里后面直接加字母不行 2.初三 error_reporting(0); extract($_GET); include "flag.php"; highlight_file(__FILE__); 这里通过extract将get的参数导入为了变量 $_function($__,$___){return $__$___?$___:$__; }; …

恒运资本:银行股适合定投吗?为什么银行股适合定投?

在股票市场上&#xff0c;出资者能够通过手动不断的买入到达基金定投的效果&#xff0c;那么&#xff0c;银行股适合定投吗&#xff1f;为什么银行股适合定投&#xff1f;下面恒运资本为我们准备了相关内容&#xff0c;以供参考。 银行股适合定投&#xff0c;即通过定投不断的买…

索尼 toio™ 应用创意开发征文|小巧机器,大无限,探索奇妙世界

文章目录 前言微型机器人的未来&#xff1a;toio™小机器人简介toio™小机器人&#xff1a;创新功能一览toio™小机器人&#xff1a;多领域的变革者toio™小机器人贪吃蛇游戏代码实现写在最后 前言 当我们谈到现代科技的创新时&#xff0c;往往会联想到复杂的机器和高级的编程…

Linux CentOS7命令及命令行

Linux CentOS7中命令及命令行是非常重要的概念。对大多数初学者来说是既熟悉又了解甚少。本文初步讨论这方面的内容&#xff0c;与同行者交流。 一、命令 命令又称为指令&#xff0c;&#xff08;英语命令 command&#xff0c;可用简写cmd表示&#xff09;&#xff0c;在终端…

小程序引入高德/百度地图坐标系详解

小程序引入高德/百度地图坐标系详解 官网最近更新时间&#xff1a;最后更新时间: 2021年08月17日 高德官网之在原生小程序中使用的常见问题 链接 目前在小程序中使用 高德地图只支持以下功能 &#xff1a;地址描述、POI和实时天气数据 小结&#xff1a;从高德api中获取数…

不就是G2O嘛

从零开始一起学习SLAM | 理解图优化&#xff0c;一步步带你看懂g2o代码 SLAM的后端一般分为两种处理方法&#xff0c;一种是以扩展卡尔曼滤波&#xff08;EKF&#xff09;为代表的滤波方法&#xff0c;一种是以图优化为代表的非线性优化方法。不过&#xff0c;目前SLAM研究的主…

【学习笔记】C++ 中 static 关键字的作用

目录 前言static 作用在变量上static 作用在全局变量上static 作用在局部变量上static 作用在成员变量上 static 作用在函数上static 作用在函数上static 作用在成员函数上 前言 在 C/C 中&#xff0c;关键字 static 在不同的应用场景下&#xff0c;有不同的作用&#xff0c;这…

老听说企业要做私域运营,那具体如何做呢?

以前企业获得新客户的方式是从各大流量平台进行引流&#xff0c;但现在这些公域平台人力投入和产出的比例不合理&#xff0c;或者费用太高而无法承担。因此&#xff0c;企业需要建立自己的私域流量池&#xff0c;无需付费、随时可接触的私域流量池。 那么&#xff0c;怎么做私域…

NIFI关于Parameter Contexts的使用

说明 nifi版本&#xff1a;1.23.2&#xff08;docker镜像&#xff09; 作用 Parameter Contexts&#xff08;参数上下文&#xff09;&#xff1a;参数上下文由 NiFi 实例全局定义/访问。访问策略可以应用于参数上下文&#xff0c;以确定哪些用户可以创建它们。创建后&#x…

自然语言处理(五):子词嵌入(fastText模型)

子词嵌入 在英语中&#xff0c;“helps”“helped”和“helping”等单词都是同一个词“help”的变形形式。“dog”和“dogs”之间的关系与“cat”和“cats”之间的关系相同&#xff0c;“boy”和“boyfriend”之间的关系与“girl”和“girlfriend”之间的关系相同。在法语和西…

如何让数据成为企业的生产力?

为什么有的企业投入大量的人力、物力、财力做数字化转型建设最终做了个寂寞&#xff01;企业领导没看到数字化的任何价值&#xff01; 如果要问企业数字化转型建设最核心的价值体现是什么&#xff0c;大部分人都会说是&#xff1a;数据&#xff01; 然而&#xff0c;不同的人…

微服务整合Seata1.5.2+Nacos2.2.1+SpringBoot

文章目录 一、Seata Server端1、下载seata server2、客户端配置-application.yml3、初始Mysql数据库4、导入初始配置到nacos5、启动测试 二、Seata Client端搭建1、为示例业务创建表2、业务代码集成 Seata 本文以seata-server-1.5.2&#xff0c;以配置中心、注册中心使用Nacos&…

百度王海峰披露飞桨生态最新成果 开发者数量已达800万

目录 前言文心大模型原生插件机制文心大模型超级助手飞桨开发者数已达800万 模型数超80万星河社区最后 前言 8月16日&#xff0c;由深度学习技术及应用国家工程研究中心举办的WAVE SUMMIT深度学习开发者大会上&#xff0c;位于北京举行。百度的首席技术官兼深度学习技术及应用…

德国金融监管机构网站遭遇大规模DDoS攻击后“瘫痪”

德国波恩的BaFin大楼 BaFin是负责监督和监管德国金融机构和市场的金融监管机构&#xff0c;其职责是确保德国金融体系的稳定性、完整性和透明度。 此外&#xff0c;BaFin 的网站还为企业和消费者提供银行、贷款和财产融资等方面的信息。它还提供消费者帮助热线和举报人信息共…

Java从入门到精通-流程控制(二)

习题讲解&#xff1a; 上次我们给大家留了一些流程控制的问题&#xff0c;这次给大家分析讲解一下&#xff1a; 条件语句练习&#xff1a; 1.编写Java程序&#xff0c;用于接受用户输入的数字&#xff0c;然后判断它是偶数还是奇数&#xff0c;并输出相应的消息。 import ja…