有没有办法在矩阵repmat阵列上执行mpower?

时间:2019-03-25 22:26:44

标签: matlab vectorization

我想知道是否有一种方法可以提高矩阵 A 作为数组的力?

假设我们有这个矩阵

A =

   5   4
   3   6

然后我们重复其形状。

>> repmat(A, 5, 1)
ans =

   5   4
   3   6
   5   4
   3   6
   5   4
   3   6
   5   4
   3   6
   5   4
   3   6

现在我想增强能力,以便长时间重复的矩阵如下所示:

>> [A^1; A^2; A^3; A^4; A^5]
ans =

       5       4
       3       6
      37      44
      33      48
     317     412
     309     420
    2821    3740
    2805    3756
   25325   33724
   25293   33756

在MATLAB / Octave中没有for循环是否可以做到这一点?

3 个答案:

答案 0 :(得分:3)

编辑

在我的回答中也要提到这一点:递归不是矢量化的,因为Matlab / Octave用户通常会想到。我只是想到了递归,匿名函数的想法,并发现给定的任务是一个不错的小例子,可以在上面测试引用的解决方案。


我一直在寻找递归的匿名函数,并发现this great answer。我从那里采纳了这些想法,以满足问题中提出的期望,并得出了这个简短的代码片段。

% Input.
A = [5 4; 3 6]

% Set up recursive anonymous function.
iif = @(varargin) varargin{2*find([varargin{1:2:end}], 1, 'first')}();
recPower = @(A, B, n, f) iif(n > 1, @() [B; f(A, A * B, n - 1, f)], true, @() B);
nPower = @(A, n) recPower(A, A, n, recPower);

% Calculate for arbitrary n.
nPower(A, 5)

有关说明,请查看链接的答案。

输出:

A =

   5   4
   3   6

ans =

       5       4
       3       6
      37      44
      33      48
     317     412
     309     420
    2821    3740
    2805    3756
   25325   33724
   25293   33756

答案 1 :(得分:3)

另一个使用arrayfun的选项

B = cell2mat(arrayfun(@(x)A^x,1:5,'UniformOutput',0).')

结果:

B =
   5       4
   3       6
  37      44
  33      48
 317     412
 309     420
2821    3740
2805    3756
25325   33724
25293   33756

但是在这种情况下,基本的for循环可能是最快的选择。

以八度为基准进行标记:

tic
iif = @(varargin) varargin{2*find([varargin{1:2:end}], 1, 'first')}();
recPower = @(A, B, n, f) iif(n > 1, @() [B; f(A, A * B, n - 1, f)], true, @() B);
nPower = @(A, n) recPower(A, A, n, recPower);
for ii = 1:1000
% Calculate for arbitrary n.
    nPower(A, 5);
end
toc

经过的时间是1.023秒。

tic
for ii = 1:1000
    B = cell2mat(arrayfun(@(x)A^x,1:5,'UniformOutput',0).');
end
toc

经过的时间是4.8684秒。

tic
for ii = 1:1000
    B=[];
    for jj = 1:5
    B = [B;A^jj];
    end
end
toc

经过的时间为0.039371秒

答案 2 :(得分:2)

如果您确实要使用向量化(在这种情况下,这是IMO的大材小用),则也可以使用以下属性:

A^n = P*D^n*P^-1 %A SHOULD BE a diagonalizable matrix

哪里

[P,D] = eig(A) %the eigenvectors and eigenvalue

所以

A = [5 4; 3 6]
n = 5;
% get the eigenvalue/eigenvector
[P,D]=eig(A);
% create the intermediate matrix
MD = diag(D).^[1:n];
MD = diag(MD(:));
% get the result
SP = kron(eye(n,n),P)*MD*kron(eye(n,n),P^-1);

使用:

SP =

      5      4      0      0      0      0      0      0      0      0
      3      6      0      0      0      0      0      0      0      0
      0      0     37     44      0      0      0      0      0      0
      0      0     33     48      0      0      0      0      0      0
      0      0      0      0    317    412      0      0      0      0
      0      0      0      0    309    420      0      0      0      0
      0      0      0      0      0      0   2821   3740      0      0
      0      0      0      0      0      0   2805   3756      0      0
      0      0      0      0      0      0      0      0  25325  33724
      0      0      0      0      0      0      0      0  25293  33756

您仍然只需要提取这些值。在这种情况下使用稀疏矩阵来减少内存使用量可能会很有趣。

类似这样的东西:

SP = sparse(kron(eye(n,n),P))*sparse(MD)*sparse(kron(eye(n,n),P^-1));