Java调用CPLEX官方示例——Blend.java

混合问题是混合整数线性规划 (MILP) 的典型应用。
这些涉及混合多个资源或物料以创建应对需求的一种或多种产品。
混合整数线性规划是要求一些变量采用整数值的线性规划。
此类规划的求解方法与整数规划相同。 分支定界算法可以利用线性松弛;其分支过程仅适用于整数变量。

金属混合问题

金属混合示例涉及混合一些金属以制造合金。 金属可能来自多个来源:纯金属、原材料、先前混合物的废料或铸块。 根据指定合金中每种金属数量下限和上限的生产约束的表述,合金必须包含特定量的各种金属。 每个来源都有一定的成本,问题涉及在最大程度地减少成本并满足生产约束的同时混合各个来源。 其他领域(例如,油、涂料和食品加工行业)中也存在类似问题。

/* --------------------------------------------------------------------------
 * Problem Description
 * -------------------
 * Goal is to blend four sources to produce an alloy: pure metal, raw materials, scrap, and ingots.
 * 
 * Each source has a cost.
 * Each source is made up of elements in different proportions.
 * Alloy has minimum and maximum proportion of each element.
 * 
 * Minimize cost of producing a requested quantity of alloy.
 */ 

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

public class Blend{
   static int    _nbElements = 3; //纯金属
   static int    _nbRaw = 2;  //原料
   static int    _nbScrap = 2;  //废料
   static int    _nbIngot = 1;   //铸块
   static double _alloy = 71.0;  //合金
  
   //成本
   static double[] _cm = {22.0, 10.0, 13.0};
   static double[] _cr = {6.0, 5.0};
   static double[] _cs = {7.0, 8.0};
   static double[] _ci = {9.0};
   //各元素中含纯金属比例的上下限
   static double[] _p  = {0.05, 0.30, 0.60};
   static double[] _P  = {0.10, 0.40, 0.80};
   
   //比例
   static double[][] _PRaw = {{0.20, 0.01},
                              {0.05, 0.00},
                              {0.05, 0.30}};
   static double[][] _PScrap = {{0.00, 0.01},
                                {0.60, 0.00},
                                {0.40, 0.70}};
   static double[][] _PIngot = {{0.10},
                                {0.45},
                                {0.45}};
   

   public static void main( String[] args ) {
      try {
         IloCplex cplex = new IloCplex();
       
         //定义决策变量
         IloNumVar[] m = cplex.numVarArray(_nbElements, 0.0, Double.MAX_VALUE);
         IloNumVar[] r = cplex.numVarArray(_nbRaw, 0.0, Double.MAX_VALUE);
         IloNumVar[] s = cplex.numVarArray(_nbScrap, 0.0, Double.MAX_VALUE);
         IloNumVar[] i = cplex.numVarArray(_nbIngot, 0.0, Double.MAX_VALUE);
         IloNumVar[] e = new IloNumVar[_nbElements];
       
         // 目标函数:最小化成本
         cplex.addMinimize(cplex.sum(cplex.scalProd(_cm, m),
                                     cplex.scalProd(_cr, r),
                                     cplex.scalProd(_cs, s), 
                                     cplex.scalProd(_ci, i)));  
       
         // 合金中各元素的最小量和最大量
         for (int j = 0; j < _nbElements; j++) {
            e[j] = cplex.numVar(_p[j] * _alloy, _P[j] * _alloy);
         }
       
         // 约束条件:生产一定数量的合金
         cplex.addEq(cplex.sum(e), _alloy);
       
         // 约束条件:满足合金元素数量要求
         for (int j = 0; j < _nbElements; j++) {
            cplex.addEq(e[j],
                        cplex.sum(m[j],
                                  cplex.scalProd(_PRaw[j], r),
                                  cplex.scalProd(_PScrap[j], s),
                                  cplex.scalProd(_PIngot[j], i)));
         }
       
         if (cplex.solve()) {
            if (cplex.getStatus().equals(IloCplex.Status.Infeasible)) {
               System.out.println("No Solution");
               return;
            }
            System.out.println("Solution status: " + cplex.getStatus());        
            double[] mVals = cplex.getValues(m);
            double[] rVals = cplex.getValues(r);
            double[] sVals = cplex.getValues(s);
            double[] iVals = cplex.getValues(i);
            double[] eVals = cplex.getValues(e);
            
            // 输出结果
            System.out.println("Cost:" + cplex.getObjValue());  //成本

            System.out.println("Pure metal:");  //纯金属
            for(int j = 0; j < _nbElements; j++)
               System.out.println("(" + j + ") " + mVals[j]);

            System.out.println("Raw material:");  //原料
            for(int j = 0; j < _nbRaw; j++)
               System.out.println("(" + j + ") " + rVals[j]);

            System.out.println("Scrap:");  //废料
            for(int j = 0; j < _nbScrap; j++)
               System.out.println("(" + j + ") " + sVals[j]);

            System.out.println("Ingots:");  //铸块
            for(int j = 0; j < _nbIngot; j++)
               System.out.println("(" + j + ") " + iVals[j]);

            System.out.println("Elements:");  //元素含量
            for(int j = 0; j < _nbElements; j++)
               System.out.println("(" + j + ") " + eVals[j]);
         }
         cplex.end();
      }
      catch (IloException exc) {
         exc.printStackTrace();
      }
   }
}

运行结果

Tried aggregator 1 time.
LP Presolve eliminated 0 rows and 2 columns.
Reduced LP has 4 rows, 9 columns, and 16 nonzeros.
Presolve time = 0.00 sec. (0.00 ticks)
Initializing dual steep norms . . .

Iteration log . . .
Iteration:     1   Dual objective     =           486.857143
Solution status: Optimal
Cost:653.5541362530414
Pure metal:
(0) 0.0
(1) 0.0
(2) 0.0
Raw material:
(0) 0.0
(1) 0.0
Scrap:
(0) 17.05900243309003
(1) 30.231143552311437
Ingots:
(0) 32.476885644768856
Elements:
(0) 3.5500000000000003
(1) 24.85
(2) 42.6

参考网址:
https://www.ibm.com/docs/zh/icos/12.8.0.0?topic=programming-blending-problems
https://www.ibm.com/docs/zh/icos/12.8.0.0?topic=cplex-java-examples

注: 代码可从“CPLEX安装路径\cplex\examples\src\java\Blend.java”中查到

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
CPLEX是一款高效的数学优化求解器,可以用来求解各种类型的优化问题,包括车辆路径规划问题(CVRP)。Java可以通过JNI(Java Native Interface)技术来调用C++编写的CPLEX库,从而实现对CVRP问题的求解。 以下是一个简单的Java调用CPLEX求解CVRP问题的示例代码: ```java import ilog.concert.*; import ilog.cplex.*; public class CVRP { public static void main(String[] args) { try { // 创建Cplex对象 IloCplex cplex = new IloCplex(); // 创建变量 int n = 10; // 节点数 int m = 3; // 车辆数 double[][] d = new double[n][n]; // 距离矩阵 IloIntVar[][] x = new IloIntVar[n][n]; // x[i][j]表示从i到j是否有路径 IloIntVar[] u = new IloIntVar[n]; // u[i]表示第i个节点的负荷 for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { x[i][j] = cplex.boolVar(); } u[i] = cplex.intVar(0, 10000); // 假设每个节点的最大负荷为10000 } // 添加约束 for (int i = 1; i < n; i++) { IloLinearNumExpr expr1 = cplex.linearNumExpr(); for (int j = 0; j < n; j++) { if (j != i) { expr1.addTerm(1.0, x[i][j]); } } cplex.addEq(expr1, 1.0); // 每个节点只能被访问一次 IloLinearNumExpr expr2 = cplex.linearNumExpr(); for (int j = 0; j < n; j++) { if (j != i) { expr2.addTerm(1.0, x[j][i]); } } cplex.addEq(expr2, 1.0); // 每个节点只能从一个节点到达 cplex.addLe(u[i], m); // 每个车辆的最大负荷不能超过车辆数 } for (int j = 0; j < n; j++) { IloLinearNumExpr expr3 = cplex.linearNumExpr(); for (int i = 0; i < n; i++) { if (i != j) { expr3.addTerm(1.0, x[i][j]); } } cplex.addEq(expr3, 1.0); // 每个节点只能到达一次 } for (int i = 1; i < n; i++) { for (int j = 1; j < n; j++) { if (i != j) { cplex.addLe(cplex.sum(u[j], cplex.prod(-1, u[i]), cplex.prod(n - 1, x[i][j])), n - 2); // 车辆容量约束 } } } // 添加目标函数 IloLinearNumExpr obj = cplex.linearNumExpr(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i != j) { obj.addTerm(d[i][j], x[i][j]); } } } cplex.addMinimize(obj); // 求解问题 cplex.solve(); // 输出结果 System.out.println("Objective value = " + cplex.getObjValue()); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i != j && cplex.getValue(x[i][j]) > 0.9) { System.out.println("Vehicle " + (i + 1) + " -> " + (j + 1)); } } } // 释放资源 cplex.end(); } catch (IloException e) { e.printStackTrace(); } } } ``` 这段代码实现了一个简单的CVRP求解过程,其中包括创建变量和约束、设置目标函数、求解问题以及输出结果。需要注意的是,在实际的CVRP问题中,还需要考虑许多其他因素,如时间窗口、多重配送等,需要根据实际情况进行相应的调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

予安qy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值