【问题标题】:construct block matrix consisting of different powers of basis matrices构造由不同幂的基矩阵组成的块矩阵
【发布时间】:2020-07-10 15:31:27
【问题描述】:

假设我们有一个基矩阵A

>> A = [1,2;-1,3]
A =

   1   2
  -1   3

我想知道是否有一个简单的命令可以构造一个由AA^2A^3...A^n 与任何给定正整数n 组成的块矩阵,比如

B = [A; A^2; A^3; ...; A^n]

显然,如果A 是一个标量,我们可以像A.^(1:n) 那样做。我想知道矩阵A 是否有类似的操作或某些命令。这就是我的动力。

我可以使用循环(for 循环或arrayfun)来实现,但我正在寻找一些简单而优雅的命令。

【问题讨论】:

标签: matlab matrix octave


【解决方案1】:

也不一定是答案,因为它也依赖于 cellfun,并且在精神上与此处的其他答案相似,但我认为这稍微优雅一些​​,并且使用内置函数而不是匿名函数(即保证更快,如果这对你很重要的话)。

此外,此版本适用于任何形状的指数矩阵,生成适当的“块”输出。

A = [ 1,2
     -1,3 ];

N = [ 1,2,3
      2,3,4
      3,4,5 ];

expblk = @(A,N) cell2mat(
             cellfun( @mpower, {A}, num2cell(N), 'UniformOutput', false )
         );

expblk(A,N)

% ans =
%     1    2   -1    8   -9   22
%    -1    3   -4    7  -11   13
%    -1    8   -9   22  -31   48
%    -4    7  -11   13  -24   17
%    -9   22  -31   48  -79   82
%   -11   13  -24   17  -41    3

【讨论】:

    【解决方案2】:

    在一行中完成的超级详细方式:

    B= cell2mat(cellfun(@mpower,mat2cell(repmat(A,n,1),[ones(n,1)*size(A,1)],size(A,2)),mat2cell([1:n]',ones(n,1),1),'UniformOutput',false))
    

    但是,我认为 for 循环(带有预分配)可能更快、更清晰。如果 for 循环清晰,则它不是“不优雅的”。清晰应该是你的目标,除非它的速度非常关键(同样,这个单线仍然在引擎盖下循环)。

    我相信有人会想出一个更清晰的衬里,但我的 cmets 仍然适用。

    PD:魔术师@LuisMendo 建议:B=cell2mat(arrayfun(@(k){A^k},1:n).') 作为更清洁的选择。 (里面还是循环)

    【讨论】:

    • 不是很容易,也不是很优雅,而且可能由于使用了单元格而很慢。否则,为找到一条线而赞叹!
    • 感谢您的回答。实际上我使用arrayfun 来构造矩阵,但我想这是一种隐藏循环。你还有什么想法吗?
    • @ThomasIsCoding 我认为您的请求的前提是无效的。没有真正的理由避免循环,除非它们不太清楚。 (例如,而不是总和)
    • 如果A 是一个标量,我们可以像A.^(1:n) 那样做。我想知道矩阵A 是否有类似的操作或某些命令
    • @ThomasIsCoding 否,因为 .^^ 是完全不同的 MATLAB 函数。你可以做你建议的事情,只是因为它是一个元素运算符,而不是因为它是一个“权力”。
    【解决方案3】:

    在矩阵 A 可对角化的情况下,您会得到一个简单的解决方案(不是单线,但仍然如此!):

    [V,D] = eig(A);
    k = size(A,1);
    B = kron(eye(n),V)*(reshape(D.^reshape(1:n,[1 1 n]),[k k*n]).')*inv(V);
    

    取自basic theory。除了在特定情况下这种解决方案外,我认为涉及Jordan形式的一般形式在Matlab中并不容易实现。

    【讨论】:

      【解决方案4】:

      如果您不介意使用递归方法,也许以下可能是一种选择

      function y = f(A,n)
        if n==1 
          y = A;
          return;
        end 
        y = [A;f(A,n-1)*kron(eye(n-1),A)];
      end
      

      然后

      B =
      
          1    2
         -1    3
         -1    8
         -4    7
         -9   22
        -11   13
        -31   48
        -24   17
        -79   82
        -41    3
      

      【讨论】:

        【解决方案5】:

        eval 可能会有所帮助:

        A = [1,2;-1,3];
        n = 3;
        B = eval(['[A' sprintf(';A^%d',2:n) ']']);
        

        但是,使用循环将矩阵与自身相乘非常有效,特别是当矩阵很大时。

        C = cell (n,1);
        D = 1;
        for k = 1:n
            D *= A; % In MATLAB use D = D * A;
            C{k} = D;
        end
        B = vertcat(C{:});
        

        以及它的 eval Octave 语法版本(为了好玩,不推荐):

        B = eval(['[D=A' repmat(';D*=A',1,n-1) ']']);
        

        【讨论】:

        • 嗯,您可能想对eval 的陷阱提出一个重大警告。甚至其文档页面的顶部也突出显示了该警告。我也怀疑这会更快,因为使用 eval 时禁用了 JIT。
        • @Adriaan 非常非常抱歉!我被这个问题强迫使用 eval,否则我不会这样做。
        • 我想为循环版本 +1,这可能比 OP 的原始循环(单独计算每个权力)效率更高。但是eval 解决方案...如果您发布了两个单独的答案,我可以赞成一个而反对另一个! :)
        • @CrisLuengo 谢谢。 eval 有其缺点,但在这个答案中,它显示了不同的思维方式,可能有资格获得支持。我可以看到一些奇怪的东西。这个问题需要一个无循环的答案,但大多数答案都包含循环!如果您有疑问,我认为我已经说服您投赞成票。提前致谢!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-09
        • 2015-04-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-24
        相关资源
        最近更新 更多