7 M) ^& V% @4 [& i
遗传算法(GA)是最早由美国Holland教授提出的一种基于自然界的“适者生存,优胜劣汰”基本法则的智能搜索算法。该法则很好地诠释了生物进化的自然选择过程。遗传算法也是借鉴该基本法则,通过基于种群的思想,将问题的解通过编码的方式转化为种群中的个体,并让这些个体不断地通过选择、交叉和变异算子模拟生物的进化过程,然后利用“优胜劣汰”法则选择种群中适应性较强的个体构成子种群,然后让子种群重复类似的进化过程,直到找到问题的最优解或者到达一定的进化(运算)时间。" H6 X( w( _6 ^8 L) p. p
/ z5 D2 }) ?+ sGa算法中的几个重要名词概念。 5 t7 R& [( R! G v! H. I2 f% Q$ |$ j% S4 z6 t+ F; r" Y+ L
个体(染色体):自然界中一个个体(染色体)代表一个生物,在GA算法中,个体(染色体)代表了具体问题的一个解。 , e" i U/ x& V7 D) f& `) o: `% A
* Q( M- v/ |' w3 D4、Python代码0 ~! E; t3 c( z. R: K3 P6 l
#-*- coding:utf-8 -*-; h. z# ?3 p8 r4 F8 _% k& [/ y
$ _, c9 Y' q2 M" s1 B0 l. [
import random5 w% }- Q+ S& y6 z& G& S0 x
import math ( x9 P6 H' I; S6 `7 y# ^( w+ k% Ofrom operator import itemgetter) R5 d+ E; k" \# l
% v0 K& p+ H: _- n0 Y
class Gene:8 @( u: n- q% |. T& Y! j0 J, D
'''0 G7 I* r" y9 {9 n
This is a class to represent individual(Gene) in GA algorithom 2 l! I0 K6 I% @& Q each object of this class have two attribute: data, size" `3 P3 Y' Q! z1 ~$ F" G- }
''' G, ^' k2 _/ u
def __init__(self,**data):- H0 q9 d6 r6 q9 y# t. P6 u
self.__dict__.update(data) l* P% }) j( w. a9 e- t! b) x) U6 N+ h
self.size = len(data['data'])#length of gene+ }1 ?! v: [9 e' l$ V! Z) ?9 X
7 }1 S$ |% }* m; n* q( n' X/ C# j, p2 R: C
1 u6 I1 }% M# C$ H! [( [+ E) @4 m
class GA:7 M- A( W+ c! h# c
''' 2 J; K4 M: O# v1 O5 k7 N9 i This is a class of GA algorithm. $ V+ R( g: [% h1 u
''' 8 r8 Y+ ~7 p; [6 E: c; Z8 g. k9 r def __init__(self,parameter): 3 z# x4 P9 D7 ^; u3 i: D. g& O ''' % l* O' u6 @ Q/ `$ S" d5 Y' K. f Initialize the pop of GA algorithom and evaluate the pop by computing its' fitness value .* B! z) B# p" `# i W& E ?# l
The data structure of pop is composed of several individuals which has the form like that: ( z1 [* X. z( k" o( R: f2 A1 i! N! N
{'Gene':a object of class Gene, 'fitness': 1.02(for example)} # D3 `% m+ S1 m' X4 ^" X' C6 [ Representation of Gene is a list: [b s0 u0 sita0 s1 u1 sita1 s2 u2 sita2]7 k$ ^" b2 h9 q1 S; w: ]
3 m, Y. ~- ^3 F1 V3 V
'''' ?. {. M U. _2 v
#parameter = [CXPB, MUTPB, NGEN, popsize, low, up]3 Q6 W$ S+ f9 O: n/ \* O3 |' k7 [
self.parameter = parameter, l. y8 X% _4 ]# O) E: ^
% e4 ?5 \9 u- r4 G low = self.parameter[4] 8 m0 Z+ q" [. M/ R up = self.parameter[5]9 _/ c3 h6 o2 `9 P; |) s8 d0 \
# w4 z, T- [7 C; H q% L5 D7 C self.bound = [] ! g: N, O2 V5 C! o5 D self.bound.append(low) 5 E% u9 i+ Y* W3 h0 Y, {& I self.bound.append(up)# n; s/ L a! _7 P' U
6 ?# J+ Z. Q3 S5 ~
pop = [] . _- z4 B( Y8 `& D. l for i in range(self.parameter[3]): . k( b# v1 ^" o( W; h$ F: l geneinfo = []7 B! }/ |5 Y) O. v' F4 M
for pos in range(len(low)): * ^% U" W2 ?/ I, U. O geneinfo.append(random.uniform(self.bound[0][pos], self.bound[1][pos]))#initialise popluation ( F; G/ W8 |$ u3 l9 ] : L, P5 E5 J4 p0 {& T$ Y8 ?: ~$ T fitness = evaluate(geneinfo)#evaluate each chromosome : Z. ]1 v. q2 V, y pop.append({'Gene':Gene(data = geneinfo), 'fitness':fitness})#store the chromosome and its fitness $ x% Y1 c" G4 B A# O% t4 l g7 \0 F1 }- h+ A( n$ g
self.pop = pop2 }1 ?9 E0 j, I" B/ o0 _/ {, U
self.bestindividual = self.selectBest(self.pop)#store the best chromosome in the population" |: f3 A! s% w* g! D
( x% P$ \, J$ A; V* }5 ~ def selectBest(self, pop): ) U5 t5 l! J# A' z8 G ''' 7 q `2 O5 p+ x7 l- r+ E select the best individual from pop / T% T( \% ?/ r7 k+ E$ R+ } ''' / h, [" T2 Q5 f: { s_inds = sorted(pop, key = itemgetter("fitness"), reverse = False) + A0 H8 ~0 G% ]5 b" u6 C return s_inds[0]! e) q( q9 |6 f( i" P5 Q9 ]7 u
) r) F8 R e9 a" {. y4 u def selection(self, individuals, k):& E, @1 c6 A7 B5 \0 H2 ~
'''7 |1 c6 W( r& }0 g
select two individuals from pop % @6 S3 w% U% g/ |2 F: `: x- U ''' 3 @% j7 { }2 d s_inds = sorted(individuals, key = itemgetter("fitness"), reverse=True)#sort the pop by the reference of 1/fitness 5 _& \6 G: U& Z( e& `2 V# k sum_fits = sum(1/ind['fitness'] for ind in individuals) #sum up the 1/fitness of the whole pop 0 K3 [1 w3 r# B* ~( X/ ~8 B+ u3 `. q" \ o) \9 F. A# M& R( l
chosen = [] , L2 m% n x, K& a% h0 v( m, p for i in xrange(k): * u5 D" Y: s- b6 | u = random.random() * sum_fits#randomly produce a num in the range of [0, sum_fits] 4 N8 p1 H" |# } p. Y sum_ = 0! Z3 E: l; w' M4 R4 ?7 v
for ind in s_inds: - z$ L- l5 z6 `1 W U/ a sum_ += 1/ind['fitness']#sum up the 1/fitness $ Z K, |& c8 l2 Z if sum_ > u:, ^& n7 l8 X# P* t( V' Z
#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 pop8 p7 `5 Y" S. w3 D, ]2 F2 n' L$ k. R
chosen.append(ind) / J, _$ G* n6 r" {& U& x3 z" N break* ~8 r8 p: ]) y$ i$ o, Z
5 j5 @3 A/ n n" H
return chosen e' z1 X. s2 ?9 U4 H4 n8 d. a$ I% L$ ]! N) k7 F
9 F+ N$ i) j) M- Z9 I, x8 b def crossoperate(self, offspring):. t9 M- R, v# C4 h! `' B/ {2 o
''' 4 z; b6 V `6 ~! Y. x& R% a. H cross operation) z! f6 T" M, g# N- `( e+ y. Q2 h ^ j
'''& W! ]3 \* I' w _
dim = len(offspring[0]['Gene'].data)- _/ ?- ~5 O# V# m
! U6 T6 M1 q$ d" X7 z7 L/ A# H
geninfo1 = offspring[0]['Gene'].data#Gene's data of first offspring chosen from the selected pop3 m" t3 w* W5 A. q8 w& Z1 k5 l# p
geninfo2 = offspring[1]['Gene'].data#Gene's data of second offspring chosen from the selected pop4 ?$ x6 y( \. S5 c
" O7 d* ?+ R" N5 ?0 B1 ~' F
pos1 = random.randrange(1,dim)#select a position in the range from 0 to dim-1, - E! _. @% S% W* S8 U( l$ U3 ] pos2 = random.randrange(1,dim) 1 S) H6 J8 i+ E* w 1 g& C" T5 A5 U! R, E8 _ newoff = Gene(data = [])#offspring produced by cross operation + |, f0 f' A4 ^' y( q: x temp = []& L5 ~" q4 \0 B7 B
for i in range(dim): & Z4 Z3 \% M! U. M$ K- d if (i >= min(pos1,pos2) and i <= max(pos1,pos2)):! ^+ E- E/ J# i- h9 y
temp.append(geninfo2) 9 w5 s8 L$ s7 y: R- y #the gene data of offspring produced by cross operation is from the second offspring in the range [min(pos1,pos2),max(pos1,pos2)] 9 [& S) `* X5 W# h4 w. J else: 7 f8 L, O) X$ d( ]# z temp.append(geninfo1)" u2 v3 n0 \0 w. V) g) [ p
#the gene data of offspring produced by cross operation is from the frist offspring in the range [min(pos1,pos2),max(pos1,pos2)] 5 D" g5 Q) s v" B! t newoff.data = temp % W$ V2 N0 X& O9 t6 b7 c0 [ [; }: h, S% C
return newoff 2 n! t: ^: x! c2 y% Q4 w: R. k# f7 ]9 D# G1 g
! ? z7 _! Y- n( K h def mutation(self, crossoff, bound):! y" p) P& k1 f |: X' D; o1 g
'''% r$ `7 J% L Y
mutation operation) {/ f. h$ r4 \6 b" M; i, u, V8 Q
''' / E Q3 c/ T, o0 J; U) _$ b# D0 k
dim = len(crossoff.data) $ Y, P( }; C! p3 y( c5 @0 G3 W: O
pos = random.randrange(1,dim)#chose a position in crossoff to perform mutation.2 c/ \2 J' X) R% V1 A
# s2 l! \/ u6 j6 j9 J
crossoff.data[pos] = random.uniform(bound[0][pos],bound[1][pos]) " Y! M* Z! c6 s7 X; s return crossoff + v: ~9 R) j, a' X- ? % U% @6 {' {: T+ T def GA_main(self): + V3 L+ A1 r! U5 }- P7 I+ {1 z '''& C9 e" e. ?, A- |
main frame work of GA . t! c$ }4 r8 ], Y '''' v1 J9 {9 [/ d% v
2 O2 ~; g: K0 p! l' L, R popsize = self.parameter[3] 2 O* ]! p, C7 I1 e7 T2 J% e3 q# c! f3 F! S( P
print("Start of evolution") , S/ ~6 u" j" c U; ?$ P' m, ^0 \& H. q# V9 Q/ e
# Begin the evolution . A4 x' R7 s8 n* _; O# n; Q for g in range(NGEN): 0 N- d; Z8 Q1 a& R: b" }$ V2 k* L+ o8 k
print("-- Generation %i --" % g) $ C( f* G+ j; g- Y* i% H) q. g1 Q 8 K) d6 R- _& u+ z: v- E #Apply selection based on their converted fitness U* r; H, M, B7 g selectpop = self.selection(self.pop, popsize) + _$ b, Y7 e# K! Z* P, G
- C: X0 I% H5 _# l nextoff = [] / s/ u4 C; s- `- A% V4 h
while len(nextoff) != popsize: 3 q, K# q5 c/ M: a2 [$ D. p% w
# Apply crossover and mutation on the offspring & N0 ?8 Y, x4 @- \ [ 1 Z3 _( M5 y5 ~) W* A) I1 `9 _* j3 w5 ~ # Select two individuals) S$ ~- Y: v/ B! u
offspring = [random.choice(selectpop) for i in xrange(2)]- Y2 c( `; u4 t3 l r1 Y5 H7 D, G
; C& |: V0 C! z. Q# E" r2 J: J
if random.random() < CXPB: # cross two individuals with probability CXPB4 y, _8 o- O4 @# X7 z% |
crossoff = self.crossoperate(offspring) 3 c, U+ V' b" T& L4 j fit_crossoff = evaluate(self.xydata, crossoff.data)# Evaluate the individuals 9 \1 d# W9 o5 \: U/ V, _& i 4 l: l, v. Y, M+ l- z/ h- Q5 v if random.random() < MUTPB: # mutate an individual with probability MUTPB 2 R" ^' U1 u; k& t. c muteoff = self.mutation(crossoff,self.bound) % t3 |9 Z8 K$ I3 s, I0 S3 a1 E fit_muteoff = evaluate(self.xydata, muteoff.data)# Evaluate the individuals4 t4 H+ }$ X. K+ b1 U8 E" d
nextoff.append({'Gene':muteoff,'fitness':fit_muteoff})' A& x6 C8 Y+ `! C9 l( Z' I4 l8 l1 j
8 k, v' R- j, a7 o" {8 d; A; E2 ? # The population is entirely replaced by the offspring 1 W0 |' _6 t9 E$ ]1 Z( e9 e6 ?4 f+ c- r self.pop = nextoff2 p5 ]8 H4 \& _% j
. C% y6 h) o* D( ~ # Gather all the fitnesses in one list and print the stats4 F! P5 h9 J( w0 a6 O( C
fits = [ind['fitness'] for ind in self.pop] ; Q7 p. ^) D- m 0 E. A7 H) s4 \+ H; m* F' d length = len(self.pop)- q. b+ A, T5 z. F
mean = sum(fits) / length1 P& R$ }" T$ Q7 u- Q
sum2 = sum(x*x for x in fits)' C1 L C) \; P
std = abs(sum2 / length - mean**2)**0.5- l' v6 h" v2 _! |% c) z5 t
best_ind = self.selectBest(self.pop) 6 }+ z8 ?" o. G" R' \& q$ Y) Z! C: [" V3 [. K, @ I7 q1 r
if best_ind['fitness'] < self.bestindividual['fitness']: ) s; c [/ @: ^- s self.bestindividual = best_ind . d7 N% l, H" t9 j4 l+ n" T) N9 p
print("Best individual found is %s, %s" % (self.bestindividual['Gene'].data,self.bestindividual['fitness'])): n4 @& f+ R& ?+ O- F
print(" Min fitness of current pop: %s" % min(fits))6 c: Z: i* o& R- O
print(" Max fitness of current pop: %s" % max(fits)), p+ ?/ i m5 w6 F, e9 W
print(" Avg fitness of current pop: %s" % mean) ; C# [1 e6 W' F' M1 p& _$ e print(" Std of currrent pop: %s" % std) 1 n6 i/ k4 x8 X0 [' J3 v/ X' }- m! n" x9 ~
print("-- End of (successful) evolution --") ) m, \4 `+ n* V# p6 f" g2 o 9 ?1 X) ?& u; U, m$ tif __name__ == "__main__":) j. _/ z6 Q i. r4 c' g8 |0 |8 t
@! Z( y" Z4 L1 O N8 Z: N CXPB, MUTPB, NGEN, popsize = 0.8, 0.3, 50, 100#control parameters2 ^* s9 `. f5 k, @/ m {' \$ L4 H. S
" p7 w- _6 |- v6 e$ {# X
up = [64, 64, 64, 64, 64, 64, 64, 64, 64, 64]#upper range for variables $ |, B5 v9 t) a low = [-64, -64, -64, -64, -64, -64, -64, -64, -64, -64]#lower range for variables3 [, Z% ?9 B k3 g
parameter = [CXPB, MUTPB, NGEN, popsize, low, up]3 Y% N: k. o$ T; p8 P& O# n) N
" G1 F: x1 r3 q! z+ j
run = GA(parameter) 3 I& H& z5 I* n% j0 T( _# ~# G run.GA_main()1 V* i O& Y7 m, ]/ _4 S+ t: q
———————————————— 8 l0 T V) Q* h! l \+ y+ S. K& v& T版权声明:本文为CSDN博主「bible_reader」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 ' o/ f0 L+ C1 w# @* h/ N& ^原文链接:https://blog.csdn.net/bible_reader/article/details/72782675, Z; J n: \! u$ W& |
7 R8 |, Y6 O/ y1 r& Q* v8 g; T
: j2 O* f8 z8 X! H0 l5 W4 o# j