python实现遗传算法求函数最大值(人工智能作业)

题目:

用遗传算法求函数f(a,b)=2a x sin(8PI x b) + b x cos(13PI x a)最大值,a:[-3,7],b:[-4:10]

实现步骤:

  • 初始化种群
  • 计算种群中每个个体的适应值
  • 淘汰部分个体(这里是求最大值,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)

参考文章

posted @ 2018-05-13 17:47  chlewn  阅读(11142)  评论(2编辑  收藏  举报