CPLEX 初识 -- JAVA实现

news/2024/9/21 10:38:24

CPLEX 初识 -- JAVA实现

本文参考《运筹优化常用模型、算法及案例实战》,同时也是笔者用来记录自己所学知识,如有问题欢迎交流讨论~

1 环境配置&模型建立

需要装配jar包及配置VM options, 如下图所示:

-Djava.library.path="/Applications/CPLEX_Studio2211/java"

一般使用IloCplex model = new IloCplex(); //建立cplex对象新建模型

2 变量

        //变量类型
//        IloNumVarType.Bool;
//        IloNumVarType.Int;
//        IloNumVarType.Float;//创建变量
//        model.numVar(lb, ub, type, name); //一般变量创建方法
//        model.intVar(); //创建整数变量
//        model.boolVar(); //创建0-1变量//        model.numVarArray(); //以数组形式创建一般变量
//        model.intVarArray(); //以数组形式创建整数变量
//        model.boolVarArray(); //以数组形式创建0-1变量

3 表达式

通常由两种方法:

  • 表达式较为简单时,可以使用基本的IloModeler中的方法(例如加、减、乘、数量积等)定义。注:IloCplexs已继承该接口,故可以直接通过IloCplexs对象进行调用。
//常用表达式
//        model.sum();
//        model.prod();
//        model.scalProd(); //数组与数组之间的数量积
//        model.diff();
//        model.negative(); //乘以-1
//        model.square(); //表达式的square
  • 表达式略复杂时,使用IloNumExpr 接口IloLinearNumExpr接口中的方法定义。

4 范围约束

使用IloRange对象表示形如lb <= expression <= ub的约束。

//        IloRange rng1 = model.range(lb, expr, ub, name); //表示lb<=expr<=ub
//        IloRange rng2 = model.le(expr, ub, name); //表示 expr <= ub ~ 也可直接model.addLe();
//        IloRange rng3 = model.ge(expr, lb, name); //表示 expr >= lb ~ 也可直接model.addGe();

5 目标函数

//        IloObjective obj = model.addMaximize(expr); //方式一
//        IloObjective obj = model.add(model.maximize(expr)); //方式二

6 建模方式

该部分通过一个简单的案例,主要介绍两种建模方式:行建模与列建模

案例:在已知各种Food所含Nutrition的前提下,各样Food需买多少,以满足营养需求及各类容量约束。信息见下表:

Food 1 Food 2 Nutrition最小需求量 Nutrition最大需求量
Nutrition 1 $$a_{11}$$ $$a_{12} $$ nutrMin[1] nutrMax[1]
Nutrition 2 $$a_{21}$$ $$a_{22}$$ nutrMin[2] nutrMax[2]
Food最小数量 foodMin[1] foodMax[1]
Food最大数量 foodMin[2] foodMax[2]
Food单位成本 foodCost[1] foodCost[2]

该表使用数据结构的方式编写如下:

private static class Data {int nFoods; //Food总种类 ~ 决定了几个决策变量int nNutrs; //Nutrition总种类 ~ 决定了m条约束int[] foodMin; //各样food的最小数量int[] foodMax; //各样food的最大数量float[] foodCost; //各样food的成本int[] nutrMin; //各样Nutrition的最小需求量int[] nutrMax; //各样Nutrition的最大需求量int[][] a_ij; //Food j中含有Nutrition i的数量// 以下是constructorpublic Data(int[] foodMin, int[] foodMax, float[] foodCost, int[] nutrMin, int[] nutrMax, int[][] a_ij) {this.foodMin = foodMin;this.foodMax = foodMax;this.foodCost = foodCost;this.nutrMin = nutrMin;this.nutrMax = nutrMax;this.a_ij = a_ij;this.nFoods = foodMin.length;this.nNutrs = nutrMin.length;}
}

6.1 行建模

  • 决策变量为:\(buy[j]\)表示\(Food[j]\)买多少,是整数变量。
  • 约束条件:
    • \(Nutrition[j],j\in\{1,2,...,m\}\) 最小满足量和最大满足量要求;即 \(nutrMin[i] \leq\sum_j a_{ij}*buy_j \leq nutrMax[i], \forall i\in\{1,2,...,m\}.\)
    • \(Food[j],j\in\{1,2,...,n\}\)最小数量和最大数量要求。(可以在创建变量时直接添加)
  • 目标函数:成本最低。
// (1)行建模
static void buildModelByRow(Data data) throws IloException {// 新建模型IloCplex model = new IloCplex();// 变量: buy[j] j \in {1,2,...,nFoods}int nFoods = data.nFoods; //变量个数IloNumVar[] buy = new IloNumVar[nFoods]; //创建变量数组,下对变量进行具体创建for (int j = 0; j < nFoods; j++) {buy[j] = model.numVar(data.foodMin[j], data.foodMax[j], IloNumVarType.Int, "buy_j");}// 约束条件int nNutrs = data.nNutrs;for (int i = 0; i < nNutrs; i++) {IloLinearNumExpr expr = model.scalProd(data.a_ij[i], buy); //\sum_j a_ij*buy_jmodel.addRange(data.nutrMin[i],expr,data.nutrMax[i]);}// 目标函数model.addMinimize(model.scalProd(data.foodCost,buy));
}

6.2 列建模

​ 按列添加本质上是添加变量,在添加的过程中需要考虑:1. 对目标函数的影响。2. 对约束的影响。实现过程如下:

  1. 使用model.column(IloObjective,coefficient)向该列添加对应的目标函数系数,返回一个列对象col1
  2. 使用model.column(IloRange constraint[i],double val)向该列添加对应的约束的系数,同样返回一个列对象col2
  3. 之后通过col = col1.and(col2)将两列对象进行”连接“,完成对目标函数和约束的更新。
  4. 使用model.numVar(IloColunmn col, double lb, double ub, IloNumVarType type)为以上创建的列col设置对应的变量(其中需要输入上下界及变量类型)。
// (2)列建模
static void buildModelByColumn(Data data) throws IloException {// 新建模型IloCplex model = new IloCplex();// 创建m条约束 和 n个变量int nNutrs = data.nNutrs;IloRange[] constraints = new IloRange[nNutrs]; // m条约束IloNumVar[] buys = new IloNumVar[data.nFoods]; // n个变量for (int i = 0; i < nNutrs; i++) { // 对约束设置上下界constraints[i] = model.addRange(data.nutrMin[i],data.nutrMax[i]);}// 向约束和目标函数中加入对应的系数,并创建变量IloObjective cost = model.addObjective(null);for (int j = 0; j < data.nFoods; j++) { //加n条列IloColumn col_j = model.column(null); //j对应的列对象,后需要由obj+cons合成IloColumn col_obj = model.column(cost, data.foodCost[j]);for (int i = 0; i < nNutrs; i++) {IloColumn col_constaints_i = model.column(constraints[i], data.a_ij[i][j]);col_j = col_obj.and(col_constaints_i);}// 对新加的列 创建变量buys[j] = model.numVar(col_j, data.foodMin[j], data.foodMax[j]);}
}

6.3 案例练习

编译实现如下线性规划:

\[\begin{alignat}{2} \max \quad &x_1+2x_2+3x_3 \tag{1} \\ \mbox{s.t.}\quad &-x_1+x_2+x_3\leq 20 \tag{2}\\ &x_1-3x_2+x_3\leq30 \tag{3} \\ &0\leq x_1\leq40, x_2,x_3\geq 0. \tag{4} \end{alignat} \]

代码如下:

//3 案例练习
static void practice() throws IloException {// 创建模型, 输入系数IloCplex model = new IloCplex();double[] obj_coeffs = {1.0, 2.0, 3.0};double[] v_lb = {0.0, 0.0, 0,0};double[] v_ub = {40.0, Double.MAX_VALUE, Double.MAX_VALUE};// Step1 变量String[] x_name = {"x_1","x_2","x_3"};IloNumVar[] x = model.numVarArray(3, v_lb, v_ub,x_name);// Step2 约束int m = 2; //两条约束double[][] a = {{-1, 1, 1}, {1, -3, 1}}; //变量前系数 A = [a_ij]double[] b = {20,30};for (int i = 0; i < m; i++) {model.addLe(model.scalProd(a[i],x),b[i]);}// Step3 目标函数model.addMaximize(model.scalProd(obj_coeffs,x));
}

7 模型求解及输出

7.1 求解

model.solve()

7.2 解状态

IloCplex.Status status = model.getStatus();
System.out.println(status);

解类型如下:

  • Bounded
  • Unbounded
  • Feasible
  • Infeasible
  • InfeasibleOrUnbounded
  • Error
  • Unknown
  • Optimal

7.3 获取obj、变量、约束相关信息

(1)获取obj_value

double objValue = model.getObjValue();
System.out.println("obj_value = " + objValue);

(2)获取变量值:单个/多个

double x_0_value = model.getValue(x[0]);//获取单个变量值
System.out.println("x_0 = " + x_0_value);double[] x_values = model.getValues(x);//获取多个变量值for (int i = 0; i < x_values.length; i++) {System.out.println("x_" + i + " = " + x_values[i]);}

(3)获取变量对应的reduced cost

double[] reducedCosts = model.getReducedCosts(x);
System.out.print("Reduced Costs = ");
for (double r_c: reducedCosts) {System.out.print(r_c + "  ");
}
System.out.println();

(4)获取约束对应的松弛变量

double[] slacks = model.getSlacks(consts);
System.out.print("Slack Variables = ");
for (double s : slacks) {System.out.print(s + "  ");
}
System.out.println();

(5)获取约束对应的对偶变量

double[] duals = model.getDuals(consts);
System.out.print("Dual Variables = ");
for (double d : duals) {System.out.print(d + "  ");
}
System.out.println();

(6)获取模型/对偶模型的极射线

//        model.getRay();
//        model.dualFarkas();

(7)模型导出导入

model.exportModel("practice.lp"); //导出
model.importModel("practice.lp"); //导入

运行结果如下:

模型导出结果:

8 参数

官方介绍:https://www.ibm.com/docs/zh/icos/12.10.0?topic=cplex-list-parameters

此处待补充具体常用参数。(后续补充)

写在最后

Like a city that is broken down and without walls is a man whose spirit is without restraint.

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

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

相关文章

VMware产品最新下载地址

好像被博通收购后好多被搜索引擎收录的地址都失效了 可以到博通网站的这个页面去下载,好像需要注册登录,国内QQ邮箱也能注册成功 https://support.broadcom.com/group/ecx/downloads

WPF使用Shape实现复杂线条动画

看到巧用 CSS/SVG 实现复杂线条光效动画的文章,便也想尝试用WPF的Shape配合动画实现同样的效果。ChokCoco大佬的文章中介绍了基于SVG的线条动画效果和通过角向渐变配合 MASK 实现渐变线条两种方式。WPF中的Shape与SVG非常相似,因此这种方式也很容易实现。但WPF中仅有的两种渐…

maven打包失败

问题: 用maven命令打包java应用jar包时打包失败,显示错误“找不到符号”,但是具体的代码中没有找到错误 解决方法: 如果打包的应用为子应用,需要到父应用中打包

EBS 可保留量(Quantity Available To Reserve) 异常 -- 子库间的转移

1、出现可保留量数量为0或者不不相等的情况 2、查看子库状态的生效状态 3、从新跑请求:保留接口管理器4、最后可用量就出来了本文来自博客园,作者:Iven_lin,转载请注明原文链接:https://www.cnblogs.com/ivenlin/p/18192660

IceRPC之调用管道Invocation pipeline与传出请求Outgoing request-快乐的RPC

作者引言 .Net 8.0 下的新RPC很高兴啊,我们来到了IceRPC之调用管道 Invocation pipeline与传出请求 Outgoing request->快乐的RPC, 基础引导,让自已不在迷茫,快乐的畅游世界。调用管道 Invocation pipeline了解如何发送请求requests和接收响应responses。定义 发送请求并…

LCD屏显示练习【二】

本次习题主要是了解开机动画与触屏切换界面的相关原理,为后续的项目实现打下基础目录题目题目分析思路解析知识点涉及代码展示优化思考问题一:观察界面切换效果,可明显观察到界面切换时有明显的刷新效果,有点影响使用效果问题二:图片的按键位置不能相近或者重合,否则有误…

.net DataGirdView 通过列索引修改单元格字体

场景是这样、我需要DataGirdView某几列数量大于0字体就变成蓝色,某几列超过标准值字体就变成红色具体列名属性void InitCols(){var col = _DataGridView.BuildCol<DataGridViewTextBoxColumn>(dgvDetail, "OrderNo", " 工单号");col.Width = 125;//…

原型设计软件对比以及介绍项目EventSphere原型设计方案

一、介绍项目的原型设计方案 项目名称:EventSphere EventSphere 旨在建立一个全面的、多维度的学生活动发布平台,涉及不仅是面对面的实体活动,还包括虚拟活动的体验,如虚拟现实(VR)活动。该平台计划提供以下功能:用户注册与登录 :允许学生、教师和活动组织者创建账户并登…