人工蜂群算法(Artificial Bee Colony, ABC)
人工蜂群算法是由土耳其学者 Karaboga 于 2005 年提出的一种基于蜜蜂采蜜行为的群体智能优化算法。该算法通过模拟蜂群中不同角色蜜蜂的分工协作,实现对优化问题解空间的高效搜索。
蜜蜂采蜜行为启发
在自然界中,蜜蜂群体通过精妙的信息共享机制,能够高效地发现并开采高质量的花蜜源。这种集体智慧为优化算法设计提供了深刻启发。
蜜蜂的采蜜行为具有以下关键特征:
- 自组织性:蜂群中无中央控制者,每只蜜蜂根据局部信息做出决策
- 分工协作:不同角色的蜜蜂承担不同任务,协同完成全局搜索
- 正反馈机制:高质量食物源吸引更多蜜蜂前往开采
- 信息共享:蜜蜂通过“摇摆舞“在蜂巢中传递食物源的位置和质量信息
在 ABC 算法中,优化问题的每一个可行解被类比为一个“食物源“,解的质量(目标函数值)对应食物源的花蜜量。蜂群通过反复搜索和评估,逐步逼近最优解。
三种蜂的角色与分工
ABC 算法将蜂群划分为三种角色:引领蜂(Employed Bee)、跟随蜂(Onlooker Bee)和侦察蜂(Scout Bee),各自承担不同的搜索任务。
引领蜂(Employed Bee)
- 每只引领蜂对应一个食物源,负责在该食物源邻域进行局部搜索
- 搜索完成后返回蜂巢,通过摇摆舞向跟随蜂传递食物源信息
- 引领蜂的数量等于食物源的数量
跟随蜂(Onlooker Bee)
- 在蜂巢中观察引领蜂的摇摆舞,根据食物源质量按概率选择前往的食物源
- 选择概率与食物源的适应度成正比(轮盘赌选择)
- 到达食物源后,在其邻域进行进一步的局部搜索
侦察蜂(Scout Bee)
- 当某个食物源经过多次开采仍无法改进时(达到 limit 次数),对应的引领蜂转变为侦察蜂
- 侦察蜂放弃当前食物源,随机生成一个新的食物源
- 侦察蜂的存在保证了算法的全局搜索能力,避免陷入局部最优
三种蜂的协作关系
| 角色 | 搜索类型 | 核心功能 | 对应算法阶段 |
|---|---|---|---|
| 引领蜂 | 局部搜索 | 开发已知食物源 | 邻域搜索 |
| 跟随蜂 | 偏好搜索 | 集中开发优质食物源 | 概率选择+邻域搜索 |
| 侦察蜂 | 全局搜索 | 发现新的食物源区域 | 随机初始化 |
算法流程
ABC 算法的主循环包含四个阶段:初始化阶段、引领蜂阶段、跟随蜂阶段和侦察蜂阶段。
算法伪代码
1. 初始化:随机生成 SN 个食物源(SN 为种群规模的一半)
2. 评估每个食物源的适应度
3. 设置计数器 trial[i] = 0, i = 1, 2, ..., SN
4. REPEAT
5. 【引领蜂阶段】
6. FOR 每个引领蜂 i = 1 to SN
7. 在食物源 x_i 的邻域产生新候选解 v_i
8. IF f(v_i) 优于 f(x_i) THEN
9. x_i = v_i; trial[i] = 0
10. ELSE
11. trial[i] = trial[i] + 1
12. END IF
13. END FOR
14. 【跟随蜂阶段】
15. 计算每个食物源的选择概率 p_i
16. FOR 每个跟随蜂
17. 按概率 p_i 选择一个食物源 x_i
18. 在 x_i 邻域产生新候选解 v_i
19. IF f(v_i) 优于 f(x_i) THEN
20. x_i = v_i; trial[i] = 0
21. ELSE
22. trial[i] = trial[i] + 1
23. END IF
24. END FOR
25. 【侦察蜂阶段】
26. IF 存在 trial[i] > limit THEN
27. 将 x_i 替换为随机生成的新食物源
28. trial[i] = 0
29. END IF
30. 记录当前最优解
31. UNTIL 满足终止条件
流程说明
- 终止条件:通常为达到最大迭代次数 MCN(Maximum Cycle Number)
- 种群规模:总蜂数 = 2 * SN(引领蜂 SN 只 + 跟随蜂 SN 只)
- limit 参数:控制食物源被放弃的阈值,通常设为 \( \text{limit} = SN \times D \),其中 \( D \) 为问题维度
食物源更新公式
食物源的更新是 ABC 算法的核心操作,决定了算法的搜索精度和收敛速度。
标准更新公式
引领蜂和跟随蜂在食物源 \( x_i \) 的邻域产生新候选解 \( v_i \) 的公式为:
\[ v_{ij} = x_{ij} + \phi_{ij} (x_{ij} - x_{kj}) \]
其中:
- \( i \) 为当前食物源编号,\( i \in {1, 2, \ldots, SN} \)
- \( j \) 为随机选择的维度,\( j \in {1, 2, \ldots, D} \)
- \( k \) 为随机选择的另一个食物源编号,\( k \neq i \)
- \( \phi_{ij} \) 为 \([-1, 1]\) 上的均匀随机数
公式分析
该更新公式具有以下特点:
- 差分扰动:\( x_{ij} - x_{kj} \) 项引入了两个食物源之间的差分信息
- 自适应步长:随着搜索推进,食物源之间的距离缩小,步长自动减小
- 单维更新:每次仅对一个随机维度进行扰动,保证了搜索的精细性
边界处理
当新解超出搜索范围 \([lb_j, ub_j]\) 时,需要进行边界处理:
\[ v_{ij} = \begin{cases} lb_j & \text{if } v_{ij} < lb_j \ ub_j & \text{if } v_{ij} > ub_j \end{cases} \]
适应度与选择概率
适应度函数将目标函数值映射为非负值,选择概率基于适应度进行轮盘赌选择。
适应度函数
对于最小化问题,适应度函数定义为:
\[ \text{fit}_i = \begin{cases} \dfrac{1}{1 + f_i} & \text{if } f_i \geq 0 \[6pt] 1 + |f_i| & \text{if } f_i < 0 \end{cases} \]
其中 \( f_i \) 为食物源 \( x_i \) 的目标函数值。
选择概率
跟随蜂选择食物源 \( x_i \) 的概率为:
\[ p_i = \frac{\text{fit}i}{\sum{j=1}^{SN} \text{fit}_j} \]
该概率确保了适应度高的食物源获得更多跟随蜂的关注,实现了对优质解区域的强化搜索。
选择概率的改进形式
为避免选择概率过于集中,有时采用如下改进形式:
\[ p_i = 0.9 \times \frac{\text{fit}i}{\max{j} \text{fit}_j} + 0.1 \]
该形式保证了每个食物源至少有 0.1 的被选概率,维持了种群多样性。
实际案例分析
以求解二维 Sphere 函数最小值为例,展示 ABC 算法的完整计算过程。
问题定义
求解以下优化问题:
\[ \min f(x_1, x_2) = x_1^2 + x_2^2, \quad -5 \leq x_1, x_2 \leq 5 \]
已知全局最优解为 \( x^* = (0, 0) \),最优值 \( f^* = 0 \)。
参数设置
- 食物源数量 \( SN = 4 \)
- 问题维度 \( D = 2 \)
- limit = \( SN \times D = 8 \)
- 最大迭代次数 MCN = 3(此处仅演示少量迭代)
第一步:初始化食物源
随机生成 4 个食物源(使用公式 \( x_{ij} = lb_j + \text{rand}(0,1) \times (ub_j - lb_j) \)):
| 食物源 | \( x_1 \) | \( x_2 \) | \( f(x) \) | 适应度 fit | trial |
|---|---|---|---|---|---|
| \( x_1 \) | 2.0 | -3.0 | 13.0 | 0.0714 | 0 |
| \( x_2 \) | -1.5 | 1.0 | 3.25 | 0.2353 | 0 |
| \( x_3 \) | 4.0 | 2.0 | 20.0 | 0.0476 | 0 |
| \( x_4 \) | -0.5 | -1.5 | 2.50 | 0.2857 | 0 |
第二步:引领蜂阶段(第1次迭代)
引领蜂 1:当前食物源 \( x_1 = (2.0, -3.0) \)
- 随机选择维度 \( j = 1 \),随机选择 \( k = 3 \)
- \( \phi = 0.6 \)(随机生成)
- \( v_{11} = 2.0 + 0.6 \times (2.0 - 4.0) = 2.0 - 1.2 = 0.8 \)
- 候选解 \( v_1 = (0.8, -3.0) \),\( f(v_1) = 0.64 + 9.0 = 9.64 \)
- 由于 \( 9.64 < 13.0 \),更新 \( x_1 = (0.8, -3.0) \),trial[1] = 0
引领蜂 2:当前食物源 \( x_2 = (-1.5, 1.0) \)
- 随机选择维度 \( j = 2 \),随机选择 \( k = 4 \)
- \( \phi = -0.3 \)
- \( v_{22} = 1.0 + (-0.3) \times (1.0 - (-1.5)) = 1.0 - 0.75 = 0.25 \)
- 候选解 \( v_2 = (-1.5, 0.25) \),\( f(v_2) = 2.25 + 0.0625 = 2.3125 \)
- 由于 \( 2.3125 < 3.25 \),更新 \( x_2 = (-1.5, 0.25) \),trial[2] = 0
引领蜂 3:当前食物源 \( x_3 = (4.0, 2.0) \)
- 随机选择维度 \( j = 1 \),随机选择 \( k = 2 \)
- \( \phi = 0.8 \)
- \( v_{31} = 4.0 + 0.8 \times (4.0 - (-1.5)) = 4.0 + 4.4 = 8.4 \)
- 边界处理:\( v_{31} = 5.0 \)(超出上界)
- 候选解 \( v_3 = (5.0, 2.0) \),\( f(v_3) = 25.0 + 4.0 = 29.0 \)
- 由于 \( 29.0 > 20.0 \),不更新,trial[3] = 1
引领蜂 4:当前食物源 \( x_4 = (-0.5, -1.5) \)
- 随机选择维度 \( j = 2 \),随机选择 \( k = 1 \)
- \( \phi = 0.4 \)
- \( v_{42} = -1.5 + 0.4 \times (-1.5 - (-3.0)) = -1.5 + 0.6 = -0.9 \)
- 候选解 \( v_4 = (-0.5, -0.9) \),\( f(v_4) = 0.25 + 0.81 = 1.06 \)
- 由于 \( 1.06 < 2.50 \),更新 \( x_4 = (-0.5, -0.9) \),trial[4] = 0
第三步:跟随蜂阶段
更新后的食物源状态:
| 食物源 | \( f(x) \) | 适应度 fit | 选择概率 \( p_i \) |
|---|---|---|---|
| \( x_1 \) | 9.64 | 0.0940 | 0.1313 |
| \( x_2 \) | 2.3125 | 0.3017 | 0.4213 |
| \( x_3 \) | 20.0 | 0.0476 | 0.0665 |
| \( x_4 \) | 1.06 | 0.4854 | 0.3809 |
选择概率计算示例:\( p_2 = \frac{0.3017}{0.0940 + 0.3017 + 0.0476 + 0.4854} = \frac{0.3017}{0.7164} \approx 0.4213 \)
跟随蜂按照概率 \( p_i \) 选择食物源并进行类似的邻域搜索操作。
第四步:侦察蜂阶段
检查所有 trial 值,此时最大值为 trial[3] = 1,未超过 limit = 8,因此本轮不触发侦察蜂。
迭代结果
经过多轮迭代后,食物源逐步向全局最优 \( (0, 0) \) 收敛。当前最优解为 \( x_4 = (-0.5, -0.9) \),\( f = 1.06 \)。
Python 代码实现
以下给出 ABC 算法求解连续优化问题的完整 Python 实现。
import numpy as np
class ArtificialBeeColony:
"""人工蜂群算法(ABC)求解连续优化问题"""
def __init__(self, obj_func, lb, ub, dim, colony_size=50, max_iter=500, limit=None):
"""
参数:
obj_func: 目标函数(最小化)
lb: 搜索下界(标量或数组)
ub: 搜索上界(标量或数组)
dim: 问题维度
colony_size: 蜂群总数(引领蜂 + 跟随蜂)
max_iter: 最大迭代次数
limit: 食物源放弃阈值
"""
self.obj_func = obj_func
self.lb = np.array(lb) if np.iterable(lb) else np.full(dim, lb)
self.ub = np.array(ub) if np.iterable(ub) else np.full(dim, ub)
self.dim = dim
self.food_num = colony_size // 2 # 食物源数量 = 引领蜂数量
self.max_iter = max_iter
self.limit = limit if limit else self.food_num * dim
# 初始化
self.foods = None # 食物源位置
self.fitness = None # 适应度值
self.obj_values = None # 目标函数值
self.trial = None # 未改进计数器
self.best_solution = None
self.best_obj = np.inf
self.convergence_curve = []
def _init_food(self, index):
"""初始化或重置第 index 个食物源"""
self.foods[index] = self.lb + np.random.rand(self.dim) * (self.ub - self.lb)
self.obj_values[index] = self.obj_func(self.foods[index])
self.fitness[index] = self._calculate_fitness(self.obj_values[index])
self.trial[index] = 0
def _calculate_fitness(self, obj_value):
"""计算适应度"""
if obj_value >= 0:
return 1.0 / (1.0 + obj_value)
else:
return 1.0 + abs(obj_value)
def _generate_candidate(self, i):
"""在食物源 i 的邻域生成候选解"""
candidate = self.foods[i].copy()
# 随机选择一个维度
j = np.random.randint(0, self.dim)
# 随机选择一个不同的食物源
k = np.random.choice([idx for idx in range(self.food_num) if idx != i])
# 更新公式
phi = np.random.uniform(-1, 1)
candidate[j] = self.foods[i][j] + phi * (self.foods[i][j] - self.foods[k][j])
# 边界处理
candidate = np.clip(candidate, self.lb, self.ub)
return candidate
def _employed_bee_phase(self):
"""引领蜂阶段"""
for i in range(self.food_num):
candidate = self._generate_candidate(i)
candidate_obj = self.obj_func(candidate)
candidate_fit = self._calculate_fitness(candidate_obj)
# 贪心选择
if candidate_fit > self.fitness[i]:
self.foods[i] = candidate
self.obj_values[i] = candidate_obj
self.fitness[i] = candidate_fit
self.trial[i] = 0
else:
self.trial[i] += 1
def _onlooker_bee_phase(self):
"""跟随蜂阶段"""
# 计算选择概率
prob = self.fitness / self.fitness.sum()
for _ in range(self.food_num):
# 轮盘赌选择
i = np.random.choice(range(self.food_num), p=prob)
candidate = self._generate_candidate(i)
candidate_obj = self.obj_func(candidate)
candidate_fit = self._calculate_fitness(candidate_obj)
# 贪心选择
if candidate_fit > self.fitness[i]:
self.foods[i] = candidate
self.obj_values[i] = candidate_obj
self.fitness[i] = candidate_fit
self.trial[i] = 0
else:
self.trial[i] += 1
def _scout_bee_phase(self):
"""侦察蜂阶段"""
max_trial_idx = np.argmax(self.trial)
if self.trial[max_trial_idx] > self.limit:
self._init_food(max_trial_idx)
def _update_best(self):
"""更新全局最优解"""
current_best_idx = np.argmin(self.obj_values)
if self.obj_values[current_best_idx] < self.best_obj:
self.best_obj = self.obj_values[current_best_idx]
self.best_solution = self.foods[current_best_idx].copy()
def optimize(self):
"""执行优化"""
# 初始化种群
self.foods = np.zeros((self.food_num, self.dim))
self.fitness = np.zeros(self.food_num)
self.obj_values = np.zeros(self.food_num)
self.trial = np.zeros(self.food_num, dtype=int)
for i in range(self.food_num):
self._init_food(i)
self._update_best()
# 主循环
for iteration in range(self.max_iter):
self._employed_bee_phase()
self._onlooker_bee_phase()
self._scout_bee_phase()
self._update_best()
self.convergence_curve.append(self.best_obj)
return self.best_solution, self.best_obj
# 使用示例
if __name__ == "__main__":
# 定义测试函数: Rastrigin 函数
def rastrigin(x):
n = len(x)
return 10 * n + sum(xi**2 - 10 * np.cos(2 * np.pi * xi) for xi in x)
# 参数配置
dim = 10
lb = -5.12
ub = 5.12
# 创建 ABC 实例并求解
abc = ArtificialBeeColony(
obj_func=rastrigin,
lb=lb,
ub=ub,
dim=dim,
colony_size=80,
max_iter=1000,
limit=None # 使用默认值 food_num * dim
)
best_solution, best_obj = abc.optimize()
print(f"最优解: {best_solution}")
print(f"最优目标值: {best_obj:.6f}")
print(f"理论最优值: 0.0")
与其他算法对比
ABC 算法与其他主流群体智能优化算法在机制和性能上各有优劣。
机制对比
| 特征 | ABC | PSO(粒子群) | GA(遗传算法) | DE(差分进化) |
|---|---|---|---|---|
| 灵感来源 | 蜜蜂采蜜 | 鸟群觅食 | 自然选择 | 种群差异向量 |
| 搜索操作 | 邻域扰动 | 速度-位置更新 | 交叉+变异 | 差分变异+交叉 |
| 选择机制 | 贪心+轮盘赌 | 全局/局部最优引导 | 适者生存 | 贪心选择 |
| 参数数量 | 少(limit) | 中(w, c1, c2) | 多(交叉率, 变异率) | 中(F, CR) |
| 全局搜索能力 | 侦察蜂保证 | 惯性权重控制 | 变异算子保证 | 差分变异保证 |
| 局部搜索能力 | 中等 | 较强 | 一般 | 较强 |
性能对比
| 评价指标 | ABC | PSO | GA | DE |
|---|---|---|---|---|
| 收敛速度 | 中等 | 快 | 慢 | 快 |
| 解的精度 | 高 | 中 | 中 | 高 |
| 鲁棒性 | 强 | 中 | 强 | 强 |
| 参数敏感性 | 低 | 高 | 中 | 中 |
| 高维问题 | 中等 | 差 | 差 | 好 |
| 多模态问题 | 好 | 一般 | 好 | 好 |
ABC 的独特优势
- 控制参数少:核心参数仅有 limit 一个,降低了调参难度
- 平衡机制清晰:三种蜂的分工明确对应探索与开发的平衡
- 鲁棒性强:对不同类型的优化问题均具有较好的适应性
- 不易早熟:侦察蜂机制有效避免种群多样性丧失
应用注意事项与局限性
在实际应用中,需要根据问题特点合理配置参数,并认识到算法的固有局限。
参数设置建议
| 参数 | 推荐范围 | 说明 |
|---|---|---|
| colony_size | 40-100 | 蜂群总数,一般取 2*SN |
| limit | \( SN \times D \) | 经典设置,D 为维度 |
| max_iter | 500-5000 | 视问题复杂度而定 |
注意事项
-
limit 参数选择
- limit 过小:食物源频繁被放弃,收敛慢
- limit 过大:搜索停滞在局部最优区域
- 推荐值:\( \text{limit} = SN \times D \)
-
种群规模选择
- 低维问题(\( D < 10 \)):colony_size = 40-60
- 中维问题(\( 10 \leq D \leq 30 \)):colony_size = 60-100
- 高维问题(\( D > 30 \)):colony_size = 100-200
-
搜索范围设定
- 应基于问题的物理意义合理设定上下界
- 范围过大会降低搜索效率,范围过小可能遗漏最优解
-
终止条件选择
- 可采用最大迭代次数、目标函数精度、连续无改进次数等
- 建议结合多个终止条件
主要局限性
- 收敛速度较慢:单维更新策略导致高维问题中收敛速度不如 DE 和 PSO
- 局部搜索能力有限:标准更新公式的搜索步长受制于食物源间距
- 高维性能下降:随维度增加,单维扰动的搜索效率显著降低
- 缺乏记忆机制:不同于 PSO 的个体最优/全局最优记忆,ABC 仅保留当前食物源
常见改进策略
| 改进方向 | 方法 | 效果 |
|---|---|---|
| 加速收敛 | 引入全局最优引导项 | 提升收敛速度,可能损失多样性 |
| 增强局部搜索 | 多维同时扰动 | 提升高维问题性能 |
| 自适应参数 | limit 动态调整 | 平衡全局与局部搜索 |
| 混合策略 | 与 DE/PSO 结合 | 综合多种算法优势 |
| 离散优化 | 修改更新规则 | 扩展应用范围 |
典型应用领域
- 函数优化与数值计算
- 神经网络权重训练
- 工程结构优化设计
- 生产调度与资源分配
- 图像处理与特征选择
- 电力系统经济调度
ABC 算法以其简洁的结构、较少的控制参数和良好的鲁棒性,成为群体智能优化领域的重要方法之一。在实际应用中,建议结合问题特点选择合适的改进变体,并与其他算法进行比较实验,以获得最佳求解效果。