lingo

lingo

  • Lingo文件类型: 文件后缀名为“.lg4”
  • 变量默认大于0,若取负数,要另外说明
  • 每个语句必须以分号“;”结束,每行可以有多个语句,语句可以跨行;
  • 可以给语句加上标号,例如[OBJ] MAX= … ;
  • 以“!”开头,以“;”结束的语句是注释语句;
  • 变量名称必须以字母(A-Z)开头,由字母、数字(0-9)和下划线“_”组成,长度不超过32个字符,不区分大小写
  • 求目标函数的最大值和最小值分别用MAX= …或MIN= …来表示;
  • 直译法
    • 对于简单的模型,可以直接照搬到lingo上,lingo是可以识别的

  • lingo模型以model:开头,end:结尾,对于简单的模型,可以省略

    • Lingo一般是把全部代码放在 model: ……. end 中间(就解决一个问题,省略也行),整个叫做模型段。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      model:
      sets: !定义集合(数据)类型;
      .....
      endsets

      data: !数据的初始化;
      ....
      enddata

      min/max...

      约束条件
      end
  • 集合段:sets: …… endsets ——用来声明和定义数组变量;

  • 数据段:data: …… enddata ——用数据对变量赋值;
    • lingo中数据部分不能使用分式,例如数据部分不能使用1/3
  • 初始化段: 在数据段给变量赋值以后,该变量在整个程序运行阶段都是 常量,而不是决策变量. 如果想对决策变量赋一定初始值,希望该初始值作为寻找最 优解的起始值(变量本身不是常量),可以在程序中增加初始 段
    • 初始化段以语句INIT:开头,以语句ENDINIT结束 如下程序 INIT: X=0.99; Y=0.01; ENDINIT Y<=@LOG(X); X^2+Y^2<=1;
    • 注: 初始化段只对非线性模型起作用,在线性模型中不起任何 作用.
  • LINGO中建立的优化模型可以由六个部分组成,或称为六“段”。

    1
    2
    3
    4
    5
    6
    集合段:用于定义数组型性变量SETS: ……ENDSETS
    数据段:用于变量赋值与数据传递DATA: ……ENDDATA
    目标与约束段:用于列出目标与约束唯一一个没有段的开始和结束标记
    计算段:用于数据初始整理计算CALC: ……ENDCALC
    初始段:用于变量赋初值迭代寻优INIT: ……ENDINIT
    子模型段:用于表达子模型进行调用@SUBMODEL mymodel:可执行语句(约束+目标)ENDSUBMODEL
  • 注意:用[]表示该部分内容可选,[]内部可以是符号加其它

  • lingo中矩阵数据是按行存储的,matlab中数据是按列存储
    • lingo集合是按列赋值

实时数据处理

  • 在某些情况,对于模型中的某些数据并不是定值。譬如模型中有一个通货膨胀率的参数,我们想在2%至6%范围内,对不同的值求解模型,来观察模型的结果对通货膨胀的依赖有多么敏感。我们把这种情况称为实时数据处理(what if analysis)。LINGO有一个特征可方便地做到这件事。
    在本该放数的地方输入一个问号(?)。

    1
    2
    3
    data:
    interest_rate,inflation_rate = .085 ?;
    enddata
  • 每一次求解模型时,LINGO都会提示为参数inflation_rate输入一个值。在WINDOWS操作系统下,将会接收到一个对话框.直接输入一个值再点击OK按钮,LINGO就会把输入的值指定给inflation_rate,然后继续求解模型。

    • 除了参数之外,也可以实时输入集的属性值(定义的变量或常量),但不允许实时输入集成员名(集合成员列表)。

数据部分的未知数值

  • 有时只想为一个集的部分成员的某个属性指定值,而让其余成员的该属性保持未知,以便让LINGO去求出它们的最优值。在数据声明中输入两个相连的逗号表示该位置对应的集成员的属性值未知。两个逗号间可以有空格。

    1
    2
    3
    4
    5
    6
    sets:
    years/1..5/: capacity;
    endsets
    data:
    capacity = ,34,20,,;
    enddata
  • 属性capacity的第2个和第3个值分别为34和20,其余的未知。

集合

  • 集合定义部分(类比c++)
    • 集合是一组相关对象构成的组合
    • 集合分为初始(基本\原始)集合和衍生(派生)集合
    • 集合在使用之前需要预先给出定义,
    • 初始集合的定义三要素:
      • 集合的名称(结构体名称或者为c++类), 集合的元素(也叫做成员列表,相当于c++类中的成员元素或者结构体中的成员), 集合的属性(定义的变量或常量).
  • lingo中集合的属性不要按之前想法理解。。。。
  • 初始集合的定义格式: 集合的名称/集合的元素/:集合的属性;
  • 衍生集合的定义四要素:
    • 集合的名称, 对应的初始集合, 集合的元素(可以省略), 集合的属性(可以没有).
    • 如果集合的元素省略不写, 则默认衍生集合的元素取它所对应初始集合的所有可能组合.
  • 定义一个原始集,用下面的语法:setname[/member_list/][:attribute_list];
    • 在attribute_ list可以指定一个或多个集成员的属性,属性之间必须用逗号隔开。
    • Member_list是集成员列表
  • 可以把集、集成员和集属性同C语言中的结构体作个类比。如下图:

    • 集 ←→ 结构体/类名
    • 集成员 ←→ 结构体的成员/类的成员
    • 集属性 ←→ 定义的结构体/对象
  • 衍生集合

    1
    2
    links(wh, wa):c;  
    //此时的衍生集合c相当于二维矩阵(数组),c++派生函数
  • 数据初始化部分以“DATA:” 开始, 以ENDDATA结束,

    • 这两个语句必须单独成一行;
    • 数据之间的逗号和空格可以替换
  • supplys /1 .. 3/: S;
    • 声明一个长度为 3 的一维数组 supplys, 并用它定义一个这样的一维数组变量 S.
    • 先是数组名(随便起),再是用两个 / 夹在中间的是数组的下标范围,中间 .. 是省略表示法,接着用 : 定义数组变量 S。
  • demands/1..4/: D; 声明一个长度为 4 的一维数组 demands,并定义一个这样的一维数组变量 D。
  • links(supplys, demands): c, x; 声明一个 的二维数组 links,并用它定义两个这样的二维数组变量 c, x.

    • 把两个一维数组放一起,起个名字叫 links,得到二维数组 links,第1个一维数组的维数就是二维数组的行数维度,第2个一维数组的维数就是二维数组的列数维度。
    • 注意:这里 links 不是Lingo关键字,可以随便起名
  • 集部分以关键字sets:开始,以endsets结束。一个模型可以没有集部分,或有一个简单的集部分,或有多个集部分。一个集部分可以放置于模型的任何地方,但是一个集及其属性在模型约束中被引用之前必须定义了它们。

  • 当显式罗列成员时,必须为每个成员输入一个不同的名字,中间用空格或逗号搁开,允许混合使用
  • 当隐式罗列成员时,不必罗列出每个集成员。可采用如下语法:
    setname/member1..memberN/[: attribute_list];
    • 当用隐式罗列方式时,只需在集成员列表中输入首成员和末成员,而中间的成员由LINGO产生。

派生集

  • c++中的派生函数
  • 可用下面的语法定义一个派生集:setname(parent_set_list)[/member_list/][:attribute_list];
    • setname是集的名字。parent_set_list是已定义的集的列表,多个时必须用逗号隔开。如果没有指定成员列表,那么LINGO会自动创建父集成员的所有组合作为派生集的成员。派生集的父集既可以是原始集,也可以是其它的派生集。(类似c++中派生函数)
  • 一个派生集的成员列表有两种方式生成:①显式罗列;②设置成员资格过滤器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    sets:
    !学生集:性别属性sex,1表示男性,0表示女性;年龄属性age. ;
    students/John,Jill,Rose,Mike/:sex,age;
    !男学生和女学生的联系集:友好程度属性friend,[0,1]之间的数。 ;
    linkmf(students,students)|sex(&1) #eq# 1 #and# sex(&2) #eq# 0: friend;
    !男学生和女学生的友好程度大于0.5的集;
    linkmf2(linkmf) | friend(&1,&2) #ge# 0.5 : x;
    endsets
    data:
    sex,age = 1 16
    0 14
    0 17
    0 13;
    friend = 0.3 0.5 0.6;
    enddata
  • 用竖线(|)来标记一个成员资格过滤器的开始。 &1可看作派生集的第1个原始父集的索引,它取遍该原始父集的所有成员;&2可看作派生集的第2 个原始父集的索引,它取遍该原始父集的所有成员;&3&4,……,以此类推。注意如果派生集B的父集是另外的派生集A,那么上面所说的原始父集是集A向前回溯到最终的原始集,其顺序保持不变,并且派生集A的过滤器对派生集B仍然有效。因此,派生集的索引个数是最终原始父集的个数,索引的取值是从原始父集到当前派生集所作限制的总和。

数据段补充



目标函数与目标条件

  • @sum@SUM是LINGO提供的内部函数,其作用是对某个集合的所有成员,求指定表达式的和.
    • @SUM有两个参数:集合名称和表达式,如MIN = @SUM(LINKS(I, J): C(I, J)*X(I, J));
    • 如果表达式中参与运算的属性属于同一个集合,则@SUM的索引可以省略. 即MIN = @SUM(LINKS: C*X);
    • 目标函数是求最小,所以用 “min=”
    • 有 $\sum$,所以需要用到 @sum() 函数, 这是Lingo里的求和函数,首先得告诉它求和的范围, i 从1到3, j 从1到4,这不正好是前面声明的(对应的)二维数组 links 的大小吗,所以就用 links(i, j)来告诉(也只能用声明的数组来告诉),并用 i 表示行索引, j 表数列索引。
    • 然后,冒号,求和里面的表达式。
  • @for是LINGO提供的内部函数,其作用是对某个集合的所有成员分别生成一个约束表达式.有两个参数:集合名和约束表达式
    • @FOR(WH(I): @SUM(VD(J): X(I, J)) <= AI(I) );wh(i)是对集合wh的下标i进行循环,然后@sum内部的vd(j)是对集合vd的下标j进行循环,内外循环就是相当于二重for循环,外循环为i,内循环为j

函数

  • 0-1规划中@bin限制为整数0或1
  • 如果整数规划问题中的所有变量仅限于取0或1两个值,则称此问题为0-1整数规划,简称0-1规划,其变量为0-1变量.





金融函数

  • @fpa(I,n)
  • @fpl(I,n)

运算符

  • LINGO中关系运算符有3种:
    • < (即<=,小于等于)
    • = (等于)
    • >(即>=,大于等于)


  • 用竖线(|)来标记一个成员资格过滤器的开始
  • 这些运算符的优先级由高到低为:
    高 #not#
    #eq# #ne# #gt# #ge# #lt# #le#
    低 #and# #or#
  • 下面给出以上三类操作符的优先级:
    1
    2
    3
    4
    5
    6
    7
    高 #not#   ﹣(取反)
      ^
        ﹡ /
      ﹢﹣
    #eq# #ne# #gt# #ge# #lt# #le#
    #and# #or#
    低 <= = >=

窗口


状态窗口

  • 状态窗口(Solver Status)的详细的介绍如下:
  • Model Class:模型类别显示的模型类别为LP, QP ILP, QP, ILP, IQP, LP, NLP等
  • Model Class 当前模型的类型

    • 可能显示:LP(线性规划),QP(二次规划),ILP(整数线性规划),IQP(整数二次规划),PILP(纯整数线性规划),PIQP(纯整数二次规划),NLP(非线性规划),MIP(混合整数规划),INLP(整数非线性规划),PINLP(纯整数非线性规划).
    • 注 以 I 开头表示 IP(整数规划),以 PI 开头表示 PIP(纯整数规划).
  • State: Possible states are “Global Optimum”表示求出了全局最优解;, “Local Optimum”, “Feasible”可行解, “Infeasible”不可行, “Unbounded”无界, “Interrupted”, and “Undetermined”未确定.

  • Objective: 目标函数的当前值.
  • Infeasibility: 当前约束不满足的总量(不是不满足的约束的个数):实数(即使该值=0,当前解也可能不可行,因为这个量中没有考虑用上下界命令形式给出的约束)
  • Iterations: 迭代次数

报告(Solve Report)窗口

  • Slack or Surplus(小于:松弛,大于:过剩):如果满足约束条件,则该值是左右差的绝对值.
    • 如果不满足约束条件,则该值为负数.
    • 如果该值为0,说明两边相等.

lingo灵敏度分析

  • 灵敏度分析报告(Range Report)
  • lingo只能对线性的模型做灵敏度分析
  • 灵敏性分析是在求解模型时作出的,因此在求解模型时灵敏性分析是激活状态,但是默认是不激活的。为了激活灵敏性分析,运行LINGO|Options…,选择General Solver Tab, 在Dual Computations列表框中,选择Prices and Ranges选项。然后点击Apply按钮。
    • 设置好了之后,你把需要进行灵敏度分析的程序写好了按 Ctrl+r 就行了

------ The Happy Ending ------