2014-01-06 58 views
6

我想重複一個長度爲n的矢量A在對角線上m次,以獲得(n+m-1) x m矩陣B。舉個例子,比如說A = [a;b;c;d],m = 4。這應該會導致如何在Matlab中沿對角線重複一個矢量

B = 
[a 0 0 0; 
b a 0 0; 
c b a 0; 
d c b a; 
0 d c b; 
0 0 d c; 
0 0 0 d] 

有關快速實現此目的的任何建議? blkdiag(repmat(A,1,m))在這種情況下不會幫助我,因爲它會創建一個(n*m) x m矩陣。

最終我其實在第三矩陣C的矩陣產品DB只是感興趣:

D=C*B 

如果你看到另一個選項獲取D無需生成B,我將不勝感激。但是對於上述問題的解決方案也會讓我感到非常高興!順便說一句,nm會很大。

謝謝!

+3

這看起來像一個換位託普利茨矩陣。我相信matlab有一個生成toeplitz矩陣的函數。這可能對你有用。 – mathematician1975

+0

@julian我的方法適合你嗎?如果m和n是高值,它可以節省創建矩陣'B'的時間,並且將所有的零乘以那裏......我只是真誠地知道它是否工作... – Adiel

回答

5

笨拙的,但一般的單行

n = 3;  %number of elements in A; 
m = 5;  %repetitions 
A = (1:n); 

B = full(spdiags(repmat(A(:),1,m)' , 1-(1:n) , n+m-1, m)) 

回報:

B = 

    1  0  0  0  0 
    2  1  0  0  0 
    3  2  1  0  0 
    0  3  2  1  0 
    0  0  3  2  1 
    0  0  0  3  2 
    0  0  0  0  3 

可選地一種改進的,通用的rubenvb's solution

B = toeplitz([A(:);zeros(m-1,1)] , zeros(1,m)) 

在這兩種情況下版本A可以be eithe r行或列向量。

更快的解決方案(因子2x)是spdiags的第一個!


編輯:甚至笨拙,但高達10倍比toeplitz -approach更快(這取決於N,M):

B = reshape([repmat([A(:);zeros(m,1)],m-1,1) ; A3(:)] ,[],m) 
+0

不幸的是'spdiags'不能處理矢量。 – julian

+0

@ julian:看看我最後一次編輯,這個解決方案比toeplitz方法快一點。 – thewaywewalk

+0

確實,你的最後一行比toeplitz更快,如果我的m和n的值非常高,那麼它的速度會稍微快一點。謝謝! – julian

7

因爲@ mathematician1975是懶得寫一個合適的回答。

Matlab具有此功能,稱爲toeplitz

你會這樣稱呼它:

c=[1;2;3;4;0;0;0]; 
r=[0, 0, 0, 0]; 
toeplitz(c,r) 

ans = 

    1 0 0 0 
    2 1 0 0 
    3 2 1 0 
    4 3 2 1 
    0 4 3 2 
    0 0 4 3 
    0 0 0 4 

您可以用零起到塑造矩陣你想要的方式。

+1

這不是懶惰,我只是不記得什麼論點 - 我總是發現寫一個評論比發表一個不正確的答案更好!無論如何,你從我身上得到+1 – mathematician1975

+0

@ mathematician1975足夠公平':-p'謝謝! – rubenvb

2

沒有矩陣B的總解決方案是對C的每一行與A進行卷積。你可以通過循環做到這一點:

for k=1:size(C,1) 
    D(k,:)=conv(C(k,:),A'); 
end 
D=D(:,length(A)-1:end-length(A)+1); % elliminate the convolution edges 

我認爲它也可以完成,無需環路,由arrayfun

k=1:size(C,1); 
D=arrayfun(@(x) conv(C(x,:),A'), k); 
D=D(:,length(A)-1:end-length(A)+1); % elliminate the convolution edges 
+0

就我所見,卷積只給出了上面對於對稱「A」(例如'[a b b a])所要求的結果。我的'A'實際上是對稱的,所以這不成問題。你的for循環比rubenvb的解決方案慢很多,但實際上比你的'arrayfun'版本要快,它必須被擴展爲:'colNoise = cell2mat(arrayfun(@(x)conv(C(x,:), A','valid')',k,'UniformOutput',0))';' – julian

+0

'valid'保存最後一行消除邊緣。 'UniformOutput'是必要的,因爲輸出是一個向量而不是標量。即使我會改變我的數據格式,因此可以擺脫所有「''''」,這仍然比較慢。但仍然非常感謝你的建議 – julian

+0

當然我的意思是'D'而不是colNoise在第一個評論中......複製和粘貼錯誤... – julian