基于遗传算法的莎士比亚猴子实验Python代码报错求助
修正基于遗传算法的莎士比亚猴子实验代码(索引错误修复)
原代码核心错误点
- DNA类的
genes和fitness_val是类属性,所有实例共享同一列表,导致基因数据混乱引发索引错误 - crossover方法中创建child实例时传入长度0,导致
genes为空,直接切片赋值触发索引错误;且错误地直接对实例进行切片操作,应操作实例的genes属性 - mutate方法错误引用未定义的
self.child,且未按突变概率触发突变,而是强制修改所有基因 - get_phrase方法存在拼写错误:
jon应为join - Population类的selection方法将索引加入交配池,而非个体本身,导致后续调用crossover方法时触发类型错误
- Population类的select_best方法引用不存在的
fit属性,且未返回最优个体的文本 - 主循环中调用不存在的
pop.get_phrase()方法,无法判断收敛状态
修正后的完整代码
import random target_text = 'Andromeda' population_size = 501 mutation_rate = 0.02 class DNA: def __init__(self, length): # 改为实例属性,每个个体有独立基因列表 self.genes = [] self.fitness_val = 0 for _ in range(length): # 生成可打印ASCII字符(32-126),避免不可见字符 self.genes.append(chr(random.randint(32, 126))) def calculate_fitness(self, target): score = 0 for gene, target_gene in zip(self.genes, target): if gene == target_gene: score += 1 self.fitness_val = score / len(target) def crossover(self, parent): child_length = len(self.genes) child = DNA(child_length) midpoint = random.randint(0, child_length - 1) # 操作child的genes属性,而非直接切片实例 child.genes[:midpoint] = self.genes[:midpoint] child.genes[midpoint:] = parent.genes[midpoint:] return child def mutate(self, mutation_rate): for i in range(len(self.genes)): if random.random() < mutation_rate: self.genes[i] = chr(random.randint(32, 126)) def get_phrase(self): return ''.join(self.genes) class Population: def __init__(self, target, population_size, mutation_rate): self.target = target self.mutation_rate = mutation_rate self.population_size = population_size self.population = [] self.mating_pool = [] for _ in range(population_size): self.population.append(DNA(len(target))) self.calculate_all_fitness() def calculate_all_fitness(self): for individual in self.population: individual.calculate_fitness(self.target) def selection(self): self.mating_pool.clear() for individual in self.population: # 根据适应度值,将个体多次加入交配池(权重越高,出现次数越多) count = int(individual.fitness_val * 100) self.mating_pool.extend([individual] * count) # 处理交配池为空的情况(所有个体适应度为0) if not self.mating_pool: self.mating_pool = self.population.copy() def generate_next_generation(self): new_population = [] for _ in range(self.population_size): # 从交配池随机选择两个父代 parent1, parent2 = random.choices(self.mating_pool, k=2) child = parent1.crossover(parent2) child.mutate(self.mutation_rate) new_population.append(child) self.population = new_population def get_best_individual(self): best_individual = self.population[0] for individual in self.population: if individual.fitness_val > best_individual.fitness_val: best_individual = individual return best_individual # 主程序 pop = Population(target_text, population_size, mutation_rate) generation_count = 0 while True: pop.selection() pop.generate_next_generation() pop.calculate_all_fitness() best = pop.get_best_individual() best_phrase = best.get_phrase() generation_count += 1 # 打印每10代的进度 if generation_count % 10 == 0: print(f"第 {generation_count} 代 | 最优结果: {best_phrase} | 适应度: {best.fitness_val:.2f}") # 判断是否收敛到目标文本 if best_phrase == target_text: print(f"\n收敛完成!共耗时 {generation_count} 代") print(f"最终结果: {best_phrase}") break
关键修正说明
- 属性作用域修正:将DNA类的
genes和fitness_val改为实例属性,确保每个个体有独立的基因数据 - 基因生成优化:限制ASCII字符范围为32-126(可打印字符),避免生成不可见乱码
- 交配池逻辑修正:将个体本身加入交配池,而非索引,确保后续能正常调用crossover方法
- 突变逻辑修正:仅当随机概率小于突变率时才修改基因,符合遗传算法的突变规则
- 收敛判断修正:通过获取最优个体的文本来判断是否达到目标,修复原代码中方法不存在的问题
- 添加进度打印:每10代打印一次当前最优结果,方便观察算法收敛过程
内容的提问来源于stack exchange,提问作者Sai Nikhil
相关产品推荐
相关产品推荐

