import numpy as np
import matplotlib.pyplot as plt
class GA(object):
def __init__(self, para_array=None, obj_func=None, max_iter=50, mp=0.05, cp=0.9, delta=0.001, population_size=100):
"""
:param para_array: 参数数组
:param max_iter: 最大迭代次数
:param mp: 变异概率
:param cp: 交叉概率
:param delta: 放大倍数
:param population_size:
"""
self.para_array = para_array
self.obj_func = obj_func
self.max_iter = max_iter
self.mp = mp
self.cp = cp
self.delta = delta
self.population_size = population_size
# 根据解的精度确定染色体(chromosome)的长度——确定二进制编码的长度
# 需要根据决策变量的上下边界来确定
# 需要根据决策变量的上下边界来确定
def get_encoded_length(self):
"""
:return: 每一个超参的二进制表示的长度
"""
# 每个变量的编码长度
lengths = []
# 根据给定的定义域(自变量的范围)来获取其二进制的长度
for i in self.para_array:
lower = i[0]
upper = i[1]
while ((np.log2((upper - lower) / self.delta)) + 1) < 6:
self.delta = self.delta / 10
# print((upper - lower) / delta)
# res = fsolve(lambda x: ((upper - lower) * 1 / delta) - 2 ** x + 1, np.array([50]))
# length = int(np.ceil(res[0]))
# 得到十进制数的二进制的位数
length = int(np.log2((upper - lower) / self.delta)) + 1
# print(length)
lengths.append(length)
return lengths
# GA NI_GA PSO 模拟退火
# 随机生成初始编码种群——二进制编码 (编码长度,种群大小)
# 第一代
def get_initial_population(self, encode_length, population_size):
"""
:param encode_length: 二进制编码的长度
:param population_size: 种群的大小
:return: 初始种群
"""
# 种群初始化
chromosomes = np.zeros((population_size, sum(encode_length)), dtype=np.uint8)
# 以0,1随机生成初代种群(染色体/个体的集合)
for i in range(population_size):
chromosomes[i, :] = np.random.randint(0, 2, sum(encode_length)) # 随机生成 encode_length个0和1
return chromosomes
# 染色体解码得到表现型的解,染色体=个体,每个0,1代表基因
def decoded_chromosome(self, encode_length, chromosomes, boundary_list):
"""
:param encode_length: 多个种群组成的矩阵
:param chromosomes: 编码后的种群
:param boundary_list: 含有多个超参数二进制长度的列表
:return: 解码后的种群
"""
populations = chromosomes.shape[0] # 染色体的个数 10
variables = len(encode_length) # 染色体片段数(种群的个数) 2
decoded_values = np.zeros((populations, variables)) # 解码出来的个体的存储ndarray
for k, chromosome in enumerate(chromosomes):
# print(k, chromosome)
chromosome = chromosome.tolist() # 将每个单独的染色体从ndarray转换为列表
start = 0
for index, length in enumerate(encode_length):
# 将一个染色体进行拆分,得到染色体片段,也就相当于将每个二进制组拆分,得到每个变量的二进制片段
power = length - 1
# 将二进制转换为十进制
decimal = 0
for i in range(start, start + length):
decimal += chromosome[i] * (2 ** power)
power -= 1
# 得到初始的十进制数,再次存为lower,upper
lower = boundary_list[index][0]
upper = boundary_list[index][1]
# 将前面二进制和转换出的十进制缩小倍数再加上lower,得到在Lower和upper中间的十进制数
decoded_value = lower + decimal * (upper - lower) / (2 ** length - 1)
# (upper - lower) / (2 ** length - 1) 表示精度
decoded_values[k, index] = decoded_value
# 将start也就是二进制的索引位置移到染色体下一段的开始位置
start = length
return decoded_values
# 得到一矩阵,最外围维度表示种群中个体数量,下一维度表示决策变量(染色体片段数或种群个数)个数
def get_fitness_value(self, func, chromosomes_decoded):
Python遗传算法的测试实现(numpy和matplotlib)
最新推荐文章于 2024-07-30 17:23:09 发布