蚁群算法

来源:互联网 发布:阅读软件哪个好 编辑:程序博客网 时间:2024/04/30 00:59

蚁群算法(ant colony optimization, ACO),又称蚂蚁算法,是一种用来在图中寻找优化路径的机率型算法。它由Marco Dorigo于1992年在他的博士论文中提出,其灵感来源于蚂蚁在寻找食物过程中发现路径的行为。蚁群算法是一种模拟进化算法,初步的研究表明该算法具有许多优良的性质。针对PID控制器参数优化设计问题,将蚁群算法设计的结果与遗传算法设计的结果进行了比较,数值仿真结果表明,蚁群算法具有一种新的模拟进化优化方法的有效性和应用价值。

如果我们要为蚂蚁设计一个人工智能的程序,那么这个程序要多么复杂呢?首先,你要让蚂蚁能够避开障碍物,就必须根据适当的地形给它编进指令让他们能够巧妙的避开障碍物,其次,要让蚂蚁找到食物,就需要让他们遍历空间上的所有点;再次,如果要让蚂蚁找到最短的路径,那么需要计算所有可能的路径并且比较它们的大小,而且更重要的是,你要小心翼翼地编程,因为程序的错误也许会让你前功尽弃。这是多么不可思议的程序!太复杂了,恐怕没人能够完成这样繁琐冗余的程序。
然而,事实并没有你想得那么复杂,上面这个程序每个蚂蚁的核心程序编码不过100多行!为什么这么简单的程序会让蚂蚁干这样复杂的事情?答案是:简单规则的涌现。事实上,每只蚂蚁并不是像我们想象的需要知道整个世界的信息,他们其实只关心很小范围内的眼前信息,而且根据这些局部信息利用几条简单的规则进行决策,这样,在蚁群这个集体里,复杂性的行为就会凸现出来。这就是人工生命、复杂性科学解释的规律!那么,这些简单规则是什么呢?


1、范围
蚂蚁观察到的范围是一个方格世界,蚂蚁有一个参数为速度半径(一般是3),那么它能观察到的范围就是3*3个方格世界,并且能移动的距离也在这个范围之内。
2、环境
蚂蚁所在的环境是一个虚拟的世界,其中有障碍物,有别的蚂蚁,还有信息素,信息素有两种,一种是找到食物的蚂蚁洒下的食物信息素,一种是找到窝的蚂蚁洒下的窝的信息素。每个蚂蚁都仅仅能感知它范围内的环境信息。环境以一定的速率让信息素消失。
3、觅食规则
在每只蚂蚁能感知的范围内寻找是否有食物,如果有就直接过去。否则看是否有信息素,并且比较在能感知的范围内哪一点的信息素最多,这样,它就朝信息素多的地方走,并且每只蚂蚁都会以小概率犯错误,从而并不是往信息素最多的点移动。蚂蚁找窝的规则和上面一样,只不过它对窝的信息素做出反应,而对食物信息素没反应。
4、移动规则
每只蚂蚁都朝向信息素最多的方向移,并且,当周围没有信息素指引的时候,蚂蚁会按照自己原来运动的方向惯性的运动下去,并且,在运动的方向有一个随机的小的扰动。为了防止蚂蚁原地转圈,它会记住刚才走过了哪些点,如果发现要走的下一点已经在之前走过了,它就会尽量避开。
5、避障规则
如果蚂蚁要移动的方向有障碍物挡住,它会随机的选择另一个方向,并且有信息素指引的话,它会按照觅食的规则行为。
6、信息素规则
每只蚂蚁在刚找到食物或者窝的时候撒发的信息素最多,并随着它走远的距离,播撒的信息素越来越少。
根据这几条规则,蚂蚁之间并没有直接的关系,但是每只蚂蚁都和环境发生交互,而通过信息素这个纽带,实际上把各个蚂蚁之间关联起来了。比如,当一只蚂蚁找到了食物,它并没有直接告诉其它蚂蚁这儿有食物,而是向环境播撒信息素,当其它的蚂蚁经过它附近的时候,就会感觉到信息素的存在,进而根据信息素的指引找到了食物。

package com.heng;import java.io.FileNotFoundException;import java.io.IOException;import java.util.logging.Level;import java.util.logging.Logger;public class Main {public static void main(String[] args) {ACO aco;aco = new ACO();try {aco.init("MyFile//eil51.tsp", 50);long start = System.currentTimeMillis();aco.run(2000);aco.ReportResult();long end = System.currentTimeMillis();System.out.println("耗时:"+(end-start));} catch (FileNotFoundException ex) {Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);} catch (IOException ex) {Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);}}}

package com.heng;import java.io.*;  /**  *蚁群优化算法,用来求解TSP问题   */  public class ACO {// 定义蚂蚁群Ant[] ants;int antcount;// 蚂蚁的数量int[][] distance;// 表示城市间距离double[][] tao;// 信息素矩阵int citycount;// 城市数量int[] besttour;// 求解的最佳路径int bestlength;// 求的最优解的长度/** * 初始化函数 * @param filename  tsp数据文件 * @param antnum  系统用到蚂蚁的数量 * @throws 如果文件不存在则抛出异常 */public void init(String filename, int antnum) throws FileNotFoundException,IOException {antcount = antnum;//系统用到的蚂蚁数目ants = new Ant[antcount];// 读取数据int[] x;int[] y;String strbuff;BufferedReader tspdata = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));strbuff = tspdata.readLine();//48System.out.println("strbuff = "+strbuff);citycount = Integer.valueOf(strbuff);distance = new int[citycount][citycount];x = new int[citycount];y = new int[citycount];for (int citys = 0; citys < citycount; citys++) {strbuff = tspdata.readLine();String[] strcol = strbuff.split(" ");x[citys] = Integer.valueOf(strcol[1]);y[citys] = Integer.valueOf(strcol[2]);}// 计算距离矩阵for (int city1 = 0; city1 < citycount - 1; city1++) {distance[city1][city1] = 0;for (int city2 = city1 + 1; city2 < citycount; city2++) {distance[city1][city2] = (int) (Math.sqrt((x[city1] - x[city2])* (x[city1] - x[city2]) + (y[city1] - y[city2])* (y[city1] - y[city2])) + 0.5);distance[city2][city1] = distance[city1][city2];}}distance[citycount - 1][citycount - 1] = 0;// 初始化信息素矩阵tao = new double[citycount][citycount];for (int i = 0; i < citycount; i++) {for (int j = 0; j < citycount; j++) {tao[i][j] = 0.1;}}bestlength = Integer.MAX_VALUE;besttour = new int[citycount + 1];// 随机放置蚂蚁for (int i = 0; i < antcount; i++) {ants[i] = new Ant();ants[i].RandomSelectCity(citycount);}tspdata.close();}/** * ACO的运行过程 * @param maxgen  ACO的最多循环次数 */public void run(int maxgen) {for (int runtimes = 0; runtimes < maxgen; runtimes++) {// 每一只蚂蚁移动的过程for (int i = 0; i < antcount; i++) {for (int j = 1; j < citycount; j++) {ants[i].SelectNextCity(j, tao, distance);}// 计算蚂蚁获得的路径长度ants[i].CalTourLength(distance);if (ants[i].tourlength < bestlength) {// 保留最优路径bestlength = ants[i].tourlength;System.out.println("第" + runtimes + "代,发现新的解" + bestlength);for (int j = 0; j < citycount + 1; j++)besttour[j] = ants[i].tour[j];}}// 更新信息素矩阵UpdateTao();// 重新随机设置蚂蚁for (int i = 0; i < antcount; i++) {ants[i].RandomSelectCity(citycount);}}}/** * 更新信息素矩阵 */private void UpdateTao() {double rou = 0.5;// 信息素挥发for (int i = 0; i < citycount; i++)for (int j = 0; j < citycount; j++)tao[i][j] = tao[i][j] * (1 - rou);// 信息素更新for (int i = 0; i < antcount; i++) {for (int j = 0; j < citycount; j++) {tao[ants[i].tour[j]][ants[i].tour[j + 1]] += 1.0 / ants[i].tourlength;}}}/** * 输出程序运行结果 */public void ReportResult() {System.out.println("最优路径长度是" + bestlength);}}

package com.heng;import java.util.Random;/** * 蚂蚁类 */public class Ant {/** * 蚂蚁获得的路径 */public int[] tour;// unvisitedcity 取值是0或1,// 1表示没有访问过,0表示访问过int[] unvisitedcity;/** * 蚂蚁获得的路径长度 */public int tourlength;int citys;/** * 随机分配蚂蚁到某个城市中 同时完成蚂蚁包含字段的初始化工作 * @param citycount   总的城市数量 */public void RandomSelectCity(int citycount) {citys = citycount;unvisitedcity = new int[citycount];tour = new int[citycount + 1];tourlength = 0;for (int i = 0; i < citycount; i++) {tour[i] = -1;unvisitedcity[i] = 1;}long r1 = System.currentTimeMillis();Random rnd = new Random(r1);int firstcity = rnd.nextInt(citycount);unvisitedcity[firstcity] = 0;tour[0] = firstcity;}/** * 选择下一个城市 * @param index    需要选择第index个城市了 * @param tao      全局的信息素信息 * @param distance 全局的距离矩阵信息 */public void SelectNextCity(int index, double[][] tao, int[][] distance) {double[] p;p = new double[citys];double alpha = 1.0;double beta = 2.0;double sum = 0;int currentcity = tour[index - 1];// 计算公式中的分母部分for (int i = 0; i < citys; i++) {if (unvisitedcity[i] == 1)sum += (Math.pow(tao[currentcity][i], alpha) * Math.pow(1.0 / distance[currentcity][i], beta));}// 计算每个城市被选中的概率for (int i = 0; i < citys; i++) {if (unvisitedcity[i] == 0)p[i] = 0.0;else {p[i] = (Math.pow(tao[currentcity][i], alpha) * Math.pow(1.0 / distance[currentcity][i], beta)) / sum;}}long r1 = System.currentTimeMillis();Random rnd = new Random(r1);double selectp = rnd.nextDouble();// 轮盘赌选择一个城市;double sumselect = 0;int selectcity = -1;for (int i = 0; i < citys; i++) {sumselect += p[i];if (sumselect >= selectp) {selectcity = i;break;}}if (selectcity == -1)System.out.println();tour[index] = selectcity;unvisitedcity[selectcity] = 0;}/** * 计算蚂蚁获得的路径的长度 * @param distance  全局的距离矩阵信息 */public void CalTourLength(int[][] distance) {tourlength = 0;tour[citys] = tour[0];for (int i = 0; i < citys; i++) {tourlength += distance[tour[i]][tour[i + 1]];}}}


案例代码下载:http://download.csdn.net/detail/u013043346/9327251


0 0
原创粉丝点击