Ограничение переменных в уточняющих фразах
В общем случае, после >= или <= может следовать любое арифметическое выражение в ранее определенных наборах, параметрах с использованием действующих фиктивных индексов. Большинство линейных программ сформулированы таким образом, что каждая переменная является неотрицательной. Объявление переменной AMPL может указывать не отрицательность либо непосредственно через >= 0, либо косвенно, как показано ниже:
param f_min{FOOD} >= 0; param f_max{j in FOOD} >= f_min[j]; var Buy{j in FOOD} >= f_min[j], <= f_max[j];
Значения после >= и <=, являются нижней и верхней границей переменных. Поскольку эти границы представляют собой своего рода ограничение, они также могут быть наложены объявлением ограничений. Поместив простые ограничения (без переменных) в объявление var, можно сделать модель более короткой и четкой.
Простые ограничения (без переменных) можно записывать при объявлении переменных:
param Vmin:= -10; param Vmax:= 10; var V >= Vmin, <= Vmax;
Вид объявления границ для переменных не влияет на оптимальное решение. Некоторые решатели обрабатывают границы специальным образом, чтобы ускорить свои алгоритмы. В AMPL все границы идентифицируются автоматически, независимо от того, как они выражены в модели. Объявления переменных не могут использовать операторы сравнения <, > или <> в уточняющих фразах. Для линейного программирования не имеет смысла ограничивать переменную, скажем <3, поскольку она всегда может быть определена равной 2.99999 ... или настолько близкой к 3, насколько возможно. Фраза «=» в объявлении переменной, приводит к определению, как и при объявлении параметра. Выражение справа от оператора «=» может содержать ранее объявленные переменные, наборы и параметры. Например, вместо записи сложной формулировки многопериодной производственной модели:
maximize Total_Profit: sum {p in PROD, t in 1..T} (sum {a in AREA[p]} revenue[p,a,t]*Sell[p,a,t] - prodcost[p]*Make[p,t] - invcost[p]*Inv[p,t]);
Можно определить отдельные переменные для представления общих доходов Total_Revenue, производственных затрат Total_Prod_Cost и затрат на хранение запасов Total_Inv_Cost:
var Total_Revenue = sum {p in PROD, t in 1..T} sum {a in AREA[p]} revenue[p,a,t] * Sell[p,a,t]; var Total_Prod_Cost = sum {p in PROD, t in 1..T} prodcost[p] * Make[p,t]; var Total_Inv_Cost = sum {p in PROD, t in 1..T} invcost[p] * Inv[p,t];
В этом случае, целевая функция будет сформулирована в виде суммы трех переменных:
maximize Total_Profit: Total_Revenue - Total_Prod_Cost - Total_Inv_Cost;
Объявленная таким образом целевая функция более понятна и легко читаема. Отдельные переменные удобно использовать с оператором display:
display Total_Revenue, Total_Prod_Cost, Total_Inv_Cost; Total_Revenue = 801385 Total_Prod_Cost = 285643 Total_Inv_Cost = 1221
Ниже представлен еще один пример назначения нижних и верхних границ переменных:
set outcome; param nsample; param lb{outcome}; param ub{outcome}; var Y1bar{k in outcome,1..nsample} >= min(0,lb[k],ub[k]), <= max(0,lb[k],ub[k]); var Y1bar{k in outcome,1..nsample} in {0} union interval[lb[k],ub[k]];
переменная равна 0 или находится в интервале между значениями lb[k] и ub[k].
Объявление отдельных переменных не приводят к дополнительным ограничениям в результирующем экземпляре задачи.
Если выражение справа от оператора «=» не содержит переменных, тогда данная запись определяет переменные, которые должны быть зафиксированы в значениях, заданных данными. В этом случае необходимо использовать вместо объявления var, - объявление param. С другой стороны, если необходимо только временно исправить некоторые переменные при разработке или анализе модели, тогда нужно оставить объявления без изменений, а вместо этого, исправить их с помощью команды fix.
Ограничение переменной списком значений
Результирующее значение переменной можно ограничить одним значением из перечня значений. Например:
var N in {0,1750,2250,3000};
Если вместо этого нужно решить 4 раза модель с фиксацией N для 4 различных значений 0, 1750, 2250, 3000, это можно сделать с использованием простого цикла:
set Nvals := {0,1750,2250,3000}; for {i in Nvals} {fix N := i; solve; display N; }