2016-11-07 8 views
0

Я заинтересован в применении генетического алгоритма с использованием DEAP в Python. Пример реализации для knapasack can be seen here. Я пытаюсь создать свою собственную функцию кроссовера, и я хочу, чтобы сохранить длину родителей следующим образом:Как сохранить переменную длину

# Crossover 
def crossover(ind1, ind2): 
    print len(ind1), len(ind2) #<------ length at the beginning 
    temp1 = copy.deepcopy(set(ind1)) 
    temp2 = copy.deepcopy(set(ind2)) 
    uniform = list(temp1.union(temp2)) 
    while len(ind1) > 0: 
     ind1.pop() 
    while len(ind2) > 0: 
     ind2.pop() 
    for i in range(max_no): 
     ind1.add(random.choice(uniform)) 
     ind2.add(random.choice(uniform)) 
    print len(ind1), len(ind2) #<---- length at the end 
    return ind1, ind2 

Однако длины ind1 и IN2 в начале функции отличаются от длин ind1 и ind2 в конце. Длина как ind1, так и ind2 в начале должна быть равна max_no. Я надеялся, что кто-то подскажет мне, почему это так. Я довольно тупой.

Спасибо, и любая помощь будет очень признательна.

Редактировать: Вот моя функция мутации. Я также пытаюсь сохранить переменную длину индивидуального здесь, как вы можете увидеть

def mutation(individual): 
    if len(individual) > 0: 
     individual.remove(random.choice(list(individual))) 
     individual.add(random.choice(nodes)) 
    return individual, 
+0

Какой тип индивидуума? похоже, что это 'set'? '.add' будет no-op, если операнд уже существует. –

+0

Да, отдельные функции как набор. Что вы подразумеваете под no-op? – meraxes

ответ

1

Ваш код в основном эквивалентно следующему:

import random 

ind1 = set(range(100)) 
ind2 = set(range(100)[::-1]) 
uniform = list(ind1.union(ind2)) 
max_no = 100 
while len(ind1) > 0: 
     ind1.pop() 
while len(ind2) > 0: 
    ind2.pop() 
for i in range(max_no): 
    ind1.add(random.choice(uniform)) 
    ind2.add(random.choice(uniform)) 

Результат
>>> print(len(ind1),len(ind2)) 
(64, 61) 

Потому что ваши физические лица наборы, когда вы добавляете случайные числа, каждый так часто бывает, что вы добавляете что-то дважды. Тогда длина результирующих множеств будет отличаться при каждом прогоне, потому что ничего не добавляется, если оно уже находится в индивидууме.

Чтобы решить проблему, вы можете использовать вместо random.sample:

import random 

ind1 = set(range(100)) 
ind2 = set(range(-100,0,-1)[::-1]) 
uniform = list(ind1.union(ind2)) 
max_no = 100 
while len(ind1) > 0: 
    ind1.pop() 
while len(ind2) > 0: 
    ind2.pop() 
for x in random.sample(uniform,max_no): 
    ind1.add(x) 
for x in random.sample(uniform,max_no): 
    ind2.add(x) 

Результат

>>> print(len(ind1),len(ind2)) 
(100, 100) 

Сказав, что, set особи оказались чрезвычайно болезненным для меня. sequence человек на сегодняшний день лучший поддерживаемый. Из documentation это очевидно, что dict и set как частный случай dict является not considered sequence types:

последовательность

итератора, который поддерживает эффективный доступ элемента, используя целое число индексов через GetItem() специальный метод и образует a len() метод, который возвращает длину последовательности. Некоторые встроенные последовательности - это список, str, кортеж и байты. Обратите внимание, что dict также поддерживает getitem() и len(), но считается сопоставлением, а не последовательностью, потому что поисковые запросы используют произвольные неизменяемые ключи, а не целые числа .

+0

Спасибо, это прекрасно! – meraxes