基于Cplex求解器的JavaAPI语法使用

文章详细介绍了如何使用Cplex求解器的JavaAPI来构建和解决线性规划问题。包括声明模型、定义不同类型的决策变量(浮点型、整型、0-1型)、建立表达式、添加约束和目标函数,以及获取求解结果的步骤。此外,还讨论了按行和按列两种建模方法。
摘要由CSDN通过智能技术生成

一、Cplex求解器的JavaAPI语法

1、声明求解模型

首先声明求解模型:

IloCplex model = new IloCplex();

2、定义决策变量(IloNumVar)

2.1 定义一个浮点型的决策变量

通过"IloNumVarType.Float"表示连续变量:

// 定义一个浮点型的决策变量
IloNumVar x = model.numVar(lb, ub, IloNumVarType.Float, "x");
  • lb:lower bound,变量的下届
  • ub:upper bound,变量的上届
  • 变量类型: IloNumVarType.Float:连续变量
  • “x”:变量的名字,可选择的项

2.2 定义整形决策变量

整形变量通过IloNumVarType.Int表示,语法如下:

// 写法1:定义一个整型的决策变量
IloNumVar x = model.numVar(0, 10, IloNumVarType.Int, "x");

// 写法2:以上写法等价于如下写法,从源码来看,model.intVar()方法内部还是调用了model.numVar()方法,因此两种写法等价,但此时不在需要传参IloNumVarType.Int:
IloIntVar x = model.intVar(0, 10, "x");

2.3 定义0-1决策变量

0-1变量通过IloNumVarType.Bool进行定义:
0-1决策变量,本质上还是整形变量,因此根据上面写法有:

IloNumVar x = model.numVar(0.0, 1.0, IloNumVarType.Bool);

还有另一种简单写法,即boolVar()方法,查看源码,内部也是对numVar()方法的调用。

IloNumVar x = model.boolVar();

2.4 定义多个决策变量

需要一下子定义多个变量,如需要解决10名护士未来7天3班倒的排班问题,需定义 x i j k ∈ { 0 , 1 } x_{ijk} \in \{0,1\} xijk{0,1},=1表示第i名护士在第j天上k班次,就需要按如下方式定义:

IloNumVar[][][] x = new IloNumVar[10][7][3];
for (int i = 0; i < 10; i++) {
	for (int j = 0; j < 7; j++) {
		for (int k = 0; k < 3; k++) {
			x[i][j][k] = model.boolVar();
		}
	}
}

对于所有这些构造方法,还存在用于一次性创建完整的建模变量数组的等效方法。这些方法称为 numVarArray、intVarArray 和 boolVarArray。

IloNumVar[] x = cplex.numVarArray(3, lb, ub, varname);  // 定义优化变量:IloNumVar,3维,以及对应的边界

3、建立表达式(IloNumExpr)

表达式可以用来构建约束和目标函数。

IloNumExpr expr = cplex.sum(x1, cplex.prod(2.0, x2));

常用方法除sum外,还有proddiffnegativesquare
建立线性表达式时,可以使用更方便的IloLinearNumExpr:

IloLinearNumExpr lin = cplex.linearNumExpr();
for (int i = 0; i < num; ++i)
    lin.addTerm(value[i], variable[i]);

上面for循环是数字的标量乘积(scalar product of an array),可利用scalProd方法重新写为:

IloLinearNumExpr lin = cplex.scalProd(value, variable);

4、约束条件(IloRange)

添加约束的形式如下:

IloRange rng = cplex.range(lb, expr, ub, "name");

当确定了表达式(expression)和右端项(rhs),可以使用IloModeler直接创建范围约束,如expr ≤ 1.0可以通过如下形式创建:

IloRange le = cplex.le(expr, 1.0);

5、目标函数(IloObjective)

目标函数表达式是IloNumExpr,目标函数构造器如下:

IloObjective obj = cplex.objective(sense, expr, name);

其中:

  • sense 是IloObjectiveSense类型,可以去两个值:IloObjectiveSense.Maximize or IloObjectiveSense.Minimize.
  • expr 是IloNumExpr类型
  • name:目标函数名称,String类型

为方便起见,提供了 Maximize 和 Minimize 方法来分别创建最大化或最小化目标,而不使用 IloObjectiveSense 参数,目标函数对象的名称是可选的。

IloObjective obj = cplex.add(cplex.maximize(expr));

6、获取求解结果

  • 通过调用 cplex.solve()判断模型是否求解成功, 当返回 true 时,求解成功,但找到的解决方案可能不是最优的,例如,优化可能会因为遇到迭代限制而提前终止,此时可以使用返回 IloCplex.Status 对象的 getStatus 方法查询求解状态。
  • 通过double objval = cplex.getObjValue();获取目标函数值。
  • 通过double x1 = cplex.getValue(var1);获取决策变量的值,通常,需要一次性获取所有决策变量的解,无需实现循环,只需调用一个函数即可使用double[] x = cplex.getValues(vars);方法来完成此操作。
  • 使用方法 IloCplex.getSlack 或 IloCplex.getSlacks 获取模型中约束的松弛值。

二、使用Cplex求解线性规划问题

运筹优化求解器构模模型并求解的基本步骤如下:

  1. 创建求解模型
  2. 添加模型参数
  3. 构建规划模型:
    • 添加决策变量
    • 添加约束条件
    • 设置目标函数
  4. 设置求解参数并求解
  5. 获取求解结果

Cplex提供的例题,在C:\Users\Username\Documents\IBM\ILOG\CPLEX_Studio1263\cplex\examples\src\java\LPex1.java路径下
max ⁡ x 1 + 2 x 2 + 3 x 3 subject to − x 1 + x 2 + x 3 ≤ 20 x 1 − 3 x 2 + x 3 ≤ 30 0 ≤ x 1 ≤ 40 , x 2 , x 3 ≥ 0 \begin{align} \max \quad & x_1+2x_2+3x_3 \\ \text{subject to} \quad & -x_1+x_2+x_3 \leq 20 \\ \quad & x_1-3x_2+x_3 \leq 30 \\ \quad & 0 \leq x_1 \leq40,x_2,x_3\geq0 \end{align} maxsubject tox1+2x2+3x3x1+x2+x320x13x2+x3300x140,x2,x30

Cplex对于模型构建有两种视角:

  • 可以按行建模,首先输入变量,然后添加对变量和目标函数的约束。
  • 通过构造一系列空约束,然后将变量插入到约束和目标函数中,可以按列对问题进行建模。

事实上,甚至可以在同一个程序中混合使用这两种方法.在列生成算法中,需要迭代寻找新的变量,加入到约束中,就可以使用按列建模(Modeling by columns)

2.1按行建模(build by rows)

import ilog.concert.IloException;
import ilog.concert.IloNumVar;
import ilog.cplex.IloCplex;

public class Main {
    public static void main(String[] args) {
        // cplex求解,一般都使用try...catch...
        try {
            // 1、声明cplex优化模型
            IloCplex cplex = new IloCplex();
            System.out.println(cplex);

            // 2、模型参数
            double[] lb = {0.0, 0.0, 0.0};  // 下限
            double[] ub = {40.0, Double.MAX_VALUE, Double.MAX_VALUE};  // 上限
            String[] varname = {"x1", "x2", "x3"};
            double[][] coeff = {
                    {-1.0, 1.0, 1.0},
                    {1.0, -3.0, 1.0}
            };  // 约束条件的系数

            double[] objvals = {1.0, 2.0, 3.0};  // 目标函数系数

            double[] rhs = {20.0, 30.0};
            // 3、模型
            // 添加决策变量
            IloNumVar[] x = cplex.numVarArray(3, lb, ub, varname);  // 定义优化变量:IloNumVar,3维,以及对应的边界
            // 设定约束条件
            for (int i = 0; i < coeff.length; i++) {
                cplex.addLe(cplex.scalProd(coeff[i], x), rhs[i]);
            }

            // 设定目标函数
            cplex.addMaximize(cplex.scalProd(x, objvals));  // 定义目标函数:addMaximize最大化,scalProd,连乘

            // 5、cplex.solve():模型求解
            if (cplex.solve()) {
                // cplex.output(),数据输出,功能类似System.out.println();
                cplex.output().println("Solution status = " + cplex.getStatus());  // cplex.getStatus:求解状态,成功则为Optimal
                // cplex.getObjValue():目标函数的最优值
                cplex.output().println("Solution value = " + cplex.getObjValue());
                // cplex.getValues(x):变量x的最优值
                double[] val = cplex.getValues(x);
                for (int j = 0; j < val.length; j++)
                    cplex.output().println("x" + (j + 1) + "  = " + val[j]);
            }
            // 退出优化模型
            cplex.end();

        } catch (IloException e) {
            System.err.println("Concert exception caught: " + e);
        }
    }

}

2.2按列建模(build by columns)

在现有模型中插入一个新的决策变量(Modeling by Column,列生成)。
如:IloColumn col = cplex.column(obj, 1.0).and(cplex.column(rng, 2.0));
在目标函数加入决策变量系数为1.0,约束中加入决策变量系数为2.0
增加该决策变量取值范围:IloNumVar var = cplex.numVar(col, 0.0, 1.0);

import ilog.concert.*;
import ilog.cplex.IloCplex;

public class ByCol {
    public static void main(String[] args) throws IloException {

        IloCplex model = new IloCplex();

        IloObjective obj = model.addMaximize();

        IloRange[] rng = new IloRange[2];

        rng[0] = model.addRange(-Double.MAX_VALUE, 20.0, "c1");
        rng[1] = model.addRange(-Double.MAX_VALUE, 30.0, "c2");

        IloRange r0 = rng[0];
        IloRange r1 = rng[1];

        IloNumVar[] x = new IloNumVar[3];
        x[0] = model.numVar(model.column(obj, 1.0).and(model.column(r0, -1.0).and(model.column(r1, 1.0))), 0.0, 40.0, "x1");
        x[1] = model.numVar(model.column(obj, 2.0).and(model.column(r0, 1.0).and(model.column(r1, -3.0))), 0.0, Double.MAX_VALUE, "x2");
        x[2] = model.numVar(model.column(obj, 3.0).and(model.column(r0, 1.0).and(model.column(r1, 1.0))), 0.0, Double.MAX_VALUE, "x3");

        if (model.solve()) {
            // cplex.output(),数据输出,功能类似System.out.println();
            model.output().println("Solution status = " + model.getStatus());  // cplex.getStatus:求解状态,成功则为Optimal
            // cplex.getObjValue():目标函数的最优值
            model.output().println("Solution value = " + model.getObjValue());
            // cplex.getValues(x):变量x的最优值
            double[] val = model.getValues(x);
            for (int j = 0; j < val.length; j++)
                model.output().println("x" + (j + 1) + "  = " + val[j]);
        }
        // 退出优化模型
        model.end();
    }
}

参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值