遗传算法案例分析及源代码
一.问题描述:
在某一区域内有n个客户,拟建一个物流中心,已知客户j地址坐标为。确定物流中心的地址坐标,使得该物流中心到几个客户之间的距离最短。
假设:简单的用两点之间的距离代替运输距离。
目标函数:
约束条件:
假设某一区域内有 5 个客户,其位置坐标如下表所示,
客户坐标及相关需求量
客户 | X(km) | Y(km) |
1 | 1 | 5 |
2 | 2 | 8 |
3 | 5 | 1 |
4 | 7 | 6 |
5 | 8 | 3 |
(1)变量:
C:是一个1*6数组,每个数组里面是一个6位二进制数,它是遗传算法中的染色体。
new_c:每一轮的新变量c。
first_c:初始群体矩阵。
sur_value:个体适应值的概率值,为0-1之间的数,所有概率值和为1。
survived:经过选择运算后产生的个体基因型组合。
intersect_c :经过交叉运算后产生的个体基因型组合。
mutation_c:经过变异运算后产生的个体基因型组合。
f:最后计算得到的最大值
(2)程序里面的方程
function out = value_function( ci ):价值函数(自适应度函数)。
function [ sur_value ] = calc_value( c ):计算群体中每一个个体的适应度的值
function survived = surviver( sur_value ):利用概率选择函数
function [ intersect_c ] = intersect( new_c ):交叉运算
function [ mutation_c ,mutation_value] = mutation( intersect_c ):变异运算
(1)遗传算法主程序
%遗传算法的主程序
%初始群体的产生,本例中,群体规模大小取为6,即由6个个体组成,每个个体随机产生。
c = rand(6,6);%产生随机群体,c表示个体变量。
%第一个6表示个体个体,第二个6表示基因型由6位无符号二进制数组成
c(c>0.5) = 1;
c(c<0.5) = 0;
%显示初始群体
first_c = c;
points = [1,5;2,8;5,1;7,6;8,3];
%目的点
%一轮算法包括选择,交叉,变异,变异完成后产生新的个体,作为子代群体进行下一轮进化。一共设置1000次进化
for n = 1:1000%设置循环次数
sur_value =calc_value(c,points);
survived =surviver(sur_value);
new_c = zeros(6,6);
for ii =1:6
new_c(ii,:) =c(survived(ii),:);
end
intersect_c =intersect(new_c);%交叉个体
mutation_c = mutation(intersect_c );%变异个体,作为子代群体
c = mutation_c;%子代群体作为新一轮的个体,继续选择,交叉,变异
end
f=0;
for jj=1:6
b =value_function(new_c(jj,:),points);
if b>f
f=b;
end
end
(2)适应度函数计算:适应度函数选择为目标函数的倒数
function distance = value_function(ci,points )
%遗传算法的价值函数,同时也可以将此目标函数值作为个体的适应度。
x = 4*ci(1)+2*ci(2)+1*ci(3)+1;
y = 4*ci(4)+2*ci(5)+1*ci(6)+1;
distance = 0;
for ii=1:length(points)
distance = distance +((x-points(ii,1))^(2)+(y-points(ii,2))^(2))^(1/2);
end
end
function [ sur_value ] = calc_value(c,points )
%计算群体中每一个个体的适应度的值
value = zeros(1,6);
for ii = 1:6 %对于第1到第6个个体
value(ii) = 1 /value_function(c(ii,:),points);%计算每个个体的适应度值
end
sur_value = value ./ sum(value);%将适应度值归一化,即每个个
%体被遗传到下一代群体中的概率
end
(3)选择计算
function survived = surviver( sur_value )
%选择个体,采用与适应度成正比的概率来确定各个个体复制到下一代群体中
survived = ones(1,6);
for ii = 1:6
random = rand(1)%随机产生一个0到1的数
%判断该随机数出现在哪一个概率区间内,以此来判断哪个个体被选中
sur_v_a=0;
%设置最后结果的输出
for jj = 1:6
sur_v_a=sur_v_a+sur_value(jj);
if random <sur_v_a
survived(ii) = jj;
break;
end
end
end
end
(4)交叉运算
随机设置交叉点
function [ r ] = random5( )
%随机设置交叉点位置,一共有5个交叉点位置。6个个体共需3次交叉
r = rand(1)*5;
r = floor(r)+1;
end
function [ intersect_c ] = intersect( new_c )
%j进行交叉运算:以某一概率相互交换某两个个体之间的部分染色体
% 此处显示详细说明
intersect_c =zeros(6,6);
for ii = 1:3
r5 = random5();
intersect_c(ii*2-1,1:r5)= new_c(ii*2-1,1:r5);
intersect_c(ii*2-1,r5+1:6) = new_c(ii*2,r5+1:6);
intersect_c(ii*2,1:r5)=new_c(ii*2,1:r5);
intersect_c(ii*2,r5+1:6)= new_c(ii*2-1,r5+1:6);
end
end
(5)变异运算,变异概率为0.05
function [ mutation_c ,mutation_value]= mutation( intersect_c )
%变异运算:对个体的某一个或某一些基因座上的基因值按某一较小的概率进行改变
%
mutation_c = intersect_c;
mutation_value = zeros(2,36);
count=1;
for ii=1:6
for jj=1:6
r = rand(1);
if r<0.05
mutation_c(ii,jj)=1-mutation_c(ii,jj);
mutation_value(1,count)=ii;
mutation_value(2,count)=jj;
count=count+1;
end
end
end
end
经过1000次迭代后,产生的结果为:C的值。对应的最优解为f的值。