毕业论文用到了遗传算法。根据的学习心得,用最简洁易懂的方式去描述一下。我做的是单目标最小值优化问题,实现n维的计算。
目录:
一. 遗传算法简介
二. 须知一般术语
三.流程图
四.实例说明
五.程序如下
附完整程序
一.遗传算法简介
解决最佳化的搜索算法,是进化算法的一种。包括遗传、突变、自然选择以及杂交等。遗传算法通常实现方式为一种计算机模拟。对于一个最优化问题,一定数量的候选解(称为个体)的抽象表示(称为染色体)的种群向更好的解进化。一般解用二进制表示。解的维数作为基因数,一组解作为一个染色体。一组染色体表示一个群体。适应度函数作为评价标准,也就是我们所求的目标函数。通过自然选择和突变产生新的生命种群,该种群在算法的下一次迭代中成为当前种群。
二.须知一般术语
基因:染色体的内部表现,也是可行解的个数
染色体:通俗讲就是一组解,也是一个个体
种群:一组染色体,多个个体,就是一个种群,我们从种群中进化出一个最优个体,就是最优解。
适应度:度量某个物种对于生存环境的适应程度,可以理解为就是目标函数
编码:对解的范围进行二进制编排
解码:二进制编码对应的十进制
选择(selection):以一定的概率从种群中选择若干个个体。
交叉(crossover):两个染色体的某一相同位置处切断,相互交换片段,形成两个新的染色体。
变异(mutation):一定的概率变异,产生新的染色体,例如0变为1
三.流程图
四.实例说明
题目很简单,主要看求解过程
步骤:
-
作为0-1规划问题,其解为0或者1,则用一位二进制表示
-
i为30,则随机生成30位二进制,作为一组可行解
-
带入适应度函数即可
-
设置种群数量。一般为300,迭代1000次.
-
此0-1规划,只需初始化个体(编码)即可,因为编码与解码一样,都是0或1
五.程序如下
初始化染色体
class ClsInit {
//初始化一条染色体,可解性的个数
public int[] initSingle(int GENE){
int[] res = new int[GENE];
for(int i = 0; i < GENE; i++){
if(Math.random() < 0.5){
res[i]=0;
}else{
res[i]=1;
}
}
return res;
}
//初始化一组染色体,即二维数组
public int[][] initAll(int GENE,int groupsize){
int[][] iAll = new int[groupsize][GENE];
for(int i = 0; i < groupsize; i++){
iAll[i] = initSingle(GENE);
}
return iAll;
}
}
计算个体的适应度
class ClsFitness {
//计算个体的适应度
public double fitSingle(int[] str,int GENE){
double fitness=0;
for (int i = 0; i < str.length; i++) {
fitness += str[i];
}
return fitness;
}
//计算二维数组的适应度
public double[] fitAll(int str[][],int GENE){
double [] fit = new double[str.length];
for(int i = 0;i < str.length; i++){
fit[i] = fitSingle(str[i],GENE);
}
return fit;
}
//适应度最值的序号
public int mFitNum(double fit[]){
double m = fit[0];
int n = 0;
for(int i = 1;i < fit.length; i++){
if(fit[i] < m){
m = fit[i];
n = i;
}
}
return n;
}
//适应度最值
public double mFitVal(double fit[]){
double m = fit[0];
for(int i = 1;i < fit.length; i++){
if(fit[i] < m){
m = fit[i];
}
}
return m;
}
}
选择
class ClsRWS {
ClsInit init = new ClsInit();
ClsFitness fitness = new ClsFitness();
/* fit[]适应度数组
* group[]群体数组
* GENE基因数,可行解的维数
* */
public int[][] RWS(int group[][], int GENE){
double p[] = new double[group.length]; //染色体概率数组
int[][] newgroup = new int[group.length][GENE];
double F = 0;
double[]fit = fitness.fitAll(group,GENE);//计算适应度数组
//所有适应度的和F
for(int i = 0; i < fit.length; i++){
F = F +fit[i];
}
//初始化p[]
for(int i = 0; i < fit.length; i++){
p[i] = fit[i] / F;
}
//求出适应度最大的个体min,它的序号是min
int min = fitness.mFitNum(fit);
//转动轮盘,适应度大的被选中的概率大
for (int i = 0; i < fit.length; i++){
double r = Math.random();
double q= 0; //累计概率
//适应度最大的个体直接继承
if(i == min){
for (int j = 0; j < GENE; j++)
newgroup[i][j] = group[i][j];
p[i] = 0; //将其概率置0
continue;
}
//遍历轮盘,轮盘指针停在哪个区域
for(int j = 0; j < fit.length; j++){
q += p[j];
if(r <= q){
for (int k = 0; k < GENE; k++) {
newgroup[i][k]=group[j][k];//假如被选中,保留进下一代
p[j] = 0; //将其概率置0
break;
}
}
newgroup[i] = init.initSingle(GENE); //假如没被选中,被外来者取代
}
}
return newgroup;
}
}
交叉
class ClsCross {
ClsFitness fitness = new ClsFitness();
//group群体
//GENE基因数
//mFitNum最大适应度染色体序号
public int[][] cross(int[][] group,int GENE,double crossRate){
int []temp1=new int [GENE];
int []temp2=new int [GENE];
int pos = 0;
double[] fit = fitness.fitAll(group,GENE);
int mFitNum = fitness.mFitNum(fit); //计算适应度最小的染色体序号
int[] min = new int[GENE];
for (int i = 0; i < GENE; i++) {
min[i]=group[mFitNum][i];
}
for(int i = 0; i < group.length; i++){
if(Math.random() < crossRate){
pos = (int)(Math.random()*GENE) + 1;//交叉点
for (int j = 0; j < pos; j++) {
temp1[j]=group[i][j];
temp2[j]=group[(i+1)%group.length][j];
}
for (int j = pos; j < GENE; j++) {
temp1[j]=group[(i+1)%group.length][j];
temp2[j]=group[i][j];
}
for (int j = 0; j < GENE; j++) {
group[i][j]=temp1[j];
group[(i+1) % group.length][j]=temp2[j];
}
}
}
for (int i = 0; i < GENE; i++) {
group[0][i]=min[i];
}
return group;
}
}
变异
class ClsMutation {
ClsFitness fitness = new ClsFitness();
public int[][] mutation(int[][] group,int GENE,double MP){
double[] fit = fitness.fitAll(group,GENE);
int mFitNum = fitness.mFitNum(fit); //计算适应度最大的染色体序号
int []min=new int [GENE];
for(int i=0;i<GENE;i++)
{
min[i]=group[mFitNum][i];
}
for(int i = 0; i < group.length * MP; i++){
int n = (int) (Math.random() * GENE * group.length ); //从[0,GENE * group.length)区间取随机数
int chrNum = (int) (n / GENE); //取得的染色体数组下标
int gNum = (int)(n % GENE); //取得的基因下标
if(group[chrNum][gNum] == 0 ){
group[chrNum][gNum]=1;
}else{
group[chrNum][gNum]=0;
}
}
for (int i = 0; i < GENE; i++) {
group[0][i]=min[i];
}
return group;
}
}
调用功能类
class GA {
public static final int groupsize = 100; //染色体数或者群体中个体数
public static final double MP = 0.06; //变异概率
public static final double CP = 0.83; //交叉概率
public static final int ITERA = 300; //迭代次数
public static final int GENE =30;//基因数或者问题的维数
//输出原群体和适应度,测试用
public void outAll(int[][] group){
ClsFitness fitness = new ClsFitness();
ClsInit init = new ClsInit();
for(int i=0;i<group.length;i++){
group[i]=init.initSingle(GENE);
}
double fit[] = fitness.fitAll(group,GENE);
System.out.println("原种群");
for (int i = 0; i < group.length; i++) {
for (int j = 0; j < GENE; j++) {
System.out.print(group[i][j]);
}
System.out.println();
}
System.out.println("原群体适应度");
for (int i = 0; i < group.length; i++) {
System.out.println(fit[i]);
}
}
double min;
//输出适应度最小值,返回最优个体
public int outmin(String string,int[][] group){
ClsFitness fitness = new ClsFitness();
double[] fit = fitness.fitAll(group,GENE);
min = fitness.mFitVal(fit);
int k = fitness.mFitNum(fit);
System.out.println(string +min);
System.out.print("可行解=");
for (int i = 0; i < GENE; i++) {
System.out.print(group[k][i]);
}
System.out.println();
return fitness.mFitNum(fit);
}
public static void main(String[] args) {
ClsInit init = new ClsInit();
ClsRWS rws = new ClsRWS();
ClsCross cross = new ClsCross();
ClsMutation mutation = new ClsMutation();
GA ga = new GA();
int[][] group = init.initAll(ga.GENE,groupsize); //初始化
ga.outAll(group);
for(int i = 0; i < ITERA; i++){
System.out.println("第"+ i+ "代");
group= rws.RWS(group, ga.GENE); //选择
ga.outmin("选择适应度=",group);
group = cross.cross(group,ga.GENE,CP); //交叉
ga.outmin("交叉适应度=",group);
group = mutation.mutation(group, ga.GENE, MP); //变异
ga.outmin("变异适应度=",group);
System.out.println("");
}
}
}