不懂先生

Lingo基础用法
Lingo解方程每个方程必须以分号“;”结束请注意:Lingo的所有符号都是英文格式下的符号Lingo的加减乘除分...
扫描右侧二维码阅读全文
04
2021/09

Lingo基础用法

Lingo解方程

  • 每个方程必须以分号“;”结束
  • 请注意:Lingo的所有符号都是英文格式下的符号
  • Lingo的加减乘除分别是:+ - * /

特别注意:

  • 2*x + 1 = 1在Lingo中不可以简写为2x+1=1,乘号不能省略。
  • 注意除号“/”的形状,如同函数y = x的图像,而不是y = -x。

例题:

2x+2y+1=5
3x-5y+5=3
解:

2*x+2*y+1=5;
3*x-5*y+5=3;

易错点:

①不写结尾的分号
②不写乘号

Lingo变量

  • Lingo默认所有变量为大于等于0的数字,因而非负的条件不必多写。
  • 万一遇到一个变量可以小于0,后面会讲到一个函数叫做 @free,来使其定义域为R。
  • m和M等价,Lingo不区分大小写,所以mmm、mMm、MMM被视为同一个变量,猜测使Lingo内部无法识别字母大小写,所以在Lingo的使用过程中,全程使用小写为宜,输出默认都改为大写字母。
mmm = 5;
X =Mmm;
输出:
  X = 5
  MMM = 5
  • 无论是C、Matlab、还是Lingo,变量均由字母、下划线、数字组成,且字母在首位
    正确的命名规范:x , x1 , max_x , _x

错误的命名规范:1x , max-x

注意:下一次课中的矩阵x,其中第一个元素是x(1),不是x1

例题

求解方程组:
x2+y2+2x = 103
2x+y=12
x>0
x>5

解:
x^2+y^2+2*x = 103;
2*x+y=12;
y>5;

注意:

①不要忘记写分号
②不要忘记写乘号
③不要忘了x>0是lingo默认条件,不用写

线性规划基础

  • 一个线性规划中只含一个目标函数。(两个以上是多目标线性规划,Lingo无法直接解,可以将多目标线性规划转换成单目标线性规划再进行求解)
  • 求目标函数的最大值或最小值分别用:max = ...或min = ...来表示
  • 以!开头,以;结束的语句是注释语句
  • 线性规划和非线性规划的本质区别是目标函数是否线性,其余一致,基本的不到全局最优
    例:设两种餐品的生产亮分别为x1和x2,则该问题的数学模型为:

目标函数:max z = 200x1+300x2
约束条件为:
X1<=100
x2<=120
X1+2x2<=160
Xi>=0,i=1,2

解:
max = 200*x1+300*x2;
x1<=100;
x2<=120;
x1+2*x2<=160;

Objective value:  29000.00
 Variable           Value
       X1        100.0000
       X2        30.00000

集合 vs 矩阵工厂

例:已知模型如下:其中ai=i , i=1,2,3,4,5, 请编程求解:
30927-91qfecdq79j.png
【解】:暴力枚举法:
①先分解以下上式:
79731-pxi7gbejct.png
Lingo公式:

a1=1;
a2=2;
a3=3;
a4=4;
a5=5;
max = s;
s=a1*x1;
s=a2*x2;
s=a3*x3;
s=a4*x4;
s=a5*x5;
x1+x2+x3+x4+x5 = 5000;

结果:
Objective value:                              2189.781

 Variable           Value        Reduced Cost
       A1        1.000000            0.000000
       A2        2.000000            0.000000
       A3        3.000000            0.000000
       A4        4.000000            0.000000
       A5        5.000000            0.000000
       S         2189.781            0.000000
       X1        2189.781            0.000000
       X2        1094.891            0.000000
       X3        729.9270            0.000000
       X4        547.4453            0.000000
       X5        437.9562            0.000000

点评:
暴力枚举法较为笨拙,所以我们将使用Lingo中非常重要的集合,亦或称之为---矩阵工厂

矩阵工厂

sets:
factory /1..6/ :a,b;
Plant /1..3/ :x,y;
Endsets

Variable           Value
A( 1)        1.234568
A( 2)        1.234568
A( 3)        1.234568
A( 4)        1.234568
A( 5)        1.234568
A( 6)        1.234568
B( 1)        1.234568
B( 2)        1.234568
B( 3)        1.234568
B( 4)        1.234568
B( 5)        1.234568
B( 6)        1.234568
X( 1)        1.234568
X( 2)        1.234568
X( 3)        1.234568
Y( 1)        1.234568
Y( 2)        1.234568
Y( 3)        1.234568

以上程序对应知识点:

  • factoryhe plant都是制造矩阵的工厂,但是他们是两家不同的工厂。
  • factory工厂后面的 /1..6/ 说明他专门生产1×6的矩阵,factory工厂最后面出现的a和b都是1×6的矩阵
  • plant工厂后面的/1..3/ 说明它专门生产1×3的矩阵,plant工厂最后面出现的x和y,都是 1×3的矩阵。
  • 矩阵工厂的名字factory是随便起的,工厂所生产行矩阵的名字a和b也是随便起的。
  • 以上这四句话,本质是定义了四个行矩阵的带线啊哦,矩阵工厂只是中介。
  • 生产玩矩阵后,工厂和矩阵之间将脱开联系。
  • Lingo不是一行一行读代码的,所以用sets: 和endsets表示矩阵工厂生产流程的起止。

【例1】:
47864-tdrq49nh6jo.png
解:没有特殊联系,只是a和b都是一行六列的矩阵
【例2】

解:
sets:
ctgumcm /1..6/ :a,b;
Endsets

96733-582rauik5dk.png

解:
sets:
ceshi /1..6/ :apple,Apple;
Endsets
不区分大小写 所以都是一个变量
sets:
ceshi /1..6/ :apple,bpple;
Endsets

矩阵的赋值

矩阵工厂不能只生产矩阵,还要给矩阵赋初值才行,例子如下:

sets:
factory /1..6/ :a,b;
plant /1..3/:c,x;
endsets
data:
a=1,2,3,4,5,6;
b=6.0,5.0,4.0,3.0,2.0,1.0;
c= 10,20,30;
Enddata
输出:

                                                    Variable           Value
                                                       A( 1)        1.000000
                                                       A( 2)        2.000000
                                                       A( 3)        3.000000
                                                       A( 4)        4.000000
                                                       A( 5)        5.000000
                                                       A( 6)        6.000000
                                                       B( 1)        6.000000
                                                       B( 2)        5.000000
                                                       B( 3)        4.000000
                                                       B( 4)        3.000000
                                                       B( 5)        2.000000
                                                       B( 6)        1.000000
                                                       C( 1)        10.00000
                                                       C( 2)        20.00000
                                                       C( 3)        30.00000
                                                       X( 1)        1.234568
                                                       X( 2)        1.234568
                                                       X( 3)        1.234568

以上程序对应以下知识点:

① 不是每个矩阵都要赋值,有些矩阵正是我们要求解的变量
② 需要赋值的矩阵必须把矩阵内的元素都赋值,不能给6个元素的矩阵只赋3个数值。
③ Lingo中可以给矩阵赋整数,也可以赋小数。
④ Lingo不是一行一行读代码的,所以用data: 和enddata表示矩阵赋值的起始
⑤ 不能赋值分数和公式

循环和求和

86486-3d742s6c489.png

【for循环】

题中约束条件:s= aixi,i=1,2,3,4,5可以利用for循环一步到位
@for(gc(i):a(i)*x(i)=S);

  1. for循环,括起整行语句,因为s=aixi,i=1,2,3,4,5相当于5个约束条件:
S=a1x1
S=a2x2
S=a3x3
S=a4x4
S=a5x5
  1. for循环内部,先写工厂,gc代表生产1行5列的矩阵,以告诉for循环几次,之后再上接约束条件。
  2. 此处的i可带可不带,甚至可以换成j,k或m等等
  3. 二维矩阵工厂出现后,同时回出现i和j,那是必须带i和j

【sun求和】

@sum(gc(i):x(i))=5000;

  • sum求和,不可以括起完整的约束条件,因为一般的求和结构是这样的:x1+x2+x3+x4+x5=5000
  • sum求和内部,先写工厂,已告诉sum求和几次,之后再上接越苏条件。
  • 此处的i可带可不带。
  • 二维矩阵工厂出现后,同时会出现i和j,那时必须带。

【for和sum出现的标志】

  • 约束条件后有i=1,2,3,4,5,一定在最外层套上for
  • 约束条件前面是88134-cbtvctzq4o.png,一定在中间加上sum。

程序如下:

model:
sets:
gc /1..5/ : a,x;
endsets

data:
a=1,2,3,4,5;
enddata

max =s;
!s = a(1)*x(1);
!s = a(2)*x(2);
!s = a(3)*x(3);
!s = a(4)*x(4);
!s = a(5)*x(5);
!x(1)+x(2)+x(3)+x(4)+x(5)=5000;
@for(gc(i):s = a(i)*x(i));
@sum(gc(i):x(i))=5000; 
end
Ps:使用了矩阵工厂创建矩阵后,程序会变得复杂,整个程序需用model:和end包起来

工厂合并

sets:
factory /1..6/ :a;
plant /1..8/ :b;
Cooperation(factory,plant):c,x;
Cooperation(factory,factory):d;
endsets

其中a是一行六列的矩阵,b是一行八列的矩阵,c和x是六列八行的矩阵,d八行八列
以上程序可以得到以下结论:

  1. Cooperation大工厂是由factory和plant两家小工厂合并而办,可生产6×8的矩阵。
  2. a是1×6的矩阵,b是1×8的矩阵,c和x都是6×8的矩阵。
  3. 如果将Cooperation(factory,plant)中的factory与plant调换位置,则生产8×6的矩阵
  4. 工厂如果合并的名字Cooperation是随便起的,矩阵的名字、c和x也是随便起的

矩阵的赋值

data:
c=6,2,6,7,4,2,5,8,
  4,9,5,3,8,5,8,2
  5,2,1,9,7,4,3,3
  7,6,7,3,9,2,7,1
  2,3,9,5,7,2,6,5
  5,5,2,2,8,1,4,3;
enddata

注意:最后一行才加分号,中间不加,这个是6×8的矩阵需要赋48个值

【例题】

75272-zzi668l0pl7.png

代码如下:

model:
sets:
factory /1..6/ :a;
plant /1..8/ :d;
coo(factory,plant):c,x;
endsets
data:
a=60,55,51,43,41,52;
d=35,37,22,32,41,32,43,38;
c=6,2,6,7,4,2,5,8
  4,9,5,3,8,5,8,2
  5,2,1,9,7,4,3,3
  7,6,7,3,9,2,7,1
  2,3,9,5,7,2,6,5
  5,5,2,2,8,1,4,3;
enddata
min = @sum(coo(i,j):c(i,j)*x(i,j));
!min =@sum(factory(i):@sum(plant(j):c(i,j)*x(i,j)));
@for(factory(i):@sum(plant(j):x(i,j))<=a(i));
@for(plant(j):@sum(factory(i):x(i,j))=d(j));
end

运算符 & 内置函数

1.1算数运算符

67000-hx87ik3hbmi.png

【解】 
x = 2;
y=3*x^10+6/(15-@sqrt(x));
!y=3*x^10+6/(15-x^(1/2));

1.2关系运算符

  • 关系运算符往往用在约束条件中,用来指定约束条件左右两边必须满足的关系。
  • Lingo只有三种关系运算符:“=”,“ >=”,“<=”。没有单独的“<”“>”,若出现,Lingo则 视为省略了“=”号,当作“ >=”,“<=”对待
  • 若想严格表达A大于B,可以用以下方式:
b=10;
e=0.0001;
a-e>b;

1.3逻辑运算符

①运算符

48689-nnc5q3tgq9n.png

②逻辑运算符唯一出现的位置

a)for循环与sum求和
b)if判断中

【例1】
92751-rrtyta57kjj.png
【解】

model:
sets:
factory /1..6/ : a;
endsets
data:
a=6,5,4,3,2,1;
enddata
y = @sum(factory(i)|i#ge#5:a(i));
end

上式中,i#ge#5对sum求和范围进行了限制,当然也可以写为#gt#4
【例2】
84368-5uuzbwrab7b.png
注释:i=1,2,5,6时 a(i)>5
【解】

model:
sets:
factory /1..6/ : a;
endsets
min = @sum(factory:a);!;
@for(factory(i)|i#lt#3 #or# i#ge#5:a(i)>5);
end

【例3】
24403-rhkvjtjnj5n.png
【解】

model:
sets:
fac /1..3/: ;
coo(fac,fac) : a;
endsets
data:
a=1,2,3
  4,5,6
  7,8,9;
enddata
y = @sum(coo(i,j)|i#le#j : a(i,j));
end

Lingo内置函数

2.1 if判断

90583-pxwwjhexunt.png
【解】
①Lingo默认所有变量不为负数,故应先进行定义域自由化
②if函数语法简单

@free(x);
@free(y);
x=-10; !给x一个随机的初值
y = @if(x#ge#0,x+10,x-10);注释:如果x>=0,执行x+10,否则执行x-10

【例2】
65796-go86pczv4rk.png
【解】
①0<=x<=500可以x#ge#0 #and# x#le#500 ,也可以直接x#le#500
②if函数的嵌套功能

x = 1500;
y = @if(x#le#500,4*x,@if(x#gt#1000,1500+2*x,500+3*x));
【提示】

①if函数通常仅仅在分段函数出出现,一般其出现频率,使用次数都很低
②Lingo中的if函数,必须自带一个else

2.2变量定界函数

88275-6iztejejpz7.png

【例】
59096-s6feit1nzu.png
【解】

@free(x);
@free(y);
min = (x+2)^2+(y-2)^2;

81300-evivgok3h5p.png
【解】

@bnd(1,x,3);
max = 2*x;

【注释】第一句可以写为x>1;x<3替代,但是不论从速度还是约束条件数量,都不如用@bnd函数

【例】
52279-cpyd354y1qr.png
【解】

model:
sets:
fac /1..8/:a,b,x;
endsets
data:
a=2,9,3,8,10,6,4,10;
b=1,3,4,3,3,1,5,10;
enddata

max = @sum(fac(i):a(i)*x(i));
@sum(fac(i) : b(i)*x(i)) <= 15;
@for(fac(i) : @bin(x(i)));
end

【例】
00068-hu5cmze1qag.png
【解】

model:
sets:
factory /1..6/:a,x;
plant /1..5/:b;
coo(factory,plant);
endsets
data:
a=2.1,1.0,1.8,1.2,2.0,1.2;
b=6,125,12500,345,5;
c=0.45,20,415,22,0.3
  0.45,28,4065,5,0.35
  0.65,40,850,53,0.6
  0.4,25,75,27,0.2
  0.5,26,76,48,0.4
  0.5,75,235,8,0.6;
enddata
max = @sum(factory:a*x);
@for(plant(j):@sum(factory(i):c(i,j)*x(i))<=b(j));
x(2)<=3;
x(4)<=2;
@for(factory(i)|i#ne#2 #and# i#ne#4 :@bnd(1,x(i),4);
@for(factory:@gin(x));
End

2.3数学函数

98901-ohjvkpjtc5q.png

【例】
46688-jhqy5hyq2w.png
【解】
y = @sin(3.14159)+@log(1024)/@log(2)+@abs(-1)+@exp(0);

2.4集合操作函数

67753-pq1iz5iphmh.png
【举例】

model:
sets:
factory/1..6/:a;
endsets
data:
a=  6,5,4,3,2,1;
enddata
prod = @prod(factory:a);
greater = @max(factory:a);
less = @min(factory:a);
in = @in(factory,5);
size = @size(factory);
end
Last modification:January 18th, 2022 at 04:27 pm

Leave a Comment