遗传算法(Genetic Algorithm, GA)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。
其主要特点是直接对结构对象进行操作,不存在求导和函数连续性的限定;具有内在的隐并行性和更好的全局寻优能力;采用概率化的寻优方法,不需要确定的规则就能自动获取和指导优化的搜索空间,自适应地调整搜索方向。
(摘自百度百科)
常用的编码方式有二进制编码法、浮点编码法、符号编码法。
这里采用的是二进制编码法。规定染色体长度为17,则一个个体的编码示例如下:
00001111000011110
首先定义种群大小、染色体长度等基本量:
elitism = true; % 选择精英操作
population_size = 100; % 种群大小
chromosome_size = 17; % 染色体长度
generation_size = 200; % 最大迭代次数
cross_rate = 0.6; % 交叉概率
mutate_rate = 0.01; % 变异概率
对种群中的每一个个体进行初始化,这里随机产生0与1对种群population数组进行幅值。
function init(population_size, chromosome_size)
global population;
for i=1:population_size
for j=1:chromosome_size
% 给population的i行j列赋值
population(i,j) = round(rand); % rand产生(0,1)之间的随机数,round()是四舍五入函数
end
end
迭代次数已在初始化中给定 generation_size = 200(即流程图中的GEN)。
for G=1:generation_size
fitness(population_size, chromosome_size); % 计算适应度
rank(population_size, chromosome_size); % 对个体按适应度大小进行排序
selection(population_size, chromosome_size, elitism); % 选择操作
crossover(population_size, chromosome_size, cross_rate);% 交叉操作
mutation(population_size, chromosome_size, mutate_rate);% 变异操作
end
进化论中的适应度,是表示某一个体对环境的适应能力,也表示该个体繁殖后代的能力。遗传算法的适应度函数也叫评价函数,是用来判断群体中的个体的优劣程度的指标,它是根据所求问题的目标函数来进行评估的。
在每次计算前将初始化为0,注意这里使用浮点数进行初始化:
for i=1:population_size
fitness_value(i) = 0.;
end
计算适应度的函数假定为 f(x) = -x-10sin(5x)-7cos(4x)
遍历每一个个体的每一个基因,首先将二进制转换为十进制,再将十进制数映射到自定义的变量区间里,比如这此程序中,就将0 - (2^17 - 1) 映射到了区间 (0,9) 中。
最后根据区间映射的值计算适应度。
在使用中,如果没有需求,其实可以不必映射到特定区间,修改适应度函数后直接使用十进制数计算适应度即可。
for i=1:population_size
for j=1:chromosome_size
if population(i,j) == 1
fitness_value(i) = fitness_value(i)+2^(j-1); % population[i]染色体串和实际的自变量xi二进制串顺序是相反的
end
end
fitness_value(i) = lower_bound + fitness_value(i)*(upper_bound-lower_bound)/(2^chromosome_size-1); % 自变量xi二进制转十进制
fitness_value(i) = fitness_value(i) + 10*sin(5*fitness_value(i)) + 7*cos(4*fitness_value(i)); % 计算自变量xi的适应度函数值
end
在每一次计算完适应度之后都要挑选出适应度最高的个体信息。
遍历种群,使用冒泡排序法,使得population(i)的适应度随i递增而递增,population(1)最小,population(population_size)最大。
for i=1:population_size
min_index = i;
for j = i+1:population_size
if fitness_value(j) < fitness_value(min_index);
min_index = j;
end
end
if min_index ~= i
% 交换 fitness_value(i) 和 fitness_value(min_index) 的值
temp = fitness_value(i);
fitness_value(i) = fitness_value(min_index);
fitness_value(min_index) = temp;
% 此时 fitness_value(i) 的适应度在[i,population_size]上最小
% 交换 population(i) 和 population(min_index) 的染色体串
for k = 1:chromosome_size
temp_chromosome(k) = population(i,k);
population(i,k) = population(min_index,k);
population(min_index,k) = temp_chromosome(k);
end
end
end
计算前i个个体的适应度之和fitness_sum(i),在后续选择操作中会用到。
for i=1:population_size
if i==1
fitness_sum(i) = fitness_sum(i) + fitness_value(i);
else
fitness_sum(i) = fitness_sum(i-1) + fitness_value(i);
end
end
保存最佳个体的信息
% fitness_average(G) = 第G次迭代 个体的平均适应度
fitness_average(G) = fitness_sum(population_size)/population_size;
% 更新最大适应度和对应的迭代次数,保存最佳个体(最佳个体的适应度最大)
if fitness_value(population_size) > best_fitness
best_fitness = fitness_value(population_size);
best_generation = G;
for j=1:chromosome_size
best_individual(j) = population(population_size,j);
end
end
从群体中选择优胜的个体,淘汰劣质个体的操作叫选择。选择的目的是把优化的个体(或解)直接遗传到下一代或通过配对交叉产生新的个体再遗传到下一代。
遗传算法中的选择操作就是用来确定如何从父代群体中按某种方法选取那些个体,以便遗传到下一代群体。选择方法有很多,本程序中策略如下:
遍历种群。每次遍历中:
首先生成一个随机数,在[0,总适应度]之间。在适应度排序中,我们已经计算出了计算前i个个体的适应度之和fitness_sum(i),接下来就可以用排中法选择适应度之和最接近次随机数的个体的位置。
取得此个体位置后,根据此个体的基因产生一个新的个体。
在遍历结束后,用population_new更新所有个体。选择操作完成。
通过这种选择操作,每次生成的随机数在[0,总适应度]之间,而population(i)的适应度随i递增而递增,因此用排中法选择的population(idx)总体数值会靠近中间值,适应度低的个体会被淘汰。
在程序中还加入了精英选择的选项,如果进行精英选择,则每次选择时都会将最优的个体保留。
for i=1:population_size
r = rand * fitness_sum(population_size); % 生成一个随机数,在[0,总适应度]之间
first = 1;
last = population_size;
mid = round((last+first)/2);
idx = -1;
% 排中法选择个体
while (first <= last) && (idx == -1)
if r > fitness_sum(mid)
first = mid;
elseif r < fitness_sum(mid)
last = mid;
else
idx = mid;
break;
end
mid = round((last+first)/2);
if (last - first) == 1
idx = last;
break;
end
end
% 产生新一代个体
for j=1:chromosome_size
population_new(i,j) = population(idx,j);
end
end
% 是否精英选择
if elitism
p = population_size-1;
else
p = population_size;
end
for i=1:p
for j=1:chromosome_size
% 如果精英选择,将population中前population_size-1个个体更新,最后一个最优个体保留
population(i,j) = population_new(i,j);
end
end
在自然界生物进化过程中起核心作用的是生物遗传基因的重组。同样,遗传算法中起核心作用的是遗传操作的交叉算子。遗传算法的交叉操作,是指对两个相互配对的染色体按某种方式相互交换其部分基因,从而形成两个新的个体。通过交叉,遗传算法的搜索能力得以飞跃提高。
给定交叉概率cross_rate,以步长为2遍历种群,如果随机生成的(0,1)的数小于交叉概率,则对相邻的个体进行交叉操作。
交叉算子的选择有很多,此程序选择较简单的做法,具体操作是:在染色体长度范围内随机选择一个位置cross_position,交换相邻个体此位置后所有的基因片段。
for i=1:2:population_size
% rand<交叉概率,对两个个体的染色体串进行交叉操作
if(rand < cross_rate)
cross_position = round(rand * chromosome_size);
if (cross_position == 0 || cross_position == 1)
continue;
end
% 对 cross_position及之后的二进制串进行交换
for j=cross_position:chromosome_size
temp = population(i,j);
population(i,j) = population(i+1,j);
population(i+1,j) = temp;
end
end
end
遗传算法中的变异运算,是指将个体染色体编码串中的某些基因座上的基因值用该基因座上的其它等位基因来替换,从而形成新的个体。
随机选择变异位置,对该位置的基因进行取反。
for i=1:population_size
if rand < mutate_rate
mutate_position = round(rand*chromosome_size); % 变异位置
if mutate_position == 0
% 若变异位置为0,不变异
continue;
end
population(i,mutate_position) = 1 - population(i, mutate_position);
end
end
主循环结束后,即可获得最优个体和适应度等结果,输出即可。
disp 最优个体:
best_individual
disp 最优适应度:
best_fitness
disp 最优个体对应自变量值:
x
disp 达到最优结果的迭代次数:
iterations
matlab源代码见我个人空间或前往链接。