智能优化算法——遗传算法(Python&Matlab实现)[2]

目录

1 知识点

2 一元函数的优化问题

2.1 案例

​ 2.2 Python实现

2.3 Matlab实现

 3 二元函数的优化问题

3.1 案例

3.2 Python实现 

3.3 Matlab实现 


1 知识点

我们在前面已经把遗传算法的知识点梳理过了——智能优化算法之遗传算法知识点。

下面我们主要分享一元函数的优化问题 二元函数的优化问题:

一元函数的优化问题

2.1 案例

一元函数的优化问题:

                                 f(x)=xcos(5\pi x)+3.5

利用遗传算法计算函数在区间[-1,2.5]上的最值。

 2.2 Python实现

# -*- coding: utf-8 -*-
# ========导入相关包============
import numpy as np
import matplotlib.pyplot as plt


# =====适应度函数,求取最大、小值======
def fitness(x):
    return x*np.cos(5*np.pi*x)+3.5    #最大
    #return -(x * np.cos(5 * np.pi * x) + 3.5)#  最小


# =====个体类============
class indivdual:
    def __init__(self):
        self.x = 0  # 染色体编码
        self.fitness = 0  # 个体适应度值

    def __eq__(self, other):
        self.x = other.x
        self.fitness = other.fitness


# =====初始化种群===========
# pop为种群适应度存储数组,N为个体数
def initPopulation(pop, N):
    for i in range(N):
        ind = indivdual()  # 个体初始化
        ind.x = np.random.uniform(-1, 2.5)  # 个体编码。-10,10的正态分布,可以自己设定限定边界
        ind.fitness = fitness(ind.x)  # 计算个体适应度函数值
        pop.append(ind)  # 将个体适应度函数值添加进种群适应度数组pop


# ======选择过程==============
def selection(N):
    # 种群中随机选择2个个体进行变异(这里没有用轮盘赌,直接用的随机选择)
    return np.random.choice(N, 2)


# ===结合/交叉过程=============
def crossover(parent1, parent2):
    child1, child2 = indivdual(), indivdual()  # 父亲,母亲初始化
    child1.x = 0.9 * parent1.x + 0.1 * parent2.x  # 交叉0.9,0.1,可以设置其他系数
    child2.x = 0.1 * parent1.x + 0.9 * parent2.x
    child1.fitness = fitness(child1.x)  # 子1适应度函数值
    child2.fitness = fitness(child2.x)  # 子2适应度函数值
    return child1, child2


# =====变异过程==========
def mutation(pop):
    # 种群中随机选择一个进行变异
    ind = np.random.choice(pop)
    # 用随机赋值的方式进行变异
    ind.x = np.random.uniform(-1, 2.5)
    ind.fitness = fitness(ind.x)


# ======最终执行===========
def implement():
    # ===种群中个体数量====
    N = 40
    # 种群
    POP = []
    # 迭代次数
    iter_N = 400
    # 初始化种群
    initPopulation(POP, N)

    # ====进化过程======
    for it in range(iter_N):  # 遍历每一代
        a, b = selection(N)  # 随机选择两个个体
        if np.random.random() < 0.65:  # 以0.65的概率进行交叉结合
            child1, child2 = crossover(POP[a], POP[b])
            new = sorted([POP[a], POP[b], child1, child2], key=lambda ind: ind.fitness,
                         reverse=True)  # 将父母亲和子代进行比较,保留最好的两个
            POP[a], POP[b] = new[0], new[1]

        if np.random.random() < 0.1:  # 以0.1的概率进行变异
            mutation(POP)

        POP.sort(key=lambda ind: ind.fitness, reverse=True)

    return POP


if __name__ == '__main__':
    POP = implement()


    # =======绘图代码============
    def func(x):
        return x*np.cos(5*np.pi*x)+3.5
        #return -(x * np.cos(5 * np.pi * x) + 3.5)


    x = np.linspace(-1, 2.5, 100)
    y = func(x)
    scatter_x = np.array([ind.x for ind in POP])
    scatter_y = np.array([ind.fitness for ind in POP])
    best = sorted(POP, key=lambda POP: POP.fitness, reverse=True)[0]  # 最佳点

    print('best_x:', best.x)
    print('best_y:', best.fitness)
    plt.plot(x, y)
    # plt.scatter(scatter_x, scatter_y, c='r')
    plt.scatter(best.x, best.fitness, c='g', label='best point')
    plt.legend()
    plt.show()
#==========结果============

#===(1)最大值====

best_x: 2.40537584441956
best_y: 5.896804913355371


#===(1)最小值====

best_x: 2.196313082366646
best_y: -1.3073691355607653

 智能优化算法——遗传算法(Python&Matlab实现)[2]_第1张图片智能优化算法——遗传算法(Python&Matlab实现)[2]_第2张图片

2.3 Matlab实现

%opt_minmax=-1;     %目标优化类型:1最大化、-1最小化
opt_minmax=1;
num_ppu=50;        %种群规模:个体个数
num_gen=60;        %最大遗传代数
len_ch=20;         %基因长度
gap=0.9;           %代沟
sub=-1;            %变量取值下限
up=2.5;            %变量取值上限
cd_gray=1;         %是否选择格雷编码方式:1是0否
sc_log=0;          %是否选择对数标度:1是0否
trace=zeros(num_gen,2);   %遗传迭代性能跟踪器,生成60行2列0矩阵
fieldd=[len_ch;sub;up;1-cd_gray;sc_log;1;1];   %区域描述器
chrom=crtbp(num_ppu,len_ch); %初始化生成种群,生成一个50*20的矩阵,矩阵元素是0-1随机数
k_gen=0;%初始化遗传次数
x=bs2rv(chrom,fieldd);                 %翻译初始化种群为10进制
fun_v=fun_sigv(x);                     %计算目标函数值
tx=sub:.01:up;
plot(tx,fun_sigv(tx))
xlabel('x')
ylabel('y')
title('一元函数优化结果')
hold on
while k_gen
function y=fun_sigv(x)
y=x.*cos(5*pi*x)+3.5;

MATLAB:未定义函数或变量 ‘crtbp‘问题解决!

 智能优化算法——遗传算法(Python&Matlab实现)[2]_第3张图片智能优化算法——遗传算法(Python&Matlab实现)[2]_第4张图片

 智能优化算法——遗传算法(Python&Matlab实现)[2]_第5张图片智能优化算法——遗传算法(Python&Matlab实现)[2]_第6张图片

 3 二元函数的优化问题

3.1 案例

智能优化算法——遗传算法(Python&Matlab实现)[2]_第7张图片

3.2 Python实现 

#==========导入相关库================#
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm  #绘制3d曲面时用于给图上色:【ax.plot_surface(X, Y, Z, rstride = 1, cstride = 1, cmap = cm.coolwarm)】
from mpl_toolkits.mplot3d import Axes3D  #用于画三维图,将二维图变换为三维图: 【fig = plt.figure()】  【ax = Axes3D(fig)】

#=======初始化及变量范围==============#
DNA_SIZE = 24
POP_SIZE = 200
CROSSOVER_RATE = 0.8
MUTATION_RATE = 0.005
N_GENERATIONS = 50
X_BOUND = [-10, 10]
Y_BOUND = [-10, 10]

#=====目标函数===========#
def F(x, y):
    t1,t2=0,0
    for i in range(5):
        t1 = t1 + i * np.cos((i + 1) * x + i)
        t2 = t2 + i * np.cos((i + 1) * y + i)
    return t1*t2

    #return x + 16 * np.sin(5 * x) + 10 * np.cos(4 * x)

#======3D绘图==========#
def plot_3d(ax):
    X = np.linspace(*X_BOUND, 10)
    Y = np.linspace(*Y_BOUND, 10)
    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(-60,60)
    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  # 减去最小的适应度是为了防止适应度出现负数,通过这一步fitness的范围为[0, np.max(pred)-np.min(pred)],最后在加上一个很小的数防止出现为0的适应度
'''
    (1)最小值适应度函数
    def get_fitness(pop): 
	    x,y = translateDNA(pop)
	    pred = F(x, y)
	    return -(pred - np.max(pred)) + 1e-3
	(2)np.min用法
        import numpy as np  
        a = np.array([[1,5,3],[4,2,6]])  
        print(a.min()) #无参,所有中的最小值   print(min(a))
        print(a.min(0)) # axis=0; 每列的最小值  print(min(a, axis = 0))
        print(a.min(1)) # axis=1;每行的最小值  print(min(a, axis = 1))
    '''

#======基因编译========#
def translateDNA(pop):  # pop表示种群矩阵,一行表示一个二进制编码表示的DNA,矩阵的行数为种群数目
    x_pop = pop[:, 1::2]  # 奇数列表示X
    y_pop = pop[:, ::2]  # 偶数列表示y

    # pop:(POP_SIZE,DNA_SIZE)*(DNA_SIZE,1) --> (POP_SIZE,1)
    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  # 孩子先得到父亲的全部基因(这里我把一串二进制串的那些0,1称为基因)
        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:]  # 孩子得到位于交叉点后的母亲的基因
        mutation(child)  # 每个后代有一定的机率发生变异
        new_pop.append(child)

    return new_pop
'''【1】 np.random.rand()
            注:使用方法与np.random.randn()函数相同 
            作用: 通过本函数可以返回一个或一组服从“0~1”均匀分布的随机样本值。随机样本取值范围是[0,1),不包括1。
    【2】np.random.randn(d0,d1,d2……dn) 
            1)当函数括号内没有参数时,则返回一个浮点数; 
            2)当函数括号内有一个参数时,则返回秩为1的数组,不能表示向量和矩阵; 
            3)当函数括号内有两个及以上参数时,则返回对应维度的数组,能表示向量或矩阵; 
            4)np.random.standard_normal()函数与np.random.randn()类似,但是np.random.standard_normal()
            的输入参数为元组(tuple). 
            5)np.random.randn()的输入通常为整数,但是如果为浮点数,则会自动直接截断转换为整数。
            作用:通过本函数可以返回一个或一组服从标准正态分布的随机样本值。
        【3】np.random.randint()
            numpy.random.randint(low, high=None, size=None, dtype=’l’) 
            输入: 
            low—–为最小值 
            high—-为最大值 
            size—–为数组维度大小 
            dtype—为数据类型,默认的数据类型是np.int。 
            返回值: 
            返回随机整数或整型数组,范围区间为[low,high),包含low,不包含high; 
            high没有填写时,默认生成随机数的范围是[0,low)'''

#==============变异==========================#
def mutation(child, MUTATION_RATE=0.003):
    if np.random.rand() < MUTATION_RATE:  # 以MUTATION_RATE的概率进行变异
        mutate_point = np.random.randint(0, DNA_SIZE * 2)  # 随机产生一个实数,代表要变异基因的位置
        child[mutate_point] = child[mutate_point] ^ 1  # 将变异点的二进制为反转

#=============选择==========================#
def select(pop, fitness):  # nature selection wrt pop's fitness
    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,
                           p=(fitness) / (fitness.sum()))
    return pop[idx]
'''
    np.random.choice()用法
    1、参数意思分别 是从a 中以概率P,随机选择3个, p没有指定的时候相当于是一致的分布,a为一维数组或int,如果是int,则生成随机样本,就好像a是np.arange(N)一样。
        a1 = np.random.choice(a=5, size=3, replace=False, p=None)
    2、非一致的分布,会以多少的概率提出来
        a2 = np.random.choice(a=5, size=3, replace=False, p=[0.2, 0.1, 0.3, 0.4, 0.0])
    replacement 代表的意思是抽样之后还放不放回去,如果是False的话,那么出来的三个数都不一样,如果是True的话, 有可能会出现重复的,因为前面的抽的放回去了。
    '''

#======打印最大适应度,最优基因,X,Y==============#
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]))

#==================主函数====================#
def main():
    fig = plt.figure()
    ax = Axes3D(fig)
    plt.ion()  # 将画图模式改为交互模式,程序遇到plt.show不会暂停,而是继续执行
    plot_3d(ax)

    pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE * 2))  # matrix (POP_SIZE, DNA_SIZE)
    for _ in range(N_GENERATIONS):  # 迭代N代
        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))
        # F_values = F(translateDNA(pop)[0], translateDNA(pop)[1])#x, y --> Z matrix
        fitness = get_fitness(pop)
        pop = select(pop, fitness)  # 选择生成新的种群

    print_info(pop)
    plt.ioff()
    plot_3d(ax)
#结果

max_fitness: 0.8502111412747931
最优的基因型: [1 0 1 1 0 1 0 1 0 0 1 1 1 1 0 0 1 0 0 0 1 1 0 0 0 1 0 0 1 0 1 1 0 1 0 0 1
 0 1 0 1 1 0 1 1 0 0 1]
(x, y): (-0.7685691576343263, 5.518563718710167)

   智能优化算法——遗传算法(Python&Matlab实现)[2]_第8张图片

3.3 Matlab实现 

clc
clear all
opt_minmax=-1;   %目标优化类型:1最大化、-1最小化
%opt_minmax=1; 
num_ppu=60;     %种群规模:个体个数
num_gen=100;    %最大遗传代数
num_v=2;        %变量个数
len_ch=20;      %基因长度
gap=0.9;        %代沟
sub=-10;        %变量取值下限
up=10;          %变量取值上限
cd_gray=1;      %是否选择格雷编码方式:1是0否
sc_log=0;       %是否选择对数标度:1是0否
trace=zeros(num_gen,2);   %遗传迭代性能跟踪器
fieldd=[repmat([len_ch],[1,num_v]);repmat([sub;up],[1,num_v]);repmat([1-cd_gray;sc_log;1;1],[1,num_v])];   %区域描述器
chrom=crtbp(num_ppu,len_ch*num_v);           %初始化生成种群
k_gen=0;
x=bs2rv(chrom,fieldd);                       %翻译初始化种群为10进制
fun_v=fun_mutv(x(:,1),x(:,2));               %计算目标函数值
[tx,ty]=meshgrid(-10:.1:10);
mesh(tx,ty,fun_mutv(tx,ty))%画三维图
xlabel('x')
ylabel('y')
zlabel('z')
title('多元函数优化结果')
hold on
while k_gen
function my=fun_mutv(x,y)
t1=zeros(size(x));
t2=t1;
for i=1:5
    t1=t1+i*cos((i+1)*x+i);
    t2=t2+i*cos((i+1)*y+i);
end
my=t1.*t2;

智能优化算法——遗传算法(Python&Matlab实现)[2]_第9张图片  智能优化算法——遗传算法(Python&Matlab实现)[2]_第10张图片

智能优化算法——遗传算法(Python&Matlab实现)[2]_第11张图片 智能优化算法——遗传算法(Python&Matlab实现)[2]_第12张图片

 此刻晚上两点,把问题都解决完了,心里踏实多啦,睡觉........

你可能感兴趣的:(#,智能优化算法,matlab,算法,python)