将符号导数转换为实际符号
Transforming Symbolic Derivatives into Actual Symbols
我需要在 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')
在我的实际应用中,我要从很多方程中求出很多导数,所以循环这样的替换并不是最明智的做法。谁能阐明更有效的解决方案?
注意:我使用的是 R2014b。符号数学功能在最新版本中发生了巨大变化,并将继续如此。不同版本的用户可能需要做一些稍微不同的事情来实现下面的结果,这依赖于访问未记录的功能。
首先,由于这是关于性能的,因此只需声明就足够了
syms f(x,y)
也将 x
和 y
定义为符号变量。
正如我在上面的评论中提到的,Matlab/MuPAD 的符号数学就是关于操纵字符串的。更直接地执行此操作并添加您自己对问题的了解可以帮助加快速度。您希望避免在字符串和 sym
/symfun
类型之间进行不必要的转换。
1. 首先要做的是调查一个特定的符号数学函数是如何处理输入和输出的,以及它正在调用哪些较低级别的私有函数。对于 jacobian
函数示例,在命令 window 中键入 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]))
这个returns[ diff(f(x, y), x), diff(f(x, y), y)]
。未记录的 mupadmex
函数是从 Matlab 中调用 MuPAD 函数的直接方法 – there are others,已记录在案。
2. 你会注意到上面的 first_d
输出是 symfun
class。我们实际上不希望将输出转换回符号函数。为避免这种情况,我们可以将附加参数传递给 mupadmex
:
syms f(x,y)
first_d = mupadmex('symobj::jacobian',char(f),char([x,y]),0)
现在 returns 字符串 matrix([[diff(f(x, y), x), diff(f(x, y), y)]])
。 (我只是通过浏览大量符号数学工具箱代码才知道添加额外 0
参数的技巧。)
3. 从这个字符串中,我们现在可以找到并用简单变量替换偏导数的各种模式。 strrep
function that you're using is generally a good choice for this. It is much faster than 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'));
这个returns符号向量[ 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
, as in this answer 虽然方便,但却是最慢的方法。在字符串之间来回转换成本很高。
我需要在 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')
在我的实际应用中,我要从很多方程中求出很多导数,所以循环这样的替换并不是最明智的做法。谁能阐明更有效的解决方案?
注意:我使用的是 R2014b。符号数学功能在最新版本中发生了巨大变化,并将继续如此。不同版本的用户可能需要做一些稍微不同的事情来实现下面的结果,这依赖于访问未记录的功能。
首先,由于这是关于性能的,因此只需声明就足够了
syms f(x,y)
也将 x
和 y
定义为符号变量。
正如我在上面的评论中提到的,Matlab/MuPAD 的符号数学就是关于操纵字符串的。更直接地执行此操作并添加您自己对问题的了解可以帮助加快速度。您希望避免在字符串和 sym
/symfun
类型之间进行不必要的转换。
1. 首先要做的是调查一个特定的符号数学函数是如何处理输入和输出的,以及它正在调用哪些较低级别的私有函数。对于 jacobian
函数示例,在命令 window 中键入 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]))
这个returns[ diff(f(x, y), x), diff(f(x, y), y)]
。未记录的 mupadmex
函数是从 Matlab 中调用 MuPAD 函数的直接方法 – there are others,已记录在案。
2. 你会注意到上面的 first_d
输出是 symfun
class。我们实际上不希望将输出转换回符号函数。为避免这种情况,我们可以将附加参数传递给 mupadmex
:
syms f(x,y)
first_d = mupadmex('symobj::jacobian',char(f),char([x,y]),0)
现在 returns 字符串 matrix([[diff(f(x, y), x), diff(f(x, y), y)]])
。 (我只是通过浏览大量符号数学工具箱代码才知道添加额外 0
参数的技巧。)
3. 从这个字符串中,我们现在可以找到并用简单变量替换偏导数的各种模式。 strrep
function that you're using is generally a good choice for this. It is much faster than 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'));
这个returns符号向量[ 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
, as in this answer 虽然方便,但却是最慢的方法。在字符串之间来回转换成本很高。