数学建模常用算法:蚁群算法求解tsp问题+att48算例测试【java实现--详细注释】

简介: 数学建模常用算法:蚁群算法求解tsp问题+att48算例测试【java实现--详细注释】

代码

蚂蚁类

package com.dam.heuristic.aco.test;
import java.util.*;
public class Ant {
    //蚂蚁所走的城市序列
    private List<Integer> sequence;
    //未访问的城市
    private LinkedHashSet<Integer> unVisitedCities;
    //信息素变化矩阵
    private double[][] delta;
    //距离矩阵
    private double[][] distanceMatrix;
    //信息素重要程度因子,其值越大,表示信息素的浓度在转移中起的作用越大
    private double alpha;
    //启发函数重要程度因子,其值越大,表示启发函数在转移中的作用越大,即蚂蚁会以较大的概率转移到距离短的城市
    private double beta;
    //城市数量
    private int cityNum;
    //蚂蚁的起始城市
    private int firstCity;
    //蚂蚁当前所在城市
    private int currentCity;
    public Ant(double[][] distanceMatrix, double alpha, double beta) {
        this.distanceMatrix = distanceMatrix;
        this.alpha = alpha;
        this.beta = beta;
        this.cityNum = distanceMatrix[0].length;
        this.unVisitedCities = new LinkedHashSet<>();
        this.sequence = new ArrayList<>();
        this.delta = new double[cityNum][cityNum];
    }
    /**
     * 初始化蚂蚁,随机选择起始位置
     */
    public void initAntMessage() {
        this.unVisitedCities.clear();
        this.sequence.clear();
        //初始化信息素变化矩阵为0
        for (int i = 0; i < cityNum; i++) {
            for (int j = 0; j < cityNum; j++) {
                this.delta[i][j] = 0;
            }
            this.unVisitedCities.add(i);
        }
        //随机挑选一个城市作为起始城市
        this.firstCity = new Random().nextInt(cityNum);
        //未访问城市集合中移除起始城市
        this.unVisitedCities.remove(this.firstCity);
        //将起始城市添加至序列中
        this.sequence.add(this.firstCity);
        //设置蚂蚁当前所在城市为起始城市
        this.currentCity = firstCity;
    }
    /**
     * 结合蚂蚁当前所在城市和信息素矩阵选择蚂蚁下一个要访问的城市
     *
     * @param pheromone 信息素矩阵
     */
    public void selectNextCity(double[][] pheromone) {
        计算从当前城市去往未访问城市的概率
        double[] p = new double[this.cityNum];
        //分母
        double denominator = 0;
        //计算分母部分
        for (Integer cityIndex : this.unVisitedCities) {
            denominator += Math.pow(pheromone[this.currentCity][cityIndex], alpha) * Math.pow(1.0 / distanceMatrix[this.currentCity][cityIndex], beta);
        }
        //计算去未访问的城市的概率矩阵,去过的城市概率为0,不用设置
        for (Integer cityIndex : this.unVisitedCities) {
            //除以分母,求概率,同时也是归一化的一种方式
            p[cityIndex] = (Math.pow(pheromone[this.currentCity][cityIndex], alpha) * Math.pow(1.0 / distanceMatrix[this.currentCity][cityIndex], beta)) / denominator;
        }
        轮盘赌选择下一个城市
        //指针指向的概率
        double selectP = new Random().nextDouble();
        //下一个要访问的城市
        int nextCity = -1;
        //存储最后一个未访问的城市,防止浮点数精度原因,没有选择到城市
        int lastAllowedCity = -1;
        double sum = 0;
        for (Integer city : this.unVisitedCities) {
            lastAllowedCity = city;
            sum += p[city];
            //找到指针指向的城市,退出循环
            if (sum >= selectP) {
                nextCity = city;
                break;
            }
        }
        //当没有选择到城市时,选择未访问城市中的最后一个城市
        nextCity = nextCity == -1 ? lastAllowedCity : nextCity;
        //从允许选择的城市中去除selectCity
        this.unVisitedCities.remove(nextCity);
        //在sequence中添加nextCity
        this.sequence.add(nextCity);
        //将当前城市改为选择的城市
        this.currentCity = nextCity;
    }
    /**
     * 计算路径长度
     *
     * @return 路径长度
     */
    private double getObjectValue() {
        double objectValue = 0;
        //sequence最终样式:起始城市,城市1,城市2,... ,结尾城市,起始城市
        //this.sequence.size() - 1的原因,两点之间有一段距离,三点之间有两端距离
        for (int i = 0; i < this.sequence.size() - 1; i++) {
            objectValue += distanceMatrix[this.sequence.get(i)][this.sequence.get(i + 1)];
        }
        return objectValue;
    }
    public List<Integer> getSequence() {
        return sequence;
    }
    public void setSequence(List<Integer> sequence) {
        this.sequence = sequence;
    }
    public LinkedHashSet<Integer> getUnVisitedCities() {
        return unVisitedCities;
    }
    public void setUnVisitedCities(LinkedHashSet<Integer> unVisitedCities) {
        this.unVisitedCities = unVisitedCities;
    }
    public double[][] getDelta() {
        return delta;
    }
    public void setDelta(double[][] delta) {
        this.delta = delta;
    }
    public double[][] getDistanceMatrix() {
        return distanceMatrix;
    }
    public void setDistanceMatrix(double[][] distanceMatrix) {
        this.distanceMatrix = distanceMatrix;
    }
    public double getAlpha() {
        return alpha;
    }
    public void setAlpha(double alpha) {
        this.alpha = alpha;
    }
    public double getBeta() {
        return beta;
    }
    public void setBeta(float beta) {
        this.beta = beta;
    }
    public double getBestObjectValue() {
        return this.getObjectValue();
    }
    public int getCityNum() {
        return cityNum;
    }
    public void setCityNum(int cityNum) {
        this.cityNum = cityNum;
    }
    public int getFirstCity() {
        return firstCity;
    }
    public void setFirstCity(int firstCity) {
        this.firstCity = firstCity;
    }
    public int getCurrentCity() {
        return currentCity;
    }
    public void setCurrentCity(int currentCity) {
        this.currentCity = currentCity;
    }
}


蚁群算法

package com.dam.heuristic.aco.test;
import java.util.Arrays;
/**
 * 蚁群算法
 */
public class AcoApi {
    //蚂蚁数组
    private Ant[] antArr;
    //蚂蚁数量
    private int antNum;
    //城市数量
    private int cityNum;
    //迭代次数
    private int MAX_GEN;
    //信息素矩阵
    private double[][] pheromone;
    //最短回路长度
    private double bestObjectValue;
    //最佳路径
    private int[] bestSequence;
    //信息素挥发程度参数
    private double rho;
    public AcoApi(int antNum, int MAX_GEN, double alpha, double beta, double rho, double[][] distanceMatrix) {
        this.antNum = antNum;
        this.cityNum = distanceMatrix[0].length;
        this.MAX_GEN = MAX_GEN;
        this.rho = rho;
        //初始化信息素矩阵
        this.pheromone = new double[this.cityNum][this.cityNum];
        for (int i = 0; i < this.cityNum; i++) {
            for (int j = 0; j < this.cityNum; j++) {
                this.pheromone[i][j] = 0.1f; //初始化为0.1
            }
        }
        //初始化最优路径长度
        bestObjectValue = Integer.MAX_VALUE;
        //初始化最优序列
        bestSequence = new int[cityNum];
        //随机放置蚂蚁
        this.antArr =new Ant[antNum];
        for (int i = 0; i < antNum; i++) {
            this.antArr[i] = new Ant(distanceMatrix, alpha, beta);
            this.antArr[i].initAntMessage();
        }
    }
    public void solve() {
        long startTime = System.currentTimeMillis();
        //迭代MAX_GEN次
        for (int t = 0; t < this.MAX_GEN; t++) {
            //让所有蚂蚁都从自己的起点出发,完整走一个回路
            for (int i = 0; i < this.antNum; i++) {
                //让第i只蚂蚁走完所有城市,形成一个回路,j从1开始是因为蚂蚁本身已在起点城市
                for (int j = 1; j < this.cityNum; j++) {
                    this.antArr[i].selectNextCity(this.pheromone);
                }
                //把这只蚂蚁起始城市加入序列中
                this.antArr[i].getSequence().add(this.antArr[i].getFirstCity());
                //查看蚂蚁i所走的路径距离是否比当前最优解更好
                if (this.antArr[i].getBestObjectValue() < this.bestObjectValue) {
                    //更新最优解
                    this.bestObjectValue = this.antArr[i].getBestObjectValue();
                    for (int j = 0; j < this.cityNum; j++) {
                        this.bestSequence[j] = this.antArr[i].getSequence().get(j);
                    }
                    System.out.println("----------------------------------------------------------------------------------------------------------------");
                    System.out.println("当前代数:" + t);
                    System.out.println("当前最优解为:" + bestObjectValue);
                    System.out.println("当前计算时间为:" + (System.currentTimeMillis() - startTime) + "ms");
                    System.out.println("----------------------------------------------------------------------------------------------------------------");
                }
                //更新这只蚂蚁的信息数变化矩阵,对称矩阵
                for (int j = 0; j < this.cityNum; j++) {
                    this.antArr[i].getDelta()[this.antArr[i].getSequence().get(j)][this.antArr[i].getSequence().get(j + 1)]
                            = (1.0 / this.antArr[i].getBestObjectValue());
                    this.antArr[i].getDelta()[this.antArr[i].getSequence().get(j + 1)][this.antArr[i].getSequence().get(j)]
                            = (1.0 / this.antArr[i].getBestObjectValue());
                }
            }
            //更新信息素
            this.updatePheromone();
            //将蚂蚁放到不同的位置,重新初始化蚂蚁
            for (int i = 0; i < this.antNum; i++) {
                this.antArr[i].initAntMessage();
            }
        }
        System.out.println("最优解:"+this.bestObjectValue);
        System.out.println("最优序列:"+ Arrays.toString(this.bestSequence));
        System.out.println("计算时间:"+(System.currentTimeMillis()-startTime)+"ms");
    }
    /**
     * 更新信息素
     */
    private void updatePheromone() {
        //信息素挥发
        for (int i = 0; i < this.cityNum; i++) {
            for (int j = 0; j < this.cityNum; j++) {
                this.pheromone[i][j] = this.pheromone[i][j] * (1 - this.rho);
            }
        }
        //信息素更新
        for (int i = 0; i < this.cityNum; i++) {
            for (int j = 0; j < this.cityNum; j++) {
                for (int k = 0; k < this.antNum; k++) {
                    this.pheromone[i][j] += this.antArr[k].getDelta()[i][j];
                }
            }
        }
    }
}


测试

package com.dam.heuristic.aco.test;
import com.dam.heuristic.aco.csdn.Aco;
import com.dam.heuristic.ts.test.TsApi;
import java.io.File;
import java.io.FileInputStream;
public class AcoMainRun {
    public static void main(String[] args) throws Exception {
        声明变量
        //距离矩阵,可以直接获取任意两个编号城市的距离
        double[][] distanceMatrix;
        读取数据
        String data = read(new File("src/main/java/com/data/tsp/att48.txt"), "GBK");
        String[] cityDataArr = data.split("\n");
        //初始化数组
        distanceMatrix = new double[cityDataArr.length][cityDataArr.length];
        for (int i = 0; i < cityDataArr.length; i++) {
            String[] city1Arr = cityDataArr[i].split(" ");
            int cityOne = Integer.valueOf(city1Arr[0]);
            for (int j = 0; j < i; j++) {
                String[] city2Arr = cityDataArr[j].split(" ");
                int cityTwo = Integer.valueOf(city2Arr[0]);
                if (cityOne == cityTwo) {
                    distanceMatrix[cityOne - 1][cityTwo - 1] = 0;
                } else {
                    distanceMatrix[cityOne - 1][cityTwo - 1] = getDistance(Double.valueOf(city1Arr[1]), Double.valueOf(city1Arr[2]), Double.valueOf(city2Arr[1]), Double.valueOf(city2Arr[2]));
                    //对称赋值
                    distanceMatrix[cityTwo - 1][cityOne - 1] = distanceMatrix[cityOne - 1][cityTwo - 1];
                }
            }
        }
     /*   System.out.println("输出距离矩阵-------------------------------------------------------------------");
        for (double[] matrix : distanceMatrix) {
            System.out.println(Arrays.toString(matrix));
        }*/
        AcoApi acoApi = new AcoApi(15,500, 1.0,5.0, 0.5, distanceMatrix);
        acoApi.solve();
    }
    /**
     * 给定两个城市坐标,获取两个城市的直线距离
     *
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @return
     */
    private static double getDistance(double x1, double y1, double x2, double y2) {
        return Math.sqrt((Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2))/10);
    }
    private static String read(File f, String charset) throws Exception {
        FileInputStream fstream = new FileInputStream(f);
        try {
            int fileSize = (int) f.length();
            if (fileSize > 1024 * 512) {
                throw new Exception("File too large to read! size=" + fileSize);
            }
            byte[] buffer = new byte[fileSize];
            fstream.read(buffer);
            return new String(buffer, charset);
        } finally {
            try {
                fstream.close();
            } catch (Exception e) {
            }
        }
    }
}


最优解:11099.299942928516
最优序列:[28, 1, 25, 3, 34, 44, 23, 9, 41, 4, 47, 38, 31, 20, 12, 24, 13, 22, 10, 11, 14, 39, 8, 0, 7, 37, 30, 43, 17, 6, 27, 5, 36, 18, 26, 42, 16, 29, 35, 45, 32, 19, 46, 33, 2, 21, 15, 40]
计算时间:1621ms
目录
相关文章
|
3月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
101 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
2月前
|
Web App开发 测试技术 API
Playwright 测试报告中显示的标签和注释。
Playwright 测试报告中显示的标签和注释。
103 57
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
65 1
|
2月前
|
存储 算法 决策智能
基于免疫算法的TSP问题求解matlab仿真
旅行商问题(TSP)是一个经典的组合优化问题,目标是寻找经过每个城市恰好一次并返回起点的最短回路。本文介绍了一种基于免疫算法(IA)的解决方案,该算法模拟生物免疫系统的运作机制,通过克隆选择、变异和免疫记忆等步骤,有效解决了TSP问题。程序使用MATLAB 2022a版本运行,展示了良好的优化效果。
|
1月前
|
算法 决策智能
基于遗传优化算法的TSP问题求解matlab仿真
本项目使用遗传算法解决旅行商问题(TSP),目标是在四个城市间找到最短路径。算法通过编码、选择、交叉、变异等步骤,在MATLAB2022A上实现路径优化,最终输出最优路径及距离。
|
2月前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
295 2
|
3月前
|
Java 程序员 测试技术
Java|让 JUnit4 测试类自动注入 logger 和被测 Service
本文介绍如何通过自定义 IDEA 的 JUnit4 Test Class 模板,实现生成测试类时自动注入 logger 和被测 Service。
41 5
|
3月前
|
存储 人工智能 Java
将 Spring AI 与 LLM 结合使用以生成 Java 测试
AIDocumentLibraryChat 项目通过 GitHub URL 为指定的 Java 类生成测试代码,支持 granite-code 和 deepseek-coder-v2 模型。项目包括控制器、服务和配置,能处理源代码解析、依赖加载及测试代码生成,旨在评估 LLM 对开发测试的支持能力。
65 1
|
3月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
83 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
3月前
|
算法 决策智能
基于GA-PSO遗传粒子群混合优化算法的TSP问题求解matlab仿真
本文介绍了基于GA-PSO遗传粒子群混合优化算法解决旅行商问题(TSP)的方法。TSP旨在寻找访问一系列城市并返回起点的最短路径,属于NP难问题。文中详细阐述了遗传算法(GA)和粒子群优化算法(PSO)的基本原理及其在TSP中的应用,展示了如何通过编码、选择、交叉、变异及速度和位置更新等操作优化路径。算法在MATLAB2022a上实现,实验结果表明该方法能有效提高求解效率和解的质量。