Подбираем подходящий набор для набора

Мне нужна помощь в следующем случае. скажем, у меня есть следующий код:

enum x= {p,k,m};
enum y= {t1,t2,t3,t4};
array[y] of set of int:against=[{1,3,6},{3,3,6},{6,1,1},{6,3,6}];

array[x] of set of int:attack=[{3,3,6},{6,2,2},{3,1,3}];
array[x] of set of y: NodesD=[{t2,t3},{t2,t3,t4},{t1,t4}];
array[x]of var y: Select; 

constraint forall(p in x)(Select[p] in NodesD[p]);

Итак, для каждого перечисления x я должен выбрать только перечисление Y. Затем я хочу выбрать тот, который подходит для каждого набора атак следующим образом:

возьмем первое перечисление x {p}, у которого есть два возможных варианта y {t2, t3}, поэтому я хочу сделать вот так: t2 = {1,1,6}, t3 = {6,3,3} поэтому я хочу вычесть каждое значение в x attack [] {3,3,6} из каждого значения в y против [] и суммировать результаты:

{1,1,6}-
{3,3,6}
-----------
{-2,-2,0} then sum them which is equal to -4

затем сделайте то же самое с t2

{6,3,3}-
{3,3,6}
------------
{3,0,-3} which is equal to 0 

и в этом случае t3, равное 0, лучше, чем t2 = -4. Я хочу сделать то же самое для каждого перечисления x и максимизировать мощность. Я пробовал сделать так, но не получается

  var int: power = sum(p in x)(card(against[Select[p]])-(card(attack[p])*Select[p]) );
solve maximize power ;

Любая помощь или подсказка, пожалуйста, :)


person future    schedule 03.07.2020    source источник


Ответы (1)


Если вы хотите сделать элемент путем сравнения элементов, матрица лучше подходит для этого, чем массив наборов, потому что таким образом вы гарантируете, что обе матрицы имеют одинаковую ширину, а также синтаксис менее громоздок, поэтому вместо суммирования с индексом от 1 до мощности набора вы используете другой набор для суммирования по столбцам матрицы.

Вы можете рассчитать сумму поэлементной разницы наборов с помощью

sum(i in 1..min(card(set_A),card(set_B)))(set_A[i] - set_B[i]);

используя min, чтобы быть уверенным, что вы выполняете итерацию только по наименьшему набору и не получаете доступ к несуществующим элементам.

Но, на мой взгляд, такой вариант написания чище, в основном, измените {} наборов для |, чтобы разграничить строки матрицы в attack и against, и добавить новую переменную, которая будет индексировать столбцы матрицы, я назвал ее FRONTS в В этом примере вы выбираете X и сравниваете разницу сил на разных фронтах.

enum X = {p,k,m};
enum y = {t1,t2,t3,t4};

set of int : FRONTS = 1..3;

array[y,FRONTS] of int : against=[|1,3,6|3,3,6|6,1,1|6,3,6|];

array[X,FRONTS] of int : attack=[|3,3,6|6,2,2|3,1,3|];

array[X] of set of y : nodesD=[{t2,t3},{t2,t3,t4},{t1,t4}];

array[X] of var y : select; 
var int: power;

constraint forall(p in X)(select[p] in nodesD[p]);

constraint power = sum(p in X)( sum(i in FRONTS)( against[ select[p], i] - attack[ p, i ] ) );

solve maximize power;

output [show(select) ++ " = " ++ show(power)];
person Matias Agelvis    schedule 04.07.2020
comment
Это был очень полезный ответ, большое спасибо. Я воспользовался всеми вашими советами. - person future; 04.07.2020