遗传算法(Genetic Algorithm,GA)详解【附算法代码与运行结果】

算法背景

遗传算法(Genetic Algorithm,GA)是模拟生物在自然环境中的遗传和进化的过程而形成的自适应全局优化搜索算法。遗传算法借鉴了达尔文的进化论和孟德尔的遗传学说。其本质是一种并行、高效、全局搜索的方法,它能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应地控制搜索过程以求得最优解。遗传算法操作使用“适者生存”的原则,在潜在的解决方案种群中逐次产生一个近似最优的方案。在遗传算法的每一代中,根据个体在问题域中的适应度值和从自然遗传学中借鉴来的再造方法进行个体选择,产生一个新的近似解。这个过程导致种群中个体的进化,得到的新个体比原个体更能适应环境,就像自然界中的改造一样。


基本原理

对每个个体都进行上述的进化,包括复制,交叉,变异。然后择优录取。

编码:将问题的可行解,抽象编码为适用于遗传算法的形式。核心思想是根据不同的问题,用一个串对不同的抽象表示。

常见的编码方式如二进制编码用一个二进制串来表示这个十进制数值。用以求解问题。比如在处理TSP问题时,给你10个城市,需要你不重复的经过每一个城市,某个解依次走过每个城市则可以表示为[3,2,1,4,5,7,6,8,9,0]。

• 给定数值解的区间范围:[1,10]。

• 给定精度:1e-5,两个数值解的间隔。

• 进行编码:为每个数值解分配一个独一无二的二进制串。

】用长度有限的二进制串表示在长度无限的区间[1,10],不能全都表示,所以就只能表示其中的一些数,两个数之间的间隔就是精度。其中表示的二进制串并非在数值上等于表示的值,两者是映射一一对应的关系。

要想实现每个数值都能分配一个独一无二的串,那么串所能表示的数值个数就要大于等于数值解的个数。

一个长度为n的串,能表示{2}^n个数。

例如,区间范围为[1,10],长度为2的串提供的精度为

数值区间长度为L,精度为E的条件下,二进制串的长度n,三者关系为(区间长度除以分段数<精度

要想达到1e-5的精度,对于区间长度为10,串的长度n应该满足

n=20时,串提供的精度约为0.00000954.

解码:二进制串的索引,就是在问当前串是第几个串。使用二进制转十进制得到。以[1,1]为例,其十进制数为3,对应的数值为1+3*3=10。

一般的,区间范围为[a,b],区间长度为L,即L=b-a,串长为n,当前串对应十进制数为T,精度为E,则该串对应实值解为:

复制策略

• 将个体适应度大小映射为概率进行复制。轮盘赌法是指适应度高的个体有更大概率复制,且复制的份数越多。

精英产生精英是指对适应度高的前N/4的个体进行复制,然后用这些个体把后N/4个体替换掉。

• 可以随机复制。

• 由于图像不知,“坏解”也可能与适应度最好的点也近,那么也可以替换掉好解来调整。

交叉策略

• 按顺序两两个体之间按概率交叉。如1和2,2和3等。或者1和2,2和4等,或者1和4这样。

• 按顺序三个及以上个体之间按概率交叉。

• 对适应度高的前N/2个体、甚至N/4的个体之间相互交叉。

• 可随机交叉,对每个个体随机从前N/2中选一个个体交叉。

• 个体中的多段进行交叉。

变异策略

• 每个个体都进行变异。

• 变异不好的,只对适应度低的后N/4的,或者后N/2个个体变异。

• 按适应度大小映射为概率变异。

• 可一个位点变异,也可多个位点变异。

    

       

​​​​​​ ​


算法实现

复制:按适应度大小映射为概率,进行轮盘赌法复制。 适应度越高的解,按道理越应该高概率的进行复制,且复制的份数应该越多。对于个体𝑥𝑖,计算对应适应度𝑓(xi) -> pi= fxi/f(xi)

交叉:1和2,3和4,以一定概率决定是否交叉。若交叉,则二者选择随机一个段进行交叉。

变异:通过扔一个随机数,一定概率决定该个体是否变异,若变异,随机选择一个位点进行变异,按位取反。

 

】轮盘赌法,不是直接对概率比较,而是对概率的累计和进行比较。随机数取值在哪就对那个个体进行复制,Rand = 0 ~ 0.2:表示对 x1 复制Rand = 0.2~0.3:表示对x2复制Rand = 0.3~0.7:表示对x3复制Rand = 0.7~1.0:表示对 x4复制。代码实现技巧方法:

pi= f(xi)/ f(xi) // 得到对应个体概率:0.2 0.1 0.4 0.3

Cs = cumsum(pi)// 累计和:0.2 0.3 0.7 1.0

i = 1 , j = 1

R = sort( rand(4) ) //生成四个随机数再升序排序:0.1 0.5 0.6 0.8

While j <= n

    if R(j)< Cs(i)

        newx(j) = oldx(i)

        j = j + 1

    else

        i = i + 1

比较结果:

i = 1 , j = 1 : Cs = 0.2 , R = 0.1 newx(1) = oldx(1)

i = 1 , j = 2 : Cs = 0.2 , R = 0.5 --------------------

i = 2 , j = 2 : Cs = 0.3 , R = 0.5 --------------------

i = 3 , j = 2 : Cs = 0.7 , R = 0.5 newx(2) = old(3)

相当于把原来乱序的判断做一个顺序的调整,这样可以使得 R< 0.7=>0.3<R< 0.7。

算法分析

优点:参数少,理论优势。变异机制赋予了群体跳出局部极值的能力等。

缺点:容易陷入局部最优。算法实现较为繁琐。

】无论是蚁群算法,粒子群算法,免疫算法,鱼群算法,蝙蝠算法,遗传算法,算法思想内涵是一致的:

保底机制 + 更新策略  = 寻得优解


案例实操

求解𝑓(𝑥) = abs(𝑥 𝑠𝑖𝑛 𝑥 𝑐𝑜𝑠 2𝑥 − 2𝑥𝑠𝑖𝑛 3𝑥 + 3𝑥 𝑠𝑖𝑛 4𝑥 )在[0,50]的最大值。

【实验代码】

%%主程序

function GA()



clear

close all

popsize=20; % 群体大小

chromlength=20; %串的长度(个体长度)

pc=0.6; %交叉概率

pm=0.1; %变异概率

xlim = [0,50];% 求解范围

G = 100 ; %迭代次数

% x = zeros(1,G); % 记录每代个体最优位置

% y = zeros(1,G); % 记录每代最优个体对应的函数值



pop= round( rand(popsize,chromlength) )  ; %随机产生初始群体

decpop =  bintodec( pop ,popsize, chromlength,xlim ) ; % 计算初代解对应十进制

fx = calobjvalue(decpop  ) ; % 计算初代解的函数值

plotfig(decpop , fx , xlim , 1  ) ; % 绘制图像

[y(1) , l ]  = max(fx); x(1) = decpop(l);



for i = 2  : G

    decpop =  bintodec( pop , popsize, chromlength,xlim ) ; % 计算上一代解对应十进制

    fx = calobjvalue(decpop  ) ; % 计算上一代解的函数值

    fitvalue = calfitvalue(fx) ;  % 适应度映射

    newpop = copyx(pop,fitvalue,popsize); %复制

    newpop = crossover(newpop, pc, popsize,chromlength ); %交叉

    newpop = mutation(newpop,pm, popsize,chromlength); %变异

    % 这时的newpop是经过复制交叉变异产生的新一代群体

    %     下边进行选择择优保留(即实现保底机制)

    newdecpop =  bintodec( newpop ,popsize, chromlength,xlim ) ;

    new_fx = calobjvalue(newdecpop) ; %计算新解目标函数

    new_fitvalue = calfitvalue(new_fx); %计算新群体中每个个体的适应度

    index = find(new_fitvalue > fitvalue) ;

   

    pop(index, : ) = newpop(index,:) ; % 更新得到最新解

    decpop = bintodec( pop ,popsize, chromlength,xlim ) ; %计算新解的十进制

    fx = calobjvalue( decpop )  ; %计算结果

    plotfig(decpop , fx ,xlim , i ) % 绘制新解的图

    % 找出更新后的个体最优函数值

    [bestindividual,bestindex] = max(  fx ) ;

    y(i)=bestindividual; % 记录每一代的最优函数值

    x(i)= decpop(bestindex) ; %十进制解

    subplot(1,2,2);

    plot(1:i,y);

    title('适应度进化曲线');

  

end

[ymax, max_index] = max(y);

disp(['找的最优解位置为:', num2str(x(max_index)) ])

disp(['对应最优解为:', num2str(ymax) ])



end



%******************************************************************************************%

%% 计算适应度

function fitvalue = calfitvalue(fx)

%这里求最大值,并且函数值又都大于0,所以直接使用函数值本身作为适应度值。

% 事实上,不同的问题适应度函数构造方法多种多样。

    fitvalue = fx ;

end



%% 复制操作

function newx = copyx(pop, fitvalue,popsize ) %传进来二进制串和对应适应度

% 按照PPT的轮盘赌策略对个体复制

    newx = pop; %只是起到申请一个size为pop大小空间的作用,newx之后要更新的

    i = 1;  j = 1;

    p = fitvalue / sum(fitvalue) ; %适应度概率

    Cs = cumsum(p) ; %累计和

    R = sort(rand(popsize,1)) ; %每个个体的复制概率

    while j <= popsize

        if R(j) < Cs(i)

            newx(j,:) = pop(i,:) ;

            j = j + 1;

        else

            i = i + 1;

        end

    end

end



%% 交叉操作

function newx = crossover(pop, pc, popsize,chromlength )

% 12 34 56交叉方式,随机选择交叉位点

% 注意个体数为奇数偶数的区别

i = 2 ;

newx = pop ; %申请空间

while i + 2 <= popsize

    %将第i 与 第 i -1 进行随机位点交叉

    if rand < pc

        x1 = pop(i-1,:);

        x2 = pop(i,:) ;

        r = randperm( chromlength , 2 ) ; %返回范围内两个整数

        r1 = min(r); r2 =max(r) ; % 交叉复制的位点

        newx(i-1,:) = [x1( 1 : r1-1),x2(r1:r2) , x1(r2+1: end)]; % x1的前半部分,并上交叉过来的x2,并上x1的后半部分

        newx(i , : ) = [x2( 1 : r1-1),x1(r1:r2) , x2(r2+1: end)];

    end

    i = i + 2 ; %更新i

end



end



%% 变异

function newx = mutation(pop,pm, popsize,chromlength)

i = 1 ;

while i <= popsize

    if rand < pm %随机生成的数比概率要小

        r = randperm( chromlength , 1 ) ;

        pop(i , r) = ~pop(i, r);%随便生成一个位置按位取反

    end

    i = i + 1;

end



newx = pop; %将变异后的结果返回。



end



%%  二进制转十进制函数

function dec = bintodec( pop ,popsize, chromlength,xlim )

    dec = zeros(1,popsize);

    index = chromlength-1:-1:0;

    for i = 1 : popsize

        dec(i) = sum(pop(i,:).* (2.^index));

    end

    dec = xlim(1) + dec*(  xlim(2) -  xlim(1) ) /( 2 ^ chromlength - 1) ;%解码计算

end





%%  绘制图像

function plotfig(decpop , fx ,xlim,k)

    f = @(x) abs(x .* sin(x) .* cos(2 * x) - 2 * x .* sin(3 * x) +3 * x .* sin(4 * x)); % 研究对象函数 

    x = xlim(1):0.05:xlim(2);

    y = f(x) ;

    subplot(1,2,1);

    plot(x,y,decpop,fx,'o')

    title(['第',num2str(k),'次迭代进化'])

    pause(0.2)

end





%% 目标函数

function fx = calobjvalue(decpop ) %参数为十进制解



f = @(x) abs(x .* sin(x) .* cos(2 * x) - 2 * x .* sin(3 * x) +3 * x .* sin(4 * x)) ; % 研究对象函数       

fx = f(decpop);

end

【运行结果】

>> >找的最优解位置为:47.5586

>> >对应最优解为:219.4966

】遗传算法迭代过程中闪现主要是靠交叉变异得来的;粒子群是迭代过程就是相对连续且缓慢。

对于含有多个自变量的高维分段函数优化问题,确实比一维情况更为复杂,但也有一些有效的策略可以帮助我们应对这类挑战。下面将介绍几种常见的处理方法和技术要点: ### 1. 函数定义 之前一样首先要精确表述好目标函数的形式。考虑到维度增加带来的书写难度增大,建议采用矩阵向量形式表达输入参数,并通过逻辑数组(logical array)配合元素级操作来简化公式编写工作。 ```matlab function y = multiVarPiecewiseFunc(x) % x为列向量 [x1; x2; ... ; xn] regionA = all([true; x >= -ones(size(x,1)-1,1)] & [false; diff(x)<=0], 'all'); % 区域划分条件之一 regionB = ~regionA; y(regionA) = sum(x(regionA).^2); % 各区域内的具体计算规则 y(regionB) = exp(sum(abs(x(regionB)))); end ``` ### 2. 初始估计边界确定 合理选择初始解非常重要,尤其是当未知数较多的时候。除了依赖专业知识外也可以借助随机抽样手段生成一组候选方案作为起点。此外还要注意检查每个决策变量合理的上下限范围以防溢出错误发生。 ### 3. 选择合适的算法 随着自由度的增长传统的一阶或二阶梯度型方法可能会变得低效甚至失效,此时我们可以转而考察一些专用于黑盒优化(black-box optimization)场景下的高效工具包: - **全局搜索器**:如遗传算法GA(genetic algorithm),粒子群PSO(particle swarm optimization),模拟退火SA(simulated annealing)等群体智能仿生学启发式搜索框架; - **模式识别技术**:例如模式搜索(pattern search)/直接搜索(direct search),适用于不允许解析梯度存在的场合下快速定位近似最佳位置; - **代理模型辅助优化(Surrogate-based Optimization)**:构建替代原真实代价高昂响应面(surface response)简单易算版本,在此基础上反复查询改进直至收敛至满意程度再回到原始空间验证真伪。 其中MATLAB自带了部分此类功能模块可以直接调用测试比较性能差异: - 调用`surrbasedopt()`执行基于Kriging建模预测指导选代更新机制。 另外值得注意的是由于引入更多超参配置项因此事前事后都要做好充分的数据预分析评估工作以便及时调整探索力度和方向避免陷入局部极值陷阱之中难以自拔出来。 ### 实现示例 假设有如下三维分段非线性映射待找最大收益点: \[ f(\mathbf{x})=\left\{ \begin{array}{ll} \sum_{i=1}^{n}(a_i-b_ix_i^m)^q ,& \text { if }\quad c_j<x_k<d_l \\ e^{-r\|\mathbf{x}\|^s}, & \text { otherwise } \end{array} \right. \] 那么就可以参照前面给出模板稍作修改形成完整脚本文件供后续进一步调优参考之用了。 ```matlab % 参数初始化设置 dimSize = 3;% 自由度大小即几元组构成状态表示 popInitRange=[lb; ub]; %[lower bounds; upper bounds] 形成矩形可行域 options = optimoptions('surrogateopt',... 'PlotFcn',{@optimplotfval,@optimplotx},'UseParallel', true); [sol,fval] = surrogateopt(@multiVarObjFun,popInitRange(:,1),popInitRange(:,2),[],[],[],[],[],options); disp(['Best solution found:' num2str(sol)]); disp(['Objective function value at best point:',num2str(fval)]); function z = multiVarObjFun(v) persistent memoTable; if isempty(memoTable)||~isfield(memoTable,'lastInput')||... any(~ismember(num2cell(round(v*1e8)),memoTable.lastInput)) if inFeasibleRegion(v)% 根据实际情况设计判定准则 z=sum((rand(dimSize,1)*v.^pi)); else r=norm(rand(1,dimSize)-mean(popInitRange)); s=rand; z=exp(-r*s); end memoTable.lastInput=num2cell(round(v*1e8));% 记忆化存储以加速重复请求回复效率 memoTable.lastOutput=z; else [~,idx]=find(cellfun(@(c)c==round(v(i)*1e8),memoTable.lastInput)); %#ok<STOD> z=memoTable.lastOutput(idx); end end function tf=inFeasibleRegion(x) tf=all(x>=repmat(lb,numel(x)/length(lb),1)&... repmat(ub,numel(x)/length(ub),1)); end ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值