为什么fsolve似乎不迭代解决方案?

时间:2019-09-12 06:49:36

标签: matlab

我正在尝试使用fsolve和dogleg方法求解两个非线性方程组。我的目标函数及其雅各布像这样

function [F jacF]= objective(x)

    F(:,1) = ((((x(:,2)./10).*k).*(x(:,1)./100)).^2).*(rZ - Rs) +(( Cmax .* ( x(:,1)./100 ) ).^2).*( w.^2.*(rZ - Rs) ) - (((x(:,2)./10).*k).*(x(:,1)./100)); 

    F(:,2) = (x(:,2).*k).^2.*(iZ - w.*Ls) + (x(:,2).*k).^2.*x(:,1).*((w.*Ls)./200) + x(:,1).*((w.*Ls)/200).*(w.*Cmax).^2 + (w.*Cmax).^2 .*(iZ -(w.*Ls));

    if nargout > 1 % need Jacobian
        jacF = [- k - (k.^2.*x(:,2).*x(:,1).*(Rs - rZ))./50,                         - (k.^2.*x(:,2).^2.*(Rs - rZ))./100 - (Cmax.^2.*w.^2.*(Rs - rZ))./100;
                2.*k.^2.*x(:,2).*(iZ - Ls.*w) + (k.^2.*Ls.*x(:,2).*w.*x(:,1))./100,(Ls.*Cmax.^2.*w.^3)./200 + (Ls.*k.^2.*x(:,2).^2.*w)./200];
    end
end

然后我对fsolve的配置如下所示:

    options = optimoptions('fsolve','Display','iter-detailed','PlotFcn',@optimplotfirstorderopt);
%     options.StepTolerance = 1e-13;
    options.OptimalityTolerance = 1e-12;
    options.FunctionTolerance = 6e-11;
    options.MaxIterations = 100000;
    options.MaxFunctionEvaluations = 400;%*400;
    options.Algorithm = 'trust-region-dogleg';%'trust-region'%'levenberg-marquardt';%
%     options.FiniteDifferenceType= 'central';
    options.SpecifyObjectiveGradient = true;
    fun= @objective;

    x0 = [x1',x2'];

    % Solve the function fun
    [gwc,fval,exitflag,output,jacobianEval] =fsolve(fun,x0,options);

成为方程式的值

Rs =
    0.1640
Ls =
   1.1000e-07
Cmax =
   7.0000e-11
w =
   1.7040e+08
rZ =
   12.6518
iZ = 
   14.5273
K =
    0.1007
x0 = 
    70.56 0.0759

我的问题来了,因为我不明白为什么fsolve似乎没有像我期望的那样遍历x(:,1)。我确实知道上述系统和参数的解决方案应该是x1=58.8x2=0.0775。 为了测试该方法的收敛性,我将其设置为初始猜测x0 = [x1*(1+20/100) 0.0759] = [70.56 0.0759](x1中有20%的错误,x2中有一个更高的值),但是fsolve给出的解决方案是初始点,这是为什么呢?我的设置做错了吗?

预先感谢

编辑:添加了具有一般系数的方程 enter image description here

1 个答案:

答案 0 :(得分:1)

使用您的代码,我试图找出问题所在,但除了“病态”行为外,似乎没有其他问题。

我试图观察您的函数的行为,并注意:

x = -50:50;
y = -50:50;

[X,Y]=meshgrid(x,y);
F1 = zeros(size(X));
F2 = zeros(size(X));
for i=1:size(X,1)
    for j=1:size(X,2)
        f = objective([X(i,j) Y(i,j)]);
        F1(i,j) = f(1);
        F2(i,j) = f(2);
    end
end

figure; 
subplot(1,2,1)
surf(X,Y,F1); shading interp; xlabel('x1');ylabel('x2');zlabel('F_1'); colorbar
subplot(1,2,2)
surf(X,Y,F2); shading interp; xlabel('x1');ylabel('x2');zlabel('F_2'); colorbar

enter image description here

F1是向量函数的第一个元素,F2是第二个元素。 请注意,F1在整个范围内几乎是恒定的(从0到1变化很小)。还要注意,对于F2的大部分表面,您都有亮黄色的部分,这意味着该功能也不会发生很大变化。对于任何给定的初始条件,F函数的范数都足够小,因此该区域中的任何点都将被视为“对于函数的零足够好”。 我们还注意到,您的等式中的某些值具有非常不同的数量级,

Rs =
    0.1640
Ls =
   1.1000e-07
Cmax =
   7.0000e-11
w =
   1.7040e+08
rZ =
   12.6518

这使得解决起来更加困难。最好的解决方案是尝试更改变量以标准化输入和输出。那应该缩放自变量和矢量值函数,以改善模型的数值误差。


好的,您现在已经提供了方程式,并且您的问题似乎(从数字意义上来说)比我最初想象的要糟糕。

您的等式是: enter image description here

鉴于x1是第二个变量的函数,实际上您只有1个自变量,而不是2。因此,您可以编写F1 = f1(x2)F2=f2(x2),因为这两个函数都是一个变量的函数。您有两种选择来求解由2个方程和1个变量组成的方程组(请注意这里的问题吗?)

  1. 第一个选择-简单的选择-是分别求解每个方程。这样,您将获得x2的两个不同值,一个满足第一个方程式,另一个满足第二个方程式。这没有帮助。

  2. 第二种选择-艰难的选择-同时求解两个方程。这里最困难的部分是,您必须定义一个精确的条件来求解方程。看,您有两个方程,但是一个变量,那么您如何知道找到的解决方案是“最优”一个?常用的准则是求解least-squares sense中的两个方程,即,找到x2的值可使平方S=F1^2+F2^2的和最小。 现在,您具有通用系数的方程式与您提供的代码不完全匹配,因此我不知道这些aibi系数中的哪个是RsLsCmax等,但通常可以用最小二乘法来求解方程:

    a1 =兰德; a2 =兰特; a3 =兰特; b1 =兰特; b2 =兰特; b3 =兰特; b4 =兰特; b5 =兰特;

    fun = @(x2)myfun(x2,a1,a2,a3,b1,b2,b3,b4,b5); x0 = 1; [X,FVAL,EXITFLAG] = fminsearch(fun,x0)

    函数S = myfun(x2,a1,a2,a3,b1,b2,b3,b4,b5)     x1 = a2 * x2 ./(a1 * x2。^ 2 + a3);

    f1 = a1*(x1.*x2).^2 - a2*x1.*x2 + a3.*x1.^2;
    f2 = b1*(x1.*x2).^2 + b2*x1.*(x1.*x2).^2 + b3*x1.^3 + b4*x1.^2 + b5*x1;
    
    S = f1^2+f2^2;
    

    结束

请注意,您将必须正确定义常数和初始估计。由于x1x2的一个函数,因此您可以在函数体内进行计算。然后,您计算函数的每个组件,然后创建平方和。函数fminsearch找到平方和的最小值-方程的解。