Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用scipy/numpy或sympy执行非线性优化?_Python_Numpy_Scipy_Sympy - Fatal编程技术网

Python 如何使用scipy/numpy或sympy执行非线性优化?

Python 如何使用scipy/numpy或sympy执行非线性优化?,python,numpy,scipy,sympy,Python,Numpy,Scipy,Sympy,我试图找到Python中以下方程组的最佳解决方案: (x-x1)^2 + (y-y1)^2 - r1^2 = 0 (x-x2)^2 + (y-y2)^2 - r2^2 = 0 (x-x3)^2 + (y-y3)^2 - r3^2 = 0 给定一个点(x,y)和一个半径(r)的值: 找到点(x,y)的最优解的最佳方法是什么 使用上面的例子可以是: ~(1,1)如果我正确理解了你的问题,我想这就是你想要的: from scipy.optimize import minimize import nu

我试图找到Python中以下方程组的最佳解决方案:

(x-x1)^2 + (y-y1)^2 - r1^2 = 0
(x-x2)^2 + (y-y2)^2 - r2^2 = 0
(x-x3)^2 + (y-y3)^2 - r3^2 = 0
给定一个点(x,y)和一个半径(r)的值:

找到点(x,y)的最优解的最佳方法是什么 使用上面的例子可以是:

~(1,1)

如果我正确理解了你的问题,我想这就是你想要的:

from scipy.optimize import minimize
import numpy as np

def f(coord,x,y,r):
    return np.sum( ((coord[0] - x)**2) + ((coord[1] - y)**2) - (r**2) )

x = np.array([0,   2,  0])
y = np.array([0,   0,  2])
r = np.array([.88, 1, .75])

# initial (bad) guess at (x,y) values
initial_guess = np.array([100,100])

res = minimize(f,initial_guess,args = [x,y,r])
这将产生:

>>> print res.x
[ 0.66666666  0.66666666]
>>> print res[0]
>>> [ 0.77961518  0.85811473]
您还可以尝试使用最小二乘法,该方法需要返回向量的目标函数。它想最小化这个向量的平方和。使用最小二乘法,目标函数如下所示:

def f2(coord,args):
    x,y,r = args
    # notice that we're returning a vector of dimension 3
    return ((coord[0]-x)**2) + ((coord[1] - y)**2) - (r**2)
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
你可以这样最小化它:

from scipy.optimize import leastsq
res = leastsq(f2,initial_guess,args = [x,y,r])
这将产生:

>>> print res.x
[ 0.66666666  0.66666666]
>>> print res[0]
>>> [ 0.77961518  0.85811473]
这基本上与使用
最小化
并将原始目标函数重新编写为:

def f(coord,x,y,r):
    vec = ((coord[0]-x)**2) + ((coord[1] - y)**2) - (r**2)
    # return the sum of the squares of the vector
    return np.sum(vec**2)
这将产生:

>>> print res.x
>>> [ 0.77958326  0.8580965 ]
请注意,
leastsq
args
的处理稍有不同,两个函数返回的数据结构也不同。有关更多详细信息,请参阅和文档


有关更多优化选项,请参阅文档。

这些方程可以看作是描述二维空间中三个圆圆周上的所有点。解决方案是圆截取的点

圆的半径之和小于其中心之间的距离,因此圆不会重叠。我已按比例绘制了以下圆圈:


没有满足这个方程组的点。

我用下面的例子编写了一个脚本。请注意,最后一行将找到最佳解决方案(a,b):

这些产出是:

3*a**2 + 3*b**2 - x0*(a + b) - x1*(a + b) - x2*(a + b) + 2*y0 + 2*y1 + 2*y2
1.0*a**2 - 0.739792011558683*a + 1.0*b**2 - 0.739792011558683*b    +0.67394435712335


12.7806239653
12.7806239653
Out[33]:
  status: 0
 success: True
 njev: 3
 nfev: 12
 hess_inv: array([[1, 0],
   [0, 1]])
 fun: 3.6178137388030356
 x: array([ 0.36989601,  0.36989601])
 message: 'Optimization terminated successfully.'
 jac: array([  5.96046448e-08,   5.96046448e-08])

我注意到接受的解决方案中的代码不再有效。。。我想自从答案发布后,
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]
结果如下所示:

def f2(coord,args):
    x,y,r = args
    # notice that we're returning a vector of dimension 3
    return ((coord[0]-x)**2) + ((coord[1] - y)**2) - (r**2)
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
[          nan  657.17740835]
0.0
结果与之前不同,因为应用的惩罚与我们之前在
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)] #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]
结果如下:

[ 0.77958328  0.8580965 ]
3.6473132399e+12
[          nan  657.17740835]
0.0
其中,
nan
基本上表示没有有效的解决方案


仅供参考,我是作者,所以我有一些偏见。然而,
mystic
的存在时间几乎与
scipy.optimize
一样长,它是成熟的,并且在这段时间内拥有一个更稳定的界面。关键是,如果您需要更灵活、更强大的约束非线性优化器,我建议
mystic

在函数
eqs
中有未定义的变量(x和y)。你能包括你正在使用的实际代码吗?我正在尝试优化方程组的x和y值。我在使用这个例子:fsolve用于数值寻根,而不是优化,即它将寻求找到输入值,从而使函数的输出为零。您所指的示例在此不适用。此外,我不明白在三个方程的上下文中,最优值x和y应该是什么意思。(从你的代码上看,计算机两者都不会。)清楚你想要实现什么。谢谢你的评论,很抱歉不清楚。我已经重新表述了这个问题,希望现在更清楚。正确,但如果不存在精确解,我想要最优解。你说的最优解是什么意思,在这种情况下,没有解存在?这正是我想要的!感谢你们的帮助,感谢病人们试图理解我在做什么。很高兴听到这个消息!您还可以在成本函数中使用l2范数而不是求和,即使用
np.linalg.norm
代替
np.sum
,看看这对结果有何影响。这里是否也可以使用leastsq?minimize()和leastsq()之间的区别是什么?这里相关的主要区别是
minimize
需要一个标量值函数,而
leastsq
需要一个向量值函数
leastsq
希望最小化目标函数返回的向量的平方和,因此它几乎就像使用l2范数
minimize
。事实上,我得到的答案是