Я пишу MILP в C ++ с использованием библиотеки CPLEX, и у меня возникают проблемы при добавлении ограничений в модель. Код довольно длинный, поэтому здесь я просто включаю общую структуру кода и одно из ограничений (и задействованных переменных).
#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)
могу подвести итоги лямбда и р для вас:
model.add(U[i][n][r] == chi[i][n][r] + beta[i][n] * IloSum( lambda[i][n][l]* p[i][n][l]));
или если это не работает, определите одномерный IloNumArray
lambda_l [l] и p_l [l] через лямбду и p.
Спасибо за вашу помощь, наконец я смог понять, что случилось. По сути, инициализация переменных была неправильной, потому что я не добавлял их в модель. Например, определение переменной 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);
}
После изменения инициализации переменных ограничения работали так, как должны, поэтому проблема устранена.