
简介本资源面向计算机、人工智能、自动化等专业的在校学生与算法学习者提供一套基于仿生群智算法求解无人机任务分配多旅行商问题的完整Python实现适合用作课程设计、毕业设计或群体智能大作业的参考方案。压缩包共7个文件约19KB以4个py源码文件为核心分别实现蚁群算法、遗传算法与粒子群算法三种基线另含1个md说明文档、1个license及1个gitignore配置结构精简、便于快速上手。代码附带超详细注释实验部分迭代200个epochs并引入Early Stop策略在连续多次性能无提升时提前终止训练方便对比不同算法的收敛表现。目前已有246人学习下载。读者可借此掌握多旅行商问题的建模思路、三种群智算法的编码与调参方法并在此基础上修改扩展用于课设、毕设或项目立项演示。1. 从多旅行商到无人机集群这个课程设计到底在解什么问题多旅行商问题MTSP放到无人机场景里本质是有 N 个目标点要巡检有 M 架无人机从同一基地出发每架飞一条闭合路径要求每个目标点被访问一次、总航程尽量短、各机负载尽量均衡。听起来像教科书里的 TSP 变体但真正动手写代码时你会发现约束一多精确求解器基本跑不动——20 个点以上穷举就是天文数字。这就是仿生群智算法登场的地方。蚁群、粒子群、人工蜂群这类算法不追求数学最优而是在可接受时间内给出足够好的解而且天然适合并行、适合加约束。这个课程设计的价值不在于算法多新而在于它把「MTSP 建模 → 群智算法求解 → 无人机任务分配可视化」这条链路完整跑通并且带超详细注释适合拿来做毕设、课程设计或者作为你入门智能优化的第一个能跑通的 Python 项目。如果你正在搜「无人机任务分配 python 源码」「多旅行商问题求解」下面我会按我实际复现这类项目的顺序把环境、建模、算法、调参、避坑一次讲清楚。2. 环境准备与项目结构先把 Python 跑通再谈算法2.1 Python 环境与依赖安装的最小命令集这类课程设计项目通常只依赖 numpy、matplotlib偶尔加个 pandas 做结果统计。不要一上来就装 Anaconda 全家桶用 venv 隔离最干净。我一般会这么做# 创建虚拟环境python 3.8~3.11 都行别用 3.12 有些老库会翻车 python -m venv venv # Windows 激活 venv\Scripts\activate # Linux / macOS 激活 source venv/bin/activate # 装核心依赖版本不用锁太死 pip install numpy matplotlib pandas如果你用的是 VSCode装好 Python 插件后按 CtrlShiftP选「Python: Select Interpreter」指向 venv 里的 python.exe。这一步不做后面 import numpy 报 ModuleNotFoundError 是高频翻车点。提示pip 安装慢的话换国内镜像源命令后面加-i https://pypi.tuna.tsinghua.edu.cn/simple这是常规操作不算敏感。2.2 一个典型课程设计项目的目录长什么样虽然我没法看到你手里那份源码的具体结构但这类「仿生群智算法 MTSP 无人机任务分配」的项目目录八九不离十是这样文件/目录作用你该关注什么main.py入口读参数、跑算法、画图先看这里知道怎么启动aco.py/pso.py群智算法核心实现信息素更新、速度位置公式mtsp_model.py问题建模距离矩阵、约束目标函数和惩罚项utils.py距离计算、路径解码、绘图路径怎么从编码还原成航线data/坐标点数据可能是 csv 或硬编码换成你自己的目标点result/输出图片、收敛曲线验证是否真的收敛拿到项目第一件事不是跑是打开main.py看它 import 了哪些本地模块然后顺着调用链读一遍。注释再详细也不如你自己画一遍调用关系。2.3 先跑通再改第一次运行的正确姿势# 在项目根目录确保 venv 已激活 python main.py如果报错按这个顺序排查缺库 → 路径问题 → 数据格式问题。路径问题最常见很多项目里写死了./data/city.csv你在别的目录跑就找不到。解决办法是os.path.dirname(__file__)拼绝对路径或者老老实实 cd 到项目根目录再跑。跑通后你应该看到控制台打印每代最优适应度最后弹出一张图上面有若干条不同颜色的闭合路径每条代表一架无人机的航线。看到这张图说明整条链路是通的接下来才是理解和解构。3. 多旅行商问题建模目标函数、约束和编码方式3.1 MTSP 和 TSP 差在哪为什么不能直接套TSP 是一个旅行商走遍所有城市回到起点MTSP 是 M 个旅行商从同一城市出发各自走一条路径所有城市被访问且仅被访问一次。差别看着小但解空间结构完全不同TSP 的解是一个排列MTSP 的解是「排列 切分点」。举个例子10 个目标点、3 架无人机。一种编码是[2,5,1,8,3,9,4,7,6]然后切两刀变成三段每段是一架无人机的访问顺序。切分点不同任务分配就不同。所以 MTSP 的优化其实包含两层访问顺序优化 任务分配优化。很多初学者只优化顺序忘了分配结果就是某架无人机飞断腿另一架几乎没动。3.2 目标函数怎么写总航程 均衡惩罚我一般用加权形式import numpy as np def mtsp_objective(routes, dist_matrix, weight_balance0.3): routes: list of list, 每架无人机的访问序列不含基地 dist_matrix: N1 x N1 距离矩阵索引 0 是基地 weight_balance: 均衡项权重越大越强制各机航程接近 lengths [] for route in routes: if not route: lengths.append(0) continue # 基地 - 第一个点 - ... - 最后一个点 - 基地 seq [0] route [0] L sum(dist_matrix[seq[i]][seq[i1]] for i in range(len(seq)-1)) lengths.append(L) total sum(lengths) # 均衡惩罚各机航程的标准差 balance np.std(lengths) return total weight_balance * balance, lengths逻辑说明total是总航程越小越好balance是各机航程标准差越小说明负载越均衡。weight_balance是你要调的关键参数——设 0 就是纯最短总航程可能一架飞完所有点设太大总航程会变长但分配均匀。我一般从 0.2~0.5 之间试。参数说明dist_matrix必须包含基地且基地索引固定为 0。如果你的数据里基地不是第一个点先重排。3.3 距离矩阵欧氏距离够用但别踩这两个坑def build_dist_matrix(coords): coords: (N1, 2) 数组第 0 行是基地 返回 (N1, N1) 对称距离矩阵 n len(coords) D np.zeros((n, n)) for i in range(n): for j in range(i1, n): d np.linalg.norm(coords[i] - coords[j]) D[i][j] d D[j][i] d return D坑一坐标没归一化。如果 x 范围 0~1000y 范围 0~1欧氏距离会被 x 主导y 几乎不起作用。要么统一量纲要么用马氏距离。坑二距离矩阵不对称。手动填的时候容易只填一半算法里读D[j][i]得到 0路径长度算出来偏小收敛曲线好看但结果是错的。用上面的写法强制对称最稳。4. 仿生群智算法实现以蚁群和粒子群为例的落地代码4.1 蚁群算法解 MTSP信息素怎么更新蚁群的核心是信息素矩阵tau形状 (N1, N1)tau[i][j]表示从点 i 到点 j 的吸引力。每只蚂蚁构造一条完整路径然后按路径质量更新信息素。import numpy as np def aco_mtsp(coords, n_drones, n_ants30, n_iter100, alpha1.0, beta3.0, rho0.5, Q100): alpha: 信息素重要程度 beta: 启发式1/距离重要程度 rho: 信息素挥发系数 Q: 信息素增量常数 n len(coords) D build_dist_matrix(coords) tau np.ones((n, n)) * 0.1 eta 1.0 / (D 1e-10) # 启发式因子 best_routes, best_cost None, float(inf) for it in range(n_iter): all_routes [] for ant in range(n_ants): routes construct_solution(tau, eta, D, n_drones, alpha, beta) cost, _ mtsp_objective(routes, D) all_routes.append((routes, cost)) if cost best_cost: best_cost, best_routes cost, routes # 信息素挥发 tau * (1 - rho) # 信息素沉积只让较优的解沉积加速收敛 all_routes.sort(keylambda x: x[1]) for routes, cost in all_routes[:max(1, n_ants//3)]: deposit Q / cost for route in routes: seq [0] route [0] for i in range(len(seq)-1): tau[seq[i]][seq[i1]] deposit return best_routes, best_cost逻辑说明construct_solution是每只蚂蚁按概率选下一个点概率正比于tau^alpha * eta^beta同时要保证每个点只被访问一次、且分配给某架无人机后不再被其他机访问。alpha越大越依赖历史经验容易早熟beta越大越贪心容易局部最优。我一般 alpha1、beta2~5 之间调。参数说明n_ants太小搜索不充分太大每代慢30~50 是常见区间。rho挥发系数 0.3~0.7太小信息素累积导致停滞太大等于没记忆。4.2 粒子群算法解 MTSP连续编码怎么映射到离散路径粒子群本来是连续优化解 MTSP 需要编码转换。常见做法是用「随机键」粒子位置是 N 维连续向量排序后得到访问顺序再按切分点分给各无人机。def pso_mtsp(coords, n_drones, n_particles40, n_iter200, w0.7, c11.5, c21.5): n len(coords) D build_dist_matrix(coords) # 位置和速度 X np.random.rand(n_particles, n) V np.random.rand(n_particles, n) * 0.1 pbest X.copy() pbest_cost np.full(n_particles, np.inf) gbest X[0].copy() gbest_cost float(inf) for it in range(n_iter): for i in range(n_particles): routes decode_particle(X[i], n_drones) cost, _ mtsp_objective(routes, D) if cost pbest_cost[i]: pbest_cost[i] cost pbest[i] X[i].copy() if cost gbest_cost: gbest_cost cost gbest X[i].copy() # 速度位置更新 r1, r2 np.random.rand(n), np.random.rand(n) V w*V c1*r1*(pbest - X) c2*r2*(gbest - X) X X V X np.clip(X, 0, 1) # 保持在 [0,1] return decode_particle(gbest, n_drones), gbest_cost逻辑说明decode_particle把连续向量排序得到访问顺序然后按某种规则切分给 n_drones 架无人机。切分可以均匀切也可以按累积距离切。w是惯性权重越大越全局搜索c1是个体学习c2是社会学习。常见调法是 w 从 0.9 线性降到 0.4前期探索后期收敛。参数说明粒子数 20~50迭代 100~500。这个算法比蚁群快但更容易早熟建议加变异或者重启机制。4.3 两种算法怎么选一张表说清维度蚁群 ACO粒子群 PSO适合规模中小规模20~50 点中小规模编码灵活收敛速度慢但稳定快易早熟参数敏感度beta、rho 影响大w、c1、c2 影响大约束处理天然离散好加约束需编码转换我的建议课程设计首选好讲想秀速度可以对比如果你只是要交课程设计蚁群足够而且注释好写、图好看。想加分就两个都实现做个对比实验。5. 避坑与排查跑不通、不收敛、结果不对怎么办5.1 现象程序跑完但所有无人机路径一样原因解码时切分点没生效或者所有粒子/蚂蚁共用同一条路径。常见于decode_particle里切分逻辑写错比如用了固定切分但没随粒子变化。解决打印每架无人机的路径长度如果完全相等检查切分函数是否真的按不同位置切。可以在切分前加随机扰动或者用累积距离比例切分。5.2 现象收敛曲线前期下降后期平但结果很差原因早熟收敛种群多样性丢失。蚁群里表现为信息素过度集中PSO 里表现为所有粒子挤在一起。解决蚁群提高 rho加快挥发或降低 alphaPSO 加惯性权重衰减、加随机变异。我一般会在 PSO 里每 50 代对最差 10% 粒子重新随机初始化。5.3 现象某架无人机路径长度为 0 或极短原因任务分配不均算法把点都塞给了一架。目标函数里均衡项权重太低或者根本没加。解决把weight_balance调到 0.5 以上试或者直接在约束里强制每架至少分配一个点。后者更硬但可能无解要留回退。5.4 现象换了坐标数据后结果全乱原因距离矩阵没重建或者坐标量纲不一致。很多人改数据只改 csv忘了build_dist_matrix是在 main 里调一次还是每次迭代调。解决确保距离矩阵在数据加载后重建一次且全局共用。坐标先做 min-max 归一化或者至少保证 x、y 量纲接近。5.5 现象matplotlib 画图中文乱码、负号显示方块原因默认字体不支持中文。解决在画图前加两行import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] # Windows # plt.rcParams[font.sans-serif] [Arial Unicode MS] # macOS plt.rcParams[axes.unicode_minus] FalseLinux 下如果没有 SimHei装fonts-wqy-zenhei或者换英文字体。6. 进阶技巧让课程设计从「能跑」到「能打」6.1 用参数扫描找一组靠谱参数不要手调写个循环跑网格import itertools best (None, float(inf)) for alpha, beta, rho in itertools.product([0.5,1.0,2.0], [2,3,5], [0.3,0.5,0.7]): routes, cost aco_mtsp(coords, n_drones3, alphaalpha, betabeta, rhorho) if cost best[1]: best ((alpha,beta,rho), cost) print(最优参数组合:, best)每个组合跑 3 次取平均避免随机性误导。这一步做完你的实验章节就有数据支撑了。6.2 加一个「无均衡项」对照组课程设计想拿高分光跑通不够要有对比。把weight_balance0和weight_balance0.5的结果画在一起展示总航程和均衡度的 trade-off。表格里放总航程、各机航程、标准差、最长单机航程。这样老师一眼能看到你理解问题本质。6.3 可视化路径图 收敛曲线 甘特图路径图是基本盘收敛曲线展示算法行为甘特图展示每架无人机的任务时间线。甘特图用 matplotlib 的 barh 就能画横轴是累计航程纵轴是无人机编号。这三张图放报告里比堆代码有说服力。6.4 我踩过最深的坑随机种子同一组参数跑两次结果差很多不是算法不稳定是没固定随机种子。在 main 开头加import numpy as np import random np.random.seed(42) random.seed(42)固定种子后结果可复现调参才有意义。但注意固定种子不代表算法确定只是你的实验可重复。写报告时说明这一点显得专业。6.5 最后一句实在话这类课程设计项目代码能跑只是及格线真正拉开差距的是你有没有理解「为什么这样建模」「参数为什么这样设」「结果为什么合理」。我一般会逼自己把每一行核心代码用一句话解释清楚解释不了就说明没懂。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。