非支配排序遗传算法(NSGA-II)是多目标优化领域的里程碑式算法,由Deb等人于2002年提出。其核心思想是通过非支配排序和拥挤度距离计算,在进化过程中维持解的多样性和收敛性。与传统的单目标优化不同,多目标优化不存在唯一最优解,而是存在一组无法相互支配的Pareto最优解集。
非支配排序是NSGA-II区别于普通遗传算法的核心特征。其数学定义为:对于最小化问题,解x1支配解x2当且仅当:
在MATLAB实现中,我们通过两两比较完成排序:
matlab复制function [fronts] = non_dominated_sort(pop)
fronts = {};
while ~isempty(pop)
front = [];
for i = 1:length(pop)
dominated = false;
for j = 1:length(pop)
if dominates(pop(j), pop(i))
dominated = true;
break;
end
end
if ~dominated
front = [front, pop(i)];
end
end
fronts{end+1} = front;
pop = setdiff(pop, front);
end
end
实际工程应用中,建议使用矩阵运算替代双重循环以提升性能,特别是在处理大规模种群时。
为保证解集在Pareto前沿上的均匀分布,NSGA-II引入了拥挤度距离指标。对于每个目标函数,先对解集按目标值排序,边界解赋予无限距离,中间解的拥挤度距离为相邻解目标值差的归一化累加:
matlab复制function pop = crowding_distance(pop, fronts)
for f = 1:length(fronts)
front = fronts{f};
for m = 1:num_objectives
[~, idx] = sort([front.(['f',num2str(m)])]);
front(idx(1)).distance = inf;
front(idx(end)).distance = inf;
for i = 2:length(front)-1
front(idx(i)).distance = front(idx(i)).distance + ...
(front(idx(i+1)).(m) - front(idx(i-1)).(m)) / ...
(max([front.(m)]) - min([front.(m)]));
end
end
fronts{f} = front;
end
end
注意:拥挤度计算需要先对各目标值进行归一化处理,避免不同量纲的目标函数导致距离计算偏差。
在提供的示例代码中,以下参数直接影响算法性能:
matlab复制pop_size = 100; % 种群规模
max_gen = 200; % 最大迭代次数
cross_rate = 0.8; % 交叉概率
mutate_rate = 0.3; % 变异概率
elite_ratio = 0.4; % 精英保留比例
参数调优经验:
对于两目标优化问题,标准实现如下:
matlab复制function [f1, f2] = obj_func(x)
% 目标函数1:最小化x1平方与(x2-1)平方和
f1 = x(:,1).^2 + (x(:,2)-1).^2;
% 目标函数2:最小化(x1-1)平方与x2平方和
f2 = (x(:,1)-1).^2 + x(:,2).^2;
end
扩展为三目标时,只需增加输出参数:
matlab复制function [f1, f2, f3] = obj_func_3obj(x)
f1 = x(:,1).^2 + x(:,2).^2;
f2 = (x(:,1)-1).^2 + (x(:,2)-1).^2;
f3 = (x(:,1)+1).^2 + (x(:,2)+1).^2;
end
对于带约束的问题,常用罚函数法处理。以下示例展示非线性约束的处理:
matlab复制function [f1, f2] = constrained_obj(x)
[f1, f2] = original_obj(x);
% 约束条件:x1 + x2 ≥ 1
violate = max(0, 1 - (x(:,1) + x(:,2)));
% 惩罚项系数需要根据目标函数尺度调整
penalty = 1000 * sum(violate, 2);
f1 = f1 + penalty;
f2 = f2 + penalty;
end
当目标函数由神经网络预测时,可采用持久变量避免重复加载模型:
matlab复制function [f1, f2] = nn_obj(x)
persistent net;
if isempty(net)
net = load('trained_model.mat'); % 加载预训练模型
end
% 批处理预测提升效率
pred = predict(net, x);
f1 = pred(:,1);
f2 = pred(:,2);
end
重要提示:神经网络预测可能存在噪声,建议在目标函数中添加平滑处理,避免算法陷入局部震荡。
标准二维Pareto前沿绘制方法:
matlab复制function plot_pareto(pareto_front)
scatter([pareto_front.f1], [pareto_front.f2], 'filled');
xlabel('Objective 1');
ylabel('Objective 2');
title('Pareto Optimal Front');
grid on;
% 添加算法信息标注
text(0.1, 0.9, ['NSGA-II with ', num2str(length(pareto_front)), ' solutions'], ...
'Units', 'normalized');
end
对于三目标问题,可使用三维散点图:
matlab复制scatter3([pareto_front.f1], [pareto_front.f2], [pareto_front.f3], 'filled');
常用量化指标包括:
HV指标计算示例:
matlab复制function hv = hypervolume(pareto_front, ref_point)
points = [[pareto_front.f1]', [pareto_front.f2]'];
hv = hv_contribution(points, ref_point);
end
现象:Pareto前沿未形成典型分布
解决方案:
现象:解集中在部分区域
解决方法:
当决策变量超过50维时:
对于工业级应用,建议采用混合策略:
matlab复制if num_vars > 50
% 启用降维预处理
[reduced_x, mapping] = pca(x, 'NumComponents', 30);
% 在降维空间执行优化
pareto_front = nsga3(@(x)obj_func(reshape(x*mapping.T, [], num_vars)));
else
% 标准NSGA-II流程
pareto_front = nsga2(@obj_func);
end
以经典的减速器设计为例,展示NSGA-II在工程中的应用:
优化目标:
约束条件:
MATLAB实现框架:
matlab复制function [f1, f2, f3] = gearbox_obj(x)
% 计算各目标
f1 = calculate_weight(x);
f2 = calculate_transmission_error(x);
f3 = -calculate_efficiency(x); % 转换为最小化问题
% 处理约束
[g1, g2, g3] = constraints(x);
violate = max(0, [g1, g2, g3]);
% 惩罚项
penalty = 1e4 * sum(violate);
f1 = f1 + penalty;
f2 = f2 + penalty;
f3 = f3 + penalty;
end
针对机械设计问题的特殊调整:
matlab复制lb = [10, 0.5, 20, ...]; % 各参数下限
ub = [50, 2.0, 60, ...]; % 各参数上限
经过200代优化后,可获得一组满足各项约束的Pareto最优设计方案,工程师可根据具体需求从中选择最合适的方案。