遗传算法(Python)

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

# 设定参数
DNA_SIZE = 24  # DNA的长度
POP_SIZE = 200  # 种群大小
CROSSOVER_RATE = 0.8  # 交叉概率
MUTATION_RATE = 0.005  # 变异概率
N_GENERATIONS = 50  # 进化次数
X_BOUND = [-3, 3]  # x的取值范围
Y_BOUND = [-3, 3]  # y的取值范围

# 目标函数
def F(x, y):
    return 3*(1-x)**2*np.exp(-(x**2)-(y+1)**2)- 10*(x/5 - x**3 - y**5)*np.exp(-x**2-y**2)- 1/3**np.exp(-(x+1)**2 - y**2)

# 画出目标函数的3D图像
def plot_3d(ax):
    X = np.linspace(*X_BOUND, 100)
    Y = np.linspace(*Y_BOUND, 100)
    X,Y = np.meshgrid(X, Y)
    Z = F(X, Y)
    ax.plot_surface(X,Y,Z,rstride=1,cstride=1,cmap=cm.coolwarm)
    ax.set_zlim(-10,10)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    plt.pause(3)
    plt.show()

# 计算适应度,适应度越高,个体越优秀
def get_fitness(pop): 
    x,y = translateDNA(pop)
    pred = F(x, y)
    return (pred - np.min(pred)) + 1e-3 

# 将二进制的DNA转换为十进制的x和y值
def translateDNA(pop): 
    x_pop = pop[:,1::2]
    y_pop = pop[:,::2]
    x = x_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(X_BOUND[1]-X_BOUND[0])+X_BOUND[0]
    y = y_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(Y_BOUND[1]-Y_BOUND[0])+Y_BOUND[0]
    return x,y

# 交叉和变异过程
def crossover_and_mutation(pop, CROSSOVER_RATE = 0.8):
    new_pop = []
    for father in pop:
        child = father
        if np.random.rand() < CROSSOVER_RATE: 
            mother = pop[np.random.randint(POP_SIZE)]
            cross_points = np.random.randint(low=0, high=DNA_SIZE*2)
            child[cross_points:] = mother[cross_points:]
        child = mutation(child)
        new_pop.append(child)
    return new_pop

# 变异过程
def mutation(child, MUTATION_RATE=0.003):
    if np.random.rand() < MUTATION_RATE:
        mutate_point = np.random.randint(0, DNA_SIZE*2)
        child[mutate_point] = child[mutate_point]^1
    return child

# 自然选择,适者生存
def select(pop, fitness):    
    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True, p=(fitness)/(fitness.sum()) )
    return pop[idx]

# 打印信息
def print_info(pop):
    fitness = get_fitness(pop)
    max_fitness_index = np.argmax(fitness)
    print("max_fitness:", fitness[max_fitness_index])
    x,y = translateDNA(pop)
    print("最优的基因型:", pop[max_fitness_index])
    print("(x, y):", (x[max_fitness_index], y[max_fitness_index]))

# 主函数
if __name__ == "__main__":
    fig = plt.figure()
    ax = Axes3D(fig) 
    plt.ion() 
    plot_3d(ax)
    pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE*2)) 
    for _ in range(N_GENERATIONS):
        x,y = translateDNA(pop)
        if 'sca' in locals(): 
            sca.remove()
        sca = ax.scatter(x, y, F(x,y), c='black', marker='o');plt.show();plt.pause(0.1)
        pop = np.array(crossover_and_mutation(pop, CROSSOVER_RATE))
        fitness = get_fitness(pop)
        pop = select(pop, fitness)
    print_info(pop)
    plt.ioff()
    plot_3d(ax)

猜你喜欢

转载自blog.csdn.net/m0_62526778/article/details/131401322