Lingo 的基本使用
哎,什么都得自学……学校课程欠缺好大……
lingo 的语法
注意除号为 /
表示次方,使用 ^
eg:x^2
lingo 不区分大小写,eg:mmm、Mmm、mMm 都视为同一个变量。(Spss 也不区分哦)
lingo、Matlab 中变量的命名不要使用驼峰式,使用下划线,且字母在首位。
lingo 不读取空格
model end 关键词可以不添加。但是 使用矩阵工厂创建矩阵后,整个程序需用 model:
和 end
包起来。
Lingo 17 有时候会报一些语法错误,但是明明没有错误……
注意:Lingo 中的代码表示的是方程组,这点很重要。不能将计算机语言中的一些默认特性带入 Lingo。比如:Lingo 中不可以 “给同一个变量赋不同的值”。(之所以打双引号是因为 Lingo 中的都是方程,用变量赋值来说,在数学上不准确)
错误实例:
c = 1;
c = 2;
Lingo 会提示异常,c 的结果也不对:
没有被赋初始值的变量,可能默认不是 0,亦有可能是 1.234568。你可以手动覆盖,问题不大。出现这种情况可能是因为内部实现使用了不同的算法。
lingo也可以用来解普通方程
lingo 用于解线性规划
如果是求线性规划问题,目标值会在 Objective value
属性中给出
-
一个线性规划中只含有一个目标函数。(两个以上的多目标线性规划,Lingo无法直接解) 如果建模同学给了我们多个目标函数,直接告诉他,没办法用 Lingo 求解,需要将多目标线性规划转换成 一个目标,这其实是有方法的。
-
求目标函数的最大值或最小值分别用 max=… 或 min=… 来表示
-
!我是注释;
但是 Lingo17 注释遇到分号就会终止注释语句,这一点一定要留意 : 不要在 Lingo 的注释语句中 写 matlab 矩阵格式 的矩阵!。以下代码直接报错
x^2 + y^2 + 2*x = 103; !sdfdsfds; 2*x + y = 12; y > 5;![2, 2; 2 3];
不写 matlab 语法中的矩阵即可
-
线性规划和非线性规划的本质区别是目标函数是否线性,其余一致,故不需要区分。但值得注意的是,非线性规划的求解十分困难,基本得不到全局最优解(可以得到 “满意解” )建议将非线性问题转化为线性问题来求解。
-
如果一个线性代数问题有多个解,则 Lingo 只会给其中的一种。
矩阵工厂
矩阵工厂就是集合的意思, 用来生产一维矩阵。
使用 A(i)
拿到一维矩阵 A 的 第 i 个元素。
sets:
factory/1..6/:a,b;
plant/1..3/:x,y;
endsets
-
factory 与 plant 都是矩阵工厂,但是是两家不同的工厂。
-
factory 工厂后面的 /1…6/ 说明它专门生产 1*6 矩阵
factory 工厂最后面出现的 a 和 b,都是 1*6 的矩阵
-
plant 工厂后面的 /1…3/ 表示 它专门生产 1*3 矩阵
-
plang、factory 工厂的名称随便起,无所谓。矩阵变量名也是如此
-
本质上只定义了四个行矩阵的大小,矩阵工厂只是中介。
-
生产完矩阵后,工厂和矩阵之间将脱开联系。
-
Lingo 不是一行行地读代码的。所以我们使用
sets:
和endsets
表示矩阵工厂生产流程的起止。
矩阵的赋值
data:
与 enddata
代码块一定要写在 sets:
和 endsets
之后
-
不是所有矩阵都要被赋值,有些矩阵正是我们要求解的变量(如 解向量 x)。
-
Lingo 矩阵赋值时,你就老实写数字,不要写 一个算式,不要打算让 Lingo 帮你先求解再给矩阵赋值:
-
for 循环
当一个数学式子需要手写好几个代码行的时候就可以使用for循环代替
这个式子,手写需要 5 行。
使用 for 循环表示如下:
sets:
col_1/1..5/:a,x;
endsets
data:
a = 1 2 3 4 5;
enddata
max S;
@for( col_1(i): a(i)*x(i) = s);
!for( col_1 : a*x = s) 这样也行;
- for 循环,执行整行语句,因为 S = ai * xi , i = 1, 2, …, 5 相当于 5 个约束条件
- for 循环内部,先写工厂,以告诉 for 循环几次,之后再上接约束条件。
- for 循环中的 i 可以替换成其他变量,随意。
- 这个 for 循环中 i 甚至可以省略,这是因为不会造成歧义。这是特殊情况。二维工厂出现后必须要带 i。
sum
暴力Lingo:
sum Lingo:
for 与 sum 出现的标志
- 约束条件后面有 i = 1 , 2 , . . . , n i = 1, 2, ...,n i=1,2,...,n ,一定在最外层 套上 for。
- 约束条件前面是 ∑ i = 1 n X i \sum_{i=1}^{n}X~i~ ∑i=1nX i 一定要在外层 加上 sum。
工厂合并
工厂合并 : 生产二维矩阵
既然是合并,那显然,首先必须要有两个生产一维矩阵的工厂
sets:
factory /1..6/ : a;
plant /1..8/ : d;
Matrix(factory, plant) : c,x;
endsets
Matrix 是生产 6*8 二维矩阵的工厂。
二维工厂也可以用于表示 for 循环。例题中会体现
二维工厂的赋值
data:
Matrix = 1 2 3 4 ...balabala... 48; !一共需要64个元素;
enddata
例题
model:
sets:
row/1..6/:ro, a;
col/1..8/:co, d;
Matrix(row, col):x, c;
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( Matrix(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
结果: