Генетический алгоритм Python для двоичного числа

Меня попросили создать генетический алгоритм с целью определить 8-битную строку с наибольшим количеством единиц и нулей. Функция eval должна возвращать количество изменений плюс 1. Так, например, 00000000 возвращает 1, 00011100 возвращает 3, а 01100101 возвращает 6. Вот что у меня есть:

def random_population():
    from random import choice

    pop = ''.join(choice(('0','1')) for _ in range(8))
    return pop   

def mutate(dna):   
    """   For each gene in the DNA, there is a 1/mutation_chance chance 
    that it will be   switched out with a random character. This ensures 
    diversity in the   population, and ensures that is difficult to get stuck in 
    local minima.   """   
    dna_out = ""   
    mutation_chance = 100   
    for c in xrange(DNA_SIZE):
        if int(random.random()*mutation_chance) == 1:
            dna_out += random_char()
        else:
            dna_out += dna[c]   return dna_out

def crossover(dna1, dna2):   
    """   Slices both dna1 and dna2 into two parts at a random index within their   
    length and merges them. Both keep their initial sublist up to the crossover   
    index, but their ends are swapped.   """   
    pos = int(random.random()*DNA_SIZE)
    return (dna1[:pos]+dna2[pos:], dna2[:pos]+dna1[pos:])

def eval(dna):
    changes = 0
    for index, bit in enumerate(dna):
        if(index == 0):
            prev = bit
        else:
            if(bit != prev):
                changes += 1
        prev = bit
    return changes+1


#============== End Functions =======================#


#============== Main ================# changes = 0

prev = 0
dna = random_population()
print "dna: "
print dna
print eval(dna)

У меня возникли проблемы с определением части генетического алгоритма (перекрест/мутация). Я должен случайным образом соединить числа, а затем случайным образом выбрать пару, оставив одну пару нетронутой, а затем пересечься в случайной точке. Затем это закончится случайной мутацией одного бита из всей популяции. Текущий код кроссовера и мутации был взят из примера генетического алгоритма, который я нашел и пытался понять. Любая помощь приветствуется.


person Nick    schedule 13.04.2013    source источник
comment
Популяция состоит из многих особей — я вижу только одну «ДНК». Кроссовер помогает с конвергенцией «подпрограмм» гена, а мутация помогает создать ошибку, необходимую для достижения цели.   -  person User    schedule 13.04.2013
comment
Кроме того, вам нужна функция пригодности, которая определяет, насколько возможно индивидуум браться за кроссовер и рекомбинацию. Вы можете использовать колесо рулетки en.wikipedia.org/wiki/Fitness_proportionate_selection, чтобы определить, кто пересекаются и создают детей, которые переходят в следующее поколение.   -  person User    schedule 13.04.2013


Ответы (2)


Часть того, что я бы предложил:

Код не работает, но, возможно, он передает информацию.

# a population consists of many individuals
def random_population(population_size = 10):
    from random import choice

    pop = [''.join(choice(('0','1')) for _ in range(8)) for i in range(population_size)]
    return pop   

# you need a fitness function
def fitness(individual):
    return # a value from 0 up

def algorithm():
    # a simple algorithm somehow alike
    # create population
    population = random_population()
    # this loop must stop after some rounds because the best result may never be reached
    while goal_not_reached(population) and not time_is_up():
        # create the roulette wheel
        roulette_wheel = map(fitness, population)
        # highest value of roulette wheel
        max_value = sum(roulette_wheel)
        # the new generation
        new_population = []
        for i in range(len(population) - len(new_population)):
             # create children from the population
                 # choose 2 random values from 0 to max_value and find the individuals
                 # for it in the roulette wheel, combine them to new individuals 
             new_population.append(new_individual)
        # mutate the population
        population = map(mutate, new_population)             # a new generation is created
person User    schedule 13.04.2013

Я обнаружил, что мне нравится делать следующее:

  1. Выберите лучших кандидатов из вашей последней партии, скажем, 5.
  2. Имейте 1 помощника с 2, 3, 4, 5.
  3. Имейте 2 помощника с 3, 4, 5
  4. Имейте 3 помощника с 4 и 5
  5. Имейте 4 пары с 5. Как правило, ваша популяция уже будет полной, прежде чем вы достигнете этой точки, если вы позволите первоначальным 5 в следующем поколении, и каждое спаривание приводит к 2 потомкам. Одно спаривание и его противоположный близнец.
  6. Что касается фактического скрещивания, я предпочитаю случайным образом обрезать хромосомы в точке между 40% и 60% длины, а затем при следующем скрещивании я выбираю другую случайную точку в диапазоне.
  7. После того, как я скрестил их, я просматриваю каждый бит в своей хромосоме и даю ему примерно !5% шанс перевернуться или мутировать.
  8. Иногда я также позволяю некоторым из худших двух матов, чтобы снизить мои шансы на локальные максимумы или минимумы.

Я надеюсь, что это было немного полезно для вас.

-Джефф

РЕДАКТИРОВАТЬ: О, мой вопрос был задан в апреле. Извините за копание могилы.

person Jeff H.    schedule 13.07.2013