在Matlab中求解多个代数方程组

在Matlab中求解多个代数方程组,matlab,equations,Matlab,Equations,我尝试在MATLAB中求解九个代数方程组,其形式如下: eq1 = x1 * 3.12091E-17 * 10.96 * exp(x2 + x3 * 4.96) - 1765; eq2 = x1 * 3.12091E-17 * 5.08 * exp(x2 + x3 * 5.09) - 720; eq3 = x1 * 3.12091E-17 * 57.2 * exp(x2 + x3 * 5.22) - 7133; eq4 = x1 * 3.12091E-17 * 1.08 * exp(x2

我尝试在MATLAB中求解九个代数方程组,其形式如下:

eq1 = x1 * 3.12091E-17 * 10.96 * exp(x2 + x3 * 4.96) - 1765;

eq2 = x1 * 3.12091E-17 * 5.08 * exp(x2 + x3 * 5.09) - 720;

eq3 = x1 * 3.12091E-17 * 57.2 * exp(x2 + x3 * 5.22) - 7133;

eq4 = x1 * 3.12091E-17 * 1.08 * exp(x2 + x3 * 5.3) - 123;

eq5 = x1 * 3.12091E-17 * 5.01 * exp(x2 + x3 * 5.32) - 565;

eq6 = (100 - x1) * 4.91606E-18 * 0.096 * exp(x2 + x3 * 6.61) - 8;

eq7 = (100 - x1) * 4.91606E-18 * 0.318 * exp(x2 + x3 * 6.64) - 28;

eq8 = (100 - x1) * 4.91606E-18 * 0.054 * exp(x2 + x3 * 6.66) - 4;

eq9 = (100 - x1) * 4.91606E-18 * 0.832 * exp(x2 + x3 * 6.9) - 57;
这个系统在九个方程式中只有三个未知数。我曾尝试使用内置的MATLAB解算器来解决这个问题,但不幸的是,没有任何效果。未知数的正确值为:
x1=4.6;x2=47;x3=-1.2

你对MATLAB无法解决这个系统的问题有什么看法

问候,,
I.M.

如果你在9个方程式中有3个未知数,那么你的问题是。如果你的系统有一个解,那么一些方程必须是其他方程的线性组合——简言之,你只需要3个(线性独立)方程来解3个变量

接下来,如注释中所述,当使用小到
10^-18
和大到
e^40
的数字时,您将遇到浮点问题,尤其是在同一表达式中!您可以看到,通过简单的测试,精确度不够高

exp(40) + 1e-18 > exp(40) % Returns false, i.e. not enough accuracy for additional term 

eps(exp(40)) % Gives smallest distance to next number, returns 32. 
             % This is many orders of magnitude larger than 10^-18!

一旦你解决了这些问题,你应该看看,这是MATLAB的解算器的非线性方程组从一些初步猜测

我认为Wolfie和Durkee在这里是错的,你只是犯了一些问题正文中没有显示的其他错误

准确性不是问题 一个大数字乘以一个小数字。这在浮点运算中通常不是问题(除了欠/溢出情况),通常是加法/减法引起问题

基本上,浮点等于二进制的科学记数法。正如在普通的科学记数法中一样,浮点保持了与所用数字的大小无关的相对精度,因为尾数和指数是独立处理的。一个小型演示(请参阅背景):

忽略位0(符号位),这两个字符串表明只有前11位(指数)不同,但其余位(尾数)相同。这意味着
p1
p2
都是所需乘积
R1*R2
在浮点中的最佳表示,并且
R1
R2
的大小对精度没有影响(除非指数低于/溢出)

解方程 现在,回到你的问题上来。首先,我很好奇你是如何用线性系统的解算器解决一组非线性方程的:)

另外,当我实现你的方程,替换你给出的值,我得到一个负值向量…所以我不确定你在这里解什么

无论如何,我做了合理的假设,并尝试使用
fsolve
解决您的系统。事实上,我没有发现任何实质性问题:

function X = eqs()

    % Oh just shut up, FSOLVE...
    options = optimset('TolX'     , 1e-14,...
                       'TolFun'   , 1e-14,...
                       'Algorithm', 'Levenberg-Marquardt',...
                       'Display'  , 'off');

    % Pretend we don't know a good initial value
    done = false;
    while ~done  
        try
            [X, ~, e] = fsolve(@equations, 100*randn(3,1), options);
            done = (e==1);
        catch ME
            if ~strcmp(ME.identifier, 'optimlib:levenbergMarquardt:UsrObjUndefAtX0')
                rethrow(ME); end
        end
    end

end

function Y = equations(X)

    % Static factors
    A = 3.12091e-17 * [10.96;  5.08;  57.2;  1.08; 5.01];
    B = 4.91606e-18 * [0.096; 0.318; 0.054; 0.832];
    C = [4.96; 5.09; 5.22; 5.30; 5.32; 6.61; 6.64; 6.66; 6.90];
    D = [1765; 720; 7133; 123; 565; 8; 28; 4; 57];

    % (found by running the equation with your solution, to have a complete
    % equation compatible with fsolve)
    E = [-7.087431856800463e+02
         -3.011362826270133e+02
         -3.097892400288644e+03
         -5.378653741735363e+01
         -2.515404691148800e+02
         -3.826949873156565e+00
         -1.466555675930393e+01
         -1.789357783939141e+00
         -3.146292129042946e+01];

    % Value of the equations at current X
    Y = [A.*X(1).*ones(5,1); B.*(100-X(1)).*ones(4,1)] .* ...
        exp(X(2) + C*X(3)) - D - E;

end
结果:

>> eqs()
ans =
     4.599999930381616e+00
     4.700000001536806e+01
    -1.200000000274661e+00

这里唯一的问题可能是速度。我使用了一个非常简单的全局搜索例程:迭代地获取随机起始值,直到它们的某些组合导致
fsolve
收敛。在问题的上下文中,您可能能够做出更合理、更准确的估计,从而减少计算时间

首先,你尝试过哪些方法。其次,你要乘以非常小的数字,这会导致浮点问题的严重问题。另外,你在你想要的解决方案中列出了两次
x1
。好的,我刚刚测试了它,你肯定有浮点问题,我想你不会在MATLAB中工作。您的
10^-18
e^40
在同一行中,在64位机器上运行不太好。您好Durkee,谢谢您的评论。我已经更正了拼写错误的变量,谢谢您指出。关于我使用的解算器-我尝试过线性和非线性解算器,特别是:linsolve、矩阵除法和非线性解算器fsolve。此外,我还使用了fminsearch的数值求解方法。你认为主要的问题是由于方程式中存在非常低的数字吗?非常低的数字和非常高的数字加起来。MATLAB通常使用64位浮点,这意味着精度有限。如果在命令窗口中键入
eps(exp(40))
,可以看到可以存储的每个可能的数字之间的距离。如您所见,该值远大于
10^-18
,这意味着没有足够的精度来进行计算。在这一点上,它将计算舍入到
~±.5*eps(exp(40))
,这是一个很大的问题,会导致很大的错误Shello Wolfie,谢谢你的评论。事实上,据我所知,其中一个原因可能是由于人数非常少。关于你的第一点,我可能只需要3个独立的方程-我如何从我的9个方程构造它们?@Durkee你可以有你想要的任意多个,只要它们不冲突。最简单的例子是1个未知和2个方程
x=1,x=2
求解
x
是不可能的!这就是为什么我说它们必须是线性相关的,也就是说,
x=1,2x=2
求解
x
是可能的。这就是为什么我链接了更多关于超定系统的信息。@I.M.我们需要更多关于这些方程是如何构造的信息。如果它们是线性相关的,那么你可以任意选择3个不是线性相关的。如果没有,那么您的系统就没有解决方案(请参阅链接的wiki文章)。事实上,这些方程是线性相关的,但是即使使用fsolve任意选择3个方程,也不会产生任何结果-只有消息“未找到解决方案”…对,因此您已经解决了问题1(超定系统)然后跳到解决部分,而不解决问题2(浮点问题)。尝试一个更简单的系统,在那里你知道没有浮点问题,让它工作,然后更改值,直到你得到一个问题。你可能需要采取不同的方法来解决任何你想解决的问题,比如更多的数学问题
function X = eqs()

    % Oh just shut up, FSOLVE...
    options = optimset('TolX'     , 1e-14,...
                       'TolFun'   , 1e-14,...
                       'Algorithm', 'Levenberg-Marquardt',...
                       'Display'  , 'off');

    % Pretend we don't know a good initial value
    done = false;
    while ~done  
        try
            [X, ~, e] = fsolve(@equations, 100*randn(3,1), options);
            done = (e==1);
        catch ME
            if ~strcmp(ME.identifier, 'optimlib:levenbergMarquardt:UsrObjUndefAtX0')
                rethrow(ME); end
        end
    end

end

function Y = equations(X)

    % Static factors
    A = 3.12091e-17 * [10.96;  5.08;  57.2;  1.08; 5.01];
    B = 4.91606e-18 * [0.096; 0.318; 0.054; 0.832];
    C = [4.96; 5.09; 5.22; 5.30; 5.32; 6.61; 6.64; 6.66; 6.90];
    D = [1765; 720; 7133; 123; 565; 8; 28; 4; 57];

    % (found by running the equation with your solution, to have a complete
    % equation compatible with fsolve)
    E = [-7.087431856800463e+02
         -3.011362826270133e+02
         -3.097892400288644e+03
         -5.378653741735363e+01
         -2.515404691148800e+02
         -3.826949873156565e+00
         -1.466555675930393e+01
         -1.789357783939141e+00
         -3.146292129042946e+01];

    % Value of the equations at current X
    Y = [A.*X(1).*ones(5,1); B.*(100-X(1)).*ones(4,1)] .* ...
        exp(X(2) + C*X(3)) - D - E;

end
>> eqs()
ans =
     4.599999930381616e+00
     4.700000001536806e+01
    -1.200000000274661e+00