首页 > 代码库 > 简学LINGO(三)——实例篇

简学LINGO(三)——实例篇

1. 装配线平衡模型

一个装配线含有一系列的工作站,在最终产品的加工过程中每个工作站执行一种或者是几种 特定的任务。装配线周期是指所有工作站完成分配给他们各自任务所花费时间的最大值。平衡装配线的目标是为每个工作站分配加工任务,尽可能使每个工作站执行 相同数量的任务,其最终标准是转配线周期最短。不适当的平衡装配线将会产生瓶颈——有较少任务的工作站将被迫等待前面分配了较多任务的工作站。

这个模型的目标是最小化装配线周期,有两类约束:

(1)要保证每件任务只能也必须分配至一个工作站来加工;

(2)要保证满足任务件的所有优先关系。

例  有1件任务(A-K)分配到四个工作站(1-4),任务按次序如下。每件任务所花时间如下

任务

时间

A

45

B

11

C

9

D

50

E

15

F

12

G

12

H

12

I

12

J

8

K

9

 

这里给出求解模型

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. model:  
  2.  !装配平衡模型;  
  3. sets:  
  4.  !任务集合,有一个完成时间属性T;  
  5.  TASK/A B C D E F G H I J K/:T;  
  6.  !人物之间的优先关系集合;  
  7.  PRED(TASK,TASK)/A,B B,C C,F C,G F,J G,J J,K  
  8.      D,E E,H E,I H,J I,J/;  
  9.  !工作站集合;  
  10.  STATION/1..4/;  
  11.  TXS(TASK,STATION):X;  
  12.  !X是派生集TXS的一个属性。如果X(I,K)=I,则表示第I个任务指派给第K个工作站完成;  
  13. endsets  
  14. data:  
  15.  !任务A B C D E F G H I J K的完成时间估计如下;  
  16. enddata  
  17.  !当任务超过15个时,模型求解将变的很慢:  
  18.  !每一个作业必须指派到一个工作站中;  
  19. @for(TASK(I):@SUM(STATION(K):X(I,K))=1);  
  20.  !对于每一个存在有限关系的作业来说,前者对应的工作站I必须小于后者对应的工作站J;  
  21. @for(PRED(I,J):@sum(STATION(K):K*X(J,K)-K*X(I,K))>=0);  
  22.  !对于每一个工作站来说,其花费时间不应大于装配线周期;  
  23. @for(STATION(K):  
  24.   @SUM(TXS(I,K):T(I)*X(I,K))<+CYCTIME);  
  25.  !目标函数时最小化转配线周期;  
  26. min=CYCTIME;  
  27.  !指定X(I,J)为0/1变量;  
  28. @for(TXS:@BIN(X));  
  29. end  

 

 

2.旅行售货员问题,又称货郎担问题

有一个销售员,从城市1出发,要遍访城市2,3,。。。,n个一次,最后返回城市1.已知从城市i到j的旅费为Cij,问他该按怎样的次序访问这些城市,是得总旅费最少?可以用多中方方法把TSP表示成整数规划模型。把该问题的每一个解看做时一个巡回。

在上述意义下,引入0-1整数变量
 

经过若干证明,这里就不在阐述了,我们可以把TSP转化为一个混合整数规划问题

 

 

 这里我们可以利用这个问题来求解一个具体问题

 问题1  现需要一台机器上加工n个零件,这些零件可以按照任意先后顺序在机器上进行加工。我们希望加工完成所有零件的总时间最小。由于加工工艺的要求,加工零件j时机器不许处在相应的状态Sj(如炉温)。设起始未加工任何零件时机器处于状态S0,且当所有零件加工完成后需回复到S0状态。已知从状态Si调整到Sj需要时间Cij。零件j本身加工时间为Pj。为方便起见,引入一个徐零件0,其中加工时间为0,要求状态为S0。则{0,1,2,。。。,n}的一个圈置转换pi就表示对所有零件的一个加工顺序,则完成所有加工所需时间为

 

这里给出一个解决该模型的一个简单的代码,就是套用上面的模型

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. !旅行售货员问题;  
  2. model:  
  3. sets:  
  4.   city/1..5/:u;  
  5.   link(city,city):dist,x;  
  6. endsets  
  7.   n=@size(city);  
  8. data:  
  9.   dist=@qrand(1);!随即产生,这里可以改为你要解决的问题的数据;  
  10. enddata  
  11.  !目标函数;  
  12. min=@sum(link:dist*x);  
  13. @for(city(K):  
  14.   @sum(city(I)|I#ne#K:x(I,K))=1;  
  15.   @sum(city(J)|J#ne#K:x(K,J))=1;  
  16. );  
  17.   
  18. !保证不出圈子;  
  19. @for(city(I)|I#gt#1:  
  20.   @for(city(J)|J#gt#1 #and# I#ne#j:  
  21.      u(I)-u(J)+n*x(I,J)<=n-1);  
  22. );  
  23. !定义X为0/1变量;  
  24. @for(link:@bin(x));  
  25. end  


3.最短路问题

给定N个点Pi组成集合{Pi},由集合中任一点Pi到另一点Pj的距离用Cij表示,如果Pi到Pj没有弧连接,则规定Cij=正无穷大,有规定Cii=0,指定一个终点PN,要求从Pi到PN的最短路线。这里我们用动态规划的方法来做。

 

 又LINGO我们可以很方便的求解上述的模型

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. !最短路问题;  
  2. model:  
  3. data:  
  4.   n=10;  
  5. enddata  
  6. sets:  
  7.   cities/1..n/:F;  
  8.   roads(cities,cities)/  
  9.     1,2 1,3  
  10.     2,4 2,5 2,6  
  11.     3,4 3,5 3,6  
  12.     4,7 4,8  
  13.     5,7 5,8 5,9  
  14.     6,8 6,9  
  15.     7,10  
  16.     8,10  
  17.     9,10  
  18. /:D,P;  
  19. endsets  
  20. data:  
  21. D=  
  22.     6 5                 !该矩阵即为传说中的权重矩阵  
  23.     3 6 9  
  24.     7 5 11  
  25.     9 1  
  26.     8 7 5  
  27.     4 10  
  28.     5  
  29.     7  
  30.     9;  
  31. enddata  
  32. F(n)=0;  
  33. @for(cities(i)|i#lt#n:  
  34.   F(i)=@min(roads(i,j):D(i,j)+F(j));  
  35. );  
  36. !显然,如果P(i,j)=1,则点i到点n的最短路径的第一步是i——j,否则就不是  
  37. 由此,我们就可方便的确定出最短路径;  
  38. @for(roads(i,j):  
  39.     P(i,j)=@if(F(i)#eq#D(i,j)+F(j),1,0)  
  40. );  
  41. end  

 

4.分配问题或称指派问题

这是给n个人分配n项工作以或得摸个最高效果的问题。第i个人完成第j项工作需要的平均时间为Cij。要求给每个人分配一项工作,并要求分配完这些工作,以使完成全部任务的总时间最小。该问题可以表示如下
 

 这个模型可以用LINGO很方便的求解

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. model:  
  2.   !7个工人,7个工作的分配问题;  
  3. sets:  
  4.     workers/w1..w7/;  
  5.     jobs/j1..j7/;  
  6.     links(workers,jobs):cost,volume;  
  7. endsets  
  8.   !目标函数;  
  9.     min=@sum(links:cost*volume);  
  10.   !每个人只能有一份工作;  
  11.     @for(workers(I):  
  12.         @sum(jobs(J):volume(I,J))=1;  
  13.     );  
  14. data:  
  15.     cost=6 2 6 7 4 2 5  
  16.          4 9 5 3 8 5 8  
  17.          5 2 1 9 7 4 3  
  18.          7 6 7 3 9 2 7  
  19.          2 3 9 5 7 2 6  
  20.          5 5 2 2 8 11 4  
  21.          9 2 3 12 4 5 10;  
  22. enddata  
  23. end       


 

5.二次分配问题

这个问题与上面的分配问题 ,大致相同。同样要引入0-1变量,而且和上述问题有同样的约束 。但是本问题又比约束问题要复杂。我们得到价格系数Cijkl,其解释是:在i(S上网一个元素)分配给j(T的一个元素)的同时把k(s的一个元素)分配给l(T的一个元素)所应承担的费用。显然只有当xij=1且xkl=1时,才承担这种费用。这时我们的模型要变成这样

 为了理解这个模型,我们在这里加入这个例子。首先认为S是一个工厂的集合,T是n个城市的集合。本问题就是要在每一个城市设置一个工厂,并要使工厂之间的总得通讯费用最少。通讯费用取决于:(1)每对工厂之间通讯的次数tik;(2)每对工厂所在两个城市之间的距离djl。所以就有cijkl=tik*djl(各位大仙凑活的看啊。。。)。因此总费用可以用上述的目标函数来表示。

这里给出一个很经典的题目,也是我遇到的第一道建模问题。想当年不知道lingo的好处,硬是凭着对C++的执拗,用了一堆栈啊,链表向量什么的用穷举给退出来啊,当时多么的自豪,哈哈哈

 

例:有四名同学到一家公司去参加三个阶段的面试:公司要求每个同学必须先找秘书初试,然后到部门主管去复制,最后到经理处去面试,并且不允许插队。由于四名同学的专业背景不同,所以没人在三个阶段的面试时间也不一样,如下表。这四名同学约定他们全部面试完成以后一起离开公司,问他们最快用多长时间完成面试?

 

这里给出求解的代码

 

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. !三阶段面试模型;  
  2. model:  
  3. sets:  
  4.     students;!学生集三阶段面试模型;  
  5.     phases;!阶段集;  
  6.     sp(students,phases):t,x;  
  7.     ss(students,students)|&1 #lt# &2:y;  
  8. endsets  
  9. data:  
  10.     students=s1..s4;  
  11.     phases=p1..p3;  
  12.     t=  
  13.         13 15 20  
  14.         10 20 18  
  15.         20 16 10  
  16.         8  10 15;  
  17. enddata  
  18.     ns=@size(students);!学生数;  
  19.     np=@size(phases);!阶段数  
  20.       
  21.     !单个学生面试时间先后顺序的约束;  
  22.     @for(sp(I,J)|J#LT#np:  
  23.         x(I,J)+t(I,J)<=x(I,J+1)  
  24.     );  
  25.     !学生间的面试先后次序保持不变的约束;  
  26.     @for(ss(I,K):  
  27.         @for(phases(J):  
  28.         x(I,J)+t(I,J)-x(K,J)<=200*y(I,K);  
  29.         x(K,J)+t(K,J)-x(I,J)<=200*(1-y(I,K));  
  30.         )  
  31.     );  
  32.     min=TMAX;  
  33.     @for(students(I):  
  34.         x(I,3)+t(I,3)<=TMAX  
  35.     );  
  36.     !把Y定义0-1变量;  
  37.     !把Y定义0-1变量;  
  38.     @for(ss:@bin(y));  
  39. end  


 以后如果遇到相应的更好的模型是,我会有选择的加上的。

l