2015-04-12 168 views
2

enter image description here如何生成在MATLAB這個矩陣

矩陣H是n乘N,N- = 10000。我可以使用循環在matlab中生成這個矩陣。我只是想知道是否有任何方法可以做到這一點,而無需在matlab中循環。

回答

3

您可以看到,矩陣的右上部分由1/sqrt(n*(n-1))組成,對角元素由-(n-1)/sqrt(n*(n-1))組成,第一列由1/sqrt(n)組成,其餘元素爲零。

我們可以生成完整的矩陣,它包含第一列全部爲1/sqrt(n),然後剩下的列爲1/sqrt(n*(n-1))然後我們需要修改矩陣以包含剩餘部分。

因此,讓我們專注於從第2行第2列開始的元素,因爲它們遵循一個模式。一旦完成,我們可以構建其他構建最終矩陣的東西。

x = 2:n; 
Hsmall = repmat([1./sqrt(x.*(x-1))], n-1, 1); 

下一步,我們將解決對角線元素:

Hsmall(logical(eye(n-1))) = -(x-1)./sqrt(x.*(x-1)); 

現在,讓我們零元素的其餘部分:

Hsmall(tril(logical(ones(n-1)),-1)) = 0; 

既然我們已經做了,讓我們創建一個將所有這些組合在一起的新矩陣:

H = [1/sqrt(n) 1./sqrt(x.*(x-1)); repmat(1/sqrt(n), n-1, 1) Hsmall]; 

因此,完整的代碼:

x = 2:n; 
Hsmall = repmat([1./sqrt(x.*(x-1))], n-1, 1); 
Hsmall(logical(eye(n-1))) = -(x-1)./sqrt(x.*(x-1)); 
Hsmall(tril(logical(ones(n-1)),-1)) = 0; 
H = [1/sqrt(n) 1./sqrt(x.*(x-1)); repmat(1/sqrt(n), n-1, 1) Hsmall]; 

下面是與n = 6一個例子:

>> H 

H = 

    Columns 1 through 3 

     0.408248290463863   0.707106781186547   0.408248290463863 
     0.408248290463863  -0.707106781186547   0.408248290463863 
     0.408248290463863       0  -0.816496580927726 
     0.408248290463863       0       0 
     0.408248290463863       0       0 
     0.408248290463863       0       0 

    Columns 4 through 6 

     0.288675134594813   0.223606797749979   0.182574185835055 
     0.288675134594813   0.223606797749979   0.182574185835055 
     0.288675134594813   0.223606797749979   0.182574185835055 
     -0.866025403784439   0.223606797749979   0.182574185835055 
         0  -0.894427190999916   0.182574185835055 
         0       0  -0.912870929175277 
+0

謝謝,我學到了一些東西。 – aaa

+0

@meng - 很高興能幫到你!這是有趣的問題。 – rayryeng

+1

一如既往的好解釋!本來會跟triu + repmat一起去的,所以不得不尋找替代方法:) – Divakar

1

既然你用的10000一個相當大的n價值的工作,你可能想擠出儘可能多的表現儘可能。 與展望,您可以使用基於cumsum的有效途徑 -

%// Values to be set in each column for the upper triangular region 
upper_tri = 1./sqrt([1:n].*(0:n-1)); 

%// Diagonal indices 
diag_idx = [1:n+1:n*n]; 

%// Setup output array 
out = zeros(n,n); 

%// Set the first row of output array with upper triangular values 
out(1,:) = upper_tri; 

%// Set the diagonal elements with the negative triangular values. 
%// The intention here is to perform CUMSUM across each column later on, 
%// thus therewould be zeros beyond the diagonal positions for each column 
out(diag_idx) = -upper_tri; 

%// Set the first element of output array with n^(-1/2) 
out(1) = -1/sqrt(n); 

%// Finally, perform CUMSUM as suggested earlier 
out = cumsum(out,1); 

%// Set the diagonal elements with the actually expected values 
out(diag_idx(2:end)) = upper_tri(2:end).*[-1:-1:-(n-1)]; 

運行測試

(i)與n = 10000,在我結束運行時是 - Elapsed time is 0.457543 seconds。 (II)現在,作爲最終的性能壓縮練習,您可以使用此MATLAB Undodumented Blog中列出的更快的預分配方案來編輯​​out的預分配步驟。因此,預分配步驟將如下所示 -

out(n,n) = 0; 

此編輯代碼的運行時爲 - Elapsed time is 0.400399 seconds

(三)n = 10000other answer by @rayryeng運行時產生 - Elapsed time is 1.306339 seconds.

+0

讓它總是把我的實現以速度吹出水面:)。 +1。 – rayryeng

+1

@rayryeng雖然你的解釋是最好的!你在優化部分有很長的路要走,特別是在bsxfun,獨特的,準確的等等! – Divakar