栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

使用pyconcorde计算二维平面的旅行商问题(TSP)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用pyconcorde计算二维平面的旅行商问题(TSP)

简介

众所周知,TSP问题是一个NP问题,想精确求得解需要指数级的计算量。即使使用分支限界方法等非近似算法算得依然很慢。在大部分情况只能考虑通过近似的方法来求解。比较好的近似算法有:

Lin–Kernighan 在100以内几乎可以得到最优解,速度很快,时间复杂度 O ( n 2.2 ) O(n^{2.2}) O(n2.2)Christofides 理论最坏情况可以达到1.5倍的近似比,时间复杂度 O ( n 3 ) O(n^3) O(n3)

但是由William J. Cook等人实现的精确求解器Concorde,通过特殊的数值优化技巧却达到了很快的速度。规模几百左右的TSP问题都能够在很快求解。非常适用用来做学术研究。

本文对该求解器的python包装版本pyconcorde进行了安装和使用。记录了详细的配置步骤和实验结果。

安装环镜

语言环境:python 3.8

系统环境:ubuntu 20 x64 或 OSX 12.0.1 x64

安装依赖
git clone  https://github.com/jvkersch/pyconcorde
cd pyconcorde
pip install . -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple
使用示例
from concorde.tsp import TSPSolver
from typing import *
from random import random
import matplotlib.pyplot as plt
import numpy as np

def tsp(dots:List[Tuple[float, float]])->List[int]:
    """
    TSP最优算法(concorde)
    :param dots: 一系列的点的坐标,点之间的距离表示代价
    :return: 一系列点的编号,代表得到的哈密顿环
    """
    # solver only supports integral edge weights, so here float will be rounded to two
    # decimals, multiplied by 100 and converted to integer
    xs = []
    ys = []
    for (x, y) in dots:
        xs.append(int(x * 1000))
        ys.append(int(y * 1000))
    solver = TSPSolver.from_data(xs, ys, norm="EUC_2D")
    solution = solver.solve()
    #print(solution.found_tour)
    #print(solution.optimal_value)
    #print(solution.tour)
    return solution.tour.tolist()

class ConcordeTsp(object):
    """
    TSP算法封装类
    使用方法:ConcordeTsp(dots).tsp()
    其中,dots为二维平面上的点的列表
    """
    def __init__(self, dots:List[Tuple[float, float]]):
        # 去除重复的点
        dotSet = set()
        dotFilted = []
        for dot in dots:
            if not dot in dotSet:
                dotSet.add(dot)
                dotFilted.append(dot)
        self.__dots = dotFilted

    def tsp(self)->List[int]:
        """
        :return: tsp回路的近似解,返回结果不包含初始结点
        """
        return tsp(self.__dots)

if __name__ == "__main__":
    """以下是测试代码"""
    dots = []
    xs = []
    ys = []
    for i in range(51):
        x = random()
        y = random()
        dots.append((x, y))
        xs.append(x)
        ys.append(y)
    path = ConcordeTsp(dots).tsp()
    print(path)
    path.append(path[0])
    plt.scatter(np.array(xs)[path], np.array(ys)[path])
    for i in range(len(xs)):
        plt.annotate(str(path[i]),
                     xy=(xs[path[i]], ys[path[i]]),
                     xytext=(xs[path[i]] + 0.0001, ys[path[i]] + 0.0001))
        # 这里xy是需要标记的坐标,xytext是标签显示的位置
    plt.plot(np.array(xs)[path], np.array(ys)[path])
    plt.show()

请查看 concordewapper.py 中的测试代码。下面是一个规模为51的欧式空间TSP问题的运行结果

注意

OSX 系统需要在pyconcorde中的setup.py开头处添加以下代码(为了跳过SSL验证,否则安装pyconcorde会报错)。

import ssl
ssl._create_default_https_context = ssl._create_unverified_context

本项目使用的是pyconcorde版本是 0.1.0

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/740816.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号