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