蚁群算法(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();//48
System.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