Matlab: не удается упростить символическую скалярную функцию, используя subs() в простом случае

#matlab #symbolic-math

#matlab #symbolic-math

Вопрос:

Это всего лишь простой случай в matlab, происходит что-то странное с функцией subs (), и я не знаю почему.

Я прочитал официальный документ справки и погуглил сообщение об ошибке, но не нашел полезной информации.

Может кто-нибудь сказать мне, что неправильно в команде «subs (f)»?

 >> syms x w b f
>> f=x*w-b
f =
w*x - b
>> w=[1 2 3 ;4 5 6; 7 8 9 ]
w =
     1     2     3
     4     5     6
     7     8     9
>> x=[1 2 3.44]'
x =
    1.0000
    2.0000
    3.4400
>> b=[ 2 4 7 ]'
b =
     2
     4
     7
>> f
f =
w*x - b
>> subs(f)
Error using symengine
New arrays must have the same dimensions or must be scalars.
Error in sym/subs>mupadsubs (line 140)
G = mupadmex('symobj::fullsubs',F.s,X2,Y2);
Error in sym/subs (line 125)
    G = mupadsubs(F,X,Y); 
  

вот скриншот сообщения об ошибке:
введите описание изображения здесь

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

1. На самом деле, я жду ответа онлайн, эммм…… пожалуйста, помогите 🙂

2. Ответ заключается в тонкостях того, как subs заменяет скаляры массивами. Прежде чем я попытаюсь ответить на вопрос последовательным образом, почему вы используете символьные переменные для начала? Вы получите намного, намного лучшую производительность, используя double и аналогичное поведение с анонимной функцией, подобной f = @(w,x,b) w*x - b; .

3. Спасибо за совет, я использую символьную переменную, потому что мне может понадобиться производная от x для какой-то другой цели, могу ли я использовать анонимную функцию и двойные переменные для этого?

4. Это полностью зависит от вашего предполагаемого использования. Но, если я правильно помню, якобиан линейной системы — это просто матрица коэффициентов.

Ответ №1:

Символьный набор инструментов работает с точки зрения того, что символьные переменные являются скалярами, и любая операция или выражение, в котором они присутствуют, использует поэлементную семантику. Как указано в subs документации:

Если old это скаляр, а new это вектор или матрица, то subs(s,old,new) заменяет все экземпляры old in s на new , выполняя все операции поэлементно. Все постоянные члены в s заменяются константой, умноженной на вектор или матрицу всех единиц.

Таким образом, выражение, подвергающееся замене, должно хорошо сочетаться с поэлементным применением и расширением при замене. Однако, когда заменяемые новые массивы не соответствуют размеру во всех измерениях (как в данном случае, когда матрица коэффициентов является прямоугольной по сравнению с вектором столбцов), в движке, скорее всего, возникнет несоответствие размеров. Даже прямое указание замены массивами ячеек выдает ошибку:

 >> wnum = [1 2 3 ;4 5 6; 7 8 9 ];
>> xnum = [1 2 3.44]';
>> bnum = [ 2 4 7 ]';
>> subs(f,{w,x,b},{wnum,xnum,bnum})
Error using symengine
New arrays must have the same dimensions or must be scalars.

Error in sym/subs>mupadsubs (line 140)
G = mupadmex('symobj::fullsubs',F.s,X2,Y2);

Error in sym/subs (line 125)
    G = mupadsubs(F,X,Y);
  

В то время как полностью соответствующие размерные замены будут работать просто отлично:

 >> subs(f,{w,x,b},{xnum,xnum,xnum}); % All 3x1
>> subs(f,{w,x,b},{wnum,wnum,wnum}); % All 3x3
  

И все это происходит из-за того, что сами символьные переменные рассматриваются как скаляры. Символический обходной путь заключается в объявлении переменных как символьных массивов для генерации отдельных элементов массивов и обеспечения возможности взаимно однозначной замены:

 >> w = sym('w',[3,3]);
>> x = sym('x',[3,1]);
>> b = sym('b',[3,1]);
>> f = w*x - b;
>> subs(f,[w,x,b],[wnum,xnum,bnum])

ans =

  333/25
  766/25
 1174/25
  

Конечно, лучший способ действий, если вы можете это сделать, — полностью или в максимально возможной степени избегать символьного набора инструментов.

 >> double(subs(f,[w,x,b],[wnum,xnum,bnum]))
ans =
   13.3200
   30.6400
   46.9600

>> fnum = wnum*xnum - bnum
fnum =
   13.3200
   30.6400
   46.9600
  

Приведенное выше обсуждение является очень, очень веской причиной того, почему я оставляю линейную алгебру собственно во время выполнения MATLAB, помимо всего связанного с этим увеличения производительности. Символьный набор инструментов, на мой взгляд, лучше оставить для анализа функций в одной или нескольких переменных (я использую его для создания рядов Тейлора, якобианов и гессианов достаточно часто) или высокоточного анализа задачи малой размерности в исследовательских целях.