python實現遺傳算法求函數最大值(人工智能做業)

##題目: 用遺傳算法求函數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

相關文章
相關標籤/搜索