遗传算法之 : 排序
用遗传算法来对数组进行排序,这个效率很低,要迭代很多次,而且不稳定,所以这里只对长度为10的数组进行了排序,并尝试了几种随机突变操作.
import random
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
1. 初始化随机无序序列
def generate_initial_seq(length, geneSet):
#random.seed(2021)
geneSeq = random.sample(geneSet, length)
return geneSeq
geneSet = list(range(100))
# parent gene
initialSeq = generate_initial_seq(10, geneSet)
# targe seq
target = sorted(initialSeq)
初始化无序数组(Initial Seq 和 Targe Seq)
2.计算适应度
这里的适应度用相邻两个元素,是否有序的个数来表示,即:∑i=0N(xi<xi+1)\sum_{i = 0}^N (x_i < x_{i+1})∑i=0N(xi<xi+1)
def get_fitness(geneSeq):
fitness = np.sum([geneSeq[i] > geneSeq[i-1] for i in range(1, len(geneSeq))])
fitness = fitness+1
return fitness
get_fitness([81, 53, 91, 61, 54, 55, 74, 50, 31, 24])
4
3.突变
- 生成两个随机索引,调换两个位置元素(不相邻位置交换)
- 生成一个随机索引,调换索引前面元素(相邻位置交换)
- 生成一个随机索引,调换索引前后元素(间隔一个元素交换)
- 生成两个随机索引,调换索引前面元素(相邻位置交换)[1.的变种]
- 生成两个随机索引,调换索引前后元素(间隔一个元素交换)[1.的变种]
def mutate_v1(geneSeq):
indices = random.sample(list(range(len(geneSeq))), 2)
childSeq = geneSeq.copy()
childSeq[indices[0]] = geneSeq[indices[1]]
childSeq[indices[1]] = geneSeq[indices[0]]
return childSeq
def mutate_v2(geneSeq):
index = random.sample(list(range(1,len(geneSeq))), 1)[0]
childSeq = geneSeq.copy()
childSeq[index-1] = geneSeq[index]
childSeq[index] = geneSeq[index-1]
return childSeq
def mutate_v3(geneSeq):
index = random.sample(list(range(1,len(geneSeq)-1)), 1)[0]
childSeq = geneSeq.copy()
childSeq[index-1] = geneSeq[index+1]
childSeq[index+1] = geneSeq[index-1]
return childSeq
4. 进化
def evolution(length, initialSeq, mutate_func):
seq_list = []
fit_list = []
#initialSeq = generate_initial_seq(length, geneSet)
initialFitness = get_fitness(initialSeq)
targetSeq = sorted(initialSeq)
targetFitness = get_fitness(targetSeq)
seq_list.append(initialSeq)
fit_list.append(initialFitness)
print('First Generation Fitness is : %d'%initialFitness)
generation_count = 1
bestFitness = initialFitness
bestSeq = initialSeq
if initialFitness == targetFitness:
return initialSeq
while True:
#for i in range(2000):
childSeq = mutate_func(bestSeq)
childFitness = get_fitness(childSeq)
seq_list.append(childSeq)
fit_list.append(childFitness)
if bestFitness > childFitness:
continue
generation_count += 1
if (generation_count%200 ==0):
print("%d's Generation fitness : %d"%(generation_count,childFitness))
if (childFitness == targetFitness) or (generation_count >=1400):
break
# update
bestSeq = childSeq
bestFitness = childFitness
return seq_list, fit_list
# 初始化无序数组
initialSeq = generate_initial_seq(10, geneSet)
initialSeq
[88, 54, 80, 48, 40, 93, 58, 84, 75, 20]
# 第一种随机突变
seqs_1, fitness_1 = evolution(10, initialSeq, mutate_v1)
First Generation Fitness is : 4
200's Generation fitness : 9
400's Generation fitness : 9
600's Generation fitness : 9
800's Generation fitness : 9
# 第三种随机突变
seqs_3, fitness_3 = evolution(10, initialSeq, mutate_v3)
First Generation Fitness is : 4
200's Generation fitness : 7
400's Generation fitness : 7
600's Generation fitness : 7
800's Generation fitness : 7
1000's Generation fitness : 7
1200's Generation fitness : 7
1400's Generation fitness : 7
#seqs_4, fitness_4 = evolution(10, geneSet, mutate_v4)
#seqs_5, fitness_5 = evolution(10, geneSet, mutate_v5)
遗传若干代后的效果对比
结果证明随机交换两个位置元素,最终收敛了,其他2,3,4,5都不行,遗传多代还是会陷入僵局.