遗传算法GA(学习笔记_05)

1. 基本概念

遗传学术语 遗传算法术语
群体 可行解集
个体 可行解
染色体 可行解的编码
基因 可行解编码的分量
基因形式 遗传编码
适应度 评价函数值
选择 选择操作
交叉 交叉操作
变异 变异操作
  • 遗传编码:

    • 二进制编码

    • 十进制编码(实数编码):只能用于连续变量问题,但计算精度高

  • 适应度(评价函数值):非负!!

    • 求目标函数最大值时:

      F(x) = f(x) + c; (f(x) + c > 0)

    • 求目标函数最小值时:

      F(x) = c - f(x); (f(x) < c)

    • 为啥要保证非负嘞:遗传算法中以个体适应度的大小来确定该个体被遗传到下一代群体中的概率。

  • 遗传操作(复制):

    • 轮盘赌选择法

    • 君主选择法

  • 交叉操作

    • 实值重组:离散重组、线性重组、中间重组...

    • 二进制交叉:单点交叉、多点交叉...

  • 变异操作

    • 实值变异:对相应基因之用取值范围内的其他随机值替代

    • 二进制变异:对相应基因值取反

2. 特点

  • 以决策变量的编码作为运算对象

  • 同时使用多个搜索点的搜索信息(从种群出发)

  • 时一种基于概率的搜索技术

3. 基本参数

  • np:群体规模

  • pc:交叉概率(0.25~1.00)

    • 太大:开辟新的搜索区域能力增强,但高性能的模式遭到破坏的可能性大

    • 太小:可能陷入迟钝状态

  • pm:变异概率:保持群体的多样性(0.001~0.1)

    • 高频度:趋于纯粹的随机算法

    • 低频度:防止群体中重要基因的可能丢失

4. 基本流程

  1. 创建初始种群

  2. for k = 1:iter_max

    1. for i = 1:np ----> 计算种群的评价值

      (1) 位串解码(二进制转十进制)

      (2)计算个体的评价值

    2. end

    3. 获取当前种群的最优适应度的个体的位置和评价值

    4. 适应值调整

    5. 遗传操作 -----> 产生新一代个体

      1. 选择操作

      2. 交叉操作

      3. 编译操作

    6. 将当前种群的最优适应值个体置于新种群中

  3. end

  4. 输出最优个体

  5. 源代码(求函数最大值)

  • 二进制编码

  • 选择操作:轮盘赌选择法

  • 交叉操作:多点交叉

  • 变异操作:二进制变异,随机取位置,对应位置取反

clear;
close all;
clc;

np = 50;  %种群数量
L = 20;  %二进制位串长度
pc = 0.8;  %交叉率
pm = 0.1;  %变异率
iter_max = 200;  %最大遗传代数
x_max = 5;
x_min = -5;
y_max = 5;
y_min = -5;
c = 100;

%% 1.随机获得初始种群
f1 = randi([0,1],np,L); 
f2 = randi([0,1],np,L);

for k = 1:iter_max
    %% 2.将二进制解码为定义域范围内十进制,计算适应度值
    for i = 1:np
        u1 = f1(i,:);  %每个个体的二进制串(染色体)
        u2 = f2(i,:);
        
        d1 = 0;  %二进制串对应的十进制
        d2 = 0;
        for j = 1:L
            d1 = d1 + u1(j)*2^(j-1);
            d2 = d2 + u2(j)*2^(j-1);
        end
        x(i,1) = x_min + d1*(x_max-x_min)/(2^L-1);  %对应个体的位置
        x(i,2) = y_min + d2*(y_max-y_min)/(2^L-1);
        fit(i) = c + func(x(i,:));  %对应个体的适应度值
    end
    
    %由于求极小值时,个体评价值改变为c - func(x(i,:)),仍为最大值
    fit_best = max(fit);  %更新最大值(最优值)
    fit_worst = min(fit);  %更新最小值
    
    for i = 1:np  %找到最优值对应位置
        if fit(i) == fit_best
            pos = i;
        end
    end
    
    best_f1 = f1(pos,:);  %最优值x(1)对应二进制串
    best_f2 = f2(pos,:);  %最优值x(2)对应二进制串
    
    best_x = x(pos,:);  %最优值对应位置
    fit = (fit - fit_worst) / (fit_best - fit_worst);  %归一化适应度值
    
    %% 3.选择操作(轮盘赌选择法)
    fit_sum = sum(fit);
    fit_value = fit./fit_sum;
    fit_value = cumsum(fit_value);  %每个个体被选取的概率
    p = sort(rand(np,1));  %升序随机产生每个个体的选择指针
    
    fit_i = 1;  %在父代中遍历的标识
    new_i = 1;  %新子代的标识
    %选择优良个体复制到下一代,产生新种群
    while new_i <= np
        if p(new_i) < fit_value(fit_i)
            nf1(new_i,:) = f1(fit_i,:);
            nf2(new_i,:) = f2(fit_i,:);
            new_i = new_i + 1;
        else
            fit_i = fit_i + 1;
        end
    end
    
    %% 4.交叉操作
    for i = 1:2:np
        p = rand;
        if p < pc
            q = randi([0,1],1,L);  %随机生成一串二进制串,确定若干个交换位置
            for j = 1:L
                if q(j) == 1  %新种群中前后两个个体的待交换位置进行交换
                    temp = nf1(i,j);
                    nf1(i,j) = nf1(i+1,j);
                    nf1(i+1,j) = temp;
                    
                    temp = nf2(i,j);
                    nf2(i,j) = nf2(i+1,j);
                    nf2(i+1,j) = temp;
                end
            end
        end
    end
    
    %% 5.变异操作
    i = 1;
    while i <= round(np*pm)
        h = randi([1,np],1,1);  %随机生成一个需要变异的染色体的位置
        for j = 1:round(L*pm)
            g = randi([1,L],1,1);  %随机生成变异的基因数
            nf1(h,g) = ~nf1(h,g);  %对相应基因进行取反
            nf2(h,g) = ~nf2(h,g);
        end
        i = i + 1;
    end
    
    f1 = nf1;
    f2 = nf2;
    f1(1,:) = best_f1;  %保留最优个体在下一代中
    f2(1,:) = best_f2;
    
    trace(k) = c + fit_best;
end

x = best_x  %最优个体的位置
y = c + fit_best
figure
plot(trace)
xlabel('迭代次数')
ylabel('目标函数值')
title('适应度进化曲线')

function results = func(x)
    results = 5 * cos(x(1) * x(2))+ x(1) * x(2) + x(2) * x(2) * x(2);
end

  6. 源代码(求函数最小值)

clear;
close all;
clc;

np = 50;  %种群数量
L = 20;  %二进制位串长度
pc = 0.8;  %交叉率
pm = 0.1;  %变异率
iter_max = 200;  %最大遗传代数
x_max = 5;
x_min = -5;
y_max = 5;
y_min = -5;
c = 666;

%% 1.随机获得初始种群
f1 = randi([0,1],np,L); 
f2 = randi([0,1],np,L);

for k = 1:iter_max
    %% 2.将二进制解码为定义域范围内十进制,计算适应度值
    for i = 1:np
        u1 = f1(i,:);  %每个个体的二进制串(染色体)
        u2 = f2(i,:);
        
        d1 = 0;  %二进制串对应的十进制
        d2 = 0;
        for j = 1:L
            d1 = d1 + u1(j)*2^(j-1);
            d2 = d2 + u2(j)*2^(j-1);
        end
        x(i,1) = x_min + d1*(x_max-x_min)/(2^L-1);  %对应个体的位置
        x(i,2) = y_min + d2*(y_max-y_min)/(2^L-1);
        fit(i) = c - func(x(i,:));  %对应个体的适应度值
    end
    
    %由于求极小值时,个体评价值改变为c - func(x(i,:)),仍为最大值
    fit_best = max(fit);  %更新最大值(最优值)
    fit_worst = min(fit);  %更新最小值
    
    for i = 1:np  %找到最优值对应位置
        if fit(i) == fit_best
            pos = i;
        end
    end
    
    best_f1 = f1(pos,:);  %最优值x(1)对应二进制串
    best_f2 = f2(pos,:);  %最优值x(2)对应二进制串
    
    best_x = x(pos,:);  %最优值对应位置
    fit = (fit - fit_worst) / (fit_best - fit_worst);  %归一化适应度值
    
    %% 3.选择操作(轮盘赌选择法)
    fit_sum = sum(fit);
    fit_value = fit./fit_sum;
    fit_value = cumsum(fit_value);  %每个个体被选取的概率
    p = sort(rand(np,1));  %升序随机产生每个个体的选择指针
    
    fit_i = 1;  %在父代中遍历的标识
    new_i = 1;  %新子代的标识
    %选择优良个体复制到下一代,产生新种群
    while new_i <= np
        if p(new_i) < fit_value(fit_i)
            nf1(new_i,:) = f1(fit_i,:);
            nf2(new_i,:) = f2(fit_i,:);
            new_i = new_i + 1;
        else
            fit_i = fit_i + 1;
        end
    end
    
    %% 4.交叉操作
    for i = 1:2:np
        p = rand;
        if p < pc
            q = randi([0,1],1,L);  %随机生成一串二进制串,确定若干个交换位置
            for j = 1:L
                if q(j) == 1  %新种群中前后两个个体的待交换位置进行交换
                    temp = nf1(i,j);
                    nf1(i,j) = nf1(i+1,j);
                    nf1(i+1,j) = temp;
                    
                    temp = nf2(i,j);
                    nf2(i,j) = nf2(i+1,j);
                    nf2(i+1,j) = temp;
                end
            end
        end
    end
    
    %% 5.变异操作
    i = 1;
    while i <= round(np*pm)
        h = randi([1,np],1,1);  %随机生成一个需要变异的染色体的位置
        for j = 1:round(L*pm)
            g = randi([1,L],1,1);  %随机生成变异的基因数
            nf1(h,g) = ~nf1(h,g);  %对相应基因进行取反
            nf2(h,g) = ~nf2(h,g);
        end
        i = i + 1;
    end
    
    f1 = nf1;
    f2 = nf2;
    f1(1,:) = best_f1;  %保留最优个体在下一代中
    f2(1,:) = best_f2;
    
    trace(k) = c - fit_best;
end

x = best_x  %最优个体的位置
y = c-fit_best
figure
plot(trace)
xlabel('迭代次数')
ylabel('目标函数值')
title('适应度进化曲线')

function results = func(x)
    results = 5 * cos(x(1) * x(2))+ x(1) * x(2) + x(2) * x(2) * x(2);
end

你可能感兴趣的:(机器学习,启发式算法)