一、案例引入
求 f(x)=200e−0.05xsinx,x∈[−2,2] 的最大值
二、使用MATLAB事先探测出该函数的最大值的大概位置
PS:使用MATLAB绘图窗口中的“工具->数据游标”即可手动探测出函数最大值所在的大致坐标.
绘图代码:
%detect.m
x = -2:0.001:2;
y = 200*exp(-0.05*x).*sin(x);
plot(x,y)
grid on;
三、源代码
目标函数
(注:对于优化问题中的最大值或极大值问题,可以直接将目标函数当作适应度函数)
%targetFun.m
function y = targetFun(x);
y = 200*exp(-0.05*x).*sin(x);
将一个二进制串转换为十进制数
%transform2To10.m
function y = transform2To10(x);
bitLength = size(x, 2);
y = x(bitLength);
for i = 1:bitLength-1
y = y + x(bitLength-i)*power(2, i);
end
计算种群中每个个体的染色体的适应度,结果存放在fitValue中;
计算种群中每个个体的染色体被复制的累积概率,结果存放在cumsumP中
%fitnessFun.m
function [fitValue, cumsumP] = fitnessFun(population);
global bitLength;
global boundsBegin;
global boundsEnd;
popSize = size(population, 1); %种群中个体的个数
for i = 1:popSize
x = transform2To10(population(i,:));
xx = boundsBegin + x * (boundsEnd - boundsBegin)/(power(2,bitLength)-1);
fitValue(i) = targetFun(xx);
end
fitValue = fitValue' + 230;
fSum = sum(fitValue);
pPerPop = fitValue/fSum;
cumsumP(1) = pPerPop(1);
for i = 2:popSize
cumsumP(i) = cumsumP(i-1) + pPerPop(i);
end
进行选择操作(从原种群中选择出两个个体的染色体),以便得到新种群
%selectTwo.m
function selTwo = selectTwo(population, cumsumP);
for i=1:2
r = rand;
prand = cumsumP - r;
j = 1;
while prand(j)<0
j = j + 1;
end
selTwo(i) = j;
end
决定在遗传运算中是否需要进行交叉或变异过程
%ifCroIfMut.m
function p = ifCroIfMut(croOrMut);
test(1:100) = 0;
l = round(100*croOrMut);
test(1:l) = 1;
n = round(rand*99)+1;
p = test(n);
根据选择出的两个个体(这两个个体在新种群中)的染色体以及交叉概率进行交叉过程的到两个子代染色体
%crossoverTwo.m
function cTwo = crossoverTwo(population, selTwo, pC);
bitLength = size(population, 2);
p = ifCroIfMut(pC);
if p == 1
choice = round(rand*(bitLength-2))+1;
cTwo(1,:) = [population(selTwo(1),1:choice) population(selTwo(2), choice+1:bitLength)];
cTwo(2,:) = [population(selTwo(2),1:choice) population(selTwo(1), choice+1:bitLength)];
else
cTwo(1,:) = population(selTwo(1),:);
cTwo(2,:) = population(selTwo(2),:);
end
根据选择出的一个个体(这个个体在新种群中)的染色体以及变异概率进行变异过程
%mutateOne.m
function new = mutateOne(old, pM);
bitLength = size(old,2);
new = old;
p = ifCroIfMut(pM);
if p == 1
choice = round(rand*(bitLength-1)) + 1;
new(choice) = abs(old(choice)-1);
end
主体求解代码:
%GA.m
global bitLength;
global boundsBegin;
global boundsEnd;
bounds = [-2 2];
precision = 0.0001;
boundsBegin = bounds(:,1);
boundsEnd = bounds(:, 2);
bitLength = ceil(log2((boundsEnd - boundsBegin)'/precision));
popSize = 50;
generationN = 12;
pCrossover = 0.90;
pMutation = 0.09;
population = round(rand(popSize, bitLength));
[fitValue, cumsumP] = fitnessFun(population);
generation = 1;
while generation < generationN + 1
for j = 1:2:popSize
%选择两个个体
selTwo = selectTwo(population, cumsumP);
%交叉两个个体
cTwo = crossoverTwo(population, selTwo, pCrossover);
cNew(j,:) = cTwo(1,:);
cNew(j+1,:) = cTwo(2,:);
%变异两个个体
mNew(j,:) = mutateOne(cNew(j,:), pMutation);
mNew(j+1,:) = mutateOne(cNew(j+1,:), pMutation);
end
population = mNew;
[fitValue, cumsumP] = fitnessFun(population);
[fMax, nMax] = max(fitValue); %nMax为fitValue中所有元素的最大值fMax在向量fitValue中的索引
fMean = mean(fitValue); %求得fitValue中所有元素的平均值
yMax(generation) = fMax;
yMean(generation) = fMean;
x = transform2To10(population(nMax,:));
xx = boundsBegin + x * (boundsEnd - boundsBegin)/(power(2,bitLength)-1);
xMax(generation) = xx;
generation = generation + 1;
end
generation = generation - 1;
bestPopulation = xx;
bestTargetFunValue = targetFun(xx);
figure(1);
hand1 = plot(1:generation, yMax);
set(hand1,'linestyle', '-','linewidth', 1.8,'marker', '*', 'markersize', 6);
hold on;
hand2 = plot(1:generation, yMean);
set(hand2,'color', 'r','linestyle', '-','linewidth', 1.8,'marker', 'h', 'markersize', 6);
xlabel('进化代数'); ylabel('最大/平均适应度'); xlim([1 generationN]);
legend('最大适应度', '平均适应度');
box off; hold off;
四、求解结果