如何在matlab中生成这个矩阵

时间:2015-04-12 20:39:28

标签: matlab matrix vectorization

enter image description here

H矩阵是n-by-n,n = 10000。我可以使用循环在matlab中生成这个矩阵。我只是想知道是否有任何方法可以做到这一点,而无需在matlab中循环。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

由于您使用的n值非常大10000,因此您可能希望尽可能多地提高性能。 与此同时,您可以使用基于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

(III)n = 10000的运行时other answer by @rayryeng屈服 - Elapsed time is 1.306339 seconds.