Общий вид синтаксиса
Общий вид синтаксиса выражений при использовании операторов данных имеет следующий вид:
Форма |
Описание компонентов |
sexpr set-op sexpr Пример: PROD union DEST opname indexing sexpr |
sexpr – выражение набора
set-op: union, diff, symdiff, inter, cross. где opname: union или inter |
Операторы работы с наборами
AMPL имеет четыре оператора, которые создают новые наборы из существующих:
union
A union B union: in either A or B
inter
A inter B intersection: in both A and B, = {i in a: i in b};
diff
A diff B difference: in A but not B = {i in a: i not in b};
symdiff
A symdiff B symmetric difference: in A or B but not both.
Сcоздание новых наборов:
ampl: set Y1 = 1990 .. 2020 by 5; ampl: set Y2 = 2000 .. 2025 by 5; ampl: display Y1 union Y2, Y1 inter Y2; set Y1 union Y2 := 1990 1995 2000 2005 2010 2015 2020 2025; set Y1 inter Y2 := 2000 2005 2010 2015 2020; ampl: display Y1 diff Y2, Y1 symdiff Y2; set Y1 diff Y2 := 1990 1995; set Y1 symdiff Y2 := 1990 1995 2025;
Операндами операторов над наборами могут выступать другие выражения наборов, что позволяет создавать более сложные выражения:
ampl: display Y1 symdiff (Y1 symdiff Y2); set Y1 symdiff (Y1 symdiff Y2) := 2000 2005 2010 2015 2020 2025; ampl: display (Y1 union {2025,2035,2045}) diff Y2; set Y1 union {2025, 2035, 2045} diff Y2 := 1990 1995 2035 2045; ampl: display 2000..2040 by 5 symdiff (Y1 union Y2); set 2000 .. 2040 by 5 symdiff (Y1 union Y2) := 2030 2035 2040 1990 1995;
Однако операнды всегда должны представлять наборы. Например, мы должны записать:
Y1 union {2025}; но никак не: Y1 union 2025
Иерархия приоритета операторов по умолчанию "слева на право", если скобками не задан иной приоритет. Операторы union, diff и symdiff имеют одинаковый приоритет, чуть ниже, чем у inter. Так, например запись:
A union B inter C diff D; идентична: (A union (B inter C)) diff D
Приоритет операторов
Иерархия приоритетов всех операторов AMPL приведена в таблице ниже:
Вы пытаетесь загрузить таблицу неизвестного типа. Возможно, вы не активировали аддон, который требуется для использования этого типа таблицы.
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 amt {NUTR,FOOD} >= 0; # Содержание нутриентов в продуктах var Buy {j in FOOD} >= f_min[j], <= 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]; # Суммарное содержание нутриентов в закупаемых продуктах меньше n_max и больше n_min
Вместо того, чтобы указывать нижний и верхний пределы количества каждого питательного вещества. Предположим, что мы хотим указать отдельно набор питательных веществ, которые имеют нижний предел, и отдельно набор питательных веществ, которые имеют верхний предел. Каждый тип питательного вещества находится в одном и/или другом наборе. В этом случае можно объявить:
set MINREQ; # нутриенты с минимальной потребностью set MAXREQ; # нутриенты с максимальной потребностью set NUTR; # все нутриенты (DUBIOUS)
Однако, тогда мы вынуждены будем полагаться на правильность ввода данных пользователем так, что бы NUTR содержал все элементы MINREQ и MAXREQ. В редком случае это ожидание оправдается, в худшем неверно введенные данные приведут к ошибке. Вместо этого, можно определить NUTR как объединение 2-х наборов:
set NUTR = MINREQ union MAXREQ; # нутриенты с минимальной потребностью + нутриенты с максимальной потребностью var Trans{A union B, A union B} >= 0;
При использовании в качестве бинарных операторов, union и inter обозначают операции двоичного набора, состоящие из объединения и пересечения. Эти ключевые слова могут также использоваться как операторы сокращения.
Все три из этих наборов необходимы, так как минимальное и максимальное ограничение на содержание питательных веществ индексируются по MINREQ и MAXREQ.
param n_min{MINREQ} >= 0; param n_max{MAXREQ} >= 0;
в то время как количество питательных веществ в продуктах индексируется по NUTR: param amt{NUTR,FOOD} >= 0;
Результат преобразований имеет следующий вид:
set MINREQ; # набор нутриентов с минимальной потребностью set MAXREQ; # набор нутриентов с максимальной потребностью set NUTR = MINREQ union MAXREQ; # Все контролируемые нутриенты set FOOD; # Все рассматриваемые продукты param cost{FOOD} > 0; # Стоимость продуктов param f_min{FOOD} >= 0; # Ограничение минимального количества закупаемых продуктов param f_max{j in FOOD} >= f_min[j]; # Ограничение максимального количества закупаемых продуктов param n_min{MINREQ} >= 0; # ограничение минимального содержания веществ param n_max {MAXREQ} >= 0; # Ограничение максимального содержания веществ param amt {NUTR,FOOD} >= 0; # Содержание веществ NUTR в продуктах FOOD var Buy {j in FOOD} >= f_min[j], <= f_max[j]; # количество закупаемых продуктов minimize Total_Cost: sum {j in FOOD} cost[j] * Buy[j]; # минимизировать стоимость закупаемой продуктовой корзины subject to Diet_Min {i in MINREQ}: sum {j in FOOD} amt[i,j] * Buy[j] >= n_min[i]; # Содержание в продуктовой корзине нутриентов >= заданного минимального количества subject to Diet_Max {i in MAXREQ}: sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i]; # Содержание в продуктовой корзине нутриентов <= заданного максимального количества
Объединение набора с индексированным набором
Объединение набора с индексированным набором производится по следующей схеме:
set WARE ; set WARE_CL {WARE}; WARE union (union {w in WARE} WARE_CL[w])