% w6 {% Q( w* _( E种群:多个个体即组成一个种群。GA算法中,一个问题的多组解即构成了问题的解的种群。 5 q# s& W: h) v( v1 l0 Q( S; {4 l0 k5 [( _
2、主要步骤 7 r1 i% n0 W. k. P. q5 {GA算法的基本步骤如下:+ T+ @" J* F4 ?% v. D& Q( _( Q
( z5 G3 a) R7 G7 |* V0 }
Step 1. 种群初始化。选择一种编码方案然后在解空间内通过随机生成的方式初始化一定数量的个体构成GA的种群。 7 N ?2 @0 i, Z( l2 N/ l! A8 ^# m 8 |) s. g/ k5 N3 f$ DStep 2. 评估种群。利用启发式算法对种群中的个体(矩形件的排入顺序)生成排样图并依此计算个体的适应函数值(利用率),然后保存当前种群中的最优个体作为搜索到的最优解。 9 E4 I& O) ^4 `6 U. P 6 s7 B$ H1 L1 \4 ~3 }, O, C4 V0 C1 lStep 3. 选择操作。根据种群中个体的适应度的大小,通过轮盘赌或者期望值方法,将适应度高的个体从当前种群中选择出来。0 K% D9 Z0 \2 i$ X
" F% G% n" ~/ {( W
Step 4. 交叉操作。将上一步骤选择的个体,用一定的概率阀值Pc控制是否利用单点交叉、多点交叉或者其他交叉方式生成新的交叉个体。 ) P5 r$ T" u- T) o+ M7 E$ P" x1 U, U& T- V4 e4 Y
Step 5. 变异操作。用一定的概率阀值Pm控制是否对个体的部分基因执行单点变异或多点变异。 . j- u7 n, p, [4 ^' S0 }2 X. i9 x- g% N( C
Step 6. 终止判断。若满足终止条件,则终止算法,否则返回Step 2。 # K A- R8 ]9 p& y& @; L' Q9 W) j0 L7 s- X) i; B i: P
流程图如下所示: , c% }4 d' X4 G4 |1 i# B4 G' k
5 u9 z* k2 t% d* ?0 b5 z- `) n
: y% f9 s- ~6 r6 _, o8 U3、主要操作介绍+ D. J* U. O" u* Z# s$ I
3.1 种群初始化 6 Q5 c# W8 ^" o( x5 [8 d3 J1 ^9 @种群的初始化和具体的问题有关。比如一个问题有n个决策变量{x1,x2,…,xn}。每个决策变量有取值范围:下界{L1,L2,…,Ln}和上界{U1,U2,…,Un},则种群中个体的初始化即随机地在决策变量的取值范围内生成各个决策变量的值:Xj={x1,x2,...,xn},其中xi属于范围(Li,Ui)内。所有的个体即构成种群。当每个个体都初始化后,即种群完成初始化。 * Y3 {0 P M R6 L& C7 F. C9 `9 L; d' Y/ g; U) e/ Z5 L
3.2 评价种群6 g* R; G( P' N& J# j F
种群的评价即计算种群中个体的适应度值。假设种群population有popsize个个体。依次计算每个个体的适应度值及评价种群。 . ^# G/ C! d9 H& { + g* b' U I( S" U2 B9 l- Q5 I3.3 选择操作' A- ~9 r/ y' f, T
GA算法中常见的选择操作有轮盘赌方式:种群中适应度值更优的个体被选择的概率越大。假设popsize=4,按照如下表达式计算各个个体的被选择概率的大小,然后用圆饼图表示如下。 # y' G) x& P0 |6 c1 Q! b* q- w4 |
P(Xj) = fit(Xj)/(fit(X1)+fit(X2)+fit(X3)+fit(X4)),j=1,2,3,4+ t: ?6 F5 m* f2 V5 y
& {6 m" [+ W8 k' a( M$ Q* _ V. T
. n! T0 o8 Q5 f! q; w; V
当依据轮盘赌方式进行选择时,则概率越大的越容易被选择到。 }" {5 x& q( R4 l( y1 e# S
# R2 C, O y- N) y9 ]3.4 交叉操作! }0 [8 `& r1 Z4 P2 O! B. E
交叉操作也有许多种:单点交叉,两点交叉等。此处仅讲解一下两点交叉。首先利用选择操作从种群中选择两个父辈个体parent1和parent2,然后随机产生两个位置pos1和pos2,将这两个位置中间的基因位信息进行交换,便得到下图所示的off1和off2两个个体,但是这两个个体中一般会存在基因位信息冲突的现象(整数编码时),此时需要对off1和off2个体进行调整:off1中的冲突基因根据parent1中的基因调整为parent2中的相同位置处的基因。如off1中的“1”出现了两次,则第二处的“1”需要调整为parent1中“1”对应的parent2中的“4”,依次类推处理off1中的相冲突的基因。需要注意的是,调整off2,则需要参考parent2。2 Q5 W+ S! }: E7 w- Z N0 f9 V
{2 v- }3 A. K ~
: a. E6 |( j7 \ o" x$ ?
- @) Q1 e- e; g( O" L$ X0 W4 u" a
3.5 变异操作+ A- b K/ r* W2 L# ]9 k! I
变异操作的话,根据不同的编码方式有不同的变异操作。; t" J& }$ r+ X7 P o; V
' Y0 G+ r, A+ x! w+ y
如果是采用整数编码方案,则一般有多种变异方法:位置变异和符号变异。0 ?; Y* L p* c1 y3 X% s0 R ]' @
, ?/ H0 U8 q$ S$ A% P# u" c
位置变异: 5 [9 ^" O! {* W5 X, L" k% J" P
, C% K* B, k2 E1 L8 K. a, o% @
6 e' S* m5 Z% ~& d4 ]/ ^- c" G符号变异: 4 `2 r9 T3 ?4 k: i- O
( c3 P# n: t+ P, {) n9 c. s! w% d ( i i9 S# _* c4、Python代码. U- o u" f: s, t }
#-*- coding:utf-8 -*-" P+ s$ L1 F- y8 J g0 `
- v$ Q# B3 ` t* v7 u
import random 8 |, S2 ?, ~/ q, Zimport math' z+ M; ?4 q4 V7 a& {6 a3 m: z
from operator import itemgetter' [' \" ]2 W; `( ~
# d8 x0 R& d( Pclass Gene: ' ~9 H( y( _& \+ a6 u8 s ''' 4 M4 l% U! q3 k1 h; l2 e: g This is a class to represent individual(Gene) in GA algorithom . O/ t/ c- w+ ] each object of this class have two attribute: data, size( K, H# V- `5 E! |2 z
'''5 ~2 D5 S2 j2 e6 S6 q( j; u7 V7 o& E
def __init__(self,**data): ! ]! A, R c# w; ?$ y1 O3 N self.__dict__.update(data) 4 t" ^3 l3 r Q8 L
self.size = len(data['data'])#length of gene; g% o. s5 ^1 O2 ~' Y0 |
2 s) y, m T8 Z8 y$ a5 @7 Q
) l! u: d9 \ _ b" d
class GA:5 Z4 c" s d8 q0 C2 U4 f
''' h/ p! |2 u0 Q6 u3 B4 n/ ~ This is a class of GA algorithm. * B5 S8 R. f2 \" q) F3 Q '''/ c3 j/ f. u7 b# U8 ~0 ?) x& b/ N
def __init__(self,parameter):' |% l9 z3 c. t# J! Y* c, F
''' ! _" @" z# N) | Initialize the pop of GA algorithom and evaluate the pop by computing its' fitness value . " N/ \( t6 H) j% h The data structure of pop is composed of several individuals which has the form like that: i5 {# W$ `( K' r . j% s7 X& h2 S {'Gene':a object of class Gene, 'fitness': 1.02(for example)}5 \0 U3 Y, ~+ u0 W9 d
Representation of Gene is a list: [b s0 u0 sita0 s1 u1 sita1 s2 u2 sita2] : d s+ L" ]" j5 o2 c# W! Y$ Y: B) `; d0 A C6 ^
''' , M$ y9 k- x: n# E #parameter = [CXPB, MUTPB, NGEN, popsize, low, up]+ _" |; C+ d# f: j3 x) \, o5 c: Q
self.parameter = parameter9 h" X. \+ q" R$ @8 `* D$ B7 y+ K0 r: z
; g1 Z% Y/ B! v% G( d* Y4 _/ J
low = self.parameter[4] / R* e1 n+ H/ ` up = self.parameter[5]) S2 C, t- ?) F7 G
+ Q: P8 s/ c2 e; p- W- v6 d. b self.bound = [] % h9 P0 n, W( v" l7 G self.bound.append(low)% R$ d, n- z) T
self.bound.append(up) $ j- M5 W8 e9 o* a2 x# P/ }1 P% s& S. K/ U# b
pop = [] . n) z, H6 z: N& Q Y! ~ for i in range(self.parameter[3]):5 Y0 |8 y- ?- h. T | Y. ^
geneinfo = []1 j0 I, _2 }% N4 {4 e
for pos in range(len(low)): , ]2 l' |: d- K+ R- p0 s& H. @ geneinfo.append(random.uniform(self.bound[0][pos], self.bound[1][pos]))#initialise popluation % d" R1 V* `! y& w0 Y3 M: {0 m# `$ o$ r & Z# l3 B5 s$ ?2 I" J( O" v fitness = evaluate(geneinfo)#evaluate each chromosome : t( J) {& N& ]& M pop.append({'Gene':Gene(data = geneinfo), 'fitness':fitness})#store the chromosome and its fitness/ T. B2 q5 p4 M' l/ P! a
B0 V. C6 H. M% F+ V self.pop = pop & n. N8 K; {+ ]2 W9 S. V" Y9 { self.bestindividual = self.selectBest(self.pop)#store the best chromosome in the population4 a; d2 U& S' f( B$ ?- a
6 Z- a E1 Y `* t( E8 h
def selectBest(self, pop): ! M( _1 E8 X' Y7 r: N '''8 e9 G+ b, j3 B5 L+ P, L/ G6 k2 F2 t
select the best individual from pop 1 n* r0 D* k) I$ P9 \0 Y/ n '''! w& I) k. _4 g( \
s_inds = sorted(pop, key = itemgetter("fitness"), reverse = False) - H/ T1 p6 l5 \! O, C; s return s_inds[0] 3 H" e2 W5 ?0 x4 T/ e' x$ j: J j
def selection(self, individuals, k):. a* t" Q0 s/ U
''', M, X0 {( y7 P( X# y5 E7 L7 B# k
select two individuals from pop / o9 a5 F9 ]) M/ N% y" i7 E; |) X '''' A$ E/ L/ U6 Z% L
s_inds = sorted(individuals, key = itemgetter("fitness"), reverse=True)#sort the pop by the reference of 1/fitness " A6 t% O/ z7 @' b% B4 k
sum_fits = sum(1/ind['fitness'] for ind in individuals) #sum up the 1/fitness of the whole pop9 m- `( a! m Y- |- j& d' I
& e8 J. c9 B7 G4 k e
chosen = []( V6 g/ `; i* k
for i in xrange(k): . _: q/ R5 h, O% s+ u u = random.random() * sum_fits#randomly produce a num in the range of [0, sum_fits]! v. x. _2 h& `( A% `% i0 U. V
sum_ = 0 $ \: \0 X2 D# ~) h f$ Y for ind in s_inds: : I( [9 m) w0 R! Z6 r$ B3 b sum_ += 1/ind['fitness']#sum up the 1/fitness ' J" f0 C5 P2 h; q! z9 t! A. _ if sum_ > u: ' { Z5 R; o3 U7 _: ? #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; z2 i( ~4 h. q" P! q
chosen.append(ind)- Z$ u7 q; q7 u7 v* p
break 5 U) x3 i o& i0 @6 b t ' Z$ L( q' @# f0 } return chosen , \, p0 ^( F" h% M# _. `6 }, ^( I
3 u7 _0 ^% l. w& p/ v
& P9 b! W, l- M N
def crossoperate(self, offspring): 9 O0 r% ^- l1 C4 G# h& Q" b5 T" G ''' . N& n- J, p( [ `' o cross operation0 D1 L3 ]' j; x- T# K, f
'''2 F H! r' V4 k( t
dim = len(offspring[0]['Gene'].data) 8 h# D/ z8 \( \8 ?; _: {! J' g3 K O$ E8 t
geninfo1 = offspring[0]['Gene'].data#Gene's data of first offspring chosen from the selected pop3 Y$ @) I6 D) ^" P
geninfo2 = offspring[1]['Gene'].data#Gene's data of second offspring chosen from the selected pop" z7 Q& U' M- U) O! M1 ~0 \
8 o- J3 g0 v- K, n pos1 = random.randrange(1,dim)#select a position in the range from 0 to dim-1, " K+ ?9 [2 |9 O pos2 = random.randrange(1,dim)* j* s" K% q( N) w0 x! r) [( z& c
& m! d7 j/ U2 l3 V- v4 P
newoff = Gene(data = [])#offspring produced by cross operation 7 ] h; O8 O3 r5 `$ U3 Z temp = [] . k1 o3 s/ q# ^ y d- Z for i in range(dim): * A$ s- T! C; \2 ^ if (i >= min(pos1,pos2) and i <= max(pos1,pos2)):. V6 s2 v# t; p, x9 G
temp.append(geninfo2)% ]9 k, y$ M4 V' E, {9 Q- [
#the gene data of offspring produced by cross operation is from the second offspring in the range [min(pos1,pos2),max(pos1,pos2)] ) q z( H) \2 s K# t p: I else: : y( ^+ t$ i+ e0 b4 j temp.append(geninfo1) / U; ^0 z) w0 R #the gene data of offspring produced by cross operation is from the frist offspring in the range [min(pos1,pos2),max(pos1,pos2)] ) G- r& W( W9 L+ @ newoff.data = temp 5 [0 b8 P; d- b" b3 P% L* ]" H1 F! o q8 s% I, P+ m8 h
return newoff) ?/ T2 b" c1 {2 d1 f
# s7 O$ w* U5 Q! e( H+ N0 E6 F3 z- U) C; d. ]7 B
def mutation(self, crossoff, bound):$ s+ I, e: A% s, z1 T' C: I0 ~: }" [
'''4 Q; Z5 e+ K9 a2 L# Q
mutation operation 8 ]% _8 a) {* D- h( w ''' # r1 r) v* x- a7 p* V6 p' d" [8 A4 L9 K* \. j) @4 |4 }- y
dim = len(crossoff.data)9 W r; j1 E* ~* A! Q+ L, a
0 d e6 p( R/ S+ j) l
pos = random.randrange(1,dim)#chose a position in crossoff to perform mutation. . _( Z/ ]2 M# w & _) h( P6 ~: L crossoff.data[pos] = random.uniform(bound[0][pos],bound[1][pos])' K- N' N/ u& [2 H! \
return crossoff" M! ~. C+ X- A# M# W0 D
- ~1 E- W* U: U2 _ def GA_main(self): ( O; u; [5 [" q9 z ''', ` P5 b0 j9 _
main frame work of GA 6 s% b2 S8 A0 @3 Z W' B- V '''5 {% y/ H. a; R. q5 F
/ C5 e3 ~# F* W( M0 o L
popsize = self.parameter[3]8 S0 j6 N$ ?* H/ g- E
6 S- E2 z4 l1 t( A& M print("Start of evolution")( H; {( ]+ u6 Z! g# H4 i
I( z) f0 u7 J: B: }* S
# Begin the evolution / b5 q6 i8 s& v) d5 H( M3 Y for g in range(NGEN): t" h+ f4 W& w4 n: o# K# d: X1 t: k; q7 `& V& }" C+ }4 {: M
print("-- Generation %i --" % g) ! i' N1 c4 C) q' a, A3 u
+ t* C4 ~5 q$ M1 ] ` K
#Apply selection based on their converted fitness" v4 `" p* ?* r" Q
selectpop = self.selection(self.pop, popsize) % E/ B d" P4 k5 a ) T/ I' `& T6 D- j2 u nextoff = [] 2 w# l" j4 z8 b' `, l
while len(nextoff) != popsize: / ]/ A) }3 F) o. M- n # Apply crossover and mutation on the offspring ; L; }8 ?! f* G
' `5 s, p G5 n; S+ ?. I$ P1 _ # Select two individuals 5 s3 c B( j8 D* R: C) E1 U offspring = [random.choice(selectpop) for i in xrange(2)] % S1 \1 [ @- e+ P+ s1 {$ B* h8 X# H% i9 _- V" i; i1 M
if random.random() < CXPB: # cross two individuals with probability CXPB* f$ h7 O$ q( B$ f8 G* s, ]
crossoff = self.crossoperate(offspring) . S0 \- A, d0 R* T: N! M fit_crossoff = evaluate(self.xydata, crossoff.data)# Evaluate the individuals 5 [4 v: i' @% G, }+ F% ^
1 Y C7 n, Z, \+ M0 p$ d if random.random() < MUTPB: # mutate an individual with probability MUTPB 8 [. Y `- l8 L: {2 r \" q% H; k muteoff = self.mutation(crossoff,self.bound) " |2 H: U3 q% b r) E) L fit_muteoff = evaluate(self.xydata, muteoff.data)# Evaluate the individuals ; x. f- q P/ d# T: B5 t nextoff.append({'Gene':muteoff,'fitness':fit_muteoff}) ; L( Z. O" \3 j `; y. M. C E. C1 a
# The population is entirely replaced by the offspring 9 d5 k- Q* ]' k7 ^) {. R! P& v self.pop = nextoff4 R; V) ~0 I8 C8 Q7 W! |. L( }& K2 a
& z' m! t3 A2 H ~" z9 U' `. ~) ^
# Gather all the fitnesses in one list and print the stats2 J3 x# j, A, q) \1 J
fits = [ind['fitness'] for ind in self.pop] " Q" Z7 G9 p/ m4 Y3 ~' m' @& q T3 O& c- I: c+ D/ k6 V
length = len(self.pop)& I H2 b% ^# k
mean = sum(fits) / length- e" X6 a+ @+ V T0 i2 q
sum2 = sum(x*x for x in fits)9 \- s# V- I* D! M0 [4 ^
std = abs(sum2 / length - mean**2)**0.5 % L) u& u. w% e; K4 u best_ind = self.selectBest(self.pop)( @, E0 }+ G2 a) D
7 ]( W4 P8 }" ^4 O3 M& V s
if best_ind['fitness'] < self.bestindividual['fitness']: * O/ ] \$ O# { g5 y5 S$ O# ` self.bestindividual = best_ind . Q5 e3 r) u x: I8 b: _- W$ r- u* @- Y4 C" n
print("Best individual found is %s, %s" % (self.bestindividual['Gene'].data,self.bestindividual['fitness'])) 9 f9 A7 z" H8 W& [) ?% v/ r) t; K print(" Min fitness of current pop: %s" % min(fits)) ' i+ o6 E+ a2 k* ` print(" Max fitness of current pop: %s" % max(fits)) ' }. w% k: }9 A1 w$ ]# K/ H- U print(" Avg fitness of current pop: %s" % mean) & K- ?2 ~3 g* _& { print(" Std of currrent pop: %s" % std)6 P) ?$ }0 d( Y, K' v/ s
1 q8 c3 n! S! o- ?5 U! P% t# K print("-- End of (successful) evolution --") # ?0 B. T. i2 i0 M- N( M
1 O, A+ ~3 t0 e% ]4 t; h# sif __name__ == "__main__":& H" m# |' o% a& h- |5 [
: |4 k `( g1 G; R4 ?0 i
CXPB, MUTPB, NGEN, popsize = 0.8, 0.3, 50, 100#control parameters 2 R2 h/ F9 x" A9 p" O& T& u7 t+ Q, m- d! }! v) E9 h7 H! Q: i
up = [64, 64, 64, 64, 64, 64, 64, 64, 64, 64]#upper range for variables 8 R! T. a8 `- E low = [-64, -64, -64, -64, -64, -64, -64, -64, -64, -64]#lower range for variables " L! l! R% w4 ^ parameter = [CXPB, MUTPB, NGEN, popsize, low, up]" Y b. P! a* g& A9 }
' f4 r: J- l3 c: D+ F. I( J
run = GA(parameter) / O& I+ {+ ~$ ` run.GA_main()8 f9 {9 D# c* B; c! u
———————————————— 0 I" M. z W3 k0 f! d _版权声明:本文为CSDN博主「bible_reader」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 2 q* |6 P* H, L+ A M* k5 }; L; Z; w原文链接:https://blog.csdn.net/bible_reader/article/details/72782675$ X e" B9 c2 R+ o