' c$ W- ~6 f h2 Q6 G/ D; {- q; H7 N- i+ a+ }/ Q- _" x
4、Python代码 ) N* U. E- J h: j4 W2 N% l#-*- coding:utf-8 -*- 8 j: h' y4 l3 z ~1 ]. O0 z, y9 W+ J8 N
import random / ^$ T# e8 h# R. k) ^; J' ?6 m& simport math0 L j) B; n; I8 T( V5 a! S" p
from operator import itemgetter* r. h8 O' T8 e% B# V+ V
0 R% t, k* D: y7 d
class Gene:/ r7 ~! X0 }" j5 T
'''% A, l' {2 d1 K- b
This is a class to represent individual(Gene) in GA algorithom U8 ]9 W+ U% k7 f- g' g8 ?
each object of this class have two attribute: data, size ' l- H8 F) E6 m; |1 t: z; T8 i ''' ' O3 e0 u- j% z, {; Q% L9 }* s def __init__(self,**data): & M2 i% U4 b+ R self.__dict__.update(data) + J9 w& n, u6 W( @
self.size = len(data['data'])#length of gene2 ^. \5 C7 V, h' q) [
% Y8 S+ U# p& G4 |, u
0 |+ F1 O9 _8 u7 J+ [
class GA: $ @7 g F3 K. x+ V# a" ~( K9 W '''+ r$ B( h* R c, P# M* R- N3 ^
This is a class of GA algorithm. 6 X7 }; W( e8 _6 L
''' ! M$ W& g" Y2 K; A" r+ }# e def __init__(self,parameter): 1 ]) Z; A! Y" J# V+ O: H3 P '''+ m( e& }0 X( ~, m& r C8 y7 O
Initialize the pop of GA algorithom and evaluate the pop by computing its' fitness value . 8 j9 } C% |. D% v5 } The data structure of pop is composed of several individuals which has the form like that:1 _$ u, g% t4 V6 P4 J: H1 q5 u8 W- t4 }/ @
) {) a8 R4 X8 t; T2 b& h
{'Gene':a object of class Gene, 'fitness': 1.02(for example)}" x. \/ j6 A9 u! {. N; E+ A3 s
Representation of Gene is a list: [b s0 u0 sita0 s1 u1 sita1 s2 u2 sita2]! T# ^, H* T. a% ]$ M& Z
b: o' Q- O' _" {( c: L h9 f+ k- f
'''4 W& V8 k# o0 T j
#parameter = [CXPB, MUTPB, NGEN, popsize, low, up]! _- `; K8 S5 l
self.parameter = parameter , k% j' e6 p0 Z% ^ 2 I( y# A) T* N3 R low = self.parameter[4]# K+ U9 j; U7 @- q- G) R. x4 I6 H" U
up = self.parameter[5]* F: K7 Z1 q; ^/ q8 U& i2 N
7 {% z5 n; I: k* F" u& ^ self.bound = [] , X" C- I5 I: c A self.bound.append(low)' W3 g N9 ~- u5 l
self.bound.append(up) ; g( Y* f" f% f2 _- |2 N. x' {( R# l5 V, h# T% H% N
pop = [] 6 d( Q) T# s, Q v$ r. Q# ]/ v for i in range(self.parameter[3]): * z8 W7 n+ ]+ I6 o geneinfo = [] ! H9 A4 [! Z# J0 G4 ?% n for pos in range(len(low)): 3 F. Z) A5 v+ L! ^! a& V geneinfo.append(random.uniform(self.bound[0][pos], self.bound[1][pos]))#initialise popluation 5 k' ~- d. e1 P3 Z: \% U+ b5 q , j9 @, d* K& t1 P8 Y P4 l fitness = evaluate(geneinfo)#evaluate each chromosome0 U S$ R" Z* g# t
pop.append({'Gene':Gene(data = geneinfo), 'fitness':fitness})#store the chromosome and its fitness) |8 S: u3 D$ t$ R( t G' ?7 n4 X
0 X( A: x# B4 i9 P; W self.pop = pop# A2 R1 {, i' i
self.bestindividual = self.selectBest(self.pop)#store the best chromosome in the population+ {: a2 j3 p2 O( b' i
$ ^ x( ?2 r4 z/ h( C/ Z3 h s x- C def selectBest(self, pop): 4 q0 Z$ S4 N) j1 U) q5 G, T* ] '''+ n6 J1 ?8 ]* g7 K0 R) b
select the best individual from pop ( w0 F1 ], H, ~% Q( ~8 A. M! _4 T '''7 `3 a! ^2 |2 b! e* t/ a( {) e
s_inds = sorted(pop, key = itemgetter("fitness"), reverse = False) ( T* D; F! D3 E return s_inds[0] + W1 ?( \% I# S2 t * a7 m, m2 p2 Y7 F& L def selection(self, individuals, k): & p$ U' w& C' B" T# ^ ''': Y' L; Q2 x8 g1 h0 T- E' ^4 c
select two individuals from pop7 v% m% w! V; ^$ O! H
'''( |7 ~) e3 g* S! K5 h0 v
s_inds = sorted(individuals, key = itemgetter("fitness"), reverse=True)#sort the pop by the reference of 1/fitness ) ~" E4 \0 s; X2 j sum_fits = sum(1/ind['fitness'] for ind in individuals) #sum up the 1/fitness of the whole pop * I" T0 Y) w7 |0 ]! x4 N- g' X+ B D5 Y. d' P6 G8 p+ Y
chosen = [] 5 m# ~/ G9 {8 u$ ?. m4 @1 p for i in xrange(k): $ [; q9 N9 [ N* P% A0 ^. [- y+ q5 K: X u = random.random() * sum_fits#randomly produce a num in the range of [0, sum_fits]2 g9 x) t; A- @
sum_ = 0 + E+ F, J) b$ M1 M& @0 N2 F for ind in s_inds: 5 J: d3 N7 F; j3 ~! w5 P) H sum_ += 1/ind['fitness']#sum up the 1/fitness3 H* M1 K# T, W. ^; Y
if sum_ > u:$ V- O& n: T5 J9 {% W2 U
#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 $ ^& h7 M' _; ^ chosen.append(ind) 0 ] n# O6 B5 t- e% E' w break M; h5 m: L( p' d& j% ] ; ^: O& I5 J L5 ~7 x return chosen " q0 G6 s' w0 z2 f
% Q* \; V1 Y$ y, l , I& l0 ~$ x0 n0 C+ I& y A% Q& ]; l: w def crossoperate(self, offspring): , l4 ?; q- J( t2 C8 w. b9 o ''' K; ? q$ v( p- D: t' ^ cross operation- e& M0 R; x9 d# R# D! d2 u& I
'''% ]5 x& ~# z+ ^3 S
dim = len(offspring[0]['Gene'].data)4 u1 w7 T: A0 z
& m# D0 \' D5 \& h2 g9 [# G' W geninfo1 = offspring[0]['Gene'].data#Gene's data of first offspring chosen from the selected pop7 D$ j! l/ p! w
geninfo2 = offspring[1]['Gene'].data#Gene's data of second offspring chosen from the selected pop 7 G. V3 f$ d. l- [/ y" `" Q: t3 E# T" m6 r# G
pos1 = random.randrange(1,dim)#select a position in the range from 0 to dim-1, , h4 h4 _0 a$ Y5 ^4 }" h
pos2 = random.randrange(1,dim) # J1 m# g* [! D1 u' d" z 4 e$ Q, [* I, Y7 D6 s3 f newoff = Gene(data = [])#offspring produced by cross operation # @% D: m+ U: ]2 s2 v _, Z8 g temp = [] 5 y8 E. C: ? t2 h h0 f for i in range(dim): ! ~( z- D7 C; C if (i >= min(pos1,pos2) and i <= max(pos1,pos2)):. b3 R, [! h, O+ H7 B
temp.append(geninfo2) $ t# y0 q" P: r6 a #the gene data of offspring produced by cross operation is from the second offspring in the range [min(pos1,pos2),max(pos1,pos2)] `7 p4 E8 H. ]' ~ else: 7 X' y2 j- l( t/ o, }8 v temp.append(geninfo1) 3 O* a; w" J: Y) { #the gene data of offspring produced by cross operation is from the frist offspring in the range [min(pos1,pos2),max(pos1,pos2)]/ B7 d# k$ j$ ~5 y) i, A/ K" B
newoff.data = temp/ j6 Y* x7 v+ Q
: l' S7 j. }$ N% | return newoff; Y4 L- y; v; X2 \8 c5 [
$ k$ i5 U3 m9 l& c% ^0 r& N/ s
, N0 I! m* J+ V6 Y
def mutation(self, crossoff, bound): * M- b8 e" F$ B2 {" q Q5 T '''5 p7 j9 P t& \
mutation operation# ~$ Y2 Z# N* _6 D6 z w
'''! H: _# V! R& F6 L1 p
$ D2 a& w2 g( I0 W& i. w
dim = len(crossoff.data)/ k! n$ o# P" }5 N7 b/ u: G+ b
7 @5 I7 {$ K* f% P4 d/ ^
pos = random.randrange(1,dim)#chose a position in crossoff to perform mutation. 2 P: w6 M5 w- I3 h( V, y6 b# J ' b- p9 T/ a7 i- P9 z crossoff.data[pos] = random.uniform(bound[0][pos],bound[1][pos]) % W: A. S& n3 B+ g; P7 S return crossoff" `0 {5 Q( q2 g0 P
4 \1 ~, M2 n; n: p/ E/ ~
def GA_main(self): $ h+ w2 O3 ~9 G, L& a& D) U ''' ) c8 H; c. M# r! u, Y main frame work of GA$ n) g" r N8 c8 G
''' # ^1 u7 E4 d4 Z6 I+ l3 V. m. R% M" F, b7 ^/ u% K l: F$ A" m1 L
popsize = self.parameter[3] 5 S9 N- q/ o( G4 M! k. j0 C. } ?7 P) r, _6 G: M
print("Start of evolution")8 A/ B% l% y0 e
9 q# U) u& b- f S2 v2 e3 l# h. k+ |8 A, `
# Begin the evolution 9 S0 c ~' W% B( I3 \# } for g in range(NGEN): 5 D, E' B* O( C1 z5 O; G* a( R 1 _* N2 u2 i$ ?- g! V) Q print("-- Generation %i --" % g) 7 q& Y6 r5 z. C0 c" |
: J3 P) T' ?7 Q9 y& B #Apply selection based on their converted fitness8 g) @6 F1 j/ O- C3 ?
selectpop = self.selection(self.pop, popsize) , u/ ~ A( i! I( G9 N3 o: o ) `6 G# P1 A4 h! D9 s6 h, g nextoff = [] 3 S! P: l" r6 m0 l# O8 a& S8 D
while len(nextoff) != popsize: : v1 ~; I& h1 R+ w0 x # Apply crossover and mutation on the offspring 2 T7 T( Y! C1 \4 }0 B% f
N) n3 }, N$ \3 `
# Select two individuals& t& b+ e1 _% |
offspring = [random.choice(selectpop) for i in xrange(2)]3 u7 v* M% S0 m% }7 s
( X0 c0 q( Q/ Q- F" A# n3 Z if random.random() < CXPB: # cross two individuals with probability CXPB , J* \1 Y" Z' w& \ W. a% `# \) L crossoff = self.crossoperate(offspring) 3 M' g9 K2 [2 Q9 A1 X4 b4 D fit_crossoff = evaluate(self.xydata, crossoff.data)# Evaluate the individuals ! A' `( u" e$ L- E' H5 a7 v6 v
, J; q( R1 m: G5 L if random.random() < MUTPB: # mutate an individual with probability MUTPB ) G, W+ y: Z1 s; A! a& Y muteoff = self.mutation(crossoff,self.bound) - _2 h v" B3 b4 B3 Q7 A8 t fit_muteoff = evaluate(self.xydata, muteoff.data)# Evaluate the individuals+ {1 s" {1 p9 }1 X' a" |# g- |+ O# t
nextoff.append({'Gene':muteoff,'fitness':fit_muteoff}) 5 J0 ~6 F" @1 H$ l ; @0 D; {9 a0 Z; {' L: X4 X5 B1 A% Y: n # The population is entirely replaced by the offspring , t, G! B% h. {) ?; u/ p+ L5 t self.pop = nextoff ! Z9 A/ J# i" X0 H3 h8 z: a. Y, t; o; t; [6 D V4 @% i
# Gather all the fitnesses in one list and print the stats # E2 Y1 B9 G, ~% R! f fits = [ind['fitness'] for ind in self.pop] - q! V# Q9 r9 h0 }6 i5 m/ \9 K9 `( n$ v$ p4 A3 \, w
length = len(self.pop) 4 J* _1 u& b' ~# C9 x7 v$ U! M mean = sum(fits) / length4 R# x$ L1 y8 t
sum2 = sum(x*x for x in fits)1 Z! o& P A/ g! N
std = abs(sum2 / length - mean**2)**0.5 , Z a3 B! p5 U2 @) q; J; R best_ind = self.selectBest(self.pop) 8 J* `0 c3 W3 C1 D& u0 \7 @! v! f, K4 y' p# S( O" G; E
if best_ind['fitness'] < self.bestindividual['fitness']:& E8 N- k8 \4 `) _/ D: j7 S
self.bestindividual = best_ind* t7 ?! ^+ [* q( R4 m; {* L
1 [% a' O5 k' h# \; V print("Best individual found is %s, %s" % (self.bestindividual['Gene'].data,self.bestindividual['fitness']))% w9 R1 k% s1 E: \& ~* N
print(" Min fitness of current pop: %s" % min(fits)) ( @4 R( g; w: M( W4 J, X0 { print(" Max fitness of current pop: %s" % max(fits))3 T! K* f" d4 j% b
print(" Avg fitness of current pop: %s" % mean) % h7 h4 ]! p& [6 k) } print(" Std of currrent pop: %s" % std)8 L2 x: U$ Q- H" t
! P' N/ D$ V3 C6 @, L8 |
print("-- End of (successful) evolution --") 4 W+ M2 c6 o, M3 N" x, a