' a$ {6 R' Y& R% f + a- g. U" _8 O% I6 ]5 ]4、Python代码/ @+ A [( R0 x. V8 P0 m
#-*- coding:utf-8 -*- " `, Y, j) ^9 x) S0 ?$ {: p. |% z, Z" g) g
import random1 r+ d- s& {7 f; H
import math) V' V, C6 ^1 a [& T
from operator import itemgetter 5 C2 G+ X3 d( @- H1 }* L8 e W. W
class Gene: / j& n2 w/ j9 z* T6 [. h! E3 G ''' }3 I; f0 G) F0 n' u This is a class to represent individual(Gene) in GA algorithom$ X$ g( Q1 n* ]- N
each object of this class have two attribute: data, size - F9 z; Z m: M) c3 W '''+ |; [4 D' |5 r2 F6 Y( z8 D
def __init__(self,**data): ! b+ Y4 R: p' _$ ]5 F self.__dict__.update(data) ; [. V2 i! m+ B( F& L' P! s% C
self.size = len(data['data'])#length of gene$ c9 {9 B, e4 ?* M6 c
( }9 y9 e! l2 U' r2 s6 q' R
( s4 Q3 a- e3 P2 B2 U
class GA: . K& a$ Q- u) S1 [: h% E, @! I '''; n; n) p2 O$ q8 j" I Z2 O
This is a class of GA algorithm. ( U2 G& E, p( @! ?% @0 l# j* r) a1 { '''0 p) D4 d% W6 r
def __init__(self,parameter):4 A/ c( s% `' t* g- J$ h
'''' k* S. u3 x) L# n
Initialize the pop of GA algorithom and evaluate the pop by computing its' fitness value . ; V2 B2 d I9 c5 t The data structure of pop is composed of several individuals which has the form like that:" U- D* c0 V4 K2 U4 f
; f2 T4 G: s% J& \ @" }/ V
{'Gene':a object of class Gene, 'fitness': 1.02(for example)} , V1 }/ l2 f) _! j! c( o Representation of Gene is a list: [b s0 u0 sita0 s1 u1 sita1 s2 u2 sita2]0 j7 N( T! d! v! Q1 d
6 ~. r! Z) b0 |. N8 _6 n8 ?
'''7 Q1 e7 L& o0 U( Q
#parameter = [CXPB, MUTPB, NGEN, popsize, low, up] : H8 r2 c4 b& f self.parameter = parameter . \- X0 C( z. |( `* F9 j" L L. j9 p. p3 {3 K$ r: w
low = self.parameter[4] 2 W' Z" a1 Y- J9 \1 O up = self.parameter[5] ) e9 Z0 Q/ p2 G9 E* H/ U Y d: d9 D: s7 w# E0 u self.bound = [] + M) w, o* f; O8 ~( Q self.bound.append(low)) V. ~. w$ j; Z# z% ]* t) b$ ]
self.bound.append(up)2 i- E% u: x+ `% _5 _
( r' L2 s W% _. j pop = [] 9 |4 ]9 @# s) ?% k- | for i in range(self.parameter[3]):! a7 }/ j' ?/ h* {4 V
geneinfo = []' ?, b, X0 T2 t) \, f% w* L
for pos in range(len(low)):( O8 I( ]1 W1 [# B
geneinfo.append(random.uniform(self.bound[0][pos], self.bound[1][pos]))#initialise popluation ( F$ c9 H% x( \, s. A( N, {+ G! f
fitness = evaluate(geneinfo)#evaluate each chromosome* _7 S# Q4 `5 }
pop.append({'Gene':Gene(data = geneinfo), 'fitness':fitness})#store the chromosome and its fitness 2 @; [9 w6 w$ d8 ?3 C6 g4 c2 G7 {8 V0 d2 p" `: C8 w W* N& R
self.pop = pop 4 q5 l; k; ?, E self.bestindividual = self.selectBest(self.pop)#store the best chromosome in the population; n: S- |) @( {5 Q# p
* o: P5 w# F8 F9 b2 v def selectBest(self, pop):/ y* q( N b7 m! F& H$ k' g1 l
''' " ]' ?/ }$ M8 J select the best individual from pop, a% a( C( Y! E4 P& x' `2 U
'''" @6 U$ Y5 @, q L
s_inds = sorted(pop, key = itemgetter("fitness"), reverse = False): H! `6 q' M9 u- v( L% v
return s_inds[0] ) q% V: X( H; f7 ~ `+ f* Z+ A8 F' q Z2 G0 Q w) U) b
def selection(self, individuals, k): 9 n+ k3 e1 s( Y) l t0 k* B '''9 c6 T4 k: f3 g/ p/ \
select two individuals from pop ) z3 H; _$ C- L6 J ''' " h; s- ~3 D* V8 m4 x s_inds = sorted(individuals, key = itemgetter("fitness"), reverse=True)#sort the pop by the reference of 1/fitness 8 h( F3 e) V; k. S
sum_fits = sum(1/ind['fitness'] for ind in individuals) #sum up the 1/fitness of the whole pop8 t# U$ i# }8 }% _9 Z
' `! G" _, ~' `% k
chosen = [] / K( B' j. C! `/ ^2 J3 U& N- | for i in xrange(k): / z" c+ b$ A1 o0 N, M% {, p u = random.random() * sum_fits#randomly produce a num in the range of [0, sum_fits]! p1 W' [9 y- ]
sum_ = 0; L( y. I( W+ S& ` p) e
for ind in s_inds:; I' Y# q- O! A# x8 F4 n
sum_ += 1/ind['fitness']#sum up the 1/fitness 2 B9 `: Q! Q; x# p; j if sum_ > u:' M) f$ y, e$ ?/ Q% N) G0 G% s
#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 + A0 r0 m4 O* b& q chosen.append(ind) * Q4 ^+ R. C4 W5 I break% q4 B$ v: _5 s h% a. ]4 e( S
' T! K$ [- S& ] return chosen 2 d9 p* M! X$ M8 `1 N- i: b) a( i# u) j2 g, U* Z. g) ~# J' D
! ]5 q+ D0 n1 {" r' B4 v5 V
def crossoperate(self, offspring):& B! V; z: \8 M( \: j! w
''' - N' K$ z. \4 k) i. [ cross operation3 |0 v' y# y1 J
''' ! S5 I7 M3 {; Q# `3 Q dim = len(offspring[0]['Gene'].data) ( l$ M" Z# U2 U- V l5 O7 }. l) ]% m; @0 | geninfo1 = offspring[0]['Gene'].data#Gene's data of first offspring chosen from the selected pop/ b8 \" D4 f$ n
geninfo2 = offspring[1]['Gene'].data#Gene's data of second offspring chosen from the selected pop & { v, N& s8 W& V2 w) _- L 1 @7 C4 \: _$ o. u& T! V, K pos1 = random.randrange(1,dim)#select a position in the range from 0 to dim-1, . s4 j; N) x" ?) S) [; ?; S pos2 = random.randrange(1,dim)# r3 _9 G% B9 N, n
- c! B8 | `7 C/ [ newoff = Gene(data = [])#offspring produced by cross operation r' M O, a0 n3 U6 }# ]
temp = [] % h l( G# b% C/ ^" t for i in range(dim): / Y( f$ v4 G0 T0 J) G& l4 n if (i >= min(pos1,pos2) and i <= max(pos1,pos2)): " y) V6 T) q, k+ V& k2 z temp.append(geninfo2)6 |9 O7 i; q( e
#the gene data of offspring produced by cross operation is from the second offspring in the range [min(pos1,pos2),max(pos1,pos2)]' B5 a8 o" n" j6 ^& t; q% `$ U; n
else: D( F& k: N) [. Q5 J; _
temp.append(geninfo1)/ V. v8 V9 T: f1 |0 B. p* f
#the gene data of offspring produced by cross operation is from the frist offspring in the range [min(pos1,pos2),max(pos1,pos2)] 8 X: p0 g$ G: ?+ I; M; d9 I/ \3 D newoff.data = temp4 ^9 ~4 |; x( i7 p7 z, c
/ M3 \/ b/ B ?' e: f return newoff & P# J8 c, o- F0 g9 l 7 U4 T1 x2 p& r1 o 4 ?3 H9 H& f: n def mutation(self, crossoff, bound): . E e& ^- ]$ \ '''7 ^. Z6 i+ i& ~3 z
mutation operation ! O- ^; U2 a, Y9 ^! L; i6 e ''', E/ V, s9 `5 M/ F: S( r! ~8 Z8 F
4 x" n' K% X' ~- d
dim = len(crossoff.data)" {5 X: x2 X: J) S$ J B5 z
7 [3 w2 g' C+ S3 b pos = random.randrange(1,dim)#chose a position in crossoff to perform mutation.# g$ S1 {' k4 _1 w1 `
: L$ S3 R: y/ }) n% h Q& k
crossoff.data[pos] = random.uniform(bound[0][pos],bound[1][pos])! @5 T; }2 K/ J+ v7 `6 ?) ^" L
return crossoff7 N) Z& Q5 r# X+ y
) b# y# Z5 k# x
def GA_main(self): 2 V" f" b) L) S U J" D( H8 U ''' r, A9 D2 z* W }) W
main frame work of GA7 [% m/ N' }- D* w
'''. v; ?2 m1 [8 f. F$ N9 T
$ \# C& G" O0 x! h popsize = self.parameter[3]; k" T H7 }! B& T4 E* O
- @. S" @; q( B: c/ v( D
print("Start of evolution")3 m! O/ D. u4 y& m
8 ^3 C3 ?2 a' I9 m
# Begin the evolution3 N, j9 E9 O0 a' g
for g in range(NGEN):6 S k" P+ T% @2 h1 p( g
0 p Z/ ] M/ r3 ?2 N% _: v/ y+ n
print("-- Generation %i --" % g) + q! h/ N Q- C h8 m8 q
! ~0 B/ ^, t, m" I8 | #Apply selection based on their converted fitness - E, Z# U0 b1 G+ \1 d- V1 Z selectpop = self.selection(self.pop, popsize) 6 ^ [# ]" J4 F. Q4 y# _& t- m' J& T5 [: z [7 G6 Q
nextoff = [] * T* W; }$ J {# D2 ]$ i while len(nextoff) != popsize: 9 A5 |/ H& P- U9 N" ~ # Apply crossover and mutation on the offspring 6 f" q9 o' e( l4 V' A) n 6 P) N, m7 a( Z3 i7 N) Z # Select two individuals , P. F! {+ G* T% o+ M. v offspring = [random.choice(selectpop) for i in xrange(2)] Y) q1 q/ x2 ]' e! q8 I" m- i* m / n& v7 I& z0 @( I v if random.random() < CXPB: # cross two individuals with probability CXPB7 d6 l, s/ ^' L8 g' L6 y! ^; Z/ y- X
crossoff = self.crossoperate(offspring) h, H. Y- q' ]2 j) k5 I: @3 k
fit_crossoff = evaluate(self.xydata, crossoff.data)# Evaluate the individuals $ z2 c, x' X( g- M1 \; V
: E% ~; B6 M% A. t" A6 s' d k
if random.random() < MUTPB: # mutate an individual with probability MUTPB # B- ^/ O' P1 ?) _! x muteoff = self.mutation(crossoff,self.bound). o5 E+ ^5 h* k5 G" x+ V) e( r5 _& y
fit_muteoff = evaluate(self.xydata, muteoff.data)# Evaluate the individuals- T: q6 G( T* ]+ I" @
nextoff.append({'Gene':muteoff,'fitness':fit_muteoff}) , C# a" o' V! Y1 v! v+ @" T l 2 ?* U% q' J# l z # The population is entirely replaced by the offspring, _* m1 w/ L r, _/ n
self.pop = nextoff! D' k5 Y$ L' O/ c/ x
5 A' ^5 b+ F& r, a
# Gather all the fitnesses in one list and print the stats" A9 F$ n1 a$ P w1 X+ U- ?
fits = [ind['fitness'] for ind in self.pop] 9 ^8 ^7 f! y) D& `: I- @" Z ( Y& Z( r1 L% w( a2 C* _$ o+ z length = len(self.pop) 4 O" {! _% C8 G8 D3 m, R mean = sum(fits) / length6 b8 O2 S) G& p/ U
sum2 = sum(x*x for x in fits)$ Z+ J1 ^" G3 i2 |( J* H1 T! j
std = abs(sum2 / length - mean**2)**0.5- v$ {+ l1 {% g+ K2 `/ j$ A
best_ind = self.selectBest(self.pop) , t7 M- f4 P0 c! z+ V3 G$ q! K( N* ]1 C
if best_ind['fitness'] < self.bestindividual['fitness']: 6 P8 |, j y7 _9 @' v0 I self.bestindividual = best_ind % m5 _# G5 `' M8 @# H1 O8 J 2 ^6 J) F! H5 X) D print("Best individual found is %s, %s" % (self.bestindividual['Gene'].data,self.bestindividual['fitness'])) + Z6 t7 s0 P: n print(" Min fitness of current pop: %s" % min(fits))3 J( u4 Y+ O- m5 F6 k( G1 b
print(" Max fitness of current pop: %s" % max(fits)) ! N$ e3 Y6 b; \9 d" ?7 ] print(" Avg fitness of current pop: %s" % mean)7 H' e$ l9 H7 p. N9 c1 K( A, V
print(" Std of currrent pop: %s" % std), C% K! i. k5 ?" v x6 Z
a! H% N- j% }* F print("-- End of (successful) evolution --") m/ ]; i G _- S4 [7 l( j
3 j/ J, Z* R: p) A9 I) |( I' \2 k
if __name__ == "__main__": 4 Q @/ ~ m, w7 e) A- Y% @; J' X! s/ s
CXPB, MUTPB, NGEN, popsize = 0.8, 0.3, 50, 100#control parameters . C# t: S2 w! w% L, V ; f5 c. B& X! a. m up = [64, 64, 64, 64, 64, 64, 64, 64, 64, 64]#upper range for variables# Z$ I3 ?7 q8 ]- Z8 G* Q3 `1 c( C
low = [-64, -64, -64, -64, -64, -64, -64, -64, -64, -64]#lower range for variables- t: x$ B9 u0 Y& ]) @: f
parameter = [CXPB, MUTPB, NGEN, popsize, low, up]1 R2 N! B0 O- G