ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

SPEA2多目标优化算法:Matlab源码解析与工程应用实战

SPEA2多目标优化算法:Matlab源码解析与工程应用实战 简介本资源是面向本科及硕士阶段科研学习者的多目标优化算法实践材料聚焦于强度帕累托进化算法第二版SPEA2在Matlab平台上的完整实现与应用验证。资源解决典型多目标优化问题的建模、求解与Pareto前沿可视化需求适用于智能优化、路径规划、投资组合分析等场景的算法原理理解与代码复现。压缩包共13个文件含8个核心Matlab函数如spea2.m主程序、Dominates.m支配关系判断、Crossover.m交叉操作等、3张结果图含Pareto前沿可视化、1个说明文档和1个测试数据集.mat整体仅471KB轻量易用。已有263人下载学习配套运行结果截图与清晰模块划分便于初学者快速掌握SPEA2算法流程、种群更新机制与适应度分配策略无需额外调试即可运行并对比不同参数下的收敛性表现。1. 项目概述与核心价值最近在整理一些老项目翻出来一个用SPEA2算法求解多目标优化问题的Matlab源码包。这个项目当时是为了解决一个工程上的多目标权衡问题做的后来发现这个框架其实挺通用的稍微改改就能套用到很多场景里比如机械设计、投资组合优化、调度问题等等。SPEA2Strength Pareto Evolutionary Algorithm 2算是多目标进化算法里一个经典且强力的选手了它比第一代的SPEA在环境选择和密度估计上做了不少改进收敛性和解集的分布性都更好。简单来说多目标优化问题就是同时要优化好几个互相“打架”的目标。比如设计一辆车你既希望它油耗低经济性好又希望它加速快动力性好这两个目标往往是矛盾的。传统的单目标优化方法在这里就有点力不从心了因为你很难找到一个“最好”的解而是一堆“帕累托最优解”——这些解的特点是你没法在改进其中一个目标的同时不让其他任何一个目标变差。SPEA2这类算法的任务就是尽可能高效、准确地找到这一大堆“帕累托最优解”的近似集合也就是所谓的“帕累托前沿”给决策者提供一个清晰的权衡空间。这个源码包的价值就在于它提供了一个从理论到实践的完整桥梁。网上虽然能找到SPEA2的论文但把论文里的公式和步骤特别是环境选择、截断这些关键操作用清晰可运行的Matlab代码实现出来并且处理好各种边界情况还是需要费不少功夫的。这个项目把这些脏活累活都干了你拿到手只需要定义清楚你自己的问题目标函数、变量范围基本上就能跑起来看到结果对于研究者快速验证想法或者工程师解决实际中的多目标决策问题都是一个很趁手的工具。2. SPEA2算法核心原理深度拆解要理解这份源码甚至想自己修改或者基于它开发我们必须先吃透SPEA2算法的核心机制。它本质上是一种基于精英策略的进化算法但它在如何保存和利用精英解即好的解上设计得非常精巧。2.1 基本流程与核心数据结构SPEA2的每一代迭代主要围绕两个集合进行操作种群Population和存档Archive。种群就是当前一代的所有候选解存档则是从历史所有解中筛选出来的精英解集合。算法的核心流程可以概括为以下几步这个循环会一直持续到满足停止条件比如达到最大迭代次数初始化随机生成初始种群并初始化一个空的存档。适应度分配为当前种群和存档中的所有个体计算适应度值。SPEA2的适应度计算是其一大特色我们稍后详细讲。环境选择根据适应度值从“种群存档”的合并集合中选择出优秀的个体形成新的存档。新存档的大小是固定的比如100个这一步保证了精英解的保留和迭代。终止判断如果满足停止条件如达到最大迭代次数则算法结束当前存档就是找到的近似帕累托最优解集。交配选择从当前存档中通过锦标赛选择等方法选出一些个体作为“父母”。变异与交叉对选出的“父母”个体应用交叉模拟基因重组和变异引入随机扰动操作生成新的子代个体这些子代个体就构成了下一代的新种群。回到第2步开始下一轮迭代。你会发现存档Archive是这个算法的记忆体和精华库。它不像有些算法只保留当前代的最优解SPEA2的存档保留了历史积累的精英并且通过环境选择不断去芜存菁这是它能找到高质量、分布均匀的帕累托前沿的关键。2.2 适应度计算Strength Density Estimation这是SPEA2区别于其他算法尤其是其前身SPEA的核心。一个个体的适应度由两部分组成原始适应度Raw Fitness和密度估计Density Estimation。原始适应度R(i) 它衡量的是一个个体i被其他个体支配的程度。具体计算方式是个体i的原始适应度等于所有支配了i的个体这些个体至少在一个目标上比i好且在所有其他目标上都不比i差的“强度Strength”之和。强度 S(j) 一个个体j的强度是它支配了多少个其他个体包括当前种群和存档中的所有个体。支配的个体越多强度越大。所以R(i) Σ S(j)其中j是支配i的所有个体。核心逻辑一个解被越多的强解支配它的原始适应度就越差值越大。非支配解即不被任何其他解支配的解的原始适应度R(i) 0。因此算法会优先选择原始适应度小的个体。密度估计D(i) 仅仅用原始适应度可能会让很多非支配解R(i)0无法区分好坏。SPEA2引入了密度信息来进一步区分这些“同样优秀”的解目的是让解在目标空间里分布得更均匀避免挤成一团。它使用了个体i到第k个最近邻个体的距离的倒数来度量密度。具体计算先对每个个体i计算它到其他所有个体的欧氏距离在目标空间里然后排序取第k个最近的距离记为 σ_i^k。通常 k 取为 sqrt(NM)其中N是种群大小M是存档大小。密度 D(i) 1 / (σ_i^k 2)。这里加2是为了防止分母为零同时做一个平滑。核心逻辑一个解如果周围很“拥挤”即 σ_i^k 很小它的密度值 D(i) 就大这是不好的。算法倾向于保留那些密度小即周围比较空旷的解从而促进解集的多样性。最终适应度F(i) F(i) R(i) D(i)。最终目标是最小化 F(i)。所以算法会优先选择那些不被支配R小且周围不拥挤D小的个体。实操心得理解这个适应度计算是看懂代码的关键。在源码的fitness_assignment函数里你会看到两个嵌套循环来计算支配关系和强度然后计算原始适应度。接着会有一个计算所有个体间距离并排序的过程用于求k近邻距离来计算密度。这个过程计算量不小尤其是当种群和存档规模较大时是算法的主要耗时点之一。在写自己的目标函数时要尽量保持计算轻量否则迭代会很慢。2.3 环境选择与存档截断这是SPEA2的另一个精髓。环境选择的任务是从合并了当前种群和旧存档的集合大小为 NM中选出 M 个个体构成新的存档。直接选适应度最好的M个行吗不行因为可能这M个都挤在一个区域。SPEA2的环境选择是一个两阶段过程复制所有非支配解首先将所有最终适应度 F(i) 1 的个体即非支配解因为R(i)0且D(i)1复制到新存档中。设这个数量为 M。截断操作如果 M M正好工作完成。如果 M M说明非支配解不够那么就从剩下的个体中挑选适应度最好的 (M - M) 个补进去。更常见且关键的情况是 M M即非支配解太多了存档放不下。这时就需要进行“截断”剔除掉一些非支配解直到数量等于M。截断的规则非常巧妙它反复剔除那个“距离其他某个个体最近”的个体。具体来说在待选的非支配解集合中对于每一个个体计算它到集合内其他所有个体的距离找到它的最近距离。然后剔除掉这个“最近距离”最小的那个个体因为它和另一个个体靠得最近最“冗余”。剔除一个后重新计算剩余个体的最近距离再剔除下一个直到存档大小降到M为止。这个截断策略完美地体现了SPEA2的哲学在保证解都是非支配的收敛性的前提下尽可能保留那些彼此距离远的解分布性/多样性。注意事项在源码的environmental_selection函数中你会清晰地看到这个截断过程的实现。它通常用一个 while 循环每次循环里都计算一次距离矩阵或更新距离然后找到最小最近距离的索引并删除。这里要注意距离计算的效率以及当两个个体距离完全相等时的处理通常随机剔除一个。这个函数的实现质量直接影响了最终帕累托前沿的分布均匀程度。3. 源码结构解析与关键模块实现拿到SPEA2算法求解多目标优化问题matlab源码.zip这个包解压后我们通常会看到类似下面这样的文件结构。理解每个文件的作用是灵活使用和修改它的前提。SPEA2_MATLAB/ ├── main.m % 算法主脚本设置参数调用核心函数 ├── initialize_population.m % 初始化种群 ├── evaluate_population.m % 评价种群计算每个个体的多个目标函数值 ├── fitness_assignment.m % SPEA2适应度计算核心 ├── environmental_selection.m % 环境选择与存档截断核心 ├── tournament_selection.m % 锦标赛选择用于交配选择 ├── crossover.m % 交叉操作如模拟二进制交叉SBX ├── mutation.m % 变异操作如多项式变异 ├── plot_pareto.m % 绘制最终找到的帕累托前沿 └── problem_definition.m % 用户需要修改的文件定义目标函数、变量边界等3.1 主流程脚本main.m这个文件是算法的总控制器。一个典型的main.m结构如下里面包含了所有关键参数的设置%% SPEA2 主程序 clear; clc; close all; % 1. 问题定义 problem.nVar 30; % 决策变量维度 problem.varMin [0, 0, ...]; % 变量下界根据实际问题定义 problem.varMax [1, 1, ...]; % 变量上界 problem.nObj 2; % 目标函数个数例如2目标问题 % 2. 算法参数设置 params.maxGen 200; % 最大进化代数 params.popSize 100; % 种群大小 params.archiveSize 100; % 外部存档大小 params.pCrossover 0.9; % 交叉概率 params.pMutation 1/problem.nVar; % 变异概率常用设置 params.etaC 20; % 交叉分布指数SBX参数 params.etaM 20; % 变异分布指数多项式变异参数 % 3. 初始化 population initialize_population(params.popSize, problem); archive []; % 初始存档为空 % 4. 主循环 for gen 1:params.maxGen % 合并种群和存档 combinedPop [population; archive]; % 评价合并种群的目标函数值 combinedObj evaluate_population(combinedPop, problem); % 计算适应度 (SPEA2核心) fitness fitness_assignment(combinedObj); % 环境选择更新存档 (SPEA2核心) archive environmental_selection(combinedPop, combinedObj, fitness, params.archiveSize); % 终止条件判断这里简单用最大代数 % 可以在这里添加其他判断如前沿变化小于阈值 % 显示进度 fprintf(Generation %d, Archive Size: %d\n, gen, size(archive, 1)); % 交配选择、交叉、变异以生成新种群 % 这里通常从archive中选择父母 parents tournament_selection(archive, params.popSize); % 基于适应度选择 offspring crossover(parents, params, problem); offspring mutation(offspring, params, problem); % 新种群成为下一代的population population offspring; end % 5. 最终结果 % 最终存档即为近似帕累托最优解集 paretoSet archive; % 决策变量 paretoFront evaluate_population(archive, problem); % 目标函数值 % 6. 绘图 plot_pareto(paretoFront); title(SPEA2 求解的帕累托前沿); xlabel(目标函数 f1); ylabel(目标函数 f2); grid on;关键参数解读popSize和archiveSize通常设置成一样大比如100。存档大小决定了最终你能得到多少帕累托最优解。pCrossover和pMutation交叉概率一般设高0.8-0.9变异概率一般设低常取1/nVar保证每个变量平均有一次变异机会。etaC和etaM这是模拟二进制交叉SBX和多项式变异中的分布指数。值越大产生的子代离父母越近搜索更精细值越小子代越远离父母探索性更强。通常设为15-30之间。3.2 问题定义文件problem_definition.m这是你必须修改的文件用来连接算法和你自己的实际问题。一个典型的双目标ZDT1测试问题的定义如下function objs problem_definition(x) % x: 一个决策向量行向量或列向量 % objs: 返回的目标函数值向量例如 [f1, f2] n length(x); f1 x(1); % 第一个目标只与第一个变量有关 g 1 9 * sum(x(2:end)) / (n-1); % 计算g函数 h 1 - sqrt(f1 / g); % 计算h函数 f2 g * h; % 第二个目标 objs [f1, f2]; end你需要做的是根据你的问题确定决策变量个数nVar和上下界varMin/varMax在main.m中设置。在这个函数里根据输入的解向量x计算出所有目标函数的值。如果你的问题有约束也需要在这里计算约束违反程度并在适应度计算中加以惩罚这是另一个进阶话题。3.3 核心函数fitness_assignment.m实现细节我们深入看一下这个核心函数的Matlab实现片段以加深理解function F fitness_assignment(objectives) % objectives: 输入为 N x M 矩阵N是个体数M是目标数 % F: 输出为 N x 1 的适应度向量 [N, M] size(objectives); % 1. 计算强度 S(i): 个体i支配了多少其他个体 S zeros(N, 1); for i 1:N % 比较个体i和所有其他个体j for j 1:N if i ~ j % 判断i是否支配j: i的所有目标都不比j差且至少一个更好 if all(objectives(i, :) objectives(j, :)) any(objectives(i, :) objectives(j, :)) S(i) S(i) 1; end end end end % 2. 计算原始适应度 R(i): 所有支配i的个体的强度之和 R zeros(N, 1); for i 1:N for j 1:N if i ~ j % 判断j是否支配i if all(objectives(j, :) objectives(i, :)) any(objectives(j, :) objectives(i, :)) R(i) R(i) S(j); end end end end % 3. 计算密度 D(i): 基于k近邻距离 k round(sqrt(N)); % SPEA2建议的k值 distances pdist2(objectives, objectives); % 计算所有个体间的欧氏距离 distances(logical(eye(N))) inf; % 将自己到自己的距离设为无穷大便于排序时排除 sortedDist sort(distances, 2); % 每行按距离排序 sigma_k sortedDist(:, k); % 取第k个最近距离 D 1 ./ (sigma_k 2); % 计算密度 % 4. 最终适应度 F R D; end实操心得与性能提示上面的双循环支配关系判断是O(N^2)的复杂度当N很大时比如种群存档超过1000会成为性能瓶颈。在实际工程代码中可以考虑向量化操作来提升速度或者使用更高效的非支配排序方法如ENS的变种。对于快速原型验证这个写法清晰易懂但对于大规模问题优化这里是必要的。另外pdist2函数来自统计和机器学习工具箱如果没安装需要自己写一个计算欧氏距离矩阵的函数。4. 实战从测试函数到自定义问题理论讲完了我们来看看怎么实际用这个源码包跑起来并应用到自己的问题上。4.1 运行测试函数最快捷的方式就是先用一个标准测试函数如ZDT1, DTLZ2验证代码是否正确。通常源码包里会自带一个problem_definition.m定义为某个测试函数。你只需要确保Matlab当前文件夹定位到源码目录。打开main.m检查problem.nVar,varMin,varMax是否与测试函数匹配例如ZDT1通常nVar30变量范围[0,1]。直接运行main.m。如果一切正常你应该能在命令行窗口看到迭代进度最后弹出一个图形窗口展示找到的帕累托前沿。对于ZDT1这样的问题其真实的帕累托前沿是已知的一条曲线你可以直观地对比算法找到的解是否接近且均匀分布在那条曲线附近。4.2 适配自定义工程问题这才是我们最终的目的。假设你有一个自己的双目标优化问题设计一个压缩弹簧目标一是重量最轻f1目标二是长度最短f2决策变量是钢丝直径d、弹簧圈径D和有效圈数n。你需要第一步修改问题定义在problem_definition.m中根据你的工程公式重写目标函数。function objs my_spring_problem(x) % x [d, D, n] d x(1); % 钢丝直径 D x(2); % 弹簧中径 n x(3); % 有效圈数 % 假设材料密度为rho剪切模量G rho 7800; % 钢的密度 kg/m^3 G 79.3e9; % 钢的剪切模量 Pa % 目标1: 重量最小化 (简化计算弹簧质量) mass rho * (pi*d^2/4) * (pi*D) * n; f1 mass; % 目标2: 长度最小化 (自由长度) % 简化模型自由长度 ≈ 压并高度 间距这里用 n * d 的倍数粗略估计 free_length 1.2 * n * d; % 系数为假设 f2 free_length; % 注意实际问题中会有大量约束如旋绕比CD/d的范围、强度约束、刚度约束等。 % 约束处理需要额外机制例如罚函数法这里仅为示意。 objs [f1, f2]; end第二步调整算法参数在main.m中修改问题参数problem.nVar 3; problem.varMin [0.001, 0.01, 2]; % d, D, n 的合理下界 problem.varMax [0.02, 0.1, 20]; % 上界 problem.nObj 2;进化代数maxGen、种群大小popSize等可以根据问题复杂度调整。复杂问题需要更多的代数500-1000和更大的种群100-200。第三步处理约束关键进阶步骤上面的弹簧问题有实际约束比如旋绕比C通常在4到16之间最大剪切应力需小于许用应力等。SPEA2本身不直接处理约束常用方法是罚函数法。你需要修改evaluate_population.m或problem_definition.m在计算目标函数的同时计算约束违反总量并将其作为一个“惩罚项”加到适应度上。例如在fitness_assignment之前可以这样做function [objs, violation] evaluate_population_with_constraint(pop, problem) objs zeros(size(pop,1), problem.nObj); violation zeros(size(pop,1), 1); % 约束违反度 for i 1:size(pop,1) x pop(i,:); % 计算目标值 objs(i,:) problem_definition(x); % 计算约束违反度假设有p个不等式约束 g_j(x) 0 % violation(i) sum(max(0, g_j(x))); 所有违反量的和 % 例如对于旋绕比约束 4 D/d 16 C x(2)/x(1); g1 4 - C; % 等价于 C 4 - g10 g2 C - 16; % 等价于 C 16 - g20 violation(i) max(0, g1) max(0, g2); % 可以加上更多约束... end end然后在计算适应度时将violation乘以一个很大的惩罚系数penalty加到原始适应度F上F F penalty * violation。这样违反约束的个体适应度会变差从而被算法淘汰。注意事项罚函数系数的选择是个技术活。系数太小约束不起作用系数太大可能会掩盖目标函数本身的差异导致搜索困难。一种自适应罚函数或者采用专门处理约束的进化算子如随机排序是更高级的方法。5. 结果分析、可视化与性能评估算法跑完了存档里有一堆解怎么判断它们好不好怎么用5.1 帕累托前沿可视化对于2目标或3目标问题直接画图是最直观的。源码中的plot_pareto函数通常就是简单的散点图。你可以进一步美化figure; scatter(paretoFront(:,1), paretoFront(:,2), 40, filled, MarkerFaceColor, b, MarkerEdgeColor, k); xlabel(重量 (kg)); ylabel(自由长度 (m)); title(弹簧设计帕累托前沿); grid on; hold on; % 如果你知道真实前沿或理想点可以画出来作为参考 % plot(trueFront_f1, trueFront_f2, r--, LineWidth, 2); legend(SPEA2 近似解集, 真实前沿如果已知);对于3目标问题可以使用scatter3绘制三维散点图或者绘制多个两两目标的二维投影图来观察。5.2 性能指标计算当没有真实帕累托前沿作比较时或者需要定量比较不同算法的结果时就需要用性能指标。常用的有超体积Hypervolume, HV衡量解集所覆盖的目标空间体积。体积越大说明解集综合性能越好既靠近真实前沿又分布广泛。这是最常用的综合性指标。Matlab中可以使用paretoset和paretovolume函数需要Global Optimization Toolbox或下载第三方HV计算工具如PlatEMO工具箱中的HV函数。反转世代距离Inverted Generational Distance, IGD需要一组真实前沿的参考点。计算近似解集中每个点到真实前沿最近距离的平均值。值越小说明近似前沿越接近真实前沿。间距Spacing衡量解集中个体分布的均匀程度。值越小分布越均匀。在你的源码基础上可以编写一个计算这些指标的函数方便评估。function [HV, Spacing] evaluate_performance(paretoFront, refPoint) % paretoFront: 算法得到的近似前沿 % refPoint: 计算超体积的参考点通常比所有解都差一点各目标值更大 % 1. 计算超体积 (示例需有HV计算函数) % 假设有一个计算超体积的函数 hypervolume(pf, refPoint) HV hypervolume(paretoFront, refPoint); % 2. 计算间距 numSol size(paretoFront, 1); d pdist(paretoFront); % 计算所有解对之间的距离 d squareform(d); % 转为方阵 d(logical(eye(numSol))) inf; % 将对角线自己到自己设为无穷大 minDist min(d, [], 2); % 每个解到其他解的最小距离 meanMinDist mean(minDist); Spacing sqrt(sum((minDist - meanMinDist).^2) / (numSol - 1)); end5.3 结果解读与决策支持最终得到的帕累托前沿图是一系列“最优折衷”方案的集合。作为决策者你需要从中选择一个最终方案。这时没有绝对的最优只有基于偏好的选择。查看极端点前沿的两端通常对应着单一目标最优的解。比如最左边的点可能重量最轻但最长最右边的点长度最短但最重。这帮你确定了性能的边界。寻找“拐点”在前沿曲线上有时会存在明显的拐点在这个点附近牺牲一点点目标A能换来目标B的大幅改善。这个点往往是性价比很高的选择。设定阈值你可以为某个目标设定一个可接受的上限。比如要求重量不得超过0.5kg那么就在前沿上找到重量小于0.5kg的那些解再从里面选长度最短的。你可以将最终的paretoSet决策变量和paretoFront目标值导出到Excel或MAT文件供进一步分析。6. 常见问题排查与调参经验在实际使用中你可能会遇到各种问题。这里记录一些典型的坑和解决方法。6.1 算法不收敛或收敛效果差现象跑了很久帕累托前沿看起来杂乱无章或者始终离期望的区域很远。可能原因与对策进化代数不够多目标优化比单目标需要更多的迭代。尝试将maxGen从200增加到500或1000。种群/存档大小太小对于变量多、目标复杂的问题popSize和archiveSize设为100可能不够探索整个空间。尝试增大到200或300。交叉变异参数不当etaC和etaM太小会导致搜索过于随机太大则缺乏探索。尝试将其调整到10-30之间。交叉概率pCrossover建议保持高值0.8-0.9变异概率pMutation保持低值如1/nVar。约束处理不当如果问题有约束而罚函数系数设置不合理可能导致算法一直在不可行域徘徊。尝试增大罚系数或者改用可行性优先的约束处理方法。问题定义有误仔细检查你的problem_definition.m确保目标函数计算正确变量边界合理。可以用一个简单的解手动测试一下函数输出。6.2 帕累托前沿分布不均匀现象解都挤在前沿的某一段其他区域没有解。可能原因与对策密度估计参数k在fitness_assignment.m中k round(sqrt(N))是经典设置。如果分布问题严重可以尝试微调k值例如k round(sqrt(N)) 1或-1观察效果。截断操作确保environmental_selection.m中的截断逻辑正确实现了“反复剔除最近距离最小个体”的规则。这是保证分布性的关键。目标尺度差异大如果两个目标函数的数值范围相差巨大例如f1在[0, 1]f2在[0, 10000]距离计算会被大数值的目标主导。务必对目标函数进行归一化处理。可以在evaluate_population后对目标值矩阵进行归一化如缩放到[0,1]区间然后再进行适应度计算和环境选择。6.3 程序运行速度太慢现象每代迭代耗时很长尤其是变量维度高、种群规模大时。可能原因与对策支配关系判断瓶颈fitness_assignment中的双循环支配判断是O(N^2)复杂度。对于大规模问题N1000考虑优化。一种简单优化是预先对目标函数值进行排序可以减少比较次数。更高级的方法是使用高效的非支配排序算法。距离计算瓶颈pdist2函数计算所有个体间距离也是O(N^2)。对于大规模问题这是另一个瓶颈。如果问题维度不高可以接受。否则需要考虑近似算法或采样方法。目标函数本身计算耗时如果你的工程仿真模型如有限元分析非常耗时那么每次评价都是瓶颈。这时减少种群大小和进化代数可能是无奈之举或者考虑使用代理模型如Kriging、神经网络来近似昂贵的目标函数。向量化检查代码尽可能将循环操作改为矩阵运算。Matlab对矩阵运算有深度优化。6.4 存档大小波动或最终解数量不足现象运行时存档大小archiveSize不固定或者最终存档中的解远少于设定的archiveSize。可能原因与对策正常现象在迭代初期非支配解可能很少存档大小会小于设定值。随着进化非支配解增多存档会被填满并启动截断。最终存档大小应等于设定的archiveSize。如果最终仍不足说明算法找到的非支配解总数就少于存档容量可以尝试增加popSize或maxGen来探索更多解。截断逻辑bug检查environmental_selection.m中当非支配解数量M大于archiveSizeM时截断过程是否正确执行并且最终返回的解数量是否精确等于M。适应度计算错误如果适应度计算有误可能导致支配关系判断出错从而影响非支配解的识别。仔细检查fitness_assignment.m中的支配判断逻辑和的使用。最后调参本身也是一个需要经验的过程。没有一套参数适合所有问题。对于新问题建议从一个中等规模的参数如popSize100, maxGen250开始观察收敛趋势和前沿分布然后有针对性地进行调整。记录每次运行的参数和结果如最终的超体积值有助于你找到适合特定问题的最佳参数组合。本文还有配套的精品资源点击获取
返回列表