2015-06-23 5 views
0

Функция evolve имеет проблемы, как и мутанта.Генетический алгоритм Python

from random import randint, random 
    from operator import add 
    from functools import reduce 



    def individual(length, min, max): 
     'Create a member of the population.' 
     return [randint(min,max) for x in range(length)] 


    def population(count, length, min, max): 
     'Create a number of individuals (i.e. a population).' 
     return [ individual(length, min, max) for x in range(count) ] 


    def fitness(individual, target): 
     'Determine the fitness of an individual. Lower is better.' 
     sum = reduce(add, individual, 0) 
     return abs(target-sum) 


    def grade(pop, target): 
     'Find average fitness for a population.' 
     summed = reduce(add, (fitness(x, target) for x in pop), 0) 
     return summed/(len(pop) * 1.0) 


    chance_to_mutate = 0.01 
    for i in p: 
     if chance_to_mutate > random(): 
      place_to_modify = randint(0,len(i)) 
      i[place_to_modify] = randint(min(i), max(i)) 


    def evolve(pop, target, retain=0.2, random_select=0.05, mutate=0.01): 
     graded = [(fitness(x, target), x) for x in pop] 
     graded = [x[1] for x in sorted(graded)] 
     retain_length = int(len(graded)*retain) 
     parents = graded[:retain_length] 

     # randomly add other individuals to promote genetic diversity 
     for individual in graded[retain_length:]: 
      if random_select > random(): 
       parents.append(individual) 

     # mutate some individuals 
     for individual in parents: 
      if mutate > random(): 
       pos_to_mutate = randint(0, len(individual)-1) 
       # this mutation is not ideal, because it 
       # restricts the range of possible values, 
       # but the function is unaware of the min/max 
       # values used to create the individuals, 
       individual[pos_to_mutate] = randint(
        min(individual), max(individual)) 

     # crossover parents to create children 
     parents_length = len(parents) 
     desired_length = len(pop) - parents_length 
     children = [] 
     while len(children) < desired_length: 
      male = randint(0, parents_length-1) 
      female = randint(0, parents_length-1) 
      if male != female: 
       male = parents[male] 
       female = parents[female] 
       half = len(male)/2 
       child = male[:half] + female[half:] 
       children.append(child) 

     parents.extend(children) 
     return parents 

    target = 371 
    p_count = 100 
    i_length = 5 
    i_min = 0 
    i_max = 100 
    p = population(p_count, i_length, i_min, i_max) 
    fitness_history = [grade(p, target),] 
    for i in range(100): 
     p = evolve(p, target) 
     fitness_history.append(grade(p, target)) 

    for datum in fitness_history: 
     print(datum) 

Я следую за этим сайтом http://lethain.com/genetic-algorithms-cool-name-damn-simple/. Он был написан для Python 2.6, поэтому он не работает для 3. Я обновил его в основном, но не могу заставить его работать.

+0

Вы подвергаетесь близко проголосовали; см. http://stackoverflow.com/help/how-to-ask и добавьте достаточно подробностей на свой вопрос, чтобы люди могли помочь, например, что не работает об этом - что он должен делать, по сравнению с тем, что он на самом деле делает , и как мы можем проверить это. – TessellatingHeckler

+0

Нет функции 'mutate'. –

+0

Возможно, вы захотите сохранить некоторую набранную @TessellatingHeckler, если в следующий раз вы наберете '[ask]' вместо 'stackoverflow.com/help/how-to-ask'. – boardrider

ответ

1

Ошибки, которые вызвал код, должны были быть достаточно информативными. Нарезка сделана:

male[:half] + female[half:] 

Использует половину, которая была плавающей в то время. Основное различие заключалось в следующем:

half = int(len(male)/2) 

Это, скорее всего, предполагаемая функциональность. Вы не можете использовать float для индексации массива, только ints.

Вот что должно быть:

from random import randint, random 
from functools import reduce 
from operator import add 
def individual(length, min, max): 
    'Create a member of the population.' 
    return [randint(min,max) for x in range(length)] 


def population(count, length, min, max): 
    'Create a number of individuals (i.e. a population).' 
    return [ individual(length, min, max) for x in range(count) ] 


def fitness(individual, target): 
    'Determine the fitness of an individual. Lower is better.' 
    sum = reduce(add, individual, 0) 
    return abs(target-sum) 


def grade(pop, target): 
    'Find average fitness for a population.' 
    summed = reduce(add, (fitness(x, target) for x in pop), 0) 
    return summed/(len(pop) * 1.0) 


def evolve(pop, target, retain=0.2, random_select=0.05, mutate=0.01): 
    graded = [(fitness(x, target), x) for x in pop] 
    graded = [x[1] for x in sorted(graded)] 
    retain_length = int(len(graded)*retain) 
    parents = graded[:retain_length] 

# randomly add other individuals to promote genetic diversity 
for individual in graded[retain_length:]: 
    if random_select > random(): 
     parents.append(individual) 

# mutate some individuals 
for individual in parents: 
    if mutate > random(): 
     pos_to_mutate = randint(0, len(individual)-1) 
     # this mutation is not ideal, because it 
     # restricts the range of possible values, 
     # but the function is unaware of the min/max 
     # values used to create the individuals, 
     individual[pos_to_mutate] = randint(
      min(individual), max(individual)) 

# crossover parents to create children 
parents_length = len(parents) 
desired_length = len(pop) - parents_length 
children = [] 
while len(children) < desired_length: 
    male = randint(0, parents_length-1) 
    female = randint(0, parents_length-1) 
    if male != female: 
     male = parents[male] 
     female = parents[female] 
     half = int(len(male)/2) 
     child = male[:half] + female[half:] 
     children.append(child) 

parents.extend(children) 
return parents 

target = 371 
p_count = 100 
i_length = 5 
i_min = 0 
i_max = 100 
p = population(p_count, i_length, i_min, i_max) 
fitness_history = [grade(p, target),] 
chance_to_mutate = 0.01 
for i in p: 
    if chance_to_mutate > random(): 
     place_to_modify = randint(0,len(i)) 
     i[place_to_modify] = randint(min(i), max(i)) 
for i in range(100): 
    p = evolve(p, target) 
    fitness_history.append(grade(p, target)) 

for datum in fitness_history: 
    print(datum) 
Смежные вопросы