给定一个2D点p
,我试图计算该点与功能曲线之间的最小距离,即找到曲线上的点,它给出了f(x) = 2*sin(x)
的最小距离,然后计算那个距离。我正在使用的示例函数是
p
我对某个点def dist(p, x, func):
x = np.append(x, func(x))
return sum([[i - j]**2 for i,j in zip(x,p)])
与提供的函数之间距离的距离函数是
p
它作为输入,点x
,函数上的位置func
和函数句柄bounds = [0, 2*np.pi]
。注意这是一个平方欧几里德距离(因为欧几里得空间的最小化与平方欧几里德空间的最小化相同)。
这个的关键部分是我希望能够为我的函数提供边界,所以我找到了距离函数段最近的距离。对于这个例子,我的界限是
scipy.optimize.minimize
我正在使用{{1}}函数来最小化我的距离函数,使用边界。上述过程的结果如下图所示。
这是显示与sin函数的距离的等高线图。请注意轮廓中是否存在不连续性。为方便起见,我在不连续点和它们映射到的曲线上的“壁橱”点上绘制了几个点。
这里实际发生的是scipy函数是找到局部最小值(给出一些初始猜测),但不是全局函数,这导致了不连续性。我知道找到任何函数的全局最小值是不可能的,但我正在寻找一种更可靠的方法来找到全局最小值。
找到全局最小值的可能方法是
关于最佳解决方法的建议,或可能解决此问题的有用功能的方向都会很棒!
答案 0 :(得分:5)
根据评论中的建议,您可以尝试使用全局优化算法,例如scipy.optimize.differential_evolution
。但是,在这种情况下,如果您具有明确且易于分析的目标函数,则可以采用半分析方法,充分利用一阶必要条件。
在下文中,第一个函数是距离度量,第二个函数是其导数w.r.t的(分子)。 x
,如果某个0<x<2*np.pi
出现最小值,则该值应为零。
import numpy as np
def d(x, p):
return np.sum((p-np.array([x,2*np.sin(x)]))**2)
def diff_d(x, p):
return -2 * p[0] + 2 * x - 4 * p[1] * np.cos(x) + 4 * np.sin(2*x)
现在,给定一个点p
,d(x,p)
的唯一潜在最小值是diff_d(x,p)
(如果有)的根,以及边界点x=0
和x=2*np.pi
。事实证明diff_d
可能有多个根。注意到导数是一个连续函数,pychebfun库提供了一种非常有效的方法来查找所有根,避免了基于scipy
根寻找算法的繁琐方法。
以下函数为给定点d(x, p)
提供了p
的最小值:
import pychebfun
def min_dist(p):
f_cheb = pychebfun.Chebfun.from_function(lambda x: diff_d(x, p), domain = (0,2*np.pi))
potential_minimizers = np.r_[0, f_cheb.roots(), 2*np.pi]
return np.min([d(x, p) for x in potential_minimizers])
结果如下: