Python实现遗传算法精英保留(Elitism)的字典逻辑问题
遗传算法精英保留逻辑修正
核心问题定位
- 原代码拼写错误的
eletism函数未实现实际精英提取逻辑,仅做了无意义的排序和打印操作 - 生成下一代种群的逻辑未将当代最优个体纳入下一代,会导致最优解被交叉、变异操作破坏
- 适应度函数为最小值优化目标,
sort_population_by_fitness按升序排列后,最优个体位于列表索引0位置,原代码末尾取[-1]实际拿到的是当代最差个体 - 原
mutate函数边界校验循环的初始标记值设为0,导致边界判断逻辑永远不会触发,变异后坐标可能超出[-2,2]的设定范围 - Python字典为引用类型,直接赋值会导致精英个体和原种群个体指向同一块内存,后续操作可能意外篡改精英值
具体修正方案
- 重写精英保留函数,直接从排序后的种群中提取适应度最优的个体,生成独立副本返回
- 调整下一代生成逻辑:原逻辑固定生成9个新个体(种群总规模为10),在新个体生成完成后将精英个体直接加入下一代列表
- 修正变异函数的边界校验循环初始标记值,保证变异后坐标始终落在设定边界内
- 修正迭代结束后全局最优个体的取值索引
修正后完整代码
import random def generate_population(size, x_boundaries, y_boundaries): lower_x_boundary, upper_x_boundary = x_boundaries lower_y_boundary, upper_y_boundary = y_boundaries population = [] for i in range(size): individual = { 'x': random.uniform(lower_x_boundary, upper_x_boundary), 'y': random.uniform(lower_y_boundary, upper_y_boundary), } population.append(individual) return population def fitness(individual): x = individual['x'] y = individual['y'] # Rosenbrock函数,最小值为0,在(1,1)处取得 return abs((-(100*(x*x - y)*(x*x - y) + (1 - x)*(1-x)))) def sort_population_by_fitness(population): return sorted(population, key=fitness) def choice_by_roulette(sorted_population, fitness_sum): drawn = random.uniform(0, 1) accumulated = 0 for individual in sorted_population: fitnessX = fitness(individual) probability = fitnessX / fitness_sum accumulated += probability if drawn <= accumulated: return individual def crossover(choice_a, choice_b): xa = choice_a['x'] ya = choice_a['y'] xb = choice_b['x'] yb = choice_b['y'] return {'x': xa+0.01, 'y': ya+0.01} def mutate(new_individual): x = new_individual['x'] y = new_individual['y'] # 修正初始标记值,首次进入循环做边界校验 flagx = 1 flagy = 1 new_x = x*(1+random.uniform(-0.01/2, 0.01/2)) new_y = y*(1+random.uniform(-0.01/2, 0.01/2)) while flagx == 1: if (new_x > 2) or (new_x < -2): new_x = x*(1+random.uniform(-0.01/2, 0.01/2)) flagx = 1 else: flagx = 0 while flagy == 1: if (new_y > 2) or (new_y < -2): new_y = y*(1+random.uniform(-0.01/2, 0.01/2)) flagy = 1 else: flagy = 0 return {'x': new_x, 'y': new_y} def elitism(sorted_population): # 提取升序排列后的第一个个体(适应度最小,即最优),生成副本避免引用篡改 best_individual = sorted_population[0].copy() return best_individual def make_next_gen(population): next_gen = [] sorted_population = sort_population_by_fitness(population) soma_fitness = sum(fitness(individual)for individual in population) # 生成9个新个体,留1个位置给精英 for i in range(9): first_choice = choice_by_roulette(sorted_population, soma_fitness) second_choice = choice_by_roulette(sorted_population, soma_fitness) new_individual = crossover(first_choice, second_choice) drawn = random.randint(1,5) if drawn == 1: new_individual = mutate(new_individual) next_gen.append(new_individual) # 加入当代精英个体,直接进入下一代 next_gen.append(elitism(sorted_population)) return next_gen generations = 100 population = generate_population(size=10, x_boundaries=(-2, 2), y_boundaries=(-2, 2)) i = 0 while i!= generations: print(f"=== 第{i}代 ===") for individual in population: print(individual, fitness(individual)) population = make_next_gen(population) i += 1 # 修正最优个体取值:升序排列第一个为最优 best_individual = sort_population_by_fitness(population)[0] print("=== 迭代结束最优个体 ===") print(best_individual, fitness(best_individual))
效果说明
修正后每一代的最优个体都会完整保留到下一代,不会被交叉、变异操作丢失,算法会稳定向(1,1)的全局最优解收敛,最终适应度会无限趋近于0。
内容的提问来源于stack exchange,提问作者João Vitor Detoni
相关产品推荐
相关产品推荐

