построить блочную матрицу, состоящую из различных степеней базисных матриц - PullRequest
4 голосов
/ 09 июля 2020

Предполагая, что у нас есть базовая матрица A

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

   1   2
  -1   3

Мне интересно, есть ли простая команда, которая может построить блочную матрицу, состоящую из A, A^2, A^3 ... A^n с любым заданным положительным целым числом n, например

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

Очевидно, если A - скаляр, мы можем сделать как A.^(1:n). Интересно, есть ли подобная манипуляция или какая-то команда для матрицы A. Это моя мотивация.

Я могу сделать это с помощью циклов (for l oop или arrayfun), но я ищу для этого простую и элегантную команду.

Ответы [ 5 ]

3 голосов
/ 09 июля 2020

Не обязательно ответ, так как он также полагается на 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
3 голосов
/ 09 июля 2020

Супер-подробный способ сделать это одной строкой:

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))

Однако я думаю, что для l oop (с предварительным выделением), вероятно, быстрее и намного, намного понятнее. A для l oop не будет «неуместным», если его ясно. Четкость должна быть вашей целью, если только ее скорость не является сверхкритической (и опять же, этот однострочник по-прежнему делает петли под капотом).

Я уверен, что кто-то придумает более четкий однострочник, но мой комментарии по-прежнему будут применяться.

PD: Маг @LuisMendo предлагает: B=cell2mat(arrayfun(@(k){A^k},1:n).') как гораздо более чистый вариант. (Внутри все еще петли)

2 голосов
/ 10 июля 2020

Если вы не против использования рекурсивного метода, возможно, следующий вариант может быть следующим:

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
2 голосов
/ 09 июля 2020

В случае, когда матрица 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);

Взято из basi c теории . Помимо этого решения в конкретных случаях c, я не думаю, что общую форму, включающую форму Джордана, легко реализовать в Matlab.

2 голосов
/ 09 июля 2020

eval могут быть полезны:

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

Однако использование al oop для умножения матрицы на себя эффективно особенно, когда матрица большая.

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) ']']);
...