matlab将符号表达式转化为函数句柄的方法汇总

http://www.ilovematlab.cn/thread-260310-1-1.html

http://blog.sina.com.cn/s/blog_66faf9cf0101ckuu.html

在用符号 (symbolic) 运算得到一个符号表达式后,我们可能需要令其进一步参与数值运算。然而,很多数值运算函数,比如数值积分函数(quad,quadgk,integral),都只能接受函数句柄作为输入。于是,将符号表达式转化为函数句柄就成了必然。

如果不怕麻烦,完全可以通过手动输入对应的符号表达式来建立函数句柄。然而,很多情况下我们得出的符号表达式可能极其复杂,甚至可能占据很多行。此时,手动输入显然相当不便。于是,找到一种自动将符号表达式转化为函数句柄的方法就显得尤为重要。下面列举出三种自动转换的办法(三种办法得到的函数都是匿名函数):

1. 最简便的办法:利用 matlabFunction(这个函数只适用于2009a及更新的版本)

  1. syms x
  2. y=exp(x)*x^2+x+1
  3. g = matlabFunction(y)
复制代码

如果你的matlab报错,这说明你的版本太老,那么请使用下面两种办法。

2. eval + vectorize 函数:vectorize 的目的是将字符串(string)表达式里的 * / ^ 替换为 .* ./ .^ ,以支持向量运算。eval 执行该字符串后得到函数句柄

  1. syms x
  2. y=exp(x)*x^2+x+1
  3. g = eval_r([\'@(x)\',vectorize(y)])
复制代码

这个方法需要借助 eval 函数,在论坛里已经被广大坛友广泛使用过。

3. str2func + vectorize 函数:str2func 函数可以直接将字符串转化为函数句柄

  1. syms x
  2. y=exp(x)*x^2+x+1
  3. g = str2func([\'@(x)\',vectorize(y)])

这两天重新 review 了一下 matlabFunction,发现这个函数其实是很强大的,特意来对 16 楼的办法做一点补充。

matlabFunction 可以在将多个符号表达式转换为向量化函数(这一转换的目的是为了供fsolve等函数使用),即函数输入是一个向量化参数,函数返回值也是一个向量化返回值。实现这一转换只需在matlabFunction调用时使用 \'vars\' 参数,并将多个自变量合写成一个向量并放在 {} 里。这个转换是一步即可完成,很方便。而我之前在 16 楼提供的办法实际上是分两步转换的:第一步是将多个函数返回值转换为一个向量化函数返回值,第二步是将多个输入自变量转换为一个向量化输入参数。显然 16 楼的办法没有直接用 \'vars\' 参数转换来得快。

现在还是以我在 16 楼的例子来说明这个问题。

  1. syms x1 x2;
  2. y = 2*x1 - x2 - exp(-x1);
  3. z = -x1 + 2*x2 - exp(-x2);
  4. % 16 楼的旧方法,分2步实现
  5. f1 = matlabFunction([y;z]);
  6. f1 = @(x) f1(x(1),x(2));
  7. fsolve(f1,[0 1])
  8. % 新方法:直接利用 \'vars\' 参数一步转换成功
  9. f2 = matlabFunction([y;z], \'vars\', {[x1 x2]});
  10. fsolve(f2,[1 1])
复制代码

运行后会发现两种方法得到了相同的结果。显然,新方法更为简洁。

另外一个例子:

  1. syms t
  2. y=sin(2*t).*exp(-0.5*t);
  3. dy = diff(y);
  4. dyf = matlabFunction(dy);
  5. t = [0:0.01:5];
  6. plot(t,subs(y));
  7. x0 = [1,2,4];
  8. x = arrayfun(@(x0) fzero(dyf,x0), x0)