ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

改进火鹰优化算法FHO的MATLAB实现:混沌初始化+惯性权重+莱维飞行

改进火鹰优化算法FHO的MATLAB实现:混沌初始化+惯性权重+莱维飞行 简介这套资源是一份改进火鹰优化算法IFHO的MATLAB代码面向需要开展元启发式算法改进与基准测试对比的研究者、研究生或竞赛参与者可用于解决原始FHO算法收敛精度不足、种群多样性受限等问题。算法在原始FHO中引入Tent映射完成种群初始化使初始解分布更加均匀同时加入非线性复合自适应惯性权重随机抉择策略兼顾全局探索与局部开发能力。代码同时保留了原始FHO作为对照集成23个标准测试函数便于直接对比两种算法的收敛速度与寻优精度。压缩包内共11个文件均为MATLAB脚本.m算法主体、初始化、距离计算、函数绘图及主程序等模块拆分清晰整体仅11KB轻量易读。目前已有181人学习下载使用者可直接运行主程序复现IFHO与FHO在23种测试函数上的对比曲线也能借助模块化脚本将改进策略迁移至其他优化算法或工程优化问题中。1. 改进火鹰优化算法FHO的切入场景火鹰优化算法Fire Hawk OptimizationFHO是近年提出的元启发式算法它把全局最优解设为“主火”把候选解分成火鹰和猎物两组火鹰负责把火焰引向新区域猎物在火鹰和主火之间来回移动。标准FHO的实现成本低、全局趋势明显但直接在多峰函数上运行时后期往往所有个体都聚到同一个局部谷底种群多样性下降得非常快。所谓“改进FHO”通常不是替换整个搜索框架而是围绕初始化、步长和跳出机制做三处修补混沌映射生成初始种群、线性递减惯性权重控制收敛节奏、小概率触发莱维飞行逃出局部最优。下面这份MATLAB实现直接给出这三处修改对应的代码并用Rastrigin函数验证效果。2. 标准火鹰优化算法FHO的数学模型与MATLAB基线2.1 火鹰、猎物与主火的分层关系在FHO里每个候选解都被称为一个“个体”。按适应度从好到差排序后适应度最好的前nFH个个体作为火鹰剩下的个体都是猎物。猎物不是随机跑的它要归属于最近的一只火鹰。这个“归属”关系决定了猎物遇到危险时往哪个方向躲也决定它逃逸时搜索空间的范围。适应度最优秀的火鹰位置被称为主火记为GB它相当于整个搜索过程的记忆中心其他所有个体都直接或间接受到GB牵引。火鹰数量在标准FHO中一般取种群规模的10%左右最小不小于2。这个比例不能太高否则猎物数量太少局部搜索能力会被削弱也不能太低否则种群失去火鹰的引导作用。工程上常见的做法是nFH max(2, round(0.1 * nPop))这个取值在后续改进版里同样保留。2.2 FHO位置更新公式与搜索策略FHO的位置更新分为两个层面。第一个层面是火鹰自己向主火移动公式为FH_i_new FH_i_old r1 * (GB - r2 * FH_i_old)r1和r2都是[0,1]区间的均匀随机数。r1控制整体步长r2控制当前火鹰位置对自身更新方向的影响。第二个层面是猎物的更新猎物有“被困”和“逃逸”两种状态。被困时猎物围绕它所属的那只火鹰做局部搜索逃逸时猎物直接向主火方向移动。两种状态的数学表达分别是X_j_new X_j_old r1 * (FH_owner - r2 * X_j_old) % 被困 X_j_new X_j_old r1 * (GB - r2 * X_j_old) % 逃逸这两种状态在标准FHO中通过一个随机开关决定通常取rand 0.5为被困否则逃逸。这个随机开关让算法在前期和后期的行为完全随机也正是标准FHO后期收敛不稳定的原因。2.3 标准FHO的最小MATLAB代码片段为了给改进版做对比这里给出标准FHO最核心的位置更新过程。下面的代码省略了初始化、边界修正和统计部分只保留主循环for t 1:MaxIter [~, ord] sort(Fitness); FH X(ord(1:nFH), :); % 前 nFH 个最优个体作为火鹰 Prey X(ord(nFH1:end), :); % 其余作为猎物 % 火鹰位置更新 r1 rand(nFH, 1); r2 rand(nFH, 1); FH FH r1 .* (repmat(GB, nFH, 1) - r2 .* FH); % 猎物的归属火鹰由距离决定 D pdist2(Prey, FH); [~, owner] min(D, [], 2); PreyNew zeros(size(Prey)); for j 1:nPrey if rand 0.5 S FH(owner(j), :); % 被困围着归属火鹰 else S GB; % 逃逸扑向主火 end PreyNew(j, :) Prey(j, :) rand * (S - rand * Prey(j, :)); end X [FH; PreyNew]; Fitness fhd(X); [~, id] min(Fitness); GB X(id, :); end这段代码的执行顺序是先更新火鹰再给猎物重新分配归属关系然后逐个体更新猎物位置最后合并种群并重新计算适应度。需要留意的是代码里rand * (S - rand * Prey(j,:))使用了两个独立的随机数第一个负责步长缩放第二个负责原位置扰动这与标准FHO的数学公式保持一致。2.4 标准FHO的主要参数与边界修正参数含义常见取值nPop总个体数50300nFH火鹰数量round(0.1 * nPop)不小于2MaxIter最大迭代次数3001000r1向目标靠近的步长系数[0,1] 随机r2原位置衰减系数[0,1] 随机标准FHO没有显式的速度项所以边界修正显得特别重要。MATLAB里最简单的修正是X min(max(X, lb), ub)。如果lb和ub是标量这个写法可以直接生效如果lb和ub是向量需要确保它们形状一致例如lb repmat(lb, nPop, 1)。否则MATLAB会因维度不匹配报错这是初学者最容易踩的坑之一。3. 改进FHO的三个方向混沌初始化、自适应权重与莱维飞行3.1 标准FHO的早熟问题与改进目标标准FHO的随机开关让每个猎物在“被困”和“逃逸”之间均匀切换这个机制在迭代后期会带来两个副作用。第一被困概率恒定算法无法把重心从全局探索切换到局部开发第二后期所有猎物都离主火很近r1 * (S - r2 * X)产生的位移越来越小一旦落入局部平坦区域就很难跳出来。改进的目标是让算法在迭代前期保持足够大的搜索范围在后期保留一部分跳出能力同时用更合理的初始种群减少前几次迭代的盲目性。3.2 改进一Logistic混沌映射初始化种群随机初始化在低维空间问题不大但在30维以上的优化问题里均匀随机数往往会让初始种群聚集在搜索空间的局部区域。Logistic混沌映射是一种常见的替代方案公式为x_next 4 * x * (1 - x)只要初始x在(0,1)区间且不等于0.25、0.5、0.75迭代生成的序列就具备混沌特性能在[0,1]区间内产生比伪随机数更充分的遍历性。MATLAB实现非常简单X zeros(nPop, dim); seed rand(1, dim); for i 1:nPop seed 4 * seed .* (1 - seed); X(i, :) lb seed .* (ub - lb); end这里seed是维度向量每次迭代都对所有维度同时更新。将seed替换为标准FHO里的rand(nPop, dim)只改动初始化部分不改变主循环结构就能让初始种群在搜索空间里的分布更均匀。3.3 改进二线性递减惯性权重标准FHO的位置更新中旧位置的影响通过- r2 * X_old体现这个系数是纯随机的不会随迭代次数变化。更稳妥的做法是引入惯性权重w让前期w大、后期w小控制种群对旧位置的保留程度。线性递减公式为w(t) wMax - (wMax - wMin) * (t - 1) / (MaxIter - 1)wMax取0.95wMin取0.35这样在前期个体能保持更多历史位置信息搜索范围更大后期w变小个体更愿意跟随目标位置局部收敛能力增强。应用方式是把更新公式改写为X_new w * X_old r1 * (target - X_old)如果用“随机衰减系数”替代r2那么标准FHO里的两个随机数就变成一个随机数加一个确定性递减权重这会让算法行为更可控曲线也更平滑。3.4 改进三概率触发的莱维飞行突变莱维飞行是一种步长服从重尾分布的随机游走它的特点是大部分时间小步移动偶尔出现一次大幅度跳跃。这个特性非常适合作为跳出局部最优的突变算子。在改进FHO里我只让一小部分猎物触发莱维飞行概率取0.2左右避免过度破坏收敛。Mantegna算法生成莱维步长的核心代码如下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));step的维度是1*dim直接叠加到猎物位置时可以写成X step .* (GB - X)。由于莱维步长可能非常大需要对该向量做归一化再乘以搜索空间尺度防止越界后直接顶到边界上。3.5 改进后的完整更新流程改进版把猎物的随机开关改成动态概率pTrap 0.2 0.5 * (t / MaxIter)。迭代初期只有20%的猎物执行被困局部搜索其余80%执行逃逸全局搜索随着迭代进行被困比例逐渐涨到70%算法重心自然切换到局部精修。与此同时火鹰更新和猎物更新都使用线性递减权重w每隔一定概率加入莱维飞行突变。这样三个改进点互相咬合不会出现“前期就聚死”或“后期胡乱跳”的失衡情况。改进点解决的标准FHO缺陷引入参数Logistic混沌初始化初始种群分布差、多样性低无线性递减惯性权重旧位置影响随机、收敛节奏不可控wMax, wMin莱维飞行突变后期缺乏跳出局部最优的能力pLevy4. 改进版FHO的完整MATLAB代码与基准测试4.1 improvedFHO.m 函数全写下面给出完整的改进版FHO函数可以直接保存为improvedFHO.m。函数接口与标准元启发式算法保持一致传入目标函数句柄、维度和边界返回最优值、最优解和收敛曲线。function [bestValue, bestPos, curve] improvedFHO(fhd, dim, lb, ub, nPop, MaxIter, pLevy) % improvedFHO: 改进火鹰优化算法 % 改进点Logistic混沌初始化 线性递减惯性权重 莱维飞行突变 % % 输入 % fhd - 目标函数句柄输入(nPop,dim)矩阵输出(nPop,1)列向量 % dim - 决策变量维数 % lb, ub - 下界/上界标量或1*dim向量 % nPop - 种群规模建议20 % MaxIter - 最大迭代次数 % pLevy - 莱维飞行触发概率默认0.2 % 输出 % bestValue - 最优目标函数值 % bestPos - 最优解向量 % curve - 每代最优值MaxIter*1 if nargin 7 pLevy 0.2; end if isscalar(lb) lb repmat(lb, 1, dim); ub repmat(ub, 1, dim); end nFH max(2, round(0.1 * nPop)); nPrey nPop - nFH; % 改进1Logistic混沌映射初始化 X zeros(nPop, dim); seed rand(1, dim); for i 1:nPop seed 4 * seed .* (1 - seed); X(i, :) lb seed .* (ub - lb); end Fitness fhd(X); [bestValue, idx] min(Fitness); GB X(idx, :); curve zeros(MaxIter, 1); wMax 0.95; % 惯性权重上界 wMin 0.35; % 惯性权重下界 for t 1:MaxIter % 按适应度排序前 nFH 个作为火鹰 [Fitness, order] sort(Fitness); X X(order, :); FH X(1:nFH, :); Prey X(nFH1:end, :); % 改进2线性递减惯性权重 w wMax - (wMax - wMin) * (t - 1) / (MaxIter - 1); % 火鹰位置更新 r1 rand(nFH, dim); r2 rand(nFH, dim); FH w .* FH r1 .* (repmat(GB, nFH, 1) - r2 .* FH); FH min(max(FH, lb), ub); % 猎物归属火鹰按欧氏距离 D pdist2(Prey, FH); [~, owner] min(D, [], 2); % 被困概率随迭代上升0.2 - 0.7 pTrap 0.2 0.5 * (t / MaxIter); PreyNew zeros(nPrey, dim); for j 1:nPrey idxFH owner(j); if rand pTrap % 被困局部搜索 if rand 0.5 target FH(idxFH, :); else target FH(randi(nFH), :); % 随机火鹰保持多样性 end else % 逃逸全局探索 if rand 0.7 target GB; else target FH(randi(nFH), :); end end r1 rand; PreyNew(j, :) w * Prey(j, :) r1 * (target - Prey(j, :)); end % 改进3概率触发莱维飞行突变 applyIdx rand(nPrey, 1) pLevy; if any(applyIdx) beta 1.5; sigma (gamma(1beta) * sin(pi*beta/2) / ... (gamma((1beta)/2) * beta * 2^((beta-1)/2)))^(1/beta); uMat randn(sum(applyIdx), dim) * sigma; vMat randn(sum(applyIdx), dim); step uMat ./ (abs(vMat).^(1/beta)); rowLen sqrt(sum(step.^2, 2)); rowLen(rowLen eps) 1; step step ./ rowLen; % 归一化限制步长尺度 PreyNew(applyIdx, :) Prey(applyIdx, :) ... 0.8 * step .* (repmat(GB, sum(applyIdx), 1) - Prey(applyIdx, :)); end PreyNew min(max(PreyNew, lb), ub); % 合并种群更新全局最优 X [FH; PreyNew]; Fitness fhd(X); [bestValue, idx] min(Fitness); GB X(idx, :); curve(t) bestValue; end bestPos GB; end这段代码有几个值得注意的细节。首先火鹰更新使用了矩阵运算一次完成所有火鹰的位置刷新猎物更新仍然逐个体进行这是为了保留“每只猎物映射到不同火鹰”的逻辑。其次pTrap放在循环内部每代变化不需要用户干预。最后莱维飞行只影响被applyIdx选中的行其余猎物的位置不受影响避免整体收敛曲线出现过高波动。4.2 用Rastrigin函数跑通调用关系Rastrigin函数是验证全局优化算法最常用的测试函数之一它的表达式为f(X) sum(X.^2 - 10*cos(2*pi*X) 10)在30维情况下理论最优值为0但局部极小值非常多。测试脚本如下clear; clc; rng(2024); dim 30; lb -100; ub 100; nPop 80; MaxIter 500; rastrigin (X) sum(X.^2 - 10*cos(2*pi*X) 10, 2); [bf, bx, curve] improvedFHO(rastrigin, dim, lb, ub, nPop, MaxIter, 0.2); fprintf(最优值 %.6e\n, bf); fprintf(最优解前3维 %.4f, %.4f, %.4f\n, bx(1), bx(2), bx(3)); semilogy(max(curve, 1e-300)); grid on; xlabel(迭代次数); ylabel(最佳适应度);rastrigin句柄里的sum(..., 2)是对每行求和输出列向量正好匹配改进版函数的输入输出约定。semilogy里加max(curve, 1e-300)是为了处理曲线中出现0的情况避免对数坐标下的警告。运行后如果不出意外最优值会远低于标准FHO在同样迭代次数下得到的结果。参数取值说明dim30维度过低无法体现多峰困难lb/ub-100/100搜索范围较大检验全局搜索nPop80种群不宜太小MaxIter500给足收敛时间pLevy0.2突变概率默认值4.3 收敛曲线解读与参数调整建议收敛曲线的形状直接反映三处改进是否生效。理想情况下前50代曲线斜率陡峭这是混沌初始化和较大w带来的全局搜索效果中间200代曲线进入缓慢下降阶段w持续变小猎物开始围绕火鹰局部精修最后阶段如果出现一次明显的向下跳变说明莱维飞行成功跳出局部最优。如果曲线一开始就平坦优先检查目标函数句柄是否写错尤其是sum的维度参数。如果后期曲线持续震荡说明pLevy取值过大可以降到0.1震荡幅度很小但收敛慢则把wMin从0.35提高到0.45。5. 把改进FHO用在工程优化前的向量化与置信度验证技巧5.1 三步把猎物种群更新改成矩阵运算上面的改进版代码为了可读性猎物更新用了循环。工程上遇到nPop在500以上、维度在30以上的问题循环会成为性能瓶颈。把猎物更新改成矩阵运算只需要三步。第一步用一个逻辑向量标记每个猎物是“被困”还是“逃逸”pFlag rand(nPrey, 1) pTrap;第二步根据标记构造目标位置矩阵T被困时T对应归属火鹰逃逸时T对应主火T zeros(nPrey, dim); T(pFlag, :) FH(owner(pFlag), :); T(~pFlag, :) repmat(GB, sum(~pFlag), 1);第三步一次性完成所有猎物的位置更新R1 rand(nPrey, 1); PreyNew w .* Prey R1 .* (T - Prey);这三步与循环版本在数学上完全等价但运行速度通常会快一个数量级。MATLAB的pdist2和矩阵广播在这里天然支持逻辑索引不需要额外循环。处理方式代码量相对耗时循环更新15行左右1.0向量化更新8行左右0.10.25.2 用随机种子做20次独立重复验证只跑一次改进版就判断“改进有效”是不可靠的。元启发式算法每次运行结果都会波动正确做法是在相同参数下循环20次统计最优值的中位数、平均数和标准差。MATLAB里用同一个随机种子先跑标准FHO再用另一个随机种子跑改进版无法统计更严谨的做法是先固定一组种子编号每个编号分别跑两个算法for k 1:20 rng(k, twister); [bf_base(k), ~, ~] FHO_baseline(fhd, dim, lb, ub, nPop, MaxIter); rng(k 1000, twister); [bf_improve(k), ~, ~] improvedFHO(fhd, dim, lb, ub, nPop, MaxIter, 0.2); end fprintf(标准FHO: 中位数 %.6e标准差 %.6e\n, median(bf_base), std(bf_base)); fprintf(改进FHO: 中位数 %.6e标准差 %.6e\n, median(bf_improve), std(bf_improve));这里要求标准FHO也封装成同样接口。如果bf_improve的中位数比bf_base低一到两个数量级同时标准差没有明显变大才可以认为改进有效。只用单次运行结果下结论在论文和工程报告里都说不过去。5.3 把改进FHO包成通用求解器直接接代价函数工程问题和基准测试的差别在于约束条件。最省事的做法是使用外点惩罚法把约束写成g(x) 0然后把惩罚项叠加到目标函数上再传给改进FHO。这样算法主体完全不需要改function f objWithPenalty(X) g constraintValue(X); % 每行对应一个个体每列对应一个约束 penalty sum(max(g, 0).^2, 2); % 二次惩罚项 f originalObjective(X) 1e4 * penalty; end惩罚系数取1e4是常见起点如果求解结果违反约束仍然明显就增大惩罚系数如果惩罚项压过了真实目标值导致算法只满足约束而不再优化目标则需要适当降低。改进FHO的混沌初始化和莱维飞行在复杂约束下依旧有效但pTrap的动态范围可能需要在离散变量问题里重新标定。离散问题还应在边界修正后加入取整操作否则算法会一直在非整数区域搜索。本文还有配套的精品资源点击获取
返回列表