Чтобы передать информацию между моделью AMPL и реляционной таблицей, необходимо начать с объявления таблицы, которая устанавливает соответствие между ними. Некоторые детали этой декларации зависят от программного обеспечения, используемого для создания и использования таблицы. В определенной ранее модели рациона с четырьмя столбцами, запись, устанавливающая соответствие модели AMPL и данных в базе данных, выглядит следующим образом:
ODBC
- Для таблицы Microsoft Access в файле базы данных diet.mdb:
table Foods IN "ODBC" "diet.mdb": FOOD <- [FOOD], cost, f_min, f_max;
- Для диапазона Microsoft Excel из файла книги diet.xls:
table Foods IN "ODBC" "diet.xls": FOOD <- [FOOD], cost, f_min, f_max;
- Для текстовой таблицы ASCII в файле Foods.tab:
table Foods IN: FOOD <- [FOOD], cost, f_min, f_max;
Каждое объявление таблицы состоит из двух частей (до двоеточия и после него).
table Foods IN "ODBC" "diet.mdb" "table-name" "SQL": FOOD <-[FOOD],cost,f_min,f_max;
Перед двоеточием декларация предоставляет общую информацию. После слова table следует имя таблицы Foods, - это имя, под которым таблица известна в AMPL. Ключевое слово IN утверждает, что по умолчанию все не ключевые столбцы таблицы будут использоваться только для чтения. AMPL будет читать значения из этих столбцов и не будет записывать в них. За ключевым словом IN следует информация о применяемом обработчике таблиц. В AMPL используется 2 обработчика таблиц: ODBC и amplxl. После информации о применяемом обработчике таблиц, располагается информация о файле базы данных, к которому в последствии будет обращаться AMPL.
Относительный и абсолютный путь к BD
Файл базы данных может быть прописан с использованием относительного ..\diet.mdb, либо абсолютного пути D:\ampl\diet.mdb. Базовым каталогом для относительного пути является текущий рабочий каталог AMPL. Следующий атрибут справочного блока "table-name" предоставляет информацию об имени таблицы базы данных. Объявленное имя таблицы AMPL Foods обеспечивает значение по умолчанию, где это необходимо.
table-name
table Foods IN "ODBC" "diet.mdb": FOOD <- [FOOD], cost, f_min, f_max;
Указание имени таблицы базы данных атрибута table-name необходимо только в том случае, когда имя таблицы базы данных отличается от имени таблицы в AMPL. В случае идентичности имен двух таблиц - атрибут table-name остается пустым. После атрибута table-name следует атрибут с помощью которого можно получить данные из различных таблиц базы данных на основании sql-запроса.
- Для Microsoft Access, таблица должна быть прочитана из файла базы данных diet.mdb с использованием обработчика ODBC AMPL. Имя таблицы в файле базы данных по умолчанию считается Foods.
Реляционная таблица Access
- Для Microsoft Excel, таблица должна быть прочитана из файла электронной таблицы diet.xls с использованием обработчика ODBC AMPL. Диапазон электронных таблиц, в котором содержится таблица, принимается по умолчанию за Foods.
Диапазон листа Excel
- При отсутствии подробностей, таблица по умолчанию читается из текстового файла ASCII Foods.tab использующего встроенный обработчик текстовой таблицы AMPL.
В общем, формат символьных строк в объявлении таблицы зависит от используемого обработчика таблицы. После двоеточия объявление таблицы содержит подробности соответствия между объектами AMPL и столбцами реляционной таблицы. Четыре записи, разделенные запятыми, соответствуют четырем столбцам в таблице, начиная с ключевого столбца, отмеченного скобками [...]. В этом примере имена столбцов таблицы FOOD, cost, f_min, f_max совпадают с именами соответствующих компонентов AMPL.
read table
Объявление таблицы определяет только соответствие. Для считывания значений из столбцов реляционной таблицы в наборы и параметры AMPL необходимо явно указать команду:
read table table-name
Таким образом, если значения данных располагаются в реляционной таблице Access, как показано на рисунке:
Реляционная таблица Access с выходными столбцами.
Объявление таблицы для Access можно использовать вместе с командой read table для чтения элементов FOOD и значений стоимости, f_min и f_max в соответствующий AMPL набор и параметры:
model diet.mod; table Foods IN "ODBC" "diet.mdb": FOOD <- [FOOD], cost, f_min, f_max; read table Foods; display cost, f_min, f_max; : cost f_min f_max := BEEF 3.19 2 10 CHK 2.59 2 10 FISH 2.29 2 10 HAM 2.89 2 10 MCH 1.89 2 10 MTL 1.99 2 10 SPG 1.99 2 10 TUR 2.49 2 10 ;
Вывод данных с помощью команды display подтверждает, что нужные значения были прочитаны из базы данных. В случае, когда необходимо прочитать данные из листа Excel, выражение соответствия идентично форме Access, за исключением использования в объявлении имени файла и именованного диапазона Excel:
model diet.mod; table Foods IN "ODBC" "diet.xls":FOOD <- [FOOD], cost, f_min, f_max; read table Foods;
Если значения хранятся в файле Foods.tab, содержащем текстовую таблицу:
ampl.tab 1 3 FOOD cost f_min f_max BEEF 3.19 2 10 CHK 2.59 2 10 FISH 2.29 2 10 HAM 2.89 2 10 MCH 1.89 2 10 MTL 1.99 2 10 SPG 1.99 2 10 TUR 2.49 2 10
Объявление для текстовой таблицы примет следующий вид:
model diet.mod; table Foods IN: FOOD <- [FOOD], cost, f_min, f_max; read table Foods;
Поскольку имя таблицы AMPL Foods одинаково для всех трех примеров, команда чтения таблицы одинакова для трех случаев: read table Foods. В общем, команда чтения таблицы определяет только имя AMPL таблицы, которую нужно прочитать. Вся информация о том, что должно быть прочитано, и как это должно быть обработано, указывается на этапе определения таблицы.
Чтобы создать второй (7-колоночный) пример реляционной таблицы из предыдущего раздела, мы могли бы использовать пару объявлений таблиц:
table ImportFoods IN "ODBC" "diet.mdb" "Foods": FOOD <- [FOOD], cost, f_min, f_max; пробелы обязательны . table ImportFoods IN "ODBC" "diet.mdb" "Foods": FOOD <- [FOOD], cost, f_min, f_max; table ExportFoods OUT "ODBC" "diet.mdb" "Foods": FOOD <- [FOOD], Buy, Buy.rc ˜ BuyRC, {j in FOOD} Buy[j]/f_max[j] ˜ BuyFrac;
Или одно объявление таблицы, объединяющее входную и выходную информацию:
table Foods "ODBC" "diet.mdb": [FOOD] IN, cost IN, f_min IN, f_max IN, Buy OUT, Buy.rc ˜ BuyRC OUT, {j in FOOD} Buy[j]/f_max[j] ˜ BuyFrac OUT;
write table
Чтобы записать результаты обратно в базу данных Access, необходимо прочитать все данные модели диеты, решить ее, и затем объявить команду write table. Вот как это может выглядеть, используя отдельные объявления таблиц для чтения и записи таблицы Access:
model diet.mod; table ImportFoods IN "ODBC" "diet.mdb" "Foods": FOOD <- [FOOD], cost, f_min, f_max; table Nutrs IN "ODBC" "diet.mdb": NUTR <- [NUTR],n_min, n_max; table Amts IN "ODBC" "diet.mdb": [NUTR, FOOD], amt; read table ImportFoods; read table Nutrs; read table Amts; solve; table ExportFoods OUT "ODBC" "diet.mdb" "Foods": FOOD <- [FOOD], Buy, Buy.rc ˜ BuyRC, {j in FOOD} Buy[j]/f_max[j] ˜ BuyFrac; write table ExportFoods;
Альтернатива, использующая одно объявление для чтения и записи Foods:
model diet.mod; table Foods "ODBC" "diet.mdb": [FOOD] IN, cost IN, f_min IN, f_max IN, Buy OUT, Buy.rc ˜ BuyRC OUT, {j in FOOD} Buy[j]/f_max[j] ˜ BuyFrac OUT; table Nutrs IN "ODBC" "diet.mdb": NUTR <- [NUTR], n_min, n_max; table Amts IN "ODBC" "diet.mdb": [NUTR, FOOD], amt; read table Foods; read table Nutrs; read table Amts; solve; write table Foods;
В любом случае таблица Access Foods будет иметь три дополнительных столбца, как показано на рисунке:
Те же операции обрабатываются аналогично для других типов файлов базы данных. В общем, действия команды write table определяются ранее объявленной таблицей AMPL, названной в команде table Foods..., и состоянием внешнего файла, связанного с таблицей AMPL через объявление таблицы. В зависимости от обстоятельств команда записи таблицы может:
- Создать новый внешний файл или таблицу;
- Перезаписать существующую таблицу;
- Перезаписать отдельные столбцы в существующей таблице;
- Добавить столбцы в существующую таблицу.
Объявление таблицы одинаково для многомерных объектов AMPL, за исключением того, что в скобках [] должно быть указано более одного ключевого столбца. Для примера производства стали, соответствие реляционной таблице можно настроить следующим образом:
table SteelProd "ODBC" "steel.mdb": [PROD, TIME], market IN, revenue IN, Make OUT, Sell OUT, Inv OUT;
Здесь ключевые столбцы PROD и TIME не указаны как IN. Это связано с тем, что считываемые параметры, market и revenue, индексируются в модели AMPL по набору {PROD, 1..T}, членство в котором будет определяться с помощью других, более простых таблиц. Команда чтения таблицы SteelProd просто использует записи PROD и TIME для каждой строки базы данных, чтобы определить пару индексов, которые должны быть связаны с market и revenue.
В нашем примере транспортировки также используется реляционная таблица для двумерных объектов. Объявление связанной таблицы аналогично:
table TransLinks "ODBC" "trans.xls" "Links": LINKS <- [ORIG, DEST], cost IN, Trans OUT;
Разница заключается в том, что LINKS, набор пар AMPL, по которым индексируются cost и Trans, является частью данных, а не определяется из более простых наборов или параметров. Таким образом, мы пишем LINKS <- [ORIG, DEST], чтобы запросить чтение пар из ключевых столбцов в LINKS одновременно с чтением соответствующих значений в cost.
Как можно видеть из наших, даже простых примеров, операторы таблиц неудобны для интерактивного ввода. Вместо этого, они обычно помещаются в программы AMPL или сценарии. Операторы чтения и записи таблицы, также могут быть включены в сценарии. Можно определить таблицу, а затем сразу же прочитать или записать ее, как показано в некоторых наших примерах выше. Однако сценарий часто более читабелен, если сложные операторы таблицы отделены от операторов, которые читают и записывают таблицы. Полные образцы сценариев и файлы Access или Excel для примеров рациона, производства и транспортировки можно получить на веб-сайте AMPL.