介绍 遗传算法 与 TSP问题

遗传算法(Genetic Algorithm,GA)

一、核心定义

遗传算法是模仿达尔文生物进化论+遗传学全局随机优化算法 ,由美国学者 John Holland 在20世纪70年代提出,。

简单说:模拟生物"优胜劣汰、基因交叉、变异",在海量可行解里,一步步筛选出最优/近似最优解


二、核心生物学类比

生物概念 遗传算法对应概念
种群 一组候选解
染色体 单个解的编码(二进制/实数编码)
基因 解里的单个参数
适应度 解的好坏评分(目标函数)
选择 保留优质解、淘汰劣质解
交叉 两个优质解交换部分参数,产生新解
变异 随机小幅修改解,避免陷入局部最优

三、完整运行流程(五步循环)

  1. 初始化种群
    随机生成一堆初始候选解,作为第一代。
  2. 计算适应度
    给每个解打分:越接近目标,适应度越高。
  3. 选择(优胜劣汰)
    优先保留分数高的优质个体,劣质个体大概率被淘汰。
  4. 交叉(基因重组)
    优质个体两两结合,交换部分基因,生成下一代新解。
  5. 变异(随机微调)
    小概率随机改动个别基因,防止算法"钻牛角尖"困在局部最优。

不断重复「评估→选择→交叉→变异」多代迭代,直到达到迭代次数/满足精度,输出最优解。


四、关键特点

优点

  1. 全局搜索,不容易卡在局部最优;
  2. 不要求目标函数连续、可导,复杂非线性问题也能用;
  3. 并行搜索,同时处理大量候选解,适合多维、复杂优化。

缺点

  1. 属于启发式算法,不一定算出绝对全局最优,多为近似最优;
  2. 超参数(交叉概率、变异概率、种群大小)需要调参;
  3. 迭代量大,复杂问题计算耗时较长。

五、适用场景

用来解决传统数学方法难算的优化问题

  1. 组合优化:路径规划(旅行商TSP)、排课、仓库布局;
  2. 函数寻优:多峰、非线性复杂函数最大值/最小值求解;
  3. 工程设计:结构参数优化、电路设计、PID参数整定;
  4. 机器学习:特征筛选、神经网络权重优化;
  5. 生产调度、资源分配等复杂决策问题。

六、极简例子

比如:求一个复杂函数的最小值

  1. 随机生成100组自变量(种群);
  2. 代入函数算结果,结果越小适应度越高;
  3. 选结果最好的50组,互相交叉组合、少量随机变异;
  4. 生成新100组,循环100代;
  5. 最后一代里数值最小的,就是近似最优解。

补充:和普通算法区别

  • 传统梯度算法:单点搜索,顺着坡度走,容易困在局部最优;
  • 遗传算法:种群多点并行搜索,靠进化迭代,适合复杂无规则的优化问题。

TSP问题是什么? 它与遗传算法有何关系?

一、TSP 问题是什么

1. 全称

TSP = 旅行商问题(Traveling Salesman Problem)

2. 通俗定义

一个商人要走遍N 个城市

  • 每个城市必须走且只能走一次
  • 最终回到起点
  • 总路程最短的行走路线

给定一系列城市和每对城市之间的距离,求解一条经过每个城市恰好一次并最终返回起点的最短路径。

用数学语言描述:

在完全无向图(或有向图)中,寻找一条总长度最小的哈密顿回路(Hamiltonian cycle)。

3. 数学本质

典型组合优化问题 + NP难问题

城市数量稍微变多,暴力穷举就完全算不动:

城市数为 (n),路线排列数:

\\text{路线总数} = (n-1)! \\div 2

举个例子:

  • 10个城市:(181440) 条路线
  • 15个城市:(435.89) 亿条路线

城市越多,暴力枚举完全不可行,传统精确算法算力爆炸。

4. 现实等价场景

物流配送路线、无人机巡检、PCB电路板打孔、景区游览规划、仓储搬运路径等,本质都是 TSP。


二、遗传算法 与 TSP 的关系

1. 核心关系

TSP 是遗传算法最经典、最常用的标杆测试案例
遗传算法是解决大规模 TSP 最主流的启发式方法之一

简单一句话:

TSP 太难精确求解,用遗传算法快速算出近似最优最短路径

2. 遗传算法如何对应解决 TSP

把 TSP 路线,直接映射成遗传算法的「染色体」:

遗传算法概念 TSP 问题对应内容
个体/染色体 一条城市行走顺序路线,如:[1,3,5,2,4,1]
基因 单个城市编号
种群 一大堆不同的行走路线
适应度 路线总距离的倒数(路程越短,适应度越高)
选择 保留短路线、淘汰长路线
交叉 两条优质路线,交换片段,生成新路线
变异 随机交换两个城市顺序,跳出局部最差路线

3. 为什么遗传算法适合 TSP

  1. TSP 是非线性、不连续、无梯度的组合问题,传统微积分、梯度优化完全用不了
  2. 遗传算法是全局随机搜索,不会卡在某一条局部短路线;
  3. 不用遍历全部排列,迭代进化快速收敛到近最优解
  4. 城市数量越大,相比暴力算法优势越明显。

4. 局限性

遗传算法算出的是近似最优解,不一定是全局绝对最短,但在工程里完全够用,效率极高。


三、总结

  1. TSP:走遍所有城市仅一次、回路最短的路径规划难题,属于NP难问题;
  2. 二者关系
    • TSP 是遗传算法的经典应用场景+教学范例
    • 遗传算法是高效求解大规模 TSP 的核心算法;
    • 通过选择、交叉、变异不断优化行走顺序,快速得到最短近似路线。

下面是一份 极简、可直接运行的**Python 遗传算法求解 TSP **完整代码,注释清晰、易懂。

python 复制代码
import math
import random

# 1. 城市坐标
cities = [
    (2, 3),
    (5, 8),
    (1, 9),
    (7, 2),
    (4, 6),
    (8, 7)
]
city_num = len(cities)

# 2. 计算两个城市距离
def distance(city1, city2):
    return math.hypot(city1[0]-city2[0], city1[1]-city2[1])

# 3. 计算一条路线总长度
def calc_path_len(path):
    length = 0
    for i in range(city_num - 1):
        length += distance(cities[path[i]], cities[path[i+1]])
    # 回到起点,形成回路
    length += distance(cities[path[-1]], cities[path[0]])
    return length

# 4. 遗传算法核心参数
pop_size = 50      # 种群数量
gen_num = 200       # 迭代代数
cross_rate = 0.8    # 交叉概率
mutate_rate = 0.1   # 变异概率

# 初始化种群:随机生成路线
population = []
for _ in range(pop_size):
    path = list(range(city_num))
    random.shuffle(path)
    population.append(path)

# 选择:轮盘赌 + 保留最优
def select(pop):
    fit_list = [1 / calc_path_len(p) for p in pop]
    total_fit = sum(fit_list)
    new_pop = []
    # 精英保留:直接保留当前最优
    best = pop[fit_list.index(max(fit_list))]
    new_pop.append(best)
    # 轮盘赌选择
    for _ in range(pop_size - 1):
        r = random.uniform(0, total_fit)
        cur = 0
        for idx, f in enumerate(fit_list):
            cur += f
            if cur >= r:
                new_pop.append(pop[idx])
                break
    return new_pop

# 交叉:顺序交叉(适配TSP,避免重复城市)
def cross(p1, p2):
    if random.random() > cross_rate:
        return p1.copy()
    left = random.randint(0, city_num-2)
    right = random.randint(left+1, city_num-1)
    child = [None] * city_num
    child[left:right+1] = p1[left:right+1]
    # 填充剩余城市
    idx = 0
    for node in p2:
        if node not in child:
            while child[idx] is not None:
                idx += 1
            child[idx] = node
    return child

# 变异:随机交换两个城市
def mutate(path):
    if random.random() < mutate_rate:
        i, j = random.sample(range(city_num), 2)
        path[i], path[j] = path[j], path[i]
    return path

# 进化一代
def evolve(pop):
    new_pop = select(pop)
    children = []
    for i in range(0, pop_size, 2):
        p1 = new_pop[i]
        p2 = new_pop[i+1] if i+1 < pop_size else new_pop[i]
        c1 = cross(p1, p2)
        c2 = cross(p2, p1)
        children.append(mutate(c1))
        children.append(mutate(c2))
    return children

# 主循环
if __name__ == "__main__":
    best_path = None
    best_len = float("inf")

    for g in range(gen_num):
        population = evolve(population)
        # 记录每代最优
        cur_best = min(population, key=calc_path_len)
        cur_len = calc_path_len(cur_best)
        if cur_len < best_len:
            best_len = cur_len
            best_path = cur_best
        if (g + 1) % 50 == 0:
            print(f"第{g+1}代 | 最短距离: {best_len:.2f}")

    print("\n===== 最终结果 =====")
    print("最优路线城市顺序:", best_path)
    print("最短回路总距离:{:.2f}".format(best_len))

代码对应关系(GA ↔ TSP)

  1. 染色体 :城市访问顺序列表 [0,2,5,1,...]
  2. 适应度1/路线总长,路程越短适应度越高
  3. 选择:保留短路径路线
  4. 交叉:特殊顺序交叉,保证城市不重复
  5. 变异:交换两座城市位置,跳出局部最优

运行效果

迭代 200 代,逐步收敛到近似最优闭环路径,城市数量增加也能正常运行。

相关推荐
解救女汉子2 小时前
SQL触发器如何获取触发源应用名_利用APP_NAME函数追踪
jvm·数据库·python
思绪无限2 小时前
YOLOv5至YOLOv12升级:血细胞检测系统的设计与实现(完整代码+界面+数据集项目)
人工智能·python·深度学习·目标检测·计算机视觉·yolov12·血细胞检测
skywalk81634 小时前
发现Kotti项目的python包Beaker 存在安全漏洞
开发语言·网络·python·安全
天天进步20154 小时前
Python全栈项目:从零构建基于 Django 的知识管理系统(KMS)
开发语言·python·django
珎珎啊5 小时前
Python3 迭代器与生成器
开发语言·python
思绪无限5 小时前
YOLOv5至YOLOv12升级:金属锈蚀检测系统的设计与实现(完整代码+界面+数据集项目)
人工智能·python·深度学习·目标检测·计算机视觉·yolov12
yejqvow125 小时前
Pandas 高效实现组内跨行时间戳匹配与布尔标记
jvm·数据库·python
2501_921960855 小时前
协同本体论:元公理体系、普适演化律则与工程范式统一构建
python·重构·numpy·pandas·scipy
小锋java12345 小时前
【技术专题】Matplotlib3 Python 数据可视化 - Matplotlib3 绘制热力图(Heatmap)
python