赞
踩
种群(Population):种群是指用遗传算法求解问题时, 初始给定的多个解的集合。遗传算法的求解过程是从这个子集开始的。
个体(Individual):个体是指种群中的单个元素,它通常 由一个用于描述其基本遗传结构的数据结构来表示。例如, 可以用0、1组成的长度为1的串来表示个体。
染色体(Chromosome):染色体是指对个体进行编码后 所得到的编码串。染色体中的每1位称为基因,染色体上由 若干个基因构成的一个有效信息段称为基因组。
适应度函数(Fitness):适应度函数是一种用来对种群中 各个个体的环境适应性进行度量的函数。其函数值是遗传 算法实现优胜劣汰的主要依据。【一般采用适应性函数来度量某个解决方案的优劣】
遗传操作(Genetic Operator):遗传操作是指作用于种群而产生新的种群的操作。标准的遗传操作包括以下3种基本形式:
– 选择(Selection)
– 杂交(Crosssover)
– 变异(Mutation)
将问题的候选解用染色体表示,实现解空间向编码空间的映射过程。遗传算法不直接处理解空间的决策变量,而是将其转换成由基因按一定结构组成的染色体。编码方式有很多,如二进制编码、实数向量编码、整数排列编码、通用数据结构编码等等。本文将采用二进制编码的方式,将十进制的变量转换成二进制,用0和1组成的数字串模拟染色体,可以很方便地实现基因交叉、变异等操作。
产生代表问题可能潜在解集的一个初始群体(编码集合)。种群规模设定主要有以下方面的考虑:从群体多样性方面考虑,群体越大越好,避免陷入局部最优;从计算效率方面考虑,群体规模越大将导致计算量的增加。应该根据实际问题确定种群的规模。产生初始化种群的方法通常有两种:一是完全随机的方法产生;二是根据先验知识设定一组必须满足的条件,然后根据这些条件生成初始样本。
利用适应度函数计算各个个体的适应度大小。适应度函数(Fitness Function)的选取直接影响到遗传算法的收敛速度以及能否找到最优解,因为在进化搜索中基本不利用外部信息,仅以适应度函数为依据,利用种群每个个体的适应程度来指导搜索。
通过选择、交叉、变异,产生出代表新的解集的群体。选择(selection):根据个体适应度大小,按照优胜劣汰的原则,淘汰不合理的个体;交叉(crossover):编码的交叉重组,类似于染色体的交叉重组;变异(mutation):编码按小概率扰动产生的变化,类似于基因突变。
末代种群中的最优个体经过解码实现从编码空间向解空间的映射,可以作为问题的近似最优解。这是整个遗传算法的最后一步,经过若干次的进化过程,种群中适应度最高的个体代表问题的最优解,但这个最优解还是一个由0和1组成的数字串,要将它转换成十进制才能供我们理解和使用。
(1)交换染色体信息
(2)染色体信息变异
通俗讲解:
父体提供一条染色体,母体提供一条染色体,然后这两条染色体之间进行部分的信息交换,这样就产生了两条新的个体。
这两条新的个体和原来的父体、母体就构成了新的族群。
当然,在交换的过程中,有可能出现信息变异,也就是信息交换中存在一些未知的可能性,可能会让遗传行为向着更有利的方向推进。
也就是说,遗传的本质就是交换信息和信息变异。
然后,再对族群优胜劣汰,防止族群的数量越来越多。
(1)创建包含100个解的初始解集
import random
def create_answer(number_set, n):
# 创建随机解集,包含n个解,每个解的长度都为10
result = []
for i in range(n):
result.append(random.sample(number_set, 10))
return result
numbers_set = random.sample(range(0, 1000), 50) # 从0-1000内随机抽取50个元素
print(numbers_set)
middle_answer = create_answer(numbers_set, 100)
print(middle_answer)
上面讲到的两种思路,代码实现时采用的是思路2,因为在交换时已经考虑到了优胜劣汰问题。
先写一个计算误差的函数
import random
def create_answer(numbers_set, n):
# 创建随机解集,包含n个解,每个解的长度都为10
result = []
for i in range(n):
result.append(random.sample(numbers_set, 10))
return result
def error_level(new_answer, numbers_set):
# new_answer 是什么
error = []
right_answer = sum(numbers_set)/10 # 表示原数组的十分之一
for item in new_answer:
value = abs(right_answer-sum(item))
if value == 0:
error.append(10)
else:
error.append(1/value)
return error
def choice_selected(old_answer, numbers_set):
result = []
error = error_level(old_answer, numbers_set)
error_one = [item/sum(error) for item in error] # 归一化
for i in range(1, len(error_one)):
error_one[i] += error_one[i-1] # 累积求和
for i in range(len(old_answer)//2):
temp = []
for j in range(2):
rand = random.uniform(0, 1)
for k in range(len(error_one)):
if k == 0:
if rand < error_one[k]:
temp.append(old_answer[k])
else:
if rand >= error_one[k-1] and rand < error_one[k]:
temp.append(old_answer[k])
rand = random.randint(0, 6)
temp_1 = temp[0][:rand] + temp[1][rand:rand+3] + temp[0][rand+3:]
temp_2 = temp[1][:rand] + temp[0][rand:rand+3] + temp[1][rand+3:] # 至此产生了新的两个个体
result.append(temp_1)
result.append(temp_2)
return result
def variation(old_answer, numbers_set, pro):
for i in range(len(old_answer)):
rand = random.uniform(0, 1)
if rand < pro:
rand_num = random.randint(0, 9)
old_answer[i] = old_answer[i][:rand_num] + random.sample(numbers_set, 1) + old_answer[i][rand_num+1:]
return old_answer
numbers_set = random.sample(range(0, 1000), 50) # 从0-1000内随机抽取50个元素
print(numbers_set)
middle_answer = create_answer(numbers_set, 100)
print(middle_answer)
first_answer = middle_answer[0]
great_answer = []
for i in range(1000):
middle_answer = choice_selected(middle_answer, numbers_set)
middle_answer = variation(middle_answer, numbers_set, 0.1)
error = error_level(middle_answer, numbers_set)
index = error.index(max(error)) # 选择误差最小的
great_answer.append([middle_answer[index], error[index]])
great_answer.sort(key=lambda x:x[1], reverse=True)
print("正确答案为", sum(numbers_set)/10)
print("给出的最优解为", great_answer[0][0])
print("该和为", sum(great_answer[0][0]))
print("选择系数为", great_answer[0][1 ])
print("最初解的和为", sum(first_answer))
# print(middle_answer)
[489, 295, 150, 490, 914, 227, 829, 678, 462, 445,
268, 260, 590, 542, 877, 980, 200, 267, 969, 161,
594, 598, 775, 587, 614, 736, 939, 439, 2, 891,
108, 238, 55, 764, 288, 947, 564, 996, 669, 254,
738, 588, 578, 817, 116, 525, 790, 153, 782, 977]
原数组的和为:27215,也就是说要找到10个数无限接近2721.5
正确答案为 2721.5
给出的最优解为 [227, 55, 598, 260, 490, 55, 238, 445, 200, 153]
该和为 2721
选择系数为 2.0
最初解的和为 5651
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。