遗传算法上机作业
一、算法流程
Step1(初始化) 确定种群规模N,交叉概率pc,变异概率pm和终止条件。 随机生成N个个体作为初始种群P(0),设种群代数t=0。
Step2(个体评价) 计算种群P(t)中每个个体的适应度值。
Step3(种群进化)
3.1 (选择父代) 运用选择算子从P(t)中选择出N/2对父代;
3.2 (交叉) 对选择的N/2对父代,依概率pc进行交叉,生成的子代个体记 为集合O1;
3.3 (变异) 对集合O1中的个体依概率pm进行变异,生成的子代个体记为 集合O2;
3.4 (选择子代) 从集合 中依据选择算子选出N个个体组成下一 代种群P(t+1);
Step4(终止检验) 如算法满足终止条件,则输出P(t+1)中具有最大适应 度值的个体作为最优解,终止算法。否则,令t=t+1,转入步骤3
def main():
#变量范围
decisionVariables = [[-3.0, 12.1], [4.1, 5.8]]
#精度
delta=0.0001
#二进制编码长度
length = getEncodeLength(decisionVariables,delta)
#初始种群数
N=200
totallength=length[0]+length[1]
#交叉概率
pc=0.6
#变异概率,注意是每个基因位变异的概率
pm=0.01
#保留精英数
E=N//5
# 最大进化代数
maxgeneration = 200
#保存每一代最大适应度对应个体的基因
maxindividuals = []
#保存每一代最大适应度
maxfitness=[]
#初始化种群
population=getinitialPopulation(totallength,N)
# print(population)
for i in range(maxgeneration):
#计算种群适应度
populationfitness=getFitnessValue(population,decisionVariables,length)
#利用轮盘赌选择选择N/2对父代进行交叉,生成交叉子代offspring
selected_parents=selectNewPopulation(populationfitness,population,N)
offspring=crossoverpopulation(selected_parents,pc)
#对交叉生成的子代变异,生成交叉变异子代
mutaoffspring=mutapopulation(offspring,pm)
#选出父代和子代集合中最好的E个个体直接保留到下一代种群,然后,根据轮盘赌选择从父代和子代集合中选N-E个个体进入下一代种群
totalpopulation=population+offspring+mutaoffspring
totalpopulationfitness=getFitnessValue(totalpopulation,decisionVariables,length)
#选出精英个体
max_indices = get_max_indices(totalpopulationfitness, E)
#精英种群
Elites=[totalpopulation[i] for i in max_indices]
#根据轮盘赌选择从父代和子代集合中选N-E个个体进入下一代种群
temp=selectNewPopulation(totalpopulationfitness,totalpopulation,N-E)
#生成下一个种群
population=Elites+temp
#记录每一代适应度最大值
maxfitness.append(max(totalpopulationfitness))
index=get_max_indices(totalpopulationfitness, 1)
#保存每一代最大适应度对应个体的基因
maxindividuals.append(totalpopulation[index[0]])
maxval=np.max(maxfitness)
index=get_max_indices(maxfitness, 1)
maxindividual=maxindividuals[index[0]]
print(maxval)
print(maxindividual)
print(decode(maxindividual,decisionVariables,length))
start_time = time.time()
main()
end_time = time.time()
runtime = end_time - start_time
print("程序运行时间: %.2f秒" % runtime)
二、具体实现
1.二进制编码
decisionVariables = [[-3.0, 12.1], [4.1, 5.8]]
#计算在变量范围decisionVariables下,精度为delta时变量的编码长度,本问题length=[18,15]
def getEncodeLength(decisionvariables, delta):
# 将每个变量的编码长度放入数组
lengths = []
for decisionvar in decisionvariables:
uper = decisionvar[1]
low = decisionvar[0]
# 计算变量范围的大小
range_size = uper - low
# 计算编码长度
length = int(np.ceil(np.log2(range_size / delta + 1)))
lengths.append(length)
# 输出编码长度数组
print("染色体长度:", lengths)
return lengths
#解码函数,用解码公式
def decode(gene,decisionVariables,length):
gene1=gene[0:length[0]]
gene2=gene[length[0]:length[0]+length[1]]
bin1=int(''.join(map(str, gene1)), 2)
bin2=int(''.join(map(str, gene2)), 2)
val1=decisionVariables[0][0]+(decisionVariables[0][1]-decisionVariables[0][0])*bin1/(2**length[0]-1)
val2=decisionVariables[1][0]+(decisionVariables[1][1]-decisionVariables[1][0])*bin2/(2**length[1]-1)
return val1,val2
#print(int(''.join(map(str, [1,1,0])), 2))
#print(decode([1,1, 1, 0,1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1,0, 0, 1, 0, 1, 1,0, 1,0],decisionVariables,length))
3.初始化种群
#初始化种群
def getinitialPopulation(totallength, populationSize):
population=[]
#种群大小为populationSize,totallength是基因总长度,本例为18+15=33
for i in range(populationSize):
individual=[]
#每个基因位随机生成0或1
for j in range(totallength):
individual.append(random.randint(0, 1))
population.append(individual)
return population
# print(getinitialPopulation(33,2))
4.适应度函数
#计算适应度函数
def fitnessFunction(a,b):
return 21.5 + a * np.sin(4 * np.pi * a) + b * np.sin(20 * np.pi * b)
#计算种群适应度
def getFitnessValue(population,decisionVariables,length):
fitness=[]
for i in range(len(population)):
x1,x2=decode(population[i],decisionVariables,length)
# print(x1,x2)
fitness.append(fitnessFunction(x1,x2))
return fitness
5.轮盘赌选择函数
#通过轮盘赌选个体进入交叉池
def selectNewPopulation(populationfitnesss,population,n):
total_fitness = sum(populationfitnesss)
#首先,计算个体的适应度占总适应度的比值
probabilities = [fitness / total_fitness for fitness in populationfitnesss]
# 计算个体累计适应度
cumulative_fitness = np.cumsum(probabilities)
index=[]
for i in range(n):
#最后,随机产生10个[0,1]之间的实数,并选择对应的个体
random_number = random.random()
# print(random_number)
for j in range(len(cumulative_fitness)):
if(random_number<cumulative_fitness[j]):
index.append(j)
# print(j)
break
# print("index:",index)
selected_parents=[]
for i in range(len(index)):
selected_parents.append(population[index[i]])
return selected_parents
6.交叉函数
#交叉函数,根据交叉概率进行两点交叉,对选择的N/2对父代,依概率pc进行交叉
def crossover(parent1, parent2):
random_numbers = [random.randint(0, 10) for _ in range(2)]
min=np.min(random_numbers)
max=np.max(random_numbers)
child1 = parent1[:min] + parent2[min:max]+parent1[max:]
child2 = parent2[:min] + parent1[min:max]+parent2[max:]
return child1, child2
def crossoverpopulation(selected_parents,pc):
offspring=[]
for i in range(0,len(selected_parents),2):
random_number = random.random()
# print(random_number)
if(random_number<pc):
child1,child2=crossover(selected_parents[i],selected_parents[i+1])
offspring.append(child1)
offspring.append(child2)
return offspring
7.变异函数
#变异函数,对集合O1中的个体依概率pm进行变异
def mutation(individual, pm):
for i in range(len(individual)):
random_number = random.random()
if(random_number<pm):
if(individual[i]==1):
individual[i]=0
else:
individual[i]=1
return individual
def mutapopulation(offspring,pm):
mutaoffspring=[]
for i in range(len(offspring)):
mutaoffspring.append(mutation(offspring[i],pm))
return mutaoffspring
8.工具函数
#以列表形式返回lst最大n个数的下标
def get_max_indices(lst, n):
indices = sorted(range(len(lst)), key=lambda i: lst[i], reverse=True)[:n]
return indices