【ALGO】启发式算法求解案例(2)

Demo1: EP

进化规划算法求解Knapsack问题
max ⁡ z = ∑ i = 1 n c i x i s . t . ∑ i = 1 n a i x i ≤ b \begin{aligned} \max z=\sum_{i=1}^n c_ix_i\\ s.t.\sum_{i=1}^n a_ix_i\leq b \end{aligned} maxz=i=1ncixis.t.i=1naixib
这是一个整数规划问题,为NP-hard.采用二进制编码的方法,变异规则:随机选取 i i i,如果 b − ∑ i = 1 n a i x i ≥ a i b-\sum_{i=1}^n a_ix_i\geq a_i bi=1naixiai,且 x i = 0 x_i=0 xi=0,则 x i = 1 x_i=1 xi=1;如果对所有的 i i i, b − ∑ i = 1 n a i x i < a i b-\sum_{i=1}^na_ix_i<a_i bi=1naixi<ai,则随机选取 j j j,令 x j = 0 x_j=0 xj=0.

EP code

function [maxx, maxf] = MLYEP2(func, popsize, iter_max)
        global fitall
        a=[198 30 167 130 35 20 105 196 94 126];
        b=546;
        nvar = length(a);
        q = round(0.7*popsize); % 设置进化策略的q值
        chome = zeros(popsize, nvar); %定义染色体
        for i=1:popsize
                chome(i, :)=rand(1, nvar)<0.5; % 初始化变量, 每个值为0-1变量,进行二进制编码
                chomeV(i, 1)=func(chome(i, :)); % 计算适应度函数值
        end
        
        [~, b1]=sort(chomeV, 'descend'); % 排序
        chome = chome(b1, :);
        chomeV = chomeV(b1);       
        maxx = chome(1, :);
        maxf = chomeV(1);
        
        % 迭代优化
        for i=1:iter_max
                for j=1:popsize
                        % 进行变异
                        newchome(j, :) = chome(j, :);
                        b1 = ceil(nvar*rand);
                        if b-newchome(j,:)*a'>=a(b1) & newchome(j, b1)==0 % 直接可以选择该物品
                                newchome(j, b1)=1;
                        else % 如果该物品不可以选择,考虑进行替换
                                s=0;
                                for k=1:nvar % 遍历所有分量,查看是否已经全部满足约束
                                        if b-newchome(j, k)*a(k)<a(k)
                                                s=s+1;
                                        end
                                end
                                if s==nvar % 如果已经全部满足约束,则随机将某个分量进行置0
                                        b2=ceil(nvar*rand);
                                        newchome(j, b2)=0;
                                end
                        end
                        newchomeV(j, 1)=func(newchome(j, :)); % 计算适应度
                end
                % 进行选择
                chome=EPSelect(chome, newchome, chomeV, newchomeV, q);
                for j=1:popsize
                        chomeV(j, 1) = func(chome(j, :));
                end
                % 筛选
                [~, b]=sort(chomeV, 'descend');
                chome = chome(b, :);
                chomeV = chomeV(b);
                if maxf<chomeV(1)
                        maxx=chome(1, :);
                        maxf=chomeV(1);
                end
                fitall(i)=mean(chomeV);
        end
end

function chome = EPSelect(old, new, oldF, newF, q)
        n = size(old, 1);
        total_chome = [old; new]; % 合并父代和子代
        total_F = [oldF; newF]; % 合并父代和子代的适应度函数
        competitor = randperm(2*n);
        for i=1:2*n
                score = 0;
                for j=1:q
                        if total_F(i)>total_F(competitor(j))
                                score=score+1;
                        end
                end
                templ(i)=score;
        end
        [~, b] = sort(templ, 'descend');
        total_chome=total_chome(b, :);
        chome=total_chome(1:n, :);
end

IFt

GA code

%% GA
fitall_ga = zeros(1, iter_max);
A = ones(1, 10);
b = 10;
ops = optimoptions('ga', 'Generations', iter_max, 'PopulationSize', 20, 'OutputFcn', @myout);
[minx_ga, minf_ga, ~, output, population, scores]=ga(@obj_func_8x, 10,  A, b, [], [], LB, UB,[],[1,2,3,4,5,6,7,8,9,10],ops);
maxx_ga = minx_ga;
maxf_ga = -minf_ga;
plot(1:output.generations, -fitall_ga(:, 1:output.generations));
grid on;

GA

Demo2: 考虑基数约束的投资组合

min ⁡ x ′ Σ x s . t . { ∑ x i = 1 x i ≥ 0 n o r m ( x , 0 ) ≥ 4 n o r m ( x , 0 ) ≤ 8 x i ≥ 0.1 , x ≠ 0 x i ≤ 0.7 , x ≠ 0 \begin{aligned} &\min x'\Sigma x\\ &s.t. \begin{cases} \sum x_i=1\\ x_i\geq 0\\ norm(x, 0)\geq 4\\ norm(x, 0)\leq 8\\ x_i\geq 0.1, x\neq 0\\ x_i\leq 0.7, x\neq 0 \end{cases} \end{aligned} minxΣxs.t.xi=1xi0norm(x,0)4norm(x,0)8xi0.1,x=0xi0.7,x=0

Code

global n Sigma
n = 10;
T = 30;
R = randn(T, n); % 表示收益率矩阵
Sigma = cov(R);
A1 = [ones(1, n), zeros(1,n)];
A2 =[zeros(1, n), ones(1, n)];
A = [A1; A2; mean(R), zeros(1, n)];
b = [1.00; n; 0.01];
LB=zeros(1, 2*n);
UB=ones(1, 2*n);
ops = optimoptions('ga', 'Generations', iter_max, 'PopulationSize', 20, 'OutputFcn', @myout);
[minport, ~] = ga(@obj_func_port,20, A, b, [], [], LB, UB, @mycon, [11:20], ops);
x_port = minport(1:n);
y_port = minport(n+1:2*n);
plot(1:output.generations, fitall_ga(:, 1:output.generations));
grid on;

fit

Demo3: 进化策略求解

使用进化策略求解下列函数的最优值
max ⁡ f ( x , y ) = 200 − ( x 2 + y − 11 ) 2 − ( y 2 + x − 7 ) 2 \max f(x, y)=200-(x^2+y-11)^2-(y^2+x-7)^2 maxf(x,y)=200(x2+y11)2(y2+x7)2
该函数为线性不可分的二维多峰函数,考虑使用进化策略求解.

重组算子

重组是将参与重组的父代染色体上的基因进行交换,主要的重组方法有三种:离散重组,中间重组和混杂重组.

变异算子

进化策略的变异是在旧的个体的基础上增加一个正态分布的随机数,从而产生新的个体. 设 X X X为染色体个体的目标变量,存在 L L L个分量, σ \sigma σ为高斯变异的标准差,在 t + 1 t+1 t+1时有:
X ( t + 1 ) = X ( t ) + N ( 0 , σ ) X(t+1)=X(t)+N(0, \sigma) X(t+1)=X(t)+N(0,σ)

选择算子

选择算子为进化规定了方向,只有具有高适应度的个体才有机会进行进化繁殖,在进化策略中,选择过程是确定的.
( μ + λ ) − (\mu+\lambda)- (μ+λ)ES策略中,在原有的 μ \mu μ个父代个体以及新产生的 λ \lambda λ个新子代个体中,再择优选择 μ \mu μ个个体作为下一代群体,即精英机制.该机制对子代数量没有限制,可以最大程度保留具有最佳适应度的个体,但是该方法可能增加计算量,降低收敛效率.
( μ , λ ) (\mu, \lambda) (μ,λ)-ES策略中,选择机制依赖于出生过生的基础上的,因此要求 μ ≥ λ \mu\geq \lambda μλ,在这个机制中,只有最新产生的子代才能加入到选择机制中,从 λ \lambda λ中选择最好的 μ \mu μ的个体,作为下一代的父代,而适应度较低的 λ − μ \lambda-\mu λμ个个体被放弃.

扫描二维码关注公众号,回复: 13479588 查看本文章

code

function [val_x, val_f] = MLYES(func, popsize, iter_max, LB, UB)
% 进化策略算法
nvar=size(LB, 1);
chome = zeros(popsize, nvar);
chomesigma=zeros(popsize, nvar);
lambda=7*popsize; %(mu-lambda)
% 初始化
for i=1:popsize
        for j=1:nvar
                chome(:, j)=unifrnd(LB(j), UB(j), popsize, 1);
                chomesigma(:, j)=3.0.*ones(popsize, 1);
        end
        chomeV(i, 1)=func(chome(i, :));
end
% 排序
[~, b]=sort(chomeV);
val_x = chome(b(1),:);
val_f = chomeV(b(1), 1);
for i=1:iter_max
        [newchome, newsigma]=ESrecombination(chome, chomesigma, lambda, 1); % 重组算子
        [newchome, newsigma]=ESmutation(newchome, newsigma, LB, UB); % 变异算子
        for j=1:popsize
                newchomeV(j, 1)=func(newchome(j, :)); % 计算适应度函数值
        end
        [chome, chomesigma]=ESselect(chome, newchome, chomeV, newchomeV, chomesigma, newsigma, 1); % 选择算子
        for j=1:popsize
                chomeV(j, 1)=func(chome(j, :));
        end
        [~, b]=sort(chomeV);
        if val_f>chomeV(b(1), 1)
                val_x=chome(b(1), :);
                val_f=chomeV(b(1), 1);
        end
end
end

% 重组算子
function [new, newsigma]=ESrecombination(oldchome, oldsigma, lambda, type)
[num, nvar]=size(oldchome);
temp = ceil(num*rand); % 随机选择一个父代
for i=1:lambda
        temp1 = ceil(num.*rand(1, 2)); % 产生2个随机位置
        switch type
                case 1   % 离散重组
                        mask = round(rand(1, nvar)); % 产生一组掩码
                        if all(mask-1) || all(mask) % 如果编码为全部0或者全部1的情况
                                mask = round(rand(1, nvar));
                        end
                        for j=1:nvar
                                if mask(j)==0
                                        new(i,j)=oldchome(temp1(1),j);
                                        newsigma(i,j)=oldsigma(temp1(1), j);
                                else
                                        new(i,j) = oldchome(temp1(2), j);
                                        newsigma(i, j)=oldsigma(temp1(2), j);
                                end
                        end
                case 2 % 中间重组
                        for j=1:nvar
                                new(i, j)=(oldchome(temp(1), j)+oldchome(temp(2), j))/2;
                                newsigma(i, j)=(oldsigma(temp(1), j)+oldsigma(temp1(2), j))/2;
                        end
                case 3 % 混杂重组
                        temp2=ceil(num*rand);
                        while temp2==temp
                                temp2=ceil(num*rand);
                        end
                        for j=1:nvar
                                new(i, j)=(oldchome(temp, j)+oldchome(temp2, j))/2;
                                newsigma(i, j)=(oldsigma(temp, j)+oldsigma(temp2, j))/2;
                        end
        end
end
end

% 变异算子
function [new, newsigma]=ESmutation(oldchome, oldsigma, LB, UB)
        [popsize, nvar]=size(oldchome);
        for j=1:popsize
                a = randn;
                for k=1:nvar
                        newsigma(j, k)=oldsigma(j, k)*exp(a+randn);
                        new(j, k) = oldchome(j, k)+normrnd(0, newsigma(j, k),1 , 1);
                        new(j, k) = boundtest(new(j, k), LB(k), UB(k)); % 进行边界检测
                end
        end
end

% 选择算子
function [chome, newsigma]=ESselect(old, new, oldF, newF, oldsigma, newsigma, type)
        num=size(old, 1);
        total_chome = [old; new];
        total_F = [oldF; newF];
        total_sigma = [oldsigma; newsigma];
        if type==1 % (N+lambda)方式
               [~, b]=sort(total_F);
               total_chome = total_chome(b, :);
               total_sigma = total_sigma(b, :);
               chome = total_chome(1: num, :);
               newsigma = total_sigma(1:num, :);
        elseif type==2 % (N, lambda)
                if size(new, 1)<num
                        error('新个体的数目太少');
                end
                [~, b] = sort(newF);
                new = new(b, :);
                newsigma = newsigma(b, :);
                chome = new(1:num, :);
                newsigma=newsigma(1:num, :);
        end
end

% 边界检测
function y=boundtest(x, LB, UB)
        if x>=UB
                y=LB+(x-UB);
        elseif x<=LB
                y=UB-(LB-x);
        else
                y=x;
        end
end

求解非线性方程组
{ sin ⁡ ( x + y ) − 6 exp ⁡ ( x ) y = 0 5 x 2 − 4 y − 100 = 0 \begin{cases} \sin(x+y)-6\exp(x)y=0\\ 5x^2-4y-100=0 \end{cases} { sin(x+y)6exp(x)y=05x24y100=0
使用进化策略求解的关键在于设计合适的适应度函数,令 e = ∑ ϕ i 2 , y = 1 1 + e e=\sum\phi_i^2, y=\frac{1}{1+\sqrt{e}} e=ϕi2,y=1+e 1,使用上述进化代码计算

%% 进化策略求解函数最优值2
LB = -10*ones(2, 1);
UB = 10*ones(2, 1);
for i=1:10
        fprintf('round... %d\n', i);
        [val_x(i, :), val_f(i)]=MLYES(@obj_func_10, 300, 500, LB, UB);
end

猜你喜欢

转载自blog.csdn.net/qq_18822147/article/details/117625718