2013-09-15 4 views
3

Позвольте A быть матрицей размера [n,n]. Если я хочу извлечь свою диагональ, я делаю diag(A).Получение противоположной диагонали матрицы в Matlab

На самом деле, я хочу противоположную диагональ, которая будет [A(n,1),A(n-1,2),A(n-2,3),...].

Один из способов сделать это через diag(flipud(A)). Однако flipud(A) довольно расточительно и умножает время, которое он занимает в 10 раз по сравнению с поиском обычной диагонали.

Я ищу быстро путь получения противоположной диагонали. Естественно, петли for кажутся ужасно медленными. Предложения были бы весьма признательны.

+0

возможно дубликат [Есть ли функция, чтобы получить перекос диагонали матрицы в MATLAB?] (Http://stackoverflow.com/questions/5201426/is-there-a -function-to-get-the-skew-diagonal-of-a-matrix-in-matlab) – horchler

+0

FYI, правильный термин для этого - «[антидиагональный] (http://en.wikipedia.org/wiki/Anti-diagonal_matrix)». – horchler

ответ

0

Элементы, которые вы хотите получить, легко получить путем индексации. Например, это должно сделать трюк.

n = 4; 
A = magic(n) 
A = 
    16  2  3 13 
    5 11 10  8 
    9  7  6 12 
    4 14 15  1 

A(cumsum(n + [0,repmat(-1,1,n-1)])) 
ans = 
    4  7 10 13 

Я также мог бы использовать sub2ind, чтобы получить эти индексы элементов, но это делает его немного более чисто, хотя и менее очевидно в том, как она работает.

9

Вот моя матрица, произведенный A = магия (5)

A = 

17 24  1  8 15 
23  5  7 14 16 
4  6 13 20 22 
10 12 19 21  3 
11 18 25  2  9 


s = size(A,1) 
A(s:s-1:end-1) 

ans = 
11 12 13 14 15 
+0

самый быстрый до сих пор – marsei

+1

более быстрый вариант: 'A (sqrt (end): sqrt (end) -1: end-1)' –

5

Ниже приводится сравнение всех упомянутых методов до сих пор, а также несколько других вариантов я мог думать. Это было протестировано на 64-битном R2013a с использованием функции TIMEIT.

function [t,v] = testAntiDiag() 
    % data and functions 
    A = magic(5000); 
    f = { 
     @() func0(A) ; 
     @() func1(A) ; 
     @() func2(A) ; 
     @() func3(A) ; 
     @() func4(A) ; 
     @() func5(A) ; 
     @() func6(A) ; 
     @() func7(A) ; 
    }; 

    % timeit and check results 
    t = cellfun(@timeit, f, 'UniformOutput',true); 
    v = cellfun(@feval, f, 'UniformOutput',false); 
    assert(isequal(v{:})) 
end 


function d = func0(A) 
    d = diag(A(end:-1:1,:)); 
end 

function d = func1(A) 
    d = diag(flipud(A)); 
end 

function d = func2(A) 
    d = flipud(diag(fliplr(A))); 
end 

function d = func3(A) 
    d = diag(rot90(A,3)); 
end 

function d = func4(A) 
    n = size(A,1); 
    d = A(n:n-1:end-1).'; 
end 

function d = func5(A) 
    n = size(A,1); 
    d = A(cumsum(n + [0,repmat(-1,1,n-1)])).'; 
end 

function d = func6(A) 
    n = size(A,1); 
    d = A(sub2ind([n n], n:-1:1, 1:n)).'; 
end 

function d = func7(A) 
    n = size(A,1); 
    d = zeros(n,1); 
    for i=1:n 
     d(i) = A(n-i+1,i); 
    end 
end 

Таймингов (в том же порядке, как они определены выше):

>> testAntiDiag 
ans = 
    0.078635867152801 
    0.077895631970976 % @AlexR. 
    0.080368641824528 
    0.195832501156751 
    0.000074983294297 % @thefourtheye 
    0.000143019460665 % @woodchips 
    0.000174679680437 
    0.000152488508547 % for-loop 

Наиболее результат для выше удивительного меня является последним. По-видимому, компиляция JIT очень эффективна для таких простых for-loops.

+0

Я обновил результаты (у меня не было подключено к ноутбуку, поэтому дросселирование процессора делало его медленнее !). Я пришел к выводу, что они очень похожи, возможно, вы [оптимизируете] (http://c2.com/cgi/wiki?PrematureOptimization) неправильная вещь :) – Amro

+0

Спасибо за сравнения и за советы Кнута! –

0

А = магии (6)

А =

35  1  6 26 19 24 
3 32  7 21 23 25 
31  9  2 22 27 20 
8 28 33 17 10 15 
30  5 34 12 14 16 
4 36 29 13 18 11 

Ь = Diag (А (1: длина (А), длина (A): - 1: 1))

б =

24 
23 
22 
33 
5 
4