Структура индексированных данных в AMPL имеет много общего со структурой реляционных таблиц, широко используемых в приложениях баз данных. Объявление таблицы AMPL позволяет использовать это сходство для определения явных связей между наборами, параметрами, переменными и выражениями в AMPL и таблицами реляционной базы данных, поддерживаемых другим программным обеспечением. Команды read table и write table впоследствии используют эти соединения для импорта значений данных в AMPL и для экспорта данных и значений решений из AMPL.
Реляционные таблицы, считываемые и записываемые AMPL, находятся в файлах, имена и местоположения которых, указывается как часть объявления таблицы. Для работы с этими файлами используются обработчики таблиц, которые являются надстройками AMPL, загружаемых по мере необходимости. Обработчики могут предоставляться поставщиками решателей или программного обеспечения для баз данных. AMPL имеет встроенные обработчики для двух простых форматов реляционных таблиц. Веб-сайт AMPL предоставляет обработчики, которые работают с широко доступным интерфейсом ODBC.
Общие принципы соответствия данных
Рассмотрим объявления, определяющие набор FOOD и три параметра, индексированные по нему:
set FOOD; param cost{FOOD} > 0; param f_min{FOOD} >= 0; param f_max{j in FOOD} >= f_min[j];
Реляционная таблица, определяющая значения для этих компонентов, имеет четыре столбца:
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 ;
В столбце FOOD перечислены элементы набора AMPL, также называемого FOOD. Это ключевой столбец таблицы. Записи в ключевом столбце должны быть уникальными, как и элементы набора AMPL, чтобы каждое значение ключа идентифицировало ровно одну строку. Столбец с заголовком cost дает значения параметра с одноименным названием, проиндексированного по набору FOOD. Значение cost["BEEF"] указано как 3.19, cost["CHK"] равно 2.59 и так далее. Оставшиеся два столбца дают значения для двух других параметров, проиндексированных по FOOD. Таблица содержит восемь строк данных, по одной для каждого элемента набора. Таким образом, каждая строка содержит все данные таблицы, соответствующие одному элементу, в данном примере - одному продукту. В контексте программного обеспечения базы данных, строки таблицы часто рассматриваются как записи данных, а столбцы - как поля внутри каждой записи. Таким образом, форма ввода данных имеет одно поле ввода для каждого столбца. Форма для примера диеты (из Microsoft Access) может выглядеть так:
Параметры не являются единственными объектами, индексированными по FOOD в этом примере. Есть также переменные:
var Buy {j in FOOD} >= f_min[j], <= f_max[j];
и различные выражения результата, которые могут отображаться:
model diet.mod; data diet2a.dat; solve; MINOS 5.5: optimal solution found. 13 iterations, objective 118.0594032 display Buy, Buy.rc, {j in FOOD} Buy[j]/f_max[j]; : Buy Buy.rc Buy[j]/f_max[j] := BEEF 5.36061 8.88178e-16 0.536061 CHK 2 1.18884 0.2 FISH 2 1.14441 0.2 HAM 10 -0.302651 1 MCH 10 -0.551151 1 MTL 10 -1.3289 1 SPG 9.30605 0 0.930605 TUR 2 2.73162 0.2 ;
Все они могут быть включены в реляционную таблицу для значений, индексированных по FOOD:
FOOD cost f_min f_max Buy BuyRC BuyFrac BEEF 3.19 2 10 5.36061 8.88178e-16 0.536061 CHK 2.59 2 10 2 1.18884 0.2 FISH 2.29 2 10 2 1.14441 0.2 HAM 2.89 2 10 10 -0.302651 1 MCH 1.89 2 10 10 -0.551151 1 MTL 1.99 2 10 10 -1.3289 1 SPG 1.99 2 10 9.30605 0 0.930605 TUR 2.49 2 10 2 2.73162 0.2
Если первые четыре столбца считываются из базы данных в AMPL, то последние три - это результаты, которые записываются обратно в базу данных AMPL. Мы назначили имена заголовкам столбцов BuyRC и BuyFrac, поскольку имена AMPL этих столбцов, обычно не являются допустимыми именами столбцов в системах управления базами данных. Другие объекты diet.mod индексируются по набору NUTR (питательные вещества): параметры n_min и n_max, двойные цены и другие значения, связанные с ограничением Diet, и выражения, включающие их. Поскольку наборы PROD и NUTR полностью отличаются друг от друга, значения, проиндексированные по NUTR заносятся в отдельную реляционную таблицу:
NUTR n_min n_max NutrDual A 700 20000 0 B1 700 20000 0 B2 700 20000 0.404585 C 700 20000 0 CAL 16000 24000 0 NA 0 50000 -0.00306905
Как показывает этот пример, любой модели, имеющей более одного набора индексации, потребуется более одной реляционной таблицы для хранения своих данных и результатов. Объекты, индексированные по одному многомерному набору, имеют сходство с реляционной таблицей. С одним ключевым столбцом для каждого измерения. Например, в случае steelT.mod следующие параметры и переменные индексируются для одного и того же двумерного набора пар продукт-время:
set PROD; # продукты param T > 0; # количество недель param market{PROD,1..T} >= 0; param revenue{PROD,1..T} >= 0; var Make{PROD,1..T} >= 0; var Sell{p in PROD, t in 1..T} >= 0, <= market[p,t];
Таким образом, соответствующая реляционная таблица имеет два ключевых столбца, один из которых содержит элементы PROD, а другой - элементы 1..T, и затем столбец значений для каждого параметра и переменной:
PROD TIME market revenue Make Sell bands 1 6000 25 5990 6000 bands 2 6000 26 6000 6000 bands 3 4000 27 1400 1400 bands 4 6500 27 2000 2000 coils 1 4000 30 1407 307 coils 2 2500 35 1400 2500 coils 3 3500 37 3500 3500 coils 4 4200 39 4200 4200 ;
Каждая упорядоченная пара элементов двух ключевых столбцов, - уникальна в этой таблице, так же как эти пары уникальны в наборе {PROD, 1..T}. Столбец market в таблице подразумевает, что market["band",1] равен 6000, а market["coils",3] - 3500. Из первой строки мы также видим, что revenue["band",1] - 25, Make["band",1 ] - 5990, а Sell["band",1] - 6000. Различные имена из модели AMPL используются в качестве заголовков столбцов, за исключением TIME, которое должно быть придумано для обозначения выражения 1..Т. Как и в предыдущем примере, заголовки столбцов могут быть любыми идентификаторами, приемлемыми для программного обеспечения базы данных, а объявление таблицы позаботится о соответствии именам AMPL.
Объекты AMPL, которые имеют достаточно похожую индексацию, обычно вписываются в одну и ту же реляционную таблицу. Мы могли бы расширить таблицу steelT.mod, например, добавив столбец для значений:
var Inv {PROD,0..T} >= 0;
Таблица будет иметь следующий вид:
PROD TIME market revenue Make Sell Inv bands 0 . . . . 10 bands 1 6000 25 5990 6000 0 bands 2 6000 26 6000 6000 0 bands 3 4000 27 1400 1400 0 bands 4 6500 27 2000 2000 0 coils 0 . . . . 0 coils 1 4000 30 1407 307 1100 coils 2 2500 35 1400 2500 0 coils 3 3500 37 3500 3500 0 coils 4 4200 39 4200 4200 0 ;
Использование «.» описывает не определенные в модели данные. Например, в данных для этой модели нет market["band",0], однако в результатах есть значение Inv["band",0]. Базы данных различаются по способу обработки «Отсутствующих NULL» записей такого рода.
Параметры и переменные также могут быть проиндексированы для набора пар, которые считываются как данные, а не составляются из одномерных наборов. Например, в модели transp3.mod мы имеем:
set LINKS within {ORIG,DEST}; param cost {LINKS} >= 0; # стоимость перевозки единицы продукта var Trans {LINKS} >= 0; # фактические единицы для отправки
Соответствующая реляционная таблица имеет два ключевых столбца, соответствующие двум компонентам набора индексации LINKS, дополнительные столбцы для параметра и переменной, которые индексируются по LINKS:
ORIG DEST cost Trans GARY DET 14 0 GARY LAF 8 600 GARY LAN 11 0 GARY STL 16 800 CLEV DET 9 1200 CLEV FRA 27 0 CLEV LAF 17 400 |
CLEV LAN 12 600 CLEV STL 26 0 CLEV WIN 9 400 PITT FRA 24 900 PITT FRE 99 1100 PITT STL 28 900 PITT WIN 13 0 ; |
Структура таблицы данных такая же, как и в предыдущем примере. Однако в таблице есть строка для каждой пары источник-пункт назначения ORIG,DEST, которая фактически находится в наборе LINKS, а не для каждой возможной пары ORIG - DEST.
Установление соответствий
Декларации наборов и параметров модели AMPL, не обязательно соответствуют во всех отношениях таблицам в соответствующих базах данных. Там, где разница существенна, может потребоваться применение языка запросов базы данных (часто SQL) для получения временных таблиц, имеющих структуру, требуемую моделью.
Ряд общих простых различий можно обрабатывать напрямую с помощью функций декларации таблицы.
Различия в именовании, пожалуй, самые распространенные. Объявление таблицы может связать столбец данных и параметр AMPL с другим именем, используя спецификацию данных вида:
param-name ~data-col-name
Так, например, если таблица Foods была определена как:
table Foods IN: [FOOD], cost, f_min ~lowerlim, f_max ~upperlim;
параметры AMPL f_min и f_max, будут считываться из столбцов данных lowerlim и upperlim реляционной таблицы. (Параметр cost будет считываться из столбца cost, как и раньше.)