2015-05-14 18 views
11

Czy istnieje jakieś wbudowane polecenie do wygenerowania przesuniętej macierzy tożsamości w programie MATLAB?Macierz przesunięcia tożsamości Matlab

A=[ ... 
0, 1, 0, 0, 0, 0, 0, 0, 0, 0 
0, 0, 1, 0, 0, 0, 0, 0, 0, 0 
0, 0, 0, 1, 0, 0, 0, 0, 0, 0 
0, 0, 0, 0, 1, 0, 0, 0, 0, 0 
0, 0, 0, 0, 0, 1, 0, 0, 0, 0 
0, 0, 0, 0, 0, 0, 1, 0, 0, 0 
0, 0, 0, 0, 0, 0, 0, 1, 0, 0 
0, 0, 0, 0, 0, 0, 0, 0, 1, 0 
0, 0, 0, 0, 0, 0, 0, 0, 0, 1 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 

kombinacja circshift i eye jest dobre, jednak potrzebuje innego polecenia, aby go naprawić. Dowolny prostszy sposób? (z tylko jedną prostą składnią)

Odpowiedz

12

Spróbuj użyć połączenia diag w połączeniu z ones. W Twoim przypadku, masz macierz jednostkową 10 x 10 i chce przenieść przekątnej w prawo o 1.

>> n = 10; 
>> shift = 1; 
>> A = diag(ones(n-abs(shift),1),shift) 

A = 

    0  1  0  0  0  0  0  0  0  0 
    0  0  1  0  0  0  0  0  0  0 
    0  0  0  1  0  0  0  0  0  0 
    0  0  0  0  1  0  0  0  0  0 
    0  0  0  0  0  1  0  0  0  0 
    0  0  0  0  0  0  1  0  0  0 
    0  0  0  0  0  0  0  1  0  0 
    0  0  0  0  0  0  0  0  1  0 
    0  0  0  0  0  0  0  0  0  1 
    0  0  0  0  0  0  0  0  0  0 

Powyższy kod działa przez pierwsze deklarowania wektor kolumnowy wszystkich 1s, ale potrzebowałoby ich n-abs(shift), ponieważ poruszanie się w prawo oznaczałoby, że potrzebowalibyśmy mniej 1s, aby wypełnić rzeczy (więcej o tym później). n-abs(shift) odpowiada również całkowitej liczbie wierszy/kolumn macierzy i odejmowaniu, ile razy przesuwa się w prawo. Następnie można użyć diag, gdzie pierwszym parametrem jest wektor kolumnowy, który tworzy macierz zero i umieszcza wektor kolumnowy jako współczynniki wzdłuż przekątnej tej macierzy. Drugi parametr (shift w twoim przypadku) umożliwia przesunięcie gdzie umieścić tę kolumnę. Określenie wartości dodatniej oznacza przesunięcie przekątnych w prawo, aw naszym przypadku przesunięcie to w prawo o shift, a tym samym nasze wyniki wyjściowe. Ponieważ w zasadzie obcinacie wektor dla każdej pozycji w prawo, w której się poruszacie, musielibyście zmniejszyć liczbę 1 w swoim wektorze o tyle.

Do tej pory nie wyjaśniłem, dlaczego wywołanie abs do shift jest wymagane w ostatnim wierszu kodu. Powodem, dla którego wymagane jest wywołanie abs, jest uwzględnienie negatywnych zmian. Jeżeli nie mamy połączenia w trzecim wierszu kodu abs, n-shift byłaby zasadniczo dodanie więcej 1s do wektora a zatem rozszerzyć naszą macierz poza n x n. Ponieważ przesunięcie przekątnych w lewo również zmniejsza ilość 1s widoczną w wyniku, dlatego wymagane jest wywołanie abs, ale zauważysz, że stała shift pozostała nietknięta w drugim parametrze diag.

Oto demonstracja z ujemnym przesunięciem, shift = -1 i zachowując rozmiar będzie 10 x 10:

A = 

    0  0  0  0  0  0  0  0  0  0 
    1  0  0  0  0  0  0  0  0  0 
    0  1  0  0  0  0  0  0  0  0 
    0  0  1  0  0  0  0  0  0  0 
    0  0  0  1  0  0  0  0  0  0 
    0  0  0  0  1  0  0  0  0  0 
    0  0  0  0  0  1  0  0  0  0 
    0  0  0  0  0  0  1  0  0  0 
    0  0  0  0  0  0  0  1  0  0 
    0  0  0  0  0  0  0  0  1  0 
+0

Wystarczy dodać, że powinna ona być 'diag (te (n-1,1), 1)' – zahmati

+0

@zahmati - Ach! dzięki! Uogólniłem ją dla dowolnej wartości 'shift'. – rayryeng

7

można uzyskać pożądany wynik z pojedynczym wywołaniu bsxfun -

n = 10 
shift = 1 
A = bsxfun(@eq,[1:n].',1-shift:n-shift) 

Ponieważ są zasadniczo tworząc macierz rzadką, alternatywnie można użyć sparse -

n = 10 
shift = 1 
A = full(sparse(1:n-shift,1+shift:n,1,n,n)) 
+0

Podejście "rzadkie" jest bardzo miłe! – rayryeng

+0

@rayryeng Yeah! To mnie uderzyło! :) – Divakar

+0

Słodki :) Widziałeś także, że uogólniłeś go dla każdej wartości zmiany. Chłodny! – rayryeng

7

sposób późno w tej grze, ale nie zapominajmy, najprostsze rozwiązanie stosując indeksowanie liniową:

n=10; a=zeros(n); 
a(n+1:n+1:end)=1 

oczywiście, że tylko rozwiązuje przesunięcie = 1 przypadek, ale o co chodzi ...

+0

Nice +1 BTW, możesz pomnożyć początkowe 'n' z' shift', aby je uogólnić. W ten sposób: 'a (zmiana * n + 1: n + 1: koniec) = 1' Chociaż działa tylko dla wartości dodatnich –

+0

Nice. Zastanawiasz się, jak to zrobić przez samo liniowe indeksowanie. – rayryeng

+0

działa również z wartością ujemną: na przykład dla przesunięcia -4: 'a ((1 + 4): n + 1: koniec-n * (4-1)) = 1' – obchardon

1

Oto kolejna alternatywna: (trochę podobny do bsxfun podejście Divakar)

n=10; 
shift = 1; 
c = repmat(1-shift:n-shift,n,1,1); 
r = repmat((1:n).',1,n,1); 
out = r == c 

może to być również jeden-liner:

out = repmat((1:n).',1,n,1) == repmat(1-shift:n-shift,n,1,1) 
+1

Dobra robota z porównaniami logicznymi. – rayryeng

2

Można użyć circshift i naprawić matrycę przed przekazanie go do funkcji:

>> shift = 1; 
>> N=10; 
>> A=circshift(diag(1:N>shift),-shift) 
A = 
    0  1  0  0  0  0  0  0  0  0 
    0  0  1  0  0  0  0  0  0  0 
    0  0  0  1  0  0  0  0  0  0 
    0  0  0  0  1  0  0  0  0  0 
    0  0  0  0  0  1  0  0  0  0 
    0  0  0  0  0  0  1  0  0  0 
    0  0  0  0  0  0  0  1  0  0 
    0  0  0  0  0  0  0  0  1  0 
    0  0  0  0  0  0  0  0  0  1 
    0  0  0  0  0  0  0  0  0  0 

1:N>shift będzie 0 dla pięści shift liczba miejsc i 1 dla pozostałych.

0

Oto kolejny jeden (działa również z negatywnymi zmianami)

rot90(blkdiag(zeros(abs(shift)),rot90(eye(n))),sign(shift))