CPLEX vs Constraint Programming Solution для линейно ограниченного MIP с нелинейной целью (деление) - PullRequest
0 голосов
/ 19 февраля 2020

Я пытаюсь решить MIP с нелинейной целью, такой как sum(a(i)*x(i))/sum(b(i)*x(i)), где a (i) и b (i) являются параметрами. Поскольку CPLEX не может извлечь это выражение, я попытался использовать CP.

Однако, у меня есть ограничение, утверждающее, что переменная решения x (i) должна быть множителем 2,5, поэтому число с плавающей запятой. Поскольку CP не может обрабатывать числа с плавающей запятой, я установил x как целое число, и подразумевается, что он должен быть умножен на 25. Во всех остальных ограничениях и выражениях я разделил x на 10, чтобы вычисления оставались такими же.

Во-первых, Я решил модель с множителем 5, я получил решение с очень маленьким зазором, и это нормально. Когда я изменил множитель на 25, модель не может завершиться в течение 2 часов (застрял с разрывом в 90%). Я полагаю, что это произошло из-за масштабирования, но все еще не могу понять это, так как я не знаком с алгоритмом CP.

Я все еще работаю над линеаризацией oblective, но любые предложения как для CPLEX, так и для CP-движков будет высоко оценен Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2020

Спасибо @ Алекс Флейшер. Я попробовал то, что вы предложили. Индекс моей переменной решения является кортежем, поэтому я написал код, подобный приведенному ниже:

dvar int scalex[1..card(hm)] in 0..10000;
int scale=100;

dexpr float A[1..card(hm)]=[];
int max_range=card(hm);

execute{
for (var i=1;i<=max_range;i++){
    A[i]==scalex[i]/scale;
}
}

Я получил ошибку времени выполнения сценария: невозможно преобразовать в число, ошибка «[a IloNumVar]». Как я могу это исправить? Спасибо.

0 голосов
/ 20 февраля 2020

пытались ли вы превратить равенства в неравенства, чтобы обеспечить некоторую гибкость?

Например,

using CP;

int scale=1000;
dvar int scalex in 0..2000;
dexpr float x=scalex/scale;

subject to
 {
   x*x==2;
 }

не дает решения, тогда как

using CP;

float epsilon=0.001;

int scale=1000;
dvar int scalex in 0..2000;
dexpr float x=scalex/scale;

subject to
 {
   abs(x*x-2)<=epsilon;
 }

дает

x = 1.414

и

using CP;

{int} hm=asSet(1..4);
float epsilon=0.001;

dvar int scalex[1..card(hm)] in 0..20000;
int scale=10000;

dexpr float A[ i in 1..card(hm)]=scalex[i]/scale;
subject to
{
  forall(i in 1..card(hm))abs(A[i]*A[i]-2)<=epsilon;
}

тоже отлично работает

...