遗传算法求解非线性规划

通常非线性整数规划是一个具有指数复杂度的NP问题。如果约束较为复杂,MATLAB优化工具箱和一些优化软件如lingo等,常常无法应用,即使能应用也不能给出一个较为令人满意的解。这时就需要针对问题设计专门的优化算法。

将遗传算法应用于非线性规划,是提高最优化质量改善收敛效果的有效途径。下述遗传算法在非线性规划中的具体应用,设计并实现求解非线性规划问题的遗传算法。

例 标准遗传算法的一个重要 概念是染色体是可能解的二进制顺序号,由这个序号在可能解的集合(解空间)中找到可能解。运用遗传算法求解设定的非线性方程组。

分析:这是遗传算法由染色体(可能解的二进制)顺序号找到可能解,把解代入设定的非线性方程组计算误差函数,判定方程组是否有解函数,选择最优染色体函数。

解:遗传算法程序的流程如下:

  1. 程序初始化,随机生成一组可能解(第一批染色体);
  2. 由可能解的序号寻找解本身;
  3. 把解代人非线性方程计算误差,如果误差符合要求,停止计算;
  4. 选择最优解对应的最优染色体;
  5. 保留每次迭代产生的最优染色体,以防最优染色体丢失:
  6. 把保留的最优染色体holdBestChromosome加入到染色体群中;
  7. 为每一条染色体(即可能解的序号)定义一个概率;
  8. 按照概率筛选染色体;
  9. 染色体杂交;
  10. 变异。

主函数

%主函数%
clc;
clear all;
circleN = 200;   %迭代次数
format long
%%%%%%%构造可能解的空间,确定染色体的个数、长度%%%%%%
solutionSum = 4;
leftBoundary= -10;
rightBoundary = 10;
distance= 1;
chromosomeSum = 500;    %染色体的个数
solutionSumError = 0.1; %解的误差

oneDimensionSet =leftBoundary:distance:rightBoundary;

oneDimensionSetN = size(oneDimensionSet,2); %返回oneDimensionSet中的元素个数
solutionN = oneDimensionSetN^solutionSum;   %解空间(解集合)中可能解的总数
binSolutionN = dec2bin(solutionN) ;         %把可能解的总数转换成二进制数
chromosomeLength = size( binSolutionN,2);   %由解空间中可能解的总数(二进制数)计算染色体的长度
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%程序初始化%%%%%%%%%%%%%%%%%%
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 < circleN            %开始达代求解
    circle = circle+1;           %记录迭代次数
%%%%%%%%%%%%%由可能解的序号寻找解本身%%%%%%%%%%%%%%%
x = chromosome_x(fatherChromosomeGroup,oneDimensionSet,solutionSum);
%%%%%%%%%%%%%把解代入非线性方程计算误差%%%%%%%%%%%%%
functionError = nonLinearSumError1(x);  %把解代入方程计算误差
[solution, minError, isTrue] = isSolution( x, functionError, solutionSumError);
if  isTrue == 1
        disp('方程得解')
        disp(solution)
        disp(minError)
        disp(circle)
    return      %站束程序
end
%%%%%%%%%%%选择最优解对应的最优染色体%%%%%%%%%%%%%
[bestChromosome, leastFunctionError] = best_worstChromosome( fatherChromosomeGroup,functionError);
%%%%%%%%%%%保留每次选代产生的最优染色体%%%%%%%%%%%
[holdBestChromosome, holdLeastFunctionError]...
= compareBestChromosome(holdBestChromosome,holdLeastFunctionError,...
bestChromosome,leastFunctionError);
%%%%%%%%%%%把保留的最优染色体加入到染色体群中%%%%%%
order = round(rand(1) * chromosomeSum);
if order == 0
   order = 1;
end
fatherChromosomeGroup(order,:) = holdBestChromosome;
functionError(order) = holdLeastFunctionError; 
%%%%%%%%%%%%%为每一条染色体,即可能解的序号定义一个概率%%%%%%%%
[p,trueP] = chromosomeProbability(functionError);
if trueP == 'Fail'
    disp( '可能解严重不适应方程,请重新开始');
    return      %结束程序
end
%%%%%%%%%%%%%按照概率筛选染色体%%%%%%%%%%
    fa = bin2dec(fatherChromosomeGroup);    %显示父染色体
%从父染体中选择优秀染色体
    selecteChromosomeGroup = selecteChromosome(fatherChromosomeGroup,p);
%%%%%%%%%%%%%染色体杂交%%%%%%%%%%%
    sle = bin2dec(selecteChromosomeGroup);
    sonChromosomeGroup = crossChromosome(selecteChromosomeGroup, 2);
    sonChromosomeGroup = crossChromosome(fatherChromosomeGroup, 2);
    sonChromosomeGroup = checkSequence( sonChromosomeGroup, solutionN);
%检查杂交后的染色体是否越界
%%%%%%%%%%杂交后变异%%%%%%%%%%
    fatherChromosomeGroup = varianceCh(sonChromosomeGroup, 0.1, solutionN);
    fatherChromosomeGroup = checkSequence(fatherChromosomeGroup ,solutionN);    %检查变异后的染色体是否越界
end

子函数

%由染色体(可能解的二进制)顺序号找到可能解
%这个函数找出染色体(可能解的序号)对应的可能解x
function x = chromosome_x( chromosomeGroup, oneDimensionSet, solutionSum )
%chromosomeGroup:染色体,也是可能解的二进制序号
%oneDinensionSet:一维数轴上的可能解
%solutionSum:非线性方程组的元数,也就是待解方程中未知变量的个数
[~, oneDimensionSetN] = size(oneDimensionSet);
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;
        else
            oneDimensionSetOrder = fix(quotient) + 1;       %fix:取整函数
        end
        if oneDimensionSetOrder == 0
            oneDimensionSetOrder = oneDimensionSetN;
        end
        x(i,j) = oneDimensionSet(oneDimensionSetOrder);
    end
end
end
%把解代入非线性方程组计算绝对误差函数
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)
];
end
%判定程序是否得解函数
function [ solution, minError, isTrue] = isSolution( x, functionError, precision)
[minError, xi]= min( functionError);    %找到最小误差,最小误差所对应的行号
solution= x(xi,:);
if minError < precision
    isTrue= 1;
else
    isTrue= 0;
end
end

%选择最优染色体函数
%找出最小误差所对应的最优染色体,最大误差所对应的最环染色体
function [ bestChromosome, leastFunctionError] = best_worstChromosome( chromosomeGroup,functionError)
[leastFunctionError, minErrorOrder] = min( functionError);
bestChromosome = chromosomeGroup( minErrorOrder, :);
end
%误差比较函数:从两个染色体中选出误差较小的染色体保留下来
function [newBestChromosome, newLeastFunctionError]...
= compareBestChromosome(oldBestChromosome, oldLeastFunctionError,...
bestChromosome, leastFunctionError)
if oldLeastFunctionError > leastFunctionError
    newLeastFunctionError = leastFunctionError;
    newBestChromosome = bestChromosome;
else
    newLeastFunctionError = oldLeastFunctionError;
    newBestChromosome = oldBestChromosome;
end

%按概率选择染色体函数
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 < cumuP(1))
        chromosome(i,:) = chromosomeGroup(1,:); %1条染色体被选中
    else
        for j = 2:chromosomeSum          %这个循环确定第1条以后的哪一条染色体被选中
            if (cumuP(j-1) <= rN) && (rN < cumuP(j))
                chromosome(i, :) = chromosomeGroup(j,:);
            break
            end
        end
    end
end
end

%父代染色体杂交产生子代染色体函数
function sonChromosome = crossChromosome( fatherChromosome, parameter)
[chromosomeSum, chromosomeLength] = size( fatherChromosome);
%chromosomeSum:染色体的条数; chromosomeLength:染色体的长度
switch parameter
    case 1      %随机选择父染色体进行交叉重组
    for i= 1:chromosomeSum/2
        crossDot = fix(rand(1) * chromosomeLength); %随机选择染色体的交叉点位
        randChromosomeSequencel = round( rand(1) * chromosomeSun);
        %随机产生第1条染色体的序号
        randChromosomeSequence2 = round(rand(1) * chromosomeSum);
        %随机产生第2条染色体的序号,这两条染色体要进行杂交
        if randChromosomeSequencel == 0     %防止产生0序号
            randChromosomeSequencel = 1;
        end
        if randChromosoneSequence2 == 0     %防止产生0序号
            randChromosomeSequence2 = 1;
        end
        if crossDot == 0 || crossDot == 1
            sonChromosome(i*2-1,:)= fatherChromosome( randChromosomeSequencel,:);
            sonChromosome(i*2, :) = fatherChromosome( randChromosomeSequence2,:);
        else
            %执行两条染色体的交叉
            sonChromosome(i*2-1,:) = fatherChromosome( randChromosomeSequencel,:);
            %把父染色体整条传给子染色体
            sonChromosome(i*2- 1, crossDot:chromosomeLength) = ...
            fatherChromosome( randChromosomeSequence2, crossDot :chromosomeLength);
            %下一条父染色体上交叉点crossDot后的基固传给子染色体,完成前一条染色体的交叉
            sonChromosome(i*2,:) = fatherChromosome( randChromosomeSequence2,:); 
            sonChromosome(i*2, crossDot : chrcmosomeLength)...
            = fatherChromosome(randChromosomeSequencel, crossDot :chromosomeLength);
        end   
    end
    case 2             %父染色体的第1号与第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(1*2-1,:) = fatherChromosome(1,:); %把父染色体整条传给子染色体
        sonChromosome(i*2-1, crossDot : chromosomeLength)...
        = fatherChromosome(i +chromosoneSua/2, crossDot : chromosomeLength);
        %下一条父染色体上交叉点crossDot后的基因传给子染色体,完成前一条染色体的交叉
        sonChronosone(i*2,:) = fatherChromosome(i +chromosomeSun/2, :);
        sonChromosome(i*2, crossDot : chromosomeLength)...
        = fatherChromosome(i, crossDot : chromosomeLength);
    end  
    end
end
end

%防止染色体超出解空间的函数
%检测染色体(序号)是否超出解空间的函数
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);
end

%变异函数
%基因变异。染色体群中的1/10变异,R是变异概率。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;
        end
        if chromosomeGroup(chromosomeOrder, aberrancePosition) == '1'
            chromosomeGroup( chromosomeOrder, aberrancePosition)='0';   %变异
        else
        chromosomeGroup( chromosomeOrder, aberrancePosition)='1';       %变异
        end    
    end
    aberranceChromosomeGroup = chromosomeGroup;
    else
        aberranceChromosomeGroup = chromosomeGroup;
    end
end

%为染色体定义概率函数,好染色体概率高,坏染色体概率低
%根据待解的非线性函数的误差计算染色体的概率
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
end

遗传算法求解非线性规划_第1张图片
即迭代137次,方程的解为[- 7,5,1,-3],解的误差为5. 471179065352771e- 13。

你可能感兴趣的:(遗传算法,matlab,matlab非线性规划,matlab,算法)