У меня есть проблема, которая может быть сведена к поиску способа отображения треугольной матрицы на вектор, пропускающий диагональ.Карта верхней треугольной матрицы на вектор, пропускающий диагональ
В основном нужно перевести этот код C++ с использованием библиотеки Gecode
// implied constraints
for (int k=0, i=0; i<n-1; i++)
for (int j=i+1; j<n; j++, k++)
rel(*this, d[k], IRT_GQ, (j-i)*(j-i+1)/2);
В этот MiniZinc (функциональный) код
constraint
forall (i in 1..m-1 , j in i+1..m)
((differences[?]) >= (floor(int2float((j-i)*(j-i+1))/int2float(2))));
И мне нужно, чтобы выяснить, индекс в differences[?]
.
MiniZinc - это функционально-математический язык, не подходящий для петель. Итак, я должен сопоставить те индексы i и j, которые касаются всех, и только ячейки верхней треугольной матрицы, пропуская ее диагональ, до k, которая выставляет эти ячейки от 0 до любого.
Если бы это была правильной треугольной матрицы (это не так), решение like this бы
index = x + (y+1)*y/2
Я обработки матрица представляет собой квадрат n*n
матрица с индексами, идущими от 0 до N-1, но было бы неплохо предоставить более общее решение для матрицы n*m
.
Вот полный код Minizinc
% modified version of the file found at https://github.com/MiniZinc/minizinc-benchmarks/blob/master/golomb/golomb.mzn
include "alldifferent.mzn";
int: m;
int: n = m*m;
array[1..m] of var 0..n: mark;
array[int] of var 0..n: differences = [mark[j] - mark[i] | i in 1..m, j in i+1..m];
constraint mark[1] = 0;
constraint forall (i in 1..m-1) (mark[i] < mark[i+1]);
% this version of the constraint works
constraint forall (i in 1..m-1 , j in i+1..m)
((mark[j] - mark[i]) >= (floor(int2float((j-i)*(j-i+1))/int2float(2))));
%this version does not
%constraint forall (i in 1..m-1, j in i+1..m)
% ((differences[(i-1) + ((j-2)*(j-1)) div 2]) >= (floor(int2float((j-i)*(j-i+1))/int2float(2))));
constraint alldifferent(differences);
constraint differences[1] < differences[(m*(m-1)) div 2];
solve :: int_search(mark, input_order, indomain, complete) minimize mark[m];
output ["golomb ", show(mark), "\n"];
Спасибо.
Я по-прежнему очень заинтересован в ответе. Я собираюсь использовать эту самую формулу для другого проекта. Не могли бы вы взглянуть на код? Благодарю. – Agostino
Извините за длинный ответ. Взгляните на мое редактирование. Ключевая точка: использовать T (i, j) = i + (j-1) * (j-2))/2 для биективного отображения {(i, j) | 1 <= i j (нижний треугольник), но в моем коде используются кортежи j> i (верхний треугольник). В любом случае это сработает, но вы спросили о верхнем треугольнике, поэтому я дал код для этого. Если вы хотите, чтобы код для нижнего треугольника тоже, не стесняйтесь спрашивать. –
Удалите понимание списка. Вместо 'array [int] из var 0..n: difference = [mark [j] - mark [i] | i в 1..m, j в i + 1..m]; 'вам просто нужно' array [1 .. (m * (m-1)) div 2] из var 0..n: difference; '. –