книги / Моделирование и оптимизация в LINGO
..pdfство ее нулю означает, что новая карта, как и последующие, не может улучшить решение (их оценки не меньше нуля). Выход из цикла означает, что все возможные перспективные карты получены и на них найдено оптимальное решение непрерывной задачи. Наконец, чтобы получить целочисленное решение задачи, снова ищется минимум основной модели на том же наборе карт, но с добавлением условия целочисленности переменных (совместное решение подмоделей MASTER_PROB и INTEGER_REQ как единой модели). Тем самым завершается итерационный процесс оптимизации.
Вычисление итоговых показателей раскроя и формирование вывода решения в табличной форме представлены в отдельном раз-
деле CALC.
Теперь, выполнив команду Solver/Solve либо нажав кнопку в виде мишени, получаем на дисплее отчет решения модели раскроя:
ЗАДАЧА РАСКРОЯ РУЛОНОВ
Всего использовано рулонов: |
|
666 |
|
|
|
|
|
|
Совокупная ширина рулонов, м: |
5328 |
|
|
|
|
|
||
Совокупная ширина лент, м: |
|
5224 |
|
|
|
|
|
|
Всего остатков, %: |
2.0 |
|
|
|
|
|
|
|
Карты раскроя (Pattern): |
5 |
6 |
7 |
8 |
||||
Ленты Заказ Факт |
1 |
2 |
3 |
4 |
===========================================================
L1 |
250 |
250 |
1 |
. |
. |
. |
1 |
. |
. |
. |
L2 |
110 |
110 |
1 |
. |
. |
. |
. |
2 |
. |
. |
L3 |
700 |
700 |
1 |
. |
3 |
. |
. |
. |
. |
2 |
L4 |
920 |
921 |
1 |
6 |
. |
. |
1 |
. |
6 |
1 |
L5 |
535 |
536 |
1 |
. |
. |
10 |
1 |
. |
1 |
2 |
===========================================================
Используется, раз: |
0 |
0 170 |
0 250 55 |
96 95 |
Отчет показывает, что в решении участвовало 8 из допустимых 15 карт (сгенерировано 7), из них в оптимальный набор вошли только 5. Все потребности удовлетворяются полностью раскроем 666 рулонов, и при этом остатки составляют всего 2 %.
71
8.ИНТЕРФЕЙС С СИСТЕМАМИ ДАННЫХ
ИПРИЛОЖЕНИЯМИ
Очевидно, что небольшие объемы данных можно переместить из Excel в LINGO копированием ячеек с данными и вставкой их в секцию DATA модели справа от имени атрибута. Аналогично небольшой отчет о решении можно перенести в Word, используя команды копирования и вставки. Однако при больших объемах данных и при встраивании LINGO в систему пользователя такой метод неприемлем. Ниже рассмотрим, как в LINGO решается эта проблема.
8.1. Взаимодействие с внешними файлами
Как отмечалось в начале пособия, LINGO предоставляет возможности импорта данных из текстовых файлов формата ASCII и экспорта решений в них.
Для получения данных из текстовых файлов используется интерфейсная функция @FILE(‘filename’). При этом данные могут быть вставлены в любое место модели, что особенно удобно для секций DATA и SETS. LINGO принимает текст из файла до тех пор, пока не встретит метку конца файла либо метку конца записи в LINGO ( ). Часть файла между метками называется записью. Если в модели последует второе (третье и т.д.) обращение к этому файлу, то данные будут читаться из файла, начиная с точки остановки предшествующего обращения, т.е. со следующей записи. В модель можно включать до 16 файлов. Вложенность функций @FILE не допускается.
Для примера вернемся к задаче PRODUCTION с исходной моделью, но часть данных для секций SETS и DATA будем брать из файла production.txt. Тогда модель примет следующий вид:
MODEL: sets:
PRODUCT: order;
EQUIPMENT / @FILE('c:\GAL\production.txt')/: TWORK, K; PR_EQ (PRODUCT, EQUIPMENT): T, X;
72
endsets data:
PRODUCT=@FILE('c:\GAL\production.txt'); order= @FILE('c:\GAL\production.txt'); T = @FILE('c:\GAL\production.txt');
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'+ EQUIP-
MENT(J), X(I,J))
)
); END
Здесь в файл production.txt записываются как элементы множества, так и данные в следующем виде:
!Оборудование; 1 . . 3 ~ !Продукция; pr1 . . pr4~ !Потребность; 75 123 0 62~ !Время; 7 11 9 14 8 10 12 7 13 10 9 11
Заметим, что в файле допустим комментарий.
Функция @TEXT( ['filename', [‘a’]]) позволяет выводить данные из LINGO во внешний файл или на экран. Второй вариант имеет место при отсутствии аргументов. При указании только имени файла запись идет в создаваемый файл или, если такой файл существует, то поверх его. При добавлении аргумента ‘a’данные записываются в конец существующего файла. Функция может быть использована только в секции DATA и при этом она записывается на левой стороне выражения вывода.
73
Примеры:
Вывод X,Y в файл: @TEXT('OUT.TXT') = X,Y;
Вывод элементов множества и значений атрибута на экран:
@TEXT() = PRODUCT, VOLUME;
Вывод элементов множества и положительных значений их атрибута в конец файла:
@TEXT(‘REPORT.TXT’,’a’)=@WRITEFOR(PRODUCT(I)|VOLUME(I)#GT# 0: PRODUCT(I), ' ', VOLUME(I));
Очевидно, что данные из полученного файла могут быть переданы вовне, например, в Excel или MS Access.
Для автоматизации выполнения часто используемой последовательности команд и/или моделей можно составить сценарий команд (Command Script). Язык команд LINGO применяется в режиме командной строки (Window| Command Window), а готовый скрипт запускается открытием содержащего его файла через меню File|Take Commands. Выполнение скрипта и работа LINGO завершаются при обнаружении команды QUIT. Иначе выполнение прекратится при достижении конца файла, после чего LINGO перейдет в режим нормального ввода. Полный перечень команд с кратким описанием приведен в приложении 3.
Для примера снова обратимся к исходной модели PRODUCTION
изапишем скрипт, запуск которого приводит к решению модели
ивыводу на дисплей и в файл SOLU.TXT краткого отчета с ненулевыми значениями переменных.
Текст приводимого ниже скрипта, написанный в окне Command Window, сохраняем в файле Myscript.ltf.
SET ECHOIN 1 MODEL: sets:
PRODUCT: order;
EQUIPMENT /1..3/: TWORK, K; PR_EQ (PRODUCT, EQUIPMENT): T, X; endsets
data:
PRODUCT=pr1.. pr4; order= 75 123 0 62; T = 7 11 9
74
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'+ EQUIP-
MENT(J), X(I,J))
)
); END
SET TERSEO 1 GO
NONZ X
!Открытие файла
DIVERT SOLU.TXT
!Запись решения в файл
NONZ X
!Закрытие файла решения
RVRT
Теперь с помощью команды меню File|Take Commands открываем файл Myscript.ltf, что приводит к выполнению нашего скрипта и выводу на дисплей отчета в следующем виде:
: SET ECHOIN 1
Parameter Old Value New Value ECHOIN 1 1
: MODEL:
?sets:
?PRODUCT: order;
?EQUIPMENT /1..3/: TWORK, K;
?PR_EQ (PRODUCT, EQUIPMENT): T, X;
?endsets
?data:
?PRODUCT=pr1.. pr4;
?order= 75 123 0 62;
?T = 7 11 9
?14 8 10
75
?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
: SET TERSEO 1
Parameter |
Old Value |
New Value |
|
TERSEO |
1 |
1 |
|
: GO |
|
|
|
Local optimal solution found. |
|
750.0000 |
|
Objective value: |
|
||
Objective bound: |
|
750.0000 |
|
Infeasibilities: |
|
0.000000 |
|
Extended solver steps: |
|
36 |
|
Total solver iterations: |
|
2499 |
|
Elapsed runtime seconds: |
|
2.33 |
|
: NONZ X |
|
|
|
Local optimal solution found. |
|
750.0000 |
|
Objective value: |
|
||
Objective bound: |
|
750.0000 |
|
Infeasibilities: |
|
0.000000 |
|
Extended solver steps: |
|
36 |
|
Total solver iterations: |
|
2499 |
|
Elapsed runtime seconds: |
|
2.34 |
|
|
Variable |
Value |
Reduced Cost |
|
X( PR1, 1) |
75.00000 |
0.000000 |
|
X( PR2, 2) |
92.00000 |
0.000000 |
|
X( PR2, 3) |
31.00000 |
10.00000 |
|
X( PR4, 1) |
22.00000 |
0.000000 |
|
X( PR4, 3) |
40.00000 |
11.00000 |
: !Открытие файла |
|
|
|
: DIVERT SOLU.TXT |
|
|
76
:! Запись решения в файл
:NONZ X
:! Закрытие файла решения
:RVRT
:
При этом в файл Solu.txt записываются только результаты решения задачи:
Local optimal solution found. |
|
750.0000 |
Objective value: |
|
|
Objective bound: |
|
750.0000 |
Infeasibilities: |
|
0.000000 |
Extended solver steps: |
|
36 |
Total solver iterations: |
|
2499 |
Elapsed runtime seconds: |
|
2.30 |
Variable |
Value |
Reduced Cost |
X( PR1, 1) |
75.00000 |
0.000000 |
X( PR2, 2) |
92.00000 |
0.000000 |
X( PR2, 3) |
31.00000 |
10.00000 |
X( PR4, 1) |
22.00000 |
0.000000 |
X( PR4, 3) |
40.00000 |
11.00000 |
Заметим, что в отличие от данных, записанных в файл, на дисплей выводится как отчет, так и весь скрипт. Скрипт не выведется, если не введена команда SET ECHOIN 1 или в ней задано значение 0.
Если скрипт сохранить в файле с именем AUTOLG.DAT в рабочей папке LINGO, то при каждом запуске LINGO он будет выполняться.
Имеется другой способ автоматического выполнения скрипта при запуске LINGO. Для этого в командную строку запуска LINGO добавляется имя файла, содержащего скрипт, с префиксом –T.
Например, чтобы выполнялся скрипт из файла Myscript.ltf, достаточно в свойствах ярлыка LINGO в поле Объект добавить строку -tMyscript.ltf, как показано на скриншоте окна свойств
(рис. 4).
Теперь при запуске LINGO будет выполнена команда File|Take Commands, и мы автоматически получим отчет о решении, точно такой же, как в файле Solu.txt (см. выше).
77
Рис. 4
Если наряду с файлом Myscript.ltf в рабочей папке LINGO есть файл AUTOLG.DAT, то он будет выполняться перед Myscript.
Если перед именем файла поставить префикс –O, то при запуске выполнится команда File|Open и скрипт из файла считается в стандартное окно. При префиксе –L автоматически выполняется команда File|Log Output и весь вывод, обычно направляемый в командное окно, посылается в файл с именем, записанным после этого префикса.
LINGO включает также служебную программу RunLingo, которая позволяет обрабатывать файлы сценариев. RunLingo вызыва-
78
ется из командной строки, где записывается вместе с файлом сцена-
рия, например: C:\LINGO16>runlingo myscript.ltf. Результаты выпол-
нения программа направляет в стандартное устройство вывода. Завершая рассмотрение работы с файлами, приведем стан-
дартные типы файлов (их расширений), принятые в LINGO:
.LG4 Файлы модели, только в Windows,
.LNG Файлы модели в текстовом формате,
.LTF Файлы скриптов,
.LDT Файлы включенных данных,
.LGR Файлы отчета.
Файлы .LG4 записываются в бинарном формате и правильно читаются только под Windows. Файл с любым другим расширением воспринимается LINGO как текстовый. Файлы .LNG могут использоваться для переноса модели на другую платформу или в приложение. Следует иметь в виду, что эти файлы не сохраняют специальное форматирование модели и, в отличие от файлов .LG4, могут не работать как контейнеры или серверы OLE.
8.2. Взаимодействие с электронной таблицей
Удобным средством хранения и манипулирования данными являются электронные таблицы. LINGO предоставляет широкие возможности взаимодействия с таблицей: импорт данных из таблицы, экспорт в нее решений, создание ссылок OLE на Excel, управление LINGO из Excel, импортирование функциональных возможно-
стей LINGO в Excel и др.
8.2.1. Импорт и экспорт данных между LINGO и Excel
Импорт данных из таблицы выполняется с помощью интерфейсной функции @OLE, которая доступна только в версии под Windows. Она обеспечивает прямую OLE передачу данных между LINGO и Excel (передачу памяти), что исключает использование промежуточных файлов. Функция применима в секциях DATA
и INIT.
79
LINGO, обнаружив функцию @OLE, загружает Excel, которая в свою очередь загружает требуемую таблицу и запрашивает диапазоны, в которых находятся нужные данные.
@OLE функция может читать в Excel как текстовые данные (элементы множеств), так и числовые атрибуты множеств. При этом допустимы только одно- и двухмерные диапазоны на одном листе, а чтение диапазона происходит слева направо и сверху вниз.
Синтаксис применения @OLE функции:
object_list = @OLE([‘spreadsheet_file’] [, range_name_list]);
Здесь object_list – список объектов модели, разделяемых запятой, который может содержать имена множеств, атрибуты и скалярные переменные;
Spreadsheet_file – имя файла таблицы, содержащего данные; Range_name_list – список имен диапазонов.
Если имя файла отсутствует, используется текущий открытый лист. Если отсутствуют имена диапазонов, то в качестве их берутся имена запрашиваемых объектов. Допускается указывать только один диапазон для получения всех данных в случаях, когда все объекты из списка одного типа и определены на одном множестве. Наконец, если каждому объекту соответствует свое имя диапазона, то объекты могут быть разного типа и из разных множеств.
Применение функции @OLE для экспорта решений возможно в двух синтаксических формах. 1-я форма:
@OLE( ['spreadsheet_file’] [, range_name_list]) = object_list;
Нетрудно видеть, что в этом выражении источником решения являются объекты модели, перечисленные в списке справа, а приемником – файл Excel. Случаи отсутствия части или всех аргументов слева воспринимаются аналогично рассмотренным для импорта. Аналогичными являются и варианты задания диапазонов.
Бóльшие возможности управления экспортом дает 2-я форма:
@OLE( ['spreadsheet_file’], range_name_list) =
@WRITEFOR( setname[ ( set_index_list) [ | conditional_ qualifier]] : output_obj_1[,…,output_obj_n]);
80