当前位置: 首页 > news >正文

蚁群算法解决TSP问题

# 蚁群算法(ACO)求解 TSP —— 含中文注释与可视化(含信息素时序热力图)
# 约定:
# 1) 仅使用 matplotlib(不使用 seaborn),每张图单独绘制;不手动指定颜色;
# 2) 图中以中文标注,并在主图右侧给出“可调参数”说明;
# 3) 展示:最终最优路径、最优/平均长度曲线、以及信息素矩阵在若干关键代的热力图(体现中间演化);
# 4) 规模与迭代数选择为教学演示友好,确保在本环境内快速完成。你可按需放大参数。import math
import random
from typing import List, Tuple, Dict, Anyimport numpy as np
import matplotlib
import matplotlib.pyplot as plt# ---------------------- 中文显示设置 ----------------------
matplotlib.rcParams['font.sans-serif'] = ['SimHei', 'Noto Sans CJK SC', 'Arial Unicode MS', 'WenQuanYi Zen Hei']
matplotlib.rcParams['axes.unicode_minus'] = FalsePoint = Tuple[float, float]def euclid(a: Point, b: Point) -> float:return math.hypot(a[0]-b[0], a[1]-b[1])def build_distance_matrix(coords: List[Point]) -> np.ndarray:n = len(coords)D = np.zeros((n, n), dtype=float)for i in range(n):for j in range(n):if i == j:D[i, j] = 1e-12  # 避免除零else:D[i, j] = euclid(coords[i], coords[j])return Ddef tour_length(route: List[int], D: np.ndarray) -> float:n = len(route)s = 0.0for i in range(n):s += D[route[i], route[(i+1) % n]]return sdef ant_construct_solution(tau: np.ndarray, eta: np.ndarray, alpha: float, beta: float, rng: random.Random) -> List[int]:"""基于概率转移规则构造一条巡回(标准 Ant System,不做局部更新)。"""n = tau.shape[0]unvisited = list(range(n))route = []# 随机选择起点(也可固定起点,不影响闭环长度)current = rng.randrange(n)route.append(current)unvisited.remove(current)while unvisited:i = current# 计算到所有未访问城市的转移概率分子tau_i = tau[i, unvisited] ** alphaeta_i = eta[i, unvisited] ** betascore = tau_i * eta_itotal = float(np.sum(score))# 数值稳定处理if total <= 0.0 or not np.isfinite(total):# 退化为均匀采样next_idx = rng.randrange(len(unvisited))else:probs = score / total# 轮盘赌采样r = rng.random()cum = 0.0next_idx = 0for k, p in enumerate(probs):cum += float(p)if r <= cum:next_idx = kbreakcurrent = unvisited.pop(next_idx)route.append(current)return routedef aco_tsp(coords: List[Point],n_ants: int = 40,n_iters: int = 80,alpha: float = 1.0,beta: float = 5.0,rho: float = 0.5,Q: float = 100.0,seed: int = 2025,snapshot_gens: List[int] = None) -> Dict[str, Any]:"""经典 Ant System:- 信息素更新:tau = (1-rho)*tau + sum_k (Q/L_k) 在其巡回边上增量沉积- 概率转移:p_ij ∝ (tau_ij^alpha) * (eta_ij^beta),eta=1/d"""rng = random.Random(seed)n = len(coords)D = build_distance_matrix(coords)eta = 1.0 / D# 初始信息素(常用:与距离尺度同阶)init_tau = 1.0 / (np.mean(D))tau = np.full((n, n), init_tau, dtype=float)np.fill_diagonal(tau, 0.0)best_route = Nonebest_len = float("inf")best_hist = []mean_hist = []# 记录信息素矩阵快照(中间演化)if snapshot_gens is None:snapshot_gens = [0, n_iters//4, n_iters//2, n_iters-1]snapshots = {}for t in range(n_iters):routes = []lengths = []# 每只蚂蚁构造一条解for k in range(n_ants):r = ant_construct_solution(tau, eta, alpha, beta, rng)L = tour_length(r, D)routes.append(r)lengths.append(L)if L < best_len:best_len = Lbest_route = r[:]# 统计best_hist.append(min(lengths))mean_hist.append(sum(lengths) / len(lengths))# 更新信息素tau *= (1.0 - rho)  # 蒸发for r, L in zip(routes, lengths):deposit = Q / Lfor i in range(n):a, b = r[i], r[(i+1) % n]tau[a, b] += deposittau[b, a] += deposit# 保存快照if t in snapshot_gens:snapshots[t] = tau.copy()return {"best_route": best_route,"best_len": best_len,"best_hist": best_hist,"mean_hist": mean_hist,"tau_snapshots": snapshots,"D": D,"params": dict(n_ants=n_ants, n_iters=n_iters, alpha=alpha, beta=beta, rho=rho, Q=Q, seed=seed)}def add_param_box(ax, params: Dict[str, Any], extra: str = ""):text = ("可调参数:\n"f"• 蚂蚁数量 = {params['n_ants']}\n"f"• 迭代次数 = {params['n_iters']}\n"f"• alpha (信息素权重) = {params['alpha']}\n"f"• beta (启发式权重) = {params['beta']}\n"f"• rho (蒸发率) = {params['rho']}\n"f"• Q (沉积分子) = {params['Q']}\n"f"• 随机种子 = {params['seed']}\n""• 生成新解:按概率 p_ij ∝ (τ^alpha)(η^beta) 逐城选择")if extra:text += "\n" + extraax.text(1.02, 0.5, text, transform=ax.transAxes, va="center", ha="left",fontsize=10, bbox=dict(boxstyle="round", alpha=0.15))# ---------------------- 运行演示 ----------------------
random.seed(9)
N = 32
coords = [(random.uniform(0, 100), random.uniform(0, 100)) for _ in range(N)]result = aco_tsp(coords,n_ants=38,n_iters=70,alpha=1.0,beta=5.0,rho=0.45,Q=120.0,seed=2025,snapshot_gens=[0, 10, 30, 69])best_route = result["best_route"]
best_len = result["best_len"]
best_hist = result["best_hist"]
mean_hist = result["mean_hist"]
tau_snaps = result["tau_snapshots"]
params = result["params"]# ---------------------- 图1:最终最优巡回路径 ----------------------
plt.figure()
xs = [coords[i][0] for i in best_route] + [coords[best_route[0]][0]]
ys = [coords[i][1] for i in best_route] + [coords[best_route[0]][1]]
plt.plot(xs, ys, marker="o")
plt.title(f"最终最优巡回路径(总长度 = {best_len:.2f})")
plt.xlabel("X 坐标"); plt.ylabel("Y 坐标")
ax = plt.gca()
add_param_box(ax, params, extra="• 目标:最短闭合回路")
plt.tight_layout()
plt.show()# ---------------------- 图2:最优路径长度 vs 迭代 ----------------------
plt.figure()
plt.plot(range(len(best_hist)), best_hist)
plt.title("最优路径长度 随 迭代次数 的变化")
plt.xlabel("迭代次数"); plt.ylabel("最优路径长度")
ax = plt.gca(); add_param_box(ax, params)
plt.tight_layout(); plt.show()# ---------------------- 图3:平均路径长度 vs 迭代 ----------------------
plt.figure()
plt.plot(range(len(mean_hist)), mean_hist)
plt.title("群体平均路径长度 随 迭代次数 的变化")
plt.xlabel("迭代次数"); plt.ylabel("平均路径长度")
ax = plt.gca(); add_param_box(ax, params)
plt.tight_layout(); plt.show()# ---------------------- 图4-7:信息素矩阵热力图(中间演化) ----------------------
# 为避免子图,逐一绘制并标注代数
for gen, tau_mat in tau_snaps.items():plt.figure()plt.imshow(tau_mat)  # 不指定 cmap,使用默认plt.title(f"信息素强度矩阵(第 {gen} 代)")plt.xlabel("城市 j"); plt.ylabel("城市 i")ax = plt.gca()plt.colorbar(label="信息素强度 τ_ij")plt.tight_layout()plt.show()# ---------------------- 额外:保存关键图(可下载) ----------------------
plt.figure()
plt.plot(xs, ys, marker="o")
plt.title(f"最终最优巡回路径(总长度 = {best_len:.2f})")
plt.xlabel("X 坐标"); plt.ylabel("Y 坐标")
ax = plt.gca(); add_param_box(ax, params)
plt.tight_layout()
best_path_png = "/mnt/data/ACO_TSP_最终最优路径.png"
plt.savefig(best_path_png)
best_path_png

http://www.dtcms.com/a/449376.html

相关文章:

  • 数据库丢失但没备份过?救星:二进制日志
  • 【C++实战(74)】深入C++安全编程:密码学实战之旅
  • inbound 概念及题目
  • UNet改进(43):SaFA-MS-UNet如何提升图像分割精度?
  • 网站建设中的智能元素凡科建站代理商登录
  • Elasticsearch 之分页查询
  • apache hop 不能处理clickhouse 数组格式怎么办?
  • 网站建设 网站设计php语言网站开发公司北京
  • 代码审计
  • 制作网站需要钱吗天津网址
  • cursor使用之没有正常的编辑器中的运行箭头
  • 建设网站优化创意网站建设价格多少
  • soular入门到实战(3) - 如何实现TikLab工具链统一登录认证
  • Python图形界面——海龟绘图
  • 《强化学习数学原理》学习笔记9——值迭代算法
  • 网站建设 统一标准体系什么是网络销售
  • 网站开发语言有哪几种临沂专业网站制作
  • 花店网站建设方案网站木马文件删除
  • Bash 的基本语法总结
  • 网站怎么进行优化网站开发 英文文章
  • 自动驾驶决策规划算法(开幕式)
  • 从零起步学习Redis || 第八章:过期删除策略与内存淘汰策略详解及实战使用(LRU和LFU算法详解)
  • 自动驾驶中的传感器技术65——Navigation(2)
  • 知识体系_scala_利用scala和spark构建数据应用
  • 备案后网站打不开沈阳营销网站建设
  • AI编辑器(FIM补全,AI扩写)简介
  • 优设网设计师导航最新seo快排技术qq
  • 【C++】哈希和哈希封装unordered_map、unordered_set
  • VS Code安装即环境配置
  • 从 LiveData 到 Flow:状态、事件、背压与回调全面实战