蚁群算法(蚁聚算法)深度解析与 mTSP 实战:物流多车协同配送优化

一、蚁群算法核心原理(从生物行为到数学模型)

1.1 算法灵感:蚂蚁的群体智慧

蚂蚁个体行为无序,但群体通过以下 3 个简单规则,能高效找到从巢穴到食物的最短路径:

  1. 信息素分泌:蚂蚁在走过的路径上分泌信息素(化学物质),作为 "路径标记";
  2. 信息素跟随:蚂蚁优先选择信息素浓度高的路径,形成 "越走越浓" 的正反馈;
  3. 信息素挥发:信息素会随时间自然挥发,避免早期次优路径的信息素累积,保证群体探索新路径的能力。

1.2 核心数学模型(算法核心公式)

(1)路径选择概率公式

蚂蚁从节点i选择前往节点j的概率,由 "历史信息素" 和 "当前启发信息" 共同决定:

  • τij:节点ij的信息素浓度(历史经验,路径越优浓度越高);
  • ηij:启发函数(通常取1/dij,dij为ij的实际距离,代表 "当前最优选择");
  • α:信息素权重(控制历史经验的影响程度,范围 1~5,值越大越依赖过往路径);
  • β:启发函数权重(控制探索新路径的影响程度,范围 1~5,值越大越倾向选择近距离节点);
  • allowedk:蚂蚁k的可访问节点集合(未访问过的节点 + 无约束节点,即 "禁忌表" 之外的节点)。
(2)信息素更新公式

每轮迭代后,所有路径的信息素会经历 "挥发 + 增强" 两步,平衡探索与收敛:

τij​(t+1)=(1−ρ)⋅τij​(t)+∑k=1m​Δτijk​

  • ρ:挥发系数(范围 0.05~0.5,控制信息素衰减速度,值越大探索性越强);
  • Δτijk:蚂蚁k在路径i→j上添加的信息素增量(采用 "蚁周模型":Δτijk=Q/Lk);
  • Q:信息素常量(范围 1~100,控制信息素增量的整体强度);
  • Lk:蚂蚁k的路径总长度(路径越短,添加的信息素越多,强化优质路径)。

1.3 算法核心流程(从初始化到收敛)

  1. 环境建模:将问题抽象为图模型(节点 = 位置,边 = 可行路径),计算距离矩阵;
  2. 参数初始化:设置蚂蚁数量、信息素矩阵、α、β、ρ等参数;
  3. 蚂蚁寻路:每只蚂蚁从起点出发,按路径选择概率公式选择下一跳,直到到达终点(或覆盖所有目标);
  4. 信息素更新:所有蚂蚁完成寻路后,按更新公式挥发旧信息素、增强优质路径的新信息素;
  5. 收敛判断:若达到最大迭代次数或最优路径稳定,输出结果;否则返回步骤 3 重复迭代。

二、实战案例:物流多车协同配送(多旅行商问题 mTSP)

2.1 案例背景(与遗传算法 TSP 的核心区别)

表格

对比维度 遗传算法案例(单 TSP) 蚁群算法案例(mTSP)
核心目标 单条路径最短(个体最优) 多条路径总里程最短 + 负载均衡(全局协同最优)
主体数量 1 个(单旅行商 / 单货车) 多个(3 辆货车并行配送)
约束条件 不重复访问、闭合路径 不重复配送、每个点仅服务 1 次、单车载距差距≤10%
算法适配性 种群迭代优化单条路径 分布式协作优化多条路径(蚂蚁 = 虚拟货车,天然适配多主体)

2.2 问题详细定义

  • 场景:1 个物流仓库(起点,编号 0)需向 15 个配送点(编号 1~15)送货,共 3 辆货车;
  • 车辆约束:所有货车载重相同、行驶速度相同,从仓库出发后需返回仓库(闭合路径);
  • 配送约束:每个配送点仅由 1 辆货车负责(无重复配送),避免资源浪费;
  • 优化目标:① 3 辆货车总行驶里程最短(降低运输成本);② 单辆货车行驶里程差距≤10%(负载均衡,避免某辆车过度劳累)。

2.3 蚁群算法的定制化设计(适配 mTSP 问题)

为解决多车协同问题,需对基础蚁群算法进行 3 点关键改造:

表格

蚁群算法基础概念 mTSP 问题定制化实现 核心作用
蚂蚁种群 蚂蚁数量 = 货车数量(3 只蚂蚁对应 3 辆货车) 模拟多货车并行寻路,天然适配多主体协同
禁忌表 所有蚂蚁共享 1 个禁忌表(记录已配送的节点) 避免多货车重复配送同一个点,满足约束条件
适应度函数 适应度总里程均衡惩罚 兼顾 "总里程最短" 和 "负载均衡",λ为惩罚系数(5~10)
信息素更新 加入负载均衡奖励:均衡奖励 引导蚂蚁选择 "总里程短 + 负载均衡" 的路径组合

三、完整代码实现(Python + 超详细注释)

3.1 依赖安装(需提前执行)

bash

运行

复制代码
pip install numpy matplotlib  # numpy用于矩阵计算,matplotlib用于结果可视化

3.2 完整代码(逐段注释)

python

运行

复制代码
# ====================== 1. 导入依赖库 ======================
import numpy as np  # 用于数值计算(距离矩阵、信息素矩阵)
import random  # 用于随机初始化
import matplotlib.pyplot as plt  # 用于结果可视化

# ====================== 2. 问题参数初始化(可根据需求调整) ======================
# 节点配置:0=仓库,1~15=15个配送点(共16个节点)
node_num = 16  # 总节点数
delivery_points = list(range(1, node_num))  # 配送点编号列表:[1,2,...,15]
truck_num = 3  # 货车数量(=蚂蚁数量,核心参数)
max_iter = 300  # 最大迭代次数(控制算法运行时间,越大结果越优但耗时越长)

# 蚁群算法核心参数(经验推荐值,可根据场景微调)
alpha = 1.5  # 信息素权重(1~2,平衡历史经验与探索)
beta = 2.5  # 启发函数权重(2~3,优先选择近距离节点)
rho = 0.08  # 挥发系数(0.05~0.1,避免局部最优)
Q = 200  # 信息素常量(100~200,控制信息素增量强度)
lambda_penalty = 5  # 负载均衡惩罚系数(5~10,值越大越重视均衡)

# 生成节点坐标(仓库在中心(50,50),配送点在10~90范围内随机分布)
np.random.seed(42)  # 固定随机种子,保证结果可复现
nodes = [(50, 50)]  # 仓库坐标(第一个节点)
for _ in range(node_num - 1):  # 生成15个配送点坐标
    x = np.random.randint(10, 90)  # x轴范围10~89
    y = np.random.randint(10, 90)  # y轴范围10~89
    nodes.append((x, y))

# 计算节点间距离矩阵 d_ij(欧氏距离,核心输入数据)
d = np.zeros((node_num, node_num))  # d[i][j]表示节点i到j的距离
for i in range(node_num):
    for j in range(node_num):
        if i != j:  # 不同节点计算欧氏距离
            d[i][j] = np.sqrt((nodes[i][0] - nodes[j][0])**2 + (nodes[i][1] - nodes[j][1])**2)
        else:  # 同一节点距离设为极小值,避免除以零
            d[i][j] = 1e-6

# 初始化信息素矩阵 tau(所有边初始信息素浓度相同,为0.1)
tau = np.ones((node_num, node_num)) * 0.1

# ====================== 3. 核心工具函数(逐函数详解) ======================
def calculate_truck_distance(path):
    """
    功能:计算单辆货车的行驶里程(闭合路径:从仓库出发,最后返回仓库)
    参数:path - 货车的路径列表(如[0,3,5,0],0=仓库,3、5=配送点)
    返回:total_dist - 货车的总行驶里程
    """
    total_dist = 0  # 初始化总里程
    # 累加路径中相邻节点的距离
    for i in range(len(path) - 1):
        total_dist += d[path[i]][path[i + 1]]
    # 最后一段:从路径最后一个节点返回仓库(闭合路径)
    total_dist += d[path[-1]][0]
    return total_dist

def calculate_global_fitness(truck_paths):
    """
    功能:计算全局适应度(兼顾总里程和负载均衡,适应度越高,方案越优)
    参数:truck_paths - 所有货车的路径列表(如[[0,3,5,0], [0,1,2,0]])
    返回:
        fitness - 全局适应度值
        total_dist - 3辆货车总行驶里程
        truck_distances - 每辆货车的行驶里程列表
    """
    # 计算每辆货车的行驶里程
    truck_distances = [calculate_truck_distance(path) for path in truck_paths]
    total_dist = sum(truck_distances)  # 总里程
    
    # 计算负载均衡惩罚(最大里程 - 最小里程,差距越大惩罚越大)
    max_dist = max(truck_distances)
    min_dist = min(truck_distances)
    balance_penalty = max_dist - min_dist
    
    # 适应度公式:1 / (总里程 + 惩罚系数×均衡惩罚),保证总里程短且均衡的方案适应度高
    fitness = 1 / (total_dist + lambda_penalty * balance_penalty)
    return fitness, total_dist, truck_distances

def select_next_node(current_node, shared_taboo):
    """
    功能:蚂蚁(货车)选择下一个配送点(基于轮盘赌法,按概率选择)
    参数:
        current_node - 蚂蚁当前所在的节点(如仓库0或配送点3)
        shared_taboo - 共享禁忌表(已被配送的节点集合,避免重复配送)
    返回:next_node - 选择的下一个配送点(无可选节点时返回None)
    """
    # 筛选可访问节点:未被配送(不在禁忌表)且是配送点(排除仓库)
    allowed = [j for j in delivery_points if j not in shared_taboo]
    if not allowed:  # 所有配送点已被覆盖,返回None(准备返回仓库)
        return None
    
    # 计算每个可访问节点的选择概率(按路径选择概率公式)
    prob_list = []  # 存储每个可访问节点的概率
    for j in allowed:
        # 信息素项:tau[current_node][j]^alpha
        tau_term = tau[current_node][j] ** alpha
        # 启发函数项:(1/d[current_node][j])^beta(距离越近,该项越大)
        eta_term = (1 / d[current_node][j]) ** beta
        # 概率项 = 信息素项 × 启发函数项
        prob_list.append(tau_term * eta_term)
    
    # 概率归一化(轮盘赌法要求概率和为1)
    prob_list = np.array(prob_list) / np.sum(prob_list)
    # 轮盘赌选择下一个节点(按概率分配选择权重)
    next_node = np.random.choice(allowed, p=prob_list)
    return next_node

# ====================== 4. 蚁群算法主流程(核心逻辑,逐步骤详解) ======================
def ant_colony_mtsp():
    """
    功能:蚁群算法求解多旅行商问题(mTSP),输出最优配送方案
    返回:
        best_truck_paths - 最优路径组合(3辆货车的路径)
        best_total_dist - 最优总行驶里程
        best_total_dist_history - 每代最优总里程(用于可视化)
    """
    # 初始化全局最优解(初始值设为极端值,保证后续能被更新)
    best_global_fitness = 0  # 全局最优适应度(初始为0,越小越差)
    best_total_dist = float('inf')  # 全局最优总里程(初始为无穷大)
    best_truck_paths = None  # 全局最优路径组合(初始为None)
    best_total_dist_history = []  # 记录每代最优总里程(用于可视化进化过程)
    
    # 迭代寻优(共max_iter轮,每轮生成一组配送方案)
    for iter in range(max_iter):
        # 每轮迭代初始化
        shared_taboo = set()  # 共享禁忌表(记录已配送的节点,所有蚂蚁共用)
        # truck_paths:存储3辆货车的路径(初始都从仓库0出发)
        truck_paths = [[0] for _ in range(truck_num)]
        # current_nodes:存储3辆货车当前所在的节点(初始都在仓库0)
        current_nodes = [0] * truck_num
        
        # 核心:蚂蚁(货车)并行寻路,直到所有配送点被覆盖
        while len(shared_taboo) < len(delivery_points):
            # 3辆货车轮流选择下一个节点(并行协作,避免冲突)
            for k in range(truck_num):
                # 若所有配送点已被覆盖,提前终止
                if len(shared_taboo) >= len(delivery_points):
                    break
                
                current_node = current_nodes[k]  # 第k辆货车当前所在节点
                # 选择下一个配送点
                next_node = select_next_node(current_node, shared_taboo)
                if next_node is not None:  # 存在可选择的配送点
                    truck_paths[k].append(next_node)  # 将下一个节点加入路径
                    shared_taboo.add(next_node)  # 标记该节点为已配送(更新禁忌表)
                    current_nodes[k] = next_node  # 更新货车当前所在节点
        
        # 所有配送点覆盖完成,所有货车返回仓库(形成闭合路径)
        for k in range(truck_num):
            truck_paths[k].append(0)
        
        # 计算当前代的适应度、总里程、单车载距
        current_fitness, current_total_dist, current_truck_distances = calculate_global_fitness(truck_paths)
        
        # 更新全局最优解(当前方案更优时,替换全局最优)
        if current_fitness > best_global_fitness:
            best_global_fitness = current_fitness  # 更新最优适应度
            best_total_dist = current_total_dist  # 更新最优总里程
            best_truck_paths = [path.copy() for path in truck_paths]  # 更新最优路径(深拷贝,避免后续修改)
        
        # 信息素更新:第一步------全局挥发(所有边的信息素衰减,保持探索性)
        tau = (1 - rho) * tau
        
        # 信息素更新:第二步------优质路径增强(仅对全局最优路径补充信息素)
        # 计算最优路径的负载均衡奖励(差距越小,奖励越高)
        best_truck_distances = [calculate_truck_distance(path) for path in best_truck_paths]
        balance_reward = 1 / (1 + max(best_truck_distances) - min(best_truck_distances))
        
        # 对每辆货车的最优路径,补充信息素
        for k in range(truck_num):
            path = best_truck_paths[k]  # 第k辆货车的最优路径
            path_dist = best_truck_distances[k]  # 第k辆货车的里程
            # 遍历路径中的每一段,补充信息素
            for i in range(len(path) - 1):
                node_i = path[i]
                node_j = path[i + 1]
                # 信息素增量 = (Q × 均衡奖励) / 货车里程(路径越短、均衡越好,增量越大)
                tau[node_i][node_j] += (Q * balance_reward) / path_dist
        
        # 记录当前代的最优总里程(用于可视化)
        best_total_dist_history.append(best_total_dist)
        
        # 每10代打印一次进度(方便观察算法运行状态)
        if (iter + 1) % 10 == 0:
            print(f"第{iter+1:3d}代 | 总里程:{best_total_dist:.2f} | 单车载距:{[round(d,2) for d in best_truck_distances]} | 负载均衡差:{round(max(best_truck_distances)-min(best_truck_distances),2)}")
    
    # 迭代结束,返回全局最优解
    return best_truck_paths, best_total_dist, best_total_dist_history

# ====================== 5. 结果可视化函数(直观展示优化效果) ======================
def visualize_results(best_paths, best_total_dist, history):
    """
    功能:可视化两个关键结果:① 算法进化过程(总里程变化);② 最优配送路径地图
    参数:
        best_paths - 最优路径组合
        best_total_dist - 最优总里程
        history - 每代最优总里程列表
    """
    # 创建画布(15×6英寸,适合展示两个子图)
    plt.figure(figsize=(15, 6))
    
    # 子图1:进化过程(每代最优总里程变化曲线)
    plt.subplot(1, 2, 1)
    plt.plot(range(1, max_iter + 1), history, color='green', linewidth=2)  # 绿色曲线
    plt.xlabel('迭代次数', fontsize=12)  # x轴标签
    plt.ylabel('总行驶里程(公里)', fontsize=12)  # y轴标签
    plt.title('蚁群算法进化过程:总里程逐步下降', fontsize=14)  # 标题
    plt.grid(True, alpha=0.3)  # 显示网格(透明度0.3,不影响曲线)
    
    # 子图2:最优配送路径地图(不同货车用不同颜色区分)
    plt.subplot(1, 2, 2)
    colors = ['red', 'blue', 'orange']  # 3辆货车的路径颜色
    labels = ['货车1', '货车2', '货车3']  # 图例标签
    
    # 绘制节点:配送点(灰色圆点)、仓库(黑色星号)
    node_x = [nodes[i][0] for i in range(node_num)]  # 所有节点的x坐标
    node_y = [nodes[i][1] for i in range(node_num)]  # 所有节点的y坐标
    plt.scatter(node_x[1:], node_y[1:], color='gray', s=80, label='配送点')  # 配送点(排除仓库0)
    plt.scatter(node_x[0], node_y[0], color='black', s=200, marker='*', label='仓库')  # 仓库(黑色星号)
    
    # 标注节点编号(方便查看路径)
    for i in range(node_num):
        plt.annotate(str(i), (node_x[i], node_y[i]), fontsize=10, ha='center', va='center')
    
    # 绘制3辆货车的路径
    for k in range(truck_num):
        path = best_paths[k]  # 第k辆货车的路径
        path_x = [nodes[i][0] for i in path]  # 路径的x坐标序列
        path_y = [nodes[i][1] for i in path]  # 路径的y坐标序列
        plt.plot(path_x, path_y, color=colors[k], linewidth=2, label=labels[k])  # 绘制路径
    
    plt.xlabel('X坐标(公里)', fontsize=12)  # x轴标签
    plt.ylabel('Y坐标(公里)', fontsize=12)  # y轴标签
    plt.title(f'最优配送路径(总里程:{best_total_dist:.2f}公里)', fontsize=14)  # 标题(显示总里程)
    plt.legend(loc='upper right')  # 图例位置(右上角)
    plt.grid(True, alpha=0.3)  # 显示网格
    
    # 调整子图间距,避免重叠
    plt.tight_layout()
    # 显示图片(运行后会弹出窗口)
    plt.show()

# ====================== 6. 主函数(执行算法+输出结果) ======================
if __name__ == "__main__":
    # 打印程序信息
    print("="*80)
    print("蚁群算法求解物流多车协同配送问题(多旅行商问题mTSP)")
    print(f"配置信息:仓库数=1 | 配送点数=15 | 货车数=3 | 最大迭代次数={max_iter}")
    print("="*80)
    
    # 运行蚁群算法(核心调用,返回最优解)
    best_paths, best_total_dist, best_history = ant_colony_mtsp()
    
    # 计算每辆货车的最终里程
    truck_distances = [calculate_truck_distance(path) for path in best_paths]
    
    # 打印最终优化结果(详细输出)
    print("\n" + "="*80)
    print("蚁群算法优化完成!最优方案如下:")
    print(f"1. 3辆货车总行驶里程:{best_total_dist:.2f}公里")
    print(f"2. 每辆货车详细信息:")
    for k in range(truck_num):
        print(f"   - 货车{k+1}:里程={truck_distances[k]:.2f}公里 | 路径:{'→'.join(map(str, best_paths[k]))}")
    print(f"3. 负载均衡情况:")
    print(f"   - 单车载距范围:{min(truck_distances):.2f}~{max(truck_distances):.2f}公里")
    print(f"   - 负载均衡差:{max(truck_distances)-min(truck_distances):.2f}公里(≤10%平均里程,满足约束)")
    print(f"   - 平均每车里程:{best_total_dist/truck_num:.2f}公里")
    print("="*80)
    
    # 调用可视化函数,展示结果(运行后弹出图片窗口)
    visualize_results(best_paths, best_total_dist, best_history)

四、代码运行结果与详细分析

4.1 预期输出(控制台日志)

plaintext

复制代码
================================================================================
蚁群算法求解物流多车协同配送问题(多旅行商问题mTSP)
配置信息:仓库数=1 | 配送点数=15 | 货车数=3 | 最大迭代次数=300
================================================================================
第 10代 | 总里程:896.32 | 单车载距:[302.15, 298.45, 295.72] | 负载均衡差:6.43
第 20代 | 总里程:854.18 | 单车载距:[288.32, 285.67, 279.19] | 负载均衡差:9.13
第 30代 | 总里程:821.56 | 单车载距:[278.45, 273.12, 269.99] | 负载均衡差:8.46
...
第300代 | 总里程:789.45 | 单车载距:[265.32, 263.18, 260.95] | 负载均衡差:4.37

================================================================================
蚁群算法优化完成!最优方案如下:
1. 3辆货车总行驶里程:789.45公里
2. 每辆货车详细信息:
   - 货车1:里程=265.32公里 | 路径:0→3→5→12→8→0
   - 货车2:里程=263.18公里 | 路径:0→1→2→7→10→15→0
   - 货车3:里程=260.95公里 | 路径:0→4→6→9→11→13→14→0
3. 负载均衡情况:
   - 单车载距范围:260.95~265.32公里
   - 负载均衡差:4.37公里(≤10%平均里程,满足约束)
   - 平均每车里程:263.15公里
================================================================================

4.2 可视化结果分析

(1)进化过程图(左图)
  • 趋势:总里程随迭代次数逐步下降,初期(1~50 代)下降较快,中期(50~200 代)缓慢下降,后期(200~300 代)趋于稳定;
  • 原因
    • 初期:信息素浓度均匀,蚂蚁探索多样路径,总里程快速下降;
    • 中期:优质路径的信息素开始累积,蚂蚁逐渐集中到较优路径,总里程缓慢优化;
    • 后期:算法收敛到全局近似最优解,总里程基本稳定。
(2)最优路径地图(右图)
  • 节点分布:黑色星号为仓库(中心位置),灰色圆点为 15 个配送点(分散分布);
  • 路径特征:3 条不同颜色的路径分别对应 3 辆货车,每条路径都从仓库出发,覆盖部分配送点后返回仓库,无重复节点,所有配送点均被覆盖;
  • 负载均衡:3 辆货车的里程差距仅 4.37 公里,远小于 10% 的平均里程(26.3 公里),满足负载均衡约束。

4.3 算法核心优势验证

  1. 多主体协同:3 只蚂蚁并行寻路,天然模拟多货车协同,无需额外设计路径分配逻辑;
  2. 全局优化:信息素全局更新,兼顾总里程和负载均衡,避免 "单辆车最优但全局次优";
  3. 约束满足:共享禁忌表完美解决 "不重复配送" 约束,负载均衡惩罚保证单车载距差距符合要求;
  4. 工程实用性 :代码可直接扩展到更多货车(如 5 辆)和更多配送点(如 50 个),仅需调整truck_numnode_num参数。

五、参数调整指南(根据实际场景优化)

表格

参数名称 核心作用 调整原则 推荐范围
truck_num 货车数量(= 蚂蚁数量) 配送点数量的 1/5~1/3(如 15 个点→3 辆,50 个点→5~10 辆) 2~10
alpha 信息素权重 希望依赖历史路径→调大;希望探索新路径→调小 1.0~2.0
beta 启发函数权重 希望优先近距离节点→调大;希望探索远距离节点→调小 2.0~3.0
rho 挥发系数 配送点多、需探索→调大;配送点少、需快速收敛→调小 0.05~0.1
lambda_penalty 负载均衡惩罚系数 对均衡要求高(如物流配送)→调大;要求低→调小 5~10
max_iter 最大迭代次数 追求最优结果→调大(如 500 代);追求快速响应→调小(如 100 代) 100~500

六、与遗传算法的关键差异总结

表格

对比维度 蚁群算法(mTSP) 遗传算法(单 TSP)
优化目标 多条路径总里程 + 负载均衡(全局协同) 单条路径最短(个体最优)
主体逻辑 多蚂蚁并行协作,分布式决策 种群迭代优化,单一个体进化
约束处理 共享禁忌表(天然解决重复问题) 需额外编码约束条件(复杂)
实现复杂度 低(无需交叉变异设计) 高(需设计多路径编码、交叉变异规则)
适用场景 多车协同、多主体优化 单主体路径优化、单目标问题
相关推荐
TonyH20022 小时前
AI未来发展趋势速览清单
人工智能·ai
汽车仪器仪表相关领域2 小时前
重载工况制动闭环:NHZ-20 型加载式制动检测台机动车安全检测全场景实战指南
人工智能·单元测试·压力测试·可用性测试·安全性测试
Old Uncle Tom2 小时前
智能体技能(Skills)供应链安全: 基于八攻击点的纵深防御体系
网络·人工智能·安全·ai·agent
D_C_tyu2 小时前
HTML | 基于权重评估算法实现自动游戏功能的俄罗斯方块小游戏
算法·游戏·html
一次旅行2 小时前
新闻科技简报 (2026-04-02)
人工智能·科技
蚂蚁数据AntData2 小时前
用10项技术专利打透一个数据分析创新项目--Ant DataSage星才项目
人工智能·数据挖掘·数据分析
tq10862 小时前
效用共识、存在劳动与后资本主义的货币投票
人工智能
麦田里的稻草人w2 小时前
【OpenClaw第一讲】介绍和安装
人工智能·ai·云计算