遗传算法(Genetic Algorithm,GA)最早是由美国的John holland于20世纪70年代提出,该算法是根据大自然中生物体进化规律而设计提出的。是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。
1、问题描述:
图1所示为一个最短路径问题,每条边代表一条可以通行的弧,边上的数值表示这条弧的长度,多条弧相互连接形成路径,目标是寻找一条从节点0出发到节点5的最短路径。
2、编码
从表现型到基因型的映射称为编码。图1中每条路径的每个节点对应一个基因,通过对节点的有序组合可以将每条路径映射为一个向量。每个向量长度为6,起始和结束位置的数值分别为0和5,代表从节点0出发,到节点5终止,图1中节点间边的长度代表节点间的距离,若两节点间无边相连,则这两个节点间的距离为一个极大的数M。由于向量长度固定为6,而解中可能并不包含所有的节点,个体中可能会存在多个相邻且重复出现的节点,因此设置节点到其本身的距离为0。
3、个体类
每个个体包含路径Path和适应度length(即路径长度)两个属性,每个个体路径属性中的起点为0,结束点为5,其余位置数值随机生成(0-5范围内的整数),向量长度固定为6。个体类中定义的compareTo方法是为了用于在选择算子中采用迭代器进行个体的删除。
public class Individual implements Comparable<Individual>{
int[] Path = new int[6]; //存储路径
int length; //表示适应度
public int[] getPath() {
return Path;
}
public void setPath(int[] path) {
Path = path;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public int compareTo(Individual o) {
if(this.getLength() > o.getLength())
{
return -1;
}
else if(this.getLength()<o.getLength())
{
return 1;
}
else
{
return 0;
}
}
}
4、遗传算法解决最短路径问题主方法
主方法包括(1)数据的初始化(2)定义初始种群(3)循环依次调用选择、交叉和变异算子(4)输出迭代后的结果。以邻接矩阵的形式表达图1中各节点间的距离, 建立一个集合表示种群,随机产生10个个体并添加到初始种群完成种群的初始化,设置迭代次数并依次调用三个算子更新种群,最终输出结果。详细代码如下:
static int[][] matrix = new int[6][6];
final static int M = 10000;
static Random rand = new Random();
public static void main(String[] args) {
//邻接矩阵
matrix[0] = new int[]{0, 6, 3, M, M, M};/*1*/
matrix[1] = new int[]{6, 0, 2, 5, M, M};/*2*/
matrix[2] = new int[]{3, 2, 0, 3, 4, M};/*3*/
matrix[3] = new int[]{M, 5, 3, 0, 2, 3};/*4*/
matrix[4] = new int[]{M, M, 4, 2, 0, 5};/*5*/
matrix[5] = new int[]{M, M, M, 3, 5, 0};/*6*/
//定义初始种群
Math.random();
List<Individual> Population = new ArrayList<>();
for (int i = 0; i < 10; i++) {
//随机生成十个个体添加到初始种群列表
Individual Popu = new Individual();
Popu.Path[0] = 0;
Popu.Path[1] = rand.nextInt(5);
Popu.Path[2] = rand.nextInt(5);
Popu.Path[3] = rand.nextInt(5);
Popu.Path[4] = rand.nextInt(5);
Popu.Path[5] = 5;
Popu.length = M;
Population.add(Popu);
}
for(int i = 0; i<2000; i++){
System.out.println("第"+(i+1)+"次迭代开始!");
//初始种群中选择出5个较优的个体
List<Individual> NewSelPopu = Selection(Population);
//交叉
List<Individual> NewCroPopu = Crossover(NewSelPopu);
//变异