利用遺傳算法計(jì)算x10+ex=100的解
照例,import一些必要的庫(kù)
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import random
不管怎么著,先把圖畫(huà)出來(lái),看一下大概的取值區(qū)間
x=np.linspace(0,2,100)
def y(x):
return np.abs(x**10+np.exp(x)-100)
plt.plot(x,y(x))
plt.show()
為了方便編碼(其實(shí)是我懶)强胰,決定取值區(qū)間為[0,2]。
下面進(jìn)行編碼妹沙,采用32位的編碼偶洋。也就是將[0,2]分割成2^32個(gè)小區(qū)段。
比如[0,0,0,...,0]是0距糖,[1,0,0,...0]是2^(-31)
sons=np.zeros([100,32])
values=np.zeros([100])
results=np.zeros([100])
sort_index=np.zeros([100])
初始化函數(shù)玄窝,先隨機(jī)生成100個(gè)點(diǎn)。
def init():
global sons
for i in range(100):
for j in range(32):
sons[i][j]=random.randint(0,1)
計(jì)算函數(shù)悍引,將對(duì)應(yīng)的編碼轉(zhuǎn)換成相應(yīng)的數(shù)值
def cmp(son):
value=0
temp=2**(-31)
for i in son:
value+=i*temp
temp*=2
return value
更新數(shù)值的函數(shù)
def update():
global sons,values
for i in range(100):
values[i]=cmp(sons[i])
遺傳算法的核心函數(shù)恩脂,首先找出最接近解的10個(gè)值,然后利用這十個(gè)值的編碼產(chǎn)生其余九十個(gè)值的編碼趣斤。
具體操作是俩块,隨機(jī)選取前十個(gè)中的兩個(gè),分別將他們的奇數(shù)編碼和偶數(shù)編碼組合生成一個(gè)新的編碼浓领。
為了能夠進(jìn)化玉凯,也就是不局限于起初產(chǎn)生的編碼,加入了突變這一因素联贩。
同時(shí)為了確保函數(shù)的收斂速度漫仆,針對(duì)不同的編碼提供不同的突變。
較接近解的編碼泪幌,不允許出現(xiàn)大突變盲厌,其余允許大突變,防止陷入局部最優(yōu)解祸泪。(在求最大值最小值的時(shí)候)
def gen():
global values,sort_index,results,sons
results=np.abs(values**10+np.exp(values)-100)
sort_index=np.argsort(results)
for i in range(100):
if i in sort_index[:10]:
continue
else:
sam=random.sample(list(sort_index[:10]),2)
sons[i][::2]=sons[sam[0]][::2]
sons[i][1::2]=sons[sam[1]][1::2]
for i in range(500):
index=random.randint(0,99)
if index in sort_index[0:3]:
flag=random.randint(0,1)
sons[index][flag]=1-sons[index][flag]
elif index in sort_index[3:10]:
flag=random.randint(0,7)
sons[index][flag]=1-sons[index][flag]
else:
flag=random.randint(0,31)
sons[index][flag]=1-sons[index][flag]
return(results[sort_index[0]],values[sort_index[0]])
main函數(shù)
def main():
init()
for i in range(1001):
update()
a,b=gen()
if i%250==0:
print(a,b)
plt.plot(values,y(values),'.',x,y(x))
plt.show()
main()
4.53816371162 1.58435669821
0.000244704122139 1.57704925584
0.000244420886716 1.57704925537
0.000244420886716 1.57704925537
2.94243349686e-07 1.57704885304
可以看到吗浩,函數(shù)迅速收斂,最后的誤差已經(jīng)很小了浴滴,只有10^(-7)這個(gè)數(shù)量級(jí)拓萌。
如果想要更精確的結(jié)果可以多迭代幾次岁钓,可以很快地找出在32位精度下的最優(yōu)解升略。
請(qǐng)不要在意那些離散在外面的點(diǎn)微王,那是因?yàn)樵试S大的突變而產(chǎn)生的,在有多個(gè)極值的情況下品嚣,它們的作用就大了炕倘。