前言

上课学的基础遗传算法,我用python实现了一遍。
选择算法使用轮盘赌博
基因交叉每次一位
基因变异每次一位

算法效果不是很好,有大佬熟悉的话感谢留言指导一下。

题目

求解函数的最大值y=xsin(10x)+xsin(2x),自变量取值:0–5
函数图像:

代码

'''
作者:LP
时间:2022年3月24日
介绍:遗传算法
参考:https://blog.csdn.net/weixin_42053726/article/details/82722758

题目:y=xsin(10x)+xsin(2x),自变量取值:0-5
'''
import numpy as np


def gene_len(len, accu):
'''
基因长度计算
参数: len 区间长度(整型)
accu 精确度(精确到小数点后多少位)
返回值: 二进制长度
'''
temp = len * (10 ** accu)
# print(temp)
i = 1
while temp > 2 :
i = i + 1
temp = temp / 2
return i

def gene_decode(arr,a,b,accu):
'''
将列表转换为十进制数并映射到区间上
参数: arr 基因列表
a 区间起始点
b 区间终点
accu 精确到小数点后多少位
返回值: 十进制数
'''
#二进制转十进制
i = 0
temp = 0
for j in arr:
temp = j * (2 ** i) + temp
i = i + 1
#映射到区间上
res = a + (b-a)/(2**len(arr)-1)*temp
res = round(res, accu)
return res

def gene_init(pop, len):
'''
初始化基因序列
参数: pop 种群个数
len 个体基因长度
返回值: 二维数组 长度为种群个数 每个元素为个体基因序列
'''
return np.random.randint(2, size=(pop, len))

def F(x): return np.sin(10*x)*x + np.cos(2*x)*x + 10

def fitness(pop, func):
"""
获取每个个体的适应度
参数: pop 种群二位数组
func 目标函数
返回值: 每个个体的适应度
"""
fit = []
prob = []
for i in pop:
fit.append(func(gene_decode(i,0,5,6))) #每个基因的适应度
for i in range(len(fit)):
prob.append(fit[i]/sum(fit)) #每个基因被选中的概率
# print(fit)
# print(prob)
# print(sum(prob))
return fit,prob

def selec(pop, prob):
'''
轮盘赌方法 根据概率选择个体 更新种群二维数组
参数: pop 种群二位数组
prob 概率数组
返回值: 新的种群二维数组
'''
rand_prob = np.random.random(len(prob))
new_pop = []
for i in rand_prob:
# print("prob:"+str(i))
sum = 0
for j in range(len(prob)):
sum += prob[j]
# print("dangqianprob:"+str(sum))
if sum < i:
continue
else :
new_pop.append(list(pop[j]))
# print(new_pop)
break
return new_pop

def gene_cross(pop, cross_rate):
'''
基因交叉(单点交叉) 根据概率选择交叉点
参数:pop 种群二维数组
cross_rate 基因交叉概率
返回值:新的种群二位数组
'''
if cross_rate < np.random.random():
local = np.random.randint(len(pop[0])) #选择交叉点位
gene_one = np.random.randint(len(pop)) #选择交叉的第一个基因
gene_two = np.random.randint(len(pop)) #选择交叉的第二个基因
while gene_one == gene_two:
gene_two = np.random.randint(len(pop))
temp = pop[gene_one][local]
pop[gene_one][local] = pop[gene_two][local]
pop[gene_two][local] = temp
return pop

def gene_change(pop, change_rate):
'''
基因突变(单点突变) 根据概率选择突变点
参数: pop 种群二维数组
change_rate 基因突变概率
返回值:新的种群二位数组
'''
if change_rate < np.random.random():
local = np.random.randint(len(pop[0])) #选择个体的基因位置
gene_choice = np.random.randint(len(pop)) #选择个体
pop[gene_choice][local] ^= 1
return pop

if __name__ == "__main__":
pop = gene_init(10,10)
for i in range(500):
[fit, prob] = fitness(pop, F)
pop = selec(pop,prob)
pop = gene_cross(pop, 0.8)
pop = gene_change(pop, 0.8)
for i in pop:
print(gene_decode(i,0,5,6))
# print(gene_decode([1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1],-1,2, 6))
# print(gene_len(3,1))