Как удалить обратные строки в матрице перестановок?

#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)))),:);
  
  1. pdist вычисляет расстояние между строками P и строками P(:,end:-1:1) .
  2. ~ отрицает результат, так что true соответствует совпадающим парам.
  3. triu сохраняется только верхняя треугольная часть матрицы, так что будет удалена только одна из двух строк совпадающей пары.
  4. ~ отрицает обратно, так что true соответствует несовпадающим парам.
  5. all выдает вектор строк с true для строк, которые следует сохранить (поскольку они не совпадают ни с одной предыдущей строкой).
  6. Это используется в качестве логического индекса для выбора строк P .