arreldemerts
arreldemerts

Reputation: 21

Adding constraints to a CPLEX model in C++

I'm coding a MILP in C++ by using the CPLEX library and I am having problems when adding the constraints to the model. The code is quite long, so here I just include the general structure of the code and one of the constraints (and the variables involved).

#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();

}

When running the code I get the following error message:

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

Does anyone know what's wrong with the definition of the constraints in this way? I tried the same way for simpler problems and it worked.

Thanks!

Upvotes: 1

Views: 1691

Answers (3)

arreldemerts
arreldemerts

Reputation: 21

Thanks for your help, finally I could figure out what was wrong. Basically, the initialization of the variables was not correct, because I was not adding them to the model. For instance, the definition of the U variable should be as follows:

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);
}

After changing the initialization of the variables the constraints worked as they should, so the problem is fixed.

Upvotes: 1

serge_k
serge_k

Reputation: 1782

First, I would recommend to use IloNumVarArray instead of IloFloatVarArray. In general it should be initialized as IloNumVarArray(const IloEnv env,IloNum lb,const IloNumArray ub,IloNumVar::Type type=ILOFLOAT), but if your variables are continuous and between 0 and infinity, then just use:

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);
    }
}

Second, are chi, beta, lambda, p constants or variables? If they are constants then it's bad idea to use IloExpr to sum them up, regular float type should work fine. If they are declared as IloNumArray's then IloSum(const IloNumArray values) can sum up lambda and p for you:

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

or if this doesn't work define one-dimensional IloNumArray's lambda_l[l] and p_l[l] via lambda and p.

Upvotes: 1

Ram Narasimhan
Ram Narasimhan

Reputation: 22516

It may not even be the constraints. As the error text says, you are getting an exception, but you are not catching it. Therefore, the program terminates.

First, you should wrap your code inside a try/catch block:

Conceptually,

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

That should tell you what the exact nature of the exception is. There are multiple reasons for that ILOG error (could be some invalid parameters, low memory or expired license among other things) and printing it out should help.

If that fails, you will have to step through your code with a debugger to see where it is breaking and why.

Upvotes: 1

Related Questions