OR工具始终如一地返回非常不理想的TSP解决方案

时间:2016-09-05 10:12:45

标签: python or-tools

生成一些随机高斯坐标,我注意到TSP求解器返回了可怕的解决方案,但是对于相同的输入,它也会一遍又一遍地返回相同的可怕解决方案。

鉴于此代码:

import numpy
import math
from ortools.constraint_solver import pywrapcp
from ortools.constraint_solver import routing_enums_pb2

import matplotlib
%matplotlib inline
from matplotlib import pyplot, pylab
pylab.rcParams['figure.figsize'] = 20, 10


n_points = 200

orders = numpy.random.randn(n_points, 2)
coordinates = orders.tolist()

class Distance:
    def __init__(self, coords):
        self.coords = coords

    def distance(self, x, y):
        return math.sqrt((x[0] - y[0]) ** 2 + (x[1] - y[1]) ** 2)

    def __call__(self, x, y):
        return self.distance(self.coords[x], self.coords[y])

distance = Distance(coordinates)

search_parameters = pywrapcp.RoutingModel.DefaultSearchParameters()
search_parameters.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.LOCAL_CHEAPEST_ARC)

search_parameters.local_search_metaheuristic = routing_enums_pb2.LocalSearchMetaheuristic.TABU_SEARCH


routing = pywrapcp.RoutingModel(len(coordinates), 1)
routing.SetArcCostEvaluatorOfAllVehicles(distance)   

routing.SetDepot(0)
solver = routing.solver()
routing.CloseModel() # the documentation is a bit unclear on whether this is needed

assignment = routing.SolveWithParameters(search_parameters)

nodes = []
index = routing.Start(0)
while not routing.IsEnd(index):
    nodes.append(routing.IndexToNode(index))
    index = assignment.Value(routing.NextVar(index))

nodes.append(0)
for (a, b) in zip(nodes, nodes[1:]):
    a, b = coordinates[a], coordinates[b]
    pyplot.plot([a[0], b[0]], [a[1], b[1]], 'r' )

例如,对于10分,我得到了一个很好的解决方案:

enter image description here

对于20更糟糕的是,仍然存在一些明显的优化(其中一个只需要交换两个点。

enter image description here

对于200而言,这太可怕了:

enter image description here

我想知道上面的代码是否实际上有一些LNS,或者只返回初始值,特别是因为大多数first_solution_strategy选项都提示确定性初始化。

为什么上面的TSP求解器返回相同数据的一致解,即使禁忌搜索和模拟退火等是随机的。而且,为什么200点解决方案如此糟糕?

我在SearchParameters中使用了多个选项,特别是在local_search_operators中启用了“使用_...”字段。这没有效果,返回了相同的次优解决方案。

1 个答案:

答案 0 :(得分:6)

我认为问题在于距离测量:)。我记得来自or-tools的C代码样本中的kScalingFactor,用于缩放距离,然后将它们舍入(通过转换)为整数:or-tools期望距离为整数。

当然,标准高斯随机坐标之间的距离通常介于0到2之间,因此大多数点对在映射到整数时具有相同的距离:垃圾输入,垃圾输出。

我通过简单地乘法和转换为整数来修复它(只是为了确保swig不会将浮点数解释为整数):

# ...
def distance(self, x, y):
    return int(10000 * math.sqrt((x[0] - y[0]) ** 2 + (x[1] - y[1]) ** 2))
# ...

然后结果更有意义:

10分:

10 points

20分:

20 points

200分:

200 points