启发式算法详解——禁忌搜索
算法原理
禁忌搜索的原理是记录已经解得的局部最优解,并在进一步的迭代中避开这些局部最优解。为了找到全局最优解,禁忌搜索每次会随机形成解集,并计算这些解集的最优解,将最优解加入到禁忌表中。在下次形成解集中,有意识地避开禁忌表中的解,从而或得更多的搜索区域。
用大白话说,禁忌表记录了当前找到比较优秀的解,下次我随机生成的数组不能出现在禁忌表中,因为禁忌表中的解随机生成的邻域解我们都已经搜索过了,重复搜索效率会较低。
算法详解
禁忌搜索算法的关键点在于禁忌表的设置,在了解代码之前,有必要了解一下禁忌表的相关的参数和方法:
- 禁忌表:禁忌表是一个List,里面记录了已经搜索过的解集。在一维装箱场景中,禁忌表是一个二维数组,数组的行代表不同的解,数组的列记录了解集的输入。
- 禁忌长度:禁忌长度是禁忌表的长度,这是一个相当重要的参数,直接决定了算法效率。
- 邻域:在禁忌算法中,我们会搜索一个解集周边的其他解,这些解称为当前解集的邻域。我们将从领域中选择一个最优秀的解加入到禁忌表中
代码
以一维装箱为例,代码如下:
/** 迭代次数 **/
private int MAX_GEN = 500;
/** 每次搜索邻居个数 **/
private int neighbourNum;
/** 禁忌长度 **/
private int tabuLength;
/** 当前路线 **/
private int[] permutation;
/** 最佳计算结果 **/
private int fit;
/** 禁忌表 **/
private PriorityQueue<int[]> tabuTable;
/** permutation数组长度 **/
private int length;
public int calculate(int[] permutation) {
int curBestFit;
int[] curBestPermutation;
for (int i = 0; i < MAX_GEN; i++) {
int[][] neighbourPermutations = getNeighbourhood();
Arrays.sort(neighbourPermutations, Comparator.comparingInt(