首页 > 解决方案 > CPLEX - Adding Lazy Constraints with variables of different type lead to InvalidCutException

问题描述

I'm solving a model that has two types of variables, x[i][j] is a ILOBOOL and u[i] is a ILOFLOAT. I'm trying to add lazy constraints to this model. I've managed to correctly add lazy constraints in the following fashion:

std::stringstream name;
IloNumVar** x = new IloNumVar*[ins.n+1];
for(int i = 0; i < ins.n+1; ++i){
    x[i] = new IloNumVar[ins.n];
    for(int j = 0; j < ins.n; ++j){
        if(ins.has_edge(i,j) || i == ins.n){
            name << "x_" << i << "_" << j;
            x[i][j] = IloNumVar(env,0,1,ILOBOOL, name.str().c_str());
            name.str("");
        }
    }
}

IloNumVar* u = new IloNumVar[ins.n+1];
for(int i = 0; i < ins.n+1; ++i){
    name << "u_" << i;
    u[i] = IloNumVar(env,(i < ins.n) ? 1 : 0,ins.L+1,ILOFLOAT,name.str().c_str());
    name.str("");
}
/*Objective function and some other non-lazy Constraints
*/
cplex.extract(model);
for(int i = 0; i < ins.n; ++i){
    for(int j = 0; j < ins.n; ++j){
        if(ins.has_edge(i,j)){
            IloConstraint edge_con(x[i][j] + x[j][i]<= 1);
            name << "edge_" <<i << "_" << j;
            edge_con.setName(name.str().c_str());
            name.str("");
            try{
                cplex.addLazyConstraint(edge_con);
            }catch(IloCplex::InvalidCutException& ex){
                auto con = ex.getCut();
                std::cout << ex.getMessage() << " " << ex.getStatus();
                std::cout << con << "\n";
            }
        }
    }
}

This code is working fine and when I print the .lp, the lazy constraints are there. However, when I change IloConstraint edge_con(x[i][j] + x[j][i]<= 1); to IloConstraint edge_con(x[i][j] + x[j][i] + u[j] <= 1); I get an InvalidCutException: invalid cut -1 message. Why this exception is being thrown?

标签: c++cplex

解决方案


Turning my comment into an answer: The problem is that CPLEX does not know about the u variables that are referenced in the lazy constraint.

If you add a regular constraint then all variables in the constraint are automatically extracted to CPLEX. For lazy constraints things are different though: the variables are not automatically extracted. So if the lazy constraint references a variable that was not used in a regular constraint or the objective before, then CPLEX will not know about this variable. This will result in failure to add the cut and you will get the exception you observed.

To fix this, explicitly add the u variables to the problem using

for (i = 0; i < ins.n+1; ++i)
    model.add(u[i]);

(and maybe do the same for the x variables)


推荐阅读