如何在matlab中生成这个矩阵
How to generate this matrix in matlab
H矩阵为n×n,n=10000。我可以使用循环在 matlab 中生成这个矩阵。我只是想知道是否有任何方法可以在不循环的情况下在 matlab 中执行此操作。
可以看到矩阵的右上部分由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
由于您正在处理相当大的 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
和 的运行时间产生了 - Elapsed time is 1.306339 seconds.
H矩阵为n×n,n=10000。我可以使用循环在 matlab 中生成这个矩阵。我只是想知道是否有任何方法可以在不循环的情况下在 matlab 中执行此操作。
可以看到矩阵的右上部分由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
由于您正在处理相当大的 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
和 Elapsed time is 1.306339 seconds.