数学建模中的lp造船模型求解

***

1. 数学建模中的lp如何造船使费用最小模型求解以及LINGO的初始用法


先看问题:

例 SAILCO公司需要决定下四个季度的帆船生产量。下四个季度的帆船需求量分别是40条,60条,75条,25条,这些需求必须按时满足。每个季度正常的生产能力是40条帆船,每条船的生产费用为400美元。如果加班生产,每条船的生产费用为450美元。每个季度末,每条船的库存费用为20美元。假定生产提前期为0,初始库存为10条船。如何安排生产可使总费用最小?

使用工具

LINGO11
LINGO初始用法总结

模型建立

目标函数是所有费用的和
数学建模中的lp造船模型求解
约束条件主要有两个:
数学建模中的lp造船模型求解

关于LINGO需要注意

  1. 无数组概念

注:LINGO中没有数组,只能对每个季度分别定义变量,如正常产量就要有RP1,RP2,RP3,RP4 4个变量等。写起来就比较麻烦,尤其是更多(如1000个季度)的时候。
记四个季度组成的集合QUARTERS={1,2,3,4},它们就是上面数组的下标集合,而数组DEM,RP,OP, INV对集合QUARTERS中的每个元素1,2,3,4分别对应于一个值。LINGO正是充分利用了这种数组及其下标的关系,引入了“集合”及其“属性”的概念,把QUARTERS={1,2,3,4}称为集合,把DEM,RP,OP, INV称为该集合的属性(即定义在该集合上的属性)。

数学建模中的lp造船模型求解

及上述所说的有16个变量

数学建模中的lp造船模型求解

LINGO代码

model:
sets:
QUARTERS/1,2,3,4/:DEM,RP,OP,INV;
endsets
[email protected](quarters:400rp+450op+20*inv);
@for(quarters(i):rp(i)<40);
@for (quarters(i)|i#gt#1:
inv(i)=inv(i-1)+rp(i)+op(i)-dem(i)????;
inv(1)=10+rp(1)+op(1)-dem(1);
data:
DEM=40,60,75,25;
enddata
end

运行结果以及分析

数学建模中的lp造船模型求解

显而易见最小值就是78450****最优解如下
数学建模中的lp造船模型求解

如果在进一步进行敏感性分析就是
数学建模中的lp造船模型求解
可是这个题目不需要这么麻烦就只求出最优解就完事了

关于LINGO用法简单做个笔记

  1. 目标函数的定义方式
    @SUM(集合(下标):关于集合的属性的表达式)
    对语句中冒号“:”后面的表达式,按照“:”前面的集合指定的下标(元素)进行求和。
    本例中目标函数也可以等价地写成
    @SUM(QUARTERS(i): 400
    RP(i) +450OP(i) +20INV(i) ),
    “@SUM”相当于求和符号“∑”,
    “QUARTERS(i)”相当于“iQUARTERS”的含义。
    由于本例中目标函数对集合QUARTERS的所有元素(下标) 都要求和,所以可以将下标i省去。*

  2. 约束的定义方式
    循环函数
    @FOR(集合(下标):关于集合的属性的约束关系式)
    对冒号“:”前面的集合的每个元素(下标),冒号“:”后面的约束关系式都要成立

    本例中,每个季度正常的生产能力是40条帆船,这正是语句“@FOR(QUARTERS(I):RP(I)<40);”的含义。
    由于对所有元素(下标I),约束的形式是一样的,所以也可以像上面定义目标函数时一样,将下标i省去,
    这个语句可以简化成“@FOR(QUARTERS:RP<40);” 。

    本例中,对于产品数量的平衡方程,由于下标i=1时的约束关系式与i=2,3,4时有所区别,所以不能省略下标“i”。实际上,i=1时要用到变量INV(0),但定义的属性变量中INV不包含INV(0)(INV(0)=10是一个已知的)。
    为了区别i=1和i=2,3,4,把i=1时的约束关系式单独写出,即“INV(1)=10+RP(1)+OP(1)-DEM(1);” ;
    而对i=2,3,4对应的约束,对下标集合的元素(下标i)增加了一个逻辑关系式“i#GT#1”(这个限制条件与集合之间有一个竖线“|”分开,称为过滤条件)。
    限制条件“i#GT#1”是一个逻辑表达式,意思就是i>1;“#GT#”是逻辑运算符号,意思是“大于(Greater Than的字首字母缩写)” 。

小结:LINGO模型最基本的组成要素

一般来说, LINGO中建立的优化模型可以由五个部分组成,或称为五“段”(SECTION):
(1)集合段(SETS):以“ SETS:” 开始, “ENDSETS”结束,定义必要的集合变量(SET)及其元素(MEMBER,含义类似于数组的下标)和属性(ATTRIBUTE,含义类似于数组)。
如上例中定义了集合quarters(含义是季节),它包含四个元素即四个季节指标(1,2,3,4),每个季节都有需求(DEM)、正常生产量(RP)、加班生产量(OP)、库存量(INV)等属性(相当于数组,数组下标由quarters元素决定)。一旦这样的定义建立起来,如果quarters的数量不是4而是1000,只需扩展其元素为1,2,…,1000,每个季节仍然都有DEM,RP,OP,INV这样的属性(这些量的具体数值如果是常量,则可在数据段输入;如果是未知数,则可在初始段输入初值)。当quarters的数量不是4而是1000时,没有必要把1,2,…,1000全部一个一个列出来,而是可以如下定义quarters集合:“quarters/1…1000/:DEM,RP,OP,INV;” ,“1…1000”的意思就是从1到1000的所有整数。
(2)目标与约束段:目标函数、约束条件等,没有段的开始和结束标记,因此实际上就是除其它四个段(都有明确的段标记)外的LINGO模型。
这里一般要用到LINGO的内部函数,尤其是与集合相关的求和函数@SUM和循环函数@FOR等。
上例中定义的目标函数与quarters的元素数目是 4或 1000并无具体的关系。约束的表示也类似。
(3)数据段(DATA):以 “DATA:” 开始, “ENDDATA”结束,对集合的属性(数组)输入必要的常数数据。
格式为:“attribute(属性) = value_list(常数列表);”
常数列表(value_list)中数据之间可以用逗号“,”分开,也可以用空格分开(回车等价于一个空格),如上面对DEM的赋值也可以写成“DEM=40 60 75 25;”。
在LINGO模型中,如果想在运行时才对参数赋值,可以在数据段使用输入语句。但这仅能用于对单个变量赋值,输入语句格式为:“变量名 = ?;”。例如,上例中如果需要在求解模型时才给出初始库存量(记为A),则可以在模型中数据段写上语句:”A = ?;”
在求解时LINDO系统给出提示界面,等待用户输入变量A的数值。当然,此时的约束语句 INV(1)=10+RP(1)+OP(1)-DEM(1);
也应该改写成 INV(1)=A+RP(1)+OP(1)-DEM(1);
这样,模型就可以计算任意初始库存量(而不仅仅只能计算初始库存量为10)的情况了。

(4)初始段(INIT):以“INIT: ”开始, “ENDINIT”结束,对集合的属性(数组)定义初值(因为求解算法一般是迭代算法,所以用户如果能给出一个比较好的迭代初值,对提高算法的计算效果是有益的)。
如果有一个接近最优解的初值,对LINGO求解模型是有帮助的。定义初值的格式为:
“attribute(属性) = value_list(常数列表);”
这与数据段中的用法是类似的。
(5)计算段(CALC):以“CALC: ”开始, “ENDCALC”结束,对一些原始数据进行计算处理。
在实际问题中,输入的数据通常是原始数据,不一定能在模型中直接使用,可以在这个段对这些原始数据进行一定的“预处理”,得到模型中真正需要的数据。
例如上例,如果希望得到全年的总需求和季度平均需求,可以增加这个段:
CALC:
T_DEM = @SUM(quarters: DEM); !总需求;
A_DEM = T_DEM / @size(quarters); !平均需求;
ENDCALC
在计算段中也可以使用集合函数(其中函数@size(quarters)表示集合quarters的元素个数,这里也就是4)。这时,变量T_DEM的值就是总需求,A_DEM的值就是平均需求(如果需要的话,这两个变量就可以在程序的其它地方作为常数使用了)。
注:上面的两个语句不能交换顺序,因为计算A_DEM必须要用到T_DEM的值。此外,在计算段中只能直接使用赋值语句,而不能包含需要经过解方程或经过求解优化问题以后才能决定的变量。

点个赞再走呗,