- i2 @+ I) p; l! ximport random; x. s* z( H' [7 T8 |8 b+ s
import math . {% F# ^( t; \6 D+ h$ o% lfrom operator import itemgetter - P4 J3 M0 J2 J: q: \0 j: t; O# i' D, C" y+ V0 x1 }: Z
class Gene:8 I3 T' k. s# v, k8 L
''' 6 R5 Y* h5 f/ M L0 I This is a class to represent individual(Gene) in GA algorithom3 p. p' e7 s8 k2 @
each object of this class have two attribute: data, size. `4 x! k+ F, `
'''3 d( M& F& _$ b- E: u
def __init__(self,**data): 3 [% Z: v7 R# g9 _4 c self.__dict__.update(data) & w: @$ J0 p" A. b3 \2 Y self.size = len(data['data'])#length of gene: G0 T3 _ P) Q" ~3 y. _3 h. `* R5 [
5 g6 u [ V- o/ j! N' t, Z m1 k& e! e8 ]. C, D" t# Q3 E
class GA:4 D. H) ^* o+ n/ T4 \
'''0 F5 g) i6 P) w9 S
This is a class of GA algorithm. ; C7 v0 ] P( P% \5 a/ B' \+ l& h [
''' , A* c ]7 @& V def __init__(self,parameter):$ K; S3 j- T' Y
''' / I; V. k( X$ K0 u: g' @3 C Initialize the pop of GA algorithom and evaluate the pop by computing its' fitness value . " T( ^/ M, ?" p7 W$ ? The data structure of pop is composed of several individuals which has the form like that: $ r9 V) H9 F- j2 ]0 v! M# o- q/ f/ b. M9 \' Q; I
{'Gene':a object of class Gene, 'fitness': 1.02(for example)}; I: h; u/ X- c- O) c/ P
Representation of Gene is a list: [b s0 u0 sita0 s1 u1 sita1 s2 u2 sita2] 0 b/ a5 p! Q- A7 z; w+ d' {5 {# k5 J" } K
''' ^0 M2 t8 t4 w2 `& N #parameter = [CXPB, MUTPB, NGEN, popsize, low, up] / h4 h/ o4 W' v5 N: e( u: y self.parameter = parameter3 p0 J# b5 d+ p: Z: \& i) Y G
5 L! ^0 V- ]0 p
low = self.parameter[4] 9 t8 @6 L$ {$ g# \; A$ K- u up = self.parameter[5]0 s4 q5 l; O0 B) s
/ E# O4 O- F; E7 `) _$ j
self.bound = []) b# E9 ~" I: B8 c6 P
self.bound.append(low), G2 |7 v. V# P7 t$ w
self.bound.append(up). P5 c6 `( q; |$ ^
7 } j* h9 m0 v! `
pop = [] 2 x5 f" \0 p6 x, A1 I5 R for i in range(self.parameter[3]):% {5 e) Y6 h/ j3 M
geneinfo = []9 ^2 j5 w3 N0 v* Y8 A; L$ `
for pos in range(len(low)): 0 g" O0 I' k& a+ k7 I geneinfo.append(random.uniform(self.bound[0][pos], self.bound[1][pos]))#initialise popluation6 I6 b/ A) p- Y: [3 G7 o+ o
) u% I# G$ v I! m; i
fitness = evaluate(geneinfo)#evaluate each chromosome v# {: J( x" e
pop.append({'Gene':Gene(data = geneinfo), 'fitness':fitness})#store the chromosome and its fitness8 q" b% [5 h9 N( V$ M
+ H# ~; W2 H {9 K' R8 v self.pop = pop " [- ?6 m- l& g0 g; ] self.bestindividual = self.selectBest(self.pop)#store the best chromosome in the population0 A0 T l3 {9 k
( C) F- w1 V) {, G- P5 H
def selectBest(self, pop): 2 d b* R! u' w- n1 C, g' J! R- E% w ''': i4 q6 s- c! v, ?, V& o% U
select the best individual from pop 7 _8 [" \" B* B! R4 e ''') ?1 _$ u' U9 | ~/ Z1 q! t
s_inds = sorted(pop, key = itemgetter("fitness"), reverse = False): r- s5 y) E% [8 f* e. x" Y
return s_inds[0] + s: v7 `: F% m % B% l @0 F2 Y& ^' Y def selection(self, individuals, k): 3 h, S/ M) ^0 @+ E5 u* ]4 R* ? ''' , f4 r/ t( X( N J/ s! d9 k select two individuals from pop + F+ ]6 x$ J) J1 E* A ''' - [: {$ M; V8 \) b; X s_inds = sorted(individuals, key = itemgetter("fitness"), reverse=True)#sort the pop by the reference of 1/fitness # A& D8 M0 `( ~( V* z sum_fits = sum(1/ind['fitness'] for ind in individuals) #sum up the 1/fitness of the whole pop e/ Z% K$ U6 {/ e5 ]$ t' o' n ~: U+ \% F" M X
chosen = []) `- ~6 ~% e% f
for i in xrange(k):: ~! t1 ] ?- R K) C9 i3 S
u = random.random() * sum_fits#randomly produce a num in the range of [0, sum_fits]* p5 d' k e" R5 v
sum_ = 0 8 u" i/ S4 l$ q) C% ?/ \! @ for ind in s_inds: ! C" y8 ?$ Z" _ sum_ += 1/ind['fitness']#sum up the 1/fitness, y# z+ I# {( l+ L# q
if sum_ > u:, a; ?' r8 {; t1 j) o- x
#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 " Z$ ]: \2 Q6 n2 B chosen.append(ind)6 K6 @0 q& z/ n! ]2 U u% d
break # ]0 S9 m3 T) D6 g ) {- H' d s& W% g2 F" w4 T2 L) l return chosen 0 ]7 A. e7 n, e* c/ S( r r - _* Y C9 z) d1 u; d! ~& Z* ~, |8 w! Y/ |1 l- b7 S% N! m/ v& M
def crossoperate(self, offspring): : P' s9 F2 i4 A1 ` ''' / A; m; V, m$ \ cross operation + A, p+ x1 D/ j, r! Z. v '''- \, x4 m( F1 t7 U
dim = len(offspring[0]['Gene'].data) 2 _) i* t) l5 I' V; V2 J2 o4 m0 j4 b
geninfo1 = offspring[0]['Gene'].data#Gene's data of first offspring chosen from the selected pop2 w, C7 ^) C9 m8 V8 Z* Z4 N1 |$ `' S
geninfo2 = offspring[1]['Gene'].data#Gene's data of second offspring chosen from the selected pop & ]* v0 U( `1 }' k1 N2 E2 W/ c5 E" Q5 M# Q7 @( q" i
pos1 = random.randrange(1,dim)#select a position in the range from 0 to dim-1, " v# I4 j; l1 H% i7 t pos2 = random.randrange(1,dim) 5 v7 ~# x8 C! }9 ` k3 S# W. b5 q2 B& D4 L, F. C% y" m' ~: l
newoff = Gene(data = [])#offspring produced by cross operation 1 t' n6 e- y/ Z8 V temp = [] 5 L/ a/ w& |& K$ B. F8 T, s for i in range(dim): . _- E1 ~ F a9 [4 x; [ if (i >= min(pos1,pos2) and i <= max(pos1,pos2)):& K" P2 ~; k& ?6 Q
temp.append(geninfo2) " z: I' ~' C; k9 y+ G( c+ t: { #the gene data of offspring produced by cross operation is from the second offspring in the range [min(pos1,pos2),max(pos1,pos2)] 9 m; ^+ w. Z# a& V5 @" |7 Y else:) T w' \, F1 |- P- r7 f
temp.append(geninfo1)0 J5 i5 |% n/ l8 C
#the gene data of offspring produced by cross operation is from the frist offspring in the range [min(pos1,pos2),max(pos1,pos2)] 0 [' R! u6 h- M3 v- h newoff.data = temp 5 b& s1 } O9 v8 j/ m) D7 \: p ( p2 t* ~( K! R: B return newoff- l5 I5 f I, G) J0 x' R
; c) F r) k7 F" J3 E6 R
$ C3 ]5 v7 W) e+ B+ ` def mutation(self, crossoff, bound): ' Q! S* v, a& V; J. x '''7 ~, W8 v2 j* k- B/ _# P3 R: g
mutation operation' x/ ^- C( j; h) o# ~* r9 G$ \
'''$ y% n! Z: p! a' ]' U
. c$ C8 y& |0 ^- E& {1 \; o
dim = len(crossoff.data) , N( t, w8 P# {' l7 X3 m) ~# C! x6 x+ W( r0 N
pos = random.randrange(1,dim)#chose a position in crossoff to perform mutation. ' H6 \' g/ F& ]) u3 ~' K/ j& Q$ q5 j" }2 {7 J
crossoff.data[pos] = random.uniform(bound[0][pos],bound[1][pos]) 0 y. Q2 \1 |4 } return crossoff 5 z, i5 ?8 ?" ?- m0 r6 K( e1 P ! X# v- @# ?) S& q Q def GA_main(self):# s K) t" M4 Z: E1 R* x3 N! ^5 ?* i
''' 1 d9 @9 E* [; `4 W% ? main frame work of GA % s3 K' P6 K$ ?" l4 d7 c- T '''4 T T. Y/ x" v1 l0 E
3 P8 C: x# k* h: E) e popsize = self.parameter[3]5 e3 L6 [3 N/ b' h! K" f: q1 h
0 f# A# ~% K( p( ?# m print("Start of evolution") & v f1 H- [2 t2 ~- t( ] p0 B + M0 V5 T8 A8 ?3 C8 E- `; V! q0 s # Begin the evolution6 r$ V5 ]1 E2 u6 O. I$ [
for g in range(NGEN):$ L: p2 m" `" |; ]4 ?
6 P2 X: z- y2 I# p, J0 g7 A
print("-- Generation %i --" % g) 3 x. M+ K7 ~" I6 A; l ]0 y _) Z& O8 ]: I" N #Apply selection based on their converted fitness - z7 O% @1 J* A1 C( f7 R. p, j selectpop = self.selection(self.pop, popsize) " m1 G/ {5 G. n" x6 D" j8 n! m9 G* c1 O
nextoff = [] : V, J: b, S8 U% z) f
while len(nextoff) != popsize: ; h- G/ Q) }+ b9 |) _, o* Y% G
# Apply crossover and mutation on the offspring 2 `) X" L2 K* ~& ? }' e) g( w. U, c6 t/ \7 l) ~0 b4 v+ o
# Select two individuals $ e1 ], ?/ y7 V) y1 H offspring = [random.choice(selectpop) for i in xrange(2)]7 E* ^ H4 p( \ j( T9 j( X# T M
- v. r5 @& B, R! V! _5 `+ d7 I
if random.random() < CXPB: # cross two individuals with probability CXPB * Z3 k/ T7 \8 l6 O9 X0 M crossoff = self.crossoperate(offspring)9 ` \: x$ y( Z; V& ^
fit_crossoff = evaluate(self.xydata, crossoff.data)# Evaluate the individuals 1 A. }; u9 h0 y3 u! v 3 i% n- p/ h; q+ ?! U4 c if random.random() < MUTPB: # mutate an individual with probability MUTPB 2 X( D) p4 D+ X S! L muteoff = self.mutation(crossoff,self.bound) ! L, W- O2 a4 P6 O; ] fit_muteoff = evaluate(self.xydata, muteoff.data)# Evaluate the individuals9 G4 Q4 {) c3 w! h5 k
nextoff.append({'Gene':muteoff,'fitness':fit_muteoff}); a' P* B# G1 g. Z) R0 I
3 p7 a* K7 ^, ~# ` # The population is entirely replaced by the offspring 1 q% ^1 n- n9 V0 o self.pop = nextoff' T2 q6 s/ T' m/ T- V2 B
" J5 h; j, b7 a, M! B
# Gather all the fitnesses in one list and print the stats, v$ }! y0 z* t
fits = [ind['fitness'] for ind in self.pop] ' [( U' [9 j% E- n7 o+ B4 f2 W 9 ~9 a1 l8 v. b1 o length = len(self.pop)% ]. n7 f7 X8 [8 h T
mean = sum(fits) / length % `2 y0 a* p6 Q; } sum2 = sum(x*x for x in fits)" l0 C7 `6 r( T4 K6 ]! T
std = abs(sum2 / length - mean**2)**0.54 w$ q+ Z7 f, [+ R/ A, ]$ v/ c
best_ind = self.selectBest(self.pop) 7 y4 {$ e5 ^( p7 y. r+ D) a * w2 V* d2 L! \" o1 ~& [0 X if best_ind['fitness'] < self.bestindividual['fitness']: ( i) W9 ]2 ~- F# V! ]$ ?6 B) Q! o' X self.bestindividual = best_ind) r$ G8 I: T" D( e; a
6 y; ]- J8 m$ g) y5 ^8 J print("Best individual found is %s, %s" % (self.bestindividual['Gene'].data,self.bestindividual['fitness'])) ) a6 b* @! c4 m4 o print(" Min fitness of current pop: %s" % min(fits)) 3 r$ l6 {3 m. A7 X: C3 l, m" f print(" Max fitness of current pop: %s" % max(fits)) 7 v! j8 y3 c: t! e. n$ t print(" Avg fitness of current pop: %s" % mean) 9 T+ v5 r& E; ]" O print(" Std of currrent pop: %s" % std)% t( t* R6 Y) @ ^5 p6 D
6 m5 [, D7 q) W$ G# H) | print("-- End of (successful) evolution --") 9 F7 X& M/ t n# C6 g, `9 A
& `5 A9 \& [2 b' L9 tif __name__ == "__main__":0 o# v+ {% h, e. j
! N. i9 n( ]+ e* O4 M CXPB, MUTPB, NGEN, popsize = 0.8, 0.3, 50, 100#control parameters U) m7 w7 T) y3 M9 D7 H: @6 g
8 i m+ }& d5 c4 K5 p/ p* i up = [64, 64, 64, 64, 64, 64, 64, 64, 64, 64]#upper range for variables' y2 T9 q& T) f4 |. V
low = [-64, -64, -64, -64, -64, -64, -64, -64, -64, -64]#lower range for variables % v1 f' a7 L$ K parameter = [CXPB, MUTPB, NGEN, popsize, low, up]8 p: Y( N8 r+ W$ u# D( V& P
2 r8 C9 H8 O# P run = GA(parameter)6 {; @2 x/ ?( g* L: G9 q
run.GA_main() M% w. _4 O5 A( Z. [% I ^. f
————————————————) r- S4 b3 }0 o+ U- z/ I
版权声明:本文为CSDN博主「bible_reader」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 ( }$ N& p" B) u! o原文链接:https://blog.csdn.net/bible_reader/article/details/727826751 Z4 J# f) Q* G9 R" n9 P1 V
* F( `! A& X. [2 b
( r, C& v2 i/ l6 z+ c- n O