- W& d4 D \9 U! i- v
遗传算法(GA)是最早由美国Holland教授提出的一种基于自然界的“适者生存,优胜劣汰”基本法则的智能搜索算法。该法则很好地诠释了生物进化的自然选择过程。遗传算法也是借鉴该基本法则,通过基于种群的思想,将问题的解通过编码的方式转化为种群中的个体,并让这些个体不断地通过选择、交叉和变异算子模拟生物的进化过程,然后利用“优胜劣汰”法则选择种群中适应性较强的个体构成子种群,然后让子种群重复类似的进化过程,直到找到问题的最优解或者到达一定的进化(运算)时间。; Z0 `( g4 A6 p' f# W$ E# |/ w
+ D* S9 m2 V$ V* S. l; yGa算法中的几个重要名词概念。5 Q5 l% S2 \8 e. i1 x
5 d/ @6 k8 o6 } }( i5 Y. N$ f个体(染色体):自然界中一个个体(染色体)代表一个生物,在GA算法中,个体(染色体)代表了具体问题的一个解。& |/ T6 E# \: m1 n, Q$ H
0 q9 y/ d& \4 S0 C0 w5 N4、Python代码 $ w: Q8 S+ j) ]" W# Y2 G% v$ j#-*- coding:utf-8 -*-1 D1 a* n ~: D! K
6 ~2 `" ^, `. T }
import random F8 w. M; z9 c; q/ ?. R( Uimport math + B2 @' w: d+ l' r# ffrom operator import itemgetter9 f3 p. q5 N9 u- H7 g' H/ Q
" h+ C2 [, g% n8 L7 y
class Gene: / q/ q& t7 N8 G) J& P '''* {' l- ~1 w8 z) Y( E
This is a class to represent individual(Gene) in GA algorithom " B" V. T. b$ H9 W' t& }2 O r each object of this class have two attribute: data, size: R8 q$ S! S9 d& E4 I/ l( z$ q0 v
'''3 x6 Z/ D9 W( I+ e6 v
def __init__(self,**data):" v6 Z( ]" C5 |6 Y" E
self.__dict__.update(data) 5 @' w$ p4 y2 U( @3 p self.size = len(data['data'])#length of gene * l. k7 Y3 T, ?/ `, x ; G/ L7 ^1 ?3 g1 a; _$ {( V* Q$ s( J ^- N' s
class GA: ( m& E5 F! H% z8 F/ P ''' , z1 `# o& R5 w* Z) i) ]; s( H This is a class of GA algorithm. 7 C* q; p; e% Z( {
'''& s. T4 K! X8 p* ]3 ^3 S# L
def __init__(self,parameter): q+ j# K3 Y: f" [
''' 4 M9 B& L4 S: Z0 E Initialize the pop of GA algorithom and evaluate the pop by computing its' fitness value .1 u, _! Q. \. |3 W5 o
The data structure of pop is composed of several individuals which has the form like that: 0 [' U0 U$ z& k4 h+ Q3 q# d8 t7 b* ^' I5 V6 X1 b1 g+ `3 O" a; t
{'Gene':a object of class Gene, 'fitness': 1.02(for example)} * w+ \$ G0 S( R4 A2 l Representation of Gene is a list: [b s0 u0 sita0 s1 u1 sita1 s2 u2 sita2]5 x' m: _ ?" K1 m
) C7 {- a+ M. i1 c6 c ''' : C. Z! T# M8 B/ g" K4 ]; u #parameter = [CXPB, MUTPB, NGEN, popsize, low, up]4 [& L2 B* H8 J3 k
self.parameter = parameter1 ]* {2 T: Q$ \/ W
$ j* g5 G2 I: u8 H low = self.parameter[4]) E$ B9 Q" J( U8 {+ B7 L) l0 M
up = self.parameter[5]5 G. l# F1 a8 g, L
* U! L& R6 Q* `/ M9 R8 l; ]$ J self.bound = [] + A& W3 m& ]- @/ b+ c) T self.bound.append(low)5 m4 h: W; d- T, g$ S, b) M7 V# f
self.bound.append(up) . e" c* E( i' }8 K1 p! j" b9 p) C; R$ O; r `
pop = [] # v( B9 G- x% j for i in range(self.parameter[3]):- N# a" ]' x& F* R' b: e
geneinfo = []# {0 |. v3 E. L# Y8 k
for pos in range(len(low)): 3 W- U. v, M5 [1 Y( D' H geneinfo.append(random.uniform(self.bound[0][pos], self.bound[1][pos]))#initialise popluation6 P6 w# ~1 i- R7 |8 ^" b5 j
* [7 e7 T( z" G* R; i" L0 m fitness = evaluate(geneinfo)#evaluate each chromosome 0 G5 N K7 I6 y pop.append({'Gene':Gene(data = geneinfo), 'fitness':fitness})#store the chromosome and its fitness1 D @: n8 Z& R8 N1 u) ~# ~! u8 _
/ i% v) A3 y# w! Z7 p6 v7 K0 r self.pop = pop% R: ], ^0 o7 n
self.bestindividual = self.selectBest(self.pop)#store the best chromosome in the population : u) W' a2 n, {% j# S; { & Z- J5 j# k; y8 o* I$ r def selectBest(self, pop): 7 O) A5 r$ Y% p6 x '''! g T7 w' \0 ?' m# N+ n! `* q
select the best individual from pop $ R/ f+ j) A: l: h, S9 U. y '''. U$ m( y/ F3 w& L/ U3 h
s_inds = sorted(pop, key = itemgetter("fitness"), reverse = False)2 x( ?- N/ x2 o5 U
return s_inds[0] 3 G( w! A" e% ]' w 8 U" x$ _) K0 |& V def selection(self, individuals, k): * o& T3 d. E# u) \5 W ''' Z4 K4 R5 @' v% W6 m- }/ b% G select two individuals from pop! V S9 H0 Z, C' I- V' k# \
'''2 t. i7 z/ x d4 i2 g$ y3 R' p6 O
s_inds = sorted(individuals, key = itemgetter("fitness"), reverse=True)#sort the pop by the reference of 1/fitness ; D. Z c! W* U# T- \- D2 Y% ?
sum_fits = sum(1/ind['fitness'] for ind in individuals) #sum up the 1/fitness of the whole pop 4 D; {- M, ]. R1 C% u$ B7 d9 [$ i 7 [( C9 M: R; Y: d' G. a chosen = []/ e: U* l- |) e9 X2 F
for i in xrange(k): 3 A$ y( B' m! n) c6 g- b u = random.random() * sum_fits#randomly produce a num in the range of [0, sum_fits] ! W. Z; J) A- n: U* `. N sum_ = 0 5 D* K b) R: [: m# ^ for ind in s_inds:1 M R0 I: O" Z2 G& R2 w
sum_ += 1/ind['fitness']#sum up the 1/fitness4 O% Z0 U7 M5 N& S4 m% R8 U
if sum_ > u: & C/ N: r! N( |( g0 Q6 T #when the sum of 1/fitness is bigger than u, choose the one, which means u is in the range of [sum(1,2,...,n-1),sum(1,2,...,n)] and is time to choose the one ,namely n-th individual in the pop ; O6 P1 }* n- \- U chosen.append(ind) & N+ f8 a9 Z3 L/ G! L) Q+ K! \% N5 [ break - k6 |* C- f0 H. c* V9 M. } - I5 j. H; I7 Z6 h7 b return chosen 6 v) o0 x) c1 X' d , o/ N$ A7 s, I* E& M4 Q & r, ]3 Y" _& j w/ O def crossoperate(self, offspring):) K7 B' o2 _, W5 H& n) {
''' $ J- b, T( J- z ]( Q cross operation $ M/ q+ H$ |. u% o2 f ''' + i# R6 m, }* Q5 g5 l ]7 r: J dim = len(offspring[0]['Gene'].data) 7 `# y% W. X5 D/ ?: C/ t2 E / H4 G# n$ `( E4 d% o( G geninfo1 = offspring[0]['Gene'].data#Gene's data of first offspring chosen from the selected pop" h5 l9 {6 G" [: G" H* ^% Q
geninfo2 = offspring[1]['Gene'].data#Gene's data of second offspring chosen from the selected pop+ [; S4 e7 U2 i$ c9 X0 M
' w) e+ l) Y& `; {5 b" N7 A pos1 = random.randrange(1,dim)#select a position in the range from 0 to dim-1, & b8 m4 M8 _9 f
pos2 = random.randrange(1,dim) 1 a% `2 g F+ J. x' [+ ~7 E) e0 V * u# O7 _7 q* }: X5 y; f( y2 L newoff = Gene(data = [])#offspring produced by cross operation , {+ I. [6 ^5 B* l4 _" r3 U. C temp = []* n) ~0 |6 B/ U2 a" k' Y
for i in range(dim): Q- c; y: d% n& ^& G if (i >= min(pos1,pos2) and i <= max(pos1,pos2)): ( j+ Q- T2 H/ v) F! z2 ? temp.append(geninfo2)3 d" Y# H) J) g, d: K7 P+ V; C
#the gene data of offspring produced by cross operation is from the second offspring in the range [min(pos1,pos2),max(pos1,pos2)] $ M+ f: h4 B1 S3 A" W4 u else:( R o. {3 k+ f' C5 r
temp.append(geninfo1) 0 c" f% e+ V t9 u' A #the gene data of offspring produced by cross operation is from the frist offspring in the range [min(pos1,pos2),max(pos1,pos2)]) K; q- P6 S8 P4 h2 j' r' _5 w
newoff.data = temp$ Y& ~& e5 Z$ p; A. U, h
( g8 s0 f/ G# |8 l
return newoff# x1 Q. S: r0 u6 p
1 p, ] z* q/ c6 Q6 B& b& K8 W
1 D7 E; S, }- {7 o; v- P! F
def mutation(self, crossoff, bound): ( f! m, M$ L; V '''$ C( Z! t5 ?( t2 r+ B' m
mutation operation 4 Y# ^1 ]8 z! I$ _; Z% H ''' 5 }5 T* s8 {& k: s5 Y- V# F: R - U: W$ l3 k6 p Y% b& J/ { dim = len(crossoff.data) ; Q j4 K! E# y7 N9 o% L6 H. |( J# y
pos = random.randrange(1,dim)#chose a position in crossoff to perform mutation. 1 l5 d4 p$ C' |# Q' I" P5 i+ u- |- }% E+ [% g2 F( o/ V
crossoff.data[pos] = random.uniform(bound[0][pos],bound[1][pos])6 n6 ~* u2 r! ~& m! }; s) d9 Z# i/ p
return crossoff/ G7 k7 u' {! W; O6 D$ T
; P6 Z! \+ V- A( P
def GA_main(self): ( W" b6 z, w4 {1 r; E$ R ''' ' U- |/ x& I2 [2 ` main frame work of GA/ q2 i9 O; Z1 k
'''; V# l) |, ^* D& N* d5 F7 r/ {4 r
* |( t6 I- h; g# N2 k- e5 V popsize = self.parameter[3] ; z2 S+ ^3 G0 A# `+ }0 i: m% O( P% {7 g) _ |
print("Start of evolution") 0 l9 t5 a* W: Y% W5 `4 F7 e7 o " G% X( X% Q7 p # Begin the evolution2 Q0 O+ I5 t# |/ j/ u1 E
for g in range(NGEN): 0 S" }+ Q* r: ^. s( D- n9 X% h g9 n/ M7 b9 y3 U% ~2 q
print("-- Generation %i --" % g) 9 ^8 |$ F8 s" V* E& i ! c" q/ m9 }2 L- d #Apply selection based on their converted fitness - E9 r( O9 f* v6 _* w) A selectpop = self.selection(self.pop, popsize) 5 |. x- @5 C, o% \! N
. G3 X$ T0 n3 }, x4 N' t h& r nextoff = [] v. N* w- D0 E( c1 P& K |2 l8 m
while len(nextoff) != popsize: 5 A% a3 b% B5 U o9 t2 D # Apply crossover and mutation on the offspring - N8 ^" @$ ?( D, N4 L, F; N- m 1 z, z. H4 R' U R* o9 Y' H9 {4 e # Select two individuals% }; Q: f0 [: ]1 Q, v6 C# A4 m
offspring = [random.choice(selectpop) for i in xrange(2)]1 X- U5 W$ A. p8 [. w2 E: Z6 x6 V+ [
) E8 j( c& K9 F' L2 D. Q' W
if random.random() < CXPB: # cross two individuals with probability CXPB9 d# ]- [. w% V, z4 Q' {. I
crossoff = self.crossoperate(offspring) 1 C2 V4 M& w& k1 G5 T fit_crossoff = evaluate(self.xydata, crossoff.data)# Evaluate the individuals & e! I: F4 U, S# Q. A3 Y3 ^/ g7 |. k9 a: y' P h
if random.random() < MUTPB: # mutate an individual with probability MUTPB 7 o$ J; O; Z; i" P* b muteoff = self.mutation(crossoff,self.bound) O7 ?1 p3 {8 M8 o+ a o
fit_muteoff = evaluate(self.xydata, muteoff.data)# Evaluate the individuals # f# O. S# Z6 n% M' I nextoff.append({'Gene':muteoff,'fitness':fit_muteoff}) 6 a0 H/ W2 {- j+ X9 X, X+ @ ; Z5 ?; ?5 g" g. z' ? # The population is entirely replaced by the offspring$ o( M- x! Y7 t D4 a" A& G
self.pop = nextoff $ M( [$ h5 p3 ~ 6 ^4 i- p7 I/ m9 E3 g4 b C: F # Gather all the fitnesses in one list and print the stats; b9 W \7 G/ M6 M
fits = [ind['fitness'] for ind in self.pop] s) I7 s k1 |6 d$ D" I5 P % w7 ]5 k) s( C F( n5 r' H length = len(self.pop) N; D' A; T+ O4 @% M0 a mean = sum(fits) / length 7 b5 K1 v$ \0 x2 x# Y& x/ C3 u1 s1 [ sum2 = sum(x*x for x in fits)3 ^9 ~1 A7 i* T0 x( u: s- n6 r
std = abs(sum2 / length - mean**2)**0.5$ g5 `# N# t$ v) |3 z |* o
best_ind = self.selectBest(self.pop) , e' i& u F- Y) t/ K9 i5 p+ U8 Q6 Y5 {5 _2 ~& d
if best_ind['fitness'] < self.bestindividual['fitness']: - I+ B) M m# a+ S7 t9 t# F self.bestindividual = best_ind W3 F7 x% ~- j) H7 e2 l2 A2 P* E! s, ]0 F/ c" Q5 u
print("Best individual found is %s, %s" % (self.bestindividual['Gene'].data,self.bestindividual['fitness'])) + }+ V1 I3 U5 L* M9 k9 k: v* B print(" Min fitness of current pop: %s" % min(fits))- ~+ _7 O, W3 k4 m! j, Y2 H; }1 C0 h+ S
print(" Max fitness of current pop: %s" % max(fits)) $ a+ k9 c6 V5 t5 J, z7 o( T6 m print(" Avg fitness of current pop: %s" % mean) + Q% q$ B; ~; L$ z print(" Std of currrent pop: %s" % std)- Y+ E% Q6 @# } N! T/ Q, R: P
4 G+ Y4 {, V" j6 z3 K) P8 y
print("-- End of (successful) evolution --") ; ]" C( W2 f0 Z3 r3 v / n' ~) o* s9 ^if __name__ == "__main__":! a9 T K+ i5 m) J1 L
k' x' h( R) h CXPB, MUTPB, NGEN, popsize = 0.8, 0.3, 50, 100#control parameters5 d& ^7 m8 I/ M. P& ]9 u6 {
8 P$ d3 i; Z* o
up = [64, 64, 64, 64, 64, 64, 64, 64, 64, 64]#upper range for variables v8 i' t0 J( G: S# L4 o low = [-64, -64, -64, -64, -64, -64, -64, -64, -64, -64]#lower range for variables- E1 O% |4 a, {. X: }, e, T6 w
parameter = [CXPB, MUTPB, NGEN, popsize, low, up] / Q1 i9 K5 E0 ~$ ~& G, F, g% N2 T% y1 [
run = GA(parameter) ) O+ X1 G5 @. M. c+ g run.GA_main(); ?$ @0 F; }" F
———————————————— 4 v% Y3 I1 M3 [版权声明:本文为CSDN博主「bible_reader」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。; c) Y" t. u3 X/ @! t
原文链接:https://blog.csdn.net/bible_reader/article/details/72782675 / X' m! i8 t: N( ~ P* x! \' ^ C$ A6 g+ F8 l, O/ N/ s2 t: P' J5 X) Z6 z, |/ C