NSGA-II自定义优化函数MATLAB实现

一、NSGA-II算法核心原理

1.1 算法特点

  • 非支配排序:将种群分层,优先选择非支配解

  • 拥挤度计算:保持种群多样性

  • 精英保留:结合父代和子代选择最优解

  • 多目标优化:同时优化多个相互冲突的目标

1.2 算法流程

graph TD A[初始化种群] --> B[评估目标函数] B --> C[非支配排序] C --> D[计算拥挤度] D --> E[选择操作] E --> F[交叉操作] F --> G[变异操作] G --> H[合并种群] H --> I[环境选择] I -->|满足终止条件| J[输出Pareto前沿] I -->|否则| B

二、NSGA-II自定义优化函数实现

2.1 主函数代码

function [pop, F, front, crowding] = nsga2_custom(fun, nVar, varMin, varMax, nPop, maxGen, params)
    % NSGA-II多目标优化算法
    % 输入:
    %   fun: 目标函数句柄 (返回行向量)
    %   nVar: 变量个数
    %   varMin: 变量最小值 (标量或向量)
    %   varMax: 变量最大值 (标量或向量)
    %   nPop: 种群大小
    %   maxGen: 最大迭代次数
    %   params: 算法参数字典
    % 输出:
    %   pop: 最终种群 (nPop×nVar)
    %   F: 目标函数值 (nPop×nObj)
    %   front: 非支配前沿 (nPop×1)
    %   crowding: 拥挤度 (nPop×1)
    
    % 默认参数设置
    if nargin < 7
        params = struct();
    end
    if ~isfield(params, 'pc'), params.pc = 0.9; end       % 交叉概率
    if ~isfield(params, 'pm'), params.pm = 1/nVar; end    % 变异概率
    if ~isfield(params, 'eta_c'), params.eta_c = 15; end   % 交叉分布指数
    if ~isfield(params, 'eta_m'), params.eta_m = 20; end   % 变异分布指数
    if ~isfield(params, 'show_progress'), params.show_progress = true; end
    
    % 初始化种群
    pop = initializePopulation(nPop, nVar, varMin, varMax);
    
    % 主循环
    for gen = 1:maxGen
        % 评估目标函数
        F = evaluatePopulation(fun, pop);
        
        % 非支配排序
        [front, rank] = nonDominationSort(F);
        
        % 计算拥挤度
        crowding = crowdingDistance(F, front);
        
        % 选择父代
        parents = tournamentSelection(pop, front, crowding, nPop);
        
        % 交叉和变异
        offspring = geneticOperators(parents, params, varMin, varMax);
        
        % 评估子代
        F_offspring = evaluatePopulation(fun, offspring);
        
        % 合并种群
        combined_pop = [pop; offspring];
        combined_F = [F; F_offspring];
        
        % 环境选择
        [pop, F, front, crowding] = environmentalSelection(combined_pop, combined_F, nPop);
        
        % 显示进度
        if params.show_progress && mod(gen, 10) == 0
            fprintf('NSGA-II: Generation %d/%d, Pareto Front Size: %d\n', ...
                    gen, maxGen, sum(front == 1));
        end
    end
    
    % 最终结果排序
    [front, rank] = nonDominationSort(F);
    crowding = crowdingDistance(F, front);
end

2.2 种群初始化函数

function pop = initializePopulation(nPop, nVar, varMin, varMax)
    % 初始化种群
    % 输入:
    %   nPop: 种群大小
    %   nVar: 变量个数
    %   varMin: 变量最小值 (标量或向量)
    %   varMax: 变量最大值 (标量或向量)
    % 输出:
    %   pop: 初始种群 (nPop×nVar)
    
    % 统一处理标量边界
    if isscalar(varMin), varMin = repmat(varMin, 1, nVar); end
    if isscalar(varMax), varMax = repmat(varMax, 1, nVar); end
    
    % 随机初始化
    pop = rand(nPop, nVar) .* (varMax - varMin) + varMin;
end

2.3 目标函数评估函数

function F = evaluatePopulation(fun, pop)
    % 评估种群中所有个体的目标函数值
    % 输入:
    %   fun: 目标函数句柄
    %   pop: 种群 (nPop×nVar)
    % 输出:
    %   F: 目标函数值 (nPop×nObj)
    
    nPop = size(pop, 1);
    F = zeros(nPop, 0);
    
    for i = 1:nPop
        % 计算目标函数值
        f = fun(pop(i, :));
        
        % 确保结果是行向量
        if iscolumn(f)
            f = f';
        end
        
        % 添加到结果矩阵
        F(i, 1:length(f)) = f;
    end
end

2.4 非支配排序函数

function [front, rank] = nonDominationSort(F)
    % 非支配排序
    % 输入:
    %   F: 目标函数值 (nPop×nObj)
    % 输出:
    %   front: 非支配前沿 (nPop×1)
    %   rank: 每个个体的秩 (nPop×1)
    
    nPop = size(F, 1);
    nObj = size(F, 2);
    
    % 初始化
    dominatedCount = zeros(nPop, 1);  % 被支配计数
    dominatedSet = cell(nPop, 1);     % 支配的个体集合
    rank = zeros(nPop, 1);            % 秩
    front = zeros(nPop, 1);           % 前沿
    
    % 计算支配关系
    for i = 1:nPop
        for j = 1:nPop
            if i == j, continue; end
            
            % 检查i是否支配j
            if all(F(i, :) <= F(j, :)) && any(F(i, :) < F(j, :))
                dominatedSet{i} = [dominatedSet{i}, j];
            % 检查j是否支配i
            elseif all(F(j, :) <= F(i, :)) && any(F(j, :) < F(i, :))
                dominatedCount(i) = dominatedCount(i) + 1;
            end
        end
        
        % 如果i不被任何个体支配,则属于第一前沿
        if dominatedCount(i) == 0
            front(i) = 1;
            rank(i) = 1;
        end
    end
    
    % 构建其他前沿
    currentFront = 1;
    while any(front == currentFront)
        nextFront = currentFront + 1;
        for i = 1:nPop
            if front(i) == currentFront
                for j = dominatedSet{i}
                    dominatedCount(j) = dominatedCount(j) - 1;
                    if dominatedCount(j) == 0
                        front(j) = nextFront;
                        rank(j) = nextFront;
                    end
                end
            end
        end
        currentFront = nextFront;
    end
end

2.5 拥挤度计算函数

function crowding = crowdingDistance(F, front)
    % 计算拥挤度距离
    % 输入:
    %   F: 目标函数值 (nPop×nObj)
    %   front: 非支配前沿 (nPop×1)
    % 输出:
    %   crowding: 拥挤度距离 (nPop×1)
    
    nPop = size(F, 1);
    nObj = size(F, 2);
    crowding = zeros(nPop, 1);
    
    % 找到最大和最小目标值
    fmin = min(F, [], 1);
    fmax = max(F, [], 1);
    
    % 对每个目标函数计算拥挤度
    for m = 1:nObj
        % 按当前目标函数排序
        [sortedF, sortIdx] = sort(F(:, m));
        sortedFront = front(sortIdx);
        
        % 边界点设置为无穷大
        crowding(sortIdx(1)) = Inf;
        crowding(sortIdx(end)) = Inf;
        
        % 计算中间点的拥挤度
        for i = 2:(nPop-1)
            if sortedFront(i) ~= sortedFront(i-1) || sortedFront(i) ~= sortedFront(i+1)
                % 避免不同前沿的点相互影响
                continue;
            end
            
            % 归一化距离
            normDist = (sortedF(i+1) - sortedF(i-1)) / (fmax(m) - fmin(m) + eps);
            crowding(sortIdx(i)) = crowding(sortIdx(i)) + normDist;
        end
    end
end

2.6 锦标赛选择函数

function parents = tournamentSelection(pop, front, crowding, nPop)
    % 二元锦标赛选择
    % 输入:
    %   pop: 种群 (nPop×nVar)
    %   front: 非支配前沿 (nPop×1)
    %   crowding: 拥挤度 (nPop×1)
    %   nPop: 要选择的个体数
    % 输出:
    %   parents: 选择的父代 (nPop×nVar)
    
    n = size(pop, 1);
    parents = zeros(nPop, size(pop, 2));
    
    for i = 1:nPop
        % 随机选择两个个体
        candidates = randperm(n, 2);
        cand1 = candidates(1);
        cand2 = candidates(2);
        
        % 比较前沿等级
        if front(cand1) < front(cand2)
            winner = cand1;
        elseif front(cand1) > front(cand2)
            winner = cand2;
        else
            % 相同前沿,比较拥挤度
            if crowding(cand1) > crowding(cand2)
                winner = cand1;
            else
                winner = cand2;
            end
        end
        
        parents(i, :) = pop(winner, :);
    end
end

2.7 遗传操作函数

function offspring = geneticOperators(parents, params, varMin, varMax)
    % 交叉和变异操作
    % 输入:
    %   parents: 父代种群 (nPop×nVar)
    %   params: 算法参数
    %   varMin: 变量最小值
    %   varMax: 变量最大值
    % 输出:
    %   offspring: 子代种群 (nPop×nVar)
    
    nPop = size(parents, 1);
    nVar = size(parents, 2);
    
    % 统一处理标量边界
    if isscalar(varMin), varMin = repmat(varMin, 1, nVar); end
    if isscalar(varMax), varMax = repmat(varMax, 1, nVar); end
    
    offspring = zeros(nPop, nVar);
    
    for i = 1:2:nPop
        % 选择两个父代
        p1 = parents(i, :);
        p2 = parents(i+1, :);
        
        % 交叉
        if rand < params.pc
            [c1, c2] = sbxCrossover(p1, p2, params.eta_c, varMin, varMax);
        else
            c1 = p1;
            c2 = p2;
        end
        
        % 变异
        c1 = polynomialMutation(c1, params.pm, params.eta_m, varMin, varMax);
        c2 = polynomialMutation(c2, params.pm, params.eta_m, varMin, varMax);
        
        % 添加到子代
        offspring(i, :) = c1;
        if i+1 <= nPop
            offspring(i+1, :) = c2;
        end
    end
end

2.8 SBX交叉函数

function [c1, c2] = sbxCrossover(p1, p2, eta_c, varMin, varMax)
    % 模拟二进制交叉 (SBX)
    % 输入:
    %   p1, p2: 父代个体
    %   eta_c: 交叉分布指数
    %   varMin, varMax: 变量边界
    % 输出:
    %   c1, c2: 子代个体
    
    nVar = length(p1);
    c1 = p1;
    c2 = p2;
    
    for i = 1:nVar
        if rand < 0.5
            % 计算交叉参数
            u = rand;
            if u <= 0.5
                beta = (2*u)^(1/(eta_c+1));
            else
                beta = (1/(2*(1-u)))^(1/(eta_c+1));
            end
            
            % 生成子代
            c1(i) = 0.5*((1+beta)*p1(i) + (1-beta)*p2(i));
            c2(i) = 0.5*((1-beta)*p1(i) + (1+beta)*p2(i));
            
            % 边界处理
            c1(i) = min(max(c1(i), varMin(i)), varMax(i));
            c2(i) = min(max(c2(i), varMin(i)), varMax(i));
        end
    end
end

2.9 多项式变异函数

function c = polynomialMutation(p, pm, eta_m, varMin, varMax)
    % 多项式变异
    % 输入:
    %   p: 父代个体
    %   pm: 变异概率
    %   eta_m: 变异分布指数
    %   varMin, varMax: 变量边界
    % 输出:
    %   c: 变异后个体
    
    nVar = length(p);
    c = p;
    
    for i = 1:nVar
        if rand < pm
            % 计算变异参数
            u = rand;
            if u < 0.5
                delta = (2*u)^(1/(eta_m+1)) - 1;
            else
                delta = 1 - (2*(1-u))^(1/(eta_m+1));
            end
            
            % 应用变异
            c(i) = p(i) + delta*(varMax(i) - varMin(i));
            
            % 边界处理
            c(i) = min(max(c(i), varMin(i)), varMax(i));
        end
    end
end

2.10 环境选择函数

function [newPop, newF, newFront, newCrowding] = environmentalSelection(combined_pop, combined_F, nPop)
    % 环境选择 (从合并种群中选择nPop个个体)
    % 输入:
    %   combined_pop: 合并种群 (2nPop×nVar)
    %   combined_F: 合并种群目标值 (2nPop×nObj)
    %   nPop: 要选择的数量
    % 输出:
    %   newPop: 新种群
    %   newF: 新种群目标值
    %   newFront: 新种群前沿
    %   newCrowding: 新种群拥挤度
    
    nCombined = size(combined_pop, 1);
    
    % 非支配排序
    [front, rank] = nonDominationSort(combined_F);
    
    % 计算拥挤度
    crowding = crowdingDistance(combined_F, front);
    
    % 按前沿和拥挤度排序
    [~, sortIdx] = sortrows([rank, -crowding], [1, 2]);
    
    % 选择前nPop个个体
    selectedIdx = sortIdx(1:nPop);
    
    newPop = combined_pop(selectedIdx, :);
    newF = combined_F(selectedIdx, :);
    newFront = front(selectedIdx);
    newCrowding = crowding(selectedIdx);
end

三、自定义目标函数示例

3.1 ZDT1测试函数

function f = zdt1(x)
    % ZDT1测试函数
    % 输入: x - 决策变量向量
    % 输出: f - 目标函数值 [f1, f2]
    
    n = length(x);
    f1 = x(1);
    g = 1 + 9 * sum(x(2:end)) / (n-1);
    f2 = g * (1 - sqrt(x(1)/g));
    
    f = [f1, f2];
end

3.2 DTLZ2测试函数

function f = dtlz2(x, M)
    % DTLZ2测试函数
    % 输入: 
    %   x - 决策变量向量
    %   M - 目标函数个数
    % 输出: f - 目标函数值 (1×M)
    
    n = length(x);
    k = n - M + 1;
    
    g = 0;
    for i = M:n
        g = g + (x(i) - 0.5)^2;
    end
    
    f = zeros(1, M);
    for i = 1:M-1
        f(i) = (1 + g) * cos(x(1)*pi/2) * cos(x(2)*pi/2) ... 
               * prod(cos(x(j)*pi/2) for j=3:i-1) * sin(x(i)*pi/2);
    end
    f(M) = (1 + g) * prod(cos(x(j)*pi/2) for j=1:M-1);
    
    % 简化版本
    if M == 3
        f(1) = (1 + g) * cos(x(1)*pi/2) * cos(x(2)*pi/2);
        f(2) = (1 + g) * cos(x(1)*pi/2) * sin(x(2)*pi/2);
        f(3) = (1 + g) * sin(x(1)*pi/2);
    end
end

3.3 自定义工程问题

function f = custom_engineering_problem(x)
    % 自定义工程优化问题示例
    % 输入: x - 设计变量 [x1, x2, x3]
    % 输出: f - 目标函数值 [成本, 重量, 应力]
    
    % 设计变量
    x1 = x(1);  % 梁高度 (m)
    x2 = x(2);  % 梁宽度 (m)
    x3 = x(3);  % 材料强度 (MPa)
    
    % 约束处理 (惩罚函数法)
    penalty = 0;
    if x1 < 0.1 || x1 > 0.5
        penalty = penalty + 1e6 * (min(abs(x1-0.1), abs(x1-0.5)))^2;
    end
    if x2 < 0.05 || x2 > 0.3
        penalty = penalty + 1e6 * (min(abs(x2-0.05), abs(x2-0.3)))^2;
    end
    if x3 < 100 || x3 > 500
        penalty = penalty + 1e6 * (min(abs(x3-100), abs(x3-500)))^2;
    end
    
    % 目标函数1: 成本 (与体积和材料相关)
    volume = x1 * x2 * 1.0;  % 假设长度1m
    material_cost = 0.1 * x3;  % 材料成本与强度相关
    cost = 1000 * volume + 0.1 * material_cost;
    
    % 目标函数2: 重量 (与体积和密度相关)
    density = 7800;  % 钢密度 (kg/m³)
    weight = volume * density;
    
    % 目标函数3: 最大应力 (越小越好)
    load = 10000;  % 载荷 (N)
    stress = (6 * load * 1.0) / (x1 * x2^2);  % 简支梁弯曲应力
    
    f = [cost, weight, stress] + penalty;
end

四、NSGA-II应用示例

4.1 基本使用

% 参数设置
nVar = 3;          % 变量个数
varMin = [0, 0, 0]; % 变量最小值
varMax = [1, 1, 1]; % 变量最大值
nPop = 100;         % 种群大小
maxGen = 200;       % 最大迭代次数

% 定义目标函数
fun = @(x) zdt1(x);

% 运行NSGA-II
[pop, F, front, crowding] = nsga2_custom(fun, nVar, varMin, varMax, nPop, maxGen);

% 结果可视化
plot(F(:,1), F(:,2), 'ro');
xlabel('目标1'); ylabel('目标2');
title('Pareto前沿');

4.2 自定义工程问题优化

% 参数设置
nVar = 3;          % 变量个数: [高度, 宽度, 材料强度]
varMin = [0.1, 0.05, 100]; % 最小值
varMax = [0.5, 0.3, 500];  % 最大值
nPop = 50;          % 种群大小
maxGen = 100;        % 最大迭代次数

% 定义目标函数
fun = @custom_engineering_problem;

% 运行NSGA-II
[pop, F, front, crowding] = nsga2_custom(fun, nVar, varMin, varMax, nPop, maxGen);

% 提取Pareto前沿
paretoIdx = find(front == 1);
paretoPop = pop(paretoIdx, :);
paretoF = F(paretoIdx, :);

% 结果可视化
figure;
subplot(1,3,1);
plot(paretoF(:,1), paretoF(:,2), 'bo');
xlabel('成本'); ylabel('重量');
title('成本 vs 重量');

subplot(1,3,2);
plot(paretoF(:,1), paretoF(:,3), 'ro');
xlabel('成本'); ylabel('应力');
title('成本 vs 应力');

subplot(1,3,3);
plot(paretoF(:,2), paretoF(:,3), 'go');
xlabel('重量'); ylabel('应力');
title('重量 vs 应力');

% 显示最佳折衷解
[~, idx] = min(paretoF(:,1) + paretoF(:,2) + paretoF(:,3));
fprintf('最佳折衷解:\n');
fprintf('  高度: %.3f m\n', paretoPop(idx,1));
fprintf('  宽度: %.3f m\n', paretoPop(idx,2));
fprintf('  材料强度: %.1f MPa\n', paretoPop(idx,3));
fprintf('  成本: %.2f 元\n', paretoF(idx,1));
fprintf('  重量: %.2f kg\n', paretoF(idx,2));
fprintf('  应力: %.2f MPa\n', paretoF(idx,3));

参考代码 NSGA2自定义优化函数MATLAB代码 www.youwenfan.com/contentcnt/160564.html

五、算法性能评估

5.1 性能指标计算

function metrics = evaluatePerformance(F, front, truePareto, trueFront)
    % 评估NSGA-II性能
    % 输入:
    %   F: 算法得到的Pareto前沿目标值
    %   front: 算法得到的前沿等级
    %   truePareto: 真实Pareto前沿 (可选)
    %   trueFront: 真实前沿等级 (可选)
    % 输出:
    %   metrics: 性能指标结构
    
    metrics = struct();
    
    % 1. 收敛性指标 (GD, IGD)
    if exist('truePareto', 'var') && ~isempty(truePareto)
        % 世代距离 (Generational Distance)
        gd = 0;
        for i = 1:size(F, 1)
            if front(i) == 1  % 只考虑Pareto前沿
                minDist = min(vecnorm(F(i,:) - truePareto, 2, 2));
                gd = gd + minDist^2;
            end
        end
        metrics.GD = sqrt(gd) / size(F(front==1,:), 1);
        
        % 反向世代距离 (Inverted Generational Distance)
        igd = 0;
        for i = 1:size(truePareto, 1)
            minDist = min(vecnorm(truePareto(i,:) - F, 2, 2));
            igd = igd + minDist^2;
        end
        metrics.IGD = sqrt(igd) / size(truePareto, 1);
    end
    
    % 2. 多样性指标 (Spacing, Spread)
    paretoF = F(front==1, :);
    nPareto = size(paretoF, 1);
    
    if nPareto > 1
        % 间距指标 (Spacing)
        distances = pdist2(paretoF, paretoF);
        minDists = min(distances + eye(nPareto)*Inf, [], 2);
        metrics.Spacing = std(minDists);
        
        % 分布性指标 (Spread)
        fmin = min(paretoF, [], 1);
        fmax = max(paretoF, [], 1);
        d1 = norm(paretoF(1,:) - fmin) / norm(fmax - fmin);
        d2 = norm(paretoF(end,:) - fmin) / norm(fmax - fmin);
        metrics.Spread = (d1 + d2 + sum(abs(minDists - mean(minDists))) / (nPareto-1)) / (d1 + d2 + nPareto-1);
    end
    
    % 3. 超体积指标 (Hypervolume)
    refPoint = max(F, [], 1) * 1.1;  % 参考点
    metrics.HV = hypervolume(paretoF, refPoint);
    
    % 4. Pareto前沿大小
    metrics.ParetoSize = nPareto;
end

function hv = hypervolume(front, refPoint)
    % 计算超体积
    n = size(front, 1);
    m = size(front, 2);
    
    if n == 0
        hv = 0;
        return;
    end
    
    % 按第一个目标排序
    [front, idx] = sortrows(front, 1);
    
    hv = 0;
    for i = 1:n
        if m == 2
            % 二维情况
            hv = hv + (refPoint(1) - front(i,1)) * (refPoint(2) - front(i,2));
        else
            % 多维情况 (简化)
            hv = hv + prod(refPoint(1:m-1) - front(i,1:m-1)) * (refPoint(m) - front(i,m));
        end
    end
end

5.2 性能测试函数

function runPerformanceTest()
    % 运行NSGA-II性能测试
    
    % 测试问题
    testProblems = {
        struct('name', 'ZDT1', 'fun', @zdt1, 'nVar', 10, 'nObj', 2, 'varMin', 0, 'varMax', 1)
        struct('name', 'DTLZ2', 'fun', @(x)dtlz2(x,3), 'nVar', 7, 'nObj', 3, 'varMin', 0, 'varMax', 1)
    };
    
    % 算法参数
    nPop = 100;
    maxGen = 200;
    
    results = cell(length(testProblems), 1);
    
    for i = 1:length(testProblems)
        prob = testProblems{i};
        fprintf('运行测试: %s\n', prob.name);
        
        % 运行NSGA-II
        [pop, F, front, crowding] = nsga2_custom(...
            prob.fun, prob.nVar, prob.varMin, prob.varMax, nPop, maxGen);
        
        % 评估性能
        metrics = evaluatePerformance(F, front);
        
        % 存储结果
        results{i} = struct('problem', prob, 'metrics', metrics, 'F', F, 'front', front);
        
        % 显示结果
        fprintf('  Pareto前沿大小: %d\n', metrics.ParetoSize);
        fprintf('  超体积: %.4f\n', metrics.HV);
        fprintf('  间距指标: %.4f\n', metrics.Spacing);
        fprintf('  分布性指标: %.4f\n', metrics.Spread);
    end
    
    % 可视化结果
    visualizeResults(results);
end

六、高级功能扩展

6.1 约束处理

function [c, ceq] = constraintFunction(x)
    % 约束函数示例
    % 输入: x - 决策变量
    % 输出: 
    %   c - 不等式约束 (c <= 0)
    %   ceq - 等式约束 (ceq = 0)
    
    % 示例约束:
    c = [x(1) + x(2) - 1.5;  % x1 + x2 <= 1.5
         -x(1) - x(2) + 0.5; % -x1 - x2 <= -0.5
         x(1)^2 - 0.25];     % x1^2 <= 0.25
    
    ceq = [];  % 无等式约束
end

% 在目标函数中添加约束惩罚
function f = constrainedObjective(x)
    % 原始目标函数
    f_raw = zdt1(x);
    
    % 约束处理
    [c, ceq] = constraintFunction(x);
    
    % 惩罚函数法
    penalty = 0;
    if ~isempty(c)
        penalty = penalty + 1e6 * sum(max(0, c).^2);
    end
    if ~isempty(ceq)
        penalty = penalty + 1e6 * sum(ceq.^2);
    end
    
    f = f_raw + penalty;
end

6.2 并行计算支持

function F = evaluatePopulationParallel(fun, pop)
    % 并行评估种群
    nPop = size(pop, 1);
    F = zeros(nPop, 0);
    
    parfor i = 1:nPop
        f = fun(pop(i, :));
        if iscolumn(f)
            f = f';
        end
        F(i, 1:length(f)) = f;
    end
end

% 修改主函数以支持并行
function [pop, F, front, crowding] = nsga2_parallel(fun, nVar, varMin, varMax, nPop, maxGen, params)
    % 使用并行评估的NSGA-II
    
    % 初始化
    pop = initializePopulation(nPop, nVar, varMin, varMax);
    
    for gen = 1:maxGen
        % 并行评估
        F = evaluatePopulationParallel(fun, pop);
        
        % 其余部分与原版相同...
    end
end

6.3 自定义选择策略

function parents = customSelection(pop, front, crowding, nPop, strategy)
    % 自定义选择策略
    % 策略: 'tournament' (默认), 'roulette', 'random'
    
    n = size(pop, 1);
    parents = zeros(nPop, size(pop, 2));
    
    switch lower(strategy)
        case 'tournament'
            % 二元锦标赛选择 (原版)
            for i = 1:nPop
                candidates = randperm(n, 2);
                cand1 = candidates(1);
                cand2 = candidates(2);
                
                if front(cand1) < front(cand2)
                    winner = cand1;
                elseif front(cand1) > front(cand2)
                    winner = cand2;
                else
                    if crowding(cand1) > crowding(cand2)
                        winner = cand1;
                    else
                        winner = cand2;
                    end
                end
                parents(i, :) = pop(winner, :);
            end
            
        case 'roulette'
            % 轮盘赌选择
            % 计算选择概率 (基于秩和拥挤度)
            ranks = front;
            invRanks = 1 ./ (ranks + 1);  % 避免除以0
            probs = invRanks / sum(invRanks);
            
            for i = 1:nPop
                idx = randsample(n, 1, true, probs);
                parents(i, :) = pop(idx, :);
            end
            
        case 'random'
            % 随机选择
            idx = randperm(n, nPop);
            parents = pop(idx, :);
            
        otherwise
            error('未知的选择策略: %s', strategy);
    end
end

七、使用注意事项

  1. 目标函数设计

    • 确保目标函数返回行向量

    • 处理无效解(返回大惩罚值)

    • 考虑目标函数的尺度差异

  2. 参数调优

    • 种群大小:通常50-200

    • 最大代数:100-1000

    • 交叉概率:0.7-0.95

    • 变异概率:1/nVar - 1/2

    • 分布指数:20-100

  3. 性能优化

    • 使用并行计算加速评估

    • 对于高维问题,考虑使用代理模型

    • 使用JIT加速或C/MEX实现关键函数

  4. 结果分析

    • 检查Pareto前沿的多样性和收敛性

    • 使用多种性能指标综合评估

    • 进行统计显著性检验

posted @ 2026-04-07 11:20  小前端攻城狮  阅读(4)  评论(0)    收藏  举报