且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在Matlab中通过'symfun'实现符号函数的导数?

更新时间:2022-10-15 17:29:41

在较新版本的Matlab(我正在使用R2014b)中,错误消息更加清晰了:

使用 sym/diff 时出错(第26行) 除第一个参数外,所有参数都不得为符号函数.

因此, sym/diff 文档所称的抽象或任意 symfun 一个定义.在文档中没有明确提到此限制,但是各种输入模式都暗示了这一限制.


解决方法1 :简单功能,自变量t仅出现在有区别的symfun中

我还没有找到任何特别优雅的解决方法.如果t仅出现在您感兴趣的变量(此处为x(t))中,而不是单独出现或出现在其他抽象符号函数中,则可以区分时间t,然后取消多余的项.例如:

syms t x(t) y(t) z
f1 = x^2+5;
f2 = x^2+z^2+5;
f3 = x^2+y^2+z^2+5+t;
dxdt = diff(x,t);
df1 = diff(f1,t)/dxdt
df2 = diff(f2,t)/dxdt
df3 = diff(f3,t)/dxdt

,由于上述原因,前两种情况返回必需的2*x(t),但第三种情况不返回.在某些情况下,您可能需要应用 simplify 来完全划分D(x)(t)条款.


解决方法2 :更强大但更复杂的方法

多次使用 subs ,您可以在问题与标准符号变量,区分并交换回去.例如:

syms t x(t) y(t) z
f3 = x^2+y^2+z^2+5+t;
xx = sym('x');
df3 = subs(diff(subs(f3,x,xx),xx),xx,x)

对于上面的第三种情况也返回2*x(t).但是我认为这是种丑陋的攻击.

Matlab无法做到这一点有点荒谬– Mathematica没有这样的问题.看来MuPAD本身有此限制.您可能会考虑为功能填充要求与The MathWorks.

Here is my Matlab program:

syms x(t) t;
f = x^2 + 5;

And the result of f:

f(t) = x(t)^2 + 5

Both f and x are of class symfun in Matlab. I want the result of df/dx, which is equal to 2*x(t). I tried this in Matlab:

diff(f, x);

and got the following errors:

Error using mupadmex
Error in MuPAD command: The variable is
invalid. [stdlib::diff]
Error in sym/diff (line 57)
    R = mupadmex('symobj::diff', S.s, x.s,
    int2str(n));

How can df/dx be obtained in Matlab?

In newer versions of Matlab (I'm using R2014b) the error message is clearer:

Error using sym/diff (line 26) All arguments, except for the first one, must not be symbolic functions.

So, it looks like sym/diff cannot take a derivative with respect to what the documentation calls an abstract or arbitrary symfun, i.e., one without a definition. This limitation is not explicitly mentioned in the documentation, but the various input patterns allude to it.


Workaround 1: Simple functions, independent variable t only appears in differentiated symfun

I haven't found any workaround that is particularly elegant. If t only appears in your variable of interest (here x(t)), and not on its own or in other abstract symbolic functions, you can differentiate with respect to time t and then cancel out the extra terms. For example:

syms t x(t) y(t) z
f1 = x^2+5;
f2 = x^2+z^2+5;
f3 = x^2+y^2+z^2+5+t;
dxdt = diff(x,t);
df1 = diff(f1,t)/dxdt
df2 = diff(f2,t)/dxdt
df3 = diff(f3,t)/dxdt

which returns the requisite 2*x(t) for the first two cases, but not the third, for the reasons stated above. You may need to apply simplify in some cases to fully divide out the D(x)(t) terms.


Workaround 2: More robust, but more complicated method

Using subs multiple times, you can replace the symbolic function in question with a standard symbolic variable, differentiate, and swap it back. For example:

syms t x(t) y(t) z
f3 = x^2+y^2+z^2+5+t;
xx = sym('x');
df3 = subs(diff(subs(f3,x,xx),xx),xx,x)

which also returns 2*x(t) for the third case above. But I think this is kind of an ugly hack.

It is kind of ridiculous that Matlab can't do this – Mathematica has no such problem. It appears that MuPAD itself has this limitation. You might consider filing a feature request with The MathWorks.