Lingo学习笔记.md

Lingo基础学习笔记

1. 普通整数规划

​ LINGO总是根据“MAX=”或“MIN=”寻找目标函数,语句顺序不重要。即可以出现在约束条件之前,也可以出现在约束条件之后。其中max是对目标函数求最大值,min是对目标函数求最小值。举个例子:

Model:
	min = 4*x + 6 * y;
	5*x + 2*y >= 12;
	3*x + 7*y >=13;
	x >= 0;
	y >= 0;
end

—值得注意的是,在lingo中<<=等价

在model中,可以通过调用@gin(x)来限制变量的取值只能是整数;调用@bin(x)来先限制变量的取值只能是0或者是1;调用@bnd(x,variable,y),限制变量variable的取值范围为(x,y);调用@free(x)表示变量的取值范围可以是负无穷到正无穷。

通常不用lingo来解非整数规划,一是因为运行时间太长,二是也只能保证得到一个局部最优解。但是如果给足运行时间的话,也是可以运行成功的。如:

Model:
	min = @sin(x) + 0.5*@abs(x - 9.5);
	x <= 12;
end

Lingo学习笔记.md_第1张图片

得到的结果如下:

Objective value: -0.3800376

Variable Value Reduced Cost
X 10.47198 0.000000

​ Row Slack or Surplus Dual Price
1 -0.3800376 -1.000000
2 1.528024 0.000000

如果我们加入限制,让x的取值只能是整数的话,那么可以表示为:

Model:
	min = @sin(x) + 0.5*@abs(x - 9.5);
	x <= 12;
	@gin(x);
end

得到的结果为:

Objective value: -0.2940211

Variable Value Reduced Cost
X 10.00000 -0.3390710

​ Row Slack or Surplus Dual Price
1 -0.3800376 -1.000000
2 1.528024 0.000000

—这里需要注意的是:@sin(x)是正弦函数,@abs(x)是取绝对值。

2. set集合的使用

​ 一个大型的Lingo模型往往由三个部分组成:1)一个SETS section;2)一个DATA section;3)模型 section。其中SETS用于描述用于解决实际问题的数据结构;DATA部分用于填充数据到数据结构中;模型部分用于写目标函数和约束条件。

​ 什么是SETS,set就是一组相似的对象。如一组产品、卡车或员工等,每一个对象都是一个变量,但是每个对象都可能存在几个不同的属性,如员工具有年龄、工资等多个属性,于是我们传统方式来描述好几个员工的特征的时候,我们需要对每一个员工的属性进行单独说明。但是如果员工的数量高达100,1000个的时候,手动输入每一个属性显然不是什么高效的办法,于是我们使用SETS,就可以统一对这些属性进行描述,然后在DATA中(稍后进行描述)进行赋值,显然,这种办法效率了很多。

​ 一个SETS在lingo中通常是以sets:开头,以endsets结尾。定义一个sets通常如下:

SETS:
setname: attribute_list;
ENDSETS

如:

SETS:
WAREHOUSE: CAPACITY, LOCATION, DOCKS;
ENDSETS

sets与data的使用方法(一):

SETS:
	SET1: X, Y;
ENDSETS

DATA:
	SET1 = M1, M2, M3;
	X = 1 2 3;
	Y = 4 5 6;
ENDDATA

输出结果为:

Variable Value
X( M1) 1.000000
X( M2) 2.000000
X( M3) 3.000000
Y( M1) 4.000000
Y( M2) 5.000000
Y( M3) 6.000000

相当于x,y属于集SET1,SET1有M1,M2,M3三个属性,于是就有x和y的每个属性对应一个值。

set与data的使用方法(二):

SETS:
	SET1: X, Y;
ENDSETS
DATA:
	SET1        X     Y =
		M1   1    4
		M2   2    5
		M3   3    6;
ENDDATA

输出结果也是一致的,只不是上一个先规定set的属性,再同意进行赋值;在本方法中,对set中的每一个成员的每一个属性进行逐个赋值。

set与data的使用方法(三):

SETS:
	SET1/M1, M2, M3/: X, Y;
ENDSETS
DATA:
	X = 1 2 3;
	Y = 4 5 6;
ENDDATA

输出的结果也是一致的,在这个方法中,我们在set里就直接规定了set1中成员的属性即M1,M2,M3,所以在data中的时候只需要直接赋值就好。

这里需要注意的是,在data中赋值的时候,用空格和逗号隔开都是可以的。

3. @sum()函数的使用

​ 求和函数@sum()的主要功能是求一个集sets中的各个属性之和,主要有两种表达形式,如下所示:

sets:
	set1/a,b,c,d,e/ : x;
endsets

data:
	x = 1 2 3 4 5;
	y = 5 4 3 2 1;
enddata

x_sum1 = @sum(set1(j):x(j));  !方式1;
x_sum2 = @sum(set1:x);	    !方式2;
x_sum3=@sum(set1(j):x(j)*y(j));

在方式1中,变量j可以认为是下标,指代集set1中的各个属性,在set1中属性是a,b,c,d,e,于是方式1的意思就是x(a),x(b),x©,x(d),x(e)求和。

方式二就是直接对集合set1中的x的各个属性和。最后结果是一样的。

第三个求和还可以对同一个集合中的x,y对应属性值相乘再求和。

结果如下:

Variable Value

X_SUM1 15.00000
X_SUM2 15.00000
X_SUM3 35.00000
X( A) 1.000000
X( B) 2.000000
X( C) 3.000000
X( D) 4.000000
X( E) 5.000000
Y( A) 5.000000
Y( B) 4.000000
Y( C) 3.000000
Y( D) 2.000000
Y( E) 1.000000

​ 此外,@sum()函数还可以按条件求和,比如只求前3个元素之和。那么可以表示为:

model:
	sets:
		set1/a,b,c,d,e/:x,y;
	endsets

	data:
		x = 1 2 3 4 5;
	enddata
	
	x_sum1 = @sum(set1(j) | j #LE# 3:x(j));  !前三个元素之和;

end

​ 可以看到唯一的区别就是添加了j #LE# 3,意味着j <= 3,在lingo中,还有其他的表示如下所示:

EQ — 等于
NE — 不等于

GT — 大于

GE — 大于等于
LT — 小于

LE — 小于等于

4. @max()和@min()函数

​ 这两个函数是求集合set1中x各个属性的最大值与最小值。如下表示:

model:
	sets:
		set1/a,b,c,d,e/:x;
	endsets

	data:
		x = 1 2 3 4 5;
	enddata
	
	x_max = @max(set1(j):x(j));
	x_min = @min(set1(j):x(j));

end

结果为:

Variable Value
X_MAX 5.000000
X_MIN 1.000000
X( A) 1.000000
X( B) 2.000000
X( C) 3.000000
X( D) 4.000000
X( E) 5.000000

5. @for函数

​ @for()函数用于循环对集中属性进行处理,比如下面的代码:

model:
	sets:
		set1/a,b,c,d,e/:x,y;
	endsets
    data:
        x = 1 2 3 4 5;
    enddata
	@for(set1(j):y(j) > 5);
end

@for()函数的作用就是限制y的每个属性对应的值都应该大于5,即:

y(a) > 5; y(b) > 5; y© > 5; y(d) > 5; y(e) > 5;

6. 如何输入矩阵进行运算?

​ 在建模中,我们通常会遇到矩阵的运算等,那么如何在lingo中加载矩阵呢?首先我们需要在sets中建立一个派生集array,最后在data中进行赋值。比如下面的例子,我在在set中设立了一个派生集array,和一个最后用于记录计算结果的集,然后在data中进行赋值,最后我将这个矩阵每行的数据进行了求和运算。其代码如下:

model:
	sets:
		row;						!;
		col;						!;
		array(row,col) : x;			  !派生矩阵集;
		sum_row/1..4/ : result;		  !用于存储每行和;
	endsets
	
	data:
		row = 1..4;					!设置矩阵的行数为4;
		col = 1..3;					!设置矩阵的列数为3;
		x = 1 2 3					!给矩阵赋值;
		    4 5 6
		    7 8 9
		    10 11 12;
	enddata

	@for(row(i):					!对于每一行;
		result(i) = @sum(col(j) : x(i,j));		!计算每一行的和并将结果放到result中;	
		);
end

其结果如下:

Variable Value
X( 1, 1) 1.000000
X( 1, 2) 2.000000
X( 1, 3) 3.000000
X( 2, 1) 4.000000
X( 2, 2) 5.000000
X( 2, 3) 6.000000
X( 3, 1) 7.000000
X( 3, 2) 8.000000
X( 3, 3) 9.000000
X( 4, 1) 10.00000
X( 4, 2) 11.00000
X( 4, 3) 12.00000
RESULT( 1) 6.000000
RESULT( 2) 15.00000
RESULT( 3) 24.00000
RESULT( 4) 33.00000

你可能感兴趣的:(Lingo)