ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

多目标优化实战:金鹰算法原理与MATLAB实现详解

多目标优化实战:金鹰算法原理与MATLAB实现详解 1. 从“多目标”到“金鹰算法”一个优化求解的实战视角在工程、金融、科研乃至日常决策中我们常常面临一个核心困境如何在一堆相互冲突的目标中找到那个“最优”的平衡点比如设计一辆汽车我们希望它油耗最低、成本最低、安全性最高、加速最快。这些目标往往此消彼长追求极致油耗可能牺牲动力追求极致安全可能增加重量和成本。这就是多目标优化问题。它的解不是一个单一的最优点而是一系列权衡折衷后的“帕累托最优解集”。找到这个解集传统方法如加权求和法、ε-约束法要么需要先验知识权重要么计算效率低下。近年来元启发式算法因其强大的全局搜索能力和对问题先验知识依赖少的特点成为求解这类问题的利器。今天要深入探讨的就是其中一种新颖且高效的算法——金鹰算法。这个名字听起来颇具气势它模拟的是金鹰在自然界中独特的捕猎策略。你可能听说过粒子群、遗传算法但金鹰算法在解决高维、复杂的多目标问题上展现出了独特的优势。它不像遗传算法那样依赖复杂的交叉变异也不像粒子群那样容易陷入局部最优。金鹰算法通过模拟金鹰的盘旋、俯冲和攻击行为巧妙地平衡了探索和开发能力。探索是为了在广阔的解空间里寻找有潜力的区域而开发则是为了在找到的好区域里精耕细作找到更优的解。很多算法容易顾此失彼而金鹰算法的机制设计让它在这两者之间切换得更加自然和高效。本文的目的不是复述论文里的数学公式而是从一个实践者的角度带你手把手理解金鹰算法的核心思想并用MATLAB将其实现用于求解一个经典的多目标优化问题。你会看到从算法原理到代码落地的完整链条包括参数怎么调、迭代过程如何可视化、结果怎么分析。无论你是刚接触优化算法的学生还是需要在项目中快速应用一种新算法的工程师这篇内容都将提供一条清晰的路径。2. 金鹰算法核心原理拆解不止是模仿更是策略金鹰算法的灵感来源于金鹰的捕猎过程这个过程被抽象为三个阶段选择搜索空间、盘旋、俯冲攻击。听起来很生物但其背后的优化思想非常深刻。2.1 阶段一选择搜索空间——全局探索的起点金鹰捕猎时首先会在高空盘旋选择一个猎物丰富的区域。在算法中这对应于初始化阶段和早期的全局探索。算法开始时会随机生成一群“金鹰”即候选解均匀分布在解空间内。但关键不在于随机生成而在于如何评估哪个区域“猎物丰富”。在单目标优化中这很简单直接比较适应度值目标函数值。但在多目标优化中一个解可能在一个目标上很好在另一个目标上很差。因此我们需要一个指标来衡量解的质量。这里引入非支配排序和拥挤度距离的概念这是处理多目标问题的基石。首先进行非支配排序如果一个解A在所有目标上都不比解B差且至少在一个目标上严格优于B则称A支配B。不被任何其他解支配的解称为帕累托最优解它们构成第一前沿面。然后从种群中移除这些解在剩下的解中继续寻找不被支配的解构成第二前沿面以此类推。这样种群就被分成了不同的等级前沿面第一前沿面的解质量最高。仅仅排序还不够为了保持解在帕累托前沿上的分布性即解的多样性不要都挤在一起我们计算每个解在其所在前沿面中的拥挤度距离。简单说就是计算一个解与其相邻两个解在每个目标维度上的距离之和。拥挤度距离大的解说明它周围比较“空旷”保留它有利于维持种群的多样性。在金鹰算法的“选择搜索空间”阶段我们可以认为那些处于较低前沿面排名靠后且拥挤度距离很小的解所在的区域是“贫瘠”的金鹰算法搜索应该减少在这些区域的投入而更多关注那些有潜力处于高前沿面或能增加多样性拥挤度距离大的区域。虽然标准GEO论文可能未显式使用帕累托排序但在多目标适配时这个思想是融入其中的指导着种群的整体移动趋势。2.2 阶段二盘旋——局部开发的精细调整金鹰选定大致区域后会开始在该区域上空盘旋不断调整位置锁定具体目标。在算法中这对应于局部搜索或开发阶段。此时算法已经通过前期的探索定位到了几个有希望的“猎物”当前最优解集即帕累托前沿上的解。盘旋的数学模型通常用一个螺旋方程来描述。金鹰的位置更新会围绕着选定的“猎物”可能是当前种群中的最优解之一或者是一个由多个优秀解构成的中心点进行。更新公式可能包含随机角度和递减的盘旋半径。这个阶段的关键在于精细调整。搜索步长相对较小允许金鹰在潜在最优解附近进行深度挖掘试图找到比当前记录更优的解即在某个目标上改进而不恶化其他目标。这个阶段平衡了“利用已知好信息”和“避免过早收敛”。在多目标语境下“猎物”可能不是单一解。一种常见的策略是对于每只金鹰从当前的非支配解集存档集中随机选择一个作为其盘旋中心。这样不同的金鹰围绕不同的优秀解进行开发有助于同时沿帕累托前沿的多个方向进行精细化搜索。2.3 阶段三俯冲攻击——决定性的收敛行动最后金鹰从盘旋状态转为极速俯冲精准攻击猎物。在算法中这代表一种决定性的、趋向最优解的移动。俯冲攻击的更新公式通常表现为向目标位置的直线或加速运动步长更大方向性更强。这个阶段是算法收敛的关键。当盘旋阶段积累了足够的信息确认了有希望的方向后俯冲攻击使解快速向帕累托前沿靠拢。为了防止过度收敛而失去多样性所有解都攻击同一个点攻击的目标点需要精心选择。同样可以从存档集中选择或者引入一些随机扰动类似于变异确保攻击的多样性。三个阶段的协同与参数控制算法通过一个或多个参数来控制这三个阶段的转换。例如可能有一个随时间递减的参数初期值较大促使算法更多进行“选择搜索空间”和“盘旋”探索后期值减小促使算法更多进行“俯冲攻击”开发。也可能为每个阶段设定一个执行概率。理解这些参数如何影响探索与开发的平衡是调参的核心。注意原始金鹰算法GEO论文主要针对单目标优化。将其应用于多目标时核心的移动策略盘旋、攻击方程可以保留但必须融入多目标优化的选择机制如上述的非支配排序和拥挤度距离来更新种群和维持存档集。这通常被称为“多目标金鹰算法”。3. 多目标优化问题的MATLAB建模与GEO算法实现框架在动手写代码之前我们必须先把问题定义清楚。我们选择一个经典的测试函数ZDT1。它被广泛用于评估多目标算法的性能因为它的帕累托前沿是已知的、凸的曲线便于我们验证算法的正确性。ZDT1问题有两个目标需要最小化有30个决策变量。它的数学定义是f1(x) x1f2(x) g(x) * [1 - sqrt(x1 / g(x))]其中 g(x) 1 9 * (sum_{i2}^{n} x_i) / (n-1)决策变量 x_i 在 [0,1] 范围内。我们的目标是找到一组解使得f1和f2都无法在不损害对方的情况下进一步降低。这组解在目标空间f1-f2平面中会形成一条从(0,1)到(1,0)的曲线。接下来我们搭建多目标金鹰算法MO-GEO的MATLAB实现框架。整个程序将包含以下几个核心模块主循环脚本控制迭代流程。初始化函数生成初始种群初始化存档集。目标函数计算计算每个个体的f1和f2。非支配排序与拥挤度计算函数核心中的核心用于评估和比较解。金鹰位置更新函数实现盘旋和攻击策略。存档集维护函数管理找到的非支配解。绘图函数实时或最终可视化帕累托前沿。3.1 核心数据结构设计在MATLAB中我们可以用矩阵来高效表示种群。假设种群大小为N决策变量维度为D。Population一个N x D的矩阵每一行是一个解。Obj一个N x M的矩阵M是目标数对于ZDT1M2每一行是对应解的目标函数值[f1, f2]。Archive存档集存储找到的非支配解同样包含其决策变量和目标值。大小动态变化但通常设一个上限如100以防止无限膨胀。3.2 非支配排序与拥挤度距离计算实现这是多目标优化的算法基石。我们需要一个函数non_dominated_sorting(pop_obj)。非支配排序步骤对于种群中的每个解p计算两个集合Sp被p支配的解集和np支配p的解的数量。所有np0的解放入第一前沿面F1。对于F1中的每个解p遍历其Sp中的每个解q将q的np减1。若q的np减为0则将q放入下一前沿面F2。重复步骤3直到所有解都被分配到某个前沿面。拥挤度距离计算步骤 对每个前沿面F内的解初始化该前沿面内所有解的拥挤距离为0。对于每个目标函数m根据目标m的值对该前沿面的解进行排序。将边界解目标值最大和最小的解的拥挤距离设为无穷大确保边界解总能被保留。对于中间的解i其拥挤距离累加上(obj(i1, m) - obj(i-1, m)) / (max_obj - min_obj)。这里obj(i, m)是解i在第m个目标上的值max_obj和min_obj是该前沿面内在目标m上的最大值和最小值。计算完成后每个解有两个关键属性前沿面等级rank越小越好和拥挤度距离distance越大越好。选择时优先选择rank小的解若rank相同则选择拥挤度距离大的解。这被称为“偏序关系”是NSGA-II等算法的核心选择策略我们可以直接借鉴到MO-GEO中。3.3 金鹰位置更新策略的多目标适配这是将单目标GEO转化为多目标的关键。在单目标中金鹰向“全局最优”或“个人历史最优”移动。在多目标中没有单一的全局最优。我们的策略是为每只金鹰选择目标对于种群中的第i只金鹰从当前存档集Archive中随机选择一个解作为其当前迭代的“目标猎物”Target_i。这确保了搜索方向朝着帕累托前沿的不同部分。盘旋行为模拟金鹰围绕目标猎物盘旋。位置更新公式可以设计为X_new X_old a * (Target_i - X_old) b * (rand - 0.5) * Levy_flight其中a是趋近系数b是盘旋扰动系数Levy_flight是一个莱维飞行随机步长能产生偶尔的大步长跳跃有助于跳出局部最优。(rand-0.5)产生一个[-0.5, 0.5]的随机方向。攻击行为以一定概率执行模拟金鹰俯冲。位置更新更直接X_new X_old c * (Target_i - X_old) d * randn其中c是攻击系数通常1表示加速冲向目标d是攻击随机扰动。randn是高斯随机数提供局部扰动。阶段选择可以设置一个概率P每次迭代时以概率P执行盘旋以概率1-P执行攻击。或者用一个随时间变化的参数来控制前期多盘旋探索后期多攻击开发。更新后需要检查新位置是否超出决策变量的边界[lb, ub]并进行处理如边界吸收或反射。3.4 存档集维护机制存档集Archive存储算法找到的所有非支配解。它需要动态更新将新生成的子代种群与当前存档集合并。对合并后的集合进行非支配排序。从第一前沿面开始向新的存档集中添加解直到添加的解数量达到存档集上限ArchiveSize。如果添加完一个完整的前沿面后存档集数量超过了上限则根据该前沿面内解的拥挤度距离从大到小选择直到填满存档集。这个过程保证了存档集始终是当前找到的最好且最具多样性的非支配解近似。4. MATLAB代码逐行详解与关键参数调试心得下面我将结合代码片段详细解释MO-GEO的实现并分享一些关键的调试经验。假设我们的主函数名为MO_GEO_ZDT1。%% 1. 问题定义与参数设置 clear; clc; M 2; % 目标数 D 30; % 决策变量维度 (ZDT1问题) lb zeros(1, D); % 下界 ub ones(1, D); % 上界 max_iter 200; % 最大迭代次数 N 100; % 种群大小 ArchiveSize 100; % 存档集大小 % 金鹰算法特定参数 a 0.5; % 盘旋趋近系数 b 0.1; % 盘旋扰动系数 c 1.5; % 攻击系数 d 0.05; % 攻击扰动系数 P 0.7; % 执行盘旋行为的概率 (1-P为攻击概率)参数设置心得N和max_iter种群大小和迭代次数是计算资源与求解精度的权衡。对于ZDT1这种30维的问题N100max_iter200通常是个不错的起点能在合理时间内得到较好的前沿。如果问题更复杂可以适当增大。a, b, c, d这些是GEO的核心参数。a和c控制着向目标移动的强度。a盘旋通常小于1表示缓慢接近c攻击通常大于1表示快速冲刺。b和d是随机扰动项防止算法陷入局部最优。b可以稍大以增强探索d应较小以确保攻击的精准性。初始调试时可以参考文献的默认值然后微调。P盘旋概率。初期可以设高一些如0.8加强探索后期可以动态降低加强开发。这里我们简化为固定值。%% 2. 初始化 % 2.1 初始化种群 Population repmat(lb, N, 1) rand(N, D) .* repmat(ub-lb, N, 1); % 2.2 计算初始目标值 Obj zeros(N, M); for i 1:N Obj(i, :) ZDT1(Population(i, :)); % ZDT1是自定义的目标函数 end % 2.3 初始化存档集 (通过非支配排序获取第一前沿面) [Fronts, ~] non_dominated_sorting(Obj); Archive_Pop Population(Fronts{1}, :); % 决策变量 Archive_Obj Obj(Fronts{1}, :); % 目标值 % 如果初始前沿面解太多按拥挤度截断 if size(Archive_Obj, 1) ArchiveSize [~, idx] sort(crowding_distance(Archive_Obj), descend); Archive_Pop Archive_Pop(idx(1:ArchiveSize), :); Archive_Obj Archive_Obj(idx(1:ArchiveSize), :); end初始化注意事项种群初始化采用简单随机生成对于复杂问题可以考虑拉丁超立方抽样以获得更好的初始分布。存档集初始化至关重要。直接取第一前沿面但如果初始解质量很差存档集可能为空或很差。我们的代码处理了这种情况并在一开始就进行了拥挤度截断确保存档集大小可控。%% 3. 主迭代循环 for iter 1:max_iter % 3.1 为当前种群中的每个个体从存档集中随机选择一个目标 new_Population zeros(N, D); for i 1:N % 随机选择一个存档解作为目标 target_idx randi(size(Archive_Obj, 1)); Target Archive_Pop(target_idx, :); % 决定执行盘旋还是攻击 if rand() P % 盘旋行为 levy_step levy_flight(D); % 生成一个D维的Levy飞行步长 new_Population(i, :) Population(i, :) ... a * (Target - Population(i, :)) ... b * (rand(1, D) - 0.5) .* levy_step; else % 攻击行为 new_Population(i, :) Population(i, :) ... c * (Target - Population(i, :)) ... d * randn(1, D); end % 边界处理越界则拉回边界 new_Population(i, :) max(new_Population(i, :), lb); new_Population(i, :) min(new_Population(i, :), ub); end % 3.2 计算子代目标值 new_Obj zeros(N, M); for i 1:N new_Obj(i, :) ZDT1(new_Population(i, :)); end % 3.3 合并父代和子代种群 combined_Pop [Population; new_Population]; combined_Obj [Obj; new_Obj]; % 3.4 环境选择从合并种群中选择N个个体进入下一代 [Fronts, Ranks] non_dominated_sorting(combined_Obj); next_Pop_idx []; next_front 1; % 按前沿面等级依次添加直到数量达到或超过N while length(next_Pop_idx) length(Fronts{next_front}) N next_Pop_idx [next_Pop_idx; find(Ranks next_front)]; next_front next_front 1; end % 如果添加当前前沿面会超出N则根据拥挤度距离选择 if length(next_Pop_idx) N current_front_indices find(Ranks next_front); current_front_objs combined_Obj(current_front_indices, :); [~, sorted_idx] sort(crowding_distance(current_front_objs), descend); needed N - length(next_Pop_idx); next_Pop_idx [next_Pop_idx; current_front_indices(sorted_idx(1:needed))]; end % 更新下一代种群 Population combined_Pop(next_Pop_idx, :); Obj combined_Obj(next_Pop_idx, :); % 3.5 更新存档集 % 合并当前存档集和子代种群中的非支配解这里用子代也可用合并后的种群 candidate_Pop [Archive_Pop; new_Population]; candidate_Obj [Archive_Obj; new_Obj]; % 对候选集进行非支配排序 [candidate_Fronts, ~] non_dominated_sorting(candidate_Obj); non_dominated_idx candidate_Fronts{1}; % 第一前沿面索引 Archive_Pop candidate_Pop(non_dominated_idx, :); Archive_Obj candidate_Obj(non_dominated_idx, :); % 如果存档集超过上限按拥挤度截断 if size(Archive_Obj, 1) ArchiveSize [~, idx] sort(crowding_distance(Archive_Obj), descend); Archive_Pop Archive_Pop(idx(1:ArchiveSize), :); Archive_Obj Archive_Obj(idx(1:ArchiveSize), :); end % 3.6 每隔一定代数输出信息或绘图 if mod(iter, 50) 0 fprintf(迭代 %d, 存档集大小: %d\n, iter, size(Archive_Obj, 1)); % 绘制当前帕累托前沿近似 figure(1); scatter(Archive_Obj(:,1), Archive_Obj(:,2), 20, filled, b); xlabel(f1); ylabel(f2); title([迭代次数: , num2str(iter)]); grid on; drawnow; end end代码实现中的关键点与避坑指南莱维飞行Levy Flight的实现莱维飞行能有效增加探索能力。其步长服从重尾分布意味着大部分是小步长偶尔会有非常大的步长。一个简单的近似生成方法是使用Mantegna算法。你需要一个levy_flight(dim)函数。网上有很多实现但要注意数值稳定性避免步长无限大。一个常见实现是function step levy_flight(dim) beta 1.5; % 常用值 sigma (gamma(1beta)*sin(pi*beta/2)/(gamma((1beta)/2)*beta*2^((beta-1)/2)))^(1/beta); u randn(1, dim) * sigma; v randn(1, dim); step u ./ (abs(v).^(1/beta)); end在实际使用中可能需要对步长进行归一化或截断防止其破坏算法的稳定性。环境选择策略我们采用了和NSGA-II类似的(μλ)选择策略合并父代和子代从中选优。这比只从子代中选择(μ,λ)选择保留了更多的精英通常收敛性更好。关键在于non_dominated_sorting和crowding_distance这两个函数的正确实现。务必用简单的测试案例验证它们。存档集更新频率我们在每次迭代后都更新存档集。这计算开销稍大但能保证存档集始终是最新的。也可以每几代更新一次以提升速度。目标函数计算优化在循环中计算ZDT1是主要耗时点。如果可能尽量向量化操作。例如ZDT1函数可以改写为一次处理整个种群矩阵避免for循环。对于复杂问题这能显著提升速度。随机性算法中有多处随机操作选择目标、盘旋/攻击决策、随机步长。为了结果可复现可以在程序开始时用rng(1)固定随机数种子。但在实际研究和应用中通常需要多次独立运行如30次来统计算法的平均性能。5. 结果分析、可视化与算法性能评估运行完算法后我们得到了最终的Archive_Obj即算法找到的帕累托前沿近似解集。如何判断它的好坏5.1 可视化对比最直观的方法是画图。我们可以将算法得到的点与真实的帕累托前沿对于ZDT1是f2 1 - sqrt(f1)f1 ∈ [0,1]画在一起。%% 绘制最终结果对比 figure(2); scatter(Archive_Obj(:,1), Archive_Obj(:,2), 40, r, filled); hold on; % 绘制真实的帕累托前沿 f1_true linspace(0, 1, 100); f2_true 1 - sqrt(f1_true); plot(f1_true, f2_true, b-, LineWidth, 2); xlabel(f1); ylabel(f2); legend(MO-GEO 求解结果, 真实帕累托前沿); title(多目标金鹰算法求解ZDT1问题结果对比); grid on; hold off;观察要点收敛性红色的点算法结果是否紧密贴合蓝色的真实前沿线点离线越远说明收敛性越差。分布性红色的点是否均匀分布在整条前沿线上如果都挤在某个小段说明算法多样性保持不好。覆盖范围红色的点是否覆盖了从(0,1)到(1,0)的整个范围两端是否有解5.2 性能指标量化为了更客观地比较不同算法或不同参数下的性能我们需要量化指标。常用的有两个世代距离Generational Distance, GD衡量算法得到的解集与真实帕累托前沿之间的“平均距离”。值越小收敛性越好。GD sqrt( sum_{i1}^{|Q|} d_i^2 ) / |Q|其中Q是算法得到的解集d_i是解i到真实前沿上最近点的欧氏距离。反世代距离Inverted Generational Distance, IGD衡量真实帕累托前沿上的点与算法解集之间的“平均距离”。它同时评价收敛性和分布性。值越小越好。IGD sum_{j1}^{|P*} d_j / |P*|其中P*是真实前沿上均匀取样的点集d_j是点j到算法解集Q中最近点的距离。在MATLAB中实现这些指标需要已知的真实前沿点集P*可以从理论公式采样获得。function gd calculate_GD(approx_front, true_front) % approx_front: 算法得到的近似前沿 [N x M] % true_front: 真实帕累托前沿采样点 [K x M] distances pdist2(approx_front, true_front, euclidean); min_dist min(distances, [], 2); % 每个近似解到真实前沿的最小距离 gd sqrt(mean(min_dist .^ 2)); end function igd calculate_IGD(approx_front, true_front) distances pdist2(true_front, approx_front, euclidean); min_dist min(distances, [], 2); % 每个真实前沿点到近似解集的最小距离 igd mean(min_dist); end5.3 参数敏感性分析与调参建议金鹰算法的性能对参数比较敏感。没有一套参数放之四海而皆准。你需要针对你的具体问题进行调整。系统性调参可以采用网格搜索或实验设计方法。例如对关键参数a,c,P在其合理范围内取几个值如a[0.3,0.5,0.7],c[1.2,1.5,1.8],P[0.6,0.7,0.8]进行全组合实验。对每组参数独立运行算法多次如20次计算平均GD和IGD。选择综合指标最好的参数组合。自适应参数更高级的策略是让参数随着迭代动态变化。例如P盘旋概率可以随着迭代次数增加而线性减小前期侧重探索后期侧重开发。a和c也可以根据种群多样性如解集的平均拥挤度进行自适应调整。我的经验对于类似ZDT1的中等维度问题从a0.5,c1.5,P0.7开始调通常是个不错的起点。如果发现算法过早收敛解集多样性差可以尝试增大b盘旋扰动或P。如果发现收敛速度慢解集离真实前沿远可以尝试增大c或减小P。6. 超越ZDT1将MO-GEO应用于更复杂问题的思考ZDT1是一个理想的起点但它相对简单前沿连续、凸。在实际项目中你可能会遇到更棘手的问题高维目标问题Many-Objective当目标数量M大于3时称为高维目标优化。此时绝大多数解都互不支配非支配排序几乎失效拥挤度距离在高维空间中也难以有效衡量多样性。针对MO-GEO可能需要采用新的选择压力如基于参考点的选择NSGA-III、基于分解的方法MOEA/D。修改金鹰的“目标选择”策略。不再从存档集随机选而是让金鹰围绕一组预设的参考向量或权重向量进行搜索。约束处理实际问题常带有约束条件。例如ZDT1的变量范围[0,1]就是边界约束。更复杂的有不等式约束g(x)0和等式约束h(x)0。处理约束的常用方法有罚函数法将约束违反程度加到目标函数上将约束问题转化为无约束问题。简单但罚因子难调。可行性优先原则在非支配排序时优先选择可行解。比较两个解时1) 都可行按帕累托支配关系2) 一个可行一个不可行选可行的3) 都不可行选约束违反程度小的。这种方法可以自然地融入到我们现有的非支配排序框架中。离散或混合变量问题如果决策变量是离散的整数、类别或混合的标准GEO的连续位置更新公式不再适用。需要设计离散化的更新规则。例如对于二进制变量位置可以表示成概率通过sigmoid函数映射到[0,1]后与随机数比较来决定取0或1。对于整数变量更新后可以四舍五入。算法混合与改进元启发式算法的一个优势是易于混合。可以考虑局部搜索在GEO的“攻击”阶段后对产生的优秀解施加一个局部搜索如梯度下降、模式搜索进行深度挖掘。与其他算法混合例如引入差分进化DE的变异策略来增强种群的多样性或者用模拟退火的思想以一定概率接受劣解避免陷入局部最优。将MO-GEO应用到新问题时最关键的一步是清晰地定义你的目标函数和约束并将其编码到MATLAB函数中。然后从标准版本的MO-GEO开始观察它在哪里失败是收敛不到前沿还是多样性不足还是处理不了约束再有针对性地进行上述改进。最后分享一个我个人的调试习惯在算法运行时除了绘制目标空间的帕累托前沿我还会实时绘制一些其他指标如种群平均目标值的变化、存档集大小变化、决策变量空间的分布等。这些图能帮助你更直观地理解算法的动态行为比如是在持续优化还是已经停滞搜索是集中还是分散。这比只看最终结果更能揭示问题的本质。
返回列表