【问题标题】:How to generate this matrix in matlab如何在matlab中生成这个矩阵
【发布时间】:2015-04-13 07:45:22
【问题描述】:

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

【问题讨论】:

    标签: matlab matrix vectorization


    【解决方案1】:

    可以看到矩阵的右上部分由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
    

    【讨论】:

    • @meng - 很高兴我能帮上忙!这是一个有趣的问题。
    • 很好的解释,一如既往!我自己会使用 triu + repmat,所以不得不寻找替代方法:)
    【解决方案2】:

    由于您正在使用相当大的n10000,您可能希望尽可能多地挤出性能。 随之而来的是,您可以使用基于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 = 10000other answer by @rayryeng 的运行时产生了 - Elapsed time is 1.306339 seconds.

    【讨论】:

    • 让您始终以速度将我的实现从水中吹出来:)。 +1。
    • @rayryeng 虽然你的解释是最好的!!而且您在优化部分取得了长足的进步,特别是在 bsxfun、unique、accumarray 等方面!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多