从考试题到实战手把手教你用Python实现轮盘赌算法附遗传算法完整代码第一次在遗传算法考题中遇到轮盘赌选择时那种面对陌生概念的茫然感我至今记忆犹新。当时盯着试卷上那四个二进制编码的个体和随机数序列完全不知道如何将抽象的数学描述转化为具体的选择操作。这种看得懂题目却写不出答案的挫败感正是许多算法学习者的共同痛点。本文将以那个让我失分的考题为起点带你用Python代码彻底拆解轮盘赌算法的实现细节最终完成一个能解决实际优化问题的完整遗传算法框架。1. 遗传算法核心流程解析遗传算法模仿生物进化过程通过选择、交叉和变异等操作逐步优化种群。其典型流程包含五个关键环节初始化种群随机生成一组潜在解适应度评估计算每个个体的优劣程度选择操作按适应度概率挑选优秀个体交叉重组交换个体基因片段基因变异随机修改部分基因其中轮盘赌算法正是实现选择操作的主流方法之一。它通过构建概率分布轮盘使适应度高的个体获得更大的选中概率就像赌场轮盘的不同区域对应不同中奖概率。注意轮盘赌选择虽然名字带有赌但实际是严格的数学概率模型与赌博活动无关2. 轮盘赌算法的数学原理与实现2.1 概率分配机制给定种群中n个个体每个个体i的适应度为f_i其被选中的概率p_i计算公式为p_i f_i / Σ(f_j) (j1到n)这就像将圆形轮盘划分为多个扇形区域每个区域的面积与对应个体的适应度成正比。旋转轮盘时指针停在某个区域的概率自然与其面积成正比。2.2 Python实现步骤我们用考题中的具体数据来演示实现过程。初始种群有4个个体其二进制编码和适应度如下个体编号二进制编码十进制值适应度f(x)x²101101131692110002457630100086441001119361实现轮盘赌选择需要三个关键步骤def roulette_wheel_selection(population, fitness_values, random_numbers): # 计算总适应度 total_fitness sum(fitness_values) # 计算每个个体的选择概率 probabilities [f/total_fitness for f in fitness_values] # 计算累积概率分布 cumulative_prob [sum(probabilities[:i1]) for i in range(len(probabilities))] selected [] for r in random_numbers: for i, cp in enumerate(cumulative_prob): if r cp: selected.append(population[i]) break return selected当输入随机数序列[0.42, 0.16, 0.89, 0.71]时算法运行过程如下总适应度 169 576 64 361 1170个体概率 [0.144, 0.492, 0.055, 0.309]累积概率 [0.144, 0.636, 0.691, 1.000]选择结果0.42 ∈ (0.144,0.636] → 选择个体20.16 ∈ (0.144,0.636] → 选择个体20.89 ∈ (0.636,1.000] → 选择个体40.71 ∈ (0.636,1.000] → 选择个体4最终新种群为[11000, 11000, 10011, 10011]3. 完整遗传算法实现现在我们将轮盘赌选择嵌入完整的遗传算法框架解决函数极值优化问题。以寻找f(x)x²在[0,31]区间的最大值为例。3.1 初始化种群import random def initialize_population(pop_size, chromosome_length): return [ .join(str(random.randint(0,1)) for _ in range(chromosome_length)) for _ in range(pop_size) ]5位二进制编码足够表示0-31的整数。初始化4个个体population initialize_population(4, 5) # 可能输出: [01101, 11000, 01000, 10011]3.2 适应度计算与选择def fitness_evaluation(population): return [int(ind,2)**2 for ind in population] fitness_values fitness_evaluation(population) selected roulette_wheel_selection(population, fitness_values, [random.random() for _ in range(4)])3.3 交叉与变异操作单点交叉实现def crossover(parent1, parent2, crossover_rate): if random.random() crossover_rate: point random.randint(1, len(parent1)-1) child1 parent1[:point] parent2[point:] child2 parent2[:point] parent1[point:] return child1, child2 return parent1, parent2位翻转变异实现def mutation(individual, mutation_rate): return .join( bit if random.random() mutation_rate else str(1-int(bit)) for bit in individual )3.4 完整迭代流程def genetic_algorithm(pop_size, chrom_length, generations, crossover_rate, mutation_rate): pop initialize_population(pop_size, chrom_length) best_individual None best_fitness 0 for gen in range(generations): fitness fitness_evaluation(pop) # 记录最优个体 current_max max(fitness) if current_max best_fitness: best_fitness current_max best_individual pop[fitness.index(current_max)] # 选择 selected roulette_wheel_selection(pop, fitness, [random.random() for _ in range(pop_size)]) # 交叉 new_pop [] for i in range(0, pop_size, 2): child1, child2 crossover(selected[i], selected[i1], crossover_rate) new_pop.extend([child1, child2]) # 变异 pop [mutation(ind, mutation_rate) for ind in new_pop] return best_individual, best_fitness4. 算法优化与实际问题应用4.1 轮盘赌算法的改进方案基础轮盘赌实现存在两个潜在问题选择压力不足适应度差异小时选择效果不明显精英丢失风险最优个体可能不被选中改进方案对比方法原理优点缺点尺度变换调整适应度计算方式简单易实现需要调参锦标赛选择局部竞争代替全局概率选择压力可控增加计算量精英保留策略强制保留最优个体保证收敛性可能降低多样性实现精英保留的改进版选择def elitist_roulette_selection(population, fitness_values, random_numbers): elite max(zip(population, fitness_values), keylambda x:x[1])[0] selected roulette_wheel_selection(population, fitness_values, random_numbers[:-1]) selected.append(elite) return selected4.2 实际优化问题案例求解函数 f(x) x*sin(10πx)2.0 在[-1,2]区间的最大值import math def real_value_ga(): # 修改适应度函数 def fitness_evaluation(pop): return [x*math.sin(10*math.pi*x)2.0 for x in (int(ind,2)/4095*3-1 for ind in pop)] # 使用20位编码提高精度 best, score genetic_algorithm( pop_size50, chrom_length20, generations100, crossover_rate0.8, mutation_rate0.01 ) x int(best,2)/1048575*3-1 # 转换为实际值 return x, score经过100代进化算法能找到全局最大值约3.85对应x≈1.85。这个案例展示了遗传算法处理复杂非线性优化的能力。