当前位置:   article > 正文

遗传算法及其MATLAB实现(附完整代码)_遗传算法matlab程序

遗传算法matlab程序

       遗传算法是经典的智能算法, 经常被用来求解各种N-P问题, 各种非线性函数的优化等, 可以实现各类模型的非最优解优化. 遗传算法稳定性比较强, 优化的效果比较好, 不是特别依赖初值, 尤其对离散自变量的函数优化是很合适的, 比较容易得到理论最优解, 整体的运行效率比较好, 对线性或非线性的约束都很友好.

        遗传算法的大体流程如下:

 流程包括:

(1)编码的设计方案, 编码就是染色体的编码, 每一个染色体都与目标函数的一个解是对应的, 也就是遗传算法的一个染色体是目标函数解的一个单射, 一个染色体唯一对应一个解(但反过来不一定, 不同的染色体可以对应同样的一个解).  编码的设计方案对于求目标函数解的可行性和效率是非常重要的, 对于不同的问题模型, 我们需要专门设计编码方案, 比如对于离散的排序问题, 我们可以设计一个自然数排序编码 [1,3,2,5,4]这样的排序编码, 来映射排序问题的自变量或解, 对于多维实数域的函数优化问题, 可以把编码设计为[0.1,0.5,1.2,1.3,2.5]这样的多维实数编码,直接对应自变量x.  如何设计编码是各类智能算法永恒的课题.

(2)读取或设置问题模型的数据和参数.

(3)设置遗传算法参数, 如种群数, 迭代次数, 交叉率, 变异率.

(4)初始化种群, 一般采用随机产生一组染色体作为算法的初始染色体.

(5)开始迭代, 进行染色体的变异操作.

(6)对染色体进行交叉操作.

(7)对染色体进行解码,  这个过程就是把染色体映射到解

(8)根据解计算目标函数值和约束,, 再把解带入问题模型,得到目标函数值以及是否满足约束等.

(9)根据解得到的目标函数对染色体进行选择, 这个选择的操作方法也是比较关键的, 这里面体现了进化论的思想, 也即适者生存, 或者适者被选中的概率更大, 久而久之,随着迭代的进行, 适应性更好的染色体会存活下来, 最后得到的是较优解, 当然如果迭代次数够充分, 种群数够大, 往往是可以得到理论最优解的, 但并不能保证你得到.

(10)输出结果, 一般包括迭代曲线和最优编码,最优解, 最优目标函数等. 进而完成了整个算法的构建和问题模型的求解.

        那么如何用MATLAB实现遗传算法呢?根据以上的步骤,  我们的问题模型是: 

其中xi∈[0,1], N=5

       那么我们可直接采用5维实数编码构造染色体(见染色体函数mygenchrome.m) , 

初始化染色体

N=5, 上下限维[0,1]区间,  则一个合法的染色体可表示为[0.1,0.5,0.6,1.0,0.4], 完全均匀随机产生, 见染色体函数mygenchrome.m.

变异(采用单点变异)

(1) 产生一个随机自然数r1,r1表示第r1位的基因发生变异

(2) 采用随机变异的方式将第r1位的基因进行变异.

举例:

r1=2, 那么染色体的变异为

[0.1,0.5,0.6,1.0,0.4]→[0.1,0.2,0.6,1.0, 0.4]

交叉

(1) 随机选择两个染色体作为父本

(2) 产生2个随机自然数r1和r2

(3) 将两个父本染色体r1至r2之间的基因片段进行交换, 得到两个子代染色体

举例:

选择的两个父本染色体

[0.1,0.5,0.6,1.0,0.4]  [0.1,0.5,0.6,0.70,0.54]

r1=2, r2=4

那么交叉过程为

[0.1,0.5,0.6,1.0,0.4]  [0.1,0.5,0.6,0.7,0.54]

交叉后

[0.1,0.5,0.6,0.7, 0.4]  [0.1,0.5,0.6,1.0, 0.54]

其他目标函数何选择函数等较为简单, 不再赘述.

          MATLAB是设计遗传算法以及其他智能算法的非常好的工具, 下面给大家提供下遗传算法的完整程序: 

主程序main.m

  1. %% 遗传算法 优化函数
  2. clc;close all;clear all;warning off;%清除变量
  3. rand('seed', 100);
  4. randn('seed', 100);
  5. format long g;
  6. my_N=10; % 设定优化问题维数
  7. % 设定遗传算法参数
  8. my_popsize=500;% 设定遗传算法种群数
  9. my_maxgen=1000;% 设定遗传算法迭代次数
  10. my_PM=0.1;% 设定变异概率
  11. my_PC=0.8;% 设定交叉概率
  12. lb=0*ones(1,my_N);
  13. ub=1*ones(1,my_N);
  14. %% 遗传算法主程序
  15. my_tracemat=zeros(my_maxgen,2);% 设定性能跟踪
  16. my_gen=0;
  17. tic;
  18. Chrom_my=mygenchrome(my_popsize,my_N,lb,ub);% 建立种群
  19. Value_my=mydecodingfun(Chrom_my,my_popsize);% 解码染色体
  20. [vmin_my,indexmin_my]=min(Value_my);
  21. bestChrom_my=Chrom_my(indexmin_my,:);% 记录最优染色体
  22. bestValue_my=vmin_my;% 记录的最优值
  23. %% 遗传算法优化的主循环
  24. while my_gen<my_maxgen
  25. %% 遗传算子
  26. FitnV=myranking(Value_my);% 分配适应度值
  27. Chrom_my=myselect('rws',Chrom_my,FitnV,1);% 选择
  28. Chrom_my=mymutationga(Chrom_my,my_popsize,my_PM,my_N,lb,ub);% 种群变异,单点变异
  29. Chrom_my=mycrossga(Chrom_my,my_popsize,my_PC,my_N);% 种群交叉,2点交叉
  30. Value_my=mydecodingfun(Chrom_my,my_popsize);% 解码染色体
  31. %% 计算最优
  32. [vmin_my,indexmin_my]=min(Value_my);
  33. my_gen=my_gen+1;
  34. %% 记录最优
  35. if bestValue_my>vmin_my
  36. bestValue_my=vmin_my;%记录的最优值
  37. bestChrom_my=Chrom_my(indexmin_my,:);
  38. end
  39. my_tracemat(my_gen,2)=mean(Value_my);
  40. my_tracemat(my_gen,1)=bestValue_my;% 保留最优
  41. end
  42. disp('算法运行时间');
  43. runtime_ga_my=toc
  44. % 显示结果
  45. disp('遗传算法优化得到的最优目标函数值');
  46. bestValue_my
  47. disp('遗传算法优化得到的最优染色体');
  48. bestChrom_my
  49. figure;
  50. plot(my_tracemat(:,1),'r-','linewidth',1);
  51. hold on;
  52. plot(my_tracemat(:,2),'b-','linewidth',1);
  53. legend({'种群最优值','种群均值'},'fontname','宋体');
  54. xlabel('迭代次数','fontname','宋体');
  55. ylabel('目标函数值','fontname','宋体');
  56. title('遗传算法迭代曲线','fontname','宋体');

交叉函数 mycrossga.m

  1. function Chrom=mycrossga(Chrom,popsize,PC,N)
  2. % 种群交叉,2点交叉
  3. index100=randperm(popsize);
  4. long1=fix(popsize/2);
  5. set1=index100(1:long1);
  6. set2=index100(long1+1:long1*2);
  7. for i=1:long1
  8. a=rand;
  9. if a<PC%小于交叉率开始交叉
  10. index201=set1(i);
  11. index202=set2(i);
  12. R1=Chrom(index201,:);
  13. R2=Chrom(index202,:);
  14. rmat=randi([1,N],1,2);%
  15. r1=min(rmat);
  16. r2=max(rmat);
  17. S1=R1(r1:r2);%交叉位置的节点
  18. S2=R2(r1:r2);%交叉位置的节点
  19. R1(r1:r2)=S2;
  20. R2(r1:r2)=S1;
  21. %更新染色体
  22. Chrom(index201,:)=R1;
  23. Chrom(index202,:)=R2;
  24. end
  25. end

解码函数mydecodingfun.m

  1. function Value = mydecodingfun(Chrom,popsize)
  2. %解码染色体
  3. Value=zeros(popsize,1);
  4. for i=1:popsize
  5. x=Chrom(i,:);
  6. y=myfun(x);
  7. Value(i,1)=y;
  8. end

目标函数myfun.m

  1. function y=myfun(x)
  2. y=sum((x-0.5).^2);

初始染色体函数mygenchrome.m

  1. function Chrom=mygenchrome(popsize,N,lb,ub)
  2. % 建立种群
  3. Chrom=zeros(popsize,N);
  4. for i=1:popsize
  5. for j=1:N
  6. Chrom(i,j)=lb(j)+(ub(j)-lb(j))*rand(1,1);
  7. end
  8. end

染色体变异函数mymutationga.m

  1. function Chrom=mymutationga(Chrom,popsize,PM,N,lb,ub)
  2. % 种群变异,单点变异
  3. for i=1:popsize
  4. a=rand;
  5. if a<PM
  6. r=unidrnd(N);
  7. Chrom(i,r)=lb(r)+(ub(r)-lb(r))*rand(1,1);
  8. end
  9. end


 

分配适应度函数

  1. function FitnV = myranking(ObjV, RFun, SUBPOP);
  2. % Identify the vector size (Nind)
  3. [Nind,ans] = size(ObjV);
  4. if nargin < 2, RFun = []; end
  5. if nargin > 1, if isnan(RFun), RFun = []; end, end
  6. if prod(size(RFun)) == 2,
  7. if RFun(2) == 1, NonLin = 1;
  8. elseif RFun(2) == 0, NonLin = 0;
  9. else error('Parameter for ranking method must be 0 or 1'); end
  10. RFun = RFun(1);
  11. if isnan(RFun), RFun = 2; end
  12. elseif prod(size(RFun)) > 2,
  13. if prod(size(RFun)) ~= Nind, error('ObjV and RFun disagree'); end
  14. end
  15. if nargin < 3, SUBPOP = 1; end
  16. if nargin > 2,
  17. if isempty(SUBPOP), SUBPOP = 1;
  18. elseif isnan(SUBPOP), SUBPOP = 1;
  19. elseif length(SUBPOP) ~= 1, error('SUBPOP must be a scalar'); end
  20. end
  21. if (Nind/SUBPOP) ~= fix(Nind/SUBPOP), error('ObjV and SUBPOP disagree'); end
  22. Nind = Nind/SUBPOP; % Compute number of individuals per subpopulation
  23. % Check ranking function and use default values if necessary
  24. if isempty(RFun),
  25. % linear ranking with selective pressure 2
  26. RFun = 2*[0:Nind-1]'/(Nind-1);
  27. elseif prod(size(RFun)) == 1
  28. if NonLin == 1,
  29. % non-linear ranking
  30. if RFun(1) < 1, error('Selective pressure must be greater than 1');
  31. elseif RFun(1) > Nind-2, error('Selective pressure too big'); end
  32. Root1 = roots([RFun(1)-Nind [RFun(1)*ones(1,Nind-1)]]);
  33. RFun = (abs(Root1(1)) * ones(Nind,1)) .^ [(0:Nind-1)'];
  34. RFun = RFun / sum(RFun) * Nind;
  35. else
  36. % linear ranking with SP between 1 and 2
  37. if (RFun(1) < 1 | RFun(1) > 2),
  38. error('Selective pressure for linear ranking must be between 1 and 2');
  39. end
  40. RFun = 2-RFun + 2*(RFun-1)*[0:Nind-1]'/(Nind-1);
  41. end
  42. end;
  43. FitnV = [];
  44. % loop over all subpopulations
  45. for irun = 1:SUBPOP,
  46. % Copy objective values of actual subpopulation
  47. ObjVSub = ObjV((irun-1)*Nind+1:irun*Nind);
  48. % Sort does not handle NaN values as required. So, find those...
  49. NaNix = isnan(ObjVSub);
  50. Validix = find(~NaNix);
  51. % ... and sort only numeric values (smaller is better).
  52. [ans,ix] = sort(-ObjVSub(Validix));
  53. % Now build indexing vector assuming NaN are worse than numbers,
  54. % (including Inf!)...
  55. ix = [find(NaNix) ; Validix(ix)];
  56. % ... and obtain a sorted version of ObjV
  57. Sorted = ObjVSub(ix);
  58. % Assign fitness according to RFun.
  59. i = 1;
  60. FitnVSub = zeros(Nind,1);
  61. for j = [find(Sorted(1:Nind-1) ~= Sorted(2:Nind)); Nind]',
  62. FitnVSub(i:j) = sum(RFun(i:j)) * ones(j-i+1,1) / (j-i+1);
  63. i =j+1;
  64. end
  65. % Finally, return unsorted vector.
  66. [ans,uix] = sort(ix);
  67. FitnVSub = FitnVSub(uix);
  68. % Add FitnVSub to FitnV
  69. FitnV = [FitnV; FitnVSub];
  70. end

选择函数myselect.m

  1. function SelCh = myselect(SEL_F, Chrom, FitnV, GGAP, SUBPOP);
  2. % Check parameter consistency
  3. if nargin < 3, error('Not enough input parameter'); end
  4. % Identify the population size (Nind)
  5. [NindCh,Nvar] = size(Chrom);
  6. [NindF,VarF] = size(FitnV);
  7. if NindCh ~= NindF, error('Chrom and FitnV disagree'); end
  8. if VarF ~= 1, error('FitnV must be a column vector'); end
  9. if nargin < 5, SUBPOP = 1; end
  10. if nargin > 4,
  11. if isempty(SUBPOP), SUBPOP = 1;
  12. elseif isnan(SUBPOP), SUBPOP = 1;
  13. elseif length(SUBPOP) ~= 1, error('SUBPOP must be a scalar'); end
  14. end
  15. if (NindCh/SUBPOP) ~= fix(NindCh/SUBPOP), error('Chrom and SUBPOP disagree'); end
  16. Nind = NindCh/SUBPOP; % Compute number of individuals per subpopulation
  17. if nargin < 4, GGAP = 1; end
  18. if nargin > 3,
  19. if isempty(GGAP), GGAP = 1;
  20. elseif isnan(GGAP), GGAP = 1;
  21. elseif length(GGAP) ~= 1, error('GGAP must be a scalar');
  22. elseif (GGAP < 0), error('GGAP must be a scalar bigger than 0'); end
  23. end
  24. % Compute number of new individuals (to select)
  25. NSel=max(floor(Nind*GGAP+.5),2);
  26. % Select individuals from population
  27. SelCh = [];
  28. for irun = 1:SUBPOP,
  29. FitnVSub = FitnV((irun-1)*Nind+1:irun*Nind);
  30. ChrIx=feval(SEL_F, FitnVSub, NSel)+(irun-1)*Nind;
  31. SelCh=[SelCh; Chrom(ChrIx,:)];
  32. end
  33. % End of function

选择函数用轮盘赌子函数rws.m

  1. function NewChrIx = rws(FitnV,Nsel)
  2. % 轮盘赌选择
  3. [Nind,ans] = size(FitnV);
  4. cumfit = cumsum(FitnV);
  5. trials = cumfit(Nind) .* rand(Nsel, 1);
  6. Mf = cumfit(:, ones(1, Nsel));
  7. Mt = trials(:, ones(1, Nind))';
  8. [NewChrIx, ans] = find(Mt < Mf & ...
  9. [ zeros(1, Nsel); Mf(1:Nind-1, :) ] <= Mt);

程序结果如下:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/554875
推荐阅读
相关标签
  

闽ICP备14008679号