在 C++ 中向 CPLEX 模型添加约束

Adding constraints to a CPLEX model in C++

我正在使用 CPLEX 库在 C++ 中编写 MILP,但在向模型添加约束时遇到问题。代码比较长,这里只包含代码的大致结构和其中一个约束条件(以及涉及的变量)。

#include <iostream>
#include <fstream>
#include <cmath>
#include <vector>
#include <string>
#include "ilcplex/ilocplex.h"

using namespace std;

ILOSTLBEGIN

int main(){

    //CPLEX environment and definition of the modelling object
    IloEnv env;
    IloModel model(env);

    //Define the multi dimensional arrays for float and bool variables
    typedef IloArray<IloBoolVarArray> BoolVar2D;
    typedef IloArray<IloFloatVarArray> FloatVar2D;
    typedef IloArray<IloArray<IloBoolVarArray> > BoolVar3D;
    typedef IloArray<IloArray<IloFloatVarArray> > FloatVar3D;
    typedef IloArray<IloArray<IloArray<IloBoolVarArray> > > BoolVar4D;

    //Definition of the variable involved in the constraint
    FloatVar3D U(env, I); //all alternatives except the opt-out
    for(int i=0; i < I; i++){
        U[i] = FloatVar2D(env, N);
        for(int n=0; n < N; n++){
            U[i][n] = IloFloatVarArray(env, R);
        }
    }

    //Construction of the constraint (chi, beta, lambda, p are parameters)
    for(int i =0; i < I; i++){
        for(int n=0; n < N; n++){
            int L_in = L[i][n];
            for(int r=0; r < R; r++){
                IloExpr sum(env);
                sum += chi[i][n][r];
                for(int l=0; l < L_in; l++){
                    sum += beta[i][n] * lambda[i][n][l] * p[i][n][l];
                }
                model.add(U[i][n][r] == sum);
            }
        }
    }

    env.end();

}

当运行代码我得到以下错误信息:

libc++abi.dylib: terminating with uncaught exception of type IloWrongUsage

有谁知道这样定义约束有什么问题吗?我尝试了同样的方法来解决更简单的问题并且它奏效了。

谢谢!

它甚至可能不是约束。正如错误文本所说,您遇到了异常,但您没有捕捉到它。因此,程序终止。

首先,您应该将代码包装在 try/catch 块中:

概念上,

int main()
{
    try
    {
        // your variable definition and constraint code
    }
    catch ( IloException& e )
    {
        std::cout << e << std::endl;
        e.end();
    }
}

这应该告诉您异常的确切性质是什么。 ILOG 错误有多种原因(可能是一些无效参数、内存不足或许可证过期等),将其打印出来应该会有所帮助。

如果失败,您将不得不使用调试器单步执行代码以查看它在哪里出错以及原因。

首先,我建议使用 IloNumVarArray 而不是 IloFloatVarArray。一般应该初始化为IloNumVarArray(const IloEnv env,IloNum lb,const IloNumArray ub,IloNumVar::Type type=ILOFLOAT),但是如果你的变量是连续的,并且在0到无穷大之间,那么就用:

typedef IloArray<IloNumVarArray> twoDarray;
for(int i=0; i < I; i++){
    U[i] = twoDarray(env, N);
    for(int n=0; n < N; n++){
        U[i][n] = IloNumVarArray(env, R);
    }
}

其次,chi, beta, lambda, p是常量还是变量?如果它们是常量,那么使用 IloExpr 来总结它们是个坏主意,常规 float 类型应该可以正常工作。如果它们被声明为 IloNumArray,那么 IloSum(const IloNumArray values) 可以为您总结 lambda 和 p:

model.add(U[i][n][r] == chi[i][n][r] + beta[i][n] * IloSum( lambda[i][n][l]* p[i][n][l]));

或者如果这不起作用通过 lambda 和 p.

定义一维 IloNumArray 的 lambda_l[l] 和 p_l[l]

感谢您的帮助,我终于弄清楚出了什么问题。基本上,变量的初始化不正确,因为我没有将它们添加到模型中。比如U变量的定义应该是这样的:

typedef IloFloatVarArray NumVar1D;
typedef IloArray<IloFloatVarArray> NumVar2D;
typedef IloArray<IloArray<IloFloatVarArray> > NumVar3D;

NumVar3D U(env);
for(int i=0; i < I; i++){
    NumVar2D Ui(env);
    for(int n=0; n < N; n++){
        NumVar1D Uin(env);
        for(int r=0; r<R; r++){
            Uin.add(IloFloatVar(env));
        }
        Ui.add(Uin);
    }
    U.add(Ui);
}

更改变量的初始化后,约束正常工作,因此问题已解决。