【多目标海鳟鱼算法,Matlab源代码】 MOSSA
海鳟鱼算法(MOSSA)这个优化算法有点意思,它模仿了海洋中鳟鱼群觅食时那种既分散又协作的行为模式。咱们今天不扯复杂的数学推导,直接上Matlab代码,边看边聊实现细节。
先看种群初始化部分。算法从随机生成候选解开始,这里用了个挺巧妙的边界约束方式:
function pop = InitializePopulation(popSize, varMin, varMax, nVar) pop = zeros(popSize, nVar); for i = 1:popSize pop(i,:) = varMin + (varMax - varMin).*rand(1, nVar); end end这个初始化函数通过varMin和varMax控制解空间范围,每个维度独立生成随机数。注意这里的.^运算符用的妙,直接实现了向量化操作,比循环赋值效率高得多。初始化质量直接影响算法收敛速度,所以边界处理很重要。
适应度计算部分需要特别注意多目标特性:
function [fitness, objectives] = EvaluatePopulation(pop) objectives = zeros(size(pop,1), 2); % 双目标示例 for i = 1:size(pop,1) x = pop(i,:); objectives(i,1) = sum(x.^2); % 目标函数1:解向量的平方和 objectives(i,2) = sum((x-2).^2); % 目标函数2:偏移后的平方和 end fitness = ParetoRanking(objectives); % 非支配排序 end这里展示了经典的双目标测试函数。实际应用时需要替换这两个目标函数,比如可以把其中一个改成约束违反程度。注意ParetoRanking这个自定义函数,它实现了非支配排序机制——就像班级里选班干部,先挑出最优的几个,再一层层筛选。
【多目标海鳟鱼算法,Matlab源代码】 MOSSA
来看核心的位置更新策略:
function newPos = UpdatePosition(current, best, worst, iter, maxIter) C = 2 * (1 - iter/maxIter); % 动态调整的趋同系数 if rand() < 0.5 % 向最优个体靠近 newPos = current + C * rand() * (best - current); else % 随机扰动 newPos = current + randn(size(current)) * (maxIter - iter)/maxIter; end % 边界处理 newPos = max(min(newPos, varMax), varMin); end这个位置更新规则体现了算法的核心思想:前期(iter较小时)更多进行全局探索,后期(iter接近maxIter)偏向局部开发。C系数随时间递减的设计挺有意思,类似模拟退火中的温度下降策略。边界处理那行代码写的很紧凑,用max(min())实现向量化约束,比用循环优雅多了。
算法运行的主循环里有个关键操作——拥挤度计算:
function crowding = CrowdingDistance(objectives) [N, M] = size(objectives); crowding = zeros(N,1); for m = 1:M [~, order] = sort(objectives(:,m)); crowding(order(1)) = Inf; crowding(order(end)) = Inf; fmin = objectives(order(1), m); fmax = objectives(order(end), m); for i = 2:(N-1) crowding(order(i)) = crowding(order(i)) + ... (objectives(order(i+1),m) - objectives(order(i-1),m)) / (fmax - fmin); end end end这段代码实现了NSGA-II中的拥挤度计算策略。注意给边界点设置Inf的处理,保证帕累托前沿的端点永远被保留。归一化处理(除以fmax-fmin)很重要,防止不同量纲的目标函数导致计算偏差。这种密度估计方法能有效维持解集的多样性。
跑完算法后可视化帕累托前沿是检验效果的关键:
function PlotParetoFront(objectives) [~,idx] = unique(objectives,'rows'); scatter(objectives(idx,1), objectives(idx,2), 'filled'); xlabel('目标1'); ylabel('目标2'); title('帕累托前沿'); grid on; end这里用散点图展示非支配解,注意unique函数去除了重复解。实际应用中可能需要更复杂的可视化,比如3D散点图或者平行坐标图,特别是目标函数超过两个时。
几个实战建议:
- 处理高维问题时,适当增加初始种群规模(popSize建议50+)
- 约束处理可以修改适应度计算部分,采用罚函数法
- 算法参数(如C系数)需要根据问题特性调整
- 并行化评估可以显著加速,用parfor替换循环评估
这个算法在工程优化、参数调优等领域效果不错,特别是当目标函数计算开销较大时。代码实现保留了足够的扩展性,比如想增加新的搜索策略,直接在UpdatePosition里加分支就行。下次遇到多目标优化问题,不妨试试这个鱼群启发的算法,说不定会有惊喜。