CPLEX - Добавление отложенных ограничений с переменными различного типа приводит к InvalidCutException - PullRequest
1 голос
/ 28 марта 2020

Я решаю модель, которая имеет два типа переменных: x [i] [j] - ILOBOOL, а u [i] - ILOFLOAT. Я пытаюсь добавить ленивые ограничения к этой модели. Мне удалось правильно добавить ленивые ограничения следующим образом:

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

Этот код работает нормально, и когда я печатаю .lp, ленивые ограничения присутствуют. Однако, когда я изменяю IloConstraint edge_con(x[i][j] + x[j][i]<= 1); на IloConstraint edge_con(x[i][j] + x[j][i] + u[j] <= 1);, я получаю сообщение InvalidCutException: invalid cut -1. Почему выбрасывается это исключение?

1 Ответ

1 голос
/ 02 апреля 2020

Превращение моего комментария в ответ: проблема в том, что CPLEX не знает о u переменных, на которые ссылаются в ленивом ограничении.

Если вы добавите регулярное ограничение, тогда все переменные в ограничении автоматически извлекаются в CPLEX. Однако для ленивых ограничений все иначе: переменные не извлекаются автоматически. Таким образом, если ленивое ограничение ссылается на переменную, которая ранее не использовалась в обычном ограничении или цели, то CPLEX не будет знать об этой переменной. Это приведет к невозможности добавить вырезку, и вы получите исключение, которое вы наблюдали.

Чтобы исправить это, явно добавьте переменные u к проблеме, используя

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

(и может сделать то же самое для x переменных)

...