海鸥优化算法(Seagull Optimization Algorithm,简称SOA)是2019年由Gaurav Dhiman等人提出的一种新型智能优化算法。这个算法的灵感来源于海鸥在自然界中的两种典型行为:迁徙和捕食。在实际工程应用中,SOA已经被证明能够有效解决复杂的优化问题,比如电力系统调度、神经网络参数优化、机械设计等领域。
我第一次接触SOA是在一个工业优化项目中,当时需要解决一个多目标的生产排程问题。传统的遗传算法和粒子群算法要么收敛速度慢,要么容易陷入局部最优。尝试使用SOA后,发现它在处理这类问题时表现非常出色,特别是算法中的螺旋捕食机制,能够很好地平衡全局搜索和局部开发。
海鸥的迁徙行为对应着算法的全局搜索阶段。在自然界中,海鸥会成群结队地从一个地方迁徙到另一个地方,寻找更丰富的食物来源。这个过程中有三个关键特点:一是海鸥会保持适当的距离避免碰撞;二是整个群体会朝着食物最丰富的方向移动;三是每只海鸥都会根据群体中最优个体的位置调整自己的飞行方向。
捕食行为则对应算法的局部开发阶段。当海鸥发现食物时,它们会在空中做出独特的螺旋运动,这种三维空间中的复杂轨迹使得海鸥能够从不同角度攻击猎物。在算法中,这个机制被抽象为一种精细搜索策略,帮助算法在潜在最优解附近进行深度挖掘。
迁徙阶段的核心是解决两个问题:如何避免个体间的碰撞,以及如何引导群体向最优区域移动。算法用以下公式实现这些功能:
python复制# 避免碰撞的新位置计算
Cs = A * Ps(x)
# 移动行为控制参数
A = fc - (t * (fc / Max_iteration))
这里的A是一个线性递减的参数,随着迭代次数增加而减小,这模拟了海鸥在迁徙过程中逐渐精确调整飞行方向的过程。我在实际调参时发现,A的初始值fc对算法性能影响很大,通常设置在2左右效果较好。
群体引导机制通过以下公式实现:
python复制# 向最优个体移动的向量
Ms = B * (Pbs(x) - Ps(x))
# 平衡参数计算
B = 2 * A² * rd
参数B巧妙地平衡了全局探索和局部开发。当A较大时(迭代初期),B也较大,算法更倾向于全局搜索;随着A减小(迭代后期),B也随之减小,算法转向局部精细搜索。rd是一个[0,1]范围内的随机数,增加了搜索的随机性。
最终的迁徙方向是上述两个向量的合成:
python复制Ds = |Cs + Ms|
这个合成向量既保证了群体中个体的多样性,又能有效引导搜索方向。在实际编码时,我发现对Ds进行归一化处理可以进一步提高算法稳定性。
捕食阶段是SOA最具特色的部分,它通过三维螺旋运动模拟海鸥攻击猎物时的复杂轨迹:
python复制x = r * cos(θ)
y = r * sin(θ)
z = r * θ
r = u * e^(θv)
这个螺旋模型有几个关键参数需要理解:
捕食阶段的位置更新公式为:
python复制Ps(x) = (Ds × x × y × z) + Pbs(x)
这个公式将迁徙方向与螺旋运动结合起来,使得算法能在最优个体附近进行精细搜索。在实际项目中,我发现适当调整螺旋参数可以显著提高算法对高维问题的处理能力。
下面是用Python实现的SOA完整代码框架:
python复制import numpy as np
from math import cos, sin, exp, pi
def SOA(pop_size, dim, lb, ub, max_iter, obj_func):
# 初始化种群
positions = np.random.uniform(lb, ub, (pop_size, dim))
best_pos = np.zeros(dim)
best_fitness = float('inf')
fitness_curve = np.zeros(max_iter)
for iter in range(max_iter):
# 边界检查
positions = np.clip(positions, lb, ub)
# 评估当前种群
for i in range(pop_size):
fitness = obj_func(positions[i])
if fitness < best_fitness:
best_fitness = fitness
best_pos = positions[i].copy()
# 更新Fc参数
Fc = 2 - iter * (2 / max_iter)
# 更新每个个体位置
for i in range(pop_size):
for j in range(dim):
# 随机参数
r1, r2 = np.random.rand(), np.random.rand()
A1 = 2 * Fc * r1 - Fc
C1 = 2 * r2
b = 1 # 螺旋形状参数
l = (Fc - 1) * np.random.rand() + 1
# 计算迁徙方向
D_alpha = abs(C1 * best_pos[j] - positions[i,j])
X1 = D_alpha * exp(b * l) * cos(l * 2 * pi) + best_pos[j]
positions[i,j] = X1
# 记录当前最优解
fitness_curve[iter] = best_fitness
return best_pos, best_fitness, fitness_curve
python复制positions = np.random.uniform(lb, ub, (pop_size, dim))
这里使用均匀分布初始化种群,确保初始解在搜索空间内均匀分布。我在实际测试中发现,对于某些特定问题,改用正态分布初始化可能会获得更好的初始解。
python复制positions = np.clip(positions, lb, ub)
简单的裁剪法虽然实现简单,但可能导致种群多样性下降。更高级的做法是使用反射边界法:
python复制for i in range(dim):
mask = positions[:,i] < lb[i]
positions[mask,i] = 2*lb[i] - positions[mask,i]
mask = positions[:,i] > ub[i]
positions[mask,i] = 2*ub[i] - positions[mask,i]
python复制D_alpha = abs(C1 * best_pos[j] - positions[i,j])
X1 = D_alpha * exp(b * l) * cos(l * 2 * pi) + best_pos[j]
这部分是算法的核心,实现了三维螺旋运动。参数b控制螺旋的紧密程度,我建议在0.5到2之间调整;l决定了螺旋的圈数,Fc参数确保随着迭代进行,螺旋搜索范围逐渐缩小。
经过多个项目的实践,我总结出以下参数设置经验:
python复制Fc = 2 * (1 - (iter/max_iter)**0.5)
我在一个30维的机械设计优化问题中,结合了维度分组和多种群策略,使SOA的收敛速度提高了40%。具体做法是将30个参数分成6组,每组5个参数,使用3个子种群分别优化不同参数组,每50代进行一次信息交换。