遗传算法及实例

        遗传算法是模拟生物在自然环境下遗传的过程而形成的自适应全局优化搜索算法。如果把某个问题的可行域看作是一个族群,目标函数看作是自然选择的条件,那么,这个族群通过一代又一代的繁衍和进化最终变成最接近筛选条件的样子。遗传算法就是利用了这个思想。

        在求解问题的过程中,将问题的可行解的全体看作是初始种群,目标函数作为适应度函数来进行筛选,通过一次又一次的迭代缩小可行解的范围,在该范围中确定最优解的位置。当然,这种方法得到的最优解往往都是最优解的近似或是局部的最优解,过于繁复的迭代也许也是它的一个缺点,但不可否认的是,遗传算法具有强大的适应性,它能够很好地解决各类问题,如大规模的优化问题,TSP问题等。

        使用遗传算法还有一个好处,或者说这类启发式算法都拥有的优势就是不需要清楚某一类问题具体的求解方法,它就是一种迭代过程,通过纯粹的迭代实现找到最优解的过程。以优化问题为例,通常的线性规划问题是通过单纯形法来求解,有着严谨的求解过程,而启发式算法则是通过一步又一步的迭代来实现这个过程。 

       遗传算法的核心步骤只有三个,一个是种群的选取,一个是“基因”的交叉,还有一个是基因的变异。其计算思路如下:

       1、选择初始种群

       2、计算适应度函数(目标函数),将其归一化后作为下一代选取的概率

       3、进行交叉操作(可以基于概率,也可以基于其他)

       4、进行变异操作

       5、重复2-4,直到达到循环条件(如迭代次数或误差小于某个值)

       以下为两个示例,第一个是通过遗传算法求解0-1规划问题;第二个是通过遗传算法求解TSP问题。 

%利用遗传算法求解目标规划问题
clear all;
close all;
clc;
c=[2 -1];%目标规划系数
A=-[5 4;-3 1];
b=-[20;3];
NP=500;%种群数目
L=length(c);%基因数目
Xs=20;%上限
Xx=0;%下限
G=1000;%最大遗传代数
Pc=0.8;%交叉概率
Pm=0.2;%变异概率
nf=zeros(NP,L);%储存子种群
f=randi([0,Xs],NP,L);%初始赋值
F=[];%储存可行解
count=0;
for k=1:G
    count=count+1;
    nn=0;
    for i=1:NP
        d(:,i)=A*f(i,:)';
        m=min(d(:,i)-b);
        if m>=0
            nn=nn+1;
            F(nn,:)=f(i,:);%筛选合适的种群
        end
    end
    %%%%%%%%%%%%%%%%%%将筛选合适的种群扩充%%%%%%%%%%%%%%%%%%%
    [aa,bb]=size(F);
    while aa<NP
        nnper=randperm(nn);
        if length(nnper)>=2
            AA=F(nnper(1),:);
            BB=F(nnper(2),:);
        else
            AA=F(nnper(1),:);
            BB=F(nnper(1),:);
        end

        F=[F;AA;BB];
        [aa,bb]=size(F);
    end
    if aa>NP%保证种群数为NP
        F=F(1:NP,:);
    end
    f=F;
    for i=1:NP
        Fit(i)=Hanshu(c,f(i,:));
    end
    MaxFit=max(Fit);
    MinFit=min(Fit);
    rr=find(Fit==MinFit);
    fBest=Fit(rr(1,1));
    xBest=f(rr(1,1),:);
    %%%%%%%%%%%%%%%%%%%%%%%%%交叉操作%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    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=nf(i+1,j);
                    nf(i+1,j)=nf(i,j);
                    nf(i,j)=temp;
                end
            end
        end
    end
    %%%%%%%%%%%%%%%%%%%%%%%变异操作%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    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);%随机选取需要变异的基因
            nf(h,g)=0;
        end
        i=i+1;
    end
    f=nf;
    f(1,:)=xBest;
    trace(k)=MinFit;
    F=[];
end
figure
xlabel('迭代次数');
ylabel('目标值函数');
title('适应度进化曲线');
plot(trace)
fBest
xBest
A*xBest'

         目标函数部为:

function result = Hanshu(f,x)
%HANSHU 此处显示有关此函数的摘要
%   此处显示详细说明
result=0;
for i=1:length(f)
    result=f(i)*x(i)+result;
end
end

       用MATLAB解决TSP问题代码如下:

​
%旅行商问题
%问题描述:
% 旅行商问题(TSP问题)。假设有一个旅行商人要拜访全国31个省会城市,
% 他需要选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最
% 后要回到原来出发的城市。对路径选择的要求是:所选路径的路程为所有路径
% 之中的最小值。
%全国31个省会城市的坐标为 
% [1304 2312;3639 1315;4177 2244;3712 1399;3488 1535;3326 1556;3238 1229;
% 4196 1004;4312 790;4386 570;3007 1970;2562 1756;2788 1491;2381 1676;1332 695;
% 3715 1678;3918 2179;4061 2370;3780 2212;3676 2578;4029 2838;4263 2931;3429 1908;
% 3507 2367;3394 2643;3439 3201;2935 3240;3140 3550;2545 2357;2778 2826;2370 2975]。

%%%%%%%%%%%%%%%%%%%%%%%%%%遗传算法求解旅行商问题%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
clc;
C=[1304 2312;3639 1315;4177 2244;3712 1399;3488 1535;3326 1556;3238 1229;
4196 1004;4312 790;4386 570;3007 1970;2562 1756;2788 1491;2381 1676;1332 695;
3715 1678;3918 2179;4061 2370;3780 2212;3676 2578;4029 2838;4263 2931;3429 1908;
3507 2367;3394 2643;3439 3201;2935 3240;3140 3550;2545 2357;2778 2826;2370 2975];
NP=500;
N=31;%基因维数
G=10000;%迭代数
N=size(C,1);%城市个数
D=zeros(N);%任意城市间的距离矩阵
%计算城市间距离矩阵
for i=1:N
    for j=1:N
        D(i,j)=sqrt((C(i,1)-C(j,1))^2+(C(i,2)-C(j,2))^2);
    end
end
f=zeros(NP,N);%储存种群
for i=1:NP
    f(i,:)=randperm(N);
end
R=f(1,:);%储存最优种群
len=zeros(NP,1);%储存径路长度
fitness=zeros(NP,1);%储存归一化适应值
gen=0;%迭代次数
while gen<G
    for i=1:NP
        len(i,1)=D(f(i,N),f(i,1));
        for j=1:(N-1)
            len(i,1)=len(i,1)+D(f(i,j),f(i,j+1));
        end
    end
    Maxlen=max(len);%最短路径
    Minlen=min(len);%最短路径
    %%%%%%%%%%%%%%%%%%%%更新最短路径%%%%%%%%%%%%%%%%%%%%%%
    rr=find(len==Minlen);
    R=f(rr(1,1),:);
    %%%%%%%%%%%%%%%%%%%计算归一化适应值%%%%%%%%%%%%%%%%%%%%
    for i=1:length(len)
        fitness(i,1)=-(len(i,1)-Maxlen)/(Maxlen-Minlen);
    end
    %%%%%%%%%%%%%%%%%%%%%选择操作%%%%%%%%%%%%%%%%%%%%%%%%%%
    nn=0;
    for i=1:NP
        if fitness(i,1)>=rand
            nn=nn+1;
            F(nn,:)=f(i,:);
        end
    end
    [aa,bb]=size(F);
    while aa<NP
        nnper=randperm(nn);
        A=F(nnper(1),:);
        B=F(nnper(2),:);
        %%%%%%%%%%%%%%%%%%%%交叉操作%%%%%%%%%%%%%%%%%%%%%
        W=ceil(N/10);%交叉点个数
        p=unidrnd(N-W+1);%随机选择交叉范围,从p到p+W
        for i=1:W
            x=find(A==B(p+i-1));
            y=find(B==A(p+i-1));
            temp=A(p+i-1);
            A(p+i-1)=B(p+i-1);
            B(p+i-1)=temp;
            temp=A(x);
            A(x)=B(y);
            B(y)=temp;
        end
        %%%%%%%%%%%%%%%%%%%%变异操作%%%%%%%%%%%%%%%%%%%%%
        p1=floor(1+N*rand());
        p2=floor(1+N*rand());
        while p1==p2
            p1=floor(1+N*rand());
            p2=floor(1+N*rand());
        end
        tmp=A(p1);
        A(p1)=A(p2);
        A(p2)=tmp;
        tmp=B(p1);
        B(p1)=B(p2);
        B(p2)=tmp;
        F=[F;A;B];
        [aa,bb]=size(F);
    end
    if aa>NP
        F=F(1:NP,:);
    end
    f=F;
    f(1,:)=R;
    F=[];
    gen=gen+1;
    Rlength(gen)=Minlen;
end
figure
for i=1:N-1
    plot([C(R(i),1),C(R(i+1),1)],[C(R(i),2),C(R(i+1),2)],'bo-');
    hold on;
end
title('最短化距离:',num2str(Minlen));
figure
plot(Rlength)
xlabel("迭代次数");
ylabel('目标函数');
title('适应度进化曲线');
R

​

         画出来的图稍显不靠谱的原因是因为计算长度没有考虑到第一个点与最后一个点之间的距离,运算结果如图所示:     


         由于我也是才开始接触这些算法(本科时没有参加建模接触这些还蛮可惜的),觉得很有意思的同时也深感需要学习的有很多,以及自己对这些算法的理解也稍显浅薄,如有不对之处还请指出。

参考:《智能优化算法及其MATLAB实例》——包子阳

  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
遗传算法的编码方式有多种,其中二进制编码是最常用的一种。下面是一个使用二进制编码的遗传算法Python示例: ```python import random # 定义目标函数 def fitness_func(chromosome): x = decode(chromosome[:10], -5, 5) y = decode(chromosome[10:], -5, 5) return x**2 + y**2 # 定义解码函数 def decode(binary, a, b): x = int(''.join(str(i) for i in binary), 2) return a + (b - a) * x / (2**len(binary) - 1) # 定义交叉函数 def crossover(parent1, parent2): point = random.randint(1, len(parent1) - 1) child1 = parent1[:point] + parent2[point:] child2 = parent2[:point] + parent1[point:] return child1, child2 # 定义变异函数 def mutation(chromosome, p): for i in range(len(chromosome)): if random.random() < p: chromosome[i] = 1 - chromosome[i] return chromosome # 初始化种群 population_size = 50 chromosome_length = 20 population = [[random.randint(0, 1) for j in range(chromosome_length)] for i in range(population_size)] # 开始迭代 max_generation = 100 crossover_rate = 0.8 mutation_rate = 0.01 for generation in range(max_generation): # 计算适应度 fitness = [fitness_func(chromosome) for chromosome in population] # 选择 parents = [] for i in range(population_size): parent1 = population[roulette_wheel_selection(fitness)] parent2 = population[roulette_wheel_selection(fitness)] parents.append((parent1, parent2)) # 交叉 offspring = [] for parent1, parent2 in parents: if random.random() < crossover_rate: child1, child2 = crossover(parent1, parent2) offspring.append(child1) offspring.append(child2) else: offspring.append(parent1) offspring.append(parent2) # 变异 population = [mutation(chromosome, mutation_rate) for chromosome in offspring] # 输出最优解 best_chromosome = population[0] best_fitness = fitness_func(best_chromosome) for chromosome in population: fitness = fitness_func(chromosome) if fitness < best_fitness: best_chromosome = chromosome best_fitness = fitness x = decode(best_chromosome[:10], -5, 5) y = decode(best_chromosome[10:], -5, 5) print("x =", x) print("y =", y) print("f(x,y) =", best_fitness) ``` 在这个例子中,我们使用二进制编码来表示自变量x和y。每个染色体由20个基因组成,前10个基因表示x,后10个基因表示y。解码函数decode将二进制编码转换为实数值。交叉函数crossover和变异函数mutation用于产生新的染色体。选择函数roulette_wheel_selection使用轮盘赌算法来选择父代。最终,我们得到了最优解x、y和目标函数的最小值f(x,y)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值