我一直在尝试各种技术来寻找点(x,y)
,该点使从(x,y)
到三个圆的圆周的总距离最小。
下图显示了使用四种技术中的前三种技术,这些圆的示例排列以及(x,y)
的位置。
我现在正在尝试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))
我不认为我正在正确地评估/求解这些方程式,因为生成的点非常错误(请参见下图)
要证明渐变不取决于圆的半径,
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)
答案 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)
,所以我们有解决方案。
我希望这概述了您必须做的事情,并且我没有犯任何错误,因为我不是专家。我愿意在这里接受建设性的批评。