我在Python中找不到2-opt算法的任何完整实现,因此我试图将缺少的部分添加到找到的here的代码中,下面将对此进行介绍。
def two_opt(route):
best = route
improved = True
while improved:
improved = False
for i in range(1, len(route)-2):
for j in range(i+1, len(route)):
if j-i == 1: continue # changes nothing, skip then
new_route = route[:]
new_route[i:j] = route[j-1:i-1:-1] # this is the 2woptSwap
if cost(new_route) < cost(best): # what should cost be?
best = new_route
improved = True
route = best
return best
为了完成此代码,我制作了一个小程序,从文本文件中提取长/纬度坐标,并用每个点的成本填充邻接矩阵。完整的代码,包括输入坐标和邻接矩阵的样本,可以在Code Review上找到。
由于我不知道上面的代码中的cost
函数是什么,所以我的想法是计算出从一个点到另一个点的所有成本,并将其放在邻接矩阵:adj_matrix
中。这表示每个点与其他点的距离。
我尝试将成本/邻接矩阵传递给该函数以使用该函数,但是鉴于邻接矩阵,我无法计算成本。
def main():
# code to read from file
# code to append co-ordinates to points and calculate the haversine distance between each point
route = random.sample(range(10), 10)
best = two_opt(route, adj_matrix) # passing my adjacency matrix
print(best)
ValueError:具有多个元素的数组的真值不明确。使用a.any()或a.all()
另一个Python 2选项问题:Generate all neighbors for 2OPT in python
任何有关如何从邻接矩阵中找到正确成本的建议。
答案 0 :(得分:1)
首先,一个adjacency matrix is typically a (0, 1)-matrix。在这里,您所拥有的被称为 cost , weight 或距离矩阵。
现在是您的问题。
成本函数可以很简单:
def cost(cost_mat, route):
return cost_mat[np.roll(route, 1), route].sum()
在这里,np.roll()
将路线“旋转”一个位置,以使其易于与route
一起使用,以建立成本矩阵索引。 sum()
只需将各个路段的费用相加即可计算出路线的总费用。
(如果您决定查看非对称TSP,则需要确保行/列顺序与cost_mat
的构造方式匹配;对于欧氏TSP,这与成本矩阵是对称的。)
使用示例:
cost_mat = np.array([
[0, 1, 2, 3],
[1, 0, 4, 5],
[2, 4, 0, 7],
[3, 5, 7, 0],
])
route = np.array([2, 1, 3, 0])
print(cost(cost_mat, route))
答案 1 :(得分:0)
2-opt删除两个边并创建两个新边(假设成本矩阵是对称的),因此可以简化成本函数以仅考虑变化的边。对于大型阵列,这比枚举整个路径要快得多。
import numpy as np
def cost_change(cost_mat, n1, n2, n3, n4):
return cost_mat[n1][n3] + cost_mat[n2][n4] - cost_mat[n1][n2] - cost_mat[n3][n4]
def two_opt(route, cost_mat):
best = route
improved = True
while improved:
improved = False
for i in range(1, len(route) - 2):
for j in range(i + 1, len(route)):
if j - i == 1: continue
if cost_change(cost_mat, best[i - 1], best[i], best[j - 1], best[j]) < 0:
best[i:j] = best[j - 1:i - 1:-1]
improved = True
route = best
return best
if __name__ == '__main__':
nodes = 1000
init_route = list(range(nodes))
print(init_route)
cost_mat = np.random.randint(100, size=(nodes, nodes))
cost_mat += cost_mat.T
np.fill_diagonal(cost_mat, 0)
cost_mat = list(cost_mat)
best_route = two_opt(init_route, cost_mat)
print(best_route)
答案 2 :(得分:0)
我在 Python 中实现了 2-opt 算法。您可以使用 pip install py2opt
从 PyPi 服务器安装它。您还可以找到它的实现 here。使用此包,您可以计算最短距离(虽然不是全局最小值)和最佳对应路线。
这是如何在几行中使用此库的示例。
from py2opt.routefinder import RouteFinder
cities_names = ['A', 'B', 'C', 'D']
dist_mat = [[0, 29, 15, 35], [29, 0, 57, 42], [15, 57, 0, 61], [35, 42, 61, 0]]
route_finder = RouteFinder(dist_mat, cities_names, iterations=5)
best_distance, best_route = route_finder.solve()
print(best_distance)
114
print(best_route)
['A', 'C', 'B', 'D']
我在这篇文章中对其进行了更详细的解释:How to Solve the Traveling Salesman Problem — A Comparative Analysis