GA遗传算法求函数极值

课程要求函数如下:

sqrt为开根号运算,x(j)的取值范围为[-500,500],初始群体大小为100。

适应度函数的大小就是函数值大小,仅仅做了归一化。 

以后可能还会用到,代码做个保存,具体实现如下:交叉,畸变,选择概率可以根据具体情况修改

import matplotlib.pyplot as plt
import numpy as np
import random
import math

# 定义遗传算法参数
pop_size = 100  # 种群大小
generation = 10  # 最大遗传代数
length = 30  # 个体长度
pc = 0.65  # 交叉概率
# 变异产生新的个体,选择导致个体消亡,可以通过调节变异概率和选择概率保证种群完好
pm = 0.1  # 变异概率

# 每个个体随机编码
def genEncoding(pop_size, length):
    pop = [[]]
    for i in range(pop_size):
        temp = []
        for j in range(length):
            temp.append(random.randint(0, 1))
        pop.append(temp)
    return pop[1:]  # ??
# 解码
def genDecoding(pop, length):
    temp = []
    for i in range(len(pop)):
        t = 0
        for j in range(length):
            t += pop[i][j]*math.pow(2, j)
        temp.append(t)
    return temp
# 计算目标值  x介于lb和ub之间
def calValue(pop, length, lb, ub):
    obj_value = []
    x_value = []
    # 获取解码后个体
    temp1 = genDecoding(pop, length)
    for i in range(len(temp1)):
        x = lb + (ub-lb)*temp1[i]/((math.pow(2, length)) - 1)  # 计算x函数值
        x_value.append(x)
        obj_value.append(np.sin(np.sqrt(x))*x)  # 计算y函数值
    return obj_value
# 计算适应度  适应度就是对应的函数值
def fitness(pop, length, lb, ub):
    obj_value = calValue(pop, length, lb, ub)
    fit_value = []
    for i in range(len(obj_value)):
        fit_value.append(obj_value[i])

    # fitness_value = list(map(abs, fitness_value))
    fit_value = list(map(lambda x: -x+max(fit_value), fit_value))

    return fit_value
# 选择函数 根据适应度值进行选择
def selection(pop, fitness_value):
    newfitness_value = []
    accumulation_value = []
    # total_fit = np.sum(fitness_value)
    fit_min = np.min(fitness_value)
    fit_max = np.max(fitness_value)
    for i in range(len(fitness_value)):
        newfitness_value.append(fitness_value[i]-fit_min/(fit_max - fit_min))  # 计算适应度的相对值
    accumulation_value = newfitness_value
    ms = []
    for i in range(len(pop)):
        ms.append(random.random())
    newpop = []
    for j in range(len(accumulation_value)):
        if 0.01 < accumulation_value[j]:
            if j >= len(pop):
                print(j, len(pop))
            t = pop[j]
            newpop.append(t)
    # # 人口膨胀
    # if len(accumulation_value)>1000:

    return newpop
# 交叉函数
def crossover(pop, fitness_value, pc):
    new_pop = selection(pop, fitness_value)
    m = len(new_pop)
    # n = len(new_pop[0])/2  # 一半的基因交叉重组
    for i in range(m-1):
        # rm = random.randint(0, m-1)
        if random.random() < pc:
			# 父代可以不保存
            # new1 = new_pop[i].copy()
            # new2 = new_pop[rm].copy()
            for j in range(10):
                k = random.randint(0, length-1)
                temp1 = new_pop[i][k]
                temp2 = new_pop[i+1][k]
                new_pop[i+1][k] = temp1
                new_pop[i][k] = temp2
            # new_pop.append(new1)
    return new_pop
# 变异函数
def mutation(pop, fitness_value, pc, pm, length):
    newpop = crossover(pop, fitness_value, pc)
    for i in range(len(newpop)):
        new = []
        if random.random() < pm:
            new = newpop[i].copy()
            m1 = random.randint(0, length-1)
            m2 = random.randint(0, length - 1)
            m3 = random.randint(0, length - 1)
            if new[m1] == 1:
                new[m1] = 0
            else:
                new[m1] = 1
            if new[m2] == 1:
                new[m2] = 0
            else:
                new[m2] = 1
            if new[m3] == 1:
                new[m3] = 0
            else:
                new[m3] = 1
            newpop.append(new)
    return newpop
if __name__ == "__main__":
    # 画出函数图
    plt.figure(1)
    lb = 0
    ub = 500
    x = np.arange(lb, ub, 0.01)
    y = np.sin(np.sqrt(x))*x
    plt.plot(x, y)
    plt.xlabel("自变量X"); plt.ylabel("应变量Y"); plt.title("sin(sqrt(x)*x")
    # 初始化群体
    pop = genEncoding(pop_size, length)
    obj_value = calValue(pop, length, lb, ub)
    gen = 0
    x_value = []
    best_x = []
    best_individual = []
    Generation = []
    Mmax = 0
    while gen < generation:
        # 计算函数值
        fit_value = fitness(pop, length, lb, ub)
        # 交叉变异
        newpop = mutation(pop, fit_value, pc, pm, length)
        temp = genDecoding(newpop, length)
        for i in range(len(temp)):
            x = lb+(ub-lb)*temp[i]/((math.pow(2, length))-1)
            x_value.append(x)
        obj_value = calValue(newpop, length, lb, ub)
        k = 0
        j = 0
        for i in range(len(obj_value)):
            if k < obj_value[i]:
                k = obj_value[i]
                j = i
        best_individual.append(k)  # 最佳个体
        if obj_value[j] > Mmax:
            Mmax = obj_value[j]
        best_x.append(x_value[j])
        fitness_value = fitness(newpop, length, lb, ub)
        Generation.append(gen)
        gen = gen+1
        pop = newpop
    k = 0
    j = 0
    for i in range(len(best_individual)):
        if k > best_individual[i]:
            k = best_individual[i]
            j = i
    print(max(best_individual))
    print(-Mmax*30)
    best_individual.sort(reverse=True)
    plt.figure(2)
    plt.plot(Generation, best_individual)
    plt.xlabel("遗传代数")
    plt.ylabel("解的变化")
    plt.title("进化过程")
    plt.show()

实验结果如下:

最佳个体最大函数值max(best_individual):418.98264752959625

原函数最小值-max(best_individual)*30:-12569.479425887888

猜你喜欢

转载自blog.csdn.net/qq_40801709/article/details/91465161