我注意到被接受的解决方案中的代码已经不再起作用了...我认为可能是因为自问题发布以来
scipy.optimize
改变了其接口。我可能是错的。但无论如何,我赞成使用
scipy.optimize
中的算法,并且被接受的答案确实演示了如何使用(如果接口未更改的话)。
我在这里添加了一个额外的答案,纯粹是为了建议一种使用
scipy.optimize
算法作为核心,但对于有约束优化更加强大的替代包,该包是
mystic
。 其中一个重大改进就是
mystic
提供了约束全局优化。
首先,这里是您的示例,非常类似于使用全局优化器的
scipy.optimize.minimize
方法。
from mystic import reduced
@reduced(lambda x,y: abs(x)+abs(y))
def objective(x, a, b, c):
x,y = x
eqns = (\
(x - a[0])**2 + (y - b[0])**2 - c[0]**2,
(x - a[1])**2 + (y - b[1])**2 - c[1]**2,
(x - a[2])**2 + (y - b[2])**2 - c[2]**2)
return eqns
bounds = [(None,None),(None,None)]
a = (0,2,0)
b = (0,0,2)
c = (.88,1,.75)
args = a,b,c
from mystic.solvers import diffev2
from mystic.monitors import VerboseMonitor
mon = VerboseMonitor(10)
result = diffev2(objective, args=args, x0=bounds, bounds=bounds, npop=40, \
ftol=1e-8, disp=False, full_output=True, itermon=mon)
print result[0]
print result[1]
当结果看起来像这样时:
Generation 0 has Chi-Squared: 38868.949133
Generation 10 has Chi-Squared: 2777.470642
Generation 20 has Chi-Squared: 12.808055
Generation 30 has Chi-Squared: 3.764840
Generation 40 has Chi-Squared: 2.996441
Generation 50 has Chi-Squared: 2.996441
Generation 60 has Chi-Squared: 2.996440
Generation 70 has Chi-Squared: 2.996433
Generation 80 has Chi-Squared: 2.996433
Generation 90 has Chi-Squared: 2.996433
STOP("VTRChangeOverGeneration with {'gtol': 1e-06, 'target': 0.0, 'generations': 30, 'ftol': 1e-08}")
[ 0.66667151 0.66666422]
2.99643333334
如前所述,在reduced
中选择lambda
会影响优化器找到的点,因为实际上没有解决方案。
mystic
还提供了将符号方程转换为函数的能力,其中生成的函数可以用作目标或惩罚函数。这里是同样的问题,但使用方程作为惩罚而不是目标。
def objective(x):
return 0.0
equations = """
(x0 - 0)**2 + (x1 - 0)**2 - .88**2 == 0
(x0 - 2)**2 + (x1 - 0)**2 - 1**2 == 0
(x0 - 0)**2 + (x1 - 2)**2 - .75**2 == 0
"""
bounds = [(None,None),(None,None)]
from mystic.symbolic import generate_penalty, generate_conditions
from mystic.solvers import diffev2
pf = generate_penalty(generate_conditions(equations), k=1e12)
result = diffev2(objective, x0=bounds, bounds=bounds, penalty=pf, \
npop=40, gtol=50, disp=False, full_output=True)
print result[0]
print result[1]
结果如下:
[ 0.77958328 0.8580965 ]
3.6473132399e+12
结果与以前不同,因为所应用的惩罚与我们之前在“reduced”中应用的惩罚不同。在“mystic”中,您可以选择要应用的惩罚。
有人指出方程没有解。从上面的结果可以看出,结果受到了严重的惩罚,这表明没有解决方案。然而,“mystic”还有另一种方法可以看出没有解。与其应用更传统的“惩罚”,该惩罚会惩罚违反约束条件的解决方案……“mystic”提供了一个“约束条件”,它本质上是一种核转换,可以消除不符合常数的所有潜在解决方案。
def objective(x):
return 0.0
equations = """
(x0 - 0)**2 + (x1 - 0)**2 - .88**2 == 0
(x0 - 2)**2 + (x1 - 0)**2 - 1**2 == 0
(x0 - 0)**2 + (x1 - 2)**2 - .75**2 == 0
"""
bounds = [(None,None),(None,None)]
from mystic.symbolic import generate_constraint, generate_solvers, simplify
from mystic.symbolic import generate_penalty, generate_conditions
from mystic.solvers import diffev2
cf = generate_constraint(generate_solvers(simplify(equations)))
result = diffev2(objective, x0=bounds, bounds=bounds, \
constraints=cf, \
npop=40, gtol=50, disp=False, full_output=True)
print result[0]
print result[1]
带有结果的情况:
[ nan 657.17740835]
0.0
其中nan
实际上表示没有有效的解决方案。
顺便说一下,我是作者,所以有些偏见。但是,mystic
已经存在了很长时间,几乎与scipy.optimize
一样成熟,并且在这段时间内具有更加稳定的接口。我的观点是,如果您需要一个更加灵活和功能强大的约束非线性优化器,我建议使用mystic
。
eqs
中有未定义的变量(x和y)。能否提供你正在使用的实际代码? - Warren Weckesser