lingo解决线性规划问题的程序经典要点.docx
《lingo解决线性规划问题的程序经典要点.docx》由会员分享,可在线阅读,更多相关《lingo解决线性规划问题的程序经典要点.docx(20页珍藏版)》请在冰豆网上搜索。
lingo解决线性规划问题的程序经典要点
Lingo12软件培训教案
Lingo主要用于求解线性规划,整数规划,非线性规划,V10以上版本可编程。
例1一个简单的线性规划问题
!
exam_1.lg4源程序
max=2*x+3*y;
[st_1]x+y<350;
[st_2]x<100;
2*x+y<600;!
决策变量黙认为非负;<相当于<=;大小写不区分
当规划问题的规模很大时,需要定义数组(或称为矩阵),以及下标集(set)
下面定义下标集和对应数组的三种方法,效果相同:
:
r1=r2=r3,a=b=c.
sets:
r1/1..3/:
a;
r2:
b;
r3:
c;
link2(r1,r2):
x;
link3(r1,r2,r3):
y;
endsets
data:
ALPHA=0.7;
a=111213;
r2=1..3;
b=111213;
c=111213;
enddata
例2运输问题
计算6个发点8个收点的最小费用运输问题。
产销单位运价如下表。
B1
B2
B3
B4
B5
B6
B7
B8
产量
A1
6
2
6
7
4
2
5
9
60
A2
4
9
5
3
8
5
8
2
55
A3
5
2
1
9
7
4
3
3
51
A4
7
6
7
3
9
2
7
1
43
A5
2
3
9
5
7
2
6
5
41
A6
5
5
2
2
8
1
4
3
52
销量
35
37
22
32
41
32
43
38
解:
设决策变量
=第i个发点到第j个售点的运货量,i=1,2,…m;j=1,2,…n;记为
=第i个发点到第j个售点的运输单价,i=1,2,…m;j=1,2,…n
记
=第i个发点的产量,i=1,2,…m;记
=第j个售点的需求量,j=1,2,…n.其中,m=6;n=8.
设目标函数为总成本,约束条件为
(1)产量约束;
(2)需求约束。
于是形成如下规划问题:
把上述程序翻译成LINGO语言,编制程序如下:
!
exam_2.lg4源程序
model:
!
6发点8收点运输问题;
sets:
rows/1..6/:
s;!
发点的产量限制;
cols/1..8/:
d;!
售点的需求限制;
links(rows,cols):
c,x;!
运输单价,决策运输量;
endsets
!
-------------------------------------;
data:
s=60,55,51,43,41,52;
d=3537223241324338;
c=62674295
49538582
52197433
76739271
23957265
55228143;
enddata
!
------------------------------------;
min=@sum(links:
c*x);!
目标函数=运输总成本;
@for(rows(i):
@sum(cols(j):
x(i,j))<=s(i));!
产量约束;
@for(cols(j):
@sum(rows(i):
x(i,j))=d(j));!
需求约束;
end
例3把上述程序进行改进,引进运行子模块和打印运算结果的语句:
!
exam_3.lg4源程序
model:
!
6发点8收点运输问题;
sets:
rows/1..6/:
s;!
发点的产量限制;
cols/1..8/:
d;!
售点的需求限制;
links(rows,cols):
c,x;!
运输单价,决策运输量;
endsets
!
==================================;
data:
s=60,55,51,43,41,52;
d=3537223241324338;
c=62674295
49538582
52197433
76739271
23957265
55228143;
enddata
!
==================================;
submodeltransfer:
min=cost;!
目标函数极小化;
cost=@sum(links:
c*x);!
目标函数:
运输总成本;
@for(rows(i):
@sum(cols(j):
x(i,j))
产量约束;
@for(cols(j):
@sum(rows(i):
x(i,j))>d(j));!
需求约束;
endsubmodel
!
==================================;
calc:
@solve(transfer);!
运行子模块(解线性规划);
@divert('transfer_out.txt');!
向.txt文件按自定格式输出数据;
@write('最小运输成本=',cost,@newline
(1),'最优运输方案x=');
@for(rows(i):
@write(@newline
(1));
@writefor(cols(j):
'',@format(x(i,j),'3.0f')));
@divert();!
关闭输出文件;
endcalc
end
打开transfer_out.txt文件,内容为:
最小运输成本=664
最优运输方案x=
0190041000
100320000
0110000400
000005038
347000000
0022002730
例4data段的编写技巧
(1):
从txt文件中读取原始数据
!
exam_3.lg4源程序中的data也可以写为:
data:
s=@file('transfer_data.txt');
d=@file('transfer_data.txt');
c=@file('transfer_data.txt');
enddata
其中,transfer_data.txt的内容为:
!
transfer.lg4程序的数据;
!
产量约束s=;
60,55,51,43,41,52~
!
需求约束d=;
3537223241324338~
!
运输单价c=;
62674295
49538582
52197433
76739271
23957265
55228143~
!
注:
字符~是数据分割符,若无此符,视所有数据为一个数据块,只赋给一个变量;
例5lingo程序的的3种输入和3种输出方法;
!
exam_5.lg4的源程序;
sets:
rows/1..3/:
;
cols/1..4/:
;
link(rows,cols):
a,b,mat1,mat2;
endsets
data:
b=1,2,3,4
5,6,7,8
9,10,11,12;!
程序内输入;
a=@file('a.txt');!
外部txt文件输入;
mat1=@ole('d:
\lingo12\data.xls',mat1);!
EXcel文件输入;
enddata
calc:
@text('a_out.txt')=a;!
列向量形式输出数据;
@for(link:
mat2=2*mat1);
@ole('d:
\lingo12\data.xls')=mat2;!
把mat2输出到xls文件中的同名数据块;
!
向.txt文件按自定格式输出数据(参照前例);
Endcalc
例6程序段中的循环和选择结构举例
!
exam_6.lg4的源程序;
sets:
rows/1..5/:
;
cols/1..3/:
;
links(rows,cols):
d;
endsets
data:
d=023
432
132
472
216;
enddata
calc:
i=1;
@while(i#le#5:
a=d(i,1);b=d(i,2);c=d(i,3);
@ifc(a#eq#0:
@write('infeasible!
',@newline
(1));
@else
delta=b^2-4*a*c;
sqrt=@sqrt(@if(delta#ge#0,delta,-delta));
@ifc(delta#ge#0:
@write('x1=',(-b+sqrt)/2/a,'x2=',(-b-sqrt)/2/a,@newline
(1));
@else
@write('x1=',-b/2/a,'+',sqrt/2/a,'i','x2=',-b/2/a,'-',sqrt/2/a,'i',@newline
(1));
);
);
i=i+1;
);
endcalc
本程序中的循环结构也可以用@for(rows(i):
程序体);进行计算。
例7指派问题(n人n任务费用最小)
B1
B2
B3
B4
B5
B6
A1
6
2
6
7
4
2
A2
4
9
5
3
8
5
A3
5
2
1
9
7
4
A4
7
6
7
3
9
2
A5
2
3
9
5
7
2
A6
5
5
2
2
8
1
解:
设决策变量
=1或0,表示第i个人是否完成第j项任务,i,j=1,2,…n;记
=第i个人完成第j项任务的费用,i,j=1,2,…n;n=6.
设目标函数为总费用,约束条件为
(1)每人只完成一项任务;
(2)每项任务只由一人完成。
于是形成如下规划问题:
!
exam_7.lg4的源程序;
model:
!
6人6任务指派问题;
sets:
rows/1..6/:
;!
6人6任务;
links(rows,rows):
c,x;!
费用和决策变量;
endsets
!
-------------------------------------;
data:
c=626742
495385
521974
767392
239572
552281;
enddata
!
==================================;
submodelappointment:
min=cost;!
目标函数极小化;
cost=@sum(links:
c*x);!
目标函数:
总费用;
@for(rows(i):
@sum(rows(j):
x(i,j))=1);!
每人完成一项;
@for(rows(j):
@sum(rows(i):
x(i,j))=1);!
每项由一人完成;
@for(links:
@bin(x));!
0-1变量约束;
endsubmodel
submodelbinVar:
@for(links:
@bin(x));!
0-1变量约束;
endsubmodel
!
==================================;
calc:
@solve(appointment,binVar);!
运行子模块(解线性规划);
@divert('appointment_out.txt');!
向.txt文件按自定格式输出数据;
@write('最小指派费用=',cost,@newline
(1),'分配方案x=');
@for(rows(i):
@write(@newline
(1));
@writefor(rows(j):
'',@format(x(i,j),'3.0f')));
@divert();!
关闭输出文件;
endcalc
end
例8多目标规划转化为单目标规划问题举例
把上述运输问题稍加修改,考虑到运输量可以要取整数,就变成整数规划问题,而且运输问题除了成本最小一个目标以外,有时也要考虑各发点的运输量尽量均衡作为另一个目标。
本程序处理的方法一是两目标加权平均,方法二是只选一个目标,另一个目标转化为约束,从而把多目标改为单目标。
!
exam_8.lg4源程序;
model:
!
6发点8收点运输问题;
sets:
rows/1..6/:
s;!
发点的产量限制;
cols/1..8/:
d;!
售点的需求限制;
links(rows,cols):
c,x;!
运输单价,决策运输量;
endsets
!
==================================;
data:
s=60,55,51,43,41,52;
d=3537223241324338;
c=62674295
49538582
52197433
76739271
23957265
55228143;
enddata
!
==================================;
submodelobj_1:
min=minCost;!
目标函数极小化;
minCost=@sum(links:
c*x);!
目标函数:
运输总成本;
endsubmodel
submodelobj_2:
min=objValue;
objValue=0.4*obj1+0.6*obj2;!
二目标加权平均;
obj1=@sum(links:
c*x);!
目标函数1:
运输总成本;
obj2=max1-min1;!
目标函数2:
发点运输量极差;
@for(links(i,j):
@sum(cols(j):
x(i,j))@sum(cols(j):
x(i,j))>min1;);
endsubmodel
submodelobj_3:
min=obj2;
obj2=max1-min1;!
目标函数:
发点运输量极差;
@for(links(i,j):
@sum(cols(j):
x(i,j))@sum(cols(j):
x(i,j))>min1;);
cost1=@sum(links:
c*x);!
运输总成本;
cost1<1.05*minCost;!
运输总成本约束;
endsubmodel
submodelsubject_to_1:
@for(rows(i):
@sum(cols(j):
x(i,j))
产量约束;
@for(cols(j):
@sum(rows(i):
x(i,j))>d(j));!
需求约束;
endsubmodel
submodelsubject_to_2:
@for(links:
@gin(x));!
整数约束;
endsubmodel
!
==================================;
calc:
@solve(obj_1,subject_to_1,subject_to_2);!
运行子模块(解线性整数规划);
@divert('intModel_out.txt');
@write(@newline
(2),'整数规划的最小运输成本=',minCost,@newline
(1),'最优运输方案x=');
@for(rows(i):
@write(@newline
(1));
@writefor(cols(j):
'',@format(x(i,j),'3.0f')));
@divert();@pause();
@solve(obj_2,subject_to_1,subject_to_2);!
运行子模块(解线性整数规划);
@divert('intModel_out.txt','a');!
向.txt文件追加输出数据;
@write(@newline
(2),'二目标加权平均最小值=',objValue,@newline
(1),'最优运输方案x=');
@for(rows(i):
@write(@newline
(1));
@writefor(cols(j):
'',@format(x(i,j),'3.0f')));
@divert();@pause();
@solve(obj_3,subject_to_1,subject_to_2);!
运行子模块(解线性整数规划);
@divert('intModel_out.txt','a');!
向.txt文件追加输出数据;
@write(@newline
(2),'成本约束时极差最小值=',obj2,@newline
(1),'成本约束时运输量最平均方案x=');
@for(rows(i):
@write(@newline
(1));
@writefor(cols(j):
'',@format(x(i,j),'3.0f')));
@divert();
endcalc
end
本例中的运输量均衡指标,可以用方差表示,但变成非线性规划问题,只能求出局部最优解,而线性规划的最优解是全局最优解。
例9杂例1
model:
!
费波那契数列;!
exam_9.lg4源程序;
sets:
II/1..100/:
Fi;!
费波那契数列;
endsets
!
==================================;
submodelmyProc:
Fi
(1)=1;
Fi
(2)=1;
@for(II(i)|(i#ge#3)#and#(i#le#n):
Fi(i)=Fi(i-1)+Fi(i-2));
endsubmodel
!
==================================;
calc:
n=10;
@solve(myProc);
@divert('Fibo_out.txt');
@writefor(II(k)|k#le#n:
'Fi(',@format(k,'2.0f'),')=',
@format(Fi(k),'3.0f'),@newline
(1));
@divert();
endcalc
end
例10杂例2
sets:
II/1..3/:
;
links(II,II):
a,x;
endsets
data:
a=1,2,3
2,1,4
3,2,2;
enddata
submodelfMin:
!
求函数的极值,极小值点;
min=z^2+4*z+3;
@free(z);
endsubmodel
submodelfzero:
!
解方程,求函数的零点;
@cos(y)=y;
@bnd(0,y,5);
endsubmodel
submodelget_invMat:
!
解矩阵方程,求逆阵;
@for(II(i):
@for(II(j):
@sum(II(k):
a(i,k)*x(k,j))=@if(i#eq#j,1,0)));
@for(links:
@free(x));
endsubmodel
calc:
@solve(fMin);
@solve(fzero);
@solve(get_invMat);
endcalc
Lingo编程语言参考:
LINGO有9种类型的函数:
1.基本运算符:
包括算术运算符、逻辑运算符和关系运算符
2.数学函数:
三角函数和常规的数学函数
3.金融函数:
LINGO提供的两种金融函数
4.概率函数:
LINGO提供了大量概率相关的函数
5.变量界定函数:
这类函数用来定义变量的取值范围
6.集操作函数:
这类函数为对集的操作提供帮助
7.集循环函数:
遍历集的元素,执行一定的操作的函数
8.数据输入输出函数:
允许模型和外部数据源相联系,进行数据输入输出
9.辅助函数:
各种杂类函数
1.基本运算符
1.1算术运算符
^、﹡、/、﹢、﹣
1.2逻辑运算符:
#not#否定该操作数的逻辑值,#not#是一个一元运算符
#eq#若两个运算数相等,则为true;否则为flase
#ne#若两个运算符不相等,则为true;否则为flase
#gt#若左边的运算符严格大于右边的运算符,则为true;否则为flase
#ge#若左边的运算符大于或等于右边的运算符,则为true;否则为flase
#lt#若左边的运算符严格小于右边的运算符,则为true;否则为flase
#le#若左边的运算符小于或等于右边的运算符,则为true;否则为flase
#and#仅当两个参数都为true时,结果为true;否则为flase
#or#仅当两个参数都为false时,结果为false;否则为true
1.3关系运算符
“=”、“<=”和“>=”,LINGO中还能用“<”表示小于等于关系,
2.2数学函数
三角函数@sin(x),@sinh(x),@asin(x),@asinh(x),@cos(x),@cosh(x),@acos(x),@acosh(x),@tan(x),@tanh(x),@atan(x),@atanh(x),@atan2(x)
@abs(x)返回x的绝对值
@exp(x)返回常数e的x次方
@floor(x)返回去掉小数部分后的整数
@log(x)返回x的自然对数
@log10(x)返回x的以10为底的对数
@lgm(x)返回x的gamma函数的自然对数
@mod(m,n)返回用n整除m的余数.,如@mod(5,3)返回2;
@pi()返回圆周率
@pow(x,y)返回x的y次幂
@sign(x)如果x<0返回-1;否则