TSP问题的Lingo求解

Lingo编程解决TSP问题

TSP问题即巡回旅行商问题,一个商人旅行经过所有城市一次最后回到原点,问什么走法使走的路程最短。接下来用Lingo编程实现,此方法具有普遍性,建议小本本记下。
假设有6个城市

思路

利用01矩阵表示一次巡回旅行的方案。如下面矩阵代表一种方案。
( 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 ) \left( \begin{matrix}{} 0\quad1\quad0\quad0\quad0\quad0 \\ 0\quad0\quad1\quad0\quad0\quad0 \\ 0\quad0\quad0\quad1\quad0\quad0 \\ 0\quad0\quad0\quad0\quad1\quad0 \\ 0\quad0\quad0\quad0\quad0\quad1 \\ 1\quad0\quad0\quad0\quad0\quad0 \\ \end{matrix} \right) 010000001000000100000010000001100000
a12=1表示从城市1走到城市2。那么这个矩阵的路线为1–>2–>3–>4–>5–>6–>1。
观察这个矩阵的特点为每一行只有一个1,每一列只有一个1。但并不是这样的矩阵都是合理的,例如如下矩阵:
( 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 ) \left( \begin{matrix}{} 0\quad1\quad0\quad0\quad0\quad0 \\ 0\quad0\quad1\quad0\quad0\quad0 \\ 1\quad0\quad0\quad0\quad0\quad0 \\ 0\quad0\quad0\quad0\quad1\quad0 \\ 0\quad0\quad0\quad0\quad0\quad1 \\ 0\quad0\quad0\quad1\quad0\quad0 \\ \end{matrix} \right) 010000001000100000000010000001000100
这个矩阵的路线为:1–>2–>3–>1,4–>5–>6–>4。说明路线矩阵不能出现子圈。
总距离=路线矩阵*距离矩阵

建立线性规划模型

设城市之间的距离用矩阵d表示,dij表示城市i与城市j的距离。
设0–1矩阵X表示经过各城市之间的路线。xij=0表示城市i不到城市j,为1则反之。
路线矩阵每一行和为1:
∑ j = 1 n x i j = 1 , i = 1 , . . . , n ( i ≠ j ) \sum\limits_{j = 1}^n {x_{ij} = 1,i = 1,...,n} \quad(i\ne j) j=1nxij=1,i=1,...,n(i=j)
每一列和为1:
∑ i = 1 n x i j = 1 , j = 1 , . . . , n ( j ≠ i ) \sum\limits_{i = 1}^n {x_{ij} = 1,j = 1,...,n} \quad(j\ne i) i=1nxij=1,j=1,...,n(j=i)
路线矩阵不可以出现子圈(破圈),引入额外变量u:
u i − u j + n x i j ≤ n − 1 , 1 < i ≠ j ≤ n u_i-u_j+nx_{ij}\le n-1,\quad1< i\ne j\le n uiuj+nxijn1,1<i=jn
对于破圈公式的解释:

  1. 两个点出现子圈的情况: x i j = 1 , x j i = 1 。 x_{ij}=1,x_{ji}=1。 xij=1,xji=1
    x i j , x j i x_{ij},x_{ji} xij,xji代入破圈公式得: u i − u j ≤ − 1 , u j − u i ≤ − 1 u_i-u_j\le-1,\quad u_j-u_i\le-1 uiuj1,ujui1
    两式相加得: 0 ≤ − 2 0\le-2 02,显然不成立,保证了两个点不可能出现子圈。

  2. 对于三个点的情况: x i j = 1 , x j k = 1 , x k i = 1 x_{ij}=1,x_{jk}=1,x_{ki}=1 xij=1,xjk=1,xki=1 代入破圈公式得:
    u i − u j ≤ − 1 , u j − u k ≤ − 1 , u k − u i ≤ − 1 u_i-u_j\le-1,\quad u_j-u_k\le-1,\quad u_k-u_i\le-1 uiuj1,ujuk1,ukui1
    相加得: 0 ≤ − 3 0\le-3 03,不成立,保证了三个点不出现子圈。

  3. 对于n个点以此类推。

此外:
x i j = 0 或 1 , i , j = 1.. n x_{ij}=0或1,i,j=1..n\quad xij=01i,j=1..n u i 为 实 数 , i = 1.. n u_i为实数,\quad i=1..n uii=1..n
目标函数为:
m i n z = ∑ i = 1 n d i j ∑ j = 1 n x i j minz= \sum\limits_{i = 1}^n {d_{ij} } \sum\limits_{j = 1}^n {x_{ij} } minz=i=1ndijj=1nxij

Lingo编程代码如下

!TSP问题;
MODEL:
SETS:
city/1..6/:u;
link(city,city):d,x;
ENDSETS
DATA:
d=@FILE(E:\d.txt);!导入距离矩阵;
@text()=@writefor(link(i,j)|x(i,j)#GT#0:'x(',i,',',j,')=',x(i,j));!指定输出格式,输出为1的x;
ENDDATA
min=@sum(link:d*x);
@for(city(j):@sum(city(i)|j#ne#i:x(i,j))=1);!一列只有一个1;
@for(city(i):@sum(city(j)|j#ne#i:x(i,j))=1);!一行只有一个1;
@for(link(i,j)|i#ne#j#and#i#gt#1:u(i)-u(j)+6*x(i,j)<=5);!破圈;
@for(link:@bin(x));!x取0或1;
End

结果

在这里插入图片描述
解得最短路程是35,其路线为1–>4–>3–>2–>5–>6–>1。

  • 22
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 27
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值