基于Cplex的线性规划问题求解(JavaAPI)

Cplex是求解线性/整数规划问题的常用求解器之一(商用),而Java是应用非常广泛的程序开发语言。本文力争通过两个优化实例,描述清楚在Java语言下,如何调用Cplex高效求解线性/整数规划问题。

算例1:线性规划问题(Cplex解题器手册中一个简单例题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

完整代码如下:

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

            // 设定变量上下限
            double[] lb = {0.0, 0.0, 0.0};  // 下限
            double[] ub = {40.0, Double.MAX_VALUE, Double.MAX_VALUE};  // 上限
            IloNumVar[] x = cplex.numVarArray(3, lb, ub);  // 定义优化变量:IloNumVar,3维,以及对应的边界

            // 设定目标函数
            double[] objvals = {1.0, 2.0, 3.0};  // 目标函数系数
            cplex.addMaximize(cplex.scalProd(x, objvals));  // 定义目标函数:addMaximize最大化,scalProd,连乘

            // 设定约束条件
            double[] coeff1 = {-1.0, 1.0, 1.0};  // 第一组约束条件的系数
            double[] coeff2 = {1.0, -3.0, 1.0};  // 第二组约束条件的系数
            cplex.addLe(cplex.scalProd(x, coeff1), 20.0);  // 定义第一组约束条件的系数,addLe(a,b):a小于等于b
            cplex.addLe(cplex.scalProd(x, coeff2), 30.0);  // 定义第二组约束条件的系数

            // 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:整数规划问题

a = [ 8 7 9 4 5 8 0 7 4 4 4 3 3 8 7 7 0 10 8 7 1 1 0 2 8 ] a=\begin{bmatrix} 8 & 7 & 9 & 4 & 5\\ 8 & 0 & 7 & 4 & 4\\ 4 & 3 & 3 & 8 & 7\\ 7 & 0 & 10 & 8 & 7\\ 1 & 1 & 0 & 2 & 8\\ \end{bmatrix} a= 88471703019731004488254778 b = [ 3 5 8 10 9 7 10 2 6 2 7 3 5 1 8 1 6 7 1 2 1 2 9 2 10 ] b=\begin{bmatrix} 3 & 5 & 8 & 10 & 9\\ 7 & 10 & 2 & 6 & 2\\ 7 & 3 & 5 & 1 & 8\\ 1 & 6 & 7 & 1 & 2\\ 1 & 2 & 9 & 2 & 10\\ \end{bmatrix} b= 3771151036282579106112928210
存在以上两个二维矩阵,要求分别从两个矩阵中的每一行,选出一个元素,使得总的数值最小化,约束条件为a和b中,相同行所选定的元素对应的列,也要相同。

min ⁡ ∑ i = 0 4 ( a i j x i j + b i j y i j ) subject to x i j = y i j , ∀ i , j ∑ j = 0 4 x i j = 1 , ∀ i ∑ j = 0 4 y i j = 1 , ∀ i \begin{align} \min \quad & \sum_{i=0}^{4}{(a_{ij}x_{ij}+b_{ij}y_{ij})} \\ \text{subject to} \quad & x_{ij}=y_{ij}, \quad \forall i,j \\ \quad & \sum_{j=0}^4x_{ij}=1 ,\quad \forall i \\ \quad & \sum_{j=0}^4y_{ij}=1 ,\quad \forall i \end{align} minsubject toi=04(aijxij+bijyij)xij=yij,i,jj=04xij=1,ij=04yij=1,i

完整代码如下:

    public static void main(String[] args) {
        int[][] a = {
                {8, 7, 9, 4, 5},
                {8, 0, 7, 4, 4},
                {4, 3, 3, 8, 7},
                {7, 0, 10, 8, 7},
                {1, 1, 0, 2, 8}
        };
        int[][] b = {
                {3, 5, 8, 10, 9},
                {7, 10, 2, 6, 2},
                {7, 3, 5, 1, 8},
                {1, 6, 7, 1, 2},
                {1, 2, 9, 2, 10}
        };
        try {
            // 声明cplex优化模型
            IloCplex model = new IloCplex();

//             定义两个二维优化变量
            IloIntVar[][] x = new IloIntVar[5][5];
            for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 5; j++) {
                    x[i][j] = model.intVar(0, 4, "x[" + i + "," + j + "]");
                }
            }
            IloIntVar[][] y = new IloIntVar[5][5];
            for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 5; j++) {
                    y[i][j] = model.intVar(0, 4, "y[" + i + "," + j + "]");
                }
            }
            
            // 定义目标函数
            IloLinearNumExpr objExpr = model.linearNumExpr();
            for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 5; j++) {
                    objExpr.addTerm(a[i][j], x[i][j]);
                    objExpr.addTerm(b[i][j], y[i][j]);
                }
            }
            model.addMinimize(objExpr);

            // 定义约束条件
            for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 5; j++) {
                    // 第一组约束
                    model.addEq(x[i][j], y[i][j]);
                }
                // 第二组约束
                model.addEq(model.sum(x[i]), 1);
                model.addEq(model.sum(y[i]), 1);
            }

            // 优化计算,输出最优解
            if (model.solve()) {
                System.out.println("最优解为:" + model.getObjValue());
                for (int i = 0; i < 5; i++) {
                    for (int j = 0; j < 5; j++) {
                        System.out.println("x[" + i + "," + j + "]: " + model.getValue(x[i][j]));
                    }
                }
            }

            // 退出优化模型
            model.end();

        } catch (IloException e) {
            throw new RuntimeException(e);
        }
    }

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值