Python遗传算法求一元函数最大值

最近接触遗传算法,参考了众多例子,有些又不尽然对,所以自己边理解边修改,然后写出了下面这堆传说中的屎山。。。

PS1:遗传算法原理啥的太多了,就不赘述了,CSDN里面很多帖子都讲得很透彻了;

PS2:要看简洁的,直接油管搜遗传算法,看莫烦的视频。

代码

外汇经纪商对比不废话了,赶紧上代码。

import math

import numpy as np

import matplotlib.pyplot as plt

import random

class GA(object):

# 目标求解2*sin(x)+cos(x)最大值

def __init__(self, population_size, chromosome_length, pm):

self.population_size = population_size

self.chromosome_length = chromosome_length

self.pm = pm

# 初始化种群

def species_origin(self): # 生成染色体和基因

population = [[]] # 二维列表,包含染色体和基因

for i in range(self.population_size):

temporary = [] # 染色体寄存器

for j in range(self.chromosome_length):

temporary.append(random.randint(0, 1)) # 生成基因,二进制

population.append(temporary) # 将基因添加到染色体中

return population[1:] # 返回种群,包含染色体和基因

# 种群解码,用于适应度判断

def translation(self, population): # 二进制转十进制

chromosome_d_list = [] # 创建染色体十进制列表

for i in range(len(population)):

chromosome_value_d = 0

for j in range(len(population[0])):

chromosome_value_d += population[i][j] * (math.pow(2, len(population[0])-j-1))

chromosome_d_list.append(chromosome_value_d)

return chromosome_d_list

# 适应度计算

def function(self, population, lower_bound, upper_bound):

all_fitness_list = [] # 创建所有染色体适应度列表

fv_list = self.translation(population)

for i in range(len(fv_list)):

x = lower_bound + fv_list[i] * (upper_bound - lower_bound)/(math.pow(2, self.chromosome_length) - 1)

y = 2 * math.sin(x) + math.cos(x) # 目标函数

all_fitness_list.append(y)

return all_fitness_list

# 剔除适应度负值

def positive_fitness(self, all_fitness_list):

pf = []

for i in range(len(all_fitness_list)):

if all_fitness_list[i] > 0:

pf.append(all_fitness_list[i])

return pf

# 正适应度染色体列表

def positive_chromosome(self, all_fitness_list, population):

positive_chromosome_list = []

for i in range(len(all_fitness_list)):

if all_fitness_list[i] > 0:

positive_chromosome_list.append(population[i])

return positive_chromosome_list

# 计算正适应度总和

def pf_sum(self, pf):

pf_total = 0

for i in range(len(pf)):

pf_total += pf[i]

return pf_total

# 正适应度变为小数

def pf_float(self, pf_total, pf):

pf_float = []

for i in range(len(pf)): # 正适应度除以适应度总数,转化为小数

pf_float.append(pf[i] / pf_total)

return pf_float

# 适应度累加,为分区做准备

def pf_div(self, pf_float):

pft_div = []

for j in range(len(pf_float)): # 将适应度转化为轮盘赌的概率

if j == 0:

pft_div.append(pf_float[j])

else:

pft_div.append(pf_float[j] + pft_div[j-1])

return pft_div

# 选择

def selection(self, pcl, pft_div):

selected_pop = [] # 挑选后的新种群

select_float = [] # 随机产生的小数

for i in range(len(pcl)): # 产生随机小数

select_float.append(random.random())

for i in range(len(pcl)): # 轮盘赌选择

j = 0

while j < len(pcl):

if select_float[i] <= pft_div[j]: # 随机小数与适应度区间对比

selected_pop.append(pcl[j])

break

else:

j += 1

return selected_pop

# 交叉

def crossover(self, selected_pop, population): # 单点交叉

new_pop = [[]]

for i in range(len(population)):

cpoint = random.randint(0, len(selected_pop[0]) - 1) # 随机生成截取点 #

while True:

spoint1 = random.randint(0, len(selected_pop) - 1)

spoint2 = random.randint(0, len(selected_pop) - 1)

if spoint1 == spoint2:

continue

else:

break

temp = [] # 染色体片段暂时存储器

temp.extend(selected_pop[spoint1][0:cpoint]) # 第i个染色体0~截取点阶段的基因存储于temp中

temp.extend(selected_pop[spoint2][cpoint:len(selected_pop[0])]) # 第i+1个染色体截取点~末端阶段的基因存储于temp中

new_pop.append(temp)

return new_pop[1:]

# 变异

def mutation(self, new_pop):

for i in range(len(new_pop)): # 对所有染色体进行有概率的变异

mpoint = random.randint(0, len(new_pop[0])-1) # 根据染色体长度,随机生成变异的位数

prandom = random.random() # 随机生成[0,1)之间的小数作为比较概率

if prandom <= self.pm:

if new_pop[i][mpoint] == 1:

new_pop[i][mpoint] = 0

else:

new_pop[i][mpoint] = 1

next_pop = new_pop

return next_pop

# 二进制转十进制

def b2d(self, value_b):

pf_d = []

for i in range(len(value_b)):

value_d = 0

for j in range(len(value_b[0])):

value_d += value_b[i][j] * math.pow(2, len(value_b[0])-1-j)

pf_d.append(value_d)

return pf_d

# 可视化

def plot(self, pcl_d_list, pf, lower_bound, upper_bound, generation, iteration):

px = []

for i in range(len(pcl_d_list)):

pxt = lower_bound + pcl_d_list[i] * (upper_bound - lower_bound) / (math.pow(2, self.chromosome_length) - 1)

px.append(pxt)

py = pf

sca = plt.scatter(px, py, s=200, lw=0, c='red', alpha=0.5)

plt.pause(0.05)

print('px', len(px))

j = generation

if j < iteration-1:

if 'sca' in locals():

sca.remove()

# 主程序

def main(self, iteration):

population = self.species_origin() # 创建种群

results = []

for i in range(iteration):

self.translation(population)

all_fitness_list = self.function(population, 0, 2*math.pi)

pf = self.positive_fitness(all_fitness_list)

pcl = self.positive_chromosome(all_fitness_list, population)

self.plot(self.translation(pcl), pf, 0, 2 * np.pi, i, iteration)

#print('pcl', pcl)

pf_total = self.pf_sum(pf)

pf_float = self.pf_float(pf_total, pf)

pft_div = self.pf_div(pf_float)

#print('pft_div', pft_div)

selected_pop = self.selection(pcl, pft_div)

new_pop = self.crossover(selected_pop, population)

next_pop = self.mutation(new_pop)

population = next_pop

results.append(pf_total)

print('The', i, 'generation pf:', pf, '\npf length', len(pf))

plt.ioff()

plt.show()

if __name__ == '__main__':

ga = GA(100, 17, 0.01)

plt.ion()

x = np.linspace(0, 2*np.pi, 100)

Fx = 2 * np.sin(x) + np.cos(x)

plt.plot(x, Fx)

plt.grid()

ga.main(500)

上一篇:descriptive statistics|inferential statistics|Observational Studies| Designed Experiments


下一篇:英语四六级翻译11:城镇化