在 TSPLIB 中计算距离

问题描述 投票:0回答:1

您好,我在从 tsp 库计算城市之间的距离时遇到问题:http://www.math.uwaterloo.ca/tsp/world/countries.html。我有这组数据(吉布提的城市):http://www.math.uwaterloo.ca/tsp/world/dj38.tsp。我在这里使用此函数来计算此 QaA 中的距离:http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/TSPFAQ.html。我用 python 编写了这个程序,现在看起来像这样,这是我的代码:

cityCoords = {
    1:(11003.611100,42102.500000),
    2:(11108.611100,42373.888900),
    3:(11133.333300,42885.833300),
    4:(11155.833300,42712.500000),
    5:(11183.333300,42933.333300),
    6:(11297.500000,42853.333300),
    7:(11310.277800,42929.444400),
    8:(11416.666700,42983.333300),
    9:(11423.888900,43000.277800),
    10:(11438.333300,42057.222200),
    11:(11461.111100,43252.777800),
    12:(11485.555600,43187.222200),
    13:(11503.055600,42855.277800),
    14:(11511.388900,42106.388900),
    15:(11522.222200,42841.944400),
    16:(11569.444400,43136.666700),
    17:(11583.333300,43150.000000),
    18:(11595.000000,43148.055600),
    19:(11600.000000,43150.000000),
    20:(11690.555600,42686.666700),
    21:(11715.833300,41836.111100),
    22:(11751.111100,42814.444400),
    23:(11770.277800,42651.944400),
    24:(11785.277800,42884.444400),
    25:(11822.777800,42673.611100),
    26:(11846.944400,42660.555600),
    27:(11963.055600,43290.555600),
    28:(11973.055600,43026.111100),
    29:(12058.333300,42195.555600),
    30:(12149.444400,42477.500000),
    31:(12286.944400,43355.555600),
    32:(12300.000000,42433.333300),
    33:(12355.833300,43156.388900),
    34:(12363.333300,43189.166700),
    35:(12372.777800,42711.388900),
    36:(12386.666700,43334.722200),
    37:(12421.666700,42895.555600),
    38:(12645.000000,42973.333300)
    }

def calcCityDistances(coordDict):
    cities = list(coordDict.keys())
    n = len(cities)
    distances = {}
    latitude = []
    longitude = []
    RRR = 6378.388;
    PI = 3.141592;

    for i in range(1,n+1):
        cityA = cities[i-1]
        latA, longA = coordDict[cityA]
        deg = int(latA)
        Min = latA - deg
        latitude.append(PI * (deg + 5 * Min / 3) / 180)
        deg = int(longA);
        Min = longA - deg;
        longitude.append(PI * (deg + 5 * Min / 3) / 180)

    for i in range(1,n+1):
        for j in range(i + 1, n + 1):
            q1 = cos(longitude[i-1] - longitude[j-1]);
            q2 = cos(latitude[i-1] - latitude[j-1]);
            q3 = cos(latitude[i-1] + latitude[j-1]);
            key = frozenset((i, j))
            distances[key] = {}
            dist = RRR * acos(0.5 * ((1.0 + q1) * q2 - (1.0 - q1) * q3)) + 1.0  
            distances[key]['dist'] = dist
            distances[key]['pher'] = init_fer
            distances[key]['vis'] = 0

    return  distances 

distances = calcCityDistances(cityCoords)

我的问题是,在这个算法中计算的距离在大范围内是不准确的。城市之间一条路线的平均长度是 10 000 公里,问题是最佳 TSP 路线是 6635。你可以想象,当我将其应用到我的蚁群系统算法时,结果约为 110 000 公里。这和6千真的不一样。有人可以解释一下我做错了什么吗?

python distance traveling-salesman
1个回答
0
投票

我不熟悉 TSP 常见问题解答中列出的距离计算。 这是我过去使用过的资源:http://www.movable-type.co.uk/scripts/latlong.html

他给出了两种大圆距离计算方法。 两者看起来都不像 TSP 提供的那样。 但是,他们都产生了一个似乎符合现实的距离(Diksa 和 Dikhil 相距约 31k)。

输入数据的单位是千分之一度,我不确定转换为给定的弧度是否考虑到了这一点。

这是一个可能会给您带来更好结果的实现:注意我将输入数据更新为度数:

import cmath
import math

cityCoords = {
    1:(11.0036111,42.1025),
    2:(11.1086111,42.3738889)
    }

def spherical_cosines(coordDict):
    R = 6371;  # kilometers
    cities = list(coordDict.keys())
    n = len(cities)
    for i in range(1,n+1):
        for j in range(i + 1, n + 1):
            cityA = cities[i-1]
            lat1, lon1 = coordDict[cityA]
            cityB = cities[j-1]
            lat2, lon2 = coordDict[cityB]
            lat1_radians = math.radians(lat1)
            lat2_radians = math.radians(lat2)
            lon1_radians = math.radians(lon1)
            lon2_radians = math.radians(lon2)
            print('A={},{} B={},{}'.format(lat1_radians, lon1_radians, lat2_radians, lon2_radians))
            delta_lon_radians = math.radians(lon2-lon1)
            distance = cmath.acos(cmath.sin(lat1_radians) * cmath.sin(lat2_radians) + cmath.cos(lat1_radians) *
                        math.cos(lat2_radians) * cmath.cos(delta_lon_radians)) * R;
            print('spherical_cosines distance={}'.format(distance))


spherical_cosines(cityCoords)

更新: 您发布的代码没有产生正确的距离值。 这是使用 calcCityDistances 和球余弦的前两个城市:

input loc=11003.6111, 42102.5
input loc=11108.6111, 42373.8889
radians A = 192.05631381917777,734.8329132074075
B=193.88890915251113,739.5740671363777
calcCityDistances distance = 8078.816781077703
input degrees A=11.0036111,42.1025 B=11.1086111,42.3738889
radians A=0.19204924330399503,0.7348272483209126
B=0.19388183901858905,0.7395638781792782
spherical_cosines> distance=(31.835225475974934+0j)

单位是公里。 球余弦产生大致正确的值。 您使用的代码与您发布的代码相同吗? 请注意,弧度转换似乎没有考虑输入的千分之一度

© www.soinside.com 2019 - 2024. All rights reserved.