python实现的遗传算法实例(一) ! T5 m( ~- h- x) P ( v) l' g3 d$ C# A6 G6 y. z一、遗传算法介绍 ) b$ k% n5 ?/ { q/ @ # j/ p) |: g7 x* p' M; ^% R. l 遗传算法是通过模拟大自然中生物进化的历程,来解决问题的。大自然中一个种群经历过若干代的自然选择后,剩下的种群必定是适应环境的。把一个问题所有的解看做一个种群,经历过若干次的自然选择以后,剩下的解中是有问题的最优解的。当然,只能说有最优解的概率很大。这里,我们用遗传算法求一个函数的最大值。 / F" z. y$ d* U- [ f(x) = 10 * sin( 5x ) + 7 * cos( 4x ), 0 <= x <= 102 \: M) l, X/ Z X- i0 D! y0 _
& P4 L1 @1 y3 t3 c
1、将自变量x进行编码 - {5 S1 [& W+ o8 ~+ j. t* G! q q' t# m
取基因片段的长度为10, 则10位二进制位可以表示的范围是0到1023。基因与自变量转变的公式是x = b2d(individual) * 10 / 1023。构造初始的种群pop。每个个体的基因初始值是[0, 1, 0, 1, 0, 1, 0, 1, 0, 1] 1 H* Y2 W% W1 |. j9 h ' }7 V p8 `9 I' S2、计算目标函数值 % b# z0 s1 u% N" X( N* W' N6 ?# Z/ q# O; z" Z7 a
根据自变量与基因的转化关系式,求出每个个体的基因对应的自变量,然后将自变量代入函数f(x),求出每个个体的目标函数值。! S$ z% l- P6 s1 [& o
% L# s. X* s( P2 C3、适应度函数* y3 s0 t$ Y2 k
X' S* D! o. g2 N# ~" L" }2 ? 适应度函数是用来评估个体适应环境的能力,是进行自然选择的依据。本题的适应度函数直接将目标函数值中的负值变成0. 因为我们求的是最大值,所以要使目标函数值是负数的个体不适应环境,使其繁殖后代的能力为0.适应度函数的作用将在自然选择中体现。( v Q0 X- P- N9 t$ Y
- g) s c0 S) p! P9 t$ \4、自然选择 7 M3 I+ _. A7 o0 Z" O6 Z % R) o4 E" [4 k( `* _% n自然选择的思想不再赘述,操作使用轮盘赌算法。其具体步骤:7 Y( X4 S8 j" h0 h' E" i& v4 Z d
7 M% o, W+ K2 k1 ^
假设种群中共5个个体,适应度函数计算出来的个体适应性列表是fitvalue = [1 ,3, 0, 2, 4] ,totalvalue = 10 , 如果将fitvalue画到圆盘上,值的大小表示在圆盘上的面积。在转动轮盘的过程中,单个模块的面积越大则被选中的概率越大。选择的方法是将fitvalue转化为[1 , 4 ,4 , 6 ,10], fitvalue / totalvalue = [0.1 , 0.4 , 0.4 , 0.6 , 1.0] . 然后产生5个0-1之间的随机数,将随机数从小到大排序,假如是[0.05 , 0.2 , 0.7 , 0.8 ,0.9],则将0号个体、1号个体、4号个体、4号个体、4号个体拷贝到新种群中。自然选择的结果使种群更符合条件了。: y, P# z7 L" j4 U' ^) l
& H8 P W% \$ n N+ K- J2 N' U
5、繁殖 + v8 @2 s; M: i2 Q1 z0 L % A5 [3 m0 j1 ^, r+ p: h假设个体a、b的基因是1 R1 u# q$ _* A' _0 s: A4 z
% D2 ~% C. a% [. P# x9 Va = [1, 0, 0, 0, 0, 1, 1, 1, 0, 0]* e9 Y! f3 v5 X1 \( \$ n' Y# y
8 k `# ]) d9 [1 Z, W
b = [0, 0, 0, 1, 1, 0, 1, 1, 1, 1]: J1 ~. U: B& O# A* W8 W7 W
3 V; m; G3 E$ r& d( P
这两个个体发生基因交换的概率pc = 0.6.如果要发生基因交换,则产生一个随机数point表示基因交换的位置,假设point = 4,则: 2 M0 X, E% L, g3 w6 `- W $ f% V5 D' i, v( @, s' o* ^a = [1, 0, 0, 0, 0, 1, 1, 1, 0, 0]; g1 o8 p6 Z# `* D* y5 ?/ L
* ?' P9 ]4 B# T: @b = [0, 0, 0, 1, 1, 0, 1, 1, 1, 1] 0 c3 ~/ K: k2 s4 F, ?8 Q* ] k! k& s- u1 B( f7 X3 ?+ i! F- @
交换后为:) q. J# p. q! Y' Q* p+ |3 U, H7 O
( |( N9 c- h' h$ P1 x) P3 S. q% m0 V
a = [1, 0, 0, 0, 1, 0, 1, 1, 1, 1]# I6 U* O( }# ~& U: k0 h
]0 G' z2 m* L, f
b = [0, 0, 0, 1, 0, 1, 1, 1, 0, 0] 6 X; ~4 N$ D# Q$ `; T- M% a2 f! t n, `" {1 d1 k
6、突变2 n4 N7 t2 K+ o, O3 m- C
1 r' O3 j- o7 i+ ^遍历每一个个体,基因的每一位发生突变(0变为1,1变为0)的概率为0.001.突变可以增加解空间/ S1 U, u2 b* l# L D/ U
# i) X6 j# a4 f6 \* I" g) {二、代码( w/ l$ |0 H! v' u ]1 K1 n8 q& N$ N
def b2d(b): #将二进制转化为十进制 x∈[0,10] $ p' J) v/ b5 h5 C1 `* j t = 0 3 ^( S8 \' S6 T5 e" t, f for j in range(len(b)): 6 d$ T( b8 O) k; P/ g% ?) [ @- ?1 w t += b[j] * (math.pow(2, j))9 @$ H+ d: R8 `' ^2 y
t = t * 10 / 10230 g) L, l5 l u) E
return t# A) j. h9 e0 d* c, i, `9 G# b& Z$ }
- j3 {9 j; Q; I
popsize = 50 #种群的大小 % p2 Z7 c7 _ H- }* V; z#用遗传算法求函数最大值: 7 [$ t( J, p) `6 b+ j7 D5 n; p#f(x)=10*sin(5x)+7*cos(4x) x∈[0,10]* X7 s% o% s# O( j; i6 e1 u+ |
3 [ O9 |0 m2 ~) ichromlength = 10 #基因片段的长度 ) @2 q; i D1 X8 L: m( P+ Rpc = 0.6 #两个个体交叉的概率& r0 D$ | O3 u* v
pm = 0.001; #基因突变的概率6 L$ a$ J8 [7 B4 U! M
results = [[]] 1 Z( @/ a; F' A4 P& W. ]3 _- @- gbestindividual = [] # T6 D. S0 N, q" I1 y/ \bestfit = 0 3 D" l+ t9 b4 O- \% B$ a5 Ufitvalue = [] 7 b0 K5 B4 w: x4 c" jtempop = [[]]/ T9 m# }7 X, R& U# f& {
pop = [[0, 1, 0, 1, 0, 1, 0, 1, 0, 1] for i in range(popsize)]2 G8 J( H% T7 {" K+ U
for i in range(100): #繁殖100代 ' b& a: H, n9 i objvalue = calobjvalue(pop) #计算目标函数值) r# o" g8 V8 u) p" H5 ^
fitvalue = calfitvalue(objvalue); #计算个体的适应值* v, { C/ Y% ?, E6 E( n
[bestindividual, bestfit] = best(pop, fitvalue) #选出最好的个体和最好的函数值0 ?/ Q7 y( w3 U1 X& X& ?
results.append([bestfit,b2d(bestindividual)]) #每次繁殖,将最好的结果记录下来; E8 q5 a C: h" Y! ^
selection(pop, fitvalue) #自然选择,淘汰掉一部分适应性低的个体' p, T8 c$ w: e$ d) J
crossover(pop, pc) #交叉繁殖 ! e' F- c4 X7 q8 a$ C$ M mutation(pop, pc) #基因突变3 G( v5 a7 {4 S w
) Q5 U" a1 O" L$ G/ @ $ V9 h i+ o( P# B' K8 R+ L( oresults.sort() . s/ G I) a# vprint(results[-1]) #打印函数最大值和对应的, u, t; E$ g3 ]; J M. j
def calfitvalue(objvalue):#转化为适应值,目标函数值越大越好,负值淘汰。 ( t) d9 O/ I" w, t* s' E fitvalue = [] ) y" j6 j- b! X# T2 d temp = 0.0 z" u0 b. L4 j% U9 J Cmin = 0;' q! k U* E( l" R
for i in range(len(objvalue)):1 }( N0 w1 P- J6 H4 w
if(objvalue + Cmin > 0): ! Q5 v0 l) K2 [8 Y temp = Cmin + objvalue! x1 l- i8 K* R( s$ t
else: % B2 u7 X: W1 p, i temp = 0.03 i+ Y A, I- P. ~9 Q4 T; o$ X
fitvalue.append(temp) & I$ `! ?, Q( o! V* }6 q return fitvalue R+ B, `" d5 [import math 9 w6 }( J' h: t0 l g$ N& m 0 f& T G* @0 M2 |0 W* K+ ddef decodechrom(pop): #将种群的二进制基因转化为十进制(0,1023) 9 s$ Y0 S) P: Q+ W" X G3 } temp = [];$ P7 H% ]8 D9 {8 A
for i in range(len(pop)): : w% C) @& _* p( T. @ W( @ ?8 W9 z t = 0;# ?. I3 v- u M- M
for j in range(10): 7 e: Y5 F/ Y/ P. X- p' }. \ t += pop[j] * (math.pow(2, j)) 7 j; f' \' ~- f1 N temp.append(t)0 o o0 t# h; r1 F8 R! D5 b
return temp l3 r1 a2 M( Z* a. }' L/ P
5 g# C Y, [! V8 Tdef calobjvalue(pop): #计算目标函数值7 \/ ~9 y" [' r- X: L, P# M
temp1 = []; 6 N: N) C- y% U9 Q0 r3 R& e: a/ L objvalue = [];6 f! ?! s( @# `7 m) Q% Q
temp1 = decodechrom(pop) . m5 D8 ~" X, [, L! h for i in range(len(temp1)): 1 z* c; J X; B7 j7 I x = temp1 * 10 / 1023 #(0,1023)转化为 (0,10): Z8 I! i; I# Z& D p
objvalue.append(10 * math.sin(5 * x) + 7 * math.cos(4 * x))) N5 g$ S, i2 R% l! ^: i
return objvalue #目标函数值objvalue[m] 与个体基因 pop[m] 对应 6 p! o6 O' z# N) A3 }
def best(pop, fitvalue): #找出适应函数值中最大值,和对应的个体# z1 O4 @2 g; y+ M7 K0 V% @8 ?
px = len(pop) # z! E3 A' Z( C) J$ t bestindividual = [] 8 x( s# w' y. s d+ `" h' H bestfit = fitvalue[0] 0 T6 a% H L5 t for i in range(1,px): ) Y+ n3 V% w9 g) n if(fitvalue > bestfit): 5 ?! Y' j& I$ w) V K* w0 b9 { bestfit = fitvalue8 k, c) m4 D0 v; _
bestindividual = pop7 V- I6 o, G1 ]. [$ N! j. x
return [bestindividual, bestfit]" N3 X* ` z! X, c! I8 h) {
import random% X3 Z) d5 ~! P+ b7 g1 r
6 y9 U) @; y+ q( F3 fdef sum(fitvalue):9 a7 Y/ I7 A" P3 P% q2 u0 B
total = 0 ; L$ x& S ]+ ^ for i in range(len(fitvalue)):8 U3 p1 c7 R3 s) b+ ?$ l& z6 x
total += fitvalue9 i9 B. a% u$ a: w+ q
return total! P% r* T$ l! y. a# s) s
( B- }2 p6 j8 c T0 i! J
def cumsum(fitvalue): 7 }9 h* M6 q: L( Q1 C for i in range(len(fitvalue)): ' X- Z) o4 W7 a8 P t = 0; ( w- }+ k- R8 R- i" ^9 V j = 0;: G7 k" x# C+ T
while(j <= i): 5 p1 e" ^5 X" h3 O. H# Y( l* w2 f t += fitvalue[j] : \1 O- w3 j" f; @) A7 k4 W5 ]5 F7 t j = j + 10 s7 ]' F z( J& r& o& h0 T8 Z! Y
fitvalue = t;0 P1 t! ]" K; C' j7 V5 K# p
/ f' M' J9 V; q1 l% [ t
def selection(pop, fitvalue): #自然选择(轮盘赌算法) - T7 ~7 Z2 J5 A. S: X newfitvalue = []" Q# j; g; {; t. N6 ?5 N' [% H
totalfit = sum(fitvalue) 4 j1 e7 e9 U& X$ A, N5 F* G; p for i in range(len(fitvalue)):/ C5 a/ e; T1 L4 g
newfitvalue.append(fitvalue / totalfit) . W0 p5 x1 w9 I! m" w cumsum(newfitvalue)! H4 w" C& w1 q0 T
ms = []; 8 d( f, d, F v2 [ poplen = len(pop)- ^. z5 a# H4 j4 M0 Z+ R. U
for i in range(poplen):8 Z. X7 Y& z& ~
ms.append(random.random()) #random float list ms - p5 f6 [% z5 @* O4 H1 N! y ms.sort() 8 I) x) d% X8 _% E1 g' e" e8 L fitin = 0 ! N+ Q2 q* k* V. o) N newin = 0- C; B3 m i4 |6 q
newpop = pop * L+ }+ e8 I8 q/ l M1 w6 r: G while newin < poplen:0 J1 u' y; f! b q4 ?7 h
if(ms[newin] < newfitvalue[fitin]): , k, I/ d" @2 ?6 C+ D newpop[newin] = pop[fitin] ! ^0 d. S2 o' m( m4 t$ t: F. S newin = newin + 12 w/ Z9 s9 A" C# l3 n* d4 ~
else: 5 C* D m' o9 y/ T6 C fitin = fitin + 1, _+ _8 @' \, p# D, o
pop = newpop $ n$ Y& l4 {5 H/ H; o% r! D8 fimport random ; c) B6 a; \: X4 n3 m2 Y& ~5 ?) k" Y8 |* \
def crossover(pop, pc): #个体间交叉,实现基因交换* d9 Q! s% i3 _# j' ?5 x+ _
poplen = len(pop), p( i- y/ g# K& |
for i in range(poplen - 1): / i3 X$ f) ~$ B' m if(random.random() < pc):( {* n. V- K% r3 o v
cpoint = random.randint(0,len(pop[0]))" `+ J8 x5 v2 k% @9 b
temp1 = [] # s2 ^2 C9 ?5 A7 l0 m temp2 = [] & ]% B5 k7 G& d3 w" E; V temp1.extend(pop[0 : cpoint]) $ |. M' M9 r# U! L$ m: |- E temp1.extend(pop[i+1][cpoint : len(pop)]) 5 E4 X: Z9 {1 ?3 O0 i temp2.extend(pop[i+1][0 : cpoint]), g/ D& [3 H8 h& l. @$ q" C1 E
temp2.extend(pop[cpoint : len(pop)]) " a' L$ Q$ K: | pop = temp18 ^2 s- o2 _$ N0 Z& b5 t
pop[i+1] = temp2) A& A3 A1 f- q( T
import random 9 S9 K! W; q9 Y6 P' Y " d6 x* W8 t l( g& P; adef mutation(pop, pm): #基因突变 # x( ~3 e9 E- P. q6 y, E& `8 l px = len(pop)# k0 f; f6 g, i- g
py = len(pop[0])! l- G) n# x Y
, T" E4 h" ?$ N" \ for i in range(px): 4 W( n( K! s% j. _; E+ [, f if(random.random() < pm):/ q8 E7 }4 C' C* t8 ^
mpoint = random.randint(0,py-1)) I) g6 h: H5 f+ f, q1 E, Y( M
if(pop[mpoint] == 1): 5 P& @ |8 m& J! H) ^7 N pop[mpoint] = 0 2 N7 g; w+ g0 q/ _' L5 H else:# N' @9 o+ `' v" b8 ] P' {# K0 R
pop[mpoint] = 1- {* B; R9 _; z m1 q4 Z
2 t! a- h7 j8 l; j2 o5 R6 H" e& X+ W) [( j5 I
————————————————' F. ?6 }! Y$ H4 F: W6 K1 p S
版权声明:本文为CSDN博主「simon-zhao」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 % b j7 E+ ~. y- s" J4 t原文链接:https://blog.csdn.net/u010902721/article/details/23531359 ( F. W- K9 w. ~$ x ' z' e, ~) m9 I, I# z4 r+ t, I/ l W+ r _) W: b