Просмотр результатов
Самый простой способ проверить данные и значения результатов - это ввести интересующую информацию с помощью команды display. Команда display автоматически форматирует значения в интуитивно понятном и привычном виде. Насколько это возможно, display использует те же форматы списков и таблиц, что и операторы данных.
Можно зафиксировать вывод команды display в файл, добавив > filename после команды display. Этот механизм перенаправления применяется также к большинству других команд, которые производят вывод.
Отображение наборов
Содержимое наборов отображается путем ввода display и списка имен наборов. Например:
display ORIG, DEST, LINKS; set ORIG := GARY CLEV PITT; set DEST := FRA DET LAN WIN STL FRE LAF; set LINKS := (GARY,DET) (GARY,LAF) (CLEV,LAN) (CLEV,LAF) (PITT,STL) (GARY,LAN) (CLEV,FRA) (CLEV,WIN) (PITT,FRA) (PITT,FRE) (GARY,STL) (CLEV,DET) (CLEV,STL) (PITT,WIN);
Отображение индексированной коллекции наборов
Если указать имя индексированной коллекции наборов, будет показан каждый набор коллекции:
display PROD, AREA; set PROD := bands coils; set AREA[bands] := east north; set AREA[coils] := east west export;
Отдельные элементы индексированной коллекции можно просматривать по подписке display AREA["band"]. Аргумент display не обязательно должен быть объявленным множеством. Это может быть любое из выражений, которые оцениваются как множества. Например, можно показать объединение всех наборов AREA[p]:
display union {p in PROD} AREA[p]; set union {p in PROD} AREA[p] := east north west export;
Или набор всех транспортных связей, стоимость доставки которых превышает 500:
display {(i,j) in LINKS: cost[i,j] * Trans[i,j] > 500}; set {(i,j) in LINKS: cost[i,j]*Trans[i,j] > 500} := (GARY,STL) (CLEV,DET) (CLEV,WIN) (PITT,FRA) (PITT,FRE) (GARY,LAF) (CLEV,LAN) (CLEV,LAF) (PITT,STL);
Поскольку членство в этом наборе зависит от текущих значений переменных Trans[i,j], нельзя ссылаться на него в модели, но это допустимо в команде display, где переменные обрабатываются так же, как параметры.
Отображение параметров и переменных
Команда display может показать значение компонента скалярной величины:
display T; T = 4
Или значения отдельных компонентов из индексированной коллекции:
display avail["reheat"], avail["roll"]; avail[’reheat’] = 35 avail[’roll’] = 40
Или произвольное выражение:
display sin(1)ˆ2 + cos(1)ˆ2; sin(1)ˆ2 + cos(1)ˆ2 = 1
Однако, основное использование display - отображение проиндексированных коллекций данных. Для «одномерных» данных - параметров или переменных, индексированных по простому набору - AMPL использует формат столбца:
display avail; avail [*] := reheat 35 roll 40 ;
Для «двумерных» параметров или переменных, индексированных по набору пар или двух простых наборов, AMPL формирует список для небольших объемов данных:
display supply; supply := CLEV bands 700 CLEV coils 1600 CLEV plate 300 GARY bands 400 GARY coils 800 GARY plate 200 PITT bands 800 PITT coils 1800 PITT plate 300 ;
Или таблица для больших значений:
display demand; demand [*,*] : bands coils plate := DET 300 750 100 FRA 300 500 100 FRE 225 850 100 LAF 250 500 250 LAN 100 400 0 STL 650 950 200 WIN 75 250 50 ;
Можно контролировать выбор между форматами отображения столбец/список, установив параметр display_1col. Параметр или переменная (или любой другой объект модели), индексированные по набору упорядоченных пар, также рассматриваются как двумерный объект и отображаются в виде списка. Ниже приведен пример отображения параметра, индексированного по набору LINKS:
display cost; cost := CLEV DET 9 CLEV FRA 27 CLEV LAF 17 CLEV LAN 12 CLEV STL 26 CLEV WIN 9 |
GARY DET 14 GARY LAF 8 GARY LAN 11 GARY STL 16 PITT FRA 24 PITT FRE 99 PITT STL 28 PITT WIN 13 ; |
Чтобы отобразить значения, проиндексированные в трех или более измерениях, AMPL формирует отдельные списки для небольших объемов данных. Однако в многомерных объектах чаще всего используются данные в больших количествах. В этом случае AMPL «разбивает» значения на двумерные таблицы:
display Trans; Trans [CLEV,*,*] : bands coils plate := DET 0 750 0 FRA 0 0 0 FRE 0 0 0 LAF 0 500 0 LAN 0 400 0 STL 0 50 0 WIN 0 250 0 |
[GARY,*,*] : bands coils plate := DET 0 0 0 FRA 0 0 0 FRE 225 850 100 LAF 250 0 0 LAN 0 0 0 STL 650 900 200 WIN 0 0 0 |
[PITT,*,*] : bands coils plate := DET 300 0 100 FRA 300 500 100 FRE 0 0 0 LAF 0 0 250 LAN 100 0 0 STL 0 0 0 WIN 75 0 50 ;
В начале первой таблицы шаблон [CLEV,*,*] указывает, что срез проходит через CLEV в первом компоненте, поэтому запись в строке LAF и столбце coils говорит, что Trans ["CLEV", "LAF", «coils»] равен 500. Поскольку первый индекс Trans всегда CLEV, GARY или PITT, в этом случае имеется всего три таблицы срезов. AMPL не всегда разрезает первый компонент, он выбирает фрагменты так, чтобы на дисплее содержалось как можно меньше столбцов. Отображение двух или более компонентов одной и той же размерности всегда представляется в виде списка, независимо от того, являются ли компоненты одномерными или нет:
display inv0, prodcost, invcost; : inv0 prodcost invcost := bands 10 10 2.5 coils 0 11 3 ;
или:
display rate, make_cost, Make; : rate make_cost Make := CLEV bands 190 190 0 CLEV coils 130 170 1950 CLEV plate 160 185 0 GARY bands 200 180 1125 GARY coils 140 170 1750 GARY plate 160 180 300 PITT bands 230 190 775 PITT coils 160 180 500 PITT plate 170 185 500 ;
Индексы отображаются в списке слева, причем крайний с права индекс изменяется наиболее быстро.
Как видно из этих примеров, display обычно размещает метки строк и столбцов в алфавитном или числовом порядке, независимо от того, в каком порядке они могли быть указаны в файле данных. Однако, когда наименования поступают из упорядоченного набора, учитывается исходный порядок:
display avail; avail [*] := 27sep 40 04oct 40 11oct 32 18oct 40 ;
По этой причине может оказаться целесообразным объявить определенные наборы модели упорядоченными, даже если их упорядочение не играет явной роли в формулировке.
Отображение индексированных выражений
Команда display может показывать значение любого арифметического выражения, действительного в модели AMPL:
display sum {p in PROD,t in 1..T} revenue[p,t]*Sell[p,t], sum {p in PROD,t in 1..T} prodcost[p]*Make[p,t], sum {p in PROD,t in 1..T} invcost[p]*Inv[p,t]; sum{p in PROD, t in 1 .. T} revenue[p,t]*Sell[p,t] = 787810 sum{p in PROD, t in 1 .. T} prodcost[p]*Make[p,t] = 269477 sum{p in PROD, t in 1 .. T} invcost[p]*Inv[p,t] = 3300
Предположим, однако, что нужно отобразить все отдельные значения revenue[p,t]*Sell[p,t]. display revenue, Sell отображает отдельные значения revenue[p,t] и Sell[p,t]. Однако выражение:
display revenue * Sell; syntax error context: display revenue >>> * <<< Sell;
приведет к ошибке. AMPL не распознает такую арифметику массивов. Чтобы отобразить произведение индексированной коллекции массивов, необходимо явно указать их индексацию:
display {p in PROD, t in 1..T} revenue[p,t]*Sell[p,t]; revenue[p,t]*Sell[p,t] [*,*] (tr) : bands coils := 1 150000 9210 2 156000 87500 3 37800 129500 4 54000 163800 ;
Чтобы применить одну и ту же индексацию к двум и более выражениям, нужно заключить эти выражения в скобки после выражения индексации:
display {p in PROD, t in 1..T}(revenue[p,t]*Sell[p,t], prodcost[p]*Make[p,t]); : revenue[p,t]*Sell[p,t] prodcost[p]*Make[p,t] := bands 1 150000 59900 bands 2 156000 60000 bands 3 37800 14000 bands 4 54000 20000 coils 1 9210 15477 coils 2 87500 15400 coils 3 129500 38500 coils 4 163800 46200 ;
Индексное выражение, за которым следует выражение или заключенный в скобки список выражений, обрабатывается как один элемент отображения, который указывает некоторую проиндексированную коллекцию значений. Команда display может содержать один из этих элементов, как указано выше, или их список через запятую.
Представление значений для индексированных выражений следует тем же правилам, что и для отдельных параметров и переменных:
display revenue, Sell
как сокращение для
display {p in PROD, t in 1..T} (revenue[p,t],Sell[p,t]); : revenue[p,t] Sell[p,t] := bands 1 25 6000 bands 2 26 6000 bands 3 27 1400 bands 4 27 2000 coils 1 30 307 coils 2 35 2500 coils 3 37 3500 coils 4 39 4200 ;
Если переставить индексирующее выражение так, чтобы t in 1..T было на первом месте, тогда, строки списка будут отсортированы первыми по элементам 1..T:
display {t in 1..T, p in PROD} (revenue[p,t],Sell[p,t]); revenue[p,t] Sell[p,t] := 1 bands 25 6000 1 coils 30 307 2 bands 26 6000 2 coils 35 2500 3 bands 27 1400 3 coils 37 3500 4 bands 27 2000 4 coils 39 4200 ;
Это изменение в представлении по умолчанию может быть достигнуто только путем размещения явного индексного выражения после display.
Помимо индексации отдельных элементов, можно указать набор, по которому индексируется вся команда display, то есть можно попросить выполнить команду один раз для каждого элемента набора индексации. Эта функция особенно полезна для перестановки срезов многомерных таблиц. Ранее отображалась трехмерная переменная Trans, индексированная по {ORIG, DEST, PROD}, AMPL разделил отображаемые значения по элементам ORIG, чтобы создать серию двумерных таблиц. Если нужно отобразить фрагменты разделенные по PROD, тогда необходимо это явно указать. Для этого после команды display следует индексное выражение, по которому необходимо сделать срезы {p in PROD}:, затем указывается общее индексное выражение:
display {p in PROD}: {i in ORIG, j in DEST} Trans[i,j,p];
Trans[i,j,’bands’] [*,*] (tr) : CLEV GARY PITT := DET 0 0 300 FRA 0 0 300 FRE 0 225 0 LAF 0 250 0 LAN 0 0 100 STL 0 650 0 WIN 0 0 75 ; |
Trans[i,j,’coils’] [*,*] (tr) : CLEV GARY PITT := DET 750 0 0 FRA 0 0 500 FRE 0 850 0 LAF 500 0 0 LAN 400 0 0 STL 50 900 0 WIN 250 0 0 ; |
Trans[i,j,’plate’] [*,*] (tr) : CLEV GARY PITT := DET 0 0 100 FRA 0 0 100 FRE 0 100 0 LAF 0 0 250 LAN 0 0 0 STL 0 200 0 WIN 0 0 50 ;
Как показывает этот пример, если display задает выражение индексации в самом начале, за которым следует двоеточие, набор индексации применяется ко всей команде. Выражения после двоеточия оцениваются и отображаются отдельно для каждого элемента набора определенного до двоеточия.
Отображение данных с условием для отображаемых значений
Можно написать оператор display с условием для отображаемых значений:
display {i in S,j in T, k in U: visit[i,j] = 1 and TA_F1[i,j,k] < 10000} TA_F1[i,j,k];