Оператор: IN
Чтобы использовать внешнюю реляционную таблицу только для чтения, необходимо использовать атрибут IN в объявлении таблицы, определяющий состояние чтения/записи. Атрибут должен соответствовать общей форме:
table table-name IN string-list: key-spec,data-spec, data-spec, ... ;
Где необязательный string-list зависит от типа базы данных и используемого метода доступа. (В интересах краткости большинство последующих примеров не показывают string-list). key-spec называет ключевые столбцы, а data-spec определяет столбцы данных. Значения данных впоследствии считываются из таблицы в объекты AMPL командой:
read table table-name;
Которая определяет значения для чтения, ссылаясь на объявленное имя таблицы.
Чтение только параметров
Чтобы назначить значения из столбцов данных, - параметрам AMPL с одинаковыми именами, достаточно дать в скобках список ключевых столбцов, а затем список столбцов данных. Простейший случай, когда есть только один ключевой столбец, иллюстрируется:
table Foods IN: [FOOD], cost, f_min, f_max;
Эта запись указывает на то, что реляционная таблица имеет четыре столбца. Ключевой столбец FOOD и столбцы данных cost, f_min и f_max. Столбцы данных связаны с параметрами cost, f_min и f_max в текущей модели AMPL. Поскольку имеется только один ключевой столбец, все эти параметры должны быть проиндексированы по одномерным наборам. Когда выполняется команда:
read table Foods
Реляционная таблица читается по одной строке за раз. Запись строки в ключевом столбце интерпретируется как подстрочный индекс для каждого из параметров. Этим подписанным параметрам присваиваются записи строки из связанных столбцов данных. Например, если реляционная таблица имеет вид:
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
Обработка первой строки присваивает значения 3.19 параметру cost[’BEEF’], 2 -f_min[’BEEF’] и 10 - f_max[’BEEF’]. Обработка второй строки присваивает 2,59 cost [’CHK’], 2 - f_min[’CHK’] и 10 - f_max[’CHK’]. И так далее все шесть оставшихся рядов.
Во время выполнения команды read table, AMPL не делает никаких предположений о том, как объявляются параметры. Они не должны быть проиндексированы для набора с именем FOOD, и, действительно, элементы их наборов индексации могут даже не быть известны. Только позже, когда впервые используется каждый параметр в каких-либо вычислениях, AMPL проверяет записи, считанные из ключевого столбца FOOD, чтобы убедиться, что каждый из них является допустимым индексом для этого параметра.
Ситуация аналогична для многомерных параметров. Имя каждого столбца данных должно быть именем параметра AMPL, а размерность набора индексации параметра должна равняться количеству ключевых столбцов. Например, если в скобках указаны два ключевых столбца:
table SteelProd IN: [PROD, TIME], market, revenue;
Перечисленные столбцы данных, market, revenue, должны соответствовать параметрам AMPL market и revenue, которые индексируются по двумерному набору.
Когда выполняется чтение таблицы SteelProd, записи каждой строки в ключевых столбцах интерпретируются как пара индексов для каждого из параметров. Таким образом, если реляционная таблица имеет вид:
PROD TIME market revenue bands 1 6000 25 bands 2 6000 26 bands 3 4000 27 bands 4 6500 27 coils 1 4000 30 coils 2 2500 35 coils 3 3500 37 coils 4 4200 39
Обработка первой строки назначит 6000 для market[’bands’,1] и 25 для revenue[’bands’,1] обработка второй строки назначит 6000 market[’bands’,2] и 26 для revenue[’bands’,2]. И так далее через все восемь рядов. Пары индексов, заданные записями ключевого столбца, должны быть определены для market и revenue, когда значения этих параметров впервые нужны AMPL.
Поскольку реляционная таблица имеет только одну коллекцию ключевых столбцов, AMPL применяет одинаковую подписку к каждому из параметров, из столбцов данных. Параметры, индексированные по одинаковому набору, можно разместить в одной таблице базы данных, оставив пустыми любые записи в строках, соответствующие недействительным подпискам. Способ указания пустой записи зависит от используемого программного обеспечения базы данных.
Значения неиндексированных (скалярных) параметров могут быть предоставлены реляционной таблицей. Для этого таблица должна содержать одну строку и не содержать ключевые столбцы. Так, что каждый столбец данных содержит ровно одно значение. Соответствующее объявление таблицы имеет пустую спецификацию ключа, []. Например, чтобы прочитать значение для параметра T, который представляет число периодов в steelT.mod, объявление таблицы должно иметь следующий вид:
table SteelPeriods IN: [], T;
Соответствующая реляционная таблица имеет один столбец, с именем Т. Значение единственной записи каждого столбца является положительным целым числом.
Чтение набора и параметров
Часто удобно читать элементы набора из ключевого столбца или столбцов таблицы. В то время как, параметры, индексированные по этому набору, считываются из столбцов данных. Чтобы указать, что набор должен быть прочитан из таблицы, спецификация ключа в объявлении таблицы записывается в виде:
set-name <- [key-col-spec, key-col-spec, ...]
Символ <- используется как ссылка, указывающая направление перемещения информации от ключевых столбцов к набору AMPL.
Простейший случай включает чтение одномерного набора и индексированных по нему параметров diet.mod:
table Foods IN: FOOD <- [FoodName], cost, f_min, f_max;
Когда выполняется команда чтения таблицы Foods, все записи в ключевом столбце FoodName реляционной таблицы считываются в AMPL, как элементы набора FOOD. Записи в столбцах данных cost, f_min и f_max читаются в одноименные параметры AMPL, как описано ранее. Если ключевой столбец называется FOOD, как и набор AMPL, тогда соответствующее объявление таблицы имеет следующий вид:
table Foods IN: FOOD <- [FOOD], cost, f_min, f_max;
Только в этом особом случае, спецификация ключа также может быть записана в сокращенной форме [FOOD] IN.
Аналогичный синтаксис используется для чтения многомерного набора вместе с индексированными по ним параметрами. Например, в случае transp3.mod объявление таблицы будет иметь следующий вид:
table TransLinks IN: LINKS <- [ORIG, DEST], cost;
Когда выполняется чтение таблицы TransLinks, каждая строка таблицы предоставляет пару записей из ключевых столбцов ORIG и DEST. Все подобные пары считываются в AMPL как элементы двумерного набора LINKS. Записи столбца cost считываются в параметр cost обычным способом.
Как и в нашем предыдущем многомерном примере, имена в скобках не обязательно должны соответствовать именам наборов в модели AMPL. Имена в квадратных скобках служат только для идентификации ключевых столбцов. Имя слева от стрелки - единственное, которое должно называть ранее объявленный набор AMPL. Более того, этот набор должен быть объявлен с тем же размером или арностью, что и число ключевых столбцов.
Следующая запись читает элементы набора LINKS из реляционной таблицы. LINKS специально объявлен в модели таким образом, что соответствующие данные считываются отдельно:
set ORIG; set DEST; set LINKS within {ORIG,DEST}; param cost {LINKS} >= 0;
В модели transp2.mod, LINKS определяется в терминах двух одномерных наборов:
set ORIG; set DEST; set LINKS = {ORIG,DEST}; param cost {LINKS} >= 0;
В transp.mod вообще не определен ни один двумерный набор:
set ORIG; set DEST; param cost {ORIG,DEST} >= 0;
В этих последних случаях, объявление таблицы все еще будет необходимо для чтения параметра cost, но мы не будем читать какой-либо связанный набор:
table TransLinks IN: [ORIG, DEST], cost;
Вместо этого, будут использоваться отдельные реляционные таблицы для предоставления элементов для одномерных наборов ORIG и DEST и значений для параметров, проиндексированных по ним.
Когда в объявлении таблицы, указан набор AMPL для присваиваемых членов, список спецификаций данных может быть пустым. В этом случае, считываются только ключевые столбцы, и единственное действие таблицы чтения заключается в назначении элементов набора AMPL из значений ключевых столбцов. Например, с заявлением:
table TransLinks IN: LINKS <- [ORIG, DEST];
последующее утверждение таблицы чтения приведет к тому, что будут считаны только значения ключевых столбцов таблицы базы данных в набор LINKS.
Чтение данных с использованием запросов
Декларации наборов и параметров модели AMPL, не обязательно соответствуют во всех отношениях таблицам в соответствующих базах данных. Там, где разница существенна, может потребоваться применение языка запросов базы данных (часто SQL) для получения временных таблиц, имеющих структуру, требуемую моделью.
Чтение индексированных коллекций
Проиндексированную коллекцию наборов можно прочитать из одного диапазона в электронной таблице, используя проиндексированную коллекцию таблиц. Например, для «set A1{p in NP}» с заданными данными, диапазон электронной таблицы может называться setA1 и может быть организован следующим образом:
Столбцы A1_P1_1 и A1_P1_2 содержат пары из набора A1["P1"], а столбцы A1_P2_1 и A1_P2_2 содержат пары из набора A1["P2"]. A1["P1"] и A1["P2"] могут иметь одинаковое количество элементов, но это не обязательно. Следующий оператор таблицы определяет таблицу для каждого p в NP:
table setA1 {p in NP} IN "amplxl" "setofsets.xlsx": A1[p] <- [("A1_"&p&"_1"),("A1_"&p&"_2")];
Строковые выражения типа ("A1 _" & p & "_ 1") используются для указания имен столбцов, которые различаются для каждого значения p. Поскольку существует индексированная коллекция таблиц, для их чтения используется цикл for:
for {p in NP} read table setA1[p];
Поскольку A1[p] - это набор пар, тогда param T_LINKS_F1{p in NP, A1[p]}
индексируется по набору троек. Таким образом, электронная таблица для этого параметра должна иметь 3 ключевых столбца и столбец данных:
а конструкция табличного выражения имеет следующий вид:
table T_LINKS_F1 IN "amplxl" "setofsets.xlsx": [NP,A1_1,A1_2], T_LINKS_F1;
https://groups.google.com/g/ampl/c/UMxeoWoPgZ8
Чтение данных для команды let
В объявлении table, используемом для считывания данных, присваиваемое выражение AMPL может появляться везде, где разрешено имя параметра. Выражение можно назначить через присваивание значения. Например, поместив его слева от := в команде let.
Имена переменных являются присваиваемыми выражениями. Таким образом, объявление таблицы может указывать столбцы данных, которые будут считываться в переменные, с целью оценки ранее сохраненного решения или обеспечения хорошего начального решения для решателя.
Чтение дополнительных данных .sstatus, .relax, .priority
Имена ограничений также являются присваиваемыми выражениями. Значения ‘‘считанные из ограничения” интерпретируются как начальные двойные значения для некоторых решателей, таких как MINOS.
Любое имя переменной или ограничения, определяемое присваиваемым суффиксом, также является присваиваемым выражением. Назначаемые суффиксы включают предопределенное имя, например (.sstatus, .relax), а также любые пользовательские суффиксы. Например, следующее объявление таблицы могло бы помочь предоставить полезную информацию для решателя CPLEX :
table Foods IN:[FOOD] IN,cost,f_min, f_max, Buy, Buy.priority ~prior;
Выполнение команды чтения таблицы Foods предоставит элементы для набора FOOD и значения для параметров cost, f_min и f_max обычным способом, а также назначит начальные значения и приоритеты ветвления для переменных Buy.
Чтение данных из разных столбцов таблицы для различных моделей
Если есть необходимость чтения данных из одного файла/таблицы для разных моделей, например для одной модели прочесть столбец S1D, а для другой - S1, это можно реализовать использованием следующего кода:
*.mod set S1; param modnum; table S_1 IN "tableproxy" "odbc" "MainInput.xlsx": S1 <- [S1]; table S_2 IN "tableproxy" "odbc" "MainInput.xlsx" "S_1": S1 <- [S1D]; let modnum := 1; if modnum = 1 then read table S_1; else read table S_2; display S1; let modnum := 2; if modnum = 1 then read table S_1; else read table S_2; display S1; *.run set S1; table S_1 IN "tableproxy" "odbc" "MainInput.xlsx": S1 <- [S1]; read table S_1; display S1; reset; set S1; table S_1 IN "tableproxy" "odbc" "MainInput.xlsx": S1 <- [S1D]; read table S_1; display S1;