启发式算法-禁忌搜索算法

禁忌搜索是一种可以用于解决组合优化问题的启发式算法,通过引入记忆机制跳出局部最优,避免重复搜索。该算法从一个初始解开始,通过邻域搜索策略来寻找当前解的邻域解,并在邻域解中选择一个最优解作为下一次迭代的当前解,为了避免算法陷入局部最优,引入禁忌表来记录已经访问过的操作,禁止算法在一定迭代次数内再次选择这些被禁忌的操作,另外算法可以设置一些特赦条件,使得被禁忌的操作可以解除禁忌,从而探索更优的解空间。

算法流程

旅行商问题

假设有 4 个城市A、B、C、D,旅行商需要从一个城市出发,遍历所有城市且每个城市只经过一次,最后回到起始城市,要求找到最短的旅行路线,城市距离矩阵如下,最短的旅行路线为 A → B → D → C → A

禁忌搜索代码

java 复制代码
public class TabuSearchTSP {

    // 城市距离矩阵
    private static final int[][] DISTANCE_MATRIX = {
            {0, 2, 9, 10},
            {2, 0, 6, 4},
            {9, 6, 0, 8},
            {10, 4, 8, 0}
    };

    private static final int NUM_CITIES = 4;      // 城市数量
    private static final int TABU_TENURE = 2;     // 禁忌表长度
    private static final int MAX_ITERATIONS = 100; // 最大迭代次数

    public static void main(String[] args) {
        int[] bestSolution = tabuSearch();
        System.out.println("最优路径: " + formatPath(bestSolution));
        System.out.println("最短距离: " + calculateDistance(bestSolution));
    }
    private static String formatPath(int[] path) {
        String[] cities = {"A", "B", "C", "D"};
        StringBuilder sb = new StringBuilder();
        for (int idx : path) {
            sb.append(cities[idx]).append(" → ");
        }
        sb.append(cities[0]);
        return sb.toString();
    }
    // 禁忌搜索核心算法
    private static int[] tabuSearch() {
        // 初始化解
        int[] currentSolution = generateInitialSolution();
        int[] bestSolution = currentSolution.clone();
        int bestDistance = calculateDistance(bestSolution);

        // 禁忌表
        Queue<String> tabuList = new LinkedList<>();

        // 迭代搜索
        for (int iter = 0; iter < MAX_ITERATIONS; iter++) {
            int[] bestCandidate = null;
            int bestCandidateDist = Integer.MAX_VALUE;
            String move = null;

            // 生成邻域解
            for (int i = 1; i < NUM_CITIES; i++) {
                for (int j = i+1; j < NUM_CITIES; j++) {
                    // 避免重复交换
                    String swapKey = i + "-" + j;

                    // 生成候选解
                    int[] candidate = currentSolution.clone();
                    swap(candidate, i, j);
                    int candidateDist = calculateDistance(candidate);

                    // 检查是否满足特赦的条件
                    boolean isAspiration = candidateDist < bestDistance;

                    // 选择最优候选解或者满足特赦条件的候选解
                    if (!tabuList.contains(swapKey) || isAspiration) {
                        if (candidateDist < bestCandidateDist) {
                            bestCandidate = candidate.clone();
                            bestCandidateDist = candidateDist;
                            move = swapKey;
                        }
                    }
                }
            }

            // 更新当前解
            if (bestCandidate != null) {
                currentSolution = bestCandidate.clone();

                // 更新禁忌表
                tabuList.add(move);
                if (tabuList.size() > TABU_TENURE) {
                    tabuList.poll();
                }

                // 更新全局最优解
                if (bestCandidateDist < bestDistance) {
                    bestSolution = bestCandidate.clone();
                    bestDistance = bestCandidateDist;
                }
            }
        }
        return bestSolution;
    }

    private static int[] generateInitialSolution() {
        int[] solution = new int[NUM_CITIES];
        for (int i = 0; i < NUM_CITIES; i++) {
            solution[i] = i;
        }
        return solution;
    }

    private static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    // 计算路径总距离
    private static int calculateDistance(int[] path) {
        int distance = 0;
        for (int i = 0; i < NUM_CITIES; i++) {
            int from = path[i];
            int to = path[(i+1)%NUM_CITIES];
            distance += DISTANCE_MATRIX[from][to];
        }
        return distance;
    }
}
相关推荐
没头脑的男大7 小时前
关于删除列表的那些事儿
算法
Book思议-7 小时前
【数据结构实战】线性表的应用
c语言·数据结构·算法·链表
鬼蛟7 小时前
Spring————事务
android·java·spring
qq_461489337 小时前
C++与Qt图形开发
开发语言·c++·算法
Yzzz-F7 小时前
Problem - 2194E - Codeforces
算法
像污秽一样7 小时前
算法设计与分析-习题12.2
算法·迭代改进·分支界限
x_xbx8 小时前
LeetCode:83. 删除排序链表中的重复元素
算法·leetcode·链表
西门吹-禅8 小时前
【sap fiori cds up error】
java·服务器·sap cap cds
_小草鱼_8 小时前
【搜索与图论】DFS算法(深度优先搜索)
算法·深度优先·图论·回溯·递归
敲代码的嘎仔8 小时前
Java后端面试——SSM框架面试题
java·面试·职场和发展·mybatis·ssm·springboot·八股