2015-03-20 15 views
6

Powiedz, że mam macierz A o wymiarze NxV. Chcę utworzyć większą macierz wielkości NTxVT, tj. Chcę zastąpić każdy element e macierzy A (e) za pomocą diag (T) * A (e)., Zachowując ogólną orientację macierzy (na przykład A (e) znajduje się po lewej stronie A (e-1), więc diag (T) * A (e) znajduje się po lewej stronie diag (T) * A (e-1).Wymień każdy element w macierzy z macierzą przekątną.

Czy istnieje Trick do osiągnięcia tego celu w Matlab (dzięki czemu każdy przekątnej matrycy i łącząc je weźmie na zawsze)

Dziękujemy ^^

+2

Czy to możliwe, że szukasz komendy Kron? http://de.mathworks.com/help/matlab/ref/kron.html – bdecaf

+1

Czy nie otrzymasz zamiast tego macierzy o rozmiarze 'NTn x V', gdzie' Tn' to 'size (T, 1) 'ponieważ' diag (T) 'miałby być' size (T, 1) '? – Divakar

Odpowiedz

3

Najprostszym sposobem mogę myśleć jest łączenie arrayfun i cell2mat funkcje:?.

B = cell2mat(arrayfun((@(x) T .* x), A, 'UniformOutput', false)); 

pierwsze, przekształca matrycy A w macierzy komórki macierzy T .* x gdzie x stanowi element A (A przyjmuje się, że T jest matryca).

Następnie użyłem cell2mat do przekształcenia z powrotem w macierz.

Oto kompletny przykład (execute online)

A = magic(3); 
T = diag([-1 1]); 
B = cell2mat(arrayfun((@(x) T .* x), A, 'UniformOutput', false)); 

powodując:

B = 

    -8 0 -1 0 -6 0 
    0 8 0 1 0 6 
    -3 0 -5 0 -7 0 
    0 3 0 5 0 7 
    -4 0 -9 0 -2 0 
    0 4 0 9 0 2 
4

Tutaj jest rozwiązanie wykorzystujące bsxfun

A = magic(3); 
T = [-1 1] 
T = diag(T); 
M=bsxfun(@times,permute(A,[3,1,4,2]),permute(T,[1,3,2,4])); 
M=reshape(M,size(T).*size(A)); 

Tworzy 4D tabeli, w której poszczególne bloki to M(:,i,:,j), to jest przekształcony do macierzy 2D.

Przybornik przetwarzania obrazu zapewnia inne rozwiązanie, które jest bardzo krótki, ale powolny:

A = magic(3); 
T = [-1 1] 
T = diag(T); 
M=blockproc(A,[1 1],@(x) x.data.*T); 

I wreszcie realizacja który generuje macierz rzadką, co może być pomocne dla dużego T jak twoja matryca będzie zawierać wiele zer:

T=[-1 1]; 
A=magic(3); 
%p and q hold the positions where the first element element is stored. Check sparse(p(:),q(:),A(:)) to understand this intermediate step 
[p,q]=ndgrid(1:numel(T):numel(T)*size(A,1),1:numel(T):numel(T)*size(A,2)); 
%now p and q are extended to hold the indices for all elements 
tP=bsxfun(@plus,p(:),0:numel(T)-1); 
tQ=bsxfun(@plus,q(:),0:numel(T)-1); 
% 
tA=bsxfun(@times,A(:),T); 
M=sparse(tP,tQ,tA); 

Gdy T ma rozmiar nx1, rzadkie rozwiązanie zmniejsza zużycie pamięci o współczynnik około n/1,55.

+0

Myślę, że 'permute (A, [3,1,4,2]). * Permute (T, [1,3,2,4])' wygląda na jaśniejsze niż jego odpowiednik 'bsxfun'. –

+2

@LeonidBeschastny: użytkownik oktawy? Matlab nie obsługuje emisji, wymagany jest bsxfun. – Daniel

+1

Masz mnie;) Przerzuciłem się na oktawę kilka lat temu. I masz rację, to nie zadziała w MatLab bez 'bsxfun'. –

6
A = magic(3); 
T = diag([-1 1]); 
kron(A,T) 

daje

-8  0 -1  0 -6  0 
0  8  0  1  0  6 
-3  0 -5  0 -7  0 
0  3  0  5  0  7 
-4  0 -9  0 -2  0 
0  4  0  9  0  2 

Ps.I skopiował pomysł z this example

+0

To jest droga! Zwięzły i szybki. – knedlsepp

+1

Pięknie działa również z rzadkimi macierzami. –

1

Korzystanie tylko indeksowania:

A = magic(3); 
T = diag([-1 1]); %// example data from Daniel's answer 
[a1, a2] = size(A); 
[t1, t2] = size(T); 
M = A(ceil(1/t1:1/t1:a1), ceil(1/t2:1/t2:a2)).*T(repmat(1:t1,1,a1), repmat(1:t2,1,a2)); 
1

Korzystanie good old-fashioned matrix multiplication -

M = reshape(diag(T)*A(:).',[size(A,1)*size(T,1) size(A,2)]) 

run Sample -

A = magic(4) 
T = magic(3) 
M = reshape(diag(T)*A(:).',[size(A,1)*size(T,1) size(A,2)]) 

spowoduje -

A = 
    16  2  3 13 
    5 11 10  8 
    9  7  6 12 
    4 14 15  1 
T = %// Notice that only diag(T) elements would be used to calculate M 
    8  1  6 
    3  5  7 
    4  9  2 
M = 
    128 16 24 104 
    80 10 15 65 
    32  4  6 26 
    40 88 80 64 
    25 55 50 40 
    10 22 20 16 
    72 56 48 96 
    45 35 30 60 
    18 14 12 24 
    32 112 120  8 
    20 70 75  5 
    8 28 30  2