LINGO的基本使用

Lingo基础

Lingo解方程

  • 每个语句以分号结尾
  • 2x2 * x不能简写为2x2x
  • Lingo默认所有的变量均大于等于0
  • 利用函数@free可以使其定义域为RR
  • Lingo不区分大小写
  • 注释以!开头,以;结尾

线性规划基础

  • 一个线性规划中只含一个目标函数,多目标线性规划需要转化为单目标规划
  • 求目标函数最大值或最小值分别用max=min=
  • 线性规划与非线性规划的本质区别是目标函数是否线性,故不作区分
  • 求解非线性规划非常困难,所以尽量转化为线性规划求解

集合与矩阵工厂

问题场景: 求解:

max Ss.t.{S=aixi,i=1,2,...,5ai=1,i=1,2,...,5i=15xi=5000max\ S\\ s.t.\left\{ \begin{aligned} & S=a_ix_i,& i=1,2,...,5 \\ &a_i=1,& i=1,2,...,5\\ &\sum_{i=1}^5x_i=5000 & \\ \end{aligned} \right.

我们可以枚举,利用如下lingo代码求解:

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

显然这种场景暴力分解太憨批了,所以我们寻求另一种表示方法:lingo中非常重要的集合,或者称之为矩阵工厂

矩阵工厂(一维矩阵)

1
2
3
4
sets:
factory/1..4/: a, b;
plant/1..3/: x, y;
endsets
  • factoryplant都是生产矩阵的工厂
  • factoryplantabxy的名字是随便取的
  • factory生产1*6的矩阵,plant生成1*3的矩阵
  • 生产完矩阵之后,工厂和矩阵之间几乎没有关系
  • sets:endsets用于表示工厂生产流程起止

矩阵的赋值

承接上面代码,增加:

1
2
3
4
5
data:
a = 1, 2, 3, 4, 5, 6;
b = 6.0, 5.0, 4.0, 3.0, 2.0, 1.0;
x = 1;
enddata

运行结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Variable     Value
A( 1) 1.000000
A( 2) 2.000000
A( 3) 3.000000
A( 4) 4.000000
B( 1) 6.000000
B( 2) 5.000000
B( 3) 4.000000
B( 4) 3.000000
X( 1) 1.000000
X( 2) 1.000000
X( 3) 1.000000
Y( 1) 0.000000
Y( 2) 0.000000
Y( 3) 0.000000
  • 不是每个矩阵都要赋初值
  • 要么赋满,要么全都设为一样
  • data:enddata标注起止

循环与求和

上述题目可以用以下代码求解:

1
2
3
4
5
6
7
sets:
f/1..5/: a, x;
endsets
max = s;
@for(f(i): a(i) * x(i) = s);
@for(f(i): a(i) = i);!可用data:a=1,2,3,4,5;enddata
@sum(f(i):x(i)) = 5000;
  • @for()表示循环,先写工厂,表示循环次数
  • @sum()表示求和,先写工厂,表示求和元素
  • 在一维的情况下,可以改写为类似@for(f: a * x = s);

二维矩阵

求解:

min z=i=16j=18cijxijs.t.{j=18xijai,i=1,2,...,6i=16xij=dj,j=1,2,...,8xij0,i=1,2,...,6,j=1,2,...,8 min\ z = \sum_{i=1}^6\sum_{j=1}^8c_{ij}x_{ij}\\ s.t.\left\{ \begin{aligned} &\sum_{j=1}^8x_{ij}\leq a_i, &i=1,2,...,6\\ &\sum_{i=1}^6x_{ij}=d_j, &j=1,2,...,8\\ &x_{ij}\geq0, &i=1,2,...,6,j=1,2,...,8 \end{aligned} \right.

其中:

1
2
3
4
5
6
7
8
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

lingo代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
model:

sets:
row/1..6/: a;
col/1..8/: d;
factory(row, col): 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(row(i):@sum(col(j): c(i,j)*x(i,j)));
min = @sum(factory(i, j): c(i, j)*x(i, j));
@for(row(i): @sum(col(j): x(i, j)) <= a(i));
@for(col(j): @sum(row(i): x(i, j)) = d(j));

end

内置函数

数学函数

函数 作用
@abs(x) 返回xx的绝对值
@sin(x) 返回xx的正弦值,xx采用弧度制
@cos(x) 返回xx的余弦值
@tan(x) 返回xx的正切值
@exp(x) 返回常数eexx次方
@log(x) 返回xx的自然对数
@lgm(x) 返回xxgammagamma函数的自然对数
@sign(x) 如果x<0x<0返回1-1;否则,返回11
@floor(x) 返回xx的整数部分。当x0x\geq0时,返回不超过xx的最大整数;当x<0x<0时,返回不低于xx的最大整数。
@smax(x1,x2,…,xn) 返回x1,x2,...,xnx_1,x_2,...,x_n中的最大值
@smin(x1,x2,…,xn) 返回x1,x2,...,xnx_1,x_2,...,x_n中的最小值

变量界定函数

函数 作用
@bin(x) 限制xx只能取0011
@gin(x) 限制xx只能取整数
@bnd(L, x, U) 限制LxUL\leq x\leq U
@free(x) 取消对变量xx的默认下界为0的限制