zoukankan      html  css  js  c++  java
  • Lingo电子教案

    线性及非线性规划计算软件

    LINGO

    LINGO是一个简便的线性规划与非线性规划计算程序,下面用一个例子来说明LINGO的基本概念,启动LINGO后,在命令窗口中输入:

            MAX = * + * ;

            X+Y<= 100;

    这就是一个最简单的线性规划,输入后,按求解键,LINGO就会给出计算结果。其中结果用求解窗口的形式给出,具体参见LINGO的帮助文件给出的详细说明。此处,2X+3Y称为目标函数,本例中求最大值。X+Y<=100为约束条件。而X、Y为变量。请注意,LINGO中的每一行都以分号结束。如果有多个约束条件,就从上面的第三行一直往下写。与LINDO一样,LINGO中<与<=均代表<=,>与>=也均代表>=。LINGO中的注解命令也是符号!,若一个命令或语句一行写不下,可以分多行写,但是,最后结束命令时,一定别忘了打个分号“;”,一行内也可写多个命令,只要每个用分号分开即可,也就是说,分号是LINGO的分隔符。LINGO的命令从来不区分大小写,当你在LINGO中定义变量时,每个变量都要以26个字母开始,后面可跟数字或者下划线,最多可以32个字符长。下面是2个例子。

    下面是一个最简单的非线性规划,它实质上是求(x-y)^2+(z-2)^2+4 的最小值。在LINGO中输入下式后,按求解图标,看一看LINGO会给出什么结果。

                MIN=x^2-2*x*y+y^2+z^2-4*z+8; x>=0; y>=0; z>=0;

    用LINGO求解规划问题,那真是方便极了,我们最后举一个例子。

    例2  下面目标函数的原型是(x1+2*x2+3*x3+4*x4+...+8*x8+9*x9)^2

    在LINGO中输入下列命令:

    MIN=

    x1^2+4*x1*x2+4*x2^2+6*x1*x3+12*x2*x3+9*x3^2+8*x1*x4+16*x2*x4+

    24*x3*x4+16*x4^2+10*x1*x5+20*x2*x5+30*x3*x5+40*x4*x5+25*x5^2+

    12*x1*x6+24*x2*x6+36*x3*x6+48*x4*x6+60*x5*x6+36*x6^2+14*x1*x7+

    28*x2*x7+42*x3*x7+56*x4*x7+70*x5*x7+84*x6*x7+49*x7^2+16*x1*x8+

    32*x2*x8+48*x3*x8+64*x4*x8+80*x5*x8+96*x6*x8+112*x7*x8+64*x8^2+

    18*x1*x9+36*x2*x9+54*x3*x9+72*x4*x9+90*x5*x9+108*x6*x9+126*x7*x9+

    144*x8*x9+81*x9^2;

    3*x3+4*x4>=1; 5*x5+6*x6+7*x7>=2;  8*x8+9*x9>=3;   

    LINGO最后给出的结果正好是我们所期望的值:36。

    请注意,与MathematicaMathlab同在一张光盘上的LINGO4是学生版,即是Student Edition,它的限定条件最多只能有4个,5个或5个以上就算不了,但这也能解决一些问题。实际计算时,请找我安装一个LINGO5的DEMO版,它最多允许计算150个限制条件,300个变量。我们下面的说明,版本4与版本5是一样的。

    下面是LINGO5的解密过程,也就是在LINGO5中去掉变量个数限制及限定条件个数限制的方法:

    找到c:lingo5Lingsolv.dll, 其文件大小是:2,108,416, 然后用二进编辑软件如UEDIT装入此文件.

       查找字符串: 00 8b 55 fc 89 02 (只有一处)

       将它替换为: 00 8b 55 fc 90 90

    再找到:

       查找字符串: a1 88 bd 20 60 (2处要改动)

       将它替换为: b8 05 00 00 00

    最后存盘,然后以demo方式进入LINGO5即可.

    在LINGO中,输入限制条件时,如果限制条件很多,那么如果某个限制条件出错,LINGO给出的错误信息是一个行号,告诉你某行出现错误,但如果你在限制条件前面加上用方括号括起来的某个字符串,参见LINGO目录下的SAMPLEBOX程序,那么此时限制条件出错,LINGO给出的错误信息会一目了然,而且LINGO最后给出的分析结果你也会看得清清楚楚,不过这个字符串应该符合变量的定义规则,建议你用这种方法输入限制条件。通过以上介绍, 就完全可以计算了, 下面我们介绍LINGO的语法.

    ◆ 算术运算符: +, -, *, /, ^, 用括号括起来的式子优先级最高.

    ◆ 逻辑运算符: #NOT#, #EQ#, #NE#, #GT#, #GE#, #LT#, #LE#, #AND#, #OR#.这与FORTRAN一致, 主要用在:@MIN,@MAX,@SUM,@FOR.

    ◆ 关系运算符: =, <=, >=. 请注意,LINGO中没有严格的><, 如果你真要用到的话,比如A<B, 请将它转化为A+e<B, 其中e是一个近似于零的数.

    ◆ 数学函数: @ABS(X), @COS(X), @EXP(X), @FLOOR(X)(返回X的整数部分,X>0,它返回小于X的最大整数,X<0,它返回大于X的最大整数), @LGM(X)[它是(X-1)的阶乘取自然对数,LN((X-1)!))], @LOG(X)(自然对数), @SIGN(X)(符号函数), @SIN(X), @SMAX(X1,X2,...,XN)(N个数的最大值), @SMIN(X1,X2,...,XN), @TAN(X)(正切函数).

    ◆ 概率函数: 参见LINGO 5.0 USSER’S MANUAL->LINGO’S OPERATORS AND FUNCTIONS->PROBABILITY FUNCTIONS.

    ◆ 变量域函数: 如果不用下面的函数明确修改变量的取值范围,LINGO认为每个变量都是非负实数, 你可用下面的命令修改LINGO的默认值. @BIN(var)限制变量VAR为一个二进制数,VAR取值为01, @BND(A,var,B)限制变量VAR在区间[A,B], @FREE(var)取消变量VAR是非负数的限制,即它可以是负数, @GIN(var)限制变量VAR为一个整数.

    以上是对LINGO所作的最简单的介绍, LINGO中即提供了一个详细的帮助文件, 这可在LINGO中的HELP菜单得到, 同时它也提供了几十个演示程序, 这可以在LINGO中打开FILE菜单的OPEN选项, 然后选取LINGO目录中的SAMPLES子目录, 这个子目录中都是LINGO的例子, OPEN装入后即可求解. 下面是LINGOSAMPLE目录下的演示程序BOX.LG4.

    ---------------------------------------------------------

    ! 程序名: BOX.LG4;

    ! !是对程序的注解;

    ! 每一个规划都以”MODEL:”开始, 又以”END”结束, 也可以省略此结构;

    MODEL:

    ! 下面表示求2*(.05*(d*w+d*h)+.1*w*h)的最小值,LINGO中的命令都以分号结束;

    ! 用方括号”[]”括起来的字符串如[COST]对实际计算没有什么用处, 但它会使LINGO;

    ! 输出结果一目了然, 具体请看看输出结果, 你就知道这些方括号的用处了;

    [COST] min = 2*( .05*(d*w + d*h) +.1*w*h);

    ! 以下都是约束条件;

       [SURFACE]  2*(h*d + h*w + d*w) >= 888;

       [VOLUME]   h*d*w >= 1512;

       [NOTNARRO] h/w <= .718;

       [NOTHIGH]  h/w >= .518;

       [FOOTPRNT] d*w <= 252;

    END

    在按下求解键后,LINGO输出计算结果为(其中汉字是我加入的,使你能看明白):

    ! 总共6,          3个变量,            整数变量没有

     Rows=      6      Vars=      3  No. integer vars=      0

    ! 非线性行数 6行        非线性变量  3个         非线性限制条件  5

     Nonlinear rows=6    Nonlinear vars=3     Nonlinear constraints=5

     Nonzeros=     20 Constraint nonz=    12 Density=0.833

     No. < :   2 No. =:   0 No. > :   3, Obj=MIN Single cols=    0

    ! 进行到第9次求出解来, 其解为50.96508

     Local optimal solution found at step: 9

    Objectiv value:                            50.96508

    ! 以下是具体数值

                 Variable           Value        Reduced Cost

                        D        23.03096           0.0000000

                        W        9.562196           0.0000000

                        H        6.865657           0.0000000

    ! 下面是约束条件的误差限

                      Row    Slack or Surplus      Dual Price

                    COST        50.96508            1.000000

                SURFACE      -0.1247204E-05      -0.2342588E-01

                   VOLUME      -0.1937612E-05      -0.1329933E-01

                 NOTNARRO       0.1185074E-10        2.298546

                  NOTHIGH       0.2000000           0.0000000

                 FOOTPRNT        31.77343           0.0000000

    -----------------------------------------------------------

    上面计算得出, 在最小值处D=23.03096, W=9.562196, H=6.865657, 下面我们将D限制在1.510.5之间, 取消W是非负值的限制, H取一个整数值, 则改成如下:

    !程序名: BOX.LG4, 已经改动

    MODEL:

    [COST] min = 2*( .05*(d*w + d*h) +.1*w*h);

     @BND(1.5,d,10.5); @FREE(W); @GIN(H);

    [SURFACE]  2*(h*d + h*w + d*w) >= 888;

     [VOLUME]   h*d*w >= 1512;

    [NOTNARRO] h/w <= .718;

     [NOTHIGH]  h/w >= .518;

    [FOOTPRNT] d*w <= 252;

    END

    其实, @BND(1.5,d,10.5)可以在限制条件中, D>=1.5D<=10.5来代替, @FREE(W) @GIN(H)是不能用别的来代替的, @GIN()可用于求整数规划. 将此程序运行一下, 看看会有什么结果?

    --------------------------------------------------------------

    下面我们再提出一个问题: 如果目标函数在不同的区域中, 取不同的值, 那么, 怎么计算, 你可能注意到, 这里的关键是目标函数的表达方式, 可以用LINGO中的逻辑运算符: #NOT#, #EQ#, #NE#, #GT#, #GE#, #LT#, #LE#, #AND#, #OR#. 这些运算符, 当条件满足时, 返回数值1, 否则返回数值0, 比如对(D #LT# 1), D<1, 其值为1, 否则为0, 因此, 如果将BOX.LG4的目标函数改一下, 改成当D<1,W<2,H<3, 还是原来的那个函数, 而当D,H,W取其它值时, 目标函数变成3*(D+W+H), 则目标函数就变成如下形式:

    MODEL:

     [COST] min = ((d #LT# 1) #AND# (W #LT# 2) #AND# (H #LT# 3))*2*( .05*(d*w + d*h) +.1*w*h) + #NOT#((d #LT# 1) #AND# (W #LT# 2) #AND# (H #LT# 3))*3*(W+D+H);

     [SURFACE]  2*(h*d + h*w + d*w) >= 888;

     [VOLUME]   h*d*w >= 1512;

     [NOTNARRO] h/w <= .718;

     [NOTHIGH]  h/w >= .518;

     [FOOTPRNT] d*w <= 252;

    END

    当然了, 限定条件也可以按一面的方式进行修改. 下面是修改后的运行结果.

    Local optimal solution found at step:             14

    Objective value:                            109.9803

                 Variable           Value        Reduced Cost

                        D        12.43758           0.1774019E-08

                        W        14.09926           0.0000000

                        H        10.12327           0.0000000

                      Row    Slack or Surplus      Dual Price

                      COST        109.9803            1.000000

                      SURFACE       0.1136868E-12      -0.6192584E-01

                      VOLUME        263.2218           0.0000000

                      NOTNARRO       0.0000000            4.041292

                      NOTHIGH       0.2000000           0.0000000

                      FOOTPRNT        76.63941           0.0000000

    可能你觉得, 目标函数的这种写法太复杂, 都几乎看不清是怎么回事了, 那么, 我们引入2个变量, 你就一目了然了.

    MODEL:

    A=((d #LT# 1) #AND# (W #LT# 2) #AND# (H #LT# 3));

    B= #NOT#((d #LT# 1) #AND# (W #LT# 2) #AND# (H #LT# 3));

     [COST] min = A*2*( .05*(d*w + d*h) +.1*w*h) + B*3*(W+D+H);

     [SURFACE]  2*(h*d + h*w + d*w) >= 888;

     [VOLUME]   h*d*w >= 1512;

     [NOTNARRO] h/w <= .718;

     [NOTHIGH]  h/w >= .518;

     [FOOTPRNT] d*w <= 252;

    END

    这次的运算结果与上面的一样,只不过LINGO还会给出AB的值.

    ------------------------------------------------------------

    LINGO中有一个语句DATA, 可以利用它来输入数值数据. 请看对BOX.LG4的修改

    MODEL:

    DATA:    ! 此语句必须以”DATA:”开始, ”ENDDATA”结束;

    const1 = 1512; const2 = 0.1;   ! 这是定义2个常量;

    input1 = ?;    ! 程序运行到此处时,会弹出一个对话框,要求你输入input1的值;

    input2 = ?;    ! 输入input2的值;

    ! 也可写成     input1 , input2=?, ?; 

    ENDDATA

     [COST] min = input1*( .05*(d*w + d*h) + const2*w*h);

     [SURFACE]  2*(h*d + h*w + d*w) >= input2;

     [VOLUME]   h*d*w >= const1;

     [NOTNARRO] h/w <= .718;

     [NOTHIGH]  h/w >= .518;

     [FOOTPRNT] d*w <= 252;

    END

    再看看下面的函数, y=4x2-x4-3, 其函数图象为:

    其最大值点为为x=, 下面是运用LINGO求解的程序:

    model:

    [MAX] max=4*x^2-x^4-3;

    @free(x);

    init:

      x=2;

    endinit

    end

    其中, “init: ... endinit”命令是给变量设一个初值, 不同的初值不仅会影响求解的精度, 而且对某些问题, 有可能会给出不同的结果, 例如, 对此问题, 初值x=2时将会得到最大值点为1.414213, 取初值x=-2, 会得到-1.414213, 但请注意, @free(x)不能忘了写, 它表示取消x非负值的约定, 否则只能得到1.414213.

    有了以上的说明,你就可用LINGO进行简单规划问题的求解了, 但是, 如果你还想用到LINGO中更为复杂的功能, 求解更为复杂的规划问题, 就得了解LINGO的语法. 下面是LINGO的语法说明:

    SET命令: SETLINGO中的一个最基本的命令, 使用它, 你可以将相似的限制条件归结到一起, 将一个很长的表达式用更为简单的方式表达出来. SET中的每个成员可能有一个或多个属性, SET命令与其它计算机语言中对变量的定义是一样的. 在一个求解模型中, 可以有SET命令, 可以没有SET命令, 也可以有多个SET命令, 它的定义如下:

               SET:

               setname [/ member_list /] [: attribute_list];

               ......

               ENDSET

    SET在模型中的位置要满足: 当求解模型用到SET中的成员(即变量), 它一定被定义. 你可以将上面的SETNAME理解成模型中的一个变量, 如果有MEMBER_LIST, 则表示该变量是一个数组, MEMBER_LIST为该数组的取值范围, 而最后面的ATTRIBUTE_LIST(属性)就是变量的实际值, 此值的具体大小一般在DATA中定义. 其中, 方括号中的内容都是可选的. 请看下面的例子.

                   SETS:

                     PRODUCT / A B/;

                     MACHINE / M N/;

                     WEEK / 1..10/;

                     ALLOWED( PRODUCT, MACHINE, WEEK);

                     X / / : X_RANGE;

                     Y /1  2  3  4  5  6/: Y_RANGE;    

                   ENDSETS

    变量PRODUCT是数组,取值于PRODUCT(A)PRODUCT(B), WEEK也是数组,取值于WEEK(1)WEEK(10), ALLOWED是由上面的3个数组变量定义的, 它实际上是一个3维数组. X则是一个变量, 它的值取自于X_RANGE. Y是一个数组即Y(1)Y(6), 它有值Y_RANGE.

    SET中所出现的变量的属性值由DATA语句来设置.

                    SETS:

                      SET1 /A, B, C/: X, Y;

                    ENDSETS

                    DATA:

                      X = 1 2 3;

                      Y = 4 5 6;

                    ENDDATA

    实际上,上面的说法有些地方是不确切的,这是因为LINGO中的数组与我们通常所提及的数组还是有点不一样。下面我编了一个演示程序,它不能计算优化问题,它和我们所通常看到的按顺序执行的计算机程序是一样的,这个程序演示了数组、FOR循环、SUM命令的使用方法,对于其它的命令,可以参考此程序,其中,以“!”开始的行是注释行。

       如果你想在LINGO中执行此程序,不用重新输入,只要用鼠标从都是“!”的行的下一行开始,一直选中到本文件的结束,然后将这段COPYLINGO中即可。另外,这段程序在光盘上的LINGO目录下,文件名是DEMO.LG4,你可以装入此程序,直接在LINGO中运行。

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    !SETSENDSET定义数组;

    sets:

    !定义数组a,其引用值为value1(1),value1(2),......,value1(5);

    !FOR,SUM等命令中的引用名称为a(1),a(2),......,a(6) ;

    a/1..5/:value1;

    !定义数组b,其引用值为value2(1),value2(2),......,value2(6);

    !FOR,SUM等命令中的引用名称为b(1),b(2),......,b(6) ;

    b/1..6/:value2;

    !定义数组c,其引用值为:

    !value3(1,1),value3(1,2),......,value3(1,6);

    !value3(2,1),value3(2,2),......,value3(2,6);

    !..............................................................

    !value3(5,1),value3(5,2),......,value3(5,6)

    !FOR,SUM等命令中的引用名称为c(i,j) ;

    c(a,b):value3;

    !定义数组d,维数与c一样;

    d(a,b):value4;

    endsets

    !数组的赋值要用DATAENDDATA命令;

    data:

    !为数组a,b,d赋值;

    !value1(1)=11,value1(2)=22,value1(3)=33,value1(4)=44,value1(5)=55;

    value1=11 22 33 44 55;

    !value2(1)=1,value2(2)=2,value2(3)=3,value2(4)=4,value2(5)=5,value2(6)=6;

    value2=1 2 3 4 5 6;

    !value4(1,1)=1,value4(1,2)=2,value4(1,3)=3,value4(1,4)=4,value4(1,5)=5,value4(1,6)=6;

    !value4(2,1)=7,value4(2,2)=8,value4(2,3)=9,value4(2,4)=10,value4(2,5)=11,value4(2,6)=12;

    !value4(3,1)=13,value4(3,2)=14,value4(3,3)=15,value4(3,4)=16,value4(3,5)=17,value4(3,6)=18;

    !value4(4,1)=19,value4(4,2)=20,value4(4,3)=21,value4(4,4)=22,value4(4,5)=23,value4(4,6)=24;

    !value4(5,1)=25,value4(5,2)=26,value4(5,3)=27,value4(5,4)=28,value4(5,5)=29,value4(5,6)=30;

    value4=    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 26 27 28 29 30;

    enddata

    !下面是一个二重循环,C=A.B+D;

    @for(a(i):

         @for(b(j):

               value3(i,j)=value1(i)*value2(j)+value4(i,j)

              )

         );

    !对数组a求和;

    total_a=@sum(a(i):value1(i));

    !对数组b,去掉前4个元素求和;

    total_b=@sum(b(i)|i #LT# 4:value2(i));

    !求数组d的和;

    total_d=@sum(d(i,j):value4);

    !对数组d,求对角线元素的和;

    total_c=@sum(c(i,j)|i #EQ# j:value4(i,j));

  • 相关阅读:
    SQL Azure (17) SQL Azure V12
    Microsoft Azure News(5) Azure新DV2系列虚拟机上线
    Azure Redis Cache (3) 在Windows 环境下使用Redis Benchmark
    Azure PowerShell (11) 使用自定义虚拟机镜像模板,创建Azure虚拟机并绑定公网IP(VIP)和内网IP(DIP)
    Windows Azure Virtual Machine (31) 迁移Azure虚拟机
    Windows Azure Web Site (16) Azure Web Site HTTPS
    Azure China (12) 域名备案问题
    一分钟快速入门openstack
    管理员必备的Linux系统监控工具
    Keepalived+Nginx实现高可用和双主节点负载均衡
  • 原文地址:https://www.cnblogs.com/ncoheart/p/10698290.html
Copyright © 2011-2022 走看看