【问题标题】:Using MATLAB to write a function that implements Newton's method in two dimensions用MATLAB写一个二维实现牛顿法的函数
【发布时间】:2013-12-26 10:52:45
【问题描述】:

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

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

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

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

谢谢!

【问题讨论】:

    标签: matlab newtons-method


    【解决方案1】:

    如果您不介意,我想重新构建您的代码,使其更具动态性和更易于阅读。

    让我们从一些预备开始。如果您想让您的脚本真正动态化,那么我建议您使用 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
    

    还有一件事……我们可以将方程放入向量或矩阵中,并使用subsxy 的所有值同时代入每个方程。

    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

    现在,当您运行此函数时,它应该会为您提供所需的内容。我没有测试过这段代码,但我很确定这会起作用。

    很高兴回答您可能有的更多问题。希望这会有所帮助。

    干杯!

    【讨论】:

    • 它看起来很棒,但我不明白J = [diff(f1, 'x') diff(f1, 'y'); diff(f2, 'x') diff(f2, 'y')]; 的行。没有更简单的命令来计算 jacobian 吗?我想到了对 n 维的概括......
    • @bela83 有一个雅可比函数,但我做了您在J 行中看到的内容,以明确显示计算。 mathworks.com/help/symbolic/jacobian.html - 顺便说一句,如果你觉得这个答案有用,你可以随时支持我的答案:D。
    • 这些需要是不同的“.m”文件还是要合并到一个脚本中?
    • 我的 R2015a 版本中似乎没有符号工具箱。因此我无法让这个示例正常工作。
    • @tannman357 1) 是单独的文件。 2) 如果您已经知道导数是什么,您可以自己创建雅可比行列式,而无需使用符号工具箱。我稍后会修改这篇文章以解决这个问题,但我目前无法。
    猜你喜欢
    • 2018-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    • 2019-09-08
    相关资源
    最近更新 更多