LINGO整数规划法解TSP问题
LINGO程序:
目前解的是6个城市的TSP问题,经过验证,30个城市的TSP问题基本可以做到秒解,50个城市的TSP问题也能在几秒内解出来。
但是100个城市的TSP问题就没办法轻易解出来了。因为TSP问题的增长规模甚至超过指数级。
注意看(2.2.1)的前三个条件都是很容易得出来的,分别表示:每个点的出度为1,入度为1,边只能取0和1;是TSP问题的典型特征(即最小哈密顿路径)。但是仅凭这三个条件是无法确定哈密顿路径的。原因是子巡回的问题。
子巡回的意思是城市序列中出现两个哈密顿回路,且他们不相交。如六个城市的旅行路线是(1-2-3-1)和(4-5-6-4)时,就是出现了子巡回,不满足TSP问题的条件。为此需要增加不含子巡回的条件。一种方法是添加变量u,并增加约束条件:
这样,含有子巡回的方案一定不满足条件:
反证法:假设一个有子巡回的方案满足条件,那么必定有一个不含有1的子巡回,假设子巡回为4-5-6-4,那么将此代入上式,得到
三者相加得到\(3n \le 3(n-1)\),即\(n \le n-1\) 显然不会成立。
不含有子巡回的方案中一定存在(可能不唯一)一种u的取值使得条件成立:
- 首先重复上面的方法,由于最后j不能取1,所以带有\(u_1\)的项不会被去掉,因此不会出现矛盾。
- 设起点的u为0,连接起点的第一个点u为1,第二个为2,...,以此类推,最后一个点为n-1。
考虑两种情况:- \(x_{ij} = 1\) : 此时\(u_i - u_j = -1, -1 + n \le n-1\) 符合条件。
- \(x_{ij} = 0\) : 此时由于u的取值不会超过n-1,因此 \(u_i - u_j \le n-1\).
需要特别注意的是我们无需设定u的取值规则,只需要设定u的取值约束即可。lingo会自动寻找到一种能使得u满足条件的取值方案,而满足取值约束的u所对应的方案一定没有子巡回,从而满足了我们的要求。不得不说,这是一种非常巧妙的方法!
你可以约束所有的\(u \le n-1\),这样,我们就可以根据u的取值直接看出哈密顿回路的连接方式了!
证明:
若i与j相连,则\(u_i-u_j\)必定是负数,否则不满足约束\(u_i - u_j + nx_{ij} \le n-1\)。这样u的值从点1(默认1为起始点,因为j不能取到1)到最后连向1的点单调增大,最后一个点(假设为t)的u值\(u_t\)一定是最大的。如果约束所有的点的u值\(u_i \le n-1\),那么\(u_t \le n-1\),这样的话就限制了从1连接到t的一串点的u值分别为0,1,2,...,n-1。进而确定了点的连接关系。
SETS: city/1..6/:u;
link(city, city): dist, x;
ENDSETS
DATA:
dist=
0 97 79 68 85 43
97 0 71 49 83 44
79 71 0 86 1 100
68 49 86 0 28 4
85 83 1 28 0 16
43 44 100 4 16 0;
ENDDATA
n=@SIZE(city);
MIN=@SUM(link: dist*x);
@FOR(city(I): @SUM(city(J)|J#NE#I: x(I, J))=1;);
@FOR(city(J): @SUM(city(I)|I#NE#J: x(I, J))=1;);
@FOR(city(I): @FOR(city(J)|I#NE#J #AND# J#GT#1:
u(I)-u(J)+n*x(I,J)<=n-1 ); );
@FOR(city(I): u(I)>=0);
@FOR(city(I): u(I)<=n-1);
@FOR(link: @BIN(x));