蚁群算法

蚁群算法(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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值