局部搜索应用:百万皇后问题皇后问题

皇后问题

在一个 \(n\times n\) 的棋盘上,每行每列有且只有一个皇后棋子,每对角线至多一个皇后棋子。

如果使用回溯法,计算10皇后、20皇后问题还是可行的。

但是当皇后数增加到一百万个时,又该如何求解呢?

局部搜索算法用于求解组合优化问题,而皇后问题是组合问题,和优化没有关系,我们可以先将皇后问题转化为最优化问题

  • 指标函数:棋盘上皇后的冲突数。

  • 表示:

    \(S=\{S_i\}\)表示一个可能解,其中 \(S_i\) 表示在第 \(i\) 行,第 \(S_i\) 列有一个皇后。

    如四皇后问题的一个解:\(S=(2,4,1,3)\)

皇后搜索算法

  1. 随机地将 \(n\) 个皇后分布在棋盘上,使得棋盘的每行、每列只有一个皇后;
  2. 计算皇后间的冲突数 \(c\)
  3. 如果冲突数 \(c\) 等于0,则转 (7)
  4. 任选两个皇后交换他们在序列中的位置;
  5. 如果交换后的冲突数 \(c\) 减少,则接受这次交换,更新冲突数 \(c\) ,转(3);
  6. 如果陷入了局部极小,即交换了所有的皇后后,冲突数仍然不能下降,则转1;
  7. 输出结果;
  8. 结束。

可以使用局部搜索算法解决大规模皇后问题(并找到全局最优解)的关键在于:我们知道冲突数这个指标有最小值,并且最小值为0,从而我们可以判断某一时刻是否陷入了局部极小,或者是否已到达最优解。

而对于另一个著名的组合问题,旅行商问题来说,我们也可以用局部搜索算法来求解,但是我们不知道指标(路径长度)的最小值是多少,因此我们只能求得局部最优解,无法判断求得的局部最优解是否全局最优。

大多数组合问题都和旅行商问题一样,使用局部搜索算法往往是无法判断全局最优的。

局部搜索算法存在的问题局部最优问题

最明显的问题是可能会得到局部最优解,如上图的 \(B\)\(C\),而得不到 \(A\)。而这些最终结果与初始点有关,因此需要多次随机地设置初始点,然后在得到的多个解中,找出相对较优的解。

解决思路

  • 按概率接受解(在领域中寻找解的时候,并不是只接受最优解,而是为每个解计算概率,然后随机走下一步)

  • 从邻域中随机选择一个解,如果该解的指标函数好于当前已知的最好解,则以大概率接受该解,否则就以小概率接受该解

求最大值时

概率的计算方法根据不同算法有不同实现,这里只是一个简单的例子。

\[P_{max}(x_i)=\frac{f(x_i)}{\sum\limits_{x_j\in N(x_b)}f(x_j)}\]

即 指标 除以 邻域内所有指标之和。

同理,求最小值时:

\[P_{min}(x_i)=1-P_{max}(x_i)\]

如何按概率接受一个解?

  • \(x_i\) 的接受概率为 \(P(x_i)\),当 \(random(0,1)<P(x_i)\) 时接受 \(x_i\)

步长问题

如果步长大,而“山峰”尖,则可能最终像上图中一样,结果落在了半山腰。

解决思路

改变步长

  • 如果步长太小,会导致计算效率降低。
  • 如果步长太大,可能导致错过最优解。

一种解决方法是,随着迭代次数的增加,逐渐减小步长。

不同的算法有不同的改变步长的做法。

大多数情况下还是需要多次调整初始步长,然后执行程序,多次调整。

起始点问题

起始点不同,最终的结果可能不同。可能得到全局最大值,也可能得到局部最大值。

解决思路

随机产生多个起始点,从多次运行结果中选择一个最好的结果。

综合求解

面对局部搜索算法存在的问题,应综合求解。

  • 按概率接受解;
  • 改变步长;
  • 多次运行方法。

有一种特殊的局部搜索算法叫模拟退火算法,就是基于“按概率接受解”和“改变步长”这两点的。