! l7 g( {3 f3 N" |/ Z# C助力国赛 | 第3弹 规划问题(Lingo版)
. M$ |+ h0 L/ O5 z4 O1 M3 n, \0 ?
. a9 P% [: \. T) Z! S- w& ^3 a- P" m/ S% r5 h
前言上次介绍了用MATLAB来求解规划问题,功能强大是强大,但总觉得有点不爽,函数里面的参数有点难记,万一输错了岂不玩完了。的确在可读性这方面,MATLAB做的差一点。正是基于此在此向各位推荐另一款软件——Lingo。Lingo在数学规划上也是大名鼎鼎的。本次首先会简单介绍下Lingo和其基本操作,齐次介绍些高级操作,最后还是回到实际问题中,在具体问题中一睹Lingo的强大。 - 基本操作
- 高级操作
- 实际应用
) G8 K1 z: n" m+ D- H/ r# ~
) @3 U8 c' }. W基本操作简介Lingo是美国Lindo系统公司开发的一套专业的求解最优化问题的软件包,可以求解线性规划、二次规划、非线性规划、线性方程组、非线性方程组和整数规划等。LINGO软件有多种版本,如LINDO,GINO 和LINGO(包括LINGO NL)软件。在这些软件中关系最让人“头痛”的恐怕就时Lingo与Lindo的关系,其实可以这样简单的理解:Lindo是可以是这些软件集合的代名词,Lingo只是其中一种具体的软件而已。管他们什么关系,知道现在被广泛使用的是Lingo就行了。
9 R) W2 j0 s( XLingo是一款商业软件,使用是需要付费的,可以登录他们的官网:http://www.lindo.com 进行查看,但在天国获取的方法就不仅限于此了,具体可以访问某度,在此就不细说了。
: _! p& \: M6 r% h1 Z ![]()
& ~ |( V' O# K! d' k1 |0 @8 X下面“吹一吹”Lingo。 强大的求解整数规划功能是Lingo软件的最大特色,且求解速度非常快。Lingo还是最优化问题的一种数学建模语言,它包括许多常用的数学函数,这些函数可供使用者在建立最优化模型时调用。此外,Lingo提供与文本文件、Excel文件和数据库文件的接口,便于输入、求解和分析大规模最优化问题。
4 K) ~( [- d4 U* ]% Y2 B) C初印象第一眼还是很重要的,下面就看一看Lingo。" U+ j. S3 f# \% O
建面如下:. P' t9 S/ [; ]/ [8 e
![]()
: d4 D+ e* Q1 t. x7 Q2 y/ L W常用工具栏: ![]()
: d$ \0 n* l. K5 D3 M( zLingo文件类型: 文件后缀名为“.lg4”保存了模型窗口中所能够看到的所有文本和其他对象及其格式信息。 运算符算数运算符: 用于数与数之间的数学运算。
5 q3 h. O1 h9 b/ R; j0 S2 hLINGO中的算术运算符有以下5种:1 B3 Q, ~7 t' Q/ I
+(加法)
! I. K; K" I8 ^4 s$ L1 v-(减法或负号)* W9 T# z5 O7 G: B, {1 t3 D6 K
*(乘法)( `& {9 C4 l8 z' }3 T! l8 O3 a4 C. Q' {
/(除法)
' {3 c5 G( ^6 ^: E! W' r2 a. A^ (求幂) 关系运算符:表示“数与数之间”的大小关系。 P! }% T, s, c
LINGO中关系运算符有3种:
; T; u1 ^& e0 G3 d) L" s< (即<=,小于等于)+ K% b1 o/ _- B* g) J
= (等于)3 A9 ~, y3 E; P1 |# \" W
> (即>=,大于等于) 简单程序编写求解如下问题:
* z# j4 V. m! E6 z C $ E; N2 z1 o D C
编写程序: ![]()
T! c0 U3 u0 {6 ~% L# b3 _点击求解按钮: $ t+ x- w4 o6 i, _
分析结果: ![]()
/ K/ @3 [6 r, N& Z! C3 ^- I" x所以当x1 = 0,x2 = 5时,取得目标函数的最优值15。 高级操作下面详细介绍Lingo的用法。 基本语法在LINGO语句中通常以MODEL开始,END结束(MODEL和END行也可以删除),目标函数表达式前需要加“MAX=”或“MIN=”. 在写LINGO模型中,注意: - LINGO模型已假设各个决策变量非负. 若变量无非负约束或有上下界,则可以考虑用@free、@sub、@slb或@bnd来定义.
- 变量名不能超过32个字符,且必须以字母(A-Z)开头,其后可以是字母、数字(0-9)和下划线(_)的任意组合.
- 变量名不区分大小写.
- 在约束中“>=”与“>”等同,“<=”与“<”等同.
- 在目标函数或约束条件中需要以“;”结束.
- 标点符号等要在英文状态下输入.
- “!”为注释符号,其后为注释内容,注释以“;”结束.
- 逻辑运算主要包括:#EQ#(等于),#NE#(不等于),#GE#(大于等于),#LT#(小于),#LE#(小于等于).
2 y+ q" D- G" g, T6 k. n 段LINGO中建立的优化模型可以由六个部分组成,或称为六“段”。 - 集合段:用于定义数组型性变量SETS: ……ENDSETS
- 数据段:用于变量赋值与数据传递DATA: ……ENDDATA
- 目标与约束段:用于列出目标与约束唯一一个没有段的开始和结束标记
- 计算段:用于数据初始整理计算CALC: ……ENDCALC
- 初始段:用于变量赋初值迭代寻优INIT: ……ENDINIT
- 子模型段:用于表达子模型进行调用@SUBMODEL mymodel:可执行语句(约束+目标)ENDSUBMODEL
- K$ S+ l+ J$ w/ Z
有了这些我们就可以,不必把表达式全都列举出来了,下面这个表达方式:
, k+ F2 F2 a1 S# G& o ( E1 C) Z" v, T4 {1 C' z+ K* r+ r
code: sets:!集合段;s/1..100/:x;!基本集合, 集合名与属性变量;endsets!目标与约束段;@sum(s(i):x(i))<90;!循环求和函数;
& r0 v* m9 p9 {/ g![]()
i1 g* `; y/ f' X% ncode: sets:!集合段;ss/1..10/:b;endsetsdata:! 数据段;b=1 0 1 2 3 5 2 6 1 2;enddata
8 G2 B3 p3 Q/ |$ V& w![]()
8 T+ O: H% w0 ^& {4 K1 w! ucode: sets:!集合段;a/1..100/:x;b/1..200/:y;Endsets!目标与约束段;@for(b(j):@gin(y(j)));@for(a(i):@bin(x(i));
) g, ^. v1 v4 S# ~, i2 }5 `派生集合派生集合就是派生出来的集合,看几个例子就懂了。
2 U; r) H$ o$ _0 f$ l& O# A 0 j) M7 @2 r7 v5 P4 W' {: B
code: sets:a/1..100/:;b/1..200/:;C(a,b):x;!派生集合;Endsets!目标与约束段;@sum(c(i,j):x(i,j))=280;2 s- u) f' j }5 e& N. P
![]()
; p7 k3 r% d, l* Ncode: sets:a/1..100/:;b/1..200/:;C(a,b):x;Endsets!目标与约束段;@for(b(j):@sum(a(i):x(i,j))>150.001);!集合元素的循环函数;
: k; ?9 d( J* ^' g# ~1 C% d5 W + G1 _$ T5 w* t/ E+ e
code: sets:a/1..100/:;b/1..200/:y;C(a,b):x;Endsets!目标与约束段;@for(b(j):@gin(y(j)));@for(c(i,j):@bin(x(i,j));
, U( j! s- j' h% E逻辑运算符与过滤条件这个前面提到过,再罗列一次:
6 U; S, _6 l3 e# ALINGO逻辑运算符有9种:
3 q, p8 y7 [- V# J#AND#(与),#OR#(或),#NOT#(非):6 ~! S& j5 {( p7 N9 p/ G
#EQ#(等于),#NE#(不等于),# { O0 S# G& N. }- w& B' {6 }7 k5 V
#GT#(大于),#GE#(大于等于),' u+ i. b* i# E3 f' a: p9 n$ n6 R
#LT#(小于),#LE#(小于等于)7 d) J. k/ F& `" ^3 Z
看下面一个例子:; e! D) Y. X# F" N
![]()
3 V/ K, v1 L5 Z" G8 ?* |- M+ l& Gcode: sets:a/1..20/:;b/1..30/:;C/1..40/:;d(a,b,c):x;Endsets!目标与约束段;@for(a(i):@for(b(j):@sum(c(i,j,k)|k#gt#1#and#k#ne#10:x(i,j,k))=100));!过滤条件;
0 E+ S0 n& I c9 z$ q4 x/ {如果我们表示一个分段函数时,就可以是if函数 @IF(logical_condition, true_result, false_result)- l3 F, E! T9 k4 J
当逻辑表达式logical_condition的结果为真时,返回true_result,否则返回false_result。 ![]()
7 u4 [! K4 F5 E8 o6 A; B( ecode: f=@IF(X#LE#500,4*X,@IF(X#LE#1000,500+3*X,1500+2*X));
+ m( e4 _" v" ^ f掌握上述方法,可以解决掉大部分规划问题,如果还想进一步了解,可以去查阅相关书籍。 实际应用线性规划![]()
$ ~1 m# b7 Y1 j l原运输问题变量更换为: ![]()
4 F% s6 H2 I0 G9 \2 J9 ~建立模型为: ![]()
+ b3 N7 c( `) D0 R9 ]5 P模型进一步转化为: ![]()
" a/ |5 R4 Y' x1 a a# g. {, U程序编写: MODEL:TITLE 调运大米的运输问题程序3;!定义集合段;SETS IANGKU/1..2/:A;!定义粮库的集合;LIANGZHAN/1..3/:B;!定义粮站的集合;YULIANG(LIANGKU,LIANGZHAN):X,C;!定义运量和距离;ENDSETSDATA:!粮库到粮站的距离;C=12 24 830 12 24;!粮库的限量;A=4 8 ;!粮站的限量;B=2 4 5;ENDDATAMIN=@SUM(YULIANG:C*X);!粮库上限的约束;@FOR(LIANGKU(I):@SUM(LIANGZHAN(J):X(I,J))<A(I));!粮站下限的约束;@FOR(LIANGZHAN(J):@SUM(LIANGKU(I):X(I,J))>B(J));END
6 N0 j( q4 M+ k" h3 ^, ]$ {! o运行程序即可得到结果。 非线性规划CUMCM2004C请你参考下面给出的数据(或自己收集资料)建立饮酒后血液中酒精含量的数学模型,并讨论以下问题: - 对大李碰到的情况做出解释;
- 。。。
8 L8 p. q9 o3 }7 o. k, G, ~
参考数据 - 。。。
- 体重约70kg的某人在短时间内喝下2瓶啤酒后,隔一定时间测量他的血液中酒精含量(毫克/百毫升),得到数据如下:
- C: y; O% a! M5 q
![]()
2 i+ \$ b/ ~8 z分析:把人体内酒精的吸收,代谢,排除过程分成两个“室”,胃是第一个室,血液为第二室,酒精先进入胃,然后被吸收进入血液,由循环到达体液内,再通过代谢,分解及排泄,出汗,呼气等方式排除。
# L e3 R1 C0 b4 \- [7 d假设胃里的酒精被吸收进入血液的速度与胃中的酒量x(t)成正比,比例常数为k1,血液中的酒被排除的速度与血液的酒量y(t)成正比,比例系数为k2,G0为短时间内喝入胃的酒精总量,则可以建立微分方程:% V8 s! P% B) K
![]() 求解得:* ?4 k5 c7 J7 O' K: h! {3 s
![]() 变换为:$ q$ K6 c: ]8 ^$ R9 O
![]()
4 n/ L# ~( K& M( V, r3 B9 l因而问题就可以转化为: 2 W4 a9 T$ @5 ]( ^% d
编写程序: MODEL:SETS:BAC/R1..R23/:T,Y;ENDSETSDATA:T=0.25 0.5 0.75 1 1.5 2 2.5 3 3.5 4 4.5 5 6 7 8 9 10 11 12 13 1415 16;Y=30 68 75 82 82 77 68 68 58 51 50 41 38 35 28 25 18 15 12 10 77 4;ENDDATAMIN=@SUM(BAC A1*(@EXP(-A2*T)-@EXP(-A3*T))-Y)^2);END; x, c% T4 H; T6 y! }* a, {& J( } `
运行程序,即可获得结果。 整数规划:对上次最后一个题目,用Lingo进行求解。
' v6 u2 Z2 J5 |( V# R4 ^1 b+ ~ ![]() 编写程序: model:sets:row/1..4/:b;col/1..5/:c1,c2,x;link(row,col):a;endsetsdata:c1=1,1,3,4,2;c2=-8,-2,-3,-1,-2;a=1 1 1 1 11 2 2 1 62 1 6 0 00 0 1 1 5;b=400,800,200,200;enddatamax=@sum(col:c1*x^2+c2*x);@for(row(i):@sum(col(j):a(i,j)*x(j))<b(i));@for(col:@gin(x));@for(col:@bnd(0,x,99));end' D/ ]/ V% c4 g$ l4 n
运行即可求出结果,还是满精确的。
) K4 B6 i, |( P/ c$ O6 c0 N: S% U3 j& n0 c! G
|