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

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

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

и результатов решения. (Вставить в модель любую функцию можно командой Solver/Paste Function.)

Как отмечалось в начале главы, LINGO имеет 2 утилиты, которые предназначены для сортировки элементов множества или атрибутов. Утилита @RANK(SET|ATTRIBUTE(S)) возвращает вектор, в котором каждому элементу соответствует номер его позиции (ранг) при упорядочении по возрастанию. @SORT(SET|ATTRIBUTE(S)) возвращает вектор, содержащий индексы элементов в порядке, соответствующем отсортированным атрибутам или членам множества.

В качестве примера используем обе утилиты для сортировки значений атрибута:

model: sets:

set1: w, wrank, wsort; endsets

data:

w = 23 9.1 17.5; enddata

calc: @set('terseo',2); wrank= @rank(w);

@writefor(set1(i):'wrank ',(i),' =', @format(wrank, '3.0g'), @NEWLINE( 1));

wsort = @sort(w); @write(@NEWLINE( 1) );

@writefor(set1(i):'wsort ',(i),' =', @format(wsort, '3.0g'), @NEWLINE( 1));

endcalc end

После выполнения этого скрипта получаем

wrank 1 =

3

wrank 2 =

1

wrank 3

=

2

wsort 1

=

2

wsort 2

=

3

wsort 3

=

1

61

7.1. Пример программирования 1

Вернемся к задаче PRODUCTION. Составим модель задачи так, чтобы получить возможность решения ее исходного и линеаризованного вариантов за один запуск решателя. С этой целью выделим в разделе ММ три подмодели, а в секции CALC запишем скрипт, определяющий порядок решения комбинированных моделей и выводимую информацию о полученных решениях. В итоге приходим к следующей модели [14]:

MODEL:

 

 

 

 

 

Title PRODUCTION;

 

 

 

sets:

 

 

 

 

 

PRODUCT: order;

 

 

 

EQUIPMENT /1..3/: TWORK, TWORKY,K;

 

 

PR_EQ (PRODUCT, EQUIPMENT): T, X, Y;

 

 

endsets

 

 

 

 

 

data:

 

 

 

 

 

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

 

 

 

 

 

submodel OBJ_1:

 

 

 

MIN = TIME1;

 

 

 

TIME1 = @MAX(EQUIPMENT: TWORK);

 

 

endsubmodel

 

 

 

 

submodel OBJ_2:

 

 

 

MIN = TIME2;

 

 

 

@FOR(EQUIPMENT: TIME2>=TWORK);

 

 

endsubmodel

 

 

 

 

submodel CONSTR:

 

 

 

@FOR(PRODUCT(I)|order #NE# 0: @SUM(EQUIPMENT(J):

 

X(I,J))=order);

@SUM(PRODUCT(I)|order

#NE#

0:

@FOR(EQUIPMENT(J):

T(I,J)*X(I,J))- TWORK(J)=0); @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))));

62

endsubmodel calc:

@SET('TERSEO',1);

@WRITE(11*' ','РЕШЕНИЕ ЛИНЕАРИЗОВАННОЙ МОДЕЛИ', @NEWLINE(1));

@WRITE(11*' ',30*'-',@NEWLINE(1)); @SOLVE(OBJ_2, CONSTR);

@FOR(PR_EQ(i,j):Y(i,j)=X(i,j);TWORKY(J)=TWORK(J)); @WRITE(' Переменные линеаризованной модели',

@NEWLINE(1));

@TABLE(Y); @WRITE(@NEWLINE(2));

@WRITE(11*' ','РЕШЕНИЕ ИСХОДНОЙ МОДЕЛИ',@NEWLINE(1)); @WRITE(11*' ',23*'-',@NEWLINE(1));

@SOLVE(OBJ_1, CONSTR);

@WRITE(' Переменные исходной модели',@NEWLINE(1)); @TABLE(X);@WRITE(@NEWLINE(2));

@CHARTBAR(

'PRODUCTION', !Chart title;

'PRODUCT by EQUIPMENT', !X-Axis label; 'PRODUCT QUANTITY', !Y-Axis label; 'OBJ_2', !Legend 1;

Y, !Attribute 1; 'OBJ_1', !Legend 2; X);

@CHARTBAR(

'PRODUCTION', !Chart title; 'EQUIPMENT', !X-Axis label; 'TIME of WORK', !Y-Axis label; 'OBJ_2', !Legend 1;

TWORKY, !Attribute 1; 'OBJ_1', !Legend 2; TWORK);

endcalc END

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

В результате решения этой модели получаем единый отчет по двум комбинированным моделям:

63

 

РЕШЕНИЕ ЛИНЕАРИЗОВАННОЙ МОДЕЛИ

 

------------------------------

Global optimal solution found.

745.0000

Objective value:

 

Objective bound:

 

745.0000

Infeasibilities:

 

0.000000

Extended solver steps:

0

Total solver iterations:

30

Elapsed runtime seconds:

0.06

Переменные линеаризованной модели

PR1

1

2

3

75.00000

0.000000

0.000000

PR2

0.000000

93.00000

30.00000

PR3

0.000000

0.000000

0.000000

PR4

22.00000

0.000000

40.00000

 

РЕШЕНИЕ ИСХОДНОЙ МОДЕЛИ

 

 

-----------------------

 

Local optimal solution found.

795.0000

Objective value:

 

Objective bound:

 

795.0000

Infeasibilities:

 

0.000000

Extended solver steps:

10

Total solver iterations:

1802

Elapsed runtime seconds:

1.84

Переменные исходной модели

3

PR1

1

2

0.000000

0.000000

75.00000

PR2

12.00000

99.00000

12.00000

PR3

0.000000

0.000000

0.000000

PR4

62.00000

0.000000

0.000000

Как и ранее, на линеаризованной модели находится глобальный минимум, а на исходной (нелинейной) модели – только локальный, но отличающийся от найденного локального минимума при первом решении этой модели. Таким образом, исходная модель является многоэкстремальной, причем локальные минимумы значительно отличаются от глобального.

Наглядное представление о различиях в решениях двух моделей дают диаграмма выпуска продукции (рис. 2) и диаграмма времени работы оборудования (рис. 3).

64

Рис. 2

Рис. 3

Приведенный пример демонстрирует, с одной стороны, возможности языка моделирования LINGO, а с другой – важность преобразования модели в модель более простого класса, в идеале – в линейную модель, гарантирующую нахождение глобального решения.

65

7.2.Пример программирования 2

Вэтом примере рассмотрим решение одной из известных задач раскроя, встречающейся при производстве бумаги, картона, металла, текстиля и т.п.

Сначала сформулируем проблему, которую будем решать. Задача состоит в том, чтобы найти такие карты раскроя двумерного материала, при использовании которых расход материала на выполнение всего заказа был бы минимальным. В качестве исходного материала возьмем рулоны определенной ширины. Из них требуется получить заказанное количество рулонов разной ширины, которые будем называть лентами, чтобы отличать их от раскраиваемых рулонов. Так как возможны разные карты раскроя рулона, а их может быть слишком много, решение задачи заключается в нахождении самого эффективного набора таких карт. Очевидно, что реальную задачу не решить полным перебором всех карт раскроя, обеспечивающих выполнение заказа.

В1961 г. П. Гилмори и Р. Гомори предложили эффективный двухэтапный алгоритм решения задачи раскроя, в частности рулонов, значительно сокращающий число рассматриваемых карт раскроя [16].

На первом этапе решается основная модель задачи на множестве карт, сгенерированных к началу текущей итерации, с условием удовлетворения всех потребностей минимумом используемых рулонов. На начальной итерации множество карт состоит из одной искусственной карты, содержащей всю номенклатуру лент (авторы назвали ее суперкартой). Результатом первого этапа является найденный на текущем множестве очередной оптимальный набор карт

ичастота их применения, а также двойственные цены лент. При этом на всех итерациях за исключением завершающей итерации решается непрерывная линейная модель.

На втором этапе используются найденные двойственные цены в качестве цен (Price) лент, характеризующие их значимость, для нахождения самой лучшей новой карты по суммарной цене лент, входящих в нее. Поэтому данный этап называют генератором карт или столбцов симплекс-метода (новая карта вводит новую перемен-

66

ную и соответствующий столбец в симплекс-таблице). Задача поиска максимума значимости набора лент, ограниченного шириной рулона, представляет собой известную классическую задачу о рюкзаке с одним условием (ширина рулона – это емкость рюкзака). При получении перспективной карты она добавляется в текущий набор карт, и снова решается основная модель.

Если не удается найти такую новую карту, то основная модель решается совместно с подмоделью целочисленности переменных, т.е. как целочисленная линейная задача. Решается она методом ветвей и границ.

Полная модель задачи раскроя рулонов имеет следующий вид:

MODEL:

! ЗАДАЧА РАСКРОЯ РУЛОНОВ;

SETS:

PATTERN: COST, X;

FG: WIDTH, DEM, PRICE, Y, YIELD; FXP( FG, PATTERN): NBR;

ENDSETS

DATA:

PATTERN = 1..15; ! Полагаем, что не потребуется; !больше 15 карт;

RMWIDTH = 8; ! Ширина раскраиваемого рулона, м; FG = L1 L2 L3 L4 L5; !Требуемые рулоны (ленты);

WIDTH= 6 4 2.5 1.2 0.8; !их ширина;

DEM = 250 110 700 920 535; !и потребность; BIGM = 999;

ENDDATA

! Основная модель;

SUBMODEL MASTER_PROB:

[MSTROBJ] MIN= @SUM( PATTERN( J)| J #LE# NPATS: COST( J)*X( J));

@FOR( FG( I): [R_DEM]

@SUM( PATTERN( J)| J #LE# NPATS:

NBR( I, J) * X( J)) >= DEM( I);

); ENDSUBMODEL

! Подмодель целочисленности;

SUBMODEL INTEGER_REQ:

@FOR( PATTERN: @GIN( X)); ENDSUBMODEL

67

! Подмодель генерации карт;

SUBMODEL PATTERN_GEN:

[SUBOBJ] MAX = @SUM( FG( I): PRICE( I)* Y( I)); @SUM( FG( I): WIDTH( I)*Y( I)) <= RMWIDTH; @FOR( FG( I): @GIN(Y( I)));

ENDSUBMODEL

! Скрипт процесса решения задачи; CALC:

! Установка параметров; @SET( 'DEFAULT');

@SET( 'TERSEO', 2); ! Запрет вывода по умолчанию;

!Максимально допустимое число карт; MXPATS = @SIZE( PATTERN);

!Создание 1-й карты как суперкарты; COST( 1) = BIGM;

@FOR( FG( I): NBR( I, 1) = 1);

!Выполнение цикла пока есть перспективные карты; NPATS = 1;

RC = -1; ! Вход в цикл;

@WHILE( RC #LT# 0 #AND# NPATS #LT# MXPATS:

!Решение основной модели с лучшими картами; @SOLVE( MASTER_PROB);

!Сохранение двойственных оценок лент для;

!подмодели генерирования карт;

@FOR( FG( I): PRICE( I) = -@DUAL( R_DEM( I)));

!Генерирование перспективной карты; @SOLVE( PATTERN_GEN);

!Относительная оценка лучшей карты на текущей итерации; RC = 1 – SUBOBJ;

!Добавление карты в главную модель,;

!если она улучшает решение;

@IFC( RC #LT# 0: NPATS = NPATS + 1;

@FOR( FG( I): NBR( I, NPATS) = Y( I)); COST( NPATS) = 1;

);

);

! Решение основной модели с условием целочисленности; @SOLVE( MASTER_PROB, INTEGER_REQ);

ENDCALC

68

!Скрипт вычисления итогов и вывода решения;

!в табличной форме;

CALC:

! Вычисление полученных лент (факт); @FOR( FG( F): YIELD( F) =

@SUM( PATTERN( J)| J #LE# NPATS: NBR( F, J) * X(J))

);

! Вычисление итоговых показателей раскроя; @WRITE(24*' ','ЗАДАЧА РАСКРОЯ РУЛОНОВ ', @NEWLINE( 1));

TOTAL_FT_USED = @SUM( PATTERN( I) | I #LE# NPATS: X( I)) * RMWIDTH;

TOTAL_FT_YIELD = @SUM(FG(I) | I #LE# NPATS: YIELD(I) * WIDTH( I));

PERC_WASTE = 100 * ( 1 – (TOTAL_FT_YIELD / TOTAL_FT_USED));

! Вывод результатов решения на экран; FW = 6;

@WRITE( @NEWLINE(1));

@WRITE(' Всего использовано рулонов: ', @SUM(PATTERN(I)| I #LE# NPATS: X( I)), @NEWLINE(2),

' Совокупная ширина рулонов, м: ', TOTAL_FT_USED, @NEWLINE(1),

' Совокупная ширина лент, м: ', TOTAL_FT_YIELD, @NEWLINE(2),

'Всего остатков, %:', @FORMAT( PERC_WASTE,

'#5.2G'), @NEWLINE(1));

@WRITE( @NEWLINE(1), 24*' ', 'Карты раскроя (Pattern):', @NEWLINE(1));

@WRITE( ' Ленты Заказ Факт');

@FOR( PATTERN(I) | I #LE# NPATS: @WRITE(@FORMAT(I,'6.6G'))); @WRITE( @NEWLINE(1));

@WRITE( ' ',FW*( NPATS+3)*'=', @NEWLINE(1)); @FOR( FG( F):

@WRITE((FW – @STRLEN( FG( F)))*' ', FG( F), ' ', @FORMAT( DEM( F), '6.6G'), @FORMAT( YIELD( F), '6.6G'));

@FOR( FXP( F, P) | P #LE# NPATS: @WRITE( @IF( NBR( F, P) #GT# 0, @FORMAT( NBR( F, P), "6.6G"), ' .')));

@WRITE(@NEWLINE(1))

);

@WRITE( ' ',FW*( NPATS+3)*'=', @NEWLINE(1)); @WRITE( ' ', 'Используется, раз:');

@WRITEFOR(PATTERN(P) | P#LE# NPATS: @FORMAT( X(P), '6.6G')); @WRITE(@NEWLINE(1));

ENDCALC END

69

В этой модели первичное множество PATTERN состоит из карт раскроя с атрибутами стоимость (COST) и количество применений X (переменные основной модели MASTER_PROB). Второе первичное множество (FG) включает требуемый набор готовой продукции (лент). Атрибутами множества являются ширина WIDTH, потребность DEM, цена PRICE, количество лент в карте Y (переменные подмодели генерирования карт PATTERN_GEN) и суммарное произведенное количество лент YIELD. Производное множество FXP является плотным на наборе сгенерированных карт и имеет один атрибут NBR – число лент в карте, определяемое для новой карты как Y.

Раздел математической модели включает в себя три подмодели: MASTER_PROB – основная модель, минимизирующая число раскроенных рулонов; PATTERN_GEN – модель генерирования карт или модель задачи о рюкзаке, определяющая текущий наилучший вариант раскроя рулона (новую карту); INTEGER_REQ – модель, устанавливающая целочисленность переменных X.

Двухэтапный процесс решения задачи реализуется скриптом первой секции CALC. Остановимся здесь на критерии, по которому определяется перспективность или бесполезность добавления новой карты. Им является относительная оценка карты RC (Reduce Cost). Формула ее вычисления исходит из того, что все коэффициенты целевой функции (COST) основной модели за исключением первого равны 1. Первая карта, содержащая по одной ленте каждого размера, является искусственной (суперкартой) и в реальный набор карт попасть не должна. С этой целью ей придается очень большой коэффициент (BIGM). Оценка реальной карты согласно симплекс-методу определяется как разность маргинальных значений ухудшения

иулучшения основного критерия, здесь они соответственно равны 1

иSUBOBJ. Решение основной задачи будет оптимальным, если не будет отрицательных оценок. Поэтому цикл WHILE будет выполняться, пока есть отрицательные оценки и число карт не достигнет заданного предела. Так как оценка определяется в результате решения задачи о рюкзаке, она является минимально возможной и равен-

70

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