JAVA for Cplex(更新版)
一、Cplex的介绍
Cplex是一种专门用来求解大规模线性规划问题的求解工具。不仅仅是LP问题,对于二次规划 QP,二次有约束规划QCP,混合整数线性规划MIP问题,甚至Network Flow问题,都是很
好的求解工具。官网https://www.ibm.com/cn-zh/products/ilog-cplex-optimization-studio中有关于Cplex简单的介绍。Cplex的优势在于:
1、 能解决一些非常困难的行业问题;
2、 求解速度非常快。
3、 在Cplex的支持下,使得matlab对于大规模的问题,以及线性规划的效率都有很多大的提升。
二、Cplex的使用环境
本文中以eclipse为开发环境,代码的是使用java语言。
三、Cplex的简单案例。
3.1 Cplex求解器的构成。
先看一个官网给的例子。
代码:
'''
public class MyTest {
/**
* obj = x1 + 5x2 + 1x3
* -x1 + x2 + x3 <=56;
* x1 - 3x2 + x3 <= 39;
* 0 <= x1 <= 40;
* 0 <= x2, x3
* @throws IloException
*/
public static void main(String[] args) throws IloException {
IloNumVarType varType = IloNumVarType.Float;
int varNum = 3;
IloCplex cplex = new IloCplex();
//决策变量申明
IloNumVar [] vars = new IloNumVar[varNum];
double[] xishu = new double[]{1,5,1};
double[] mins = new double[]{0,0,0};
double[] maxs = new double[]{30,Double.MAX_VALUE,Double.MAX_VALUE};
for (int i = 0; i < vars.length; i++) {
vars[i] = cplex.numVar(mins[i], maxs[i],varType);
}
//目标函数
cplex.addMaximize(cplex.scalProd(vars, xishu));
//约束条件
cplex.addLe(cplex.sum(cplex.prod(1.0, vars[0]), cplex.prod(1.0, vars[1]), cplex.prod(1.0,vars[2])), 56);
cplex.addLe(cplex.sum(cplex.prod(1.0, vars[0]), cplex.prod(-3.0, vars[1]), cplex.prod(1.0,vars[2])), 39);
if(cplex.solve()){
cplex.output().println("Solution status = " + cplex.getStatus());
cplex.output().println("Solution value = " + cplex.getObjValue());
double[] val = cplex.getValues(vars);
int ncols = cplex.getNcols();
for (int j = 0; j < ncols; ++j)
cplex.output().println("Column: " + j + " Value = " + val[j])
}
cplex.end();}
运行结果:
以上代码实现了求目标函数在不等式约束条件下的最优解。由运行结果可以看出该线性规划问题的最优值是280,最优解x1,x2,x3的值分别是0,56,0。
总结一下,Cplex求解器的构成主要有三大部分:(1)决策变量的定义;(2)目标函数的形式;(3)约束条件的表达。这三部分是我们需要关注的重点,如果正确地表达出来,那
么我们便能利用Cplex求解任何的线性规划问题。简单地介绍一下,代码中IloNumVar [] vars = new IloNumVar[varNum];这里定义的是一个连续变量的数组,数组大小为
varNum。数组中存放的是决策变量x1,x2,x3. cplex.addMaximize()方法用于输入目标函数的形式,比如obj = 1x1 + 5x2 + 1*x3,我们可以这样表达
cplex.addMaximize(cplex.scalProd(vars, xishu));其中,cplex.scalProd()是一个先乘后加的方法。对于约束条件而言,不等式约束常常用cplex.addLe()方法。
四、Cplex的使用
4.1 变量定义
● IloNumVar(IloIntVar) :模型需要求解的决策变量。
eg:创建三个连续(离散)变量,lb和ub是变量取值的上限和下限。
IloNumVar[] x = cplex.numVarArray(3, lb, ub);
● IloNumExpr(IloIntExpr):模型的中间变量。通常是关于决策变量的表达式。
eg: 对于x0 + 2x1+3x2,cplex中写为:
IloNumExpr expr = cplex.sum(x[0], cplex.prod(2.0, x[1]),cplex.prod(3.0, x[2]))。
● IloRange : 模型的变量的约束范围。cplex.addLe()和cplex.addEq()的返回值.通常在添加约束的时候用到。
eg: 形如 lb <= expr <= ub,cplex.addLe(10, x1)表示的就是x1>=10。cplex.addEq(double arg0,IloNumExpr arg1): 返回值为IloRange,即arg0<=arg1<=arg0。也
就是arg1的值取值为arg0,相当于赋了一个常数。
● IloObjective :模型的优化目标。cplex.addMaximize()和cplex.addMinimize()的返回值。
eg : 最小化(最大化)目标函数。对于求表达式x1 + 2x2 + 3x3的最小值,cplex中写为(一种写法):
cplex.addMinimize(cplex.sum(x1,cplex.prob(2,x2),cplex.prob(3,x3))).另一种写法:double[] objvals = {1.0, 2.0, 3.0};
cplex.addMinimize(cplex.scalProd(x, objvals))。
4.2 常用方法
● 加法:cplex.sum();
● 减法:cplex.diff();
● 乘法:cplex.prod();
● 除法:cplex.prod();计算除法的方法和乘法的一致,也就是将除法转化为乘法。比如C=A/B就可以转化为A=B*C.
● 累加求和:cplex.scalProd(INumExpr[], double[]);有关括号里的参数类型需要根据具体问题具体分析。
eg:对于x1+2x2+3x3+4x4,cplex中写为:
double[] objvals = {1.0, 2.0, 3.0,4.0};
IloIntVar[]x=cplex.intVarArray(4,lb1,ub1);
cplex.scalProd(x, objvals);
● 平方cplex.square();
● 创建一个0-1变量:cplex.boolVar();
eg:若想定义一个取值为0或1的变量,cplex写为:IloIntVar y=cplex.boolVar();此时y的取值只能是0或1。
● 创建一个数组:cplex.numVarArray(),类似的还有,cplex.intVarArray(),cplex.boolVarArray,cplex.numExprArray()等等;
eg:创建一个包含8个变量的数组,上限为lb,下限为ub、cplex中写为:
IloNumVar[] x = cplex.numVarArray(8, lb, ub);
4.3约束方程的表达
● 不等式约束cplex.addLe();
eg: 对于不等式约束-x[0] + x[1] + x[2] <= 20.0,cplex中写为:
cplex.addLe(cplex.sum(cplex.negative(x[0]), x[1], x[2]), 20);
● 等式约束 cplex.addEq();
eg: 对于等式约束x0==x1,则可以用cplex.addEq(x0,x1)。
● cplex能接受的非线性表达式
1、 min和minl:多个数字表达式的最小值;
2、 max和maxl:多个数字表达式的最大值;
3、 abs:数字表达式的绝对值;
● 线性表达式:cplex.linearNumExpr();
eg: 创建一个线性表达式,求出一数组所有元素的总和。cplex写为:IloNumVar [][] x=new IloNumVar [][] x=new IloNumVar[20][30];
for(int i=0; i < 10; i++) {
IloLinearNumExpr summer=cplex.linearNumExpr();//默认为null.
for(int j=0; j < 10; j++) {
summer.addTerm(1.0, x[i][j]);
}
IloRange con = cplex.addEq(summer, 1);
con.setName("yourConstraintName(" + i + ")");
}
4.4数字表达式的分段线性组合
分段线性函数的表达:cplex.pieceiwiseLinear()
eg:表示一个分段线性函数:当x<=100,斜率为1;100<=x<=200,斜率为2;x>200,斜率为-3。代码实现:
IloNumVar x=cplex.numVar(-Double.MAX_VALUE, Double.MAX_VALUE);//定义一个实数范围内的x
double [] points={100,200};//两个分割点
double []slopes={1,2,-3};//斜率
IloNumExpr fx=cplex.piecewiseLinear(x1, points, slopes, 0, 300);
4.5求解模型
● IloCplex.solve():精确求解
● IloCplex.solveRelaxed():松弛求解
● IloCplex.getStatus():针对于模型无界或者不可行的情况,可调用该方法得到模型解的状态。
4.6输出格式
● cplex.output().println():cplex中的打印格式。
eg:
cplex.output().println("Solution status = " + cplex.getStatus());
cplex.output().println("Solution value = " + cplex.getObjValue());
● cplex.getObjValue(): 得到目标函数的最值。
● cplex.getValue(): 得到最优目标函数值所对应的最优解x,即决策变量的值。
● cplex.getstatus(): 返回optimal或者其他情况。
4.7 常见的异常
● java.lang.NullPointerException:空指针异常
空指针就是空引用,java空指针异常就是引用本身为空,却调用了方法,这个时候就会出现空指针异常。因为我们在定义一个中间变量IloNumExpr的时候,我们没有对其初始化,又
因该表达式默认是为null,所以,我们有必要为此类变量指定其存储数据的上下限。否则就会产生空指针异常。通常的做法是创建两个变量,一个作为下限,一个作为上限。指定上
限和下限的值,并令上文提到的变量处于上限和下限之间即可。举个例子,以下代码定义了EES_t数组变量的上下限变量lEES_t,uEES_t。然后指定其值分别是0,1000。最后通过
cplex.numVarArray()方法使得数组变量EES_t存储数据的取值范围处于0~1000。
int R1,R2=10;
double[][] lEES_t = new double[R1][R2];
double[][] uEES_t = new double[R1][R2];
for (int i = 0; i < R1; i++) {
for (int j = 0; j < R2; j++) {
lEES_t[i][j] = 0;
uEES_t[i][j] = 1000;
}
}
for (int i=0; i<R1; i++) {
EES_t[i] = cplex.numVarArray(R2, lEES_t[i], uEES_t[i]);
}
五、小结
对比于lingo,Yalmip,guaobi,Cplex展现出了其独特的优势,比如运行速度快,在求解大规模问题上略胜一筹。它提供了python,java,c++等各大编程软件的API,是一款值得一用
的工具。关于Cplex建模的问题,当我们将实际问题建模,并转化为数学公式后,然后将公式写入Cplex的搭好的框架中,求解就很简单了。对于不同的线性或是非线性规划问题模
型,Cplex会依据目标函数的形式以及约束方程去判断模型是属于哪一种规划问题,这一方面显示出了其独特的优势。但Cplex也并非有足够地智能。当我们发现编译通过了,但是求
解的结果是不可行(不可行指的是不存在满足所有约束、界限和整数性限制的解)或者无界(无界指的是可以使目标函数任意大)的状态时,优化器只会告知不可行,我们往往不知道
不可行性的原因是什么。对于小型的模型而言,通过调参排查问题可以解决,但是对于大型的模型,一步一步排查约束条件,变量的范围是否规范等等就会显得力不从心了。当然,
Cplex仍然是一个很强大的工具,有待开发和利用。
六、相关资源
Cplex的官方链接如下:
这里包含更加全面的文档资源,供我们参考学习。另外还有运筹优化技术论坛:
]()https://www.optimize.fun/forum.php?mod=forumdisplay&fid=53。
里面有很多的Cplex环境配置问题以及开发中可能会遇到的技术问题的探讨与解答。覆盖的领域范围也比较广泛,涉及交通物流,电力,供应链等等经典的优化问题。
JAVA for Cplex(更新版)的更多相关文章
- 探索Antlr(Antlr 3.0更新版)
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明 http://www.blogbus.com/dreamhead-logs/10756716.html <探索Antlr> ...
- Rsession让Java调用R更简单
Rsession让Java调用R更简单 R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大. R语言作为统计学一门语言,一直在小众领域闪耀着光芒. ...
- Windows 7 Ultimate(旗舰版)SP1 32/64位官方原版下载(2011年5月12日更新版)
MSDN于2011年5月12日,最新发布简体中文Windows 7 Ultimate 旗舰版 SP1 DVD镜像安装包,分32位和64位两个版本.最新发行代号分别是:677486(32位),67740 ...
- 微软开放技术发布针对 Mac 和 Linux 的更新版 Azure Node.JS SDK 和命令行工具
发布于 2013-12-04 作者 Eduard Koller 这次为我们使用Linux 的朋友带来了更多关于部署云上虚拟机的消息.今天,微软开放技术有限公司 (MS Open Tech),想与大家分 ...
- (转载)Windows 7 Ultimate(旗舰版)SP1 32/64位官方原版下载(2011年5月12日更新版)
MSDN于2011年5月12日,最新发布简体中文Windows 7 Ultimate 旗舰版 SP1 DVD镜像安装包,分32位和64位两个版本.最新发行代号分别是:677486(32位),67740 ...
- macOs升级到10.13.1Beta || JAVA升级到最新版之后PhpStorm菜单栏问题
macOs升级到10.13.1Beta || JAVA升级到最新版之后PhpStorm菜单栏会消失,估计不止出现在PhpStorm,一系列jetbrains的产品可能都会有这个问题,包括eclipis ...
- 最简单的基于FFmpeg的视频编码器-更新版(YUV编码为HEVC(H.265))
===================================================== 最简单的基于FFmpeg的视频编码器文章列表: 最简单的基于FFMPEG的视频编码器(YUV ...
- Elasticsearch .net client NEST使用说明 2.x -更新版
Elasticsearch .net client NEST使用说明 目录: Elasticsearch .net client NEST 5.x 使用总结 elasticsearch_.net_cl ...
- Win 10更新版1709有哪些新功能值得关注!
windows 10秋季创意者更新版1709发布已经有段时间了,也有很多用户选择升级这次更新的系统.那么,这次Win 10 更新版1709有哪些新功能值得关注呢?下面,一起随主机吧来看一看吧! 1. ...
- 胡小兔的NOIP2017游记【出成绩后更新版】
胡小兔的NOIP2017游记[出成绩后更新版] 2017.11.22 Update 前几天成绩出来啦,看这篇博客访问量还挺多的,下面就分享一下结果吧: 我的Day1T2和Day2T1两道最水的题都跪了 ...
随机推荐
- mysql数据库慢SQL优化
mysql数据库慢SQL优化优化来源: 阿里云 云数据库RDS 慢sql 或者CAT监控系统中的Transaction SQL or URL根据平均时间反馈来排查,决定是否增加索引,或者调整业务逻辑代 ...
- error while loading shared libraries: liblzma.so.5: cannot open shared object file: No such file or directory
CentOS6安装mongo报错 error while loading shared libraries: liblzma.so.5: cannot open shared object file: ...
- 初学者必读:如何使用 Nuxt 中间件简化网站开发
title: 初学者必读:如何使用 Nuxt 中间件简化网站开发 date: 2024/6/24 updated: 2024/6/24 author: cmdragon excerpt: 本文概述了N ...
- Netty(一)IO模型
1. Netty介绍 Netty 是由JBOSS提供的一个Jave开源框架,是一个异步地.基于事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络IO程序. Netty主要针对在TCP协议下,面向 ...
- JDK各个版本汇总
JDK1.4 正则表达式,异常链,NIO,日志类,XML解析器,XLST转换器 JDK1.5 自动装箱.泛型.动态注解.枚举.可变长参数.遍历循环 JDK1.6 提供动态语言支持.提供编译API和卫星 ...
- 在IDEA中找不到Mapper报错
前言 相信大多数互联网公司的持久层框架都是使用 Mybatis 框架,而大家在 Service 层引入自己编写的 Mapper 接口时应该会遇到下面的情况: 我们可以看到,上面的红色警告在提示我们,找 ...
- Solo 开发者周刊 (第 1 期):开源产品的探索之路
产品推荐 如何着手将一个简单的想法转变为一个成熟的开源项目,以及如何在此过程中利用和贡献于开源社区.同时使其达到商业化的同时,保持原有的开源精神.这些是我们需要探索的. Spug 开源运维平台 Spu ...
- CGI,FastCGI和PHP-FPM之间的关系和区别
什么是CGI?早期的web server只可以处理简单的静态web文件,但是随着技术的发展出现动态语言如PHP,Python.PHP语言交给PHP解析器进行处理,但是处理之后如何和web server ...
- django信号中的条件判断不符合时如何提示错误并返回
在Django中,如果你在信号(Signal)处理函数中需要进行条件判断,如果条件不符合,你可以触发一个异常,并在视图或其他地方捕获这个异常,然后返回相应的错误提示. 以下是一个简单的例子,演示如何在 ...
- BigDecimal的精度与刻度
BigDecimal是Java中用于高精度算术运算的类.当您需要精确地处理非常大或非常小的数字时,例如在金融计算中,它特别有用.由于众所周知得原因,Double这种类型在某些情况下会出现丢失精度的问题 ...