据说,可以用在很多领域。
先学习在函数优化方面的应用。
据说,对于非线性、多模型、多目标的函数优化问题,GA似乎可以得出不错的结果。
“优胜劣汰”。
基本操作:选择、交叉,变异。
每一个基本操作,又有很多种方法。
1. 选择。
根据适应度来选择。在函数优化问题中,为了找最大值,那适应度可以直接定义为f(x0),把某一个个体送入函数,该函数的输出结果。、
(1) 按比例的适应度计算
(2) 基于排序的适应度计算
选择一般有:
(1) 轮盘赌(目前我只知道这个。就像外面搞抽奖活动,一个盘,一根指针。你去转那个盘,最后指针会停在某个扇形上。不过一般都是谢谢惠顾。)
(2) 随机遍历抽样
(3) 局部选择
(4) 截断选择
(5) 锦标赛选择
2. 交叉。
结合父辈的信息,交配产生信的个体。根据个体编码方式不同,可以有:
(1) 实值重组
离散重组
中间重组
线性重组
扩展线性重组
(2) 二进制交叉
单点交叉(我只知道,
多点交叉 这两种)
均匀交叉
洗牌交叉
缩小代理交叉
3. 变异
对子代基因按小概率进行扰动。根据个体编码方式不同,可以有:
(1) 实值变异
(2) 二进制变异(如:对某个个体的二进制编码的某一位取反)
clear;
close all;
clc
%%
NP = 100;
NG = 100;
precision = 0.001;
prob_cross = 0.9;
prob_variation = 0.01;
x_low = 0;
x_high = 40;
[xv,fv] = my_GA1(@fitness,x_low,x_high,NP,NG,prob_cross,prob_variation,precision);
[xv,fv]
x = x_low:0.01:x_high;
for i = 1:length(x)
y(i) = fitness(x(i));
end
plot(x,y)
function [ res ] = fitness( x )
% function [ res ] = fitness( x )
% 这里直接把目标函数当做适应度
% 要找f(x) 在区间 [a,b] 上的最大值
res = (x^3 - 60 * x^2 + 900 * x + 100);
% res = (x - 1) * (x - 2)^2;
% res = sin(2*pi*x);
% res = -(x^2-20);
end
基本遗传算法
function [xv,fv]=my_GA1(fitness,a,b,NP,NG,Pc,Pm,eps)
L = ceil(log2((b-a)/eps+1)); %根据离散精度,确定二进制编码需要的码长
x = zeros(NP,L); % NP个个体,L是二进制编码的长度 % NP行,L列。每个个体用L位二进制代表其基因。
for i=1:NP
x(i,:) = Initial(L); %种群初始化 % x随便取-_-!
% fx 各个个体往目标函数里面代,返回值
fx(i) = fitness(Dec(a,b,x(i,:),L)); %个体适应值 --> 可以把个体往目标函数里面代 -_-!
end
fx = fx - min(fx); %%%%%%%%%%%%%%% 调整为全是正数!
for k=1:NG % 一共产生NG代
sumfx = sum(fx); %所有个体适应值之和
Px = fx/sumfx; %所有个体适应值的平均值 --> 不是平均值啊,是各个个体适应度的比例,个体的选择概率
PPx = 0;
PPx(1) = Px(1); % 这是累计概率
for i=2:NP %用于轮盘赌策略的概率累加
PPx(i) = PPx(i-1) + Px(i);
end
for i=1:NP % 轮转NP次,相当于是生了N个孩子
theta = rand(); % 每次轮转,就产生一个(0,1)的数,看落在哪个范围
for n=1:NP
if theta <= PPx(n) % 累计范围 --> 这种写法相当于是NP个if… -_-!
SelFather = n; %根据轮盘赌策略确定的父亲
break;
end
end
Selmother = floor(rand()*(NP-1))+1; %随机选择母亲(这段婚姻真随意,甚至会出现“自交”???自己和自己交配。。。?)
posCut = floor(rand()*(L-2)) + 1; %随机确定交叉点
r1 = rand();
if r1<=Pc % 以一定的概率,发生交叉 %交叉
nx(i,1:posCut) = x(SelFather,1:posCut); % 这种交叉的方法是,用父亲的前posCut & 母亲的后 posCut 相结合
nx(i,(posCut+1):L) = x(Selmother,(posCut+1):L);
r2 = rand();
if r2 <= Pm % 以一定的概率,发生变异 %变异
posMut = round(rand()*(L-1) + 1); % 变异的位置 这里是 1位
nx(i,posMut) = ~nx(i,posMut); % 这里的变异就是,某一位取反
end
else
nx(i,:) = x(SelFather,:); % 如果不交叉,子代染色体就是父代
end
end
x = nx; % 新的个体,重新赋值给了x
for i=1:NP
fx(i) = fitness(Dec(a,b,x(i,:),L)); %子代适应值
end
fx = fx - min(fx); %%%%%%%%%%%%%%% 调整为全是正数!
end
% 最后,在最终一代里面选,最佳适应的那个个体
fv = -inf;
for i=1:NP
fitx = fitness(Dec(a,b,x(i,:),L));
if fitx > fv
fv = fitx; %取个体中的最好值作为最终结果
xv = Dec(a,b,x(i,:),L);
end
end
function result = Initial(len) %初始化函数
for i=1:len
r = rand();
% X = rand returns a single uniformly
% distributed random number
% in the interval (0,1).
result(i) = round(r);
end
function y = Dec(a,b,x,L) %二进制编码转换为十进制编码
base = 2.^((L-1):-1:0);
y = dot(base,x);
y = a + y*(b-a)/(2^L-1);