C++ 中的优化问题不会产生与 CPLEX 中相同的结果

问题描述 投票:0回答:1

到目前为止,我直接在 IBM ILOG CPLEX Optimization Studio 中对优化问题进行了建模。

现在,我想在使用 CPLEX API 的同时尝试使用 C++ 来制定模型。

为此,我从一个非常简单的问题开始,只是为了学习 C++ 并感受如何使用 CPLEX API。

问题在 CPLEX 中如下所示:

range j = 1..3;

dvar int+ x[i];
dvar float+ y[j];

maximize -3*x[1] - 2*x[2] + 4*x[3] + y[1] - 3*y[2] - 2*y[3];

subject to {
  c1: -2*x[1] + 4*x[2] - x[3] + 3*y[1] - 2*y[2] + 3*y[3] <= -4;
  c2: -x[1] - 2*x[2] + 4*x[3] + 2*y[1] + 4*y[2] - 5*y[3] <= 2;
  c3: forall(i in i) x[i] <= 6;
}

现在,我只想用 C++ 编写相同的模型。这是我当前的代码:

#include <iostream>
#include "ilcplex//ilocplex.h";
using namespace std;

int main() {

    IloEnv env;
    IloModel Model(env);

    IloIntVar x1(env, 0, IloInfinity, "x1");
    IloIntVar x2(env, 0, IloInfinity, "x2");
    IloIntVar x3(env, 0, IloInfinity, "x3");
    IloNumVar y1(env, 0, IloInfinity, ILOFLOAT, "y1");
    IloNumVar y2(env, 0, IloInfinity, ILOFLOAT, "y2");
    IloNumVar y3(env, 0, IloInfinity, ILOFLOAT, "y3");

    Model.add(IloMaximize(env, -3 * x1 - 2 * x2 + 4 * x3 + y1 - 3 * y2 - 2 * y3));

    Model.add((-2 * x1 + 4 * x2 - x3 + 3 * y1 - 2 * y2 + 3 * y3) <= -4);
    Model.add((-x1 - 2 * x2 + 4 * x3 + 2 * y1 + 4 * y2 - 5 * y3) <= 2);
    Model.add(x1 <= 6);
    Model.add(x2 <= 6);
    Model.add(x3 <= 6);

    IloCplex cplex(Model);

    if (!cplex.solve()) {
        env.error() << "Optimization failed" << endl;
        throw(-1);
    }

    double obj = cplex.getObjValue();
    cout << "\n\n\t objective value: " << obj << endl;  

    cout << "x1 = " << cplex.getValue(x1) << endl;
    cout << "x2 = " << cplex.getValue(x2) << endl;
    cout << "x3 = " << cplex.getValue(x3) << endl;
    cout << "y1 = " << cplex.getValue(y1) << endl;
    cout << "y2 = " << cplex.getValue(y2) << endl;
    cout << "y3 = " << cplex.getValue(y3) << endl;
}

老实说,我已经研究这个有一段时间了,我不明白为什么这两个程序不能产生相同的解决方案。

CPLEX 程序的目标值为 2.429,这是正确的解决方案。 C++程序打印出optimization failed,意思是没有找到解决方案。

有人看到我犯的错误吗?

c++ mathematical-optimization cplex mixed-integer-programming operations-research
1个回答
0
投票

有趣 - 我在 Windows 上使用 CPLEX 20.1 和 VS2022 尝试了此操作,因为无论如何我都需要刷新我的 C++ CPLEX 内容。我同意您上面的代码被报告为不可行,但是下面的一个小更改似乎可以很好地解决:

IloIntVar x1(env, 0, 6, "x1");
IloIntVar x2(env, 0, 6, "x2");
IloIntVar x3(env, 0, 6, "x3");
IloNumVar y1(env, 0, IloInfinity, ILOFLOAT, "y1");
IloNumVar y2(env, 0, IloInfinity, ILOFLOAT, "y2");
IloNumVar y3(env, 0, IloInfinity, ILOFLOAT, "y3");

Model.add(IloMaximize(env, -3 * x1 - 2 * x2 + 4 * x3 + y1 - 3 * y2 - 2 * y3));

Model.add((-2 * x1 + 4 * x2 - x3 + 3 * y1 - 2 * y2 + 3 * y3) <= -4);
Model.add((-x1 - 2 * x2 + 4 * x3 + 2 * y1 + 4 * y2 - 5 * y3) <= 2);
//Model.add(x1 <= 6);
//Model.add(x2 <= 6);
//Model.add(x3 <= 6);

即更改是在声明这些 x 变量时将它们的界限设置为 6,而不是通过约束单独设置。这是修改后模型的输出日志:

Version identifier: 20.1.0.0 | 2020-11-10 | 9bedb6d68
Found incumbent of value -6.000000 after 0.00 sec. (0.00 ticks)
Tried aggregator 1 time.
Reduced MIP has 2 rows, 6 columns, and 12 nonzeros.
Reduced MIP has 0 binaries, 3 generals, 0 SOSs, and 0 indicators.
Presolve time = 0.00 sec. (0.00 ticks)
Tried aggregator 1 time.
Reduced MIP has 2 rows, 6 columns, and 12 nonzeros.
Reduced MIP has 0 binaries, 3 generals, 0 SOSs, and 0 indicators.
Presolve time = 0.00 sec. (0.00 ticks)
MIP emphasis: balance optimality and feasibility.
MIP search method: dynamic search.
Parallel mode: deterministic, using up to 16 threads.
Root relaxation solution time = 0.00 sec. (0.00 ticks)

        Nodes                                         Cuts/
   Node  Left     Objective  IInf  Best Integer    Best Bound    ItCnt     Gap

*     0+    0                           -6.0000                           0.00%
*     0+    0                           -1.9524                           0.00%
      0     0        4.0000     1       -1.9524        4.0000        3  304.88%
*     0+    0                            1.9231        4.0000           108.00%
*     0+    0                            2.2857        4.0000            75.00%
      0     0        2.5000     2        2.2857    MIRcuts: 1        5    9.37%
*     0+    0                            2.4286        2.5000             2.94%
      0     0        cutoff              2.4286                      5     ---
Elapsed time = 0.05 sec. (0.05 ticks, tree = 0.01 MB, solutions = 5)

Mixed integer rounding cuts applied:  1

Root node processing (before b&c):
  Real time             =    0.05 sec. (0.05 ticks)
Parallel b&c, 16 threads:
  Real time             =    0.00 sec. (0.00 ticks)
  Sync time (average)   =    0.00 sec.
  Wait time (average)   =    0.00 sec.
                          ------------
Total (root+branch&cut) =    0.05 sec. (0.05 ticks)


         objective value: 2.42857
x1 = 4
x2 = -0
x3 = 5
y1 = 0.142857
y2 = 0
y3 = 2.85714

我预计这应该在 CPLEX 预求解后生成一个非常相似的模型并给出相同的结果,但它显然做了一些不同的事情。我会将此事报告给 IBM 进行进一步调查。

© www.soinside.com 2019 - 2024. All rights reserved.