遗传算法理论
遗传算法是模拟生物演化理论的最优求解算法。生物演化是一种群为基础的,组成种群的单个生物,生物都有过度繁殖的倾向,而种群的可利用的资源是有限的,因此对环境适应度高的、牛B的个体参与繁殖的机会比较多,后代就会越来越多。适应度低的个体参与繁殖的机会比较少,后代就会越来越少。,生物繁殖时会伴随着染色体的重新组合和基因变异,经过长时间的演化,才呈现出现在的生态系统。
简答来说,可分为以下几条:
- 生物进化的基础是种群
- 种群都有过度繁殖倾向
- 繁殖过程中会有染色体交叉组合
- 繁殖过程中会有基因变异
- 只有适应环境的个体才具有较多的繁殖机会
遗传算法也具备这几个特征:即繁殖、变异、重组、选择等,当然遗传算法还有编码和译码的过程。
繁殖(Crossover):种群中个体复制,适应度高的个体繁殖机会大
变异(Crossover):种群中某个体的某基因变异,即个体的某一位取反
变异前:
000001110000 0 00010000
变异后:
000001110000 1 00010000
重组(Crossover):2条染色体交换部分基因,来构造下一代的2条新的染色体
重组前:
00000|011100000000|10000
11100|000001111110|00101
重组后:
00000|000001111110|10000
11100|011100000000|00101
遗传算法程序示例
关于遗传算法的机理以及相关参考资料很多,这里给出一个基本的程序参考脚本,可以在这个基础上改动使用。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import numpy as np
import random
class Population(object):
"""
类名:population
功能:遗传算法类
参数:popsize 种群大小
chromlength 字符串长度
pc 交叉概率
pm 变异概率
pop 群体编码
作者:犇丿灬犇
"""
def __init__(self,popsize=20,chromlength=10,pc=0.6,pm=0.001):
self._popsize=popsize
self._chromlength=chromlength
self._pc=pc
self._pm=pm
self._pop=self.__popinit()
#np.around(np.random.random(size=(popsize,chromlength)))
def __popinit(self):
"""
函数名:__popinit 私有函数
功能:种群编码
返回值:行为种群数量,列为字符串长度的数列
"""
pop=np.random.random(size=(self._popsize,self._chromlength))
pop=np.around(pop)
return pop
def decodebinary(self,pop):
"""
函数名:decodebinary
功能:将二进制数转化为十进制
返回值:十进制数
"""
px, py = pop.shape
pop1 = []
for i in range(py):
mid_var=2**(py-i-1)*pop[:,i]
pop1.append(mid_var)
pop1= np.array(pop1)
pop2=sum(pop1)
return pop2
def decodechrom(self,pop,spoint,length):
"""
函数名:decodechrom
功能:取字符串中几位转为十进制
返回值:十进制数
"""
py=self._chromlength
try:
pop1=pop[:,spoint:spoint+length]
pop2 = self.decodebinary(pop1)
except:
pop1=pop[spoint:spoint+length]
for i in range(py):
pop1[i] = 2 ** (py - i - 1) * pop[i]
pop2 = sum(pop1)
return pop2
def crossover(self,pop):
"""
函数名:crossover
功能:交叉
返回值:交叉后种群
"""
px, py = pop.shape
newpop=np.ones(shape=(px,py))
for i in range(px-1):
if i%2:
mid_var = random.random()
if mid_var<self._pc:
cpoint=round(mid_var*py)
'''
col_var=np.array([pop[i,:cpoint],
pop[i+1,cpoint:py]])
col_var.resize(py)
print(col_var)
'''
col_var=np.zeros(py)
col_var[:cpoint]=pop[i,:cpoint]
col_var[cpoint:py]=pop[i+1,cpoint:py]
newpop[i,:]=col_var
'''
col_var=np.array([pop[i+1,:cpoint],
pop[i,cpoint:py]])
col_var.resize(py)
'''
col_var[:cpoint] = pop[i+1, :cpoint]
col_var[cpoint:py] = pop[i , cpoint:py]
newpop[i+1,:]=col_var
else:
newpop[i,:]=pop[i,:]
newpop[i+1, :] = pop[i+1, :]
return newpop
def mutation(self,pop):
"""
函数名: mutation
功能:变异
返回值:变异后种群
"""
px, py = pop.shape
newpop = np.ones(shape=(px, py))
for i in range(px):
mid_var = random.random()
if mid_var<self._pm:
mpoint=round(mid_var*py)
if mpoint<=0:
mpoint=1
newpop[i,:]=pop[i,:]
if newpop[i,mpoint]==0:
newpop[i, mpoint]=1
elif newpop[i,mpoint]==1:
newpop[i, mpoint]=0
else:
newpop[i, :] = pop[i, :]
return newpop
def selection(self,pop,fitvalue):
"""
函数名: selection
功能: 选择复制
返回值: 返回新种群
"""
totalfit=sum(fitvalue)
fitvalue=fitvalue/totalfit
fitvalue=np.cumsum(fitvalue)
px, py = pop.shape
ms=np.random.random(px)
ms=np.sort(ms)
fitin=0
newin=0
newpop = np.ones(shape=(px, py))
while newin<px:
if ms[newin]<fitvalue[fitin]:
newpop[newin]=pop[fitin]
newin+=1
else:
fitin+=1
return newpop
def best(self, pop, fitvalue):
"""
函数名: best
功能: 求适应度最大的值
返回值: 最大值适应值,最大个体
"""
px, py = pop.shape
bestindividual=pop[0,:]
bestfit=fitvalue[0]
for i in range(px):
if fitvalue[i]>bestfit:
bestfit=fitvalue[i]
bestindividual=pop[i,:]
return bestfit,bestindividual
应用实例
求函数
y=10×sin(5×x)+7×cos(4×x) y = 10 × sin ( 5 × x ) + 7 × cos ( 4 × x )
的最大值。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from Genetic_algorithm import *
from math import *
import numpy as np
def calfitvalue(objvalue):
Cmin=0
x=objvalue.size
fitvalue = np.zeros(x)
for i in range(x):
if objvalue[i]+Cmin>0:
temp=objvalue[i]+Cmin
else:
temp=0
fitvalue[i]=temp
return fitvalue
def calobjvalue(c_pop):
temp1=c_pop.decodechrom(c_pop._pop,0,c_pop._chromlength)
x=temp1*10/1023
obvalue=10*np.sin(5*x)+7*np.cos(4*x)
#obvalue = -x**2+10*x+8
return obvalue
if __name__ == '__main__':
c_pop=Population(popsize=20,chromlength=10,pc=0.8,pm=0.001)
iter_i=100
x = np.zeros(iter_i)
y=np.zeros(iter_i)
for i in range(iter_i):
objvalue=calobjvalue(c_pop)
fitvalue =calfitvalue(objvalue)
newpop=c_pop.selection(c_pop._pop,fitvalue)
newpop=c_pop.crossover(newpop)
newpop=c_pop.mutation(newpop)
bestfit,bestindividual=c_pop.best(c_pop._pop,fitvalue)
#print(bestindividual,bestfit)
x[i]=c_pop.decodechrom(bestindividual,0,c_pop._chromlength)*10/1023
y[i]=bestfit
c_pop._pop=newpop
print(x,y)
print(max(y))
结果
MATLAB工具包
matlab提供遗传算法工具包。曾经用它做过多智能体预测控制算法参数配置。要求矩阵
Ω=(AD+Bkyec+BakcCD−JN⊗C1BkzI)(1491) (1491) Ω = ( A D + B k y e c + B a k c B k z C D − J N ⊗ C 1 I )
的特征值在单位圆内。其中
AD=diag(A1,A2...AN)(1492) (1492) A D = d i a g ( A 1 , A 2 . . . A N )
Bkyec=diag(B1(Ky1+l11Ke1)C2,B2(Ky2+l22Ke2)C2,...,BN(KyN+lNNKeN)CN)(1493) (1493) B k y e c = d i a g ( B 1 ( K 1 y + l 11 K 1 e ) C 2 , B 2 ( K 2 y + l 22 K 2 e ) C 2 , . . . , B N ( K N y + l N N K N e ) C N )
Bakc=(B1(Ky1+l11Ke1)C2,B2(Ky2+l22Ke2)C2,...,BN(KyN+lNNKeN)CN)(1494) (1494) B a k c = ( B 1 ( K 1 y + l 11 K 1 e ) C 2 , B 2 ( K 2 y + l 22 K 2 e ) C 2 , . . . , B N ( K N y + l N N K N e ) C N )
Bakc=⎛⎝⎜⎜⎜⎜⎜a11B1Ke1C1a21B2Ke2C1⋮aN1BNKeNC1a12B1Ke1C2a22B2Ke2C2⋮aN2BNKeNC2⋯⋯⋱⋯a1NB1Ke1CNa2NB2Ke2CNaNNBNKeNCN⎞⎠⎟⎟⎟⎟⎟(1495) (1495) B a k c = ( a 11 B 1 K 1 e C 1 a 12 B 1 K 1 e C 2 ⋯ a 1 N B 1 K 1 e C N a 21 B 2 K 2 e C 1 a 22 B 2 K 2 e C 2 ⋯ a 2 N B 2 K 2 e C N ⋮ ⋮ ⋱ a N 1 B N K N e C 1 a N 2 B N K N e C 2 ⋯ a N N B N K N e C N )
Bkz=diag(B1Kz1,B2Kz2,...,BNKzN)(1496) (1496) B k z = d i a g ( B 1 K 1 z , B 2 K 2 z , . . . , B N K N z )
CD=diag(C1,C2...CN)(1497) (1497) C D = d i a g ( C 1 , C 2 . . . C N )
JN=[[0,1,...,1]T,0n×(n−1)](1498) (1498) J N = [ [ 0 , 1 , . . . , 1 ] T , 0 n × ( n − 1 ) ]
具体数值见参考文献[1],具体做法,如果矩阵Ω Ω 的特征值都在单位圆内,则绝对值最大的特征值应该也在单位圆内,只要不断优化其最大绝对值特征值即可,代码如下:
计算矩阵Ω Ω :
A_W=[0 1 1; 1 0 1; 1 1 0];
A1=[1.7 -1.3;1.6 -1.8];
B1=[1.0;2.0];
C1=[1.0 0.3];
A2=[1.8 -1.4;1.8 -1.9];
B2=[1.7 ;3.4];
C2=[0.7 0.2];
A3=[1.4 -1.1;1.3 -1.5];
B3=[0.8;1.6];
C3=[1.1 0.4];
T=0.1;
% [A1,B1]=c2d(A1,B1,T);
% [A2,B2]=c2d(A2,B2,T);
% [A3,B3]=c2d(A3,B3,T);
% z_root=[0.5-0.5i 0.5+0.5i 0.7+0.1i 0.7-0.1i 0.6+0.2i 0.6-0.2i -0.3+0.3i -0.3-0.3i];
% expand((z-z_root(1))*(z-z_root(2))*(z-z_root(3))*(z-z_root(4))*(z-z_root(5))*(z-z_root(6))*(z-z_root(7))*(z-z_root(8)))
AD=blkdiag(A1,A2,A3);
Bkyec=blkdiag(B1*(ky1+lii(A_W,1)*ke1)*C1,B2*(ky1+lii(A_W,2)*ke1)*C2,B3*(ky1+lii(A_W,3)*ke1)*C3);
Bakc=[A_W(1,1)*B1*ke1*C1 A_W(1,2)*B1*ke1*C2 A_W(1,3)*B1*ke1*C3;A_W(2,1)*B2*ke1*C1 A_W(2,2)*B2*ke1*C2 A_W(2,3)*B2*ke1*C3;A_W(3,1)*B3*ke1*C1 A_W(3,2)*B3*ke1*C2 A_W(3,3)*B3*ke1*C3];
Bkz=blkdiag(B1*kz1,B2*kz1,B3*kz1);
CD=blkdiag(C1,C2,C3);
JN=[[0;1;1],zeros(3,2)];
Omg=[AD+Bkyec+Bakc Bkz;CD-kron(JN,C1) eye(3)];
% Root=eig(Omg)
function y=lii(A,i)
S=sum(A,2);
y=-S(i);
end
遗传算法
clc
clear
NIND=40; %个体数目(Number of individuals)
MAXGEN=50; %最大遗传代数(Maximum number of generations)
PRECI=20; %变量的二进制位数(Precision of variables)
GGAP=0.9; %代沟(Generation gap)
trace=zeros(4, MAXGEN); %寻优结果的初始值
FieldD=[PRECI PRECI PRECI;-1 -1 -1;1 1 1;1 1 1;0 0 0;1 1 1;1 1 1]; %区域描述器(Build field descriptor)表示染色体个体到实际的数字的映射关系
Chrom=crtbp(NIND, PRECI*3); %初始种群
gen=0; %代计数器
YZE=bs2rv(Chrom, FieldD); %计算初始种群的十进制转换
Y=YZE(:,1);
Z=YZE(:,2);
E=YZE(:,3);
ObjV=zeros(40,1);
%%%%%%计算模最大的特征值%%%%%%%%%%%%%%%%%%%%
for i=1:40
ky1=Y(i);
kz1=Z(i);
ke1=E(i);
cal
Root=eig(Omg);
Mroot=abs(Root);
ObjV(i)=max(Mroot);
end
%ObjV=-variable.*(variable - 4); %计算目标函数值
while gen<MAXGEN
FitnV=ranking(ObjV); %分配适应度值(Assign fitness values)
SelCh=select('sus', Chrom, FitnV, GGAP); %选择
SelCh=recombin('xovsp', SelCh, 0.7); %重组
SelCh=mut(SelCh); %变异
YZE=bs2rv(SelCh, FieldD); %子代个体的十进制转换
Y=YZE(:,1);
Z=YZE(:,2);
E=YZE(:,3);
ObjVSel=zeros(NIND*GGAP,1);
for i=1:NIND*GGAP
ky1=Y(i);
kz1=Z(i);
ke1=E(i);
cal
Root=eig(Omg);
Mroot=abs(Root);
ObjVSel(i)=max(Mroot);
end
%variable=bs2rv(SelCh, FieldD); %子代个体的十进制转换
%ObjVSel=-variable.*(variable - 4);%计算子代的目标函数值
[Chrom ObjV]=reins(Chrom, SelCh, 1, 1, ObjV, ObjVSel);
%重插入子代的新种群
variable=bs2rv(Chrom, FieldD);
gen=gen+1; %代计数器增加
%输出最优解及其序号,并在目标函数图像中标出,Y为最优解,I为种群的序号
[Y, I]=min(ObjV);%hold on;
%plot(variable(I), Y, 'bo');
fprintf('%f,%f,%f %f\n',variable(I,1),variable(I,2),variable(I,3),Y);
trace(1, gen)=min(ObjV); %遗传算法性能跟踪
trace(2, gen)=sum(ObjV)/length(ObjV);
end
variable=bs2rv(Chrom, FieldD); %最优个体的十进制转换
%hold on, grid;
%plot(variable,ObjV,'b*');
figure(1);
plot(trace(1,:));
hold on;
plot(trace(2,:),'-.');grid
legend('解的变化','种群均值的变化')
结果