friendchj 发表于 2009-6-8 19:33

关于 solve 和 fsolve 的简单比较

以matlab R2008a版本为例,各版本出错提示可能有所不同。有不对之处,欢迎指正。
1.solve 和 fsolve的基本含义
matlab给出的关于solve 和 fsolve的基本描述为:
solve——Symbolic solution of algebraic equations
fsolve——Solve system of nonlinear equations
可见solve用于解决代数方程(组)的符号(解析)解,而fsolve用来解决非线性方程(组)的数值解。
【在matlab里面solve命令主要是用来求解代数方程(即多项式)的解,但是也不是说其它方程一个也不能解,不过求解非代数方程的能力相当有限,通常只能给出很特殊的实数解。从计算机的编程实现角度讲,如今的任何算法都无法准确的给出任意非代数方程的所有解,但是我们有很多成熟的算法来实现求解在某点附近的解。matlab也不例外,它也只能给出任意非代数方程在某点附近的解,函数有两个:fzero和fsolve,具体用法请用help或doc命令查询吧。如果还是不行,你还可以将问题转化为非线性最优化问题,求解非线性最优化问题的最优解,可以用的命令有:fminbnd, fminsearch, fmincon等等。】(引自:http://blog.sina.com.cn/s/blog_4c4af5c101008w9f.html,作者:ggbondg)
下面举几个例子:
例1:>> solve('a*x-1')
ans =
1/a
例2:>> solve('exp(x)+sin(x)-2')
ans =
.44867191635127271149118657202662
注:对于solve结果的显示,有时看起来比较长,可用vpa进行精度控制,如:
>> vpa(solve('exp(x)+sin(x)-2'),3)
ans =
.449
例3:>> fsolve(@(x)exp(x)+sin(x)-2,0)
Optimization terminated: first-order optimality is less than options.TolFun.
ans =
    0.4487
2.关于solve 和 fsolve求解方程组时的书写规则
对于solve,方程可以直接书写,不需要运算符”.”;
对于fsolve,当未知量与未知量有乘除操作或未知量有开方、幂等操作时运算符”.”可写也可不写(记得好像必须写,试了试,发现不写也行)。下面举几个例子:
例4:>> solve('x+y.^2-1','x.^2-y-3')
??? Error using ==> solve at 77
' x+y.^2-1 ' is not a valid expression or equation.
例5:>> solve('x+y^2-1','x^2-y-3')
ans =
    x:
    y:

例6:function shiyan
clc
clear
x0=;
fsolve(@mf,x0)

function F=mf(x)
F=[x(1)+x(2)^2-1;
   x(1)^2-x(2)-3];
%%%%%Result%%%%%%
Optimizer appears to be converging to a minimum that is not a root:
Sum of squares of the function values is > sqrt(options.TolFun).
Try again with a new starting point.
ans =
    1.6268   -0.1537


例7:把例6中的mf函数,换成如下再试试。
function F=mf(x)

F=[x(1)+x(2).^2-1;
x(1).^2-x(2)-3];

例8:把例6的初值x0设为x0=[-2,2]; 运行结果为:

Optimization terminated: first-order optimality is less than options.TolFun.
ans =
-2.1875
1.7854
可见,用fsolve解非线性方程组,比较依赖处置的选择,因此建议用fsolve解方程时,能大致了解问题的求解区间,以便选择合适的初值。
3. 关于solve 和 fsolve求解时,参数为多数值的求解
问题来源:http://forum.vibunion.com/thread-82658-1-1.html
类似问题描述:k=(5.0e+4):(1e+3):(6e+4);h=1.6e-6;n1=2.2899;n0=1.5040;n2=1.000;解方程组:
p1=sqrt(k.^2.*n1.^2-b.^2;p2=sqrt(b.^2-k.^2.*n2.^2);p0=sqrt(b.^2-k.^2.*n0.^2);
p1*h-pi-atan(p0./p1)-atan(p2./p1)=0。(见:http://forum.vibunion.com/thread-83102-1-1.html)
解决方法:这是非线性方程组,不过我们可以先用solve试试:

例9:问题如前所述。考虑用solve是否能解。
clear
clc
k=(5.0e+4):(1e+3):(6e+4);
h=1.6e-6;
n1=2.2899;
n0=1.5040;
n2=1.000;
for i=1:length(k)
y=solve(['p1=sqrt(',num2str(k(i)),'^2*',num2str(n1),'^2-b^2)'],...
    ['p2=sqrt(b^2-',num2str(k(i)),'^2*',num2str(n2)','^2)'],...
    ['p0=sqrt(b^2-',num2str(k(i)),'^2.*',num2str(n0),'^2)'],...
    ['p1*',num2str(h),'-',num2str(pi),'-atan(p0/p1)-atan(p2/p1)=0']);
end

%%%%%Result%%%%%
> In solve at 140

In shiyan at 9
y=solve(['p1=sqrt(',num2str(k(i)),'^2*',num2str(n1),'^2-b^2)'],...

['p2=sqrt(b^2-',num2str(k(i)),'^2*',num2str(n2)','^2)'],...

['p0=sqrt(b^2-',num2str(k(i)),'^2.*',num2str(n0),'^2)'],...

['p1*',num2str(h),'-',num2str(pi),'-atan(p0/p1)-atan(p2/p1)=0']);
Warning: Warning, solutions may have been lost
Warning: Explicit solution could not be found.
>> whos y

NameSizeBytesClassAttributes
y   0x0    64   sym
由此说明利用solve并不能解决这个复杂的非线性方程组,考虑数值解法。
例10:问题如例9,考虑fsolve求解问题。
% 主程序
clear
clc
global k h n1 n2 n0
k1=(5.0e+4):(1e+3):(6e+4);
h=1.6e-6;
n1=2.2899;
n0=1.5040;
n2=1.000;
x0=;
b=zeros(1,length(k1));
for i=1:length(k1)
    k=k1(i);
    y=fsolve(@myfun,x0);
    b(i)=y(4);
end
plot(k1,b);
% 子程序
function F=myfun(x)
global k h n1 n2 n0
% p0 p1 p2 b----x(1) x(2) x(3) x(4)
F=[sqrt(k^2*n1^2-x(4)^2)-x(2);
   sqrt(x(4)^2-k^2*n2^2)-x(3);
   sqrt(x(4)^2-k^2*n0^2)-x(1);
   x(2)*h-pi-atan(x(1)./x(2))-atan(x(3)./x(2))];
%%%%% Result%%%%%%%%%
y=fsolve(@myfun,x0);
Optimizer appears to be converging to a minimum that is not a root:
Sum of squares of the function values is > sqrt(options.TolFun).
Try again with a new starting point.


这说明所选初值并不合理。
例11 例10还可以这样改写:
% 主程序
clear
clc
% global k h n1 n2 n0
k1=(5.0e+4):(1e+3):(6e+4);
h=1.6e-6;
n1=2.2899;
n0=1.5040;
n2=1.000;
x0=;
b=zeros(1,length(k1));
for i=1:length(k1)
    k=k1(i);
    y=fsolve(@(x)myfun(x,k, h, n1, n2, n0),x0);
    b(i)=y(4);
end
plot(k1,b);
% 子程序
function F=myfun(x,k, h, n1, n2, n0)
% global k h n1 n2 n0
% p0 p1 p2 b----x(1) x(2) x(3) x(4)
F=[sqrt(k^2*n1^2-x(4)^2)-x(2);
   sqrt(x(4)^2-k^2*n2^2)-x(3);
   sqrt(x(4)^2-k^2*n0^2)-x(1);
   x(2)*h-pi-atan(x(1)./x(2))-atan(x(3)./x(2))];


例12 参见http://forum.vibunion.com/thread-82658-1-1.html此贴,看看大侠ChaChing,dingd(1stOpt解法)等的解法。
注:利用fsolve解数值解,初值的选择十分重要。而1stOpt则对初值的选择要求比较低,不妨一试。关于这一点,请参考如下文章:
作者:dingd 非线性方程组-1stOpt与fsolve的比较:
http://forum.vibunion.com/thread-48384-1-5.html

cammer534 发表于 2009-9-26 17:13

fsolve函数 求解非线性最小二乘解 是不是最好的方法??求解答

friendchj 发表于 2009-9-26 22:43

回复 沙发 cammer534 的帖子

这个不一定。fsolve求解需要指定初始值。解的好坏应该和函数采用的算法有很大关系。

fn001cn 发表于 2011-3-30 23:23

讲的非常好,谢谢。

meiyongyuandeze 发表于 2011-4-1 09:57

什么软件都不是万能的,有时候也不能太相信!

蓝天白云bmw 发表于 2011-4-14 14:21

感谢楼主分享。
页: [1]
查看完整版本: 关于 solve 和 fsolve 的简单比较