logo资料库

遗传算法解非线性方程组的Matlab程序.doc

第1页 / 共9页
第2页 / 共9页
第3页 / 共9页
第4页 / 共9页
第5页 / 共9页
第6页 / 共9页
第7页 / 共9页
第8页 / 共9页
资料共9页,剩余部分请下载后查看
遗传算法解非线性方程组的 Matlab 程序 程序用 MATLAB 语言编写。之所以选择 MATLB,是因为它简单,但又功能强大。写 1 行 MATLAB 程序,相当于写 10 行 C++程序。 在编写算法阶段,最好用 MATLAB 语言,算法验证以后,要进入工程阶段,再把它翻译成 C++语言。 本程序的算法很简单,只具有示意性,不能用于实战。 非线性方程组的实例在函数(2)nonLinearSumError1(x)中,你可以用这个实例做样子构造你自己待解的非线性方程组。 %注意:标准遗传算法的一个重要概念是,染色体是可能解的 2 进制顺序号,由这个序号在可能解的集合(解空间)中找到可能解 %程序的流程如下: %程序初始化,随机生成一组可能解(第一批染色体) %1: 由可能解的序号寻找解本身(关键步骤) %2:把解代入非线性方程计算误差,如果误差符合要求,停止计算 %3:选择最好解对应的最优染色体 %4:保留每次迭代产生的最好的染色体,以防最好染色体丢失 %5: 把保留的最好的染色体 holdBestChromosome 加入到染色体群中 %6: 为每一条染色体(即可能解的序号)定义一个概率(关键步骤) %7:按照概率筛选染色体(关键步骤) %8:染色体杂交(关键步骤) %9:变异 %10:到 1 %这是遗传算法的主程序,它需要调用的函数如下。 %由染色体(可能解的 2 进制)顺序号找到可能解: %(1)x=chromosome_x(fatherChromosomeGroup,oneDimensionSet,solutionSum); %把解代入非线性方程组计算误差函数:(2)functionError=nonLinearSumError1(x); %判定程是否得解函数:(3)[solution,isTrue]=isSolution(x,funtionError,solutionSumError); %选择最优染色体函数: %(4)[bestChromosome,leastFunctionError]=best_worstChromosome(fatherChromosomeGroup,functionError); %误差比较函数:从两个染色体中,选出误差较小的染色体 %(5)[holdBestChromosome,holdLeastFunctionError]... % =compareBestChromosome(holdBestChromosome,holdLeastFunctionError,... % bestChromosome,leastFuntionError) %为染色体定义概率函数,好的染色体概率高,坏染色体概率低 %(6)p=chromosomeProbability(functionError); %按概率选择染色体函数: %(7)slecteChromosomeGroup=selecteChromome(fatherChromosomeGroup,p); %父代染色体杂交产生子代染色体函数 %(8)sonChrmosomeGroup=crossChromosome(slecteChromosomeGroup,2); %防止染色体超出解空间的函数 %(9)chromosomeGroup=checkSequence(chromosomeGroup,solutionSum) %变异函数 %(10)fatherChromosomeGroup=varianceCh(sonChromosomeGroup,0.8,solutionN); %通过实验有如下结果: %1。染色体应当多一些
%2。通过概率选择染色体,在迭代早期会有效选出优秀的染色体,使解的误差迅速降低, %但随着迭代的进行,概率选择也会导致某种染色体在基因池中迅速增加,使染色体趋同, %这就减少了物种的多样性,反而难以逼近解 %3。不用概率选择,仅采用染色体杂交,采用保留优秀染色体,也可以得到解 %%%%%%%%%%%%%%%%%%%%%%%%程序开始运行 clear,clc;%清理内存,清屏 circleN=200;%迭代次数 format long %%%%%%%%%%%%%%%构造可能解的空间,确定染色体的个数、长度 solutionSum=4;leftBoundary=-10;rightBoundary=10; distance=1;chromosomeSum=500;solutionSumError=0.1; %solutionSum:非线性方程组的元数(待解变量的个数);leftBoundary:可能解的左边界; %rightBoundary:可能解的右边界;distance:可能解的间隔,也是解的精度 %chromosomeSum:染色体的个数;solveSumError:解的误差 oneDimensionSet=leftBoundary:distance:rightBoundary; %oneDimensionSet:可能解在一个数轴(维)上的集合 oneDimensionSetN=size(oneDimensionSet,2);%返回 oneDimensionSet 中的元素个数 solutionN=oneDimensionSetN^solutionSum;%解空间(解集合)中可能解的总数 binSolutionN=dec2bin(solutionN);%把可能解的总数转换成二进制数 chromosomeLength=size(binSolutionN,2);%由解空间中可能解的总数(二进制数)计算染色体的长度 %%%%%%%%%%%%%%%%程序初始化 %随机生成初始可能解的顺序号,+1 是为了防止出现 0 顺序号 solutionSequence=fix(rand(chromosomeSum,1)*solutionN)+1; for i=1:chromosomeSum%防止解的顺序号超出解的个数 if solutionSequence(i)>solutionN; solutionSequence(i)=solutionN; end end %染色体是解集合中的序号,它对应一个可能解 %把解的十进制序号转成二进制序号 fatherChromosomeGroup=dec2bin(solutionSequence,chromosomeLength); holdLeastFunctionError=Inf;%可能解的最小误差的初值 holdBestChromosome=0;%对应最小误差的染色体的初值 %%%%%%%%%%%%%%%%%%开始计算 circle=0; while circle
%%%%%%%%%%%%%2:把解代入非线性方程计算误差 functionError=nonLinearSumError1(x);%把解代入方程计算误差 [solution,minError,isTrue]=isSolution(x,functionError,solutionSumError); %isSolution 函数根据误差 functionError 判定方程是否已经解开,isTrue=1,方程得解。solution 是方程的解 if isTrue==1 '方程得解' solution minError circle return%结束程序 end %%%%%%%%%%%%%3:选择最好解对应的最优染色体 [bestChromosome,leastFunctionError]=best_worstChromosome(fatherChromosomeGroup,functionError); %%%%%%%%%%%%%4:保留每次迭代产生的最好的染色体 %本次最好解与上次最好解进行比较,如果上次最好解优于本次最好解,保留上次最好解; %反之,保留本次最好解。保留的最好染色体放在 holdBestChromosome 中 [holdBestChromosome,holdLeastFunctionError]... =compareBestChromosome(holdBestChromosome,holdLeastFunctionError,... bestChromosome,leastFunctionError); %circle %minError %solution %holdLeastFunctionError %%%%%%%%%%%%%%5:把保留的最好的染色体 holdBestChromosome 加入到染色体群中 order=round(rand(1)*chromosomeSum); if order==0 order=1; end fatherChromosomeGroup(order,:)=holdBestChromosome; functionError(order)=holdLeastFunctionError; %%%%%%%%%%%%%%%6:为每一条染色体(即可能解的序号)定义一个概率(关键步骤) %%%%%%%%%%%%%%%好的染色体概率高,坏的概率低。依据误差 functionError 计算概率 [p,trueP]=chromosomeProbability(functionError); if trueP =='Fail' '可能解严重不适应方程,请重新开始' return%结束程序 end %%%%%%%%%%%%%%%7:按照概率筛选染色体(关键步骤) %fa=bin2dec(fatherChromosomeGroup)%显示父染色体 %从父染体中选择优秀染色体 %selecteChromosomeGroup=selecteChromosome(fatherChromosomeGroup,p); %%%%%%%%%%%%%%%8:染色体杂交(关键步骤)
%sle=bin2dec(selecteChromosomeGroup)%显示选择出来的解的序号(染色体) %用概率筛选出的染色体 selecteChromosomeGroup 进行杂交,产生子代染色体 %sonChromosomeGroup=crossChromosome(selecteChromosomeGroup,2); %不用概率筛选出的染色体 selecteChromosomeGroup 进行杂交,而直接用上一代(父代)的 sonChromosomeGroup=crossChromosome(fatherChromosomeGroup,2); %cro=bin2dec(sonChromosomeGroup)%显示杂交后的子代染色体 sonChromosomeGroup=checkSequence(sonChromosomeGroup,solutionN);%检查杂交后的染色体是否越界 %%%%%%%%%%%%%%%9:变异 %不杂交直接变异 %fatherChromosomeGroup=varianceCh(fatherChromosomeGroup,0.1,solutionN); %杂交后变异 fatherChromosomeGroup=varianceCh(sonChromosomeGroup,0.1,solutionN); fatherChromosomeGroup=checkSequence(fatherChromosomeGroup,solutionN);%检查变异后的染色体是否越界 end 函数(1):由染色体(可能解的 2 进制)顺序号找到可能解 %这个函数找出染色体(可能解的序号)对应的可能解 x function x=chromosome_x(chromosomeGroup,oneDimensionSet,solutionSum) %chromosomeGroup:染色体,也是可能解的二进制序号 %oneDimensionSet:一维数轴上的可能解 %solutionSum:非线性方程组的元数,也就是待解方程中未知变量的个数 [row oneDimensionSetN]=size(oneDimensionSet); %oneDimensionSetN:一维数轴上可能解的个数 chromosomeSum=size(chromosomeGroup);%chromosomeSum:染色体的个数 xSequence=bin2dec(chromosomeGroup);%把可能解的二进制序号(染色体)转换成十进制序号 for i=1:chromosomeSum%i:染色体的编号 remainder=xSequence(i); for j=1:solutionSum dProduct=oneDimensionSetN^(solutionSum-j);%sNproduct: quotient=remainder/dProduct; remainder=mod(remainder,dProduct);%mod:取余函数 if remainder==0 oneDimensionSetOrder=quotient; %oneDimensionSetOrder:可能解在数轴上的序号 else oneDimensionSetOrder=fix(quotient)+1;%fix:取整函数 end if oneDimensionSetOrder==0 oneDimensionSetOrder=oneDimensionSetN; end x(i,j)=oneDimensionSet(oneDimensionSetOrder); end end
函数(2):把解代入非线性方程组计算绝对误差函数: function funtionError=nonLinearSumError1(X)%方程的解是-7,5,1,-3 funtionError=... [ abs(X(:,1).^2-sin(X(:,2).^3)+X(:,3).^2-exp(X(:,4))-50.566253390821)+... abs(X(:,1).^3+X(:,2).^2-X(:,4).^2+327)+... abs(cos(X(:,1).^4)+X(:,2).^4-X(:,3).^3-624.679868769613)+... abs(X(:,1).^4-X(:,2).^3+2.^X(:,3)-X(:,4).^4-2197) ]; 函数(3):判定程是否得解函数: %判断方程是否解开 function [solution,minError,isTrue]=isSolution(x,functionError,precision) [minError,xi]=min(functionError);%找到最小误差,最小误差所对应的行号 solution=x(xi,:); if minErrorleastFunctionError newLeastFunctionError=leastFunctionError; newBestChromosome=bestChromosome; else newLeastFunctionError=oldLeastFunctionError; newBestChromosome=oldBestChromosome; end 函数(6):为染色体定义概率函数,好的染色体概率高,坏染色体概率低 %根据待解的非线性函数的误差计算染色体的概率 function [p,isP]=chromosomeProbability(x_Error) InfN=sum(isinf(x_Error));%估计非线性方程计算的结果 NaNN=sum(isnan(x_Error));
if InfN>0 || NaNN>0 isP='Fail'; p=0; return else isP='True'; errorReciprocal=1./x_Error; sumReciprocal=sum(errorReciprocal); p=errorReciprocal/sumReciprocal;%p:可能解所对应的染色体的概率 end 函数(7):按概率选择染色体函数: function chromosome=selecteChromosome(chromosomeGroup,p) cumuP=cumsum(p);%累积概率,也就是把每个染色体的概率映射到 0~1 的区间 [chromosomeSum,chromosomeLength]=size(chromosomeGroup); for i=1:chromosomeSum%这个循环产生概率值 rN=rand(1); if rN==1 chromosome(i,:)=chromosomeGroup(chromosomeSum,:); elseif (0<=rN) && (rN
end if randChromosomeSequence2==0%防止产生 0 序号 randChromosomeSequence2=1; end if crossDot==0 || crossDot==1 sonChromosome(i*2-1,:)=fatherChromosome(randChromosomeSequence1,:); sonChromosome(i*2,:)=fatherChromosome(randChromosomeSequence2,:); else %执行两条染色体的交叉 sonChromosome(i*2-1,:)=fatherChromosome(randChromosomeSequence1,:); %把父染色体整条传给子染色体 sonChromosome(i*2-1,crossDot:chromosomeLength)=... fatherChromosome(randChromosomeSequence2,crossDot:chromosomeLength) %下一条父染色体上交叉点 crossDot 后的基因传给子染色体,完成前一条染色体的交叉 sonChromosome(i*2,:)=fatherChromosome(randChromosomeSequence2,:); sonChromosome(i*2,crossDot:chromosomeLength)... =fatherChromosome(randChromosomeSequence1,crossDot:chromosomeLength) end end case 2 %父染色体的第 i 号与第 chromosomeSum+1-i 号交叉 for i=1:chromosomeSum/2 crossDot=fix(rand(1)*chromosomeLength);%随机选择染色体的交叉点位 if crossDot==0 || crossDot==1 sonChromosome(i*2-1,:)=fatherChromosome(i,:); sonChromosome(i*2,:)=fatherChromosome(chromosomeSum+1-i,:); else %执行两条染色体的交叉 sonChromosome(i*2-1,:)=fatherChromosome(i,:);%把父染色体整条传给子染色体 sonChromosome(i*2-1,crossDot:chromosomeLength)... =fatherChromosome(chromosomeSum+1-i,crossDot:chromosomeLength); %下一条父染色体上交叉点 crossDot 后的基因传给子染色体,完成前一条染色体的交叉 sonChromosome(i*2,:)=fatherChromosome(chromosomeSum+1-i,:); sonChromosome(i*2,crossDot:chromosomeLength)... =fatherChromosome(i,crossDot:chromosomeLength); end end case 3 %父染色体的第 i 号与第 i+chromosomeSum/2 号交叉 for i=1:chromosomeSum/2 crossDot=fix(rand(1)*chromosomeLength);%随机选择染色体的交叉点位 if crossDot==0 || crossDot==1 sonChromosome(i*2-1,:)=fatherChromosome(i,:); sonChromosome(i*2,:)=fatherChromosome(i+chromosomeSum/2,:); else %执行两条染色体的交叉
sonChromosome(i*2-1,:)=fatherChromosome(i,:);%把父染色体整条传给子染色体 sonChromosome(i*2-1,crossDot:chromosomeLength)... =fatherChromosome(i+chromosomeSum/2,crossDot:chromosomeLength); %下一条父染色体上交叉点 crossDot 后的基因传给子染色体,完成前一条染色体的交叉 sonChromosome(i*2,:)=fatherChromosome(i+chromosomeSum/2,:); sonChromosome(i*2,crossDot:chromosomeLength)... =fatherChromosome(i,crossDot:chromosomeLength); end end end 函数(9):防止染色体超出解空间的函数 %检测染色体(序号)是否超出解空间的函数 function chromosome=checkSequence(chromosomeGroup,solutionSum) [chromosomeSum,chromosomeLength]=size(chromosomeGroup); decimalChromosomeSequence=bin2dec(chromosomeGroup); for i=1:chromosomeSum %检测变异后的染色体是否超出解空间 if decimalChromosomeSequence(i)>solutionSum chRs=round(rand(1)*solutionSum); if chRs==0 chRs=1; end decimalChromosomeSequence(i)=chRs; end end chromosome=dec2bin(decimalChromosomeSequence,chromosomeLength); 函数(10):变异函数 %基因变异.染色体群中的 1/10 变异。vR 是变异概率。solutionN 是解空间中全部可能解的个数 function aberranceChromosomeGroup=varianceCh(chromosomeGroup,vR,solutionN) [chromosomeSum,chromosomeLength]=size(chromosomeGroup); if chromosomeSum<10 N=1; else N=round(chromosomeSum/10); end if rand(1)>vR %变异操作 for i=1:N chromosomeOrder=round(rand(1)*chromosomeSum);%产生变异染色体序号 if chromosomeOrder==0 chromosomeOrder=1; end aberrancePosition=round(rand(1)*chromosomeLength);%产生变异位置 if aberrancePosition==0 aberrancePosition=1;
分享到:
收藏