混合问题是混合整数线性规划 (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”中查到