#arrays #matlab #matrix #permutation
#массивы #matlab #матрица #перестановка
Вопрос:
Я ищу быстрый способ в MATLAB сделать следующее:
Учитывая матрицу перестановок вектора, скажем [1, 2, 3]
, я хотел бы удалить все повторяющиеся обратные строки.
Итак, матрица P = perms([1, 2, 3])
3 2 1
3 1 2
2 3 1
2 1 3
1 3 2
1 2 3
становится
3 2 1
3 1 2
2 3 1
Ответ №1:
Вы можете заметить, что симметрично первый элемент каждой строки должен быть больше последнего:
n = 4; %row size
x = perms(1:n) %all perms
p = x(x(:,1)>x(:,n),:) %non symetrical perms
Или вы можете заметить, что количество строк, содержащихся в p
матрице, следует этой последовательности OEIS для каждого n
и соответствует size(x,1)/2
so, поскольку perms выводит перестановку в обратном лексикографическом порядке:
n = 4; %row size
x = perms(1:n) %all perms
p = x(1:size(x,1)/2,:) %non symetrical perms
Ответ №2:
Вы можете использовать fliplr
метод MATLAB, чтобы перевернуть массив слева направо, а затем использовать ismember
для поиска строк P
в перевернутой версии. Наконец, повторите все местоположения и выберите уже найденные строки.
Вот некоторый код (протестирован с Octave 5.2.0 и MATLAB Online):
a = [1, 2, 3];
P = perms(a)
% Where can row x be found in the left right flipped version of row x?
[~, Locb] = ismember(P, fliplr(P), 'rows');
% Set up logical vector to store indices to take from P.
n = length(Locb);
idx = true(n, 1);
% Iterate all locations and set already found row to false.
for I = 1:n
if (idx(I))
idx(Locb(I)) = false;
end
end
% Generate result matrix.
P_star = P(idx, :)
Ваш пример:
P =
3 2 1
3 1 2
2 3 1
2 1 3
1 3 2
1 2 3
P_star =
3 2 1
3 1 2
2 3 1
Добавлено 4
к примеру:
P =
4 3 2 1
4 3 1 2
4 2 3 1
4 2 1 3
4 1 3 2
4 1 2 3
3 4 2 1
3 4 1 2
3 2 4 1
3 2 1 4
3 1 4 2
3 1 2 4
2 4 3 1
2 4 1 3
2 3 4 1
2 3 1 4
2 1 4 3
2 1 3 4
1 4 3 2
1 4 2 3
1 3 4 2
1 3 2 4
1 2 4 3
1 2 3 4
P_star =
4 3 2 1
4 3 1 2
4 2 3 1
4 2 1 3
4 1 3 2
4 1 2 3
3 4 2 1
3 4 1 2
3 2 4 1
3 1 4 2
2 4 3 1
2 3 4 1
Как и требовалось в вашем вопросе (по крайней мере, насколько я понимаю), строки берутся сверху вниз.
Ответ №3:
Вот другой подход:
result = P(all(~triu(~pdist2(P,P(:,end:-1:1)))),:);
pdist
вычисляет расстояние между строкамиP
и строкамиP(:,end:-1:1)
.~
отрицает результат, так чтоtrue
соответствует совпадающим парам.triu
сохраняется только верхняя треугольная часть матрицы, так что будет удалена только одна из двух строк совпадающей пары.~
отрицает обратно, так чтоtrue
соответствует несовпадающим парам.all
выдает вектор строк сtrue
для строк, которые следует сохранить (поскольку они не совпадают ни с одной предыдущей строкой).- Это используется в качестве логического индекса для выбора строк
P
.