union, inter, diff и symdiff, card, in, within
Операции над составными наборами, насколько это возможно, аналогичны операциям для простых наборов. Наборы пар, троек или более длинных кортежей можно комбинировать с union, inter, diff и symdiff. Кортежи могут быть проверены конструкциями in и within, подсчитано их количество элементов с помощью card. Размеры операндов должны совпадать. Нельзя объединить наборы пар с набором троек. Кроме того, составные наборы в AMPL не могут быть объявлены как упорядоченные или циклические. Следовательно, кортежи не могут быть аргументами таких функций как first и next и других описанных ранее, которые работают только с упорядоченными наборами.
cross
Результатом действия оператора множества cross, является множество всех пар его аргументов. Оператор cross обозначает декартово произведение. Таким образом, задав выражение:
ORIG cross DEST
мы определяем тот же набор, что и индексное выражение {ORIG, DEST}.
А запись: ORIG cross DEST cross PROD дает тот же результат, что и индексное выражение {ORIG, DEST, PROD}.
Как и в случае простых наборов, членство в составном наборе может быть ограничено логическим условием в конце выражения индексации. Например, для модели смешанной перевозки можно определить:
set DEMAND = {j in DEST, p in PROD: demand[j,p] > 0};
Так что DEMAND содержит только пары (j,p) с положительным спросом на продукт p в пункте назначения j. В качестве другого примера: предположим, что мы также хотели бы смоделировать передачу продуктов из одного источника в другой. Мы могли бы просто определить:
set TRANSF = {ORIG,ORIG};
указать множество всех пар элементов из ORIG. Но этот набор будет включать такие пары, как ("PITT", "PITT"). Чтобы указать множество всех не повторяющихся пар из ORIG, необходимо добавить условие i1<>i2:
set TRANSF = {i1 in ORIG, i2 in ORIG: i1 <> i2};
ord
Это еще один случай, когда два разных фиктивных индекса, i1 и i2, должны быть определены для работы над одним и тем же набором. Условие выбирает те пары, где i1 не равен i2. Если набор упорядочен, условие в выражении индексации также может ссылаться на порядковый номер элемента набора:
set ORIG ordered; set TRANSF = {i1 in ORIG, i2 in ORIG: ord(i1) < ord(i2)};
Использование условия ord(i1) < ord(i2) приводит к тому, что мы строим наборы пар из ORIG, которые не содержат одновременно 2-а одинаковых элемента и не содержат обратных пар. Например, TRANSF будет содержать одну из пар (PITT, CLEV) или (CLEV, PITT), в зависимости от того, какой элемент указан первым в ORIG, но не будет содержать обе. Наборы чисел могут обрабатываться аналогичным образом, поскольку они естественно упорядочены.
Предположим, что мы хотим учесть запасы разных периодов в многопериодной модели производства, объявив:
set PROD; # продукты param T > 0; # количество недель param A > 0; # maximum age of inventory var Inv{PROD,0..T,0..A} >= 0; # tons inventoried
В зависимости от того, как обрабатываются начальные запасы, нам может потребоваться включить ограничение, cогласно которому имеющиеся запасы в период T не могут быть старше t недель:
subject to Too_Old {p in PROD, t in 1..T, a in 1..A: a > t}: Inv[p,t,a] = 0;
В этом случае есть более простой способ написать индексное выражение:
subject to Too_Old {p in PROD, t in 1..T, a in t+1..A}: Inv[p,t,a] = 0;
Здесь фиктивный индекс, определенный t in 1..T, сразу используется во фразе a in t+1..A. В этом и других случаях, когда индексное выражение задает два или более набора, фразы, разделенные запятыми, оцениваются слева направо. Любой фиктивный индекс, определенный в начальной фразе, доступен для использования во всех последующих.
Динамический набор кортежей
Динамическое создание набора для каждой итерации
set P = {1,2,3,4,5}; # Объявление набора P set L = {6,7,8,9}; # Объявление набора L set V = {10,11,12,13}; # Объявление набора V set KN within {l in L, p in P, j in V}; # Объявление набора состоящего из подмножества элементов наборов P, L, V set PRO{L} ordered default {}; # Объявление пустого индексированного набора PRO{L} set NEWKNJ within {l in L, p in PRO[l], v in V} default {}; # Объявление пустого набора состоящего из подмножества элементов наборов L, PRO[l], V param NEWD {NEWKNJ}; # Объявление параметра NEWD {NEWKNJ} set PMAPPER {l in L, p in P} default {}; # Объявление пустого набора PMAPPER {l in L, p in P} data; set PRO[6] := 1,2,3; set PRO[7] := 1,2,3; set KN = (6,2,10), (7,3,11); set PMAPPER[6,2] = 1,2,3; set PMAPPER[7,3] = 1,2,3; for {(l,p,v) in KN}{ for {newp in PMAPPER[l, p]}{ let NEWKNJ := NEWKNJ union {(l, newp, v)}; display NEWKNJ; } }