生物的进化是一个奇妙的优化过程,它通过选择淘汰,突然变异,基因遗传等规律产生适应环境变化的优良物种。而遗传算法就是根据生物进化思想而启发得到的一种全局优化方法,它的基本思想建立在达尔文的进化论和孟德尔的遗传学说之上。
生物只有经过许多世代的不断演化,才能更好地完成生存与繁衍的任务。遗传算法也遵循同样的方式,需要随着时间的推移不断成长、演化,最后才能收敛,得到针对某类特定问题的一个或多个解。
用遗传算法求解问题一般分为4步:
1.确定问题的表示方案。(编码与解码)
2.确定个体适应度评价方案。
3.确定各种算子类型及控制算法的参数和变量
4.确定停止运行的准则。
下面是用遗传算法求解一个数学问题的示例。
计算下列函数的最大值:
max f(x) = x + 10sin(5x) + 7cos(4x)
s.t. 0 <= x <= 10
决策变量为x,优化模型为f(x),求解步骤如下。
(1)确定编码与解码方法。假定编码精度要求为1e-6,则需要用长度为22位的二进制编码串来表示决策变量x。解码则是算出二进制编码串的十进制值,再进行一个逆运算得到具体的x值。
(2)确定个体评价方法。由于目标函数的取值可正可负,并且优化的目标是求函数的最大值,故可将个体的适应度取为每次迭代的最小值的绝对值加上目标函数值。
(3)设计遗传算子。选择运算使用比例选择算子,杂交运算使用单点交叉算子,变异运算使用基本位变异算子。
(4)确定算法的运行参数。群体大小取50,终止代数取100代,杂交概率取0.65,变异概率取0.05。
下面就是遗传算法的执行过程了。
#遗传算法
import numpy as np
import math
import random as rd
# max y = x + 10sin(5x) + 7cos(4x)
# 0 <= x <= 10
def code (x): #编码 用22位2进制码对x进行表示
s = bin(round(x / 10 * 4194303))
s = s[2:]
for i in range(22 - len(s)):
s = '0' + s
return s
def f(x): #目标函数
return x + 10 * math.sin(5 * x) + 7 * math.cos(4 * x)
def decode(s): #解码
return int(s,2) * 10 / 4194303
def fitnessEva(race): #评估种群适应性,适应度取为每次迭代的最小值的绝对值加上目标函数值
x = []
for i in range(len(race)):
x.append(f(decode(race[i])))
minVal = abs(min(x))
for i in range(len(x)):
x[i] = minVal + x[i]
return x
def choose(race): #比例选择算子
fitness = fitnessEva(race)
nextRace = []
roulette = np.array(fitness).cumsum() #生成轮盘
while len(nextRace) != N:
for i in range(len(race)):
r = rd.uniform(0,max(roulette))
if roulette[i] >= r:
nextRace.append(race[i])
if len(nextRace) == N:
break
return nextRace
def intersect(race): #单点交叉算子
pair = []
selected = []
for i in range(len(race)):
if i in selected:
continue
selected.append(i)
r = np.random.randint(i,len(race))
while r in selected:
r = np.random.randint(i, len(race))
selected.append(r)
pair.append([i,r]) #随机两两配对
for i in range(len(pair)):
interlocaition = np.random.randint(0,21)
r = rd.random()
if r < pc:
exchange(race,interlocaition,pair[i])
def mutate(race): #基本位变异算子
for i in range(len(race)):
r = rd.random()
if r < pm:
mutLocation = np.random.randint(0,22)
if race[i][mutLocation] == '0':
race[i] = race[i][:mutLocation] + '1' + race[i][mutLocation + 1:]
else:
race[i] = race[i][:mutLocation] + '0' + race[i][mutLocation + 1:]
def exchange(race,location,pairNum): #交换两个个体的部分染色体
# s = race[pairNum[0]]
# race[pairNum[0]][location + 1:] = race[pairNum[1]][location + 1:]
# race[pairNum[1]][location + 1:] = s[location + 1:]
s1 = race[pairNum[0]][:location + 1]
s2 = race[pairNum[0]][location + 1:]
s3 = race[pairNum[1]][:location + 1]
s4 = race[pairNum[1]][location + 1:]
race[pairNum[0]] = s1 + s4
race[pairNum[1]] = s3 + s2
if __name__ == '__main__':
N = 50 #群体大小
Ger = 100 #终止代数
pc = 0.65 #杂交概率
pm = 0.05 #变异概率
generation = 0
race = []
for i in range(N):
x = rd.uniform(0, 10)
race.append(code(x))
while generation < Ger:
race = choose(race) #选择
intersect(race) #杂交
mutate(race) #变异
generation += 1
fitness = fitnessEva(race)
print("函数最大值为:")
print(f(decode(race[fitness.index(max(fitness))])))
遗传算法是一种启发式方法,不能保证其所得解为全局最优解,且它容易出现过早收敛、过慢结束等问题。