【启发式算法】灰狼优化算法(Grey Wolf Optimizer, GWO)详细介绍(Python)

📢本篇文章是博主启发式算法领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在👉启发式算法专栏:

【启发式算法】(13)---《灰狼优化算法(Grey Wolf Optimizer, GWO)(Python)》

灰狼优化算法(Grey Wolf Optimizer, GWO)详细介绍(Python)

目录

一、引言

二、灰狼社会等级与算法映射

三、狩猎行为的数学建模

[3.1 包围猎物(Encircling Prey)](#3.1 包围猎物(Encircling Prey))

[3.2 协同狩猎(Hunting)](#3.2 协同狩猎(Hunting))

[3.3 探索与开发(Exploration vs Exploitation)](#3.3 探索与开发(Exploration vs Exploitation))

四、算法流程

五、论文结果

[Python 灰狼算法实现](#[Python] 灰狼算法实现)

[Results 运行结果](#[Results] 运行结果)

[Notice 注意事项](#[Notice] 注意事项)

六、总结


一、引言

在现代计算智能领域,优化问题广泛存在于机器学习、工程设计、图像处理、路径规划等诸多应用中。传统梯度类优化方法在处理非凸、高维、不可导问题时表现受限,因此,基于自然界启发的**元启发式优化算法(Metaheuristics)**成为研究热点。

**灰狼优化算法(Grey Wolf Optimizer, GWO)**由 Mirjalili 等人于 2014 年提出,是一种模拟灰狼社会等级与狩猎行为的群体智能优化算法。GWO 算法结构简洁、参数少、全局搜索能力强,已在多个 benchmark 函数与工程问题中展现出优越性能。


二、灰狼社会等级与算法映射

灰狼群体具有严格的社会等级结构,GWO 算法将其映射为优化过程中的候选解:

狼等级 算法角色 优化含义
α(Alpha) 最优解 当前群体中的最佳候选解
β(Beta) 次优解 第二优解,辅助 Alpha 决策
δ(Delta) 第三优解 第三优解,参与引导搜索
ω(Omega) 其他个体 被引导的候选解,向 α、β、δ 学习

三、狩猎行为的数学建模

灰狼的狩猎行为主要包括三个阶段:包围猎物、追踪猎物、攻击猎物。GWO 算法将这三个阶段建模为如下数学形式。

3.1 包围猎物(Encircling Prey)

设猎物位置为 ,灰狼个体位置为 ,则包围行为定义如下:

其中,为系数向量,定义如下:

  • 随迭代线性减小,从 2 降至 0,控制探索与开发的转换;

  • 为随机向量,增强搜索的随机性。

3.2 协同狩猎(Hunting)

在 GWO 中,Alpha、Beta 和 Delta 狼负责估计猎物位置,其余个体根据它们的引导更新位置。具体公式如下:

首先计算与三只头狼的距离:

然后根据它们的引导更新位置:

最终位置更新为三者平均:

3.3 探索与开发(Exploration vs Exploitation)

GWO 通过调节参数实现探索与开发的动态平衡:

  • :搜索个体远离猎物,进行**全局探索 **;

  • :搜索个体靠近猎物,进行**局部开发**。

此外,向量引入随机扰动,有助于跳出局部最优,增强全局搜索能力。


四、算法流程

GWO 算法流程如下:

复制代码
1. 初始化灰狼种群 X_i (i = 1, 2, ..., N)
2. 计算每个个体的适应度
3. 记录 Alpha、Beta、Delta 狼
4. 对于每次迭代:
   a. 更新参数 a, A, C
   b. 对于每个个体:
      i. 根据 Alpha、Beta、Delta 更新位置
      ii. 计算新位置的适应度
   c. 更新 Alpha、Beta、Delta
5. 满足终止条件则结束,否则返回步骤 4

算法示例:

1.问题设定:Rastrigin 二维函数最小化

函数:f(x,y)=20+x2+y2−10(cos2πx+cos2πy)

全局最小值在 (0,0),f=0。

搜索范围:x,y∈-5,5

(曲面高低起伏,有很多局部极小,适合观察 GWO 如何跳出陷阱。)

2.初始化(t=0)

种群大小 N=5,随机生成 5 只灰狼(为便于手算,只保留 2 位小数):

编号 (x,y) f(x,y) 等级
1 ( 2.1, -1.3) 27.84 ω
2 (-0.8, 0.4) 8.24 β
3 ( 1.2, 2.4) 35.56 ω
4 (-0.3, -0.2) 1.92 α
5 ( 3.0, -2.5) 58.30 ω

立刻选出前三狼:

α = 4 号 (-0.3, -0.2)

β = 2 号 (-0.8, 0.4)

δ = 1 号 ( 2.1, -1.3)

3.第一次迭代(t=1)

3.1 更新控制参数

a = 2 → 0 线性递减,这里第一次迭代取 a=2。

r1,r2∈0,1 随机,假设本次:

r1=0.3, r2=0.8 →

A = 2a·r1 - a = 2·2·0.3 - 2 = -0.8

C = 2·r2 = 1.6

3.2 对任意一只普通狼(以 3 号为例)演示完整更新

3 号当前位置 X=(1.2, 2.4)

Step-1 计算与 α,β,δ 的距离

Dα=|C·Xα - X|=|1.6·(-0.3, -0.2) - (1.2, 2.4)|

= |(-0.48, -0.32) - (1.2, 2.4)| = (1.68, 2.72)

同理(手算省略)得

Dβ=(2.08, 1.92)

Dδ=(4.56, 4.48)

Step-2 计算三只"引导狼"给出的下一步位置

X1 = Xα - A·Dα = (-0.3, -0.2) - (-0.8)·(1.68, 2.72)

= (-0.3, -0.2) + (1.344, 2.176) = (1.044, 1.976)

X2 = Xβ - A·Dβ = (-0.8, 0.4) + 0.8·(2.08, 1.92)

= (0.864, 1.936)

X3 = Xδ - A·Dδ = (2.1, -1.3) + 0.8·(4.56, 4.48)

= (5.748, 2.284)

Step-3 取平均得到新位置

X(t+1)= (X1+X2+X3)/3

= ( (1.044+0.864+5.748)/3 , (1.976+1.936+2.284)/3 )

= (2.55, 2.06)

3.3 计算新位置适应度

f(2.55, 2.06)= 20 + 2.55² + 2.06² -10(cos2π·2.55 + cos2π·2.06) ≈ 22.4

比原 f=35.56 明显下降,移动有效!

3.4 对整个种群重复上述操作

得到 5 个新位置后,重新排序,选出新的 α,β,δ,进入下一次迭代。

4.迭代轨迹可视化(示意图)
  • 初始 α 在 (-0.3,-0.2)

  • 第 1 步后 α 可能已被更优个体取代,向 (0,0) 靠近

  • 随着 a 减小,搜索步长自动缩小,群体逐渐"收缩"到全局最小值 (0,0)


五、论文结果

论文中GWO 在 29 个标准测试函数上与 PSO、GSA、DE 等算法对比,结果如下:

测试类型 函数特性 GWO 表现
单峰函数 检验开发能力 收敛速度快,精度高
多峰函数 检验探索能力 避免局部最优能力强
复合函数 综合性能 探索与开发平衡良好

Python 灰狼算法实现

项目代码我已经放入GitCode里面,可以通过下面链接跳转:🔥

【启发式算法】灰狼优化算法(Grey Wolf Optimizer, GWO)(Python)

后续相关启发式算法也会不断在【HeuristicAlgorithm】项目里更新,如果该项目对你有所帮助,请帮我点一个星星 ✨✨✨✨✨,鼓励分享,十分感谢!!!

若是下面代码复现困难或者有问题,也欢迎评论区留言

python 复制代码
"""《灰狼算法》
    时间:2024.10.30
    作者:不去幼儿园
"""
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'SimHei'  # Windows系统常用中文字体

# 参数设置
Pop_size = 10
Max_T = 75
Dim = 2
Num_obstacles = 50
safe_distance = 5
bounds = np.array([[0, 100], [0, 100]])


# 随机生成起点和终点
def generate_start_and_goal(bounds, safe_distance,
                            min_sep=None, margin=5):
    """
    保证起点在左上矩形,终点在右下矩形,且两者欧氏距离 >= min_sep
    bounds:  np.array([[xmin, xmax], [ymin, ymax]])
    margin:  距离边界的最小留白,防止起点/终点贴边
    min_sep: 两点间最小距离,默认等于 safe_distance
    """
    if min_sep is None:
        min_sep = safe_distance

    x_min, x_max = bounds[0, 0], bounds[0, 1]
    y_min, y_max = bounds[1, 0], bounds[1, 1]

    # 计算中心点,把地图切成左上 / 右下两个矩形
    x_c = (x_min + x_max) / 2
    y_c = (y_min + y_max) / 2

    # 左上矩形边界
    left_x1, right_x1 = x_min + margin, x_c - margin
    bottom_y1, top_y1    = y_c + margin, y_max - margin

    # 右下矩形边界
    left_x2, right_x2 = x_c + margin, x_max - margin
    bottom_y2, top_y2    = y_min + margin, y_c - margin

    # 确保矩形有效
    assert left_x1 < right_x1 and bottom_y1 < top_y1, "左上区域过小,请调大地图或减小 margin"
    assert left_x2 < right_x2 and bottom_y2 < top_y2, "右下区域过小,请调大地图或减小 margin"

    while True:
        # 在左上矩形采起点
        start = np.array([np.random.uniform(left_x1, right_x1),
                          np.random.uniform(bottom_y1, top_y1)])
        # 在右下矩形采终点
        goal  = np.array([np.random.uniform(left_x2, right_x2),
                          np.random.uniform(bottom_y2, top_y2)])

        if np.linalg.norm(start - goal) >= min_sep:
            return start, goal


# 随机生成障碍物
def generate_obstacles(num_obstacles, bounds, start, goal, safe_distance):
	obstacles = []
	while len(obstacles) < num_obstacles:
		obs = np.random.uniform(bounds[:, 0], bounds[:, 1], size=(1, 2)).flatten()
		if (np.linalg.norm(obs - start) >= safe_distance and
				np.linalg.norm(obs - goal) >= safe_distance and
				all(np.linalg.norm(obs - other) >= 2 * safe_distance for other in obstacles)):
			obstacles.append(obs)
	return np.array(obstacles)


# 适应度函数(标准GWO与改进GWO共用)
def fitness_function(position, goal, obstacles, safe_distance):
	distance_to_goal = np.linalg.norm(position - goal)
	penalty = sum([1000 / dis_to_obs for obs in obstacles
				   if (dis_to_obs := np.linalg.norm(position - obs)) < safe_distance])
	return distance_to_goal + penalty


# 标准GWO算法实现
def standard_gwo(Pop_size, Max_T, Dim, start, goal, bounds, obstacles, safe_distance):
	positions = np.random.uniform(bounds[:, 0], bounds[:, 1], size=(Pop_size, Dim))
	alpha_pos, beta_pos, delta_pos = start.copy(), None, None
	alpha_score, beta_score, delta_score = float('inf'), float('inf'), float('inf')
	best_path, best_scores = [start.copy()], []

	for iter in range(Max_T):
		for i in range(Pop_size):
			fitness = fitness_function(positions[i, :], goal, obstacles, safe_distance)

			if fitness < alpha_score:
				delta_score, delta_pos = beta_score, beta_pos
				beta_score, beta_pos = alpha_score, alpha_pos
				alpha_score, alpha_pos = fitness, positions[i, :].copy()
			elif fitness < beta_score:
				delta_score, delta_pos = beta_score, beta_pos
				beta_score, beta_pos = fitness, positions[i, :].copy()
			elif fitness < delta_score:
				delta_score, delta_pos = fitness, positions[i, :].copy()

		best_path.append(alpha_pos.copy())
		best_scores.append(alpha_score)

		for i in range(Pop_size):
			for j in range(Dim):
				r1_alpha, r2_alpha = np.random.rand(), np.random.rand()
				A1 = 2 * (2 - iter * (2 / Max_T)) * r1_alpha - (2 - iter * (2 / Max_T))
				C1 = 2 * r2_alpha
				D_alpha = abs(C1 * alpha_pos[j] - positions[i, j])
				X1 = alpha_pos[j] - A1 * D_alpha

				A2, C2 = 2 * (2 - iter * (2 / Max_T)) * np.random.rand() - (
						2 - iter * (2 / Max_T)), 2 * np.random.rand()
				D_beta = abs(C2 * beta_pos[j] - positions[i, j]) if beta_pos is not None else 0
				X2 = beta_pos[j] - A2 * D_beta

				A3, C3 = 2 * (2 - iter * (2 / Max_T)) * np.random.rand() - (
						2 - iter * (2 / Max_T)), 2 * np.random.rand()
				D_delta = abs(C3 * delta_pos[j] - positions[i, j]) if delta_pos is not None else 0
				X3 = delta_pos[j] - A3 * D_delta

				positions[i, j] = (X1 + X2 + X3) / 3

		positions = np.clip(positions, bounds[:, 0], bounds[:, 1])

	return best_path, best_scores, alpha_pos


# 改进GWO算法实现
def modified_gwo(Pop_size, Max_T, Dim, start, goal, bounds, obstacles, safe_distance):
	positions = np.random.uniform(bounds[:, 0], bounds[:, 1], size=(Pop_size, Dim))
	alpha_pos, beta_pos, delta_pos = start.copy(), None, None
	alpha_score, beta_score, delta_score = float('inf'), float('inf'), float('inf')
	best_path, best_scores = [start.copy()], []

	for iter in range(Max_T):
		a = 2 - iter * (2 / Max_T)

		for i in range(Pop_size):
			fitness = fitness_function(positions[i, :], goal, obstacles, safe_distance)
			if fitness < alpha_score:
				delta_score, delta_pos = beta_score, beta_pos
				beta_score, beta_pos = alpha_score, alpha_pos
				alpha_score, alpha_pos = fitness, positions[i, :].copy()
			elif fitness < beta_score:
				delta_score, delta_pos = beta_score, beta_pos
				beta_score, beta_pos = fitness, positions[i, :].copy()
			elif fitness < delta_score:
				delta_score, delta_pos = fitness, positions[i, :].copy()

		best_path.append(alpha_pos.copy())
		best_scores.append(alpha_score)

		for i in range(Pop_size):
			for j in range(Dim):
				r1, r2 = np.random.rand(), np.random.rand()
				A1, C1 = 2 * a * r1 - a, 2 * r2
				D_alpha = abs(C1 * alpha_pos[j] - positions[i, j])
				X1 = alpha_pos[j] - A1 * D_alpha

				A2, C2 = 2 * a * np.random.rand() - a, 2 * np.random.rand()
				D_beta = abs(C2 * beta_pos[j] - positions[i, j]) if beta_pos is not None else 0
				X2 = beta_pos[j] - A2 * D_beta

				A3, C3 = 2 * a * np.random.rand() - a, 2 * np.random.rand()
				D_delta = abs(C3 * delta_pos[j] - positions[i, j]) if delta_pos is not None else 0
				X3 = delta_pos[j] - A3 * D_delta

				positions[i, j] = (0.6 * X1 + 0.3 * X2 + 0.1 * X3)

		positions = np.clip(positions, bounds[:, 0], bounds[:, 1])

	return best_path, best_scores, alpha_pos


start, goal = generate_start_and_goal(bounds, safe_distance)
obstacles = generate_obstacles(Num_obstacles, bounds, start, goal, safe_distance)

# 运行两种GWO算法
standard_path, standard_scores, standard_final_pos = standard_gwo(Pop_size, Max_T, Dim, start, goal, bounds, obstacles,
																  safe_distance)
modified_path, modified_scores, modified_final_pos = modified_gwo(Pop_size, Max_T, Dim, start, goal, bounds, obstacles,
																  safe_distance)

# 绘制最终路径
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.title("标准GWO - 最终路径")
plt.plot(start[0], start[1], 'go', markersize=10, label='起点')
plt.plot(goal[0], goal[1], 'ro', markersize=10, label='终点')
plt.plot(obstacles[:, 0], obstacles[:, 1], 'ks', markersize=4, label='障碍物')
standard_path_np = np.array(standard_path)
plt.plot(standard_path_np[:, 0], standard_path_np[:, 1], 'c-', linewidth=1.5, label='路径')
plt.scatter(standard_path_np[:, 0], standard_path_np[:, 1], color='c', s=20, marker='o')
plt.plot(standard_final_pos[0], standard_final_pos[1], 'c*', markersize=12, label='最终Alpha位置')
plt.legend()

plt.subplot(1, 2, 2)
plt.title("改进GWO - 最终路径")
plt.plot(start[0], start[1], 'go', markersize=10, label='起点')
plt.plot(goal[0], goal[1], 'ro', markersize=10, label='终点')
plt.plot(obstacles[:, 0], obstacles[:, 1], 'ks', markersize=4, label='障碍物')
modified_path_np = np.array(modified_path)
plt.plot(modified_path_np[:, 0], modified_path_np[:, 1], 'm-', linewidth=1.5, label='路径')
plt.scatter(modified_path_np[:, 0], modified_path_np[:, 1], color='m', s=20, marker='o')
plt.plot(modified_final_pos[0], modified_final_pos[1], 'm*', markersize=12, label='最终Alpha位置')
plt.legend()
plt.show()

# 绘制收敛曲线对比
plt.figure()
plt.plot(range(Max_T), standard_scores, 'b-', label='标准GWO')
plt.plot(range(Max_T), modified_scores, 'r-', label='改进GWO')
plt.xlabel('迭代次数')
plt.ylabel('最优适应度值')
plt.title('收敛曲线对比')
plt.legend()
plt.show()

# 计算最优路径长度
standard_path_Len = sum(np.linalg.norm(standard_path_np[i] - standard_path_np[i + 1])
						for i in range(len(standard_path_np) - 1))

print(f'标准路径长度: {standard_path_Len}')

modified_path_Len = sum(np.linalg.norm(modified_path_np[i] - modified_path_np[i + 1])
						for i in range(len(modified_path_np) - 1))

print(f'改进路径长度: {modified_path_Len}')

Results 运行结果


Notice 注意事项

GWO 就是:

"让最厉害的三只狼(α,β,δ) 当'导航员',其余狼每隔一步都向它们学习一次,逐渐把整群狼拖到谷底。"

把上面的手算步骤对照代码走一遍,你会发现"包围-狩猎-攻击"不再抽象,而是每一步都在做向量加加减减------这就是灰狼优化的全部秘密。

bash 复制代码
​# 环境配置
Python                  3.11.5
torch                   2.1.0
torchvision             0.16.0
gym                     0.26.2

六、总结

灰狼优化算法(GWO)作为一种群体智能优化方法,具有以下优势:

  • 结构简洁,参数少,易于实现;

  • 模拟社会等级与协同行为,具备良好全局搜索能力;

  • 在探索与开发之间实现动态平衡;

  • 在标准测试函数与工程问题中表现优异,具备广泛应用前景。

参考资料:

Mirjalili S., Mirjalili S.M., Lewis A. (2014). *Grey Wolf Optimizer*, Advances in Engineering Software, Vol. 69, pp. 46--61.

https://github.com/Dev-Soni-2608/Grey-Wolf-Optimizer-for-Robot-Path-Planning/tree/main

更多启发式算法 文章,请前往:【启发式算法】专栏


博客都是给自己看的笔记,如有误导深表抱歉。文章若有不当和不正确之处,还望理解与指出。由于部分文字、图片等来源于互联网,无法核实真实出处,如涉及相关争议,请联系博主删除。如有错误、疑问和侵权,欢迎评论留言联系作者,或者添加VX:**Rainbook_2,**联系作者。✨

相关推荐
杠杠的blog几秒前
企业级提示词管理
python·agent·提示词·生产级实践
旖-旎3 分钟前
《LeetCode 646 最长数对链 || LeetCode 1143 最长公共子序列》
c++·算法·leetcode·动态规划
武子康3 分钟前
LingBot 四线全拆:Video / World / VLA / VA 按最终输出选型 + 开源许可证避坑表
人工智能·llm·agent
Drgfd5 分钟前
工业智能跃迁:工业互联网深度迭代,终结传统自动化时代
人工智能
龙腾AI白云6 分钟前
英伟达押注的Physical AI与量智融合
人工智能·知识图谱
user-猴子6 分钟前
还在手动复制粘贴处理Excel?用AI自动化办公
人工智能·自动化·excel
易观Analysys10 分钟前
2026年中国具身智能重点行业应用与场景价值分析报告
人工智能
小小放舟、15 分钟前
VS Code Code Runner 中文乱码修复与 IDEA 风格输出配置
vscode·python·code runner
衣舞晨风15 分钟前
什么样的 AI 网关算是一个好网关
网络·人工智能·网关·ai·大模型·ai网关
小宋102121 分钟前
普通人如何把 AI 用成“第二大脑”?从提问到知识整理的完整方法
人工智能