用Python解决TSP问题(2)——动态规划算法

文章源码在Github:https://github.com/jinchenghao/TSP

本介绍用python解决TSP问题的第二个方法——动态规划法

算法介绍

动态规划算法根据的原理是,可以将原问题细分为规模更小的子问题,并且原问题的最优解中包含了子问题的最优解。也就是说,动态规划是一种将问题实例分解为更小的、相似的子问题,并存储子问题的解而避免计算重复的子问题,以解决最优化问题的算法策略。

 

我使用DP求解TSP问题的主要分为三个主要部分:

1)     假定我们从城市0出发,经过了所有城市,并返回到城市0。那么我们需要记录的信息有:当前所在城市location,当前未遍历的城市集合s。

2)     状态转移方程,状态转移方程是DP算法的核心部分,它代表了子问题和原问题的关系,通过状态转移方程可以将原问题不断细分为各个子问题。我们状态转移方程的定义如下所示:

 

 

 

T(s,init)代表的意思是从init点出发经过s中全部的点回到init的距离。

3)     构建T表记录T的值,如果不去记录每次递归的T值,那么以后每次搜索都要重新计算,就成了暴力搜索。所以我们构建一个T表dp[s][init],记录每次求出来的T函数值,即将T(s,init)的值记录在dp[s][init]位置。

程序

输入:

1 2066 2333
2 935 1304
3 1270 200
4 1389 700
5 984 2810
6 2253 478
7 949 3025
8 87 2483
9 3094 1883
10 2706 3130

代码:

"""
动态规划法
name:xxx
date:6.8
"""
import pandas as pd
import numpy as np
import math
import time

dataframe = pd.read_csv("./data/TSP10cities.tsp",sep=" ",header=None)
v = dataframe.iloc[:,1:3]

train_v= np.array(v)
train_d=train_v
dist = np.zeros((train_v.shape[0],train_d.shape[0]))

#计算距离矩阵
for i in range(train_v.shape[0]):
    for j in range(train_d.shape[0]):
        dist[i,j] = math.sqrt(np.sum((train_v[i,:]-train_d[j,:])**2))

"""
N:城市数
s:二进制表示,遍历过得城市对应位为1,未遍历为0
dp:动态规划的距离数组
dist:城市间距离矩阵
sumpath:目前的最小路径总长度
Dtemp:当前最小距离
path:记录下一个应该到达的城市
"""

N=train_v.shape[0]
path = np.ones((2**(N+1),N))
dp = np.ones((2**(train_v.shape[0]+1),train_d.shape[0]))*-1

def TSP(s,init,num):
    if dp[s][init] !=-1 :
        return dp[s][init]
    if s==(1<<(N)):
        return dist[0][init]
    sumpath=1000000000
    for i in range(N):
        if s&(1<<i):
            m=TSP(s&(~(1<<i)),i,num+1)+dist[i][init]
            if m<sumpath:
                sumpath=m
                path[s][init]=i
    dp[s][init]=sumpath
    return dp[s][init]

if __name__ == "__main__":
    init_point=0
    s=0
    for i in range(1,N+1):
        s=s|(1<<i)
    start = time.clock()
    distance=TSP(s,init_point,0)
    end = time.clock()
    s=0b11111111110
    init=0
    num=0
    print(distance)
    while True:
        print(path[s][init])
        init=int(path[s][init])
        s=s&(~(1<<init))
        num+=1
        if num>9:
            break
    print("程序的运行时间是:%s"%(end-start))

结果:

  • 11
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
TSP问题(Traveling Salesman Problem,旅行商问题)是一个经典的组合优化问题,它要求在给定的城市之间找到一条最短路径,使得每个城市只被经过一次,并且最终回到起点。 在本文中,我们将介绍如何使用Python解决TSP问题动态规划算法动态规划算法 动态规划算法是一种解决复杂问题的有效方法,它通常用于优化问题。TSP问题动态规划算法的思路是:将问题分解为子问题,然后通过计算子问题的最优解来逐步构建整个问题的最优解。 具体来说,我们可以使用以下步骤来解决TSP问题: 1. 定义状态:将TSP问题定义为一个二元组$(S,i)$,其中$S$表示已经经过的城市集合,$i$表示当前所在的城市。 2. 定义状态转移方程:我们定义$dp(S,i)$表示从城市$i$出发,经过集合$S$中所有城市的最短路径长度。状态转移方程为: $$ dp(S,i) = \begin{cases} 0 & \text{if } S=\{i\} \\ \min\limits_{j\in S,j\ne i}\{dp(S-\{i\},j)+dist[j][i]\} & \text{otherwise} \end{cases} $$ 其中$dist[i][j]$表示城市$i$到城市$j$之间的距离。 3. 初始状态:$dp(\{i\},i)=0$。 4. 最终状态:$dp(\{1,2,\cdots,n\},1)$即为所求的最短路径长度。 代码实现 下面是使用Python实现TSP问题动态规划算法的代码: ```python import math def tsp_dp(dist): n = len(dist) # 记录子问题的最优解 dp = [[math.inf] * n for _ in range(1 << n)] # 初始状态 for i in range(n): dp[1 << i][i] = 0 # 构建状态转移方程 for s in range(1, 1 << n): for i in range(n): if s & (1 << i) == 0: continue for j in range(n): if i == j or s & (1 << j) == 0: continue dp[s][i] = min(dp[s][i], dp[s ^ (1 << i)][j] + dist[j][i]) # 返回最终状态 return min(dp[(1 << n) - 1][i] + dist[i][0] for i in range(n)) # 示例 dist = [ [0, 2, 9, 10], [1, 0, 6, 4], [15, 7, 0, 8], [6, 3, 12, 0] ] print(tsp_dp(dist)) # 输出:21 ``` 在上面的代码中,我们首先使用$dp$数组记录子问题的最优解,然后通过状态转移方程逐步构建整个问题的最优解。 最后,我们通过计算$dp(\{1,2,\cdots,n\},1)$和从最后一个城市回到起点的距离之和的最小值来得到TSP问题的最优解。 总结 通过本文,我们学习了如何使用Python解决TSP问题动态规划算法TSP问题是一个经典的组合优化问题,它的解决方法还有很多其他的算法,例如分支定界算法、遗传算法等。如果你对这些算法感兴趣,可以进一步学习相关的知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值