##題目: 用遺傳算法求函數f(a,b)=2a x sin(8PI x b) + b x cos(13PI x a)最大值,a:[-3,7],b:[-4:10] ##實現步驟:python
- 初始化種羣
- 計算種羣中每一個個體的適應值
- 淘汰部分個體(這裏是求最大值,f值存在正值,因此淘汰全部負值)
- 輪盤算法對種羣進行選擇
- 進行交配、變異,交叉點、變異點隨機
##分析: 爲了方便,先將自變量範圍調整爲[0,10]、[0,14] 有兩個變量,種羣中每一個個體用一個列表表示,兩個列表項,每項是一個二進制字符串(分別由a、b轉化而來) 種羣之間交配時須要肯定交叉點,先將個體染色體中的兩個二進制字符串拼接,再肯定一個隨機數做爲交叉點 爲了程序的數據每一步都比較清晰正確,我在select、crossover、mutation以後分別都進行了一次適應值的從新計算 ##具體代碼:算法
import math import random def sum(list): total = 0.0 for line in list: total += line return total def rand(a, b): number = random.uniform(a,b) return math.floor(number*100)/100 PI = math.pi def fitness(x1,x2): return 2*(x1-3)*math.sin(8*PI*x2)+(x2-4)*math.cos(13*PI*x1) def todecimal(str): parta = str[0:4] partb = str[4:] numerical = int(parta,2) partb = partb[::-1] for i in range(len(partb)): numerical += int(partb[i])*math.pow(0.5,(i+1)) return numerical def tobinarystring(numerical): numa = math.floor(numerical) numb = numerical - numa bina = bin(numa) bina = bina[2:] result = "0"*(4-len(bina)) result += bina for i in range(7): numb *= 2 result += str(math.floor(numb)) numb = numb - math.floor(numb) return result class Population: def __init__(self): self.pop_size = 500 # 設定種羣個體數爲500 self.population = [[]] # 種羣個體的二進制字符串集合,每一個個體的字符串由一個列表組成[x1,x2] self.individual_fitness = [] # 種羣個體的適應度集合 self.chrom_length = 22 # 一個染色體22位 self.results = [[]] # 記錄每一代最優個體,是一個三元組(value,x1_str,x2_str) self.pc = 0.6 # 交配機率 self.pm = 0.01 # 變異機率 self.distribution = [] # 用於種羣選擇時的輪盤 def initial(self): for i in range(self.pop_size): x1 = rand(0,10) x2 = rand(0,14) x1_str = tobinarystring(x1) x2_str = tobinarystring(x2) self.population.append([x1_str,x2_str]) # 添加一個個體 fitness_value = fitness(x1,x2) self.individual_fitness.append(fitness_value) # 記錄該個體的適應度 self.population = self.population[1:] self.results = self.results[1:] def eliminate(self): for i in range(self.pop_size): if self.individual_fitness[i]<0: self.individual_fitness[i] = 0.0 def getbest(self): "取得當前種羣中的一個最有個體加入results集合" index = self.individual_fitness.index(max(self.individual_fitness)) x1_str = self.population[index][0] x2_str = self.population[index][1] value = self.individual_fitness[index] self.results.append((value,x1_str,x2_str,)) def select(self): "輪盤算法,用隨機數作個體選擇,選擇以後會更新individual_fitness對應的數值" "第一步先要初始化輪盤" "選出新種羣以後更新individual_fitness" total = sum(self.individual_fitness) begin = 0 for i in range(self.pop_size): temp = self.individual_fitness[i]/total+begin self.distribution.append(temp) begin = temp new_population = [] new_individual_fitness = [] for i in range(self.pop_size): num = random.random() # 生成一個0~1之間的浮點數 j = 0 for j in range(self.pop_size): if self.distribution[j]<num: continue else: break index = j if j!=0 else (self.pop_size-1) new_population.append(self.population[index]) new_individual_fitness.append(self.individual_fitness[index]) self.population = new_population self.individual_fitness = new_individual_fitness def crossover(self): "選擇好新種羣以後要進行交配" "注意這只是一次種羣交配,種羣每一次交配過程,會讓每兩個相鄰的染色體進行信息交配" for i in range(self.pop_size-1): if random.random()<self.pc: cross_position = random.randint(1,self.chrom_length-1) i_x1x2_str = self.population[i][0]+self.population[i][1] # 拼接起第i個染色體的兩個二進制字符串 i1_x1x2_str = self.population[i+1][0]+self.population[i+1][1] # 拼接起第i+1個染色體的兩個二進制字符串 str1_part1 = i_x1x2_str[:cross_position] str1_part2 = i_x1x2_str[cross_position:] str2_part1 = i1_x1x2_str[:cross_position] str2_part2 = i1_x1x2_str[cross_position:] str1 = str1_part1+str2_part2 str2 = str2_part1+str1_part2 self.population[i] = [str1[:11],str1[11:]] self.population[i+1] = [str2[:11],str2[11:]] "而後更新individual_fitness" for i in range(self.pop_size): x1_str = self.population[i][0] x2_str = self.population[i][1] x1 = todecimal(x1_str) x2 = todecimal(x2_str) self.individual_fitness[i] = fitness(x1,x2) def mutation(self): "個體基因變異" for i in range(self.pop_size): if random.random()<self.pm: x1x2_str = self.population[i][0]+self.population[i][1] pos = random.randint(0,self.chrom_length-1) bit = "1" if x1x2_str[pos]=="0" else "0" x1x2_str = x1x2_str[:pos]+bit+x1x2_str[pos+1:] self.population[i][0] = x1x2_str[:11] self.population[i][1] = x1x2_str[11:] "而後更新individual_fitness" for i in range(self.pop_size): x1_str = self.population[i][0] x2_str = self.population[i][1] x1 = todecimal(x1_str) x2 = todecimal(x2_str) self.individual_fitness[i] = fitness(x1, x2) def solving(self,times): "進行times次數的整個種羣交配變異" "先得到初代的最優個體" self.getbest() for i in range(times): "每一代的染色體個體和適應值,須要先淘汰,而後選擇,再交配、變異,最後獲取最優個體。而後進入下一代" self.eliminate() self.select() self.crossover() self.mutation() self.getbest() def returnbest(self): self.results.sort() return self.results[len(self.results)-1] if __name__ == '__main__': demo = Population() demo.initial() demo.solving(100) answer = demo.returnbest() value = answer[0] x1 = todecimal(answer[1]) x2 = todecimal(answer[2]) print(x1,x2,value)
參考文章app