高度依赖初始猜测的非线性系统的解

Solution of a nonlinear system highly dependent on initial guess

我有一个非线性方程组

  1. xF - xA * exp(-(wAA * xA + wBB * xB)) = 0
  2. xF - xB * exp(-(wBB * xB + wAB * xA)) = 0
  3. xA + xB + xF -1 = 0

其中变量为xA、xB、xF,wAA、wBB、wAB为给定参数。变量是非负的并且在 [0,1] 区间内 这里有一个最小的示例代码

import math
from scipy.optimize import least_squares

coupleInteractions = [10000., 10., 0.]

def equations(p):
    xA, xB, xF = p
    wAA, wBB, wAB = coupleInteractions

    eq1 = xF - xA * math.exp(-(wAA * xA + wBB * xB))
    eq2 = xF - xB * math.exp(-(wBB * xB + wAB * xA))
    eq3 = xA + xB + xF -1

    return (eq1, eq2, eq3)

guess = [0., 1., 0.]
bounds = ([0., 0., 0.], [1., 1., 1.])
root = least_squares(equations, x0=guess, bounds=bounds, xtol=1.e-15, gtol = 1.e-15, ftol = 1.e-15, loss="cauchy")

print(root)
print(root.x)

我想在一些极限情况下测试代码。例如,如果所有参数都为零,wAA = wAB = wBB = 0,我有一个简单的线性系统,其中 xA = xB = xF = 1./3。在这种情况下,代码可以完美运行而不依赖于猜测值。

我想像发布的代码一样测试 wAA >> wBB 和 wAA >> wAB 的情况。从数学的角度来看,我得到了 xA = 1、xB = 0 和 xF = 0。但是使用 least_square 函数我得到了错误的答案。我故意使用“错误”的猜测来测试该方法,因为在中间情况下我不希望结果高度依赖于初始选择。我的代码有错误吗?

我进行了一项新测试,看看全局优化是否可行。我已经定义了函数:

def scalarEquations(p):
    xA, xB, xF = p
    wAA, wBB, wAB = coupleInteractions

    eq1 = xF - xA * math.exp(-(wAA * xA + wBB * xB))
    eq2 = xF - xB * math.exp(-(wBB * xB + wAB * xA))
    eq3 = xA + xB + xF -1

    return (eq1**2 + eq2**2 + eq3 **2)

它returns 3 个方程的平方和。然后我进行了蛮力法。

from scipy.optimize import brute
rranges = (slice(0,1, 0.05), slice(0,1, 0.005), slice(0,1, 0.005))
t = brute(scalarEquations, rranges)
print(t)

我得到了同样的“错误”解决方案。我知道全局优化器应该找到绝对最小值。没看懂。

您的代码看起来没问题。对于大于 e 的 wAA 和大于 e 的 wBB,看起来在 [0,1,0] 附近有一个局部最小值,并且优化正在向它收敛。

可能我找到了解决办法。我在我的方程系统对数函数的两边都应用了。另外,我用这个想法定义了一个新的损失函数。我将下限更改为 1.e-15 以避免域错误。最后,我进行了粗略的优化。这是我的新代码

def scalarEquations(p):
    xA, xB, xF = p
    wAA, wBB, wAB = coupleInteractions

    eq1 = math.log(xF) - math.log(xA * math.exp(-(wAA * xA + wAB * xB)))
    eq2 = math.log(xF) - math.log(xB * math.exp(-(wBB * xB + wAB * xA)))
    eq3 = math.log(xA + xB + xF) -math.log(1.)

    return (eq1**2 + eq2**2 + eq3 **2)

rranges = ((1.e-15, 1.), (1.e-15, 1.), (1.e-15, 1.) )
t = brute(scalarEquations, rranges, Ns = 100)
print(t)