第五篇为《遗传算法的基础知识与编程》
借鉴自然进化的理念,优化问题的过程可以看成类似于生物进化的过程,通过模拟自然界的生物进化,遗传算法被提出用于解决优化问题。
遗传算法吸收了生命科学与工程科学的重要理论成果,用于解决复杂优化问题。
自然进化过程如下图1所示,其主要包括自然选择,交配、变异以及淘汰了这些过程,遗传算法结合自然进化的方式的方式来解决优化问题。
图1 自然进化过程
在生物的进化与遗传过程中有一个重要的携带信息的结构,即染色体。染色体是遗传信息基因的载体,基因在染色体上按照一定的次序组合。
在遗传算法中,问题的每个有效解也被称为一个“染色体”,染色体的具体形式是一个使用特定编码方式生成的编码串。编码串中的每一个编码单元称为“基因”。
在遗传算法中海油以下基本概念:
(1)适应值:适应值用于区分染色体的优劣,适应值越大的染色体越优秀。
(2)评估函数:用来计算并确定染色体对应的适应值
(3)选择算子:按照一定的规则对群体的染色体进行选择,得到父代种群。越优秀的染色体被选中的次数越多。
(4)交配算子:作用于没两个成功交配的染色体,染色体交换各自的部分基因,产生两个子染色体。子染色体取代父染色体进入新种群,而没有交配的染色体则直接进入新种群。
(5)变异算子:使新种群进行小概率的变异。
1、染色体编码
在使用遗传算法的时候,首先需要把要解决的问题的解表示出来,即染色体的编码方式。只有先确定了编码方式,才能进行接下类的交配变异等操作。
目前常用的比较简单的编码方式有:
(1)二进制编码方法:编码的染色体是一个二进制符号序列,在下面的程序编程中使用的编码方法就是二进制编码方法。在二进制编码方法中,染色体上的每个基因智能取0和1,就是对应着下面0-1背包的0和1.
(2)浮点数编码方式:浮点数编码方法中,染色体的长度等于问题定义的解的变量个数,染色体的每一个基因等于解的每一维变量。
2、群体初始化
遗传算法在开始进化迭代之前需要初始化进化的群体,一般采用产生随机数的方法进行群体的初始化。比如下面的编程就使用随机数初始这个染色体,因为染色体上只有0与1,因此只需根据随机数来生成0与1即可。
3、评估适应值
对于适应值的评估使用评估函数来进行,适应度用来评估一个染色体的优劣。评估函数基本是根据问题的优化目标来进行确定的。在遗传算法中,规定适应值越大的染色体越好。
4、选择算子
种群的选择操作使用轮盘赌选择算法,轮盘赌选择算法基于概率的随机选择,比如电影里经常看到的在枪里放一颗子弹,进行开枪赌运气。
5、交配算子
在染色体交配阶段,每个染色体能否进行交配由交配概率P来决定,如果随机数在这个概率之内则表示两个染色体需要进行交配。
6、变异算子
同样的有一个变异算子,设定一个变异概率P,产生随机数小于这个编译概率,那么可以进行变异。
Step 1 :初始化群体N,使用随机数生成器对群体中的每个个体染色体进行随机编码,标记迭代次数c=0。
Step 2:使用评估函数对这些初始出的个体染色体进行评估,计算出他们的适应度,然后标记最大的适应值Best。
Step 3:采用轮盘赌方式进行选择操作,产生规模同样为N的种群
Step 4:按照交配概率P,选择则染色体进行交配。
Step 5:按照变异概率P,选择染色体进行变异。
Step 6:使用交配变异后的新种群代替旧种群,重新通过评估函数计算适应值。若新种群的最大适应值在于前面标记的Best,就更新Best。
Step 7:将迭代次数加1,继续第三步进行迭代。
代码好像不是自己写的,来自网络,三年前找到的代码,找不到出处了,侵删。
该代码为遗传算法解决0-1背包问题,主要包含如下两个文件:
(1)ga.c:
#include
#include
#include
#include
#include
#define ROUND 4000
#define INIT 100 //初始染色体数目
#define TotalGoods 50 //货物总数
#define Load 600 //背包总容量
int Weights[TotalGoods]; //存储每件货物重量数组
int Values[TotalGoods]; //存储每件货物价值数组
int TotalWeights[INIT]; //存储每个组合的总重量
int TotalValues[INIT]; //存储每个组合的总价值
double Fitness[INIT]; //适应度
char ParentChromosome[INIT][TotalGoods+1]; //存储父代基因组合,即染色体
char ChildChromosome[INIT][TotalGoods+1]; //存储子代基因组合,即染色体
double Prob[INIT]; //每个组合的选择概率,用于轮盘赌选择
int count = 0;
/*******************************************************/
//读取配置文件
//Line1: 货物重量
//Line2: 货物价值
//Line3……:备选初始组合,因为初始组合是随机产生的,不能保证满足“重量和<背包容量”,须在本程序中进行判断
/******************************************************/
void ReadConfFIle(char *filename)
{
int i, j;
int sum=0;
char *fname = filename;
FILE *fid = fopen(fname, "r");
for (i=0; i< TotalGoods; i++)
{
fscanf(fid, "%d",&Weights[i]);
}
for (i=0; i< TotalGoods; i++)
{
fscanf(fid, "%d", &Values[i]);
}
//从文件中读取满足约束条件的组合作为初始组合
for (i=0; i< INIT; i++)
{
fscanf(fid, "%s", &ParentChromosome[i]);
sum=0;
for (j=0; j< TotalGoods; j++)
{
sum += (int)(ParentChromosome[i][j]-48) * Weights[j];
}
if(sum >= Load)
{
i--;
}
}
fclose(fid);
}
/*******************************************/
//计算所有个体的适应度
//得到适应度数组
//输入:
// char Chromosome[][]: 父辈基因的组合
//输出:
// double *fitness : 所有基因组合的适应度
/******************************************/
void CalculateFitness(char Chromosome[][TotalGoods+1],double *fitness )
{
int i,j;
for (i=0; i< INIT; i++)
{
TotalValues[i] = 0;
TotalWeights[i]=0;
for (j=0; j< TotalGoods; j++)
{
TotalWeights[i]+=Weights[j]*(int)(Chromosome[i][j]-48);
TotalValues[i] +=Values[j] *(int)(Chromosome[i][j]-48);
}
fitness[i]=(double)TotalValues[i];
}
}
/********************************************************/
//通过轮盘赌来选择确定选择交叉的父染色体
//parent中存储了两个选择的父染色体的下标
//输入:
// double *fitness: 适应度,即每一个组合的价值
// double *prob : 每个组合的选择概率
//输出:
// int *parent : 选择出来的两个父染色体的标号
/*******************************************************/
void RoundRobinSelection(double *fitness, double *prob, int *parent)
{
double FintnessSum = 0;
int i, j;
double r1, r2, r;
double ProbSum=0;
int parent1, parent2;
for (i=0; i< INIT; i++)
{
FintnessSum += fitness[i];
}
for (i=0; i< INIT; i++)
{
prob[i] = (float)fitness[i] / FintnessSum;
}
r1 = rand() /(double) (RAND_MAX);
r2 = rand()/(double) (RAND_MAX);
if(r1>r2)
{
r= r1;
r1 = r2;
r2 = r;
}
for (i=0; i< INIT-1; i++)
{
if (ProbSum < r1 && ProbSum + prob[i] >= r1)
{
parent[0] = i;
break;
}
ProbSum += prob[i];
}
for( ;i < INIT-1; i++)
{
if(ProbSum < r2 && ProbSum + prob[i] >=r2)
{
parent[1] = i;
break;
}
ProbSum += prob[i];
}
}
/******************************************************/
//根据轮盘赌的结果,对选择出来的组合进行杂交
//杂交过程中要注意杂交的结果是否满足我们的重量约束条件
//输入:
// int *Parent: 轮盘赌选择的进行杂交的父辈基因组合序号
//输出:
// ChildChromosome[]:将满足约束条件的杂交结果存储
/**********************************************************/
void ChromosomeCross(int *Parent)
{
int r1;
int i;
char c;
int weights1=0, weights2=0;
r1=rand()%TotalGoods; //随机生成交叉点
char tmp1[TotalGoods+1], tmp2[TotalGoods+1];
memcpy(tmp1, ParentChromosome[Parent[0]], TotalGoods+1);
memcpy(tmp2, ParentChromosome[Parent[1]], TotalGoods+1);
for (i=r1; i < TotalGoods; i++) // 染色体交叉重组
{
c=tmp1[i];
tmp1[i]= tmp2[i];
tmp2[i]= c;
}
for(i=0; i< TotalGoods; i++)
{
weights1 += Weights[i]*(int)(tmp1[i]-48);
weights2 += Weights[i]*(int)(tmp2[i]-48);
}
if (weights1 <= Load )
{
if (count<100)
{
memcpy(ChildChromosome[count], tmp1, TotalGoods+1 );
count++;
}
}
if (weights2 <= Load )
{
if(count<100)
{
memcpy(ChildChromosome[count], tmp2, TotalGoods+1 );
count++;
}
}
}
/******************************************/
//基因变异
//如果基因的变异使基因组合的适应度增大,接收变异
//否则以一定概率接受变异
/*****************************************/
void Genovariation()
{
double p;
int v;
int i,r;
for (i=0; i< INIT; i++)
{
r=rand()%(TotalGoods-1);
p=(double)rand()/RAND_MAX;
if (ChildChromosome[i][r]=='0')
{
if (TotalWeights[i] + Weights[r] <= Load)
{
ChildChromosome[i][r]='1';
}
}
else
{
if (p>0.8)
{
ChildChromosome[i][r]='0';
}
}
}
}
int main()
{
int Parent[2];
int i, j;
double MaxFitness=0, MinFitness = 10000, FinalMaxFitness = 0;
double FinalMax[ROUND];
int max_index, min_index, final_max_index;
int w;
FILE *fid;
srand(time(NULL));
char filename[50]="test.txt";
ReadConfFIle(filename);
fid = fopen("result.txt", "w");
for (j=0; jMaxFitness && TotalWeights[i]<=Load)
{
MaxFitness = Fitness[i];
max_index = i;
}
if (Fitness[i] FinalMaxFitness)
{
FinalMaxFitness = FinalMax[j];
final_max_index = j;
}
fprintf(fid, "Round %d: MaxFitness = %lf, %s\n",j, MaxFitness, ParentChromosome[max_index]);
for (i=0; i< 100*INIT; i++)
{
RoundRobinSelection(Fitness, Prob, Parent);
ChromosomeCross(Parent);
if (count >=100)
{
count = 0;
break;
}
}
Genovariation();
for (i=0; i< INIT; i++)
{
memcpy(ParentChromosome[i], ChildChromosome[i], TotalGoods+1);
}
}
fprintf(fid, "MaxValue : %lf Line : %d\n", FinalMaxFitness, final_max_index+1);
fclose(fid);
return 0;
}
(2)test.txt:
71
34
82
23
1
88
12
57
10
68
5
33
37
69
98
24
26
83
16
26
18
43
52
71
22
65
68
8
40
40
24
72
16
34
10
19
28
13
34
98
29
31
79
33
60
74
44
56
54
17
26
59
30
19
66
85
94
8
3
44
5
1
41
82
76
1
12
81
73
32
74
54
62
41
19
10
65
53
56
53
70
66
58
22
72
33
96
88
68
45
44
61
78
78
6
66
11
59
83
48
00000000000000000000010001000000000000000000000000
00000000000000000010000000000000000000000001000001
10000000000000000001010000000000000001000000000000
00100100010000000000000010000000100000010000000000
00000001100010000010010000000000010000000001000010
00000000100001000000000000000000000000000100000000
00000000000001000000000000001000010100000000000010
00000010000000000000000000000000000000110011000000
00001000000000000000001000000001000100000000010000
00000010000000010000000000000101000000000000000000
00000000001000000100000000000000000000000001000000
00000000010001000000000000000001101000000000000000
00010000100000000000010010010000000001000001100010
00000000000001000000000000100000000100001000000000
00000000000010000000000000001000010000000000001001
00010000000000000000110000000000000000011010000010
00000100110100000000000100000000000000010000000000
00001000000100000000000000000000000000000001000000
00000000001000000100000000000000100011010100000000
00000000000000000100000000000001010000000000010100
10000000000000100000100011000001000000000010010000
01000000000000000000000100001000000000000000000001
00100000000000000000000100000000000010000000010000
00010000000000100000000011000000000000000000000010
00001000100010000000000100000000000001000000010000
00000010001011000000100100000000000000100100001000
00000001000001000000100000000000000000000000000000
01000100000000100000000000000000000000000010000000
00000000000000100000000000100000100001000000000000
11000000011000000001000010000000000011000000000000
00000000000000000000000000000000010000000000000000
00000000000000000000000000001000000000000000000000
01000000000000000000000101000000000000010000000000
00000000100000000101110000000000000000000000000000
00000110001000010000000100100010000001000000000000
00000010000000000000000000000000000000110000000000
00000001000100000000000100000000000000000000000000
00010000010000000000000000100000010000000000000000
10000001000000010000000000000100000000000000000000
00000000000000000000000000010000000000000000000010
10000010000000010000000001000000000000010000000000
00000000000000000000110000001000000010000000000100
01000000000000000110000000000000000001000011000000
00001000000000000100000000000000000000000000000000
00000000000000000010000100000110000000000000000010
11000010000000000010000000000000000000000000000010
00000000001000001000010000100000000100000000010000
01001000000000001000000000010000000100000001100011
00010000000000100000000100000000000000000000001000
00001000000101000000000000000001000000010000000100
00010000000000010001000000100000010000000000001011
00000000000001000000000100000000000000110000000000
00000000000010010000100000000000000000000001000000
01001100000100001000000000000010000000000000000000
00000100000000100000000000000000000011010000000000
00000000000010000100001000101000000000000000000000
00000000000000000000000011000000000000000000000000
00000000000001000001000000010000000000010101000000
00000000000000000000000000010000000000000100101100
10000001000100000000000000000000000000000000000000
00010000000001000010000000110000000000000000000000
00001000000000000000000000000000000001000100010000
00010010000110000000000000000000000100000000001000
10000001000000000000000000000000000110000000001000
00000010001100000000000000100000000000000000000000
01000000001000000000000000000000000000000001000001
00000010011001000000000000000000010010000010000011
01000000000010100100000000000000000100001000000000
00000000000000000000100000000001001001000100010000
00001000000000000000000000000000100000010100000100
00010100100000000000001000000000010000001000000100
00000000001100000000100000000000010000000000000001
00000000100010010000000010000100100000000000000000
00000000000001100000000000000000000000000000000000
00001100010100000000000000000000000000000000000000
00000000000010000000000000000000000000000010000000
00000010000000010001000000000000000000000101000000
00100000000001000100000000000000000000000001000000
01000000000000000000010000000000000000000000000000
00100001000010000000000000000100100000000101110000
00000010000000000100000000000001000100000000010000
00110010000000000000000010000000000000101000000000
00001100010000000000000000000000000000001000000010
00000000100000000000001000000101000100101100100000
00001101100000000000000100000000000010000000000010
00000000000000000001000000000100000000000000001000
10100000000000000000100000010010000000000000010100
10000000000001000000001000000000000010000000000000
00100000001000000000000000000000001000000100100000
00000000000001000010000000000000000000000100010100
00000000000000000000100000010000000100000010000001
00000000000000010000000000000010101000000100100000
00000000000010000000000000000100100000000000000101
01000100010001000010000000000010000000010000000010
00000000000000000000000000100001000010000010000000
01000000000000000010000000000000000001000000000000
10000000000000010000100000000000000000110010000000
00000010100000000000000100000100000000000000000000
00000011000000000001000000100000010000000000100000
00000000001000000100000000000000010000100000000010
10100010000001000000000010000010000000010000000000
10000001000000000000010000000000000000000010000100
00100000000010000000010000000010000001000100000000
00000010010000001000000000000001010000001100000000
00001000000000000000000100000000000000000000000001
00000000000100001000001000000000000001000000000000
00000000000000001000000000000000000000000010000000
00101000000000100010000000000000000000000000001000
00000000000000001000000000000000001010000000000000
00100000000010000000010010001000000100000000000001
00000000000000000000000100000010000000000000000001
01000001000000000000101100100000000000000000000100
00000000000000000000000001000001000000000010110000
00000001000000100000000000000000000000010000000000
10000001000001100000000000000100000000000000000000
01000000000000000000000000000001000000000101000000
00000000000000000000000100000000000000000000001000
00000000000000000000000000010100000000000100010000
00000011100000000000000000000100000010000000000000
00010000000000100000000000100100000000000000100000
00000000100000000000000000000000000001000000000000
00000100000100000100001000000000000100000000000000
01001000000000000000000001010000000000000110001000
00000000000000001001000000000010010100000000000000
00000000000000000001110000000000000000001000000010
00000000000100000010001000110000000000101000000000
10000000000000001000010000000000100000000000000000
00000000000010000000000000000000000010000010010010
00000000000011001110000000000000000000000101000010
00000011000000000001000000010000001000101000000000
00000000001101001000101000000000010000000000000000
00010000110000110000000000000000001110000000000110
00010010000000000000000010000000000000000100000000
00000000000000000000000001100000100000001000000000
10100000000000000100000000000000000001000000000000
00000000000000001000000000000000000100000000000000
10000001000100000000100000000000000100010000000000
00000011000000000000000001000000010000000000000000
00000000001000000000000010100000001000101000000000
00000000011000000000010000000000000000000100000100
01000100000000000000000000000000000000100000000000
00010000000000000000000000000000010000000000011000
11000000000000010000000000000000000000000001100000
00100000000000000010101000000000000000001000000000
01000000000000000000000000100010110110000000000000
00010010000100010000010000001010000001000000000000
00000000000000000001001000100000000000000010000000
00000000000000000000000100000000000000000000000000
00000000010000100000000001001000000001010000010000
10000000000000000001000000000010000100000000000000
10000000000001001000100000001000000000000000100000
00000000000001000000001000000000001000000000100100
01000100000000011010000000001000001000001000100010
00000000000000001010100000000000000010000000000000
00000100000000000000000000001000000000100000000110
10001000001010001000000000000001000000000000000000
00010000001000010000010000000101010000000001100100
00000000000000000000000100000000001000100000100000
00000000110001000010000000010000000101010000000100
00000000000010000000000000000000000010101000001000
00101001000000000000001000000010001001010000000100
00000000000000000000000000000010000010000000000000
00000000000001100100000000001010000000000000000000
00000000000110000000000001000000000000011100000000
00000000000000000000001100001000000000000000000001
00100000000000001000001000010000000000001000000001
01000010000000100000000001000000100000000010000000
00000000000000001000000000000000000000010000001000
00100000000101101000000000000000010001000000000000
00100000000000001000010000000000010000010000000000
00000000000000000010000000010000000000000100000100
00000000100000010000000000001000000110000100000000
00000000000010000000000000000000010000000000001000
00000000010000100000010001000000010000000000000000
01100000000000000100000000000000001000000000000000
00100000110000001000000000000000000000000000001000
10000110010000000000010100000000000000000011000000
00000000000000000010000000010000000000000000001100
00010000000000000000000000000000000000000000001000
00000100010110000100000000001000100000000100000001
00000000010000000001000000001000000000000000000000
00000000000100000000000000000000000001000010000000
00000000010000000000000100000100000000001000000010
00100000000001000000100000001000010000001000010010
00000000010000000000001000000000000000100000100000
00101000010000000010000000000001010000000000000000
01000000000010000000000000000000000001000000000000
00000000000000000000000000000000000000000000000000
01001000000000000000100000000000000001000010100000
00100000000000100100000000000010000100000010001100
01000000100001000000000000000001000000000000000000
00000000000000000000000000000001000001000000100000
01000000010000010010000000000001000100000000000000
11000000010000000000000000000000100000001000000000
00100000010010000001000000001100000000000010000000
10100010000000000000000000000010000000000000100000
10000000000000000100000000000000000000000010000000
00000000000000000000000010100001000000000000000010
00000010000000000000110000001000000000000000000000
00100110010000010000100010000000000100000100000001
00000011000000000000000000010001000110000100000000
00000001000100000000000000000101000100000000000000
00000000100001000000000000000100000000000000010000
01000000000000000001000000010000000000000000000000
00000000001100000000000000000000000000000000001000
00000000000000100110000100000000000000010000000001
01000000000001000001001000000000010000100000000000
00000000000000001000000100001000000010000000010000
00000000000000000000000000000010000000000000000001
00101000000010000000000000000100100000000001000000
10000010000000001001011000000000000010000001000000
11000001000000000000000001000010000000100000010000
10000100000000000001000000000000100000110000000000
00000000000000000000000000000000000000000001000000
00000000000010100000000000010001000000000000000001
10000000000000000000000000000000000001000000000100
00001000000000001000010010000000000010010000000100
00000000001100000010000000000000000100000000100010
10000001000000000000000000000000000000000001000000
00001000001000000000000000000000000000000000001010
01000000000100000000100100000000000100000000000000
00000000000000001000000000001000000000000000000000
00010000000000000010000000000000010101000000000000
00000000000000000001000000010000000010010000000000
00001000000000000010000001101000000000010100000011
00000100000000000000000000000001000000100000000000
10110000000000000000100000010000000000000000000010
00010000000000010010000000000000000000000000000000
00000000000001100000000000000000100011000000000000
00000000000000000000000100001001001000000000000000
00100000000001000000000000010000010100000000000000
00000000000000010001000010000000000000000000000000
00000000000100000000000000010001000000000100000000
00010000000000000000011000000000000000000000010000
10000010000000010010010001000100000000000000100000
10000000000100000000000000000000000000000000010000
00000000000101000000000000000000000000000000100100
00000000000000100000100000000000110000000000000000
00000100010000000000100000000000000100000000000000
00001000000000000010100010100000010000000000000100
00000000001000010001000010000000000000000000010000
00100000000000000000100111000001000000000000100000
00000001000100000000000110000000001000000010001000
00000000000000000000000000110000000000001000000000
00000001000100010000010100100010000000000000000000
10000000000000000000000000000000000000000000000000
00000010000000001000000000000000000000001000000000
00000010000001000100000000000000110001000000000000
00100000001000000000001000100000000000001011000000
00000000000000001000000000000010000001000000000000
00100100000000000000000000000100001000000000100000
00100001000001000000010000100010100000000000000100
00000000000000000000000000000000000100010000000000
00000000001000001000000000000000000000000011000000
10100000000010100000000000000000000000000000001000
00011000000000000000000010001000001000000000001000
00000000000000000000000000000000000000001000000000
00000000001000000010000000000001010000001000000000
00000010010000000010010101000010000100000010000000
00000101000000000000000010000000000000111000000000
00000001000100000000010000001000000000001000000000
00100010000001000001000100000000000000010001000011
00010000000000100000000000100100100000010000000001
01000110010000000010010010001000000000000000100000
00000000000000000010000000000001000000000000100000
01001000000010000000100100000000000000000011000010
00000000001000000100001000001000000000000001000001
11000110000000001000000010010000100000000000000000
00000001000000000010000000001100010000000011000000
00010000000000000100100000010000000001000000010000
00000000000001001000000000001000001000001000010000
00000000000000000000010000010001001010000010100000
00100000000000010100000100000000000000001000000000
10000001000000000000000001000001000000000000000010
00000000000000000000100010000000000000001000000000
00010100001000000000000001000000001000010000000000
00000010010000000000010000100000000000000100000000
00100000000000101000001000000000000000110000000000
10000001000000000001011000001000000000001100010000
00000000010100010000000000000000000000100000000000
00000000000000100000000000000000010100000010000000
00000000000100000000001000000011000100000000110000
00000000000000000001000000000000010000000000000101
00000000000000000000100000000000001000000000000000
00000000000000101000000000000010000000000000000001
00000000000000000001000000000010000000000011000000
01000000000000000000000000000000010000000000000010
00100000000000001000000000100000010000101000000000
00000000000000001000000000000010000001000000000000
00000010000000000000000000000001000000001000000000
00010000000000000010000000000000100000000001000000
00100100010000000000000000001000001000000001000000
01010000000010000010000000000000000000000000001000
00000001010000001000000000000000010000000000000000
00100000000000000001000000101000000000000001000100
00000001000000100100000000000100000000000100000100
01000000000010000100001000100000000010100000000000
00000001000000000000000000000000000000110010000000
10000000110000000000100010000000011000000000000001
10000000000000001000000000001000010000000000010000
最后执行的结果会保存在当前目录下的result.txt中