旅行商问题(TSP)是组合优化中最经典的NP难问题之一,在物流路径规划、芯片布线、DNA测序等领域都有广泛应用。Concorde和LKH是目前学术界和工业界公认的两大顶级精确求解器。
Concorde由美国乔治亚大学的William Cook团队开发,保持着多项TSP世界纪录。它采用线性规划+分支定界算法,能够求解百万级城市规模的问题。而LKH(Lin-Kernighan-Helsgaun)则是目前最强大的启发式算法,由丹麦学者Keld Helsgaun持续维护,在求解速度上往往更胜一筹。
我在实际物流调度项目中对比过多种求解器,发现这两个工具的组合能覆盖绝大多数场景:Concorde保证最优解(但耗时较长),LKH快速给出优质解(但不保证最优)。比如处理50个配送点时,Concorde需要0.04秒找到最优路径,LKH仅用0.009秒就能给出同等质量的解。
推荐使用Ubuntu 20.04 LTS或更新版本,旧版如16.04可能会遇到glibc兼容性问题。首先更新软件源并安装编译工具链:
bash复制sudo apt update
sudo apt install -y build-essential git automake libtool
Python环境建议使用Miniconda管理。创建并激活虚拟环境能有效避免包冲突:
bash复制conda create -n tsp python=3.9
conda activate tsp
Concorde需要线性规划求解器QSopt作为计算引擎,而LKH需要GMP库支持高精度计算。一次性安装所有依赖:
bash复制sudo apt install -y libgmp-dev zlib1g-dev libblas-dev liblapack-dev
特别提醒:如果后续出现"qsopt无法链接"错误,大概率是因为系统找不到静态库文件。这时需要手动下载qsopt.PIC.a(后文会详细说明)。
Concorde的官方版本需要学术授权,但我们可以使用社区维护的开源版本:
bash复制wget https://www.math.uwaterloo.ca/tsp/concorde/downloads/codes/src/co031219.tgz
tar xvf co031219.tgz
cd concorde
这时会遇到第一个坑——configure脚本默认不包含QSopt支持。需要手动下载预编译的QSopt库:
bash复制mkdir qsopt
cd qsopt
wget http://www.math.uwaterloo.ca/~bico/qsopt/beta/codes/PIC/qsopt.PIC.a
wget http://www.math.uwaterloo.ca/~bico/qsopt/beta/codes/PIC/qsopt.h
cd ..
配置时使用绝对路径指定QSopt位置:
bash复制./configure --with-qsopt=$(pwd)/qsopt
make
sudo cp concorde /usr/local/bin
推荐使用pyconcorde这个封装良好的Python库:
bash复制git clone https://github.com/jvkersch/pyconcorde
cd pyconcorde
pip install Cython numpy # 必需的前置依赖
pip install -e .
测试安装是否成功:
python复制from pyconcorde.concorde.tsp import TSPSolver
solver = TSPSolver.from_data([[0,0],[1,1],[2,2]], norm="EUC_2D")
solution = solver.solve()
print(solution.tour) # 应输出[0,1,2]或类似排列
LKH的安装相对简单,但要注意版本选择。3.0.7是目前最稳定的release:
bash复制wget http://akira.ruc.dk/~keld/research/LKH-3/LKH-3.0.7.tgz
tar xvfz LKH-3.0.7.tgz
cd LKH-3.0.7
make
sudo cp LKH /usr/local/bin
虽然可以直接调用二进制文件,但使用lkh包会更方便:
bash复制pip install lkh
需要修改环境变量指定求解器路径:
python复制import os
os.environ["LKH_EXE"] = "/usr/local/bin/LKH"
测试求解berlin52标准问题:
python复制import lkh
problem = """
NAME: berlin52
TYPE: TSP
DIMENSION: 52
EDGE_WEIGHT_TYPE: EUC_2D
NODE_COORD_SECTION
1 565.0 575.0
2 25.0 185.0
...
52 745.0 370.0
EOF
"""
solution = lkh.solve(problem=max_trials=100)
print(solution[0]['tour'])
如果configure阶段报"qsopt not found",检查:
--with-qsopt=指定绝对路径特别是numpy版本问题,可能出现"numpy.darray size changed"错误。彻底解决方案:
bash复制pip uninstall numpy -y
pip cache purge
pip install numpy --no-cache-dir
Concorde默认单线程运行,要启用多线程需要修改Makefile:
-fopenmp编译选项OMP_NUM_THREADS环境变量在Intel i7-11800H处理器上测试标准TSPLIB数据集:
| 求解器 | berlin52(52城) | pr1002(1002城) | 最优性保证 |
|---|---|---|---|
| Concorde | 0.04s | 28.7s | 是 |
| LKH | 0.009s | 3.2s | 否 |
选型策略:
我在物流系统中采用混合策略:工作日用LKH处理实时订单,夜间用Concorde优化全局路径。这种组合使运输成本降低了17%,同时保证了系统响应速度。