Удаление или переопределение компонентов модели
Команда delete удаляет ранее объявленный компонент модели при условии, что другие компоненты не используют его в своих объявлениях. Форма команды - определяющее слово delete, за которым следует разделенный запятыми список имен компонентов модели:
model dietobj.mod; data dietobj.dat; delete Total_Number, Diet_Min;
Нельзя удалить набор, параметр или переменную, которые используются позже в модели. Но можно удалить любую целевую функцию или ограничение. Также можно указать компонент name формы check n, чтобы удалить n-й оператор check в текущей модели.
Команда purge удаляет не только перечисленные компоненты, но и все компоненты, которые зависят от них, либо напрямую (путем ссылки на них), либо косвенно (путем ссылки на их иждивенцев). purge имеет ту же форму, но с ключевым словом purge вместо delete. Рассмотрим следующий пример использования команды purge:
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]; minimize Total_Cost: sum {j in FOOD} cost[j] * Buy[j];
Команда purge f_min удаляет параметр f_min и компоненты, объявления которых относятся к f_min, включая параметр f_max, переменную Buy и цель Total_Cost, которая косвенно зависит от f_min посредством ссылки на Buy .
Что бы узнать, какие элементы модели зависят от определенного компонента, необходимо использовать команду xref:
xref f_min; # 4 entities depend on f_min: f_max Buy Total_Cost Diet
Команды delete, purge и xref могут быть применены к любому списку компонентов модели. После удаления компонента с помощью delete или purge, любое ранее скрытое значение имени компонента снова становится видимым. Например, после удаления ограничения с именем prod, AMPL снова распознает prod, как оператор повторного умножения. Если ранее не было скрытого значения, имя компонента, удаляемого при delete или purge, снова становится неиспользованным. Впоследствии, оно может быть объявлено как имя любого нового компонента. В том случае, когда необходимо внести относительно небольшие изменения в объявления, может пригодиться команда redeclare. Объявление данной команды имеет следующий вид:
redeclare param f_min{FOOD} > 0 integer;
redeclare изменяет только условия для f_min. Объявления всех компонентов, которые зависят от f_min, остаются неизменными, как и все значения f_min.
Операторы fix, unfix; drop, restore
reset
Самый простой (но самый радикальный) способ изменить модель - выполнить команду reset, которая удаляет всю текущую модель и данные. После reset можно ввести новую модель model и команды data, чтобы установить новую проблему оптимизации. Эффект reset подобен вводу quit и перезапуску AMPL, за исключением того, что параметры не сбрасываются до значений по умолчанию. Если операционная система или графическая оболочка для AMPL позволяют редактировать файлы, сохраняя AMPL активным, reset полезен для отладки и экспериментов. Можно внести изменения в модель или файлы данных, ввести reset, а затем прочитать измененные файлы.
shell
(Если нужно выйти из AMPL для запуска текстового редактора, тогда нужно использовать команду shell.
drop
Команда drop заставляет AMPL игнорировать определенные ограничения или цели текущей модели. В качестве примера, если модель содержит индексированное ограничение:
subject to Diet_Max {i in MAXREQ}: sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i];
Тогда, команда drop может указать одно из этих ограничений, которое следует игнорировать:
drop Diet_Max["CAL"];
drop может указывать все ограничения или цели, проиндексированные некоторым набором:
drop {i in MAXNOT} Diet_Max[i];
Где MAXNOT, ранее был определен как некоторое подмножество MAXREQ. Весь набор ограничений может быть проигнорирован:
drop{i in MAXREQ} Diet_Max[i];
или проще:
drop Diet_Max;
Как правило, эта команда состоит из ключевого слова drop, необязательного индексного выражения и имени ограничения, которое может быть проигнорировано. Последовательные команды drop имеют накопительный эффект.
restore
Команда restore отменяет эффект drop. Она имеет тот же синтаксис, за исключением ключевого слова restore.
Fix, unfix
Команда fix фиксирует указанные переменные в их текущих значениях, как если бы было ограничение, что переменные должны равняться этим значениям. Команда unfix отменяет эффект fix. Эти команды имеют тот же синтаксис, что и drop и restore, за исключением того, что они именуют переменные, а не ограничения. В представленном ниже примере, устанавливаются значения всех переменных задачи с рационом равными их нижним границам. Фиксируются значения всех переменных, представляющих продукты, в которых содержится более 1200 мг натрия в упаковке, и оптимизируются оставшиеся переменные:
let{j in FOOD} Buy[j]:= f_min[j]; fix{j in FOOD: amt["NA",j] > 1200} Buy[j]; solve; MINOS 5.5: optimal solution found. 7 iterations, objective 86.92 Objective = Total_Cost[’A&P’] display{j in FOOD} (Buy[j].lb,Buy[j],amt["NA",j]); : Buy[j].lb Buy[j] amt[’NA’,j] := BEEF 2 2 938 CHK 2 2 2180 FISH 2 10 945 HAM 2 2 278 MCH 2 9.4285 1182 MTL 2 10 896 SPG 2 2 1329 TUR 2 2 1397 ;
Вместо того, чтобы устанавливать и исправлять переменные в отдельных выражениях, можно добавить определяющую фразу в команду fix:
fix {j in FOOD: amt["NA",j] > 1200} Buy[j] := f_min[j];
Команда unfix работает таким же образом, чтобы отменить эффект исправления и при необходимости также сбросить значение переменной.
Ослабление целостности
option relax_integrality
Изменение параметра relax_integrality со значения по умолчанию 0 на любое ненулевое значение:
option relax_integrality 1;
Говорит AMPL игнорировать ограничения целочисленности всех переменных. Переменные, объявленные как integer, получают границы, которые пользователь указал для них. В то время как переменные, объявленные как binary, получают в качестве значения нижней границы, - ноль, а верхней, - единицу. Чтобы восстановить ограничения целостности, необходимо установить параметр relax_integrality обратно в 0.
Суффикс .relax
Имя переменной, за которым следует суффикс .relax, указывает ее текущий статус ослабления целостности: 0, если применяется целостность, в противном случае - ненулевое значение. Можно использовать этот суффикс, чтобы ослабить целостность только для выбранных переменных. Например,
let Buy[’CHK’].relax = 1;
ослабляет целостность только для переменной Buy[’CHK’]. Тогда как,
let {j in FOOD: f_min[j] > allow_frac} Buy[j].relax := 1;
ослабляет целостность всех переменных Buy для продуктов, у которых объем покупки больше чем значение параметра allow_frac. Некоторые из решателей, которые работают с AMPL, предоставляют свои собственные указания для ослабления целостности, но они не обязательно имеют тот же эффект, что и опция AMPL relax_integrality или суффикс .relax. Эти различия обусловлены последствиями этапа упрощения или предварительного решения проблемы AMPL. AMPL снимает ограничения целостности перед фазой предварительного решения, так что решатель получает истинное непрерывное ослабление исходной целочисленной задачи. Если ослабление выполняется решателем, тогда ограничения целостности все еще действуют в течение фазы предварительного решения AMPL, и в результате AMPL может выполнить некоторое дополнительное сжатие и упрощение.
В качестве простого примера, предположим, что объявления переменных модели диеты написаны так, чтобы можно было регулировать ограничения для рациона f_max путем установки дополнительного параметра scale:
var Buy {j in FOOD} integer >= f_min[j], <= scale * f_max[j];
В примере, все значения f_max равны 10.
set NUTR; set FOOD; param cost {FOOD} > 0; param f_min {FOOD} >= 0; param f_max {j in FOOD} >= f_min[j]; param n_min {NUTR} >= 0; param n_max {i in NUTR} >= n_min[i]; param scale; param amt {NUTR,FOOD} >= 0; var Buy {j in FOOD} integer >= f_min[j], <= scale * f_max[j]; minimize Total_Cost: sum {j in FOOD} cost[j] * Buy[j]; subject to Diet {i in NUTR}: n_min[i] <= sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i]; set NUTR := A B1 B2 C NA CAL ; set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ;
param: 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 ; |
param: n_min n_max := A 700 20000 C 700 20000 B1 700 20000 B2 700 20000 NA 0 40000 CAL 16000 24000 ; |
param amt (tr): A C B1 B2 NA CAL := BEEF 60 20 10 15 938 295 CHK 8 0 20 20 2180 770 FISH 8 10 15 10 945 440 HAM 40 40 35 10 278 430 MCH 15 35 15 15 1182 315 MTL 70 30 15 15 896 400 SPG 25 50 25 15 1329 370 TUR 60 20 15 10 1397 450 ;
Установив значение параметра scale равным 0,95, мы получим следующие результаты решения:
option relax_integrality; option relax_integrality 0; let scale := 0.95; solve; CPLEX 8.0.0: optimal integer solution; objective 122.89 6 MIP simplex iterations 0 branch-and-bound nodes
Когда в AMPL не указано никакого ослабления целчисленности, presolve видит, что все переменные имеют верхние пределы 9.5. AMPL знает (на основании введенных значений), что переменные должны принимать целочисленные значения, в результате он округляет значения до 9. Затем эти пределы отправляются в решатель, где они остаются, даже если мы даем указание решателю ослабить целочисленность:
option cplex_options ’relax’; solve; CPLEX 8.0.0: relax Ignoring integrality of 8 variables. CPLEX 8.0.0: optimal solution; objective 120.2421057 2 dual simplex iterations (0 in phase I) display Buy; Buy [*] := BEEF 8.39898 CHK 2 FISH 2 HAM 9 MCH 9 MTL 9 SPG 8.93436 TUR 2 ;
Если вместо этого для параметра relax_integrality задано значение 1, то на стадии предварительного решения верхние границы сохраняются равными 9,5. Эти границы отправляются решателю, что позволяет сделать решение задачи менее трудным и, следовательно, получить лучшее решение:
option relax_integrality 1; solve; CPLEX 8.0.0: optimal solution; objective 119.1507545 3 dual simplex iterations (0 in phase I) display Buy; Buy [*] := BEEF 6.8798 CHK 2 FISH 2 HAM 9.5 MCH 9.5 MTL 9.5 SPG 9.1202 TUR 2 ;
Переменные, которые были в верхней границе, равной 9 в предыдущем решении, теперь находятся в верхней границе 9.5. Та же самая ситуация может возникнуть в гораздо менее очевидных обстоятельствах и может привести к неожиданным результатам. Как правило, оптимальное значение целочисленной программы с параметром AMPL relax_integrality может быть ниже (для минимизации) или выше (для максимизации), чем оптимальное значение, переданное решателю с указаниями ослабления.