注:由于编码选择二进制编码,所以只能在整数范围进行搜索,也就是说求解到的最优解一定是最优的整数解 ,如果选择一些映射方法可以将离散问题连续化,但这样就和进化算法本身无关了,所以本文只写了基本的遗传算法
超参设置
染色体长度:10 种群:20 进化次数:50代 变异靶点:3 变异方式:插入,交换,局部逆序 变异概率:0.1 交叉方式:PMX修订两点交叉
import matplotlib. pyplot as plt
from math import *
import numpy as np
import random
import copy
minNum = 10
maxNum = 101
long = 10
population = 20
target_points = [ 1 , 2 , 3 ]
gens = 50
genRate = 0.1
def parseInt ( bit) :
if isinstance ( bit, str ) :
n = '0b' + bit
return int ( eval ( n) )
else :
return int ( eval ( '0b' + '' . join( bit) ) )
def parseBin ( i, t= str ) :
if t == str :
return str ( bin ( i) [ 2 : ] )
else :
return bin ( i) [ 2 : ]
def fitness ( x) :
if type ( x) != int :
x = parseInt( x)
return x ** 3
def translong ( i) :
length = len ( i)
n = long - length
if n != 0 :
for h in range ( n) :
i = '0' + i
return i
def initPop ( num) :
population = [ ]
xset = [ random. randrange( minNum, maxNum) for i in range ( num) ]
for j in xset:
i = str ( bin ( j) [ 2 : ] )
length = len ( i)
n = long - length
if n != 0 :
for h in range ( n) :
i = '0' + i
population. append( i)
return population
def overSection ( bit) :
n = parseInt( bit)
if minNum < n < maxNum:
return False
else :
return True
def twoPontsCross ( p1, p2) :
p1_ = list ( copy. deepcopy( p1) )
p2_ = list ( copy. deepcopy( p2) )
point1 = random. randint( 0 , len ( p1_) )
point2 = random. randint( 0 . , len ( p1) )
while point1 > point2 or point1 == point2:
point1 = random. randint( 0 , len ( p1) )
point2 = random. randint( 0 . , len ( p1) )
p1_[ point1: point2] , p2_[ point1: point2] = p2_[ point1: point2] , p1_[ point1: point2]
p1_ = '' . join( p1_)
p2_ = '' . join( p2_)
return str ( p1_) , str ( p2_)
def gene_exchange ( n) :
n = list ( n)
point1 = random. randint( 0 , len ( n) - 1 )
point2 = random. randint( 0 , len ( n) - 1 )
while point1 == point2 or point1 > point2:
point1 = random. randint( 0 , len ( n) - 1 )
point2 = random. randint( 0 , len ( n) - 1 )
n[ point1] , n[ point2] = n[ point2] , n[ point1]
n = '' . join( n)
return n
def gene_insertion ( n) :
n = list ( n)
point1 = random. randint( 0 , len ( n) - 1 )
point2 = random. randint( 0 , len ( n) - 1 )
while point1 == point2:
point1 = random. randint( 0 , len ( n) - 1 )
point2 = random. randint( 0 , len ( n) - 1 )
x = n. pop( point1)
n. insert( point2, x)
n = '' . join( n)
return n
def gene_reverse ( n) :
n = list ( n)
point1 = random. randint( 0 , len ( n) - 1 )
point2 = random. randint( 0 , len ( n) - 1 )
while point1 == point2 or point1 > point2:
point1 = random. randint( 0 , len ( n) - 1 )
point2 = random. randint( 0 , len ( n) - 1 )
ls_res = n[ point1: point2]
ls_res. reverse( )
l1 = n[ : point1]
l2 = n[ point2: ]
n_res_end = l1 + ls_res + l2
n = '' . join( n)
return n_res_end
class node :
def __init__ ( self, bit) :
self. bit = bit
self. fitness = fitness( bit)
def main ( ) :
best = [ ]
pops = initPop( population)
popsfit = [ node( i) for i in pops]
popsfit. sort( key= lambda x: x. fitness)
popsfit. reverse( )
print ( parseInt( popsfit[ 0 ] . bit) )
print ( '--' * 20 )
for gen in range ( gens) :
children = [ ]
pop_children1 = pops[ 1 : : 2 ]
pop_children2 = pops[ : : 2 ]
for r in range ( len ( pop_children1) ) :
child1, child2 = twoPontsCross( pop_children1[ r] , pop_children2[ r] )
if overSection( child1) :
child1 = initPop( 1 ) [ 0 ]
if overSection( child2) :
child2 = initPop( 1 ) [ 0 ]
children. append( translong( child1) )
children. append( translong( child2) )
for i in children:
rate = random. random( )
if rate < genRate:
target = random. choice( target_points)
if target == 1 :
c_exchange = gene_exchange( i)
if overSection( c_exchange) :
children[ children. index( i) ] = initPop( 1 ) [ 0 ]
else :
children[ children. index( i) ] = c_exchange
elif target == 2 :
c_insert = gene_insertion( i)
if overSection( c_insert) :
children[ children. index( i) ] = initPop( 1 ) [ 0 ]
else :
children[ children. index( i) ] = c_insert
else :
c_reverse = gene_reverse( i)
if overSection( c_reverse) :
children[ children. index( i) ] = initPop( 1 ) [ 0 ]
else :
children[ children. index( i) ] = c_reverse
childrenFitness = [ node( i) for i in children]
initpopulationFitness = [ node( i) for i in pops]
initpopulationFitness += childrenFitness
initpopulationFitness. sort( key= lambda x: x. fitness)
initpopulationFitness. reverse( )
del initpopulationFitness[ 10 : ]
pops = [ i. bit for i in initpopulationFitness]
best. append( parseInt( pops[ 0 ] ) )
if gen % 10 == 0 :
print ( f'第{gen}代,当前最优解{parseInt(pops[0])}' )
print ( f'全局最优为:{parseInt(pops[0])}' )
return parseInt( pops[ 0 ] ) , fitness( pops[ 0 ] )
if __name__ == '__main__' :
a, b = main( )
x = np. linspace( 10 , 100 , 1000 )
y = [ i ** 3 for i in x]
plt. plot( x, y)
plt. plot( a, b, '.r' )
plt. show( )