* T4 a1 i9 r6 y+ {3 a$ z3 Xclass Gene: * V P' ^' v* ~1 o9 L2 g4 C/ ^$ k3 u' L '''5 H, f: e4 `) ]& E
This is a class to represent individual(Gene) in GA algorithom! E7 w: \4 p5 r! `3 S1 x6 f" U6 n3 d
each object of this class have two attribute: data, size* y8 w' C4 {$ a8 x2 P5 O9 S h' J5 b
'''1 |/ u" s" K+ o: H1 y+ e, ?
def __init__(self,**data):0 z6 {: y1 m( {* _% u7 v, P
self.__dict__.update(data) K) p, t N( f self.size = len(data['data'])#length of gene 8 W- D2 }# Y6 o( C' }8 \+ Z E! L8 I2 ]2 K) i# j
" u/ t, n2 V. j& q2 V e- [
class GA: % B T, w" d9 n1 C& i ''' - X) n/ Q5 _0 i$ f+ r) {$ X$ Q This is a class of GA algorithm. " G6 H/ H1 i6 B ''' ' w" K# z" G9 y2 S$ y) H def __init__(self,parameter): 4 e1 m1 K" n+ b ''' 2 T9 m0 l0 [) S1 c5 _/ V2 e" C Initialize the pop of GA algorithom and evaluate the pop by computing its' fitness value . : g, A7 O/ O6 B5 Y The data structure of pop is composed of several individuals which has the form like that: ; j% v/ U6 n7 v# @% r5 N 9 @9 Y/ t& }, b5 ~6 Q' v( @4 R* F {'Gene':a object of class Gene, 'fitness': 1.02(for example)}+ h {; D. i6 t9 z6 B3 h
Representation of Gene is a list: [b s0 u0 sita0 s1 u1 sita1 s2 u2 sita2]% G' V8 v0 `; ^8 F& O
: E7 T/ I, S8 |
''', i; k, C9 W9 C$ }8 S% q
#parameter = [CXPB, MUTPB, NGEN, popsize, low, up] ; `, ^: J6 D* n( Z% O8 y0 U self.parameter = parameter : m* _$ P. Y* S( F: b % {3 A4 O O! X7 R# D low = self.parameter[4] , a0 r2 i {" t) K1 D, ^1 c up = self.parameter[5] ' o' B( I4 E5 b- w% `, ]6 z 8 g- c1 v4 E+ F' p& g self.bound = [] ) x0 |+ y( E/ _ self.bound.append(low)/ K/ N9 C! r$ }; d( i
self.bound.append(up). ]! r% ]+ @. h# k
0 M( K5 c$ d! _' q) f a6 G3 x$ a& K
pop = []% o+ R3 M% v$ A# O1 l1 d% {" k
for i in range(self.parameter[3]):5 f3 ?( }# R _5 G$ g3 o6 O5 J
geneinfo = []3 L4 t) n# z; Q& p+ C1 N P& e
for pos in range(len(low)):* n0 D6 k* ]; j: }( j* Z
geneinfo.append(random.uniform(self.bound[0][pos], self.bound[1][pos]))#initialise popluation # |' h' _+ }2 B1 G0 A7 u0 n5 V9 S2 i7 ]% _% S9 y
fitness = evaluate(geneinfo)#evaluate each chromosome( R' _6 T- e* E! e" e: U4 f! M
pop.append({'Gene':Gene(data = geneinfo), 'fitness':fitness})#store the chromosome and its fitness . O9 `5 Y7 ~3 S K7 Q * [0 _2 c7 ]& t& F* X; W self.pop = pop5 Y5 @0 s; m, B& ^, u! r9 Y1 Q9 O% H
self.bestindividual = self.selectBest(self.pop)#store the best chromosome in the population% t R4 [! j( ~6 y+ ~
9 S- C& ]) M; T% ^" ?; g
def selectBest(self, pop):% P; k7 T" R) k
'''6 r* K" ~5 f0 B% h% P6 W' F9 @
select the best individual from pop . H: ]& K- b ] '''; v! t; [0 u7 `- p
s_inds = sorted(pop, key = itemgetter("fitness"), reverse = False)" x; `3 S' m) b$ ~ O8 A
return s_inds[0] 0 B, ]* q% J2 i h . I8 B; X4 s5 H, D2 @) ^ def selection(self, individuals, k): / S, { w Z1 t '''$ O, e7 O! Y! f2 a' ^
select two individuals from pop 8 O- K0 L: H! J" |0 p' d# [ '''( \6 }& q7 o F7 j; O3 o" D) ^
s_inds = sorted(individuals, key = itemgetter("fitness"), reverse=True)#sort the pop by the reference of 1/fitness 7 U( k# P5 t' O# _' ] sum_fits = sum(1/ind['fitness'] for ind in individuals) #sum up the 1/fitness of the whole pop1 l% p* S P% {0 u
' d4 k" Q, G/ T+ A$ {- W chosen = []6 }, c/ w2 @5 ~" a0 _6 p) _" D
for i in xrange(k):) B& Q) i8 W; |
u = random.random() * sum_fits#randomly produce a num in the range of [0, sum_fits] + C- W, {' C" v7 K4 ]3 r+ c sum_ = 0 / W7 A: U0 \1 ?9 W for ind in s_inds: / e. v1 I3 }0 n. A sum_ += 1/ind['fitness']#sum up the 1/fitness 4 k2 M6 P l8 t5 M4 V if sum_ > u:8 G2 l& B9 m7 Y0 L; Y- s5 k
#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 pop9 S& T! H, u4 u9 Y8 e- j
chosen.append(ind) e$ B6 Z2 k! T) o& \
break+ r0 x$ f; i+ P# B$ J
. N5 |8 l+ G- L8 b
return chosen : i8 S" _+ N8 O ) o, U# C9 w, X# P" p1 F' ?1 M* l" n
def crossoperate(self, offspring):! s# B* Q# R3 r' j- l; V* I
'''& l& d O1 V0 O+ i8 b
cross operation z! I- q: x! K& ]4 m4 j% J ''' & G) d& \9 Q/ w' w8 b+ D dim = len(offspring[0]['Gene'].data)* p( c. }$ T1 A1 u1 f$ {7 Y3 h7 e: k7 _
# w( g& c8 v1 E( l# f5 q geninfo1 = offspring[0]['Gene'].data#Gene's data of first offspring chosen from the selected pop$ E4 }4 q0 } O$ r( X5 r. l `
geninfo2 = offspring[1]['Gene'].data#Gene's data of second offspring chosen from the selected pop + I2 j* G- \1 R: j: @3 V5 Z6 j1 s ' W+ B7 N0 H" s6 s pos1 = random.randrange(1,dim)#select a position in the range from 0 to dim-1, / o8 O" N. l! P- ~+ A1 N$ U/ _# | pos2 = random.randrange(1,dim)4 u4 a! c% e/ s3 z. J9 a# H
7 f4 a# L# {: ^3 O4 M
newoff = Gene(data = [])#offspring produced by cross operation* P; W! x$ K) t. {# F, ?& u4 C/ _+ d6 X
temp = [] }, e9 g: E. Q/ A for i in range(dim): ) S. D7 h" Q+ W9 i& c' V: Z if (i >= min(pos1,pos2) and i <= max(pos1,pos2)): 6 n! a3 O: z4 S6 Q& |2 |3 [% f+ s temp.append(geninfo2): @; n( N7 f& }2 x* f9 `
#the gene data of offspring produced by cross operation is from the second offspring in the range [min(pos1,pos2),max(pos1,pos2)]% z: \% W* D( u) m6 b
else:6 H& G# C$ |: f5 {3 t2 p
temp.append(geninfo1) ; \; T& _) p# j" d" } #the gene data of offspring produced by cross operation is from the frist offspring in the range [min(pos1,pos2),max(pos1,pos2)]1 `0 |( L6 O; a6 E1 Y# a4 d
newoff.data = temp ( p) P$ y: h5 Y# D' D8 ~! K4 C1 J" j! v/ k
return newoff ) K) y8 I7 K. q1 B C- X \/ z" v6 f+ U( c! x( `. P
, K7 a, j4 e" I! F4 R
def mutation(self, crossoff, bound):7 @7 ]3 ?, z, y5 X
''' : \# k: d, a7 ] mutation operation, M# [! G& N5 |
''' ) D% ~7 ?& ~% n- k7 | % L4 O- T0 d! | dim = len(crossoff.data) # }- h/ L( ^$ F4 ?9 x. B- k# O( L8 B6 K( E% H. j/ G8 \2 k
pos = random.randrange(1,dim)#chose a position in crossoff to perform mutation./ y: v3 m( p7 I* s) l
& I, N$ G0 t, g# P$ g crossoff.data[pos] = random.uniform(bound[0][pos],bound[1][pos])7 ~5 e W3 ~ M [4 Q
return crossoff % `. e4 j' P4 e i" v$ e7 K5 ~, T6 c1 }) C* h7 q" J
def GA_main(self): & ^* U4 v# W& x) C. x ''', q9 T! q. i, e& r
main frame work of GA6 y) O$ A* _' m( a, N
'''# [5 F4 }4 `, P$ e5 w% d
& N5 g* |% Q* y: d- Q! X" C! _! R4 V
popsize = self.parameter[3] * W% N& O" `' _/ T) t, n# f% }" a . x5 {% L! w9 |8 {0 D _ print("Start of evolution") s! Q) B7 g( j& Y d 3 H* J6 j0 X Z' h. k# N # Begin the evolution2 a, ]/ E- m, j' [
for g in range(NGEN):1 h3 J5 j) x* u7 s8 X9 h" t
1 q; `" \) e* l+ E" s0 ^
print("-- Generation %i --" % g) 4 e( `: u- Z8 M
; C! d4 q" g" W
#Apply selection based on their converted fitness " P& V/ R7 r8 n7 V+ J3 ? selectpop = self.selection(self.pop, popsize) ( H: q! \+ b5 g/ H2 ]
$ o( h% H! V4 `& [ nextoff = [] : }& [1 Z% ^/ M* N. d
while len(nextoff) != popsize: / B0 l: t( r% [6 N1 }" N$ P
# Apply crossover and mutation on the offspring # P" ^3 n; i' }9 A1 R0 H( [ - F* u4 Z- g* M! B& \9 j' K # Select two individuals - r3 {, x& M' S1 ]( H3 n" Z offspring = [random.choice(selectpop) for i in xrange(2)] c5 o$ P# V8 Z0 q" `! y5 y, J 3 X! W2 Z/ J4 ]/ q7 q7 Q if random.random() < CXPB: # cross two individuals with probability CXPB + m- Z% a( S; c1 \5 D2 {( u; ^; w+ w crossoff = self.crossoperate(offspring) 1 Z- M3 p% T ^/ o: `; Y3 ^ fit_crossoff = evaluate(self.xydata, crossoff.data)# Evaluate the individuals * M; `0 ?3 M; P' Q( ~# E- ~/ ~: c1 s. m! a/ ~2 L
if random.random() < MUTPB: # mutate an individual with probability MUTPB S) D. t5 v# s9 f& |) B' m" K muteoff = self.mutation(crossoff,self.bound)8 c+ T7 M2 o$ M! z" ]2 h7 I/ y
fit_muteoff = evaluate(self.xydata, muteoff.data)# Evaluate the individuals ( T$ g2 Q2 h2 t/ A4 K, L% |' U nextoff.append({'Gene':muteoff,'fitness':fit_muteoff}) H2 |( Q5 R3 `) y* S# P8 f! H6 X$ r, \, X
# The population is entirely replaced by the offspring) v/ d) Q4 ~3 x; P0 Y- r
self.pop = nextoff # ]1 q5 q. A2 y! @" [5 E g1 \1 |( l8 N# D1 j
# Gather all the fitnesses in one list and print the stats9 k, c' F5 |$ W- X) U0 r7 F
fits = [ind['fitness'] for ind in self.pop] , V7 O! d# i; Q, O / G0 s" H4 F/ g6 | length = len(self.pop)# ?0 m( Z0 a+ `' m+ C0 s( R# }" j
mean = sum(fits) / length8 A: W* R N3 ], U
sum2 = sum(x*x for x in fits) # A* n6 H% ~9 z6 K- C1 h; G std = abs(sum2 / length - mean**2)**0.5; n; O, M+ s$ n( ^ [+ u8 k2 u
best_ind = self.selectBest(self.pop) : y$ L0 n+ B. }7 L( I3 S! P# y9 d( c; o, [& v0 a
if best_ind['fitness'] < self.bestindividual['fitness']:& i2 P6 a1 n) P' I# Y
self.bestindividual = best_ind # q" {" O5 k2 m2 ?+ o- A6 M1 ]7 O2 V) ?8 K/ z! n
print("Best individual found is %s, %s" % (self.bestindividual['Gene'].data,self.bestindividual['fitness'])) 3 K+ @0 J0 ]# e; ~ print(" Min fitness of current pop: %s" % min(fits))1 Y1 L4 B) a9 J$ Y
print(" Max fitness of current pop: %s" % max(fits)) & h/ L+ L& ^9 x/ o" C. m: N# d print(" Avg fitness of current pop: %s" % mean)- j- m6 h! q2 m9 p2 |( z8 v a
print(" Std of currrent pop: %s" % std) 3 @1 K8 a# s7 z* U% Y: e9 x. H9 P+ y& F* l
print("-- End of (successful) evolution --") 7 J1 ]) `: L4 }9 M6 _- ~6 N( t3 C' z0 _7 Y& G/ z- W+ ?
if __name__ == "__main__":1 S V& h2 x ?" b! j z
, ^! T' ~1 Z% g G/ R, ] CXPB, MUTPB, NGEN, popsize = 0.8, 0.3, 50, 100#control parameters . n* F8 | w8 d; ?+ o, ~ - B% y8 A9 v% f Z# U2 m: @( Z7 t up = [64, 64, 64, 64, 64, 64, 64, 64, 64, 64]#upper range for variables . Z& f' j2 X% u6 B& q0 U/ _0 J3 ` low = [-64, -64, -64, -64, -64, -64, -64, -64, -64, -64]#lower range for variables( B$ f. [1 l" O$ F
parameter = [CXPB, MUTPB, NGEN, popsize, low, up] & Y8 [/ n4 K, D, M% L( n1 A$ u7 n; q" M
run = GA(parameter) % f) M6 b: v7 m6 m% n run.GA_main() 3 X9 h% S$ a5 X$ |8 _) Q1 s+ o———————————————— 8 p2 h- ^; s, J" r6 X版权声明:本文为CSDN博主「bible_reader」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。1 D0 W, X/ c, f0 F4 \
原文链接:https://blog.csdn.net/bible_reader/article/details/72782675- h* `+ T/ x, c! y5 I# z
n5 b& C5 a* `. K! E8 w
; M" P' P% V4 r1 Z' H) G