Sympy-找到最小化到三个圆周的距离的点

时间:2018-12-19 22:17:14

标签: python sympy

我一直在尝试各种技术来寻找点(x,y),该点使从(x,y)到三个圆的圆周的总距离最小。

下图显示了使用四种技术中的前三种技术,这些圆的示例排列以及(x,y)的位置。

demo

我现在正在尝试this stackexchange post中描述的第四种技术。简而言之,我想使用sympy计算损失函数的一阶导数以找到其最小值/最大值,然后计算二阶导数来隔离最小值。

这是损失函数:

$ E(x,y)= \ sum_i \ big((x-x_i)^ 2 +(y-y_i)^ 2-r_i ^ 2 \ big)^ 2 $

这是一阶导数:

$ E'(x,y)= \ sum_i \ frac {y-y_i} {-x + x_i} $

以下代码尝试根据y来求解x的一阶导数方程,然后代之以求解x

x, y = sympy.symbols('x y')
x1, y1 = 0, 0
x2, y2 = 3, 0
x3, y3 = 2, 3

def fprime(x,y):
    return (y-y1)/(-x+x1) + (y-y2)/(-x+x2) + (y-y3)/(-x+x3)

sols = sympy.solve(fprime(x,y), y)
y = sols[0]
x_sols = sympy.solve(fprime(x,y), x)
y_sols = []
for x_sol in x_sols:
    y_sols.append(y.evalf(subs={x:x_sol}))

for x,y in zip(x_sols, y_sols):
    plt.scatter(float(x), float(y)) 

我不认为我正在正确地评估/求解这些方程式,因为生成的点非常错误(请参见下图)

enter image description here

要证明渐变不取决于圆的半径,

In [2]: x,y = sympy.symbols('x y')

In [3]: xi, yi, ri = sympy.symbols('xi yi ri', constant=True)

In [4]: def f(x,y):
   ...:     return ((x-xi)**2 + (y-yi)**2 - ri**2)**2
   ...:
   ...:

In [5]: sympy.idiff(f(x,y), x, y)
Out[5]: (y - yi)/(-x + xi)

1 个答案:

答案 0 :(得分:1)

batch.record.size不计算梯度。您想要的是idiff。我将仅针对一对( x_i,y_i ):

sympy.vector.gradient

哪个给你

import sympy
from sympy.vector import CoordSys3D, gradient

xi, yi, ri = sympy.symbols('xi yi ri', constant=True)
R = CoordSys3D('R')
f1 = ((R.x-xi)**2 + (R.y-yi)**2 - ri**2)**2
fprime = gradient(f1)

这是2D矢量场。现在,我们要找到In [25]: fprime Out[25]: ((4*R.x - 4*xi)*(-ri**2 + (R.x - xi)**2 + (R.y - yi)**2))*R.i + ((4*R.y - 4*yi)*(-ri**2 + (R.x - xi)**2 + (R.y - yi)**2))*R.j R.x,以便两个分量都为零。因此,我首先将R.y分量求解为零:

R.i

屈服

sympy.solve(fprime.components[R.i], R.x)

我只是从中选择了一种解决方案,您以后可以验证这是否确实是最低要求。因此,现在我们需要将其插入[xi, xi - sqrt((-R.y + ri + yi)*(R.y + ri - yi)), xi + sqrt((-R.y + ri + yi)*(R.y + ri - yi))] 组件中以获得R.j的方程式:

R.y

解决
eq = fprime.components[R.j].subs(R.x, xi - sympy.sqrt((-R.y + ri + yi)*(R.y + ri - yi)))

简单地给出sympy.solve(eq3, R.y) ,所以我们有解决方案。

我希望这概述了您必须做的事情,并且我没有犯任何错误,因为我不是专家。我愿意在这里接受建设性的批评。