文章目录

  • 1.蚁群算法概要
    • 什么是蚁群算法
    • 蚁群算法的数学公式
      • 蚂蚁从i城市到j城市的概率公式
      • 信息素的释放公式
      • 信息素的挥发公式
    • 蚁群算法的框架
  • 2.TSP描述(旅行商问题)
  • 3.JAVA源代码实现
    • 参数设置
    • 几个重要的函数
    • JAVA具体代码
    • 运行结果及分析

1.蚁群算法概要

什么是蚁群算法

  • 蚁群算法是一种用于寻找优化路径概率算法
  • 蚁群算法模拟蚁群可以在不同的环境中寻找到最优路径
  • 进一步研究表明,蚂蚁在路径上会释放一种称之为信息素的物质,假如一只蚂蚁寻找到食物(较优路径),其在路径上的信息素(概率)就会引导同伴蚂蚁走相同的路径,蚂蚁增多的同时释放更浓的信息素(正反馈机制)。假设信息素引导的路径不是食物(不是较优路径),则这条路径的信息素就只有相对较少的值(与有食物的路径相比较小)。
  • 信息素会随着时间流失而挥发(较差的路径被选择的概率变小
  • 由以上的描述可知,算法应模拟蚁群,令不同的蚂蚁去寻食(找更短的路径),若寻找到食物(较优路径),通过释放信息素(改变路径被选中的概率),引导其余蚂蚁选择更优的路径。通过不断寻找(在较优路径的基础上不断地迭代寻找更优的路径),最终找到一个比较短的距离(最终的路径)。
  • 在具体实现采用的是TSP问题,蚁群算法还可用于其他问题求解,在此不多做说明。

蚁群算法的数学公式

蚂蚁从i城市到j城市的概率公式

pi,jkp^{k}_{i,j}pi,jk​ = [τi,j(t)]α[ηi,j(t)]β∑j∈allow(k)[τi,j(t)]α[ηi,j(t)]βj∈allow(k)\frac{[\tau^{}_{i,j}(t)]^{\alpha}[\eta^{}_{i,j}(t)]^{\beta}}{\sum_{j\in allow(k)}[\tau^{}_{i,j}(t)]^{\alpha}[\eta^{}_{i,j}(t)]^{\beta}}{j\in allow(k)}∑j∈allow(k)​[τi,j​(t)]α[ηi,j​(t)]β[τi,j​(t)]α[ηi,j​(t)]β​j∈allow(k)

  • 其中K是第K只蚂蚁,i,j是两座城市之间的边,pi,jkp^{k}_{i,j}pi,jk​意为第K只蚂蚁在I城市选择去J城市的可能性,且J城市一定为K蚂蚁从未到达的城市。
  • [τi,j(t)]α{[\tau^{}_{i,j}(t)]^{\alpha}}[τi,j​(t)]α:[τi,j(t)]{[\tau^{}_{i,j}(t)]}[τi,j​(t)]为路径上的信息素浓度,α{\alpha}α代表信息素重要程度。
  • [ηi,j(t)]β{[\eta^{}_{i,j}(t)]^{\beta}}[ηi,j​(t)]β:[ηi,j(t)]{[\eta^{}_{i,j}(t)]}[ηi,j​(t)]是i到j城市的距离的倒数,β{{\beta}}β代表路径距离重要程度。
  • allow(k)allow(k)allow(k)是存放当前没有走过城市的集合。
  • 当一个城市不在allow(k)中时,我们将其概率P设置为0。

信息素的释放公式

Δτi,j(t){\Delta\tau^{}_{i,j}(t)}Δτi,j​(t) =QLk= \frac{Q}{L^{}_{k}}=Lk​Q​

  • 这里采用蚂蚁每走完一周才释放信息素,具体代码实现时是让所有蚂蚁走完一圈才进行信息素的释放,以避免前面的蚂蚁直接影响到后面的蚂蚁。
  • Q{Q}Q是一个常量(我设置为1),Lk{L^{}_{k}}Lk​为第KKK只蚂蚁经过的路径长度

信息素的挥发公式

τi,j(t)=ρ∗τi,j(t){\tau^{}_{i,j}(t)} = \rho*\tau^{}_{i,j}(t)τi,j​(t)=ρ∗τi,j​(t)(ρ\rhoρ为设置的挥发系数)

蚁群算法的框架

  • 初始化参数:对初始的信息素浓度进行定义,定义如α之类的常量,设置蚂蚁的个数,以及循环(iter)的次数
  • 进行循环:令蚁群进行觅食,每进行一次迭代,更新信息素,并释放信息素,若本次产生较前次更优的路径,则记录更优解。
  • 得到最终结果,并输出路径

2.TSP描述(旅行商问题)

旅行商问题是给定一组城市,环绕此城市一圈,经过每一个城市,找到路径的最短距离
此类问题在路径较小时可使用暴力解,但当城市数量较多时(本次采用ATT48的数据,共48个城市,解空间大小为48的阶乘),暴力解及传统的解法无法在较短的时间内计算出路径(普通计算机得连续工作几万年,反正那时谁还记得谁,另一句,几万年是我瞎BB的,就是时间很长就行了,不过也差不多是这个数),这显然不是我们想要的,而贪婪算法能在有限时间内求得一个较好的答案,但仍然离最优解相差甚远(误差值达到13%)。
蚁群算法本质上是一种启发式的优化算法,有分布计算、信息正反馈和启发式搜索的特征,能尽量避开局部最优,达到一个较好的解(根据我的实测,依然不如遗传算法,有时间再写个遗传算法)。

3.JAVA源代码实现

参数设置

参数设置对于蚁群算法的性能有着极其重要的影响,不同的参数设置会导致结果的较大差异,一般情况下将不同常量设置如下可取得较好的结果:
α{\alpha}α(信息素浓度的影响因子):设置为1;
β{\beta}β(城市间距离的影响因子):设置为5;
ρ{\rho}ρ(挥发因子):设置为0.9。

几个重要的函数

通过这几天写各种算法,我深刻体会到将不同的计算包装成不同的函数,可以提高很大的效率,以下介绍几个具体的函数。

  • init_p(int [][]distance):对路径开始的信息素浓度进行初始化,初始值我将他设定为路径与每个结点路径和的倒数;
  • roulette(double [][]p,int current,int []allow,int[][]distance):轮盘赌算法,用于结点概率的选择;
  • not_exit(int current,int []allow):判断当前选择的城市是否存在于ALLOW子集,这一点至关重要;
  • init(String filename) :算出距离矩阵,返回二维数组Distance.
  • 这里额外提一下,什么是伪欧式距离,第一次接触这个我也比较懵逼,他对原距离进行了除以根号十的处理,现在才明白这个距离是官方文档(ATT48数据集)定义的距离公式,他综合考虑了以下两点因素,1.地球是圆的(欧式距离计算的是平面距离)2.大数据不方便处理,所以采用了这个公式。
    JAVA代码公式体现在这:double rij = Math .sqrt(((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])) /10.0);

JAVA具体代码

蚁群算法类(main方法所在类):

package aca;import java.awt.Image;
import java.io.IOException;import javax.xml.parsers.DocumentBuilder;
import javax.xml.stream.events.StartDocument;public class ACA {int ant_num=50;/*蚂蚁数量*/int alpha =1;//α因子int beta = 5;//β因子static double rho =0.9;//信息素挥发因子int Q=1;//常数public double[][] init_p(int [][]distance) {//对信息素概率的初始量进行更新,初始概率为每个点到其余点的路径和分之路径double p[][] = new double[48][48] ;//用于保存信息素概率for(int i=0;i<48;i++) {double sum = for_each_sum(distance, i);//对每个结点进行和的计算for(int j=0;j<48;j++) {p[i][j]=(distance[i][j]*1.0)/sum;}}for(int i=0;i<48;i++) {p[i][i]=0;}return p;}public int[] start(double [][]p,int[][]distance) {int length=0;int []allow = new int[48];//保存走过的距离for(int m=0;m<48;m++) {allow[m]=100;//防止NOT_EXIT失效}int i=0;int temple = (int) (Math.random()*48);allow[i]=temple;i++;int current =temple;while(i<48) {int tmp[]= new int[48];for(int m=0;m<48;m++) {tmp[m]=allow[m];//System.out.println(m);}int next = roulette(p, current, tmp,distance);allow[i]=next;current = next;i++;}return allow;}public int roulette(double [][]p,int current,int []allow,int[][]distance) {//轮盘赌,current为当前城市标号double sum =0;int temple = 0;double a = sum_single_possible(distance, p, current,allow);while(sum<0.3) {temple = (int) (Math.random()*48);if(not_exit(temple, allow)) {//假如该数不在数组里,则令概率增加double n =1.0/distance[current][temple];n = Math.pow(n, beta);double t = p[current][temple];t = Math.pow(t, alpha);sum =sum + n*t*1.0/a;}}return temple;}public double sum_single_possible(int [][]distance,double[][]p,int current,int[]allow) {//根据公式计算概率double sum=0;for(int i=0;i<48;i++) {if(not_exit(i, allow)) {double a =1.0/distance[current][i];a= Math.pow(a,beta);double b =p[current][i];b= Math.pow(b, alpha);sum = sum+a*b;}}return sum;}public boolean not_exit(int current,int []allow) {//判断当前数是否已经存在于走过的路径中boolean flag = true;for(int i=0;i<allow.length;i++) {if(current == allow[i])return false;}return true;}public double for_each_sum(int [][]distance,int i) {//辅助函数,帮助计算每行总值,I表达第I个结点double sum=0;for(int j = 0;j<48;j++){sum = sum + distance[i][j];}return sum;}public int sum_path_length(int [][]distance,int [][]path,int current) {//辅助函数,计算蚂蚁走过路径总值int sum=0;for(int i=0;i<47;i++) {sum = sum + distance[path[current][i]][path[current][i+1]];}sum = sum + distance[path[current][47]][path[current][0]];return sum;}public static void main(String []args) throws IOException {bbtsp a = new bbtsp();int [][]distance = a.init("c://data.txt");ACA b =new ACA();double p[][] =b.init_p(distance);//产生概率int iter = 200;int i=1;int [][]path = new int[50][48];int min = Integer.MAX_VALUE;//保存最佳路径int best_path[]=new int[48];//保存最佳路径while(i<100) {for(int j=0;j<50;j++)//令每个蚂蚁去寻找路径{int[]allow = b.start(p,distance);//产生一个初始路径for(int m=0;m<48;m++) {//将此值保存在路径数组中用于处理path[j][m]=allow[m];}}//释放信息素for(int j=0;j<50;j++) {int current = j;//选中第J条路径int L = b.sum_path_length(distance, path, current);//计算每条路径长度if(L<min) {min = L;//更新最优解for(int k=0;k<48;k++)//保存最短路径{best_path[k]=path[current][k];}}for(int k=0;k<47;k++) {//释放信息素的值p[path[j][k]][path[j][k+1]]=p[path[j][k]][path[j][k+1]]+1.0/L;}p[path[j][47]][path[j][0]]=p[path[j][47]][path[j][0]]+1.0/L;}//挥发信息素for(int j=0;j<48;j++) {for(int k=0;k<48;k++) {p[j][k]=rho*p[j][k];}}i++;}System.out.println("最终路径:");for(int k=0;k<48;k++) {System.out.print(best_path[k]+1+" ");}System.out.print("最小距离:");System.out.println(min);/*int[]allow = b.start(p,distance); for(int i=0;i<48;i++){for(int j=0;j<48;j++) {if(allow[i]>allow[j]) {int temp=allow[i];allow[i]=allow[j];allow[j]=temp;}}}for(int j = 0;j<48;j++){System.out.println(allow[j]);}*/}}

返回距离矩阵的类:

package aca;import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;class bbtsp{int [][]distance;//距离矩阵int citynum = 48;public bbtsp(int [][]dis) {this.distance = dis;}public bbtsp() {}public int[][] init(String filename) throws IOException {// 读取数据int[] x;int[] y;String strbuff;BufferedReader data = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));distance= new int[citynum][citynum];x = new int[citynum];y = new int[citynum];for (int i = 0; i < citynum; i++) {// 读取一行数据,数据格式1 6734 1453strbuff = data.readLine();// 字符分割String[] strcol = strbuff.split(" ");x[i] = Integer.valueOf(strcol[1]);// x坐标y[i] = Integer.valueOf(strcol[2]);// y坐标}data.close();// 计算距离矩阵// ,针对具体问题,距离计算方法也不一样,此处用的是att48作为案例,它有48个城市,距离计算方法为伪欧氏距离,最优值为10628for (int i = 0; i < citynum - 1; i++) {distance[i][i] = -1; // 对角线为0for (int j = i + 1; j < citynum; j++) {double rij = Math.sqrt(((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j])* (y[i] - y[j])) /10.0);// 四舍五入,取整int tij = (int) Math.round(rij);if (tij < rij) {distance[i][j] = tij + 1;distance[j][i] = distance[i][j];} else {distance[i][j] = tij;distance[j][i] = distance[i][j];}}}distance[citynum - 1][citynum - 1] = -1;return distance;}}

运行结果及分析

这是我得到的11011的数据:11011
5 48 42 10 24 45 35 4 26 2 29 41 16 22 3 34
14 25 13 23 11 12 15 40 9 1 8 38 31 44 18 7
28 36 6 37 19 27 43 17 30 46 33 20 47 21
32 39
最优解为10628,误差值为0.03%,显然这个误差值是比较大的,但相对于贪婪算法13%的误差,这个值还能接受

蚁群算法(ACA)详细介绍(JAVA实现及代码详解)相关推荐

  1. 【 无错版】基于蚁群算法的机器人路径规划matlab程序代码实现

    文章目录 1. 按 2. 介绍 3. matlab实现 3.1. 代码 3.2. 效果 1. 按 网上有发的这个算法的错误版的,不知道发的意义何在,是在误人子弟吗???在此对其行为表示强烈的谴责. 错 ...

  2. 3.蚁群算法求解格栅地图路径规划matlab代码

    往期: 1.Dijkstra算法求解格栅地图路径matlab代码_墨叔叔的博客-CSDN博客 2.A*搜索算法原理及matlab代码_墨叔叔的博客-CSDN博客 一.蚁群算法原理 原理:蚁群系统(An ...

  3. Qt开发技术:QCharts(三)QCharts样条曲线图介绍、Demo以及代码详解

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108022984 各位读者,知识无穷而人力有穷 ...

  4. Qt开发技术:Q3D图表开发笔记(二):Q3DBar三维柱状图介绍、Demo以及代码详解

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/130150728 各位读者,知识无穷而人力有穷,要么改需 ...

  5. Qt开发技术:Q3D图表开发笔记(三):Q3DSurface三维曲面图介绍、Demo以及代码详解

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/130264470 各位读者,知识无穷而人力有穷,要么改需 ...

  6. 【运筹优化】ACO蚁群算法求解TSP问题(Java实现)

    文章目录 代码 Ant蚂蚁类 AntColonyOptimization_TSP蚁群算法类 运行结果 代码 Ant蚂蚁类 import lombok.Data;import java.util.Arr ...

  7. 【OpenCV/C++】KNN算法识别数字的实现原理与代码详解

    KNN算法识别数字 一.KNN原理 1.1 KNN原理介绍 1.2 KNN的关键参数 二.KNN算法识别手写数字 2.1 训练过程代码详解 2.2 预测分类的实现过程 三.KNN算法识别印刷数字 2. ...

  8. qchart折现图_Qt开发技术:QCharts(二)QCharts折线图介绍、Demo以及代码详解

    若该文为原创文章,未经允许不得转载 各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究 敬请期待- 红胖子,来也! 介绍了整体框架,开始动手码代码,按照顺序,从折线图开始. QCh ...

  9. mysql索引详细介绍简书_MySql索引详解

    image 常见索引类型(实现层面) 索引种类(应用层面) 聚簇索引与非聚簇索引 覆盖索引 最佳索引使用策略 1.常见索引类型(实现层面) 首先不谈Mysql怎么实现索引的,先马后炮一下,如果让我们来 ...

最新文章

  1. 16-flutter-Swiper 插件的使用
  2. OpenGL中摄像机矩阵的计算原理
  3. Transformer落地:使用话语重写器改进多轮人机对话
  4. html文件语言表示网页标题,HTML网页基本结构(HTML文件、编程语言)——十一号笔记...
  5. oracle 实现ID自增
  6. HDU-1712-ACboy needs your help
  7. 使用DBUnit做单元测试
  8. Mysql安装的目录结构详解
  9. 性能测试oracle瓶颈定位,性能测试难点之瓶颈分析
  10. 火车票价还不够高(按照《经济学通识》手敲的(非原创))
  11. xshell .swp文件
  12. 常见DB2锁等待解决流程
  13. 特殊字符编码格式数据库不支持
  14. NLP判断语言情绪_健玲:NLP的基本精神12条前提假设,打破你的思维墙
  15. spark 相关性分析_基本统计 - correlations(相关性系数) - 《spark机器学习算法研究和源码分析》 - 书栈网 · BookStack...
  16. 4-14 递归求阶乘和 (10分)
  17. plt.scatter散点图
  18. 我的世界服务器权限组权限修改器,permissionsEX v1.19.5 —— 超级权限插件
  19. POST和GET有什么区别?
  20. Windows补丁更新Tips

热门文章

  1. TurboMail邮件系统灾害后的数据快速恢复
  2. flink tableapi从DataStream创建表
  3. SQL Server以windows验证登录之后,修改sa密码,不能用sa登录的解决方案
  4. 强化绩效计算机自动考评,市财政局:建立完善绩效考核机制 不断提高公务员管理水平...
  5. 域名哪家便宜?怎么买便宜域名?
  6. 随机变量(Random Varibales)
  7. #后疫情时代的新思考#越是疫情当前,企业在营销层面越应该设定底线丨数据猿公益策划...
  8. GiHub 干货(主要还是看原文链接)
  9. 非常完善的Log4net详细说明
  10. 佰钧成的危城抗“疫”日记