介紹轉載自https://blog.csdn.net/xujinpeng99/article/details/6211597,後面用自己設置的函數進行實驗。
引言:遺傳算法求函數極值算是遺傳算法的一種最簡單的應用,這裏就介紹一種簡單的,全文基本翻譯自codeproject的一篇文章,作者爲Luay Al-wesi,軟件工程師。例子中的函數爲y = -x2+ 5 ,大家可以將其改爲其他複雜一些的函數,比如說f=x+10sin(5x)+7cos(4x)等。
一、編碼以及初始種羣的產生
編碼採用二進制編碼,初始種羣採用矩陣的形式,每一行表示一個染色體,每一個染色體由若干個基因位組成。關於染色體的長度(即基因位的個數)可根據具體情況而定。比如說根據要求極值的函數的情況,本文的染色體長度爲6,前5個二進制構成該染色體的值(十進制),第6個表示該染色體的適應度值。長度越長,表示解空間搜索範圍越大。關於如何將二進制轉換爲十進制,這個應該很簡單,文後的C代碼中函數x即爲轉換函數。
初始種羣結構如下圖所示:
圖1
該初始種羣共有4個染色體,第一列表示各個染色體的編號,第2列表示該染色體值的正負號,0表示正,1表示負。第3列到第7列爲二進制編碼,第8列表示各個染色體的適應度值。第2列到第7列的0-1值都是隨機產生的。
二、適應度函數
一般情況下,染色體(也叫個體,或一個解)的適應度函數爲目標函數的線性組合。本文直接以目標函數作爲適應度函數。即每個染色體的適應度值就是它的目標函數值,f(x)=-x2+ 5。
三、選擇算子
初始種羣產生後,要從種羣中選出若干個體進行交叉、變異,那麼如何選擇這些個體呢?選擇方法就叫做選擇算子。一般有輪盤賭選擇法、錦標賽選擇法、排序法等。本文采用排序法來選擇,即每次選擇都選出適應度最高的兩個個體。那麼執行一次選擇操作後,得到的新種羣的一部分爲下圖所示:
圖2
四、交叉算子
那麼接下來就要對新種羣中選出的兩個個體進行交叉操作,一般的交叉方法有單點交叉、兩點交叉、多點交叉、均勻交叉、融合交叉。方法不同,效果不同。本文采用最簡單的單點交叉。交叉點隨機產生。但是交叉操作要在一定的概率下進行,這個概率稱爲交叉率,一般設置爲0.5到0.95之間。交叉後產生的新個體組成的新種羣如下:
圖3
黑體字表示子代染色體繼承母代個體的基因情況。
五、變異
變異就是對染色體的結構進行變異,使其改變原來的結構(值也就改變),達到突變進化的目的。變異操作也要遵從一定的概率來進行,一般設置爲0到0.5之間。本文的變異方法直接採取基因位反轉變異法,即0變爲1,1變爲0。要進行變異的基因位的選取也是隨機的。
六、終止規則
遺傳算法是要一代一代更替的,那麼什麼時候停止迭代呢?這個規則就叫終止規則。一般常用的終止規則有:若干代後終止,得到的解達到一定目標後終止,計算時間達到一定限度後終止等方法。本文采用迭代數來限制。
%VELASCO, Gimel David F.
%2012-58922
%Cmsc 191
%Genetic Algorithm
%Final Exam
%for runs=1:3
clear;
tic;
%%%%%%%%%%%%%%%%%%%%%%%%%%%INPUT ARGUMENTS%%%%%%%Sir Joel, dito po%%%%%%%%%
CostF =2; % | 1 - DE JONGS | 2 - AXIS PARALLEL HYPER-ELLIPSOID | 3 - ROTATED HYPER-ELLIPSOID | 4 - RASTRIGINS | ow - ACKLEYS |
nVar = 3; %number of dimensions
VarSize = zeros(nVar); %stores the fittest chromosome per iteration
VarMin = -5.12; %upper bound of variable value
VarMax = 5.12; %lower bound of variable value
MaxGen = 100000; %maximum number of generations
nPop = 5000; %chromosome population
nSel = 1; % | 1 - Tournament Selection | ow - Roulette Wheel Selection |
mu = 0.1; %mutation rate
sigma = 0.25; %crossover rate
cxver= 2; % | 1 - Single point Crossover | ow - Three point Crossover |
tol = 0.0000025; %fitness tolerance (minimization problem)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%STEP 1: Initialization
test_func = CostF;
ub = VarMax;
lb = VarMin;
ulb = ub; %temporary bengat
tpl = nVar;
popsize = nPop; %Population Size
maxgens = MaxGen; %Maximum Generations
pc = sigma; %crossover rate
pm = mu; %mutation rate
%tol = tol; %tolerance
iteration_array = zeros(1);
fittest_array = zeros(1);
solution_array = VarSize;
Chromosome = zeros(popsize,tpl);
for i=1:popsize
Chromosome(i,:) = 2*ulb*(rand(1,tpl)-0.5); %initializing first generation
end
%%%%%%%%%%%%%%%%%%%%%%%%%GENETIC ALGORITHM%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
for generation=1:maxgens %LOOPS STEPS 2 to 5(最大的迭代次數)
%STEP 2: Selection
if nSel == 1
%(錦標賽選擇法)
for i=1:popsize/4 %Tournament process
red = abs(floor(popsize*rand(1))) + 1; %兩個隨機染色體
blu = abs(floor(popsize*rand(1))) + 1;
if OBJFUNC(Chromosome(red,:),tpl,test_func) > OBJFUNC(Chromosome(blu,:),tpl,test_func) %competition
Chromosome(red,:) = Chromosome(blu,:); %Blue Wins the tournament and overwrites Red
else
Chromosome(blu,:) = Chromosome(red,:); %Red Wins the tournament and overwrites Blue
end
end
else
%輪盤賭選擇法
F_obj = zeros(1);
for i=1:popsize
F_obj(i) = OBJFUNC(Chromosome(i,:),tpl,test_func);
end
Total = 0;
Fitness = zeros(1);
P = zeros(1);
C = zeros(1);
R = zeros(1);
NewChromosome = zeros(tpl);
for i=1:popsize
Fitness(i) = 1/(1+F_obj(i));
Total = Total + Fitness(i);
end
for i=1:popsize
P(i) = Fitness(i)/Total;
end
ctr = 0;
for i=1:popsize
ctr = ctr + P(i);
C(i) = ctr;
end
for i=1:popsize
R(i) = rand(1);
end
for i=1:popsize
NewChromosome(i,:) = zeros(1,tpl);
for j=1:popsize-1
if R(i) > C(j) && R(i) <= C(j+1)
NewChromosome(i,:) = Chromosome(j,:);
end
end
if NewChromosome(i,:) == zeros(1,tpl)
NewChromosome(i,:) = Chromosome(1,:);
end
end
for i=1:popsize
Chromosome(i,:) = NewChromosome(i,:);
end
end
%%
R = rand(1,popsize);
k = zeros(1);
PChromosome = zeros(tpl);
cp = zeros(1);
cp3 = zeros(3);
ctr = 0; %holds number of parents
for i=1:popsize
if R(i) < pc
%選擇父代
ctr = ctr + 1;
k(ctr) = i; %will save the positions of the parent chromosomes
PChromosome(ctr,:) = Chromosome(i,:);
end
end
if ctr == 0 %if no parents were selected for the next generation
continue;
end
%%
%STEP 3: 交叉
if cxver == 1 %單點交叉
for i=1:ctr
cp(i) = floor(abs((tpl-1)*rand(1)))+1; %crossover points
end
for i=1:ctr-1
Chromosome(k(i),:) = CROSSOVER(PChromosome(i,:),PChromosome(i+1,:),cp(i),tpl); %crossover ci and ci+1
end
Chromosome(k(ctr),:) = CROSSOVER(PChromosome(ctr,:),PChromosome(1,:),cp(ctr),tpl); %crossover ck and c1
else %三點交叉
for i=1:ctr
cp3(i,:) = floor(abs((tpl-1)*rand(1,3)))+1; %crossover points
end
for i=1:ctr-1
Chromosome(k(i),:) = CROSSOVER3(PChromosome(i,:),PChromosome(i+1,:),cp3(i,:),tpl); %crossover ci and ci+1
end
Chromosome(k(ctr),:) = CROSSOVER3(PChromosome(ctr,:),PChromosome(1,:),cp3(ctr,:),tpl); %crossover ck and c1
end
%%
%STEP 4: 變異
%Per Chromosome mutation
mu = round(pm*popsize); %#ofchromosomestomutate = mutationrate*populationsize
for i=1:mu
cngn = abs(floor(popsize*rand(1))) + 1; %random popsize number
q = OBJFUNC(Chromosome(cngn,:),tpl,test_func);
if q < 1
Chromosome(cngn,:) = 2*ulb*q*(rand(1,tpl)-0.5); %mutation
else
Chromosome(cngn,:) = 2*ulb*(rand(1,tpl)-0.5);
end
end
%%
%STEP 5: 終止評價
F_obj = zeros(1);
for i=1:popsize
F_obj(i) = OBJFUNC(Chromosome(i,:),tpl,test_func);
end
%%
fittest = F_obj(1);
for i=1:popsize
fi = 1;
if fittest > F_obj(i)
fittest = F_obj(i);
fi = i;
end
end
%fprintf('Fittest: %.16f\t\tRuntime: %.2f seconds\n',fittest,toc);
%disp(Chromosome(fi,:))
fittest_array(generation) = fittest;
iteration_array(generation) = generation;
solution_array(generation,:) = Chromosome(fi,:);
if fittest < tol %&& abs(DECODE(Chromosome(fi,:),tpl) - round(DECODE(Chromosome(fi,:),tpl))) < 0.00005
break;
end
%Step 6: 重複進行代數迭代
end
%%
%STEP 7: 得出最優染色體
if test_func == 1
fprintf('====================DE JONGS FUNCTION=============================\n');
elseif test_func == 2
fprintf('==============AXIS PARALLEL HYPER-ELLIPSOID FUNCTION==============\n');
elseif test_func == 3
fprintf('===============ROTATED HYPER-ELLIPSOID FUNCTION====================\n');
elseif test_func == 4
fprintf('====================RASTRIGINS FUNCTION===========================\n');
else
fprintf('=====================ACKLEYS FUNCTION=============================\n');
end
fprintf('====================GENETIC ALGORITHM=============================\n');
if nSel == 1
fprintf('Tournament Selection. ');
else
fprintf('Roulette-Wheel Selection. ');
end
if cxver == 1
fprintf('Single Point Crossover.\n');
else
fprintf('Triple Point Crossover.\n');
end
fprintf('===================Generations: %d\tPopulation: %d===========\n',maxgens,popsize);
%fprintf('Final Generation\n');
%Chromosome = SORT(Chromosome,popsize,tpl,test_func);
%disp(Chromosome)
fprintf('Generation Number: %d\nPopulation Size: %d\nCrossover Rate: %.2f\nMutation Rate: %.2f\nDimensions: %d\n',maxgens,popsize,pc,pm,tpl);
%fprintf('\nThe Fittest Chromosome is\n');
%disp(Chromosome(fi,:)')
%fprintf('Using Tournament Selection\n');
fprintf('Fitness Function Value of %.16f\nTotal Runtime of %f seconds\n',fittest,toc);
fprintf('The Root for Test Function %d is:\n',test_func);
disp(Chromosome(fi,:))
fprintf('==================================================================\n');
%%
figure
subplot(2,1,1);
plot(iteration_array,fittest_array);
legend('Cost Function Value');
xlabel('Generation');
ylabel('Fitness of fittest Chromosome');
solution_array = transpose(solution_array);
subplot(2,1,2);
plot(iteration_array,solution_array);
xlabel('Generation');
ylabel('Solution of fittest Chromosome');
%%
%end
結果: