课程要求函数如下:
sqrt为开根号运算,x(j)的取值范围为[-500,500],初始群体大小为100。
适应度函数的大小就是函数值大小,仅仅做了归一化。
以后可能还会用到,代码做个保存,具体实现如下:交叉,畸变,选择概率可以根据具体情况修改
import matplotlib.pyplot as plt
import numpy as np
import random
import math
# 定义遗传算法参数
pop_size = 100 # 种群大小
generation = 10 # 最大遗传代数
length = 30 # 个体长度
pc = 0.65 # 交叉概率
# 变异产生新的个体,选择导致个体消亡,可以通过调节变异概率和选择概率保证种群完好
pm = 0.1 # 变异概率
# 每个个体随机编码
def genEncoding(pop_size, length):
pop = [[]]
for i in range(pop_size):
temp = []
for j in range(length):
temp.append(random.randint(0, 1))
pop.append(temp)
return pop[1:] # ??
# 解码
def genDecoding(pop, length):
temp = []
for i in range(len(pop)):
t = 0
for j in range(length):
t += pop[i][j]*math.pow(2, j)
temp.append(t)
return temp
# 计算目标值 x介于lb和ub之间
def calValue(pop, length, lb, ub):
obj_value = []
x_value = []
# 获取解码后个体
temp1 = genDecoding(pop, length)
for i in range(len(temp1)):
x = lb + (ub-lb)*temp1[i]/((math.pow(2, length)) - 1) # 计算x函数值
x_value.append(x)
obj_value.append(np.sin(np.sqrt(x))*x) # 计算y函数值
return obj_value
# 计算适应度 适应度就是对应的函数值
def fitness(pop, length, lb, ub):
obj_value = calValue(pop, length, lb, ub)
fit_value = []
for i in range(len(obj_value)):
fit_value.append(obj_value[i])
# fitness_value = list(map(abs, fitness_value))
fit_value = list(map(lambda x: -x+max(fit_value), fit_value))
return fit_value
# 选择函数 根据适应度值进行选择
def selection(pop, fitness_value):
newfitness_value = []
accumulation_value = []
# total_fit = np.sum(fitness_value)
fit_min = np.min(fitness_value)
fit_max = np.max(fitness_value)
for i in range(len(fitness_value)):
newfitness_value.append(fitness_value[i]-fit_min/(fit_max - fit_min)) # 计算适应度的相对值
accumulation_value = newfitness_value
ms = []
for i in range(len(pop)):
ms.append(random.random())
newpop = []
for j in range(len(accumulation_value)):
if 0.01 < accumulation_value[j]:
if j >= len(pop):
print(j, len(pop))
t = pop[j]
newpop.append(t)
# # 人口膨胀
# if len(accumulation_value)>1000:
return newpop
# 交叉函数
def crossover(pop, fitness_value, pc):
new_pop = selection(pop, fitness_value)
m = len(new_pop)
# n = len(new_pop[0])/2 # 一半的基因交叉重组
for i in range(m-1):
# rm = random.randint(0, m-1)
if random.random() < pc:
# 父代可以不保存
# new1 = new_pop[i].copy()
# new2 = new_pop[rm].copy()
for j in range(10):
k = random.randint(0, length-1)
temp1 = new_pop[i][k]
temp2 = new_pop[i+1][k]
new_pop[i+1][k] = temp1
new_pop[i][k] = temp2
# new_pop.append(new1)
return new_pop
# 变异函数
def mutation(pop, fitness_value, pc, pm, length):
newpop = crossover(pop, fitness_value, pc)
for i in range(len(newpop)):
new = []
if random.random() < pm:
new = newpop[i].copy()
m1 = random.randint(0, length-1)
m2 = random.randint(0, length - 1)
m3 = random.randint(0, length - 1)
if new[m1] == 1:
new[m1] = 0
else:
new[m1] = 1
if new[m2] == 1:
new[m2] = 0
else:
new[m2] = 1
if new[m3] == 1:
new[m3] = 0
else:
new[m3] = 1
newpop.append(new)
return newpop
if __name__ == "__main__":
# 画出函数图
plt.figure(1)
lb = 0
ub = 500
x = np.arange(lb, ub, 0.01)
y = np.sin(np.sqrt(x))*x
plt.plot(x, y)
plt.xlabel("自变量X"); plt.ylabel("应变量Y"); plt.title("sin(sqrt(x)*x")
# 初始化群体
pop = genEncoding(pop_size, length)
obj_value = calValue(pop, length, lb, ub)
gen = 0
x_value = []
best_x = []
best_individual = []
Generation = []
Mmax = 0
while gen < generation:
# 计算函数值
fit_value = fitness(pop, length, lb, ub)
# 交叉变异
newpop = mutation(pop, fit_value, pc, pm, length)
temp = genDecoding(newpop, length)
for i in range(len(temp)):
x = lb+(ub-lb)*temp[i]/((math.pow(2, length))-1)
x_value.append(x)
obj_value = calValue(newpop, length, lb, ub)
k = 0
j = 0
for i in range(len(obj_value)):
if k < obj_value[i]:
k = obj_value[i]
j = i
best_individual.append(k) # 最佳个体
if obj_value[j] > Mmax:
Mmax = obj_value[j]
best_x.append(x_value[j])
fitness_value = fitness(newpop, length, lb, ub)
Generation.append(gen)
gen = gen+1
pop = newpop
k = 0
j = 0
for i in range(len(best_individual)):
if k > best_individual[i]:
k = best_individual[i]
j = i
print(max(best_individual))
print(-Mmax*30)
best_individual.sort(reverse=True)
plt.figure(2)
plt.plot(Generation, best_individual)
plt.xlabel("遗传代数")
plt.ylabel("解的变化")
plt.title("进化过程")
plt.show()
实验结果如下:
最佳个体最大函数值max(best_individual):418.98264752959625
原函数最小值-max(best_individual)*30:-12569.479425887888