因此,我正在制定遗传算法,其中最适染色体是全部[1,1,1,1 ...]。在调试时,我在下面编写了整个代码,发现交叉,变异,generate_population有效,并且我遍历了其他函数的代码,它们都很有意义。但是,每当我运行它时,我都会发现在第二代或第三代之后,我的其他所有代都是相同的。所以我的问题是,为什么会这样,因为我检查了代码,每个新一代都应该有一个不同的“适合”的人群,并且每个人群之间应该有差异。任何帮助将非常感激。 result image
import random
def generate_population(size):
population = []
for i in range(size):
individual = []
for g in range(64):
x = random.randrange(0,2)
individual.append(x)
population.append(individual)
return population
def fitnessFunc(individual):
fit = 0
for i in individual:
if i == 1:
fit += 1
else:
fit = fit
return fit
def choice_by_roulette(sorted_population, fitness_sum):
offset = 0
normalized_fitness_sum = fitness_sum
lowest_fitness = fitnessFunc(sorted_population[0])
if lowest_fitness < 0:
offset = lowest_fitness
normalized_fitness_sum += offset * len(sorted_population)
draw = random.uniform(0, 1)
accumulated = 0
for individual in sorted_population:
fitness = fitnessFunc(individual)+offset
probability = fitness / normalized_fitness_sum
accumulated += probability
if draw <= accumulated:
return individual
def sort_population_by_fitness(population):
return sorted(population, key=fitnessFunc)
def crossover(individual_a, individual_b):
for i in range(64):
pop = random.randint(1,2)
if pop == 1:
individual_a[i] = individual_b[i]
else:
individual_a = individual_a
return individual_a
def mutate(individual):
rand = random.randrange(0,10)
if rand == 5:
if individual[rand]==1:
individual[rand]=0
else:
individual[rand]=1
return individual
def make_next_generation(previous_population):
next_generation = []
sorted_by_fitness_population = sort_population_by_fitness(previous_population)
population_size = len(previous_population)
fitness_sum = sum(fitnessFunc(individual) for individual in population)
for i in range(population_size):
choice = choice_by_roulette(sorted_by_fitness_population, fitness_sum)
schoice = choice_by_roulette(sorted_by_fitness_population, fitness_sum)
if choice != None:
first_choice = choice
if schoice != None:
second_choice = schoice
individual = crossover(first_choice, second_choice)
individual = mutate(individual)
next_generation.append(individual)
return next_generation
population = generate_population(size=10)
generations = 1000
i = 1
while True:
print(f" GENERATION {i}")
for individual in population:
print(individual, fitnessFunc(individual))
if i == generations:
break
i += 1
population = make_next_generation(population)
best_individual = sort_population_by_fitness(population)[-1]
print(" FINAL RESULT")
print(best_individual, fitnessFunc(best_individual))
我发现了三个主要问题。会尝试将其分解,但是由于我不确定要达到的预期结果,因此很难确定应如何完成。
问题1:交叉功能在创建下一代时,将父代“原地”突变。这意味着约有25%的一个亲本基因会向其他亲本基因集突变。
问题2:make_next_generation()无法确保将两个不同的人发送到分频器。有时,这将导致个人保持不变地移交给下一代。
问题3:mutate(单个)仅影响64个基因中的一个。(猜测不是故意的)
import random
def generate_individual():
# Use list comprehensions
return [random.randrange(0,2) for g in range(64)]
def generate_population(size):
# Same result, only less code
return [generate_individual() for i in range(size)]
def fitnessFunc(individual):
# Yes, this line does the same work.
return sum(individual)
# fit = 0
# for i in individual:
# if i == 1:
# fit += 1
# The following two lines did nothing
# else:
# fit = fit
# return fit
choice_by_roulette()中确实存在问题。但是,不知道它应该如何工作。在下面评论。
def choice_by_roulette(sorted_population, fitness_sum):
offset = 0
normalized_fitness_sum = fitness_sum
lowest_fitness = fitnessFunc(sorted_population[0])
# Lower than 0? fitnessFunc() will never return that.
# Could it be lowest_fitness > 0?
if lowest_fitness < 0:
offset = lowest_fitness
normalized_fitness_sum += offset * len(sorted_population)
draw = random.random()
accumulated = 0
for individual in sorted_population:
fitness = fitnessFunc(individual)+offset
probability = fitness / normalized_fitness_sum
accumulated += probability
if draw <= accumulated:
return individual
def sort_population_by_fitness(population):
return sorted(population, key=fitnessFunc)
交叉不应该变异旧个体(?)。由于同一个人可能会被多次挑选,因此他们将向同一代中的另一个人变异〜50%。这可能是您最大的问题。
def crossover(individual_a, individual_b):
for i in range(64):
pop = random.randint(1,2)
if pop == 1:
individual_a[i] = individual_b[i]
else:
individual_a = individual_a
return individual_a
我的建议:
def crossover(individual_a, individual_b):
return [random.choice(genes) for genes in zip(individual_a, individual_b)]
这里您不需要退货。您实际上是在变异个人。另外,只有基因5可以突变,但这也许应该是吗?
def mutate(individual):
rand = random.randrange(0,10)
if rand == 5:
individual[rand] = 1 - individual[rand] # Toggle: 1-0=1, 1-1=0
# if individual[rand]==1:
# individual[rand]=0
# else:
# individual[rand]=1
def make_next_generation(previous_population):
next_generation = []
sorted_by_fitness_population = sort_population_by_fitness(previous_population)
population_size = len(previous_population)
fitness_sum = sum(fitnessFunc(individual) for individual in population)
for i in range(population_size):
choice = choice_by_roulette(sorted_by_fitness_population, fitness_sum)
schoice = choice_by_roulette(sorted_by_fitness_population, fitness_sum)
# This code will not work. first_choice will be user without being declared below if any of there are None.
# if choice != None:
# first_choice = choice
# if schoice != None:
# second_choice = schoice
# choice and schoice will sometimes be the same individual. That will definitely diminish the genetic diversity.
while choice == schoice:
schoice = choice_by_roulette(sorted_by_fitness_population, fitness_sum)
individual = crossover(choice, schoice)
mutate(individual)
next_generation.append(individual)
return next_generation
population = generate_population(size=10)
generations = 1000
for i in range(1, generations+1):
print(f" GENERATION {i}")
for individual in population:
print(individual, fitnessFunc(individual))
population = make_next_generation(population)
best_individual = sort_population_by_fitness(population)[-1]
print(" FINAL RESULT")
print(best_individual, fitnessFunc(best_individual))