启发式算法-蚁群算法

蚁群算法是模拟蚂蚁觅食行为的仿生优化算法,原理是信息素的正反馈机制,蚂蚁通过释放信息素来引导同伴找到最短路径。把问题的元素抽象为多条路径,每次迭代时为每只蚂蚁构建一个解决方案,该解决方案对应一条完整的路径,每次迭代后对所有路径上的信息素按一定比例模拟自然蒸发,避免局部最优,然后找出当前的最优路径进行信息素增强,在之后的迭代中蚂蚁就会倾向于选择信息素浓度高的路径,经过多次迭代后,找出全局的最优路径。该算法通常用于解决旅行商等NP难问题,算法性能依赖参数(如信息素重要因子 α、启发式因子 β、挥发率 ρ 等),结果难以预测,有一定的玄学。

算法流程
在这里插入图片描述

集合覆盖问题

给定一个全集U和若干子集S1, S2, …, Sn,找到最少数量的子集,使得它们的并集等于U。例如:

全集 U = {1, 2, 3, 4, 5}
子集 S1 = {1, 3}, S2 = {2, 3}, S3 = {3, 4}, S4 = {1, 4, 5}
最优解:[S1, S3] 能覆盖所有元素的最小子集数量为2。

蚁群算法代码

import java.util.*;

public class AcoSetCover {
    // 定义全集和子集
    static Set<Integer> universe = new HashSet<>(Arrays.asList(1, 2, 3, 4,5));
    static List<Set<Integer>> subsets = Arrays.asList(
            new HashSet<>(Arrays.asList(1, 3)),
            new HashSet<>(Arrays.asList(2, 3)),
            new HashSet<>(Arrays.asList(3, 4)),
            new HashSet<>(Arrays.asList(1, 4, 5))
    );
    static int numSubsets = subsets.size();

    // 算法参数
    static int m = 10;      // 蚂蚁数量
    static int maxIter = 10000;     // 最大迭代次数
    static double alpha = 1.0;    // 信息素重要因子
    static double beta = 2.0;     // 启发式因子
    static double rho = 0.1;      // 信息素挥发率
    static double Q = 1.0;        // 信息素强度

    static double[] pheromone;    // 子集的信息素

    public static void main(String[] args) {
        initializePheromone();
        List<Integer> bestSolution = null;
        int bestSize = Integer.MAX_VALUE;

        for (int iter = 0; iter < maxIter; iter++) {
            List<List<Integer>> antSolutions = new ArrayList<>();
            for (int ant = 0; ant < m; ant++) {
                List<Integer> solution = constructSolution();
                antSolutions.add(solution);
                if (solution.size() < bestSize) {
                    bestSize = solution.size();
                    bestSolution = new ArrayList<>(solution);
                }
            }
            updatePheromone(antSolutions);
        }
        System.out.println("全集: "+universe);
        System.out.println("子集: "+subsets);
        System.out.println("最优解子集下标: " + bestSolution);
        for(int i:bestSolution){
            System.out.println(subsets.get(i));
        }
    }


    // 初始化信息素
    static void initializePheromone() {
        pheromone = new double[numSubsets];
        Arrays.fill(pheromone, 1.0); // 初始信息素为1
    }

    // 蚂蚁构建解
    static List<Integer> constructSolution() {
        Set<Integer> covered = new HashSet<>();
        List<Integer> solution = new ArrayList<>();
        List<Integer> candidates = new ArrayList<>();

        while (!covered.equals(universe)) {
            candidates.clear();
            for (int i = 0; i < numSubsets; i++) {
                if (!solution.contains(i) && !Collections.disjoint(subsets.get(i), universe)) {
                    Set<Integer> subset = subsets.get(i);
                    if (!covered.containsAll(subset)) {
                        candidates.add(i);
                    }
                }
            }
            if (candidates.isEmpty()) break;

            // 计算选择概率
            double[] probabilities = new double[candidates.size()];
            double total = 0.0;
            for (int i = 0; i < candidates.size(); i++) {
                int subsetIdx = candidates.get(i);
                double heuristic = (double) (subsets.get(subsetIdx).size() - covered.size()) / subsets.get(subsetIdx).size();
                probabilities[i] = Math.pow(pheromone[subsetIdx], alpha) * Math.pow(heuristic, beta);
                total += probabilities[i];
            }

            // 轮盘赌选择
            double rand = Math.random() * total;
            double cumulative = 0.0;
            int selected = -1;
            for (int i = 0; i < candidates.size(); i++) {
                cumulative += probabilities[i];
                if (cumulative >= rand) {
                    selected = candidates.get(i);
                    break;
                }
            }

            // 更新覆盖集和解
            solution.add(selected);
            covered.addAll(subsets.get(selected));
        }
        return solution;
    }

    // 更新信息素
    static void updatePheromone(List<List<Integer>> antSolutions) {
        // 信息素挥发
        for (int i = 0; i < numSubsets; i++) {
            pheromone[i] *= (1 - rho);
        }

        // 蚂蚁释放信息素
        for (List<Integer> solution : antSolutions) {
            double delta = Q / solution.size();
            for (int subsetIdx : solution) {
                pheromone[subsetIdx] += delta;
            }
        }
    }
}

在这里插入图片描述

该算法还可以用于解决覆盖设计问题
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值