十进制编码的遗传算法,实际上就是直接使用实数来进行交叉和变异计算。
十进制编码遗传算法
由于我们的数据本身就是用十进制表示的,所以十进制编码相当于不编码。
相应的,我们的交叉方法与变异方法也要针对十进制做出相应改变。
以下改变都是在混合遗传算法的基础上作出的。工程优化设计与Matlab实现——混合遗传算法求解多维问题
Part 1 Arith交叉算法
对染色体x1与x2进行交叉操作,方法如下:

由于在交叉之前已经“洗牌”,所以对相邻两个染色体交叉相当于对任取的两个染色体交叉。
%**********************************************************************%
%*********************相邻两个染色体Arith交叉算法函**********************%
%**********************************************************************%
function X = Cross(n_Population, X, pc)
if mod(n_Population ,2) == 0
cross_num = n_Population; %如果个体数为偶数,参与交叉个体数为全部个体数
else
cross_num = n_Population - 1; %如果个体数为奇数,参与交叉个体数为全部个体数-1,,最后一个不参与交叉
end
for i = 1:2:cross_num
hand_of_god = rand; %上帝之手随机做选择
if hand_of_god < pc %如果上帝手小于交叉概率pc,就进行交叉,否则不交叉
Cross_Temp_1 = X(:, i);
Cross_Temp_2 = X(:, i+1);
r = rand;
X(:, i) = r * Cross_Temp_1 + (1 - r) * Cross_Temp_2;
X(:, i+1) = r * Cross_Temp_2 + (1 - r) * Cross_Temp_1;
end
end
end
Part 2 变异算法
对染色体x1进行变异操作,方法如下:

相当于在x1与下界之间任取一个新x1。这就导致如果变异概率过大,导致变异的次数过多,会使所有种群所有个体向下界靠近。
%**********************************************************************%
%****************************变异函数****************************%
%**********************************************************************%
function X = mutate(n_Population, lb, X, pm)
for i = 1:n_Population
hand_of_god = rand; %上帝之手随机做选择
if hand_of_god < pm %如果上帝手小于变异概率pc,就进行变异,否则不变异
X(:, i) = lb + (X(:, i) - lb) * rand; %变异
end
end
end
Part 3 一些问题
遗传算法早熟现象十分明显,导致很多时候只找到了局部最优解就结束迭代。
Part 4 栗子
利用十进制混合遗传算法,求2维Rastrigin测试函数的极小值点
目标函数定义:
function f = func(x)
D = 2;
f = 0;
for i = 1 : D
f = f+(x(i)^2-10*cos(2*pi*x(i)));
end
f = 10 * D + f;
十进制混合遗传算法定义:
%----------求函数极小值----------%
clc;
clear all;
close all;
%----------设置参数----------%
n_Population = 20; %种群个体数目
ub = [5.12; 5.12]; %给定上界
lb = [-5.12; -5.12]; %给定下界
Chromosome = 2; %染色体个数
E = 0.0001; %给定精度要求
pc = 0.8; %交叉概率
pm = 0.001; %变异概率
n_loop_max = 500; %最大迭代次数
%----------一些矩阵说明----------%
X = zeros(Chromosome, n_Population)*nan; %X为种群染色体矩阵,Chromosome行n_Population列
X_Fitness = zeros(1, n_Population)*nan; %X_Fitness适应度矩阵,Chromosome行n_Population列
Possibility = zeros(1, n_Population)*nan; %Possibility累积概率概率矩阵,1行n_Population列
History_X1 = zeros(n_loop_max, n_Population)*nan; %染色体1矩阵历史记录,最终为n_loop_max+1行n_Population列
History_X2 = zeros(n_loop_max, n_Population)*nan; %染色体2矩阵历史记录,最终为n_loop_max+1行n_Population列
History_FX = zeros(n_loop_max, n_Population)*nan; %X为函数值矩阵历史记录,最终为n_loop_max+1行n_Population列
History_X_Fitness = zeros(n_loop_max, n_Population)*nan; %X为适应度矩阵历史记录,最终为n_loop_max行n_Population列
for n_loop = 1:n_loop_max
if n_loop == 1
X = X_init(Chromosome, n_Population,lb,ub); %种群初始化
end
%将当前种群状态存储进历史记录
History_X1(n_loop, :) = X(1, :); %存储当前染色体1
History_X2(n_loop, :) = X(2, :); %存储当前染色体2
History_FX(n_loop, :) = GetFunction(n_Population, X); %储存当前函数值
History_X_Fitness(n_loop, :) = GetFitness(n_Population, X); %储存适应度值
fprintf('第%d次迭代n',n_loop)
fprintf('初始种群:')
display(X)
%洗牌(打乱顺序)
shuffle = randperm(n_Population);
for i = 1:Chromosome
X = X(:,shuffle);
end
%交叉
for i = 1:Chromosome
X = Cross(n_Population, X, pc);
end
%变异
for i = 1:Chromosome
X = mutate(n_Population, lb, X, pm);
end
%选择
[X, x_fitness_max] = Select(n_Population, X, E);
fprintf('选择后的新种群:')
display(X)
if x_fitness_max <= E %如果最大的适应度函数小于精度(最大函数值与最小函数值差距特别小)则退出迭代
break
end
end
History_X1(n_loop+1, :) = X(1, :); %存储当前染色体1
History_X2(n_loop+1, :) = X(2, :); %存储当前染色体2
History_FX(n_loop+1, :) = GetFunction(n_Population, X); %储存当前函数值
History_X_Fitness(n_loop+1, :) = GetFitness(n_Population, X); %储存适应度值
X_Function = GetFunction(n_Population, X); %计算当前函数值
[min_f, min_x_position] = min(X_Function); %找出最小函数值
min_x = X(:, min_x_position); %找到最小函数值对应的个体
%**********************打印结果**********************%
fprintf('二进制编码混合遗传算法:n')
fprintf('****************参数设置****************n')
fprintf('种群个体数目: %dn', n_Population)
fprintf('给定上界: %f %f 给定下界: %f %fn', ub, lb)
fprintf('精度为: %fn', E)
fprintf('交叉概率: %fn', pc)
fprintf('变异概率: %fn', pm)
fprintf('最大迭代次数: %dn', n_loop_max)
fprintf('****************迭代结果****************n')
fprintf('共迭代 %d 次n', n_loop)
fprintf('极小值点为: %fn', min_x)
fprintf('极小值为: %fn', min_f)
fprintf('****************************************n')
fprintf('endn')
%**********************************************************************%
%****************************种群X初始化函数****************************%
%**********************************************************************%
function X = X_init(Chromosome, n_Population, lb, ub)
for n = 1: Chromosome
for i = 1:n_Population %随机生成位于上下界内的种群
X(n, i) = lb(n) + rand * (ub(n) - lb(n));
if X(n, i) > ub(n) %如果圆整后超过上界则纠正到上界
X(n, i) = ub(n);
elseif X(n, i) < lb(n) %如果圆整后超过下界则纠正到下界
X(n, i) = lb(n);
end
end
end
end
%**********************************************************************%
%****************************计算函数值函数****************************%
%**********************************************************************%
function X_Function = GetFunction(n_Population, X)
for i = 1:n_Population
X_Function(i) = func(X(:, i));
end
end
%**********************************************************************%
%****************************计算适应度函数****************************%
%**********************************************************************%
function X_Fitness = GetFitness(n_Population, X)
X_Function = GetFunction(n_Population, X); %调用计算函数值函数
max_x_function = max(X_Function);
for i = 1:n_Population
X_Fitness(i) = max_x_function - X_Function(i);
end
end
%**********************************************************************%
%*********************相邻两个染色体Arith交叉算法函**********************%
%**********************************************************************%
function X = Cross(n_Population, X, pc)
if mod(n_Population ,2) == 0
cross_num = n_Population; %如果个体数为偶数,参与交叉个体数为全部个体数
else
cross_num = n_Population - 1; %如果个体数为奇数,参与交叉个体数为全部个体数-1,,最后一个不参与交叉
end
for i = 1:2:cross_num
hand_of_god = rand; %上帝之手随机做选择
if hand_of_god < pc %如果上帝手小于交叉概率pc,就进行交叉,否则不交叉
Cross_Temp_1 = X(:, i);
Cross_Temp_2 = X(:, i+1);
r = rand;
X(:, i) = r * Cross_Temp_1 + (1 - r) * Cross_Temp_2;
X(:, i+1) = r * Cross_Temp_2 + (1 - r) * Cross_Temp_1;
end
end
end
%**********************************************************************%
%****************************变异函数****************************%
%**********************************************************************%
function X = mutate(n_Population, lb, X, pm)
for i = 1:n_Population
hand_of_god = rand; %上帝之手随机做选择
if hand_of_god < pm %如果上帝手小于变异概率pc,就进行变异,否则不变异
X(:, i) = lb + (X(:, i) - lb) * rand; %变异
end
end
end
%**********************************************************************%
%********************************选择函数********************************%
%**********************************************************************%
function [X, x_fitness_max] = Select(n_Population, X, E)
X_Function = GetFunction(n_Population, X); %求当前函数值
[~, x_best_position] = min(X_Function); %最小函数值索引
x_best = X(:, x_best_position); %找到最小函数值对应的个体
X_Fitness = GetFitness(n_Population, X); %求当前适应度值
x_fitness_max = max(X_Fitness); %适应度函数值中最大的,即当前种群最大适应度
if x_fitness_max > E
fitness_sum = sum(X_Fitness); %适应度求和
Possibility = cumsum(X_Fitness / fitness_sum); %根据适应度计算,X_Fitness / fitness_Sum是被选择到的概率,Possibility为累积概率
for i = 1:(n_Population - 1) %n_Population选n_Population-1,可重复选(就算全选了一样的也没关系,后面还有变异)
hand_of_god = rand; %“上帝之手”转动轮盘,皮一下好开心
for ii = 1:n_Population
if hand_of_god < Possibility(ii)
Temp_X(:,i) = X(:,ii); %Temp_X为临时存储选择到的值的矩阵
break
end
end
end
end
[~, max_x_position] = max(X_Fitness); %找出最大适应度
Temp_X(:, n_Population) = X(:, max_x_position);
X = Temp_X; %得到选择后的种群
end
计算结果:

