我注意到已接受的解决方案中的代码不再工作。。。我想也许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

如前所述,在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)] #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。