我需要在Matlab中得到很多方程式的导数w.r.t.通用函数,它将为我提供类型的通用衍生物:
diff(f(x,y),x)
或
D([1],f(x,y)).
我需要的是将这些衍生物转换为实际的符号变量,以便能够使用solve
等。我现在正在做的,但效率非常低,是强力字符串替换。以下是我正在做的最小工作示例:
syms x y
f(x,y) = sym('f(x,y)')
jacobian(f)
first_d = jacobian(f)
strrep(char(first_d),'D([1], f)(x, y)','fx')
在我的实际应用中,我有许多衍生物可以从很多方程式中获取,因此循环这样的替换并不是最明智的事情。任何人都可以为更有效的解决方案提供一些帮助吗?
答案 0 :(得分:1)
注意:我正在使用R2014b。符号数学功能在最近的版本中发生了很大变化,并且仍在继续。不同版本的用户可能需要做稍微不同的事情来实现下面的结果,这依赖于访问未记录的功能。
首先,因为这是关于性能的,所以简单地声明
就足够了syms f(x,y)
还将x
和y
定义为符号变量。
正如我在上面的评论中提到的,Matlab / MuPAD的符号数学就是操纵字符串。更直接地执行此操作并添加您自己的问题知识可以帮助加快速度。您希望避免字符串与sym
/ symfun
类型之间的不必要转换。
1。要做的第一件事是研究特定符号数学函数如何处理输入和输出以及它调用的低级私有函数。对于jacobian
函数示例,请在命令窗口中键入edit jacobian
以查看编辑器中的代码。你看到的大部分内容可能令人困惑,但你应该看到这一行:
res = mupadmex('symobj::jacobian',Fsym.s,v.s);
这将调用低级'symobj::jacobian'
函数并传入函数和变量的字符串版本。要自己调用,您可以这样做(这也假设您知道您的变量是x
和y
):
syms f(x,y)
first_d = mupadmex('symobj::jacobian',char(f),char([x,y]))
返回[ diff(f(x, y), x), diff(f(x, y), y)]
。未记录的mupadmex
函数是在Matlab中调用MuPAD函数的直接方法 - there are others,这些函数已记录在案。
2。您会注意到上面的first_d
输出是symfun
类。我们实际上不希望将输出转换回符号函数。为避免这种情况,我们可以将附加参数传递给mupadmex
:
syms f(x,y)
first_d = mupadmex('symobj::jacobian',char(f),char([x,y]),0)
with now返回字符串matrix([[diff(f(x, y), x), diff(f(x, y), y)]])
。 (我只知道通过浏览大量符号数学工具箱代码添加额外的0
参数的技巧。)
3. 从这个字符串中,我们现在可以使用简单变量查找和替换偏导数的各种模式。您正在使用的strrep
函数通常是一个很好的选择。它比regexprep
快得多。但是,如果要替换大量不同但相似的模式,则可以在两者之间进行性能比较。这可能是一个单独问题的主题。
我不确定您的总体目标是什么或问题的完整程度,但这是我的示例的最终代码:
syms f(x,y)
first_d = mupadmex('symobj::jacobian',char(f),char([x,y]),0)
first_d = strrep(first_d(9:end-2),'diff(f(x, y), x)','fx');
first_d = sym(strrep(first_d,'diff(f(x, y), y)','fy'));
这将返回符号向量[ fx, fy]
。如果您需要symfun
,则需要稍微修改最后一行。在一些简单的测试中,这个基本示例比调用jacobian
快10%,并将结果转换回字符串。如果直接将输入指定为字符串而不是分配符号函数,则结果比原始函数快30%:
first_d = mupadmex('symobj::jacobian','f(x,y)','[x,y]',0)
first_d = strrep(first_d(9:end-2),'diff(f(x, y), x)','fx');
first_d = sym(strrep(first_d,'diff(f(x, y), y)','fy'));
使用subs
,如同this answer一样,虽然方便,但却是最慢的方法。在字符串之间来回转换是很昂贵的。