遗传算法详解 附python代码实现

遗传算法

遗传算法是用于解决最优化问题的一种搜索算法。从名字来看,遗传算法借用了生物学里达尔文的进化理论:”适者生存,不适者淘汰“,将该理论以算法的形式表现出来就是遗传算法的过程。

问题引入

上面提到遗传算法是用来解决最优化问题的,下面我将以求二元函数:

def F(x, y):
	return 3*(1-x)**2*np.exp(-(x**2)-(y+1)**2)- 10*(x/5 - x**3 - y**5)*np.exp(-x**2-y**2)- 1/3**np.exp(-(x+1)**2 - y**2)

x ∈ [ − 3 , 3 ] , y ∈ [ − 3 , 3 ] x\in[-3, 3], y\in[-3, 3] x[3,3],y[3,3]范围里的最大值为例子来详细讲解遗传算法的每一步。该函数的图像如下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过旋转视角可以发现,函数在这个局部的最大值大概在当 x ≈ 0 , y ≈ 1.5 x \approx 0,y\approx1.5 x0,y1.5时,函数值取得最大值,这里的 x , y x,y x,y的取值就是我们最后要得到的结果。

算法详解

先直观看一下算法过程:

寻找最小值:

在这里插入图片描述

寻找最大值
在这里插入图片描述

首先我们生成了200个随机的(x,y)对,将(x, y)坐标对带入要求解的函数F(x,y)中,根据适者生存,我们定义使得函数值F(x,y)越大的(x,y)对越适合环境,从而这些适应环境的(x,y)对更有可能被保留下来,而那些不适应该环境的(x,y)则有很大几率被淘汰,保留下来的点经过繁殖产生新的点,如此进化下去最后留下的大部分点都是试应环境的点,即在最高点附近。下图为算法执行结果,和上面的分析 x ≈ 0 , y ≈ 1.5 x \approx 0,y\approx1.5 x0,y1.5相近。

在这里插入图片描述

种群和个体的概念

遗传算法启发自进化理论,而我们知道进化是由种群为单位的,种群是什么呢?维基百科上解释为:在生物学上,是在一定空间范围内同时生活着的同种生物的全部个体。显然要想理解种群的概念,又先得理解个体的概念,在遗传算法里,个体通常为某个问题的一个解,并且该解在计算机中被编码为一个向量表示! 我们的例子中要求最大值,所以该问题的解为一组可能的 ( x , y ) (x, y) (x,y)的取值。比如 ( x = 2.1 , y = 0.8 ) , ( x = − 1.5 , y = 2.3 ) . . . (x=2.1,y=0.8), (x=-1.5, y=2.3)... (x=2.1,y=0.8),(x=1.5,y=2.3)...就是求最大值问题的一个可能解,也就是遗传算法里的个体,把这样的一组一组的可能解的集合就叫做种群 ,比如在这个问题中设置100个这样的 x , y x,y x,y的可能的取值对,这100个个体就构成了种群。

编码、解码与染色体的概念

在上面个体概念里提到个体(也就是一组可能解)在计算机程序中被编码为一个向量表示,而在我们这个问题中,个体是 x , y x,y x,y的取值,是两个实数,所以问题就可以转化为如何将实数编码为一个向量表示,可能有些朋友有疑惑,实数在计算机里不是可以直接存储吗,为什么需要编码呢?这里编码是为了后续操作(交叉和变异)的方便。实数如何编码为向量这个问题找了很多博客,写的都是很不清楚,看了莫烦python的教学代码,终于明白了一种实数编码、解码的方式。


生物的DNA有四种碱基对,分别是ACGT,DNA的编码可以看作是DNA上碱基对的不同排列,不同的排列使得基因的表现出来的性状也不同(如单眼皮双眼皮)。在计算机中,我们可以模仿这种编码,但是碱基对的种类只有两种,分别是0,1。只要我们能够将不同的实数表示成不同的0,1二进制串表示就完成了编码,也就是说其实我们并不需要去了解一个实数对应的二进制具体是多少,我们只需要保证有一个映射
y = f ( x ) , x   i s   d e c i m a l   s y s t e m , y   i s   b i n a r y   s y s t e m y=f(x), x \ is\ decimal \ system, y \ is \ binary\ system y=f(x),x is decimal system,y is binary system
能够将十进制的数编码为二进制即可,至于这个映射是什么,其实可以不必关心。将个体(可能解)编码后的二进制串叫做染色体染色体(或者有人叫DNA)就是个体(可能解)的二进制编码表示。为什么可以不必关心映射 f ( x ) f(x) f(x)呢?因为其实我们在程序中操纵的都是二进制串,而二进制串生成时可以随机生成,如:

#pop表示种群矩阵,一行表示一个二进制编码表示的DNA,矩阵的行数为种群数目,DNA_SIZE为编码长度,不理解乘2的看后文
pop 
遗传算法是一种优化算法,可用于解决路径规划问题。在Python中,您可以使用遗传算法库进行路径规划的实现。以下是一个简单的示例: ```python import random # 定义路径规划问题 # 假设我们有一个包含城市坐标的列表,需要找到最短路径经过所有城市并回到起点 city_list = [(2, 4), (5, 7), (8, 3), (1, 6), (9, 2)] # 定义遗传算法参数 population_size = 100 # 种群大小 elite_size = 20 # 精英个体数量 mutation_rate = 0.01 # 变异率 generations = 100 # 迭代次数 # 创建一个路径类表示个体 class Path: def __init__(self, path): self.path = path self.distance = 0 def calculate_distance(self): total_distance = 0 for i in range(len(self.path) - 1): city1 = self.path[i] city2 = self.path[i + 1] total_distance += ((city2[0] - city1[0]) ** 2 + (city2[1] - city1[1]) ** 2) ** 0.5 self.distance = total_distance # 创建初始种群 def create_population(): population = [] for _ in range(population_size): path = random.sample(city_list, len(city_list)) population.append(Path(path)) return population # 计算每个个体的适应度(路径长度) def calculate_fitness(population): for path in population: path.calculate_distance() # 选择精英个体 def select_elite(population): sorted_population = sorted(population, key=lambda x: x.distance) return sorted_population[:elite_size] # 交叉操作 def crossover(parent1, parent2): child = [] gene_a = int(random.random() * len(parent1.path)) gene_b = int(random.random() * len(parent1.path)) start_gene = min(gene_a, gene_b) end_gene = max(gene_a, gene_b) for i in range(start_gene, end_gene): child.append(parent1.path[i]) for city in parent2.path: if city not in child: child.append(city) return Path(child) # 变异操作 def mutate(path): for _ in range(len(path.path)): if random.random() < mutation_rate: index1 = int(random.random() * len(path.path)) index2 = int(random.random() * len(path.path)) path.path[index1], path.path[index2] = path.path[index2], path.path[index1] # 迭代进化 def evolve(population): elite = select_elite(population) new_population = elite while len(new_population) < population_size: parent1 = random.choice(elite) parent2 = random.choice(elite) child = crossover(parent1, parent2) mutate(child) new_population.append(child) return new_population # 主函数 def main(): population = create_population() for _ in range(generations): calculate_fitness(population) population = evolve(population) best_path = min(population, key=lambda x: x.distance) print("最短路径:", best_path.path) print("最短路径长度:", best_path.distance) if __name__ == '__main__': main() ``` 上述代码演示了如何使用遗传算法解决路径规划问题。您可以根据实际需求进行扩展和修改。希望对您有所帮助!
评论 349
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值