用lingo求解hamilton圈
hamilton圈:
包含的每个顶点的轨叫做Hamilton(哈密顿)轨;闭的Hamilton轨叫做Hamilton圈或圈;含Hamilton圈的图叫做Hamilton图。
直观地讲,Hamilton图就是从一顶点出发每顶点恰通过一次能回到出发点的那种图,即不重复地行遍所有的顶点再回到出发点。
分析:hamilton圈要每个点不重复的经过,因此要确定他,只需要确定选那几条边即可,假设有n个点的图,首先用flod算法算出任意两点的最短距离,此时可得到一个完全图。这时我们只需确定n条边即可。如果群举的话只需在 的2倍选出n条边,这时我们列出约束条件,用lingo求解:
一条边选不选我们用0-1变量标记(1表示选,0表示不选)
这时我们根据hamliton圈的特点(任意一个顶点的出度和入度都为1)列出约束条件
此时我们列出着两个条件,但不能确定是负这两个条件一定能得到hamilton圈,我们可以举反例试试能不能推翻它,
这时发现:若一共有6个人,3个一首尾相连,即有两个圈,此时他不是hamilton圈,因此我们还要增加条件,
让他只能形成一个圈,其实一个圈和多个圈的不同就是:构成这个圈的边的数量不同,因此增加条件:
先随便写一点:
从一点k1(编号)出发,就可以确定下一个点k2,(因为出度为1),依次类推,k3,k4,....kn,k1;
xk1k2+xk2k3+xk3k4+ ......xkn-1kn+xknk1 = n;
现在的问题是我们不知道(k1随便选),k2,k3,k4,....kn是什么,而使问题变的复杂,现在的解决方案(目前)好的方法是:
编号,假设选1号点为初始点,记为u(1)=1;与1号点相连的点假设为3,此时记u(3) = 2,那么1号点就与除三号点的其他点就不能够再相连,u(j)(j = 2,4,5,6,,,,n),此时u(j)什么不给赋值,参看下列公式:
但用lingo求解的话1式有分段函数,若用lingo处理会出现错误或速率降低,总而言之不适合lingo求解,我们需要处理一下,而且将等号装换为不等号,因为等号的要求太高,这样能加快速度吧更适合写程序。
编号之差最小为-(n-1);
lingo程序:
model:sets:
city / 1.. 53/: u;
link( city, city):
dist, ! 距离矩阵;
x;
endsets
n = @size( city);
data: !距离矩阵,它并不需要是对称的;
dist =@ole('E:\完全图.xls','DIST');//保证数据要对
!随机产生,这里可改为你要解决的问题的数据;
enddata
!目标函数;
min = @sum( link: dist * x);
//link为一个集合,x为真正的变量。
@FOR( city( K):
!进入城市K;
@sum( city( I)| I #ne# K: x( I, K)) = 1;
!离开城市K;
@sum( city( J)| J #ne# K: x( K, J)) = 1;
);
!保证不出现子圈;
@for(city(I)|I #gt# 1:
@for( city( J)| J#gt#1 #and# I #ne# J:
u(I)-u(J)+n*x(I,J)<=n-1);
);
!限制u的范围以加速模型的求解,保证所加限制并不排除掉TSP问题的最优解;
@for(city(I) | I #gt# 1: u(I)<=n-2 );
!定义X为0\1变量;
@for( link: @bin( x));
end