+ V3 i( y2 W1 w3 ?import random ! H8 n, v- F+ r$ M; R( ?& Oimport math " ]( N+ O4 @# L- tfrom operator import itemgetter 6 L! I" W( B! d" I" G7 O6 D- Q0 ?' k- P% [6 P
class Gene:6 g3 V4 d) W3 U Q) j% R
'''% }& X4 r( P7 x6 n% L
This is a class to represent individual(Gene) in GA algorithom7 v. u$ m7 J7 z# {4 b& Q5 r6 G
each object of this class have two attribute: data, size; N0 Z# t8 c3 X3 E2 E/ x
''' " }9 I+ w4 U, y b def __init__(self,**data):0 \. z! l: a4 @ r \. N+ r$ R! D
self.__dict__.update(data) 5 K D' J/ W, c8 N, `+ E
self.size = len(data['data'])#length of gene: ?' p2 `$ O3 E/ Q6 k) i4 p" F
8 M5 E( O \, i9 F" e 3 T! s h' A9 [% `& D; X. c# q7 S6 ?" Uclass GA:2 h! d# w5 R, ?3 G6 C) ~/ ^( r
'''1 H1 f1 n) V6 Q! {' p
This is a class of GA algorithm. 4 a4 O3 C& [4 H8 ^
''': t3 K5 Q: n' [* Y. I
def __init__(self,parameter): * w& k" \, H$ o- V8 H ''': r* u" Z1 i. @9 O0 `
Initialize the pop of GA algorithom and evaluate the pop by computing its' fitness value . 8 f# s% q5 J# T( A6 r+ L( m V The data structure of pop is composed of several individuals which has the form like that: ' O2 K) x3 A, D: X. v0 g: h0 q; F; R8 F6 `9 b
{'Gene':a object of class Gene, 'fitness': 1.02(for example)} 6 c2 H- V4 ^, W( ^2 m3 y" T Representation of Gene is a list: [b s0 u0 sita0 s1 u1 sita1 s2 u2 sita2] ' ~0 b& f' a. V6 v9 R$ n* v( w* f% |' z$ U. Z( I( C
'''5 f3 t6 y( _7 |
#parameter = [CXPB, MUTPB, NGEN, popsize, low, up] [( J. b5 M" V. E" ?" Y1 e& y
self.parameter = parameter ( j) B h1 |% ]: w1 j 9 y; J' G+ z }2 c7 O1 ?3 W, N low = self.parameter[4] 4 j! f9 m' ]" U) N up = self.parameter[5]0 o, |9 H8 j* u
$ S2 |3 Z2 G1 a/ q, ~1 V6 U, ^
self.bound = []8 T3 L q" U6 f# U) A7 v+ v$ s
self.bound.append(low)9 O ^9 m$ p8 y6 |9 K
self.bound.append(up)! Q; w$ z" X* T# r0 i
0 [5 U" @0 l m7 S pop = [] ' v& g0 e" n. }' w" Z/ L for i in range(self.parameter[3]):# K/ n7 i7 w& S. M0 z5 _1 |- r, _8 ?! R
geneinfo = [] " A/ C9 X- `8 D" {- { for pos in range(len(low)): ( U6 p, c1 O3 _- @5 T% L# m geneinfo.append(random.uniform(self.bound[0][pos], self.bound[1][pos]))#initialise popluation% Z5 S3 g* E6 }$ F9 }
4 `3 ]- B: A1 w( Z5 c! L fitness = evaluate(geneinfo)#evaluate each chromosome ! Y4 V6 a/ V) i+ p3 j! k& g& H: R pop.append({'Gene':Gene(data = geneinfo), 'fitness':fitness})#store the chromosome and its fitness 8 A, R! K" X u: n( X" E5 e2 k5 k6 D- o+ ?0 D% \. w
self.pop = pop) ?7 n+ e5 u' d; A# `7 |& l8 n
self.bestindividual = self.selectBest(self.pop)#store the best chromosome in the population' q+ Z* J W$ X: Q: K5 i' ]
; G6 w3 B1 K2 m( @) b def selectBest(self, pop):0 W% R+ Y k8 j
''' ) w) t3 }( m0 B4 D select the best individual from pop 4 A2 i# a& c- F '''2 @. |* `- }; d# k' n' S
s_inds = sorted(pop, key = itemgetter("fitness"), reverse = False)4 J/ K7 n6 o9 x5 ]
return s_inds[0] 1 ?9 T* ?, r$ C, u( C8 T) B& M7 i: |3 ~, K5 ]/ u4 {) ?
def selection(self, individuals, k):* g2 ?- O! T* P3 X5 B' z& _
''' , g, }$ k" ~4 D& I7 \4 k' ` select two individuals from pop+ @* K+ f" ^9 t+ p: r& h
'''% A6 K/ e1 J# v- Y4 M' J1 P# N: {
s_inds = sorted(individuals, key = itemgetter("fitness"), reverse=True)#sort the pop by the reference of 1/fitness : C( i' c/ I, s ?$ D: C
sum_fits = sum(1/ind['fitness'] for ind in individuals) #sum up the 1/fitness of the whole pop {9 s1 ]' a3 }4 d. u! ^ o
; O: Q! \# r1 W1 b0 k7 o$ w chosen = [] % P s1 q- ]) @ w% X4 B8 Z" I+ { for i in xrange(k): 6 D& ~0 p5 `3 Q# f u = random.random() * sum_fits#randomly produce a num in the range of [0, sum_fits] ' M( k! ?; |+ c0 C5 c6 z: | sum_ = 0+ H. }: j- ^/ B8 |5 s5 Q
for ind in s_inds: ) P3 _ f) S5 r6 } sum_ += 1/ind['fitness']#sum up the 1/fitness) B) p9 i! |; Z E+ A$ s
if sum_ > u:# I4 Z( r4 m# O
#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 6 g# x) ?& D! @$ a chosen.append(ind) % [9 ` R5 f. I! T3 ~ j; { break; f% j o) K5 Y4 a/ H+ y
l: `7 Y+ K" r return chosen $ p" a K) h g3 i
, {1 X+ _) ]" T N7 s. C: }
. l( k' P0 g8 M: k9 ~
def crossoperate(self, offspring):# f$ s3 s& ~/ ^ ?1 M' |
'''* ~: V- Y# R; @2 N [$ F& z& n
cross operation S$ W; k' h" e) ^4 r ''' . v ^$ S, ~* }# H" |6 K dim = len(offspring[0]['Gene'].data)/ u6 I+ {* y) ^( r: v$ v
* s& ^# ~9 M3 O0 z0 X3 N% I
geninfo1 = offspring[0]['Gene'].data#Gene's data of first offspring chosen from the selected pop: n9 R4 L" k% d2 }5 j; V
geninfo2 = offspring[1]['Gene'].data#Gene's data of second offspring chosen from the selected pop* k& W! {' Z; l
4 \" ~1 B3 x2 l- j. K& i i pos1 = random.randrange(1,dim)#select a position in the range from 0 to dim-1, : Y& q. U% H5 u. ?; {* M: t
pos2 = random.randrange(1,dim) 3 c7 S% l( ]) r" u) R1 p4 Z8 [3 ?0 _0 I! E% R( b( Y) o: E5 }1 q3 u
newoff = Gene(data = [])#offspring produced by cross operation J1 d7 D! T! K3 e( E* l* a
temp = [] 9 P) ?3 `% c1 V; t! o for i in range(dim):! H8 W& j, Z7 o6 d! W
if (i >= min(pos1,pos2) and i <= max(pos1,pos2)): , }3 w- ? t- J temp.append(geninfo2)( y8 ]: `% ]/ J* M1 V6 o
#the gene data of offspring produced by cross operation is from the second offspring in the range [min(pos1,pos2),max(pos1,pos2)]* \/ R+ x7 U: Y9 c) T/ u' s
else:" M1 k+ w/ X2 h- D# p" `1 N1 P( [
temp.append(geninfo1)4 |" J4 n% z0 w
#the gene data of offspring produced by cross operation is from the frist offspring in the range [min(pos1,pos2),max(pos1,pos2)] & j' c( }; G) `: C; B5 U newoff.data = temp 9 L2 c9 h ]9 ]& h" J# N) k; b; K6 i, ^/ E2 f. R- r
return newoff% ^4 N, G; C& b. \
* t$ G/ F: \, [' @1 l
( M2 J" f* |7 K# M) V2 o2 I dim = len(crossoff.data)' M7 Q: ]4 W. W5 g' `5 I" {4 R
# K# v& s7 s$ q2 T. u4 [6 M8 }
pos = random.randrange(1,dim)#chose a position in crossoff to perform mutation.9 z# @7 P# m' x- d# ~4 R: i
% ?! u5 }+ J& T( e/ e8 B( ^ crossoff.data[pos] = random.uniform(bound[0][pos],bound[1][pos]) 7 H6 n$ |& ~: G: G return crossoff6 R3 Y7 `$ O* [: j3 u: o
$ G4 F# ^$ T: w. |8 ^! [& h
def GA_main(self): % {9 q" Y: f4 C# k ''' ( z# I% x" F( V; G. V+ D5 ` main frame work of GA / u4 D e& q" J5 W, r- M( P- y$ X ''': i( @0 A. r: B9 r+ {
# ~4 X% M! x% Q! s0 \' E) n
popsize = self.parameter[3] + s( _9 ]. C- k/ a& M9 n9 J& ]" n% o6 W1 q( O f4 i5 J2 y8 q' e0 s
print("Start of evolution")/ v( q' E. I- {9 n5 J
1 _0 s( p2 Z7 }$ Q1 P; _6 R, t # Begin the evolution7 q1 Z$ [, v' m0 T$ p1 K, ^
for g in range(NGEN):$ \( Y6 o+ t- `# L% R) R
) e8 `; ]9 o1 I5 O6 h
print("-- Generation %i --" % g) + V% ~: u+ r& `1 Q8 c. B
& l" E, \# H- w8 {, S/ Z& B) U
#Apply selection based on their converted fitness " @! u( u$ {2 P3 e+ C0 V8 d selectpop = self.selection(self.pop, popsize) . ? J# A, @) E; G& `' E * x1 D+ p" p" i6 t e0 \2 f! f i nextoff = [] + B) l! Q* a" S* b1 {$ C( C& L' ^ while len(nextoff) != popsize: $ L" L' u U3 q$ x4 P8 Y
# Apply crossover and mutation on the offspring ' b$ d# Q0 B$ e2 Z% ^4 r. p
; k9 c% b! j7 Q # Select two individuals" r4 s+ h2 l: x3 f/ C
offspring = [random.choice(selectpop) for i in xrange(2)] 2 o! Z8 L- U! G/ S- ~/ O7 n5 d N" s u0 T2 l
if random.random() < CXPB: # cross two individuals with probability CXPB " G, Z% s: X/ a) \ crossoff = self.crossoperate(offspring) : v: z, \5 V' F3 g fit_crossoff = evaluate(self.xydata, crossoff.data)# Evaluate the individuals + A: {8 u/ _/ h4 U$ j3 k$ {1 ~2 U, T7 S( [8 i4 M! J' P) ]
if random.random() < MUTPB: # mutate an individual with probability MUTPB 7 m5 y3 H- V! e2 ?+ J* m muteoff = self.mutation(crossoff,self.bound) 5 b; e) l! l/ Z2 y4 A3 F2 C2 Z& p fit_muteoff = evaluate(self.xydata, muteoff.data)# Evaluate the individuals 2 a" v$ [- }2 x nextoff.append({'Gene':muteoff,'fitness':fit_muteoff})- P- C4 _+ B2 P% Y+ g5 g. e
" u% @( c" u/ V
# The population is entirely replaced by the offspring 0 Y8 q* e( S/ \+ Z2 E1 t self.pop = nextoff7 w$ v( q- H% }; L3 n3 S
9 P7 W) d( ?# y+ s1 `7 V1 G6 V # Gather all the fitnesses in one list and print the stats $ p0 Q9 _' ^5 Z5 q* V# q$ @4 X fits = [ind['fitness'] for ind in self.pop]! ^' H/ B4 n# D
* h5 ]+ n) Y3 T) N7 h7 B9 o
length = len(self.pop) " G) T- a& F( E; o mean = sum(fits) / length) g" W) [% O$ W$ h
sum2 = sum(x*x for x in fits) / R7 d/ P3 I. P3 S. H% W std = abs(sum2 / length - mean**2)**0.5+ `5 P- y4 x+ p
best_ind = self.selectBest(self.pop) 7 J* K1 {- B7 Q* ^4 S6 I( w" a0 y R9 r; K$ K: l: }0 b
if best_ind['fitness'] < self.bestindividual['fitness']:5 p7 a, k& T( Z0 X( d' Z& l7 n
self.bestindividual = best_ind; j( V( L4 w; Y3 |$ }
: q! H) G8 }' m print("Best individual found is %s, %s" % (self.bestindividual['Gene'].data,self.bestindividual['fitness']))* p( ]+ T* G* x) ]2 V1 k- H) b2 x
print(" Min fitness of current pop: %s" % min(fits)). d& s( U$ E& a6 d4 Z. m
print(" Max fitness of current pop: %s" % max(fits))( e' `7 K5 S; l1 I" v9 _
print(" Avg fitness of current pop: %s" % mean)2 G* J& h7 K4 I ^" |9 O3 d* D0 H
print(" Std of currrent pop: %s" % std)3 U' h1 f" K; g1 I
# k6 s) v& U& `$ |! J* o8 h6 E' _ print("-- End of (successful) evolution --") + d- w: \7 @& O! I0 B& j% v- U6 d# \4 t; Q/ w, V
if __name__ == "__main__": # M3 k$ a. Q, O% d6 r- p+ f+ p& _( A$ F0 K
CXPB, MUTPB, NGEN, popsize = 0.8, 0.3, 50, 100#control parameters . I/ m' q0 }" P: z+ r: k. r ; w0 }$ t$ C2 O: ~5 x up = [64, 64, 64, 64, 64, 64, 64, 64, 64, 64]#upper range for variables; F# y* J, @! l5 s9 @1 f% E. w+ F* J: p
low = [-64, -64, -64, -64, -64, -64, -64, -64, -64, -64]#lower range for variables5 a' E0 w* G+ V9 W" Z
parameter = [CXPB, MUTPB, NGEN, popsize, low, up] ( r5 h( b8 r. Y4 w3 x ; u9 M) p! B' a" S# S( k run = GA(parameter) $ ~5 Q7 s* t' e8 }* O run.GA_main() ( m- S# M+ y3 g8 K Z! P, T———————————————— . @! s$ b7 d' s版权声明:本文为CSDN博主「bible_reader」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。0 U# E! g& k, {7 Q- i8 x% O
原文链接:https://blog.csdn.net/bible_reader/article/details/72782675 5 P4 i- ^" {2 v$ r4 G! z1 A . a: Y9 ^: l! V U; d) g! {0 A: M& v* }5 L. f, ^