我正在尝试使用边界和初始值求解 GEKKO 中的非线性方程。以下示例说明了我试图解决更大的非线性方程组的两个主要问题。
from gekko import GEKKO
import numpy as np
m = GEKKO()
a = m.Const(value=1)
b = m.Const(value=1)
x = m.Var(value=3,lb=0)
y = m.Var(value=3,lb=0)
m.Equation(10**-x + y == a)
m.Equation(x - 10**y == b)
m.solve(disp=False)
print(x.value,y.value)
这给出了一个解决方案:
[10.999999998] [0.99999999999]
问题 1 - 我想使用 a 常量的输入范围来求解 x,y,并且也不关心舍入误差。例如,我可以加入
np.linspace
吗?
a = np.linspace(1,10,10)
问题2 - 到a=4时,
value=3
的初始值就不起作用了。为了解决这个问题,我想使用 x,y 解作为下一次迭代的初始值。例如,对于 a=1,解决方案是 [10.999999998] [0.99999999999]
,我希望将其作为下一次迭代的初始值 a=2:
x = m.Var(value=10.999999998,lb=0)
y = m.Var(value=0.99999999999,lb=0)
依此类推,直到达到a=10。
将
m.Param()
用于 a
,以便可以在每个循环中调整 a.value
。还可以调整 x.value
和 y.value
来给出初步猜测。 Gekko 自动将先前的解决方案存储为新的初始猜测,因此无需重新初始化 x
和 y
。
from gekko import GEKKO
import numpy as np
m = GEKKO()
av = np.linspace(1,10,10)
xv = 3; yv = 3
a = m.Param()
b = m.Const(value=1)
x = m.Var(value=xv,lb=0)
y = m.Var(value=yv,lb=0)
m.Equation(10**-x + y == a)
m.Equation(x - 10**y == b)
for ai in av:
a.value = ai
x.value = xv
y.value = yv
m.solve(disp=False)
# print solution
xv = np.round(x.value[0],2)
yv = np.round(y.value[0],2)
print(f'a: {np.round(ai,2)} x: {xv} y: {yv}')
这给出了解决方案:
a: 1.0 x: 11.0 y: 1.0
a: 2.0 x: 101.0 y: 2.0
a: 3.0 x: 1001.0 y: 3.0
a: 4.0 x: 10001.0 y: 4.0
a: 5.0 x: 100001.0 y: 5.0
a: 6.0 x: 1000001.0 y: 6.0
a: 7.0 x: 10000001.0 y: 7.0
a: 8.0 x: 100000001.0 y: 8.0
a: 9.0 x: 1000000001.0 y: 9.0
a: 10.0 x: 10000000001.0 y: 10.0
解决此问题的另一种方法是使用
IMODE=2
一次性解决 a
中的所有排列。对于这个问题,需要使用 IMODE=3
进行初始化。这可能会快得多,因此可以解决一个更大的优化问题,而不是解决一系列优化问题。
from gekko import GEKKO
import numpy as np
m = GEKKO()
a = m.Param(value=1)
b = m.Const(value=1)
x = m.Var(value=3,lb=0)
y = m.Var(value=3,lb=0)
m.Equation(10**-x + y == a)
m.Equation(x - 10**y == b)
m.options.IMODE=3
m.solve(disp=False)
m.options.IMODE=2
a.value=np.linspace(1,10,10)
m.solve(disp=False)
for i,ai in enumerate(a.value):
xv = np.round(x.value[i],2)
yv = np.round(y.value[i],2)
print(f'a: {np.round(ai,2)} x: {xv} y: {yv}')
结果是一样的:
a: 1.0 x: 11.0 y: 1.0
a: 2.0 x: 101.0 y: 2.0
a: 3.0 x: 1001.0 y: 3.0
a: 4.0 x: 10001.0 y: 4.0
a: 5.0 x: 100001.0 y: 5.0
a: 6.0 x: 1000001.0 y: 6.0
a: 7.0 x: 10000001.0 y: 7.0
a: 8.0 x: 100000001.0 y: 8.0
a: 9.0 x: 1000000001.0 y: 9.0
a: 10.0 x: 10000000001.0 y: 10.0