Почему cumsum не работает с символьными векторами?

#octave #symbolic-math #cumsum

#octave #символьно-математический #cumsum

Вопрос:

Я написал небольшой скрипт Octave, работающий с cumsum символьными векторами, который, как я ожидал, будет работать, но, к сожалению, это не так. Вот код:

 pkg load symbolic
n = 3;
syms q x
q = sym('q', [n 1]);
x = sym('x', [n 1]);
cumsum(q - x)
  

Вместо ожидаемого результата я получаю:

ошибка: cumsum: неверный аргумент типа ‘class’

Почему это происходит? Будет ли это работать с Matlab Symbolic Toolbox? (К сожалению, у меня его нет, поэтому я не могу протестировать.)

Комментарии:

1. Это работает в MATLAB с символическим набором инструментов, выводя [q1 - x1; q1 q2 - x1 - x2; q1 q2 q3 - x1 - x2 - x3] , как и следовало ожидать

2. Работает с MATLAB Онлайн. Так что, я думаю, это будет работать и с MATLAB.

3. Спасибо, что подняли эту проблему. Я добавил базовые функции cumsum и cumprod в качестве запроса на слияние на [странице проекта] ( sourceforge.net/p/octave/symbolic/merge-requests ).

4. Обновление: github.com/cbm755/octsympy/pull/1034

Ответ №1:

Это просто потому cumsum , что запись в Octave не поддерживается для символьных элементов, как указано в сообщении об ошибке. Ваш код дает следующее в MATLAB:

 ans =
                     q1 - x1
           q1   q2 - x1 - x2
 q1   q2   q3 - x1 - x2 - x3
  

Вы можете сделать что-то вроде этого:

 t1 = q-x;
t2 = triu(ones(numel(t1)));
sum(repmat(t1,1,3).*t2).'
% repmat is necessary here because implicit expansion is also not 
% supported for matrices of class sym in Octave

  

Приведенный выше код в Octave и MATLAB дает следующее соответственно:

 ans = (sym 3×1 matrix)

  ⎡            q₁₁ - x₁₁            ⎤
  ⎢                                 ⎥
  ⎢      q₁₁   q₂₁ - x₁₁ - x₂₁      ⎥
  ⎢                                 ⎥
  ⎣q₁₁   q₂₁   q₃₁ - x₁₁ - x₂₁ - x₃₁⎦
  
 ans =
                     q1 - x1
           q1   q2 - x1 - x2
 q1   q2   q3 - x1 - x2 - x3
  

Комментарии:

1. Хороший ответ. Интересно, однако, будет ли реализация cumsum в виде цикла for обязательно намного медленнее, чем выполнение его как вычисления матрицы, когда дело доходит до символьной математики?

2. Что также работает: for i = 1:n; b(i) = sum(q(1:i)) - sum(x(1:i)); end или даже короче: A = tril(ones(n)); A*(q - x) На самом деле, у меня уже была tril версия как умножение матрицы, но затем я обнаружил ошибку в (числовом) cumsum варианте и исправил ее. Позже я также хотел исправить левостороннюю матрицу A , чтобы оба варианта давали одинаковый результат. Теперь они работают. 🙂

Ответ №2:

Рискуя заявить очевидное, это может быть реализовано как цикл for .
Вот одна реализация.

 function Y = cumsum( X, N )
    if nargin < 2, N = 1; end
    YDims = size( X );  NDim = YDims(N); Y = sym( zeros( YDims ) );
    XIdx = substruct( '()', repmat( {':'}, 1, ndims( X ) ) );
    YIdx = substruct( '()', repmat( {':'}, 1, ndims( Y ) ) );
    for i = 1 : NDim
        XIdx.subs{N} = 1 : i;
        YIdx.subs{N} = i;
        Y = subsasgn( Y,
                      YIdx,
                      sum( subsref( X, XIdx ), N )
                    );
    end
end
  

Скопируйте это в вашу символическую папку установки 1 как cumsum.m, и ваш приведенный выше скрипт будет работать как в matlab.


1: (в моем случае это было ~/ .octave/symbolic-2.9.0/@sym/cumsum.m потому что я установил свой префикс pkg как ~/.octave )