Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Моделирование и оптимизация в LINGO

..pdf
Скачиваний:
10
Добавлен:
12.11.2023
Размер:
2.55 Mб
Скачать

Допустим, множество FOODS с атрибутом Prod содержит 10 продуктов, и из первых трех в рацион можно включить не более одного. Такое требование будет учтено записью

@SOS1('DIET', Prod(1)); @SOS1('DIET', Prod(2));

@SOS1('DIET', Prod(3));

Очевидно, что возможен вариант и с использованием функции цикла:

@FOR(FOODS(J) | J #LE# 3: @SOS1('DIET', Prod(J)));

В этих примерах набору из первых трех продуктов присвоено имя

DIET.

Если же из этого набора должен войти в рацион только один, то в предыдущих записях достаточно заменить @SOS1 на @SOS3.

Следующий пример отражает требование, чтобы каждый потребитель получал товары только от одного поставщика:

@FOR(CONSUMERS(J): @FOR(SUPPLIERS(I):X(I,J)<= 100*Y(I,J);@SOS3('CONSUM_' + CONSUMERS(J), Y(I,J))));

Здесь Y(I, J) определяет, есть поставки от I к J или нет. Пусть имеем потребителей A,B,C и D. Тогда для каждого потребителя определится свой набор переменных с именами 'CONSUM_A', 'CONSUM_B', 'CONSUM_C' и 'CONSUM_D'. Если условие поставить в виде «не более одного поставщика», то достаточно применить функцию @SOS1 без использования бинарных переменных Y(I, J):

@FOR(CONSUMERS(J): @FOR(SUPPLIERS(I): @SOS1('CONSUM_' + CONSUMERS(J), X(I,J))));

Функция @SOS2 применяется, например, при описании ку- сочно-линейных зависимостей. В этом случае веса точек изломов кусочно-линейной функции будут переменными, к которым относится требование смежности. Очевидно, если вычисляемая точка (аргумент функции) точно соответствует излому, то только один из весов изломов будет равна 1. Если же вычисляемая точка лежит между изломами, то ровно 2 веса будут положительными, в сумме равные 1, а их индексы – смежными. Например, с помощью @SOS2 некоторая кусочно-линейная функция Profit=F(X), описывается линейными зависимостями:

31

Profit=@SUM(A(I): Z(I)*W(I));

X = @SUM( A(I): V(I) * W(I)); @SUM( A(I): W(I)) = 1;

@FOR( A(I): @SOS2('SPISOK', W(I)));,

где исходная переменная X представлена через известные точки излома V(I) и веса этих точек W(I), а функция Profit – через веса и ее значения в точках излома Z(I). V, W и Z – атрибуты множества изломов A. Набору переменных (весов), к которым применяется функция

@SOS2, дано имя 'SPISOK'.

Синтаксис функции @CARD идентичен синтаксису функций @SOS. При использовании функции @CARD записи по всем переменным списка дополняются особой записью (одной на список), в которой вместо переменной указывается целое число N. В этом случае число ненулевых переменных из списка ограничивается сверху (<=) величиной N.

Примеры:

1.@CARD('Primer1', 2); @CARD('Primer1', A); @CARD('Primer1', B); @CARD('Primer1', C);

2.@FOR(CONSUMERS(J): @CARD('CONSUM_'+ CONSUMERS(J), N);

@FOR(SUPPLIERS(I): @CARD('CONSUM_' + CONSUMERS(J), X(I,J))));

В первом примере из трех переменных списка 'Primer1' ненулевыми будут не более двух. Во втором примере каждому потребителю соответствует свой список и свое значение N, которое должно быть задано в предшествующей секции DATA. Покажем, как LINGO преобразует такие конструкции на следующей модели:

Model:

sets:

CONSUMERS /A B C / : N; SUPPLIERS /SUP1.. SUP4/ ; C_SUP(SUPPLIERS, CONSUMERS ): X; endsets

data: N=2 3;

enddata

@FOR(CONSUMERS(J): @CARD('CONSUM_'+ CONSUMERS(J), N);

@FOR(SUPPLIERS(I): @CARD('CONSUM_' + CONSUMERS(J), X(I,J))));

end

32

Генератор моделей выдаст развернутую модель ограничений на переменные в виде:

MODEL:

@CARD( 'CONSUM_A', X_SUP1_A); @CARD( 'CONSUM_A', X_SUP2_A); @CARD( 'CONSUM_A', X_SUP3_A); @CARD( 'CONSUM_A', X_SUP4_A); @CARD( 'CONSUM_A', 2);

@CARD( 'CONSUM_B', X_SUP1_B); @CARD('CONSUM_B', X_SUP2_B); @CARD( 'CONSUM_B', X_SUP3_B); @CARD( 'CONSUM_B', X_SUP4_B); @CARD( 'CONSUM_B', 3);

END

Функция @SEMIC используется для описания зависимостей с разрывом в нуле. Так, при учете в модели фиксированных затрат на производство или перевозки суммарные затраты равны нулю при нулевом производстве, а при ненулевом – растут пропорционально объему производства со значения, равного фиксированным затратам.

Синтаксис функции @SEMIC имеет вид

@SEMIC(lower_bound,variable,upper_bound);

Из него следует, что при наличии производства или перевозок затраты должны лежать в диапазоне [нижняя граница, верхняя граница].

Примеры:

@SEMIC(5, COST, 40);

В этом случае COST может быть равна нулю либо лежать в диапа-

зоне [5,40].

@FOR( ROUTES: @SEMIC(2, VOLUME, 15));

Здесь накладывается ограничение на объем перевозок по маршрутам: либо не перевозить, либо перевозить не менее двух и не более 15 единиц груза. Как и ранее, границы могут быть заданы символьными константами, значения которых приводятся в секции

DATA или CALC.

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

@PRIORITY(variable_name, relative_priority);

33

где relative_priority – неотрицательное целое число. Самому низкому приоритету соответствует нулевое значение.

Примеры:

@PRIORITY(X, 50); @FOR(PRODUCT(I): @PRIORITY(VOLUME(I),100));

Функция @POSD обеспечивает, как минимум, положительную полуопределенность матрицы, используемой в модели. Единственный аргумент функции – исходная двумерная матрица, которая является атрибутом двумерного множества. Матрица может быть треугольной (верхней или нижней) или квадратной. В случае квадратной матрицы функция @POSD обеспечивает также симметричность результирующей матрицы.

Пример: пусть определено двумерное множество COV(SHOP,SHOP) с атрибутами X, Y и ERROR. Исходная матрица X, определяемая как ковариационная, из-за неточностей оказалась не положительно полуопределенной, что недопустимо для ковариационной матрицы. Поэтому встала задача получить положительно полуопределенную матрицу Y, наиболее близкую к исходной. Следующий фрагмент математической модели позволяет решить эту задачу:

MIN = @SUM(COV(I, J): ERROR(I, J)^2); @FOR(COV(I, J):

ERROR(I, J) = Y(I, J) – X(I, J); @FREE(ERROR);

);

@FOR(COV(I, J)| I #NE# J: @FREE(Y(I, J))); @POSD(Y);

6.3. Пример построения модели в LINGO

Рассмотрим типичную производственную задачу Production, построим ее математическую модель, а затем представим на языке моделирования LINGO.

Постановка задачи. Пусть некоторая фирма имеет n типов универсального оборудования, на котором можно производить определенный ассортимент изделий (m видов). Типы оборудования

34

отличаются временем tij, необходимым на изготовление одного i-го изделия на j-м оборудовании. При получении заказа на изделия его необходимо распределить по оборудованию так, чтобы выполнить заказ за минимальное время. Следует учесть, что заказ может включать не весь ассортимент изделий, и по технологическим причинам число видов изделий, производимых на одном типе оборудования за время выполнения заказа, ограничено величиной kj.

На основе постановки строим математическую модель задачи

Production в виде:

Time maxTj min,

(1)

j

 

m

 

 

 

 

 

Tj tij xij , j 1,n,

(2)

i 1

 

n

 

 

 

 

 

xij bi ,i 1,m,

(3)

j 1

 

m

 

 

 

yij k j , j 1,n,

(4)

i 1

 

0 xij Myij , ij,

(5)

xij целые; yij бинарные, ij,

(6)

где xij – количество изделий i-го типа, производимых на j-м оборудовании; bi – заказанное количество изделий i-го типа; yij =1, если на j-м оборудовании производятся i-е изделия, иначе yij = 0; M – большое положительное число; Tj – время работы j-го оборудования.

Приведенная модель содержит 2nm+n переменных, n+m равенств и n+nm неравенств, что говорит о большой размерности задачи для реального производства.

На языке моделирования LINGO модель этой же задачи записываем в следующем виде:

MODEL: sets:

PRODUCT: order;

EQUIPMENT /1..3/: TWORK, K; PR_EQ (PRODUCT, EQUIPMENT): T, X; endsets

data:

35

PRODUCT=pr1.. pr4; order= 75 123 0 62; T = 7 11 9

14 8 10

12 7 13

10 9 11; K = 2 1 3; enddata

MIN = TIME;

@FOR(PRODUCT(I)|order #NE# 0: @SUM(EQUIPMENT(J): X(I,J))=order);

@FOR(EQUIPMENT(J): @SUM(PRODUCT(I)|order #NE# 0: T(I,J)*X(I,J))- TWORK(J)=0);

TIME = @MAX(EQUIPMENT: TWORK); @FOR(PR_EQ(I,J)|order(I) #NE# 0: @GIN(X));

@FOR( EQUIPMENT(J): @CARD( 'name'+ EQUIPMENT(J), K);

@FOR( PRODUCT(I)|order #NE# 0: @CARD('name'+ EQUIPMENT(J), X(I,J))

)

); END

Здесь введены два первичных множества и одно производное. Атрибутом множества PRODUCT является величина заказа order, а атрибутами множества EQUIPMENT – время работы оборудования TWORK и число видов изделий K. Заметим, что ограничения (4) по числу видов изделий на одном типе оборудования kj описаны не неравенствами с булевыми переменными, а функцией @CARD. Тем самым отпадает необходимость в условиях (5) и в бинарных переменных yij, что резко снижает размер модели.

Условие order #NE# 0 исключает из модели ограничения и переменные, соответствующие отсутствующим в заказе видам изделий. Очевидно, что выражения целевой функции и ограничений в этой модели не зависят от значений n и m и при их изменении потребуется изменить только данные. Для примера мы взяли n=3 и m=4, в этом случае LINGO сгенерирует для решателя развернутую математическую модель, соответствующую введенным данным, в виде

MODEL:

[_1] MIN= TIME;

[_2] X_PR1_1 + X_PR1_2 + X_PR1_3 = 75;

[_3] X_PR2_1 + X_PR2_2 + X_PR2_3 = 123;

[_4] X_PR4_1 + X_PR4_2 + X_PR4_3 = 62;

36

[_5] 7 * X_PR1_1 + 14 * X_PR2_1 + 10 * X_PR4_1 – TWORK_1 = 0; [_6] 11 * X_PR1_2 + 8 * X_PR2_2 + 9 * X_PR4_2 – TWORK_2 = 0; [_7] 9 * X_PR1_3 + 10 * X_PR2_3 + 11 * X_PR4_3 – TWORK_3 = 0; [_8] TIME = @SMAX( TWORK_1, TWORK_2, TWORK_3);

@CARD( 'NAME1', X_PR1_1); @CARD( 'NAME1', X_PR2_1); @CARD( 'NAME1', X_PR4_1); @CARD( 'NAME1', 2); @CARD( 'NAME2', X_PR1_2); @CARD( 'NAME2', X_PR2_2); @CARD( 'NAME2', X_PR4_2); @CARD( 'NAME2', 1); @CARD( 'NAME3', X_PR1_3); @CARD( 'NAME3', X_PR2_3); @CARD( 'NAME3', X_PR4_3); @CARD( 'NAME3', 3);

@GIN( X_PR1_1); @GIN( X_PR1_2); @GIN( X_PR1_3); @GIN(X_PR2_1); @GIN( X_PR2_2); @GIN( X_PR2_3); @GIN( X_PR4_1); @GIN(X_PR4_2); @GIN( X_PR4_3);

END

Как и следовало ожидать, в этой модели присутствуют только те ограничения и переменные, которые соответствуют реальному заказу.

После успешного решения данной модели LINGO выдает стандартный отчет:

Local optimal solution found.

848.0000

Objective value:

Objective bound:

848.0000

Infeasibilities:

0.000000

Extended solver steps:

2

Total solver iterations:

771

Model Class:

PINLP

Total variables:

16

Nonlinear variables:

3

Integer variables:

18

Total constraints:

8

Nonlinear constraints:

1

Total nonzeros:

26

Nonlinear nonzeros:

3

Variable

Value

Reduced Cost

TIME

848.0000

0.000000

ORDER( PR1)

75.00000

0.000000

ORDER( PR2)

123.0000

0.000000

37

ORDER( PR3)

0.000000

0.000000

ORDER( PR4)

62.00000

0.000000

TWORK( 1)

620.0000

0.000000

TWORK( 2)

848.0000

0.000000

TWORK( 3)

845.0000

0.000000

K( 1)

2.000000

0.000000

K( 2)

1.000000

0.000000

K( 3)

3.000000

0.000000

T( PR1, 1)

7.000000

0.000000

T( PR1, 2)

11.00000

0.000000

T( PR1, 3)

9.000000

0.000000

T( PR2, 1)

14.00000

0.000000

T( PR2, 2)

8.000000

0.000000

T( PR2, 3)

10.00000

0.000000

T( PR3, 1)

12.00000

0.000000

T( PR3, 2)

7.000000

0.000000

T( PR3, 3)

13.00000

0.000000

T( PR4, 1)

10.00000

0.000000

T( PR4, 2)

9.000000

0.000000

T( PR4, 3)

11.00000

0.000000

X( PR1, 1)

0.000000

0.000000

X( PR1, 2)

0.000000

11.00000

X( PR1, 3)

75.00000

0.000000

X( PR2, 1)

0.000000

0.000000

X( PR2, 2)

106.0000

8.000000

X( PR2, 3)

17.00000

0.000000

X( PR3, 1)

0.000000

0.000000

X( PR3, 2)

0.000000

0.000000

X( PR3, 3)

0.000000

0.000000

X( PR4, 1)

62.00000

0.000000

X( PR4, 2)

0.000000

9.000000

X( PR4, 3)

0.000000

0.000000

Row

Slack or Surplus

Dual Price

1

848.0000

-1.000000

2

0.000000

0.000000

3

0.000000

0.000000

4

0.000000

0.000000

5

0.000000

0.000000

6

0.000000

1.000000

7

0.000000

0.000000

8

0.000000

-1.000000

38

В первой строке отчета мы видим, что найдено только локальное решение. Этого следовало ожидать, так как построенная модель задачи является нелинейной и целочисленной (класс PINLP). Затем в первой части отчета приводится оптимальное значение критерия, его лучшая граница, величина недопустимости решения, число итераций и полная характеристика модели.

Во второй части отчета выведены исходные данные, имена

(Variable), значения (Value) и оценки переменных (Reduced Cost).

Третья часть относится к строкам модели (Row). В ней показывается, как выполняется соответствующее ограничение: для неравенств <= выдается резерв (Slack), а для неравенства >= – избыток (Surplus). В нашем случае ограничения заданы в виде равенств, поэтому для допустимого решения значения Slack or Surplus равны нулю. Значения, приводимые в столбце двойственных переменных (Dual Price), как и в столбце Reduced Cost второй части отчета, в анализе целочисленных задач не используются. Далее будет дана интерпретация этих величин.

Модель (1)–(6) можно простым преобразованием привести к линейному виду: достаточно исключить из целевой функции взятие максимума, заменив его неравенствами

Time Tj, j=1..n.

(7)

Тогда в LINGO-модели изменяется только раздел ММ:

MIN = TIME;

@FOR(PRODUCT(I)|order #NE# 0: @SUM(EQUIPMENT(J): X(I,J))=order);

@FOR(EQUIPMENT(J): @SUM(PRODUCT(I)|order #NE# 0: T(I,J)*X(I,J))- TWORK(J)=0);

@FOR(EQUIPMENT: TIME>=TWORK); @FOR(PR_EQ(I,J)|order(I) #NE# 0: @GIN(X));

@FOR( EQUIPMENT(J): @CARD( 'name'+ EQUIPMENT(J), K); @FOR( PRODUCT(I)|order #NE# 0: @CARD('name'+ EQUIPMENT(J), X(I,J))));

Отчет о решении этой модели представим только его началом:

Global optimal solution found.

745.0000

Objective value:

39

Objective bound:

745.0000

Infeasibilities:

0.000000

Extended solver steps:

0

Total solver iterations:

75

Model Class:

MILP

Как видим, теперь достигнут глобальный оптимум нашей задачи, в котором значение критерия значительно меньше, чем в найденном выше локальном минимуме. При этом и число итераций для нахождения оптимума уменьшилось в 10 раз. Если при решении исходной (нелинейной) модели на вкладке опций глобального решателя включить опцию Use Globel Solver, то получим такое же решение.

Аналогичный результат при решении исходной модели будем иметь, если используем возможность LINGO линеаризовать некоторые нелинейности. Для этого командой Solver|Options откроем окно Options и на вкладке Model generator установим опцию линеаризации Degree на уровень Math Only. В этом случае верхняя часть отчета будет представлена в виде

Linearization components added:

Constraints:

7

Variables:

4

Integers:

3

Global optimal solution found.

745.0000

Objective value:

Objective bound:

745.0000

Infeasibilities:

0.000000

Extended solver steps:

0

Total solver iterations:

66

Model Class: MILP

Из отчета следует, что линеаризация модели осуществлена путем добавления 7 ограничений и 4 переменных. В результате генератор модели передал на решение смешанную целочисленную линейную модель (MILP) вместо исходной нелинейной модели. Это позволило LINGO применить более эффективный решатель. В итоге получено глобальное решение всего за 66 итераций.

40

Соседние файлы в папке книги