TSP问题

前言

TSP问题是广为人知的组合优化问题,它易于描述,但是难以求解。基于TSP问题的特性,决定使用通过TSP问题来学习各类启发算法,比较不同启发算法在旅行商问题上的表现。

问题

TSP问题可以描述为:现有一些节点,节点和节点之间均可相连形成边,节点之间的边存在距离,需要找到一个遍历方案先后访问所有的点,使的遍历的总距离最短。
在这里插入图片描述
在这里插入图片描述

模型

旅行商问题可以建模为一个纯整数规划模型:
在这里插入图片描述
目标函数最小化总距离,约束1-2保证每个节点都能进出一次,约束3保证不会出现多个圈,约束4-5保证便利顺序属于0~n-1,约束6-7约束变量为整数。

数据

数据集保存在distance.txt中,为纯距离数据,数据来源TSP问题官方dataset,共26个节点。

0	83	93	129	133	139	151	169	135	114	110	98	99	95	81	152	159	181	172	185	147	157	185	220	127	181
83	0	40	53	62	64	91	116	93	84	95	98	89	68	67	127	156	175	152	165	160	180	223	268	179	197
93	40	0	42	42	49	59	81	54	44	58	64	54	31	36	86	117	135	112	125	124	147	193	241	157	161
129	53	42	0	11	11	46	72	65	70	88	100	89	66	76	102	142	156	127	139	155	180	228	278	197	190
133	62	42	11	0	9	35	61	55	62	82	95	84	62	74	93	133	146	117	128	148	173	222	272	194	182
139	64	49	11	9	0	39	65	63	71	90	103	92	71	82	100	141	153	124	135	156	181	230	280	202	190
151	91	59	46	35	39	0	26	34	52	71	88	77	63	78	66	110	119	88	98	130	156	206	257	188	160
169	116	81	72	61	65	26	0	37	59	75	92	83	76	91	54	98	103	70	78	122	148	198	250	188	148
135	93	54	65	55	63	34	37	0	22	39	56	47	40	55	37	78	91	62	74	96	122	172	223	155	128
114	84	44	70	62	71	52	59	22	0	20	36	26	20	34	43	74	91	68	82	86	111	160	210	136	121
110	95	58	88	82	90	71	75	39	20	0	18	11	27	32	42	61	80	64	77	68	92	140	190	116	103
98	98	64	100	95	103	88	92	56	36	18	0	11	34	31	56	63	85	75	87	62	83	129	178	100	99
99	89	54	89	84	92	77	83	47	26	11	11	0	23	24	53	68	89	74	87	71	93	140	189	111	107
95	68	31	66	62	71	63	76	40	20	27	34	23	0	15	62	87	106	87	100	93	116	163	212	132	130
81	67	36	76	74	82	78	91	55	34	32	31	24	15	0	73	92	112	96	109	93	113	158	205	122	130
152	127	86	102	93	100	66	54	37	43	42	56	53	62	73	0	44	54	26	39	68	94	144	196	139	95
159	156	117	142	133	141	110	98	78	74	61	63	68	87	92	44	0	22	34	38	30	53	102	154	109	51
181	175	135	156	146	153	119	103	91	91	80	85	89	106	112	54	22	0	33	29	46	64	107	157	125	51
172	152	112	127	117	124	88	70	62	68	64	75	74	87	96	26	34	33	0	13	63	87	135	186	141	81
185	165	125	139	128	135	98	78	74	82	77	87	87	100	109	39	38	29	13	0	68	90	136	186	148	79
147	160	124	155	148	156	130	122	96	86	68	62	71	93	93	68	30	46	63	68	0	26	77	128	80	37
157	180	147	180	173	181	156	148	122	111	92	83	93	116	113	94	53	64	87	90	26	0	50	102	65	27
185	223	193	228	222	230	206	198	172	160	140	129	140	163	158	144	102	107	135	136	77	50	0	51	64	58
220	268	241	278	272	280	257	250	223	210	190	178	189	212	205	196	154	157	186	186	128	102	51	0	93	107
127	179	157	197	194	202	188	188	155	136	116	100	111	132	122	139	109	125	141	148	80	65	64	93	0	90
181	197	161	190	182	190	160	148	128	121	103	99	107	130	130	95	51	51	81	79	37	27	58	107	90	0

求解

使用ortools调用SCIP求解器对上述TSP问题进行求解。

import pandas as pd
from ortools.linear_solver import pywraplp

# 数据
distance = pd.read_table('distance.txt', header=None, index_col=None)
distance = distance.values.tolist()
city_num = len(distance)

# 求解器
solver = pywraplp.Solver.CreateSolver('SCIP')

# 决策变量
x = [[solver.IntVar(0, 1, 'x[{}][{}]'.format(i, j)) for j in range(city_num)] for i in range(city_num)]
y = [solver.IntVar(0, solver.infinity(), 'y[{}]'.format(i)) for i in range(city_num)]

# 目标函数
expression_obj = 0
for i in range(city_num):
    for j in range(city_num):
        expression_obj += distance[i][j] * x[i][j]
solver.Minimize(expression_obj)

# 约束
solver.Add(y[0] == 0, 'c0')
for i in range(city_num):
    solver.Add(sum([x[i][j] for j in range(city_num) if i != j]) == 1, 'c1[{}]'.format(i))  # 每个城市只能进一次
    solver.Add(sum([x[j][i] for j in range(city_num) if i != j]) == 1, 'c2[{}]'.format(i))  # 每个城市只能出一次
    solver.Add(y[i] <= city_num - 1, 'c3[{}]'.format(i))
    for j in range(1, city_num):
        if i == j:
            continue
        solver.Add(y[j] >= y[i] + 1 - (1 - x[i][j]) * city_num, 'c4[{}][{}]'.format(i, j))  # 防止多个圈

# 求解
# print(solver.ExportModelAsLpFormat(False))
print('number of variables = ', solver.NumVariables())
print('number of constraints = ', solver.NumConstraints())
status = solver.Solve()
# 结果
if status == solver.OPTIMAL:
    print('total length = ', solver.Objective().Value())
    print('the travel order is:')
    for i in range(city_num):
        for j in range(city_num):
            if y[j].solution_value() == i:
                print(j)
    print(0)
else:
    print('no optimal solution found')

结果

总旅行距离为937

number of variables =  702
number of constraints =  704
total length =  937.0
the travel order is:
0
24
23
22
25
21
20
16
17
19
18
15
10
11
12
14
13
9
8
7
6
4
5
3
2
1
0

Process finished with exit code 0
  • 27
    点赞
  • 92
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值