Как записать средние ограничения в CPLEX OPL? - PullRequest
1 голос
/ 25 мая 2019

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

Сначала я читаю лист Excel со следующими столбцами:

{string} Items = …;
tuple Item {
int weight;
int classification_1;
int classification_2;
…}

dvar int a[Items] in 0..1;

классификация_1 и классификация_2 - это две отдельные классификации объектов. Вы можете себе представить, что, например, классификация_1 содержит целое число, представляющее цвет, а классификация_2 имеет другое свойство (например, форму, где число представляет определенную форму). Чтобы прояснить ситуацию еще больше, вы можете представить объект следующим образом:

Ball_object; 23; 1; 2; …

Где Ball_object - это имя, 23 - вес, 1 - синий цвет и 2 - круг, остальные свойства не имеют непосредственного отношения к моему вопросу. Теперь предположим, что у меня есть следующее ограничение: 1. Для всех предметов их вес должен составлять менее 10% от общего веса выбранных предметов.

Я пробовал следующее:

Subjected to {
    Forall ( i_1 in Items )
    ctItemRatio:
    (Item[i_1].weight * a[i_1]) / (sum (I in Items) (Item[i].weight * a[i])) <= 0.1;
}

Но, похоже, это не работает, так как моя студия CPLEX не может извлечь выражение. Но я немного смущен тем, что я на самом деле сделал неправильно с этим ограничением. У кого-нибудь есть идеи, как мне это решить?

  1. Для каждой фигуры общий вес данной фигуры не должен превышать 15% от общего веса.

На самом деле я понятия не имею, как это сделать, поскольку я не могу просто перебрать классификацию_2, верно? Как я могу смоделировать его таким образом, чтобы я мог использовать поиск по классификации_2? (Я хотел бы найти решение OPL, а не просто именовать все фигуры от руки.

Спасибо за помощь!

1 Ответ

3 голосов
/ 25 мая 2019

Для ограничения # 1 способ, которым вы его написали, является нелинейным. Если вы просто умножите обе стороны на sum (I in Items) (Item[i].weight * a[i]), он станет линейным, и CPLEX должен быть счастлив:

Item[i_1].weight * a[i_1] <= 0.1 * (sum (I in Items) (Item[i].weight * a[i]));

Для ограничения № 2 я бы предложил создать список уникальных значений классификационной_2 (перед вызовом кода OPL), а затем выполнить цикл по этим значениям, создав для каждого ограничение. Я не знаком с синтаксисом OPL, но, вероятно, вы можете добавить условие в сумму; что-то вроде:

sum (i in Items : classification_2[i] == <some value>)
...