如何在一维和n维空间中有效地选择邻域进行模拟退火

时间:2015-06-11 16:31:37

标签: java algorithm search optimization simulated-annealing

我想在一些预定义的时间间隔内使用模拟退火来找到单变量多项式函数的局部最小值。我还想尝试找到全局最小二次函数。

诸如此类的无衍生算法不是解决问题的最佳方法,因此这仅用于研究目的。

虽然算法本身非常简单,但我不确定如何在单维或n维空间中有效地选择邻居。

让我们说我正在寻找局部最小函数:2 * x ^ 3 + x + 1超过区间[-0.5,30],并假设间隔减少到每个数字的十分之一,例如{ 1.1,1.2,1.3,......,29.9,30}。

我想要实现的是随机行走和从起点到能量较低点的收敛速度之间的平衡。

如果我只是每次从给定的间隔中选择随机数,那么就没有随机游走,算法可能会绕圈。相反,如果通过简单地以相等的概率加上或减去0.1来选择下一个点,那么算法可能会变成穷举搜索 - 基于起点。

如何有效平衡单维和n维空间中的模拟退火邻域搜索?

2 个答案:

答案 0 :(得分:3)

所以你试图找到一个在另一个n维点P附近“随机”的n维点P';例如,在距离T处。(由于这是模拟退火,我假设您将偶尔递减T)。

这可行:

double[] displacement(double t, int dimension, Random r) {
      double[] d = new double[dimension];
      for (int i=0; i<dimension; i++) d[i] = r.nextGaussian()*t;
      return d;
}

输出在所有方向上随机分布并以原点为中心(注意r.nextDouble()倾向于45°角并且以0.5为中心)。您可以根据需要增加t来改变排量; 95%的结果将在原点的2 * t范围内。

编辑:

要在给定的位置附近生成移位点,您可以将其修改为

double[] displaced(double t, double[] p, Random r) {
      double[] d = new double[p.length];
      for (int i=0; i<p.length; i++) d[i] = p[i] + r.nextGaussian()*t;
      return d;
}

对于所有调用,您应该使用相同的r(因为如果为每个调用创建一个新的Random(),您将一遍又一遍地获得相同的位移)。

答案 1 :(得分:1)

在“ C ++的数字收据”中,有一章名为“通过模拟退火进行连续最小化”。在其中

  

如果存在局部下坡运动,但几乎总是建议进行上坡运动,则随机变化的生成器效率很低。我们认为,好的发电机不应在狭窄的山谷中变得效率低下。随着趋近于最小化,它也不应该变得越来越无效率。

然后他们继续讨论“下坡单纯形法”。