Navigator
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=1∑ncixis.t.i=1∑naixi≤b
这是一个整数规划问题,为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 b−∑i=1naixi≥ai,且 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 b−∑i=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
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;
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=1xi≥0norm(x,0)≥4norm(x,0)≤8xi≥0.1,x=0xi≤0.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;
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+y−11)2−(y2+x−7)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 λ−μ个个体被放弃.
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=05x2−4y−100=0
使用进化策略求解的关键在于设计合适的适应度函数,令 e = ∑ ϕ i 2 , y = 1 1 + e e=\sum\phi_i^2, y=\frac{1}{1+\sqrt{e}} e=∑ϕi2,y=1+e1,使用上述进化代码计算
%% 进化策略求解函数最优值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