在Python中,根据转移概率为TSP生成随机路径

In Python, generate a random path for the TSP according to transition probabilities

对于旅行商问题 (TSP),我想在 Python 中从状态转换矩阵 M ( n x n),其中 M[i,j] 包含最短全局路径将节点 i 连接到节点 j 的概率。

有人知道如何在 Python 中做到这一点吗?我在这里询问执行此操作的一般方法或模块。

示例:假设 M[i,j]=1 for j=(i+1)%n 和 0 别处。将生成的所有路径(总是从 0 开始)是:(0,1,2,...,n)。如果稍微更改此矩阵,将 1.0 替换为 0.9 并将 0.1 放在 M[i,i+2] 处,则可能的路径是:(0,2,3,..,n,1)。在这个某些概率为 0 的特定示例中,我知道最后一步是不可能的(从节点 n 到节点 1),因此您可以假设概率始终大于 0。

(如果您提供一些代码,这将是一个更好的问题;特别是因为该问题针对的是一个之前有很多步骤的步骤)

这里有一些方法,应该只作为一些想法,因为设置可能有点烦人(cvxpy 和一些 MIP-solver 这还不错;我在这里使用 CBC,请参阅 cvxpy 的文档备选方案或 setup-docs)。它也没有真正经过测试。这个想法有点基于概率图形模型中的 MAP-calculation,但转移可能在数学上是错误的(不保证)。这也更难,因为在我们的例子中 opt-problem 受到约束!

想法

制定一个 optimization-problem 最大化 a-priori-probabilities 使用的 = solution-path 的一部分(并且平方这个 = 更大的偏差受到更严重的惩罚),同时生成有效的解决方案(有效路径) .

虽然问题可能是 non-convex(我不确定),因此无法以 globally-optimal 方式解决),但我们正在使用一些 well-analyzed 启发式 此处凸规划的区别

备注: 这种方法是设计用来搜索 global-optimum(不完全正确,因为我们使用的是 nonconvex-optimization 算法)。这意味着,在这种方法中,使用不同解决方案的多次采样并不是很自然(但是使用不同的 starting-points 调用 DCCP 例程将很可能导致不同的解决方案)。

备注 2: non-small 实例(使用 non-commercial 求解器)的性能非常差,这使得它更 theoretical-approach。

实施

这里是使用Python3、numpy、scipy(最短路径)、cvxpy(opt-problem公式)和dccp(cvxpy的凸函数优化扩展的区别)的一些实现

代码

import numpy as np
from scipy.sparse.csgraph import csgraph_from_dense, shortest_path
from scipy.spatial import distance
from cvxpy import *
import dccp
np.random.seed(1)

""" Create random problem """
N = 10
distances = np.random.rand(N, N)                    # assymetric

""" Calculate shortest paths """
csparse_distances = csgraph_from_dense(distances)
shortest = shortest_path(csparse_distances)         # directed

""" Calculate a-prori probabilities based on global shortest paths """
shortest_global = np.copy(shortest)
for row in range(shortest_global.shape[0]):
    # normalize sum to 1
    row_sum = np.sum(shortest_global[row, :])
    shortest_global[row, :] /= row_sum

""" Formulate MIQP problem """
# Based on: https://en.wikipedia.org/wiki/Travelling_salesman_problem
#       and my example here: https://github.com/cvxgrp/cvxpy/blob/master/examples/tsp_mip.py#L16

# Variables
x = Bool(N, N)                                      # edge x,y in PATH
u = Int(N)                                          # aux-var

# Constraints
constraints = []

for j in range(N):                                      # ingoing: exactly 1
    indices = list(range(0, j)) + list(range(j + 1, N))
    constraints.append(sum_entries(x[indices, j]) == 1)
for i in range(N):
    indices = list(range(0, i)) + list(range(i + 1, N)) # outgoing: exactly 1
    constraints.append(sum_entries(x[i, indices]) == 1)

for i in range(1, N):                               # subtour-elimination
    for j in range(1, N):
        if i != j:
            constraints.append(u[i] - u[j] + N*x[i, j] <= N-1)

# Objective
obj = Maximize(sum_entries(square(mul_elemwise(shortest_global, x))))

# Solve
prob = Problem(obj, constraints)
print("problem is DCP: ", prob.is_dcp())
prob.solve(method='dccp', solver=CBC, ccp_times=10)  # do not use default solver!
# Remark: formulation above not accepted by CVX-ruleset
#         -> need "difference of convex function"-extension
#         -> heuristic (which is well-known for good behaviour)!


""" Print solution """
print('Solution path matrix')
print(np.round(x.value).astype('int'))
print('A-priori probability matrix')
print(np.round(shortest_global, 2))

输出

...
...
iteration= 1 cost value =  0.34508891154470694 tau =  0.005
iteration= 2 cost value =  0.5092119781611304 tau =  0.006
iteration= 3 cost value =  0.5092119781611304 tau =  0.0072
Solution path matrix
[[0 0 0 0 0 0 0 0 1 0]
 [1 0 0 0 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0]
 [0 0 0 0 1 0 0 0 0 0]
 [0 0 0 0 0 1 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 1]
 [0 0 1 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 1 0 0 0]
 [0 0 0 0 0 0 0 1 0 0]
 [0 1 0 0 0 0 0 0 0 0]]
A-priori probability matrix
[[ 0.    0.14  0.    0.24  0.11  0.07  0.07  0.03  0.13  0.21]
 [ 0.12  0.    0.09  0.22  0.01  0.17  0.13  0.11  0.06  0.07]
 [ 0.11  0.1   0.    0.27  0.08  0.12  0.05  0.02  0.1   0.15]
 [ 0.06  0.17  0.06  0.    0.15  0.12  0.11  0.09  0.01  0.23]
 [ 0.09  0.16  0.09  0.18  0.    0.13  0.13  0.11  0.05  0.05]
 [ 0.01  0.15  0.02  0.21  0.12  0.    0.08  0.05  0.15  0.22]
 [ 0.06  0.17  0.06  0.25  0.03  0.12  0.    0.09  0.11  0.11]
 [ 0.09  0.07  0.07  0.21  0.08  0.08  0.11  0.    0.14  0.15]
 [ 0.11  0.16  0.11  0.09  0.07  0.14  0.11  0.12  0.    0.1 ]
 [ 0.07  0.17  0.07  0.21  0.15  0.12  0.12  0.09  0.    0.  ]]

编辑:

  • 哎呀,不知何故 ECOS_BB 似乎仍在使用,这告诉我们更好的 solver-setup 有更多的潜力。