微分进化(Difference Evolution,DE)算法是一种优化算法,据称其比GA(遗传算法)等更为优秀。
借鉴网上实现的DE算法,用Matlab实现了对若干函数优化问题的解法,代码如下:
function [] = de_test
clear all;
close all;
clc;
%解:X = [0, 0, ...]
%nVar = 30
%dims: [-30, 30]
function fitness = sphere(vals)
prod = vals .* vals;
fitness = sum(prod, 2);
end
%f(x) = 1/4000 * sum^n_1(x_i)^2 - prod^n_1 * cos(x_i/sqrt(i)) + 1
%f* = 0, x* = [0, 0, ...];
%nVar = 30
%dims: [-600, 600]
function fitness = griewank(vals)
[h w] = size(vals);
p1 = vals.^2;
p1 = 1/4000 .* sum(p1, 2);
t = sqrt([1:w]);
p2 = vals ./ repmat(t, h, 1);
p2 = cos(p2);
p2 = prod(p2, 2);
fitness = p1 - p2 + 1;
end
%解: X = [1, 1, 1, ...]
function fitness = RosenBroek(vals)
[k n] = size(vals);
vals1 = vals(:, 1:n-1);
vals2 = vals(:, 2:n);
tmp = vals2 - vals1 .* vals1;
tmp = 100 * tmp .* tmp;
tmp1 = (vals1 - 1).^2;
fitness = sum(tmp, 2) + sum(tmp1, 2);
end
%许多局部最小值,最优解:X = [0, 0], 固定2个变量
function fitness = Rastrigin (X)
v = X.^2 - 10 .* cos(2 * pi .* X) + 10;
fitness = sum(v, 2);
%fitness = 20 + X(:, 1).^2 + X(:, 2).^2 - 10 .* (cos(2 * pi * X(:, 1)) + cos(2 * pi * X(:, 2)));
end
%参数
popSize = 100; % 群规模
F = 0.5;% 突变因子
C = 0.9;% 交叉率
iterTimes = 300; % 迭代次数
Run = 4; % 测试轮次
id = [1:popSize];
%结果
bestFit = 1e5; %设取最小值
bestGene = [];
for r = 1:Run %轮次
Func = r; % 测试适应度函数
switch Func
case 1
Func = @sphere;
Xmin = -100;
Xmax = 100;
nVar = 30;
case 2
Func = @griewank;
Xmin = -600;
Xmax = 600;
nVar = 2;
case 3
nVar = 2;
Func = @RosenBroek;
Xmin = -100;
Xmax = 100;
case 4
nVar = 2;
Func = @Rastrigin
Xmin = -5.12;
Xmax = 5.12;
end;
Func
tic;
%1.初始化种群
X = Xmin + rand(popSize, nVar) * Xmax;
%2.每轮迭代
for i = 1:iterTimes
X0 = X;
% F = 2 * (1 - (i-1)/iterTimes);
%个体突变得到V
for j = 1:popSize
ids = id;
ids(j) = [];
rids = randperm(popSize - 1, 3);
rids = ids(rids);
V = X(rids(1), :) + F * (X(rids(2), :) - X(rids(3), :));
%对V(j, :)值域检查
ids = find(V < Xmin);
if length(ids) > 0
V(ids) = Xmin;
end;
ids = find(V > Xmax);
if length(ids) > 0
V(ids) = Xmax;
end;
%对每个X和V的配对,进行交叉操作,结果存在U中
jrand = floor(rand() * nVar + 1); %必交叉项,保证至少一个交叉
for n = 1:nVar
R1 = rand();
if (R1 < C || n == jrand)
U = V; %保留子代基因
else
U = X(j, :); %保留父代基因
end
end
%在子代和父代间做选择运算
if Func(U) < Func(X(j, :))
Tr = U;
else
Tr=X(j, :);
end
% 更新种群基因
X(j,:) = Tr;
%计算新的适应度
fitness = Func(X(j,:));
%记录全局最优解
if fitness < bestFit
bestFit = fitness;
bestGene = X(j, :);
end;
end %结束个体更新
end
bestGene
bestFit
toc
end
end运行结果如下:
Func =
@de_test/sphere
bestGene =
Columns 1 through 15
-7.5570 -11.9099 9.9957 -37.8403 -17.9445 -7.1438 -21.4304 -33.6260 -22.1812 -66.1438 0.9014 -39.6724 -0.3175 -56.4815 26.5422
Columns 16 through 30
6.5446 -31.9653 -9.3640 -37.1629 -23.7325 2.7271 -6.3413 -21.3204 -13.1450 28.7402 -28.8170 -22.6226 10.9031 -16.6128 -14.7637
bestFit =
2.0583e+04 (从此结果看,算法效果不佳)
时间已过 2.285354 秒。
Func =
@de_test/griewank
bestGene =
1.0e-08 *
0.1702 0.1424
bestFit =
0
时间已过 3.337347 秒。
Func =
@de_test/RosenBroek
bestGene =
1.0e-08 *
0.1702 0.1424
bestFit =
0
时间已过 1.747765 秒。
Func =
@de_test/Rastrigin
Func =
@de_test/Rastrigin
bestGene =
1.0e-08 *
0.1702 0.1424
bestFit =
0
时间已过 1.403871 秒。