【CPLEX教程03】java调用cplex求解一个TSP问题模型
00 前言
前面我们已经搭建好cplex的java环境了,相信大家已经跃跃欲试,想动手写几个模型了。今天就来拿一个TSP的问题模型来给大家演示一下吧~
CPLEX系列教程可以关注我们的公众号哦!获取更多精彩消息!

01 TSP建模
关于TSP建模,就不多解释了。以及什么是TSP问题,也不要问我了。直接贴一个现成的模型出来吧。

02 程序框架
整个程序框架如图,app下是调用cplex的主要package。

其中:
- App.java:程序入口,cplex调用建模求解过程。
- ConstraintFactory.java:控制子环约束的。
- FileManager.java:读取instance数据的。
package graph定义了一些变量,在求解过程中需要用到。input是算例,包含100-9000个城市。
03 求解过程
求解过程可以分为以下几步进行:
- 定义一个模型
IloCplex model = new IloCplex();
- 定义决策变量,boolVar可以返回一个01的bool类型决策变量。
// define variables
IloIntVar[][] x = new IloIntVar[data.size()][data.size()];
for (int i = 0; i < x.length; i++) {
for (int j = 0; j < x.length; j++) {
x[i][j] = model.boolVar("X[" + i + ", " + j + "]");
}
}
- 添加约束7-1,addTerm将1*x[i][j]添加进表达式r里面,最终r的取值是里面所有的元素之和,也就是\(1*x[i][1]+1*x[i][2]+...+1*x[i][n]\)。
// one has only a city to go, and should
for (int i = 0; i < x.length; i++) {
IloLinearIntExpr r = model.linearIntExpr();
for (int j = 0; j < x.length; j++) {
// if (i == j)
// continue;
r.addTerm(1, x[i][j]);
}
model.addEq(r, 1);
}
- 添加约束7-2,原理同上一条。
// one can only arrive to one city at a time, and should
for (int j = 0; j < x.length; j++) {
IloLinearIntExpr r = model.linearIntExpr();
for (int i = 0; i < x.length; i++) {
// if (i == j)
// continue;
r.addTerm(1, x[i][j]);
}
model.addEq(r, 1);
}
- 添加约束7-3,子环约束处理有点复杂,但这个不是本文重点,读者自行理解。
// add cycle restrictions
for (Stack<Edge> stack : stacks) {
// stack.forEach((edge) -> System.out.println(edge.getFrom() + "->" + edge.getTo()));
constraintFactory.cycleRestrictions(model, x, stack);
}
- 添加目标函数,z的表达式同上。
// one should complete the tour within the smallest distance possible
IloLinearNumExpr z = model.linearNumExpr();
for (int i = 0; i < x.length; i++) {
for (int j = 0; j < x.length; j++) {
if (i == j)
continue;
z.addTerm(distance[i][j], x[i][j]);
}
}
- 确定目标是最小化目标
model.addMinimize(z);
- 开始求解
if (model.solve()) {
// get tour
for (int i = 0; i < x.length; i++) {
for (int j = 0; j < x.length; j++) {
if (model.getValue(x[i][j]) >= 0.5) {
tour.add(new Edge(i, j));
}
}
}
// repaint tour
} else {
System.err.println("Boi, u sick!");
System.exit(1);
}
注意,一次求解不一定能求得最优解,小编跑了一个早上都跑不出来,还是100个节点的。model.getValue(x[i][j]) >= 0.5这个判断只是把求解过程中一些较好的边给添加进去而已。最优解是要满足所有约束的。
04 运行说明
代码下载请关注我们的公众号哦!后台回复【CPTSP】不包括【】即可下载。

代码来源GitHub,小编去掉了部分代码。期待后期进一步精简和修改,大家下载下来后用eclipse导入,设置好cplex环境以后。在App.java里面,右键Run As->Run configurations...:

找到App,在Arguments窗口,找到Program arguments:

输入参数说明:
--instancePath+空格+算例文件的路径,注意用英文双引号括起来。
--maximumRead+空格+数字,表示算例大小,也就是多少个城市,文件名可以直接看出。
然后就可以愉快的run了。
附上运行结果:

大家可以在while(count<1)这个条件里面更改迭代次数,以便能获取更好的解。
【CPLEX教程03】java调用cplex求解一个TSP问题模型的更多相关文章
- 【CPLEX教程02】配置Cplex的Java环境以及API说明
00 前言 因为小编一般用的C++和Java比较多,而且现在开发大型算法用这类面向对象的编程语言也方便得多.基于上面的种种考虑,加上时间和精力有限,所以就暂时只做C++和Java的详细教程辣.关于ma ...
- 代码 | 用ALNS框架求解一个TSP问题 - 代码详解
写在前面 前面好多篇文章,我们总算是把整个ALNS的代码框架给大家说明白了.不知道大家对整个框架了解了没有.不过打铁要趁热,心急了要吃热豆腐.今天就来实战一下,教大家怎么用ALNS的代码框架,求解一个 ...
- 机器学习——Java调用sklearn生成好的Logistic模型进行鸢尾花的预测
机器学习是python语言的长处,而Java在web开发方面更具有优势,如何通过java来调用python中训练好的模型进行在线的预测呢?在java语言中去调用python构建好的模型主要有三种方法: ...
- 零基础大数据入门教程:Java调用阿里云短信通道服务
这里我们使用SpringBoot 来调用阿里通信的服务. 阿里通信,双11.收到短信,日发送达6亿条.保障力度非常高. 使用的步骤: 1.1. 第一步:需要开通账户 1.2. 第二步:阅读接口文档 1 ...
- Java-Runoob-高级教程-实例-字符串:03. Java 实例 - 删除字符串中的一个字符
ylbtech-Java-Runoob-高级教程-实例-字符串:03. Java 实例 - 删除字符串中的一个字符 1.返回顶部 1. Java 实例 - 删除字符串中的一个字符 Java 实例 以 ...
- [Java 教程 03] 我的第一个Java程序
现在,大家应该都已经安装好jdk环境了吧!是不是已经跃跃欲试,按耐不住心中的小激动了?那我们现在就来写我们java学习生涯中的第一个java程序. 文件相关设置 为了方便后面大家的学习呢?有一点大家还 ...
- Java-Runoob-高级教程-实例-方法:03. Java 实例 – 汉诺塔算法-un
ylbtech-Java-Runoob-高级教程-实例-方法:03. Java 实例 – 汉诺塔算法 1.返回顶部 1. Java 实例 - 汉诺塔算法 Java 实例 汉诺塔(又称河内塔)问题是源 ...
- java接口调用——webservice就是一个RPC而已
很多新手一听到接口就蒙逼,不知道接口是什么!其实接口就是RPC,通过远程访问别的程序提供的方法,然后获得该方法执行的接口,而不需要在本地执行该方法.就是本地方法调用的升级版而已,我明天会上一篇如何通过 ...
- 分享:写了一个 java 调用 C语言 开发的动态库的范例
分享:写了一个 java 调用 C语言 开发的动态库的范例 cfunction.h 代码#pragma once#ifdef __cplusplusextern "C" {#e ...
随机推荐
- Redis 多级缓存架构和数据库与缓存双写不一致问题
采用三级缓存:nginx本地缓存+redis分布式缓存+tomcat堆缓存的多级缓存架构 时效性要求非常高的数据:库存 一般来说,显示的库存,都是时效性要求会相对高一些,因为随着商品的不断的交易,库存 ...
- Redis cluster的核心原理分析
一.节点间的内部通信机制 1.基础通信原理 (1)redis cluster节点间采取gossip协议进行通信 跟集中式不同,不是将集群元数据(节点信息,故障,等等)集中存储在某个节点上,而是互相之间 ...
- Ambari深入学习(III)-开源使用及其改进思考
Ambari采用的不是一个新的思想和架构,也不是完成了软件的新的革命,而是充分利用了一些已有的优秀开源软件,巧妙地把它们结合起来,使其在分布式环境中做到了集群式服务管理能力.监控能力.展示能力.这些优 ...
- java基础 String
标准格式:数据类型[] 数组名称 = new 数据类型[] {元素1,元素2,...};省略格式:数据类型[] 数组名称 = {元素1,元素2,...}; Scanner类实现的功能,可以实现键盘输入 ...
- 2019-07-24 PHP中mysql_fetch_assoc 和 mysql_fetch_array 有什么区别?
mysql_fetch_assoc() 函数从结果集中取得一行作为关联数组 来看下面的例子: 数据库中有上述几条数据,一般我们想取用就要按照如下代码: $con = mysql_connect('12 ...
- 使用vue-router在页面之间传值及接收值
第一页 点击去第二页的时候进行传值直接贴代码看: <template> <div id="app"> <div><router-link ...
- MySQL CentOS7 手动安装
手动安装MySQL的目的: 1.一个服务器上可以同时装多个版本,甚至相同版本MySQL的多个实例,这种需求很常见: 2.一次初始化和配置后,可以快速复制到本服务器或其他服务器,及封装为初始MySQL的 ...
- Java 读取控制台输入
方式1:InputStreamReader+BufferedReader package my_package; import java.io.BufferedReader; import java. ...
- httpclient工具类,post请求发送json字符串参数,中文乱码处理
在使用httpclient发送post请求的时候,接收端中文乱码问题解决. 正文: 我们都知道,一般情况下使用post请求是不会出现中文乱码的.可是在使用httpclient发送post请求报文含中文 ...
- element中日期时间插件(DateTimePicke) el-date 开始时间大于等于当前时间小于结束时间,结束时间大于开始时间且大于当前时间
pickerOptions1: { disabledDate: time => { if (this.endTime) { return ( time.getTime() > new Da ...