2013-01-14 43 views
1

我想運行我在python中編寫的遺傳算法。不幸的是,當發生突變時,儘管使用精英主義將最優秀的解決方案從上一代傳遞到新一代,但最適合的解決方案可能會更糟,以至於上一代最適合的解決方案。像這樣:Elitism在遺傳算法中失敗

There are 86825 generations left 
Invalid count is: 0 
The fittest individual has a fitness of 16.9094. 
The least fit individual has a fitness of 36.6535 
******************************************************************************* 
mutation on 107 
There are 86824 generations left 
Invalid count is: 3 
The fittest individual has a fitness of 19.8637. 
The least fit individual has a fitness of 1.1618e+09 

我試圖實施精英主義,我認爲會避免這種情況發生,但它仍然發生。我的算法執行這個命令:

NUM_GEN = 100000 
print "Running Genetic Algorithm for %d generations." % NUM_GEN 
gen_count = 0 
while gen_count < NUM_GEN: 
    #genetic.add_fitness_key() 
    genetic.add_fitness_fast() 
    fittest_list = np.append(fittest_list, genetic.fittest_fitness) 
    least_fit_list = np.append(least_fit_list, genetic.least_fitness) 
    genetic.sort_pop() 
    genetic.make_new_pop() 
    genetic.elitism() 
    genetic.population = genetic.new_pop 
    print "There are %g generations left" %(NUM_GEN-gen_count) 
    gen_count+=1 

與呼叫功能是這些:

def select_parent_from_tournament(self): 
    x = random.randint(0, 19) 
    player1 = self.population[x] 
    y = random.randint(0, 19) 
    player2 = self.population[y] 
    if player1['fitness'] <= player2['fitness']: 
     parent = player1['chrom_list'] 
    else: 
     parent = player2['chrom_list'] 
    return parent 

def crossover(self): 
    crossover_point = random.randint(0, self.chromosome_size)*(self.string_length) 
    parent1 = self.select_parent_from_tournament() 
    parent2 = self.select_parent_from_tournament() 
    parent1 = self.mutate(parent1) 
    parent2 = self.mutate(parent2) 
    child1 = parent1[:crossover_point] + parent2[crossover_point:] 
    child2 = parent1[crossover_point:] + parent2[:crossover_point] 
    return child1, child2 

def mutate(self, chromosome): 
    for i in range(len(chromosome)): 
     if random.random() < self.mutation_rate: 
      print 'mutation on %i' % i 
      if chromosome[i] =='0': 
       chromosome[i] = '1' 
      else: 
       chromosome[i] = '0' 
    return chromosome 

def make_new_pop(self): 
    self.new_pop = [] 
    for i in range(10): 
     dictionary1= {} 
     dictionary2 = {} 
     dictionary1['chrom_list'], dictionary2['chrom_list'] = \ 
     self.crossover() 
     self.new_pop = np.append(self.new_pop, [dictionary1, dictionary2]) 

def elitism(self): 
    r = random.randint(0, 19) 
    self.new_pop[r] = self.population[0] 

所以我不明白爲什麼從老年人口優勝劣汰的解決方案是不傳遞到新的人口是否存在突變?

+0

你有沒有做過任何調試? –

+2

交叉/變異後,你的適合個體可能會被毀壞。 –

+0

@equinoxel @frb如果我在我的while循環的'genetic.elitism()'之前或之後輸出genetic.population',它將首先打印出最適合的解決方案。另外,如果我在self.new_pop [r] = self.population [0]之前在elitism函數中打印'self.population [0]',它會打印最適合的解決方案。 – nicholaschris

回答

3

在您的交叉方法中,您執行parent1 = self.select_parent_from_tournament(),它將引用返回到原始羣體中染色體列表。之後,你做一個修改列表的變化(在原始人羣中)。只有在突變後,您才能通過child1 = parent1[:crossover_point] + parent2[crossover_point:]複製兒童內容。正如@ Xavier所建議的那樣,您需要從mutation()的原始人羣中創建元素的物理副本。

實際上,您的mutation()方法更改了原始人口。

作爲一個方面說明,通常交叉和變異是兩個不同的操作。此外,文獻中還有參考文獻提示突變概率應該保持非常低。否則它會阻止你融合。

+1

謝謝!我在'def mutate(self,chromosome)'正下方添加了'chromosome = list(chromosome)'。有用。我顯然需要了解更多關於python引用對象的知識! – nicholaschris

+0

@nicholaschris不用擔心:)幾年前我有同樣的問題。 –