我注意到接受的解决方案中的代码不再起作用......我认为scipy.optimize
自从发布答案以来可能已经改变了它的界面。我可能是错的。无论如何,我支持使用算法的建议scipy.optimize
,并且接受的答案确实展示了如何(或者如果界面发生了变化,则曾经做过)。
我在这里添加了一个额外的答案,纯粹是为了建议一个使用scipy.optimize
核心算法的替代包,但对于约束优化来说更加健壮。包是mystic
. 其中一项重大改进是mystic
提供了受限的全局优化。
首先,这是您的示例,与方式非常相似scipy.optimize.minimize
,但使用了全局优化器。
from mystic import reduced
@reduced(lambda x,y: abs(x)+abs(y)) #choice changes answer
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)] #unnecessary
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
如前所述,in 的选择lambda
会reduced
影响优化器找到的点,因为方程没有实际的解。
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)] #unnecessary
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
有另一种方法可以在没有解决方案的情况下看到。而不是应用一个更传统的penalty
,它惩罚违反约束的解决方案......mystic
提供了一个constraint
,它本质上是一个内核转换,它删除了所有不满足常量的潜在解决方案。
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)] #unnecessary
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
.