Генетичен алгоритъм на Python за двоично число

От мен се иска да направя генетичен алгоритъм с цел да определя 8-битов низ с най-много 1 и 0. Функцията 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