使用MATLAB编写一个在二维中实现牛顿方法的函数

时间:2013-12-09 10:54:26

标签: matlab newtons-method

我正在尝试编写一个在二维中实现牛顿方法的函数,虽然我已经完成了这个,但我现在必须调整我的脚本,以便我的函数的输入参数必须为f(x)in列向量,f(x)的雅可比矩阵,初始猜测x0以及函数f(x)及其雅可比矩阵在单独的.m文件中的容差。

作为我编写的实现Newton方法的脚本示例,我有:

n=0;            %initialize iteration counter     
eps=1;          %initialize error     
x=[1;1];        %set starting value

%Computation loop     
while eps>1e-10&n<100 
    g=[x(1)^2+x(2)^3-1;x(1)^4-x(2)^4+x(1)*x(2)];         %g(x)      
    eps=abs(g(1))+abs(g(2));                             %error     
    Jg=[2*x(1),3*x(2)^2;4*x(1)^3+x(2),-4*x(2)^3+x(1)];   %Jacobian     
    y=x-Jg\g;                                            %iterate     
    x=y;                                                 %update x     
    n=n+1;                                               %counter+1     
end 

n,x,eps       %display end values

因此,使用此脚本,我已将函数和雅可比矩阵实现到实际脚本中,我正在努力研究如何使用所需的输入参数实际创建脚本。

谢谢!

1 个答案:

答案 0 :(得分:6)

如果您不介意,我想重新构建您的代码,以便它更具动态性和用户友好性。

让我们从一些预赛开始吧。如果你想让你的脚本真正动态,那么我建议你使用Symbolic Math Toolbox。这样,您就可以使用MATLAB为您解决函数的派生。首先需要使用syms命令,然后使用您想要的任何变量。这告诉MATLAB你现在要将这个变量视为“符号”(即不是常数)。让我们从一些基础开始:

syms x;
y = 2*x^2 + 6*x + 3;
dy = diff(y); % Derivative with respect to x.  Should give 4*x + 6;
out = subs(y, 3); % The subs command will substitute all x's in y with the value 3
                  % This should give 2*(3^2) + 6*3 + 3 = 39

因为这是2D,我们将需要2D函数......所以我们将xy定义为变量。调用subs命令的方式略有不同:

syms x, y; % Two variables now
z = 2*x*y^2 + 6*y + x;
dzx = diff(z, 'x'); % Differentiate with respect to x - Should give 2*y^2 + 1
dzy = diff(z, 'y'); % Differentiate with respect to y - Should give 4*x*y + 6
out = subs(z, {x, y}, [2, 3]); % For z, with variables x,y, substitute x = 2, y = 3
                               % Should give 56

还有一件事......我们可以将方程式放入向量或矩阵中,并使用subs同时将xy的所有值替换为每个等式。

syms x, y;
z1 = 3*x + 6*y + 3;
z2 = 3*y + 4*y + 4;
f = [z1; z2];
out = subs(f, {x,y}, [2, 3]); % Produces a 2 x 1 vector with [27; 25]

我们可以为矩阵做同样的事情,但为了简洁起见,我不会告诉你如何做到这一点。我将遵从代码,然后你可以看到它。

现在我们已经建立了这个,让我们一次一个地处理你的代码,以真正实现这一点。您的函数需要初始猜测x0,函数f(x)作为列向量,雅可比矩阵作为2 x 2矩阵,公差tol

在运行脚本之前,您需要生成参数:

syms x y; % Make x,y symbolic
f1 = x^2 + y^3 - 1; % Make your two equations (from your example)
f2 = x^4 - y^4 + x*y;
f = [f1; f2]; % f(x) vector

% Jacobian matrix
J = [diff(f1, 'x') diff(f1, 'y'); diff(f2, 'x') diff(f2, 'y')];

% Initial vector
x0 = [1; 1];

% Tolerance:
tol = 1e-10;

现在,将您的脚本变成一个函数:

% To run in MATLAB, do: 
% [n, xout, tol] = Jacobian2D(f, J, x0, tol);
% disp('n = '); disp(n); disp('x = '); disp(xout); disp('tol = '); disp(tol);

function [n, xout, tol] = Jacobian2D(f, J, x0, tol)

% Just to be sure...
syms x, y;

% Initialize error
ep = 1; % Note: eps is a reserved keyword in MATLAB

% Initialize counter
n = 0;

% For the beginning of the loop
% Must transpose into a row vector as this is required by subs
xout = x0';

% Computation loop     
while ep > tol && n < 100 
   g = subs(f, {x,y}, xout);   %g(x)
   ep = abs(g(1)) + abs(g(2)); %error     
   Jg = subs(J, {x,y}, xout);  %Jacobian  
   yout = xout - Jg\g;         %iterate     
   xout = yout;                %update x     
   n = n + 1;                  %counter+1     
end

% Transpose and convert back to number representation
xout = double(xout');

我应该告诉你,当你使用符号数学工具箱进行计算时,你计算它们时数字的数据类型是sym个对象。您可能希望将这些转换回实数,因此您可以使用double将它们转换回来。但是,如果您将它们保留为sym格式,则会将您的数字显示为整齐的分数,如果这是您要查找的内容。如果您想要小数点表示,请转换为double

现在,当您运行此功能时,它应该可以为您提供所需的功能。我没有测试过这段代码,但我很确定这会有用。

很高兴回答您的任何问题。希望这会有所帮助。

干杯!