一、核心逻辑与本质
蚁群算法(ACO)是一种模拟自然界蚂蚁觅食行为的启发式群体智能优化算法。
本质:它不依赖于目标函数的梯度或导数,而是通过模拟蚂蚁群体的“正反馈机制”与“间接通信”,让群体在解空间中自发寻找最优解。
适用场景:特别适合解决离散型组合优化问题,最经典的应用是旅行商问题(TSP)、车辆路径规划、网络路由等。
二、输入与输出
输入(Input):
图结构/距离矩阵:描述节点之间拓扑关系的距离矩阵(如城市之间的坐标或距离)。
算法控制参数:蚂蚁数量、信息素重要程度 \alpha、启发式信息重要程度
、挥发系数
、最大迭代次数等。
输出(Output):
最优路径序列:例如 TSP 问题中,遍历所有节点的最短路线顺序。
最优目标值:该最优路径的总长度(或总成本)。
三、核心数学公式与底层原理
ACO 的核心逻辑是“概率决定走向,好路越走越宽”。其数学模型主要由两个核心公式构成:
1. 状态转移概率公式(决定蚂蚁下一步往哪走)
参数深度拆解:
(信息素):节点 i 到 j 这条路上的“历史口碑”。走过的好蚂蚁越多,这个值越大。
(启发式信息):节点 i 到 j 的“眼前诱惑”。通常定义为距离的倒数
,距离越近,诱惑越大。
(允许节点集合):蚂蚁 k 当前还未访问,允许选择的节点集合。
和
:控制信息素和启发式信息相对重要程度的参数。
越大越倾向于历史信息,\beta 越大越倾向于当前距离较近的节点。
2. 信息素更新规则(以经典蚁群系统为例)
(挥发机制):
是挥发系数。时间一长,信息素会自然消散。这相当于“遗忘机制”,防止算法过度依赖历史信息,降低陷入局部最优的风险。
(增强机制):所有蚂蚁走过的路径,都会留下新的信息素。走过的路越短,留下的
就越多。通常:
其中,Q 是信息素强度常数,是蚂蚁 k 的路径总长度。
四、完整的工程实现流程
ACO 的实现是一个不断迭代、优胜劣汰的闭环:
初始化:读取距离矩阵,计算启发式信息矩阵
(通常为
)。初始化信息素矩阵 \tau(通常设为一个较小的均匀常数),并设置
、
、
等参数。
构造解(蚂蚁寻路):每只蚂蚁随机选择一个起点。根据状态转移概率公式,计算走向下一个未访问节点的概率,通过轮盘赌或随机数决定下一步去哪。重复直到蚂蚁走完所有节点(形成一条完整路径),并记录路径总长度
。
信息素更新(口碑重塑):
挥发:将所有路径上的信息素乘以
,让旧信息衰减。
增强:遍历每只蚂蚁,根据它的路径长度
,在它走过的路径上增加信息素
。路越短,加得越多。
记录与终止判断:记录当前迭代中的最短路径(全局最优)。判断是否达到最大迭代次数?如果是,输出最优路径;如果不是,清空蚂蚁的记忆(禁忌表),返回步骤 2。
五、核心代码实现(Python + NumPy)
以下代码以求解 10 个城市的旅行商问题(TSP)为例,完整展示了上述流程:
import numpy as np # 1. 定义问题与参数 NUM_CITIES = 10 cities = np.random.rand(NUM_CITIES, 2) * 100 # 随机生成10个城市坐标 # 计算距离矩阵与启发式信息矩阵(1/d) dist_matrix = np.zeros((NUM_CITIES, NUM_CITIES)) for i in range(NUM_CITIES): for j in range(NUM_CITIES): dist_matrix[i, j] = np.linalg.norm(cities[i] - cities[j]) eta = 1.0 / (dist_matrix + 1e-10) NUM_ANTS, ALPHA, BETA, RHO, Q, ITERATIONS = 20, 1.0, 2.0, 0.5, 100, 50 tau = np.ones((NUM_CITIES, NUM_CITIES)) * 0.1 # 初始化信息素 best_path, best_length = None, float('inf') # 2. ACO 主循环 for iteration in range(ITERATIONS): all_paths, all_lengths = [], [] # (1) 构造解:每只蚂蚁独立寻路 for ant in range(NUM_ANTS): path, current_city = [], np.random.randint(0, NUM_CITIES) path.append(current_city) for step in range(NUM_CITIES - 1): # 获取未访问城市(禁忌表机制) unvisited_mask = np.ones(NUM_CITIES, dtype=bool) unvisited_mask[np.array(path)] = False # 计算状态转移概率 probs = ( (tau[current_city, unvisited_mask] ** ALPHA) * (eta[current_city, unvisited_mask] ** BETA) ) probs /= np.sum(probs) next_city_idx = np.random.choice( np.where(unvisited_mask)[0], p=probs ) path.append(next_city_idx) current_city = next_city_idx # 计算路径总长度 length = sum( dist_matrix[path[i], path[i + 1]] for i in range(len(path) - 1) ) length += dist_matrix[path[-1], path[0]] all_paths.append(path) all_lengths.append(length) if length < best_length: best_length, best_path = length, path.copy() # (2) 信息素更新(挥发 + 增强) tau *= (1 - RHO) # 挥发 for i, path in enumerate(all_paths): delta_tau = Q / all_lengths[i] # 路越短,留下的信息素越多 for step in range(len(path) - 1): city_from, city_to = path[step], path[step + 1] tau[city_from, city_to] += delta_tau tau[city_to, city_from] += delta_tau tau[path[-1], path[0]] += delta_tau tau[path[0], path[-1]] += delta_tau print( f"Iteration {iteration + 1}: " f"Best Length = {best_length:.2f}" ) print("\nOptimal Path:", best_path) print("Optimal Length:", best_length)