1. 程式人生 > >Lingo使用筆記

Lingo使用筆記

Lingo是用於求解線性規劃、非線性規劃、整數規劃的專門軟體。使用Lingo建模語言描述問題後,軟體能自動化為標準形式,並根據問題選擇相應的求解器。

Lingo程式碼每行以分號結尾。變數和關鍵字不區分大小寫。除Calc段和Init段外,程式碼各行的順序隨意。
Lingo中變數不需要定義直接使用。預設變數型別為非負實數。使用

@FREE(x)  !移除非負約束 
@GIN(x)   !新增整數約束
@BND(lower_bound, x, upper_bound)  !上下界約束
@SEMIC( lower_bound, variable, upper_bound)  !上下界或零

Lingo中沒有”陣列”的概念,對應最接近的概念是”Set集合”。
Set是Lingo中的核心概念之一,是描述具有輪轉和對稱性約束的主要手段。
在Lingo中使用sets: …… endsets

關鍵字定義集合段。

定義一維集合

setname [/ member_list /] [: attribute_list];
WAREHOUSES /1..6/: location,price;

定義集合時也可以不指定大小,lingo會根據初始值的維度自動決定


定義二維集合

setname(parent_set_list) [ / member_list /] [: attribute_list];

SETS:
  PRODUCT / A B/;
  MACHINE / M N/;
  WEEK / 1..2/;
  ALLOWED(PRODUCT, MACHINE, WEEK);
ENDSETS

ALLOWED集合是PRODUCT和MACHINE集合的笛卡爾積。
若只需要生成部分集合,可手工指定成員列表

ALLOWED(PRODUCT, MACHINE, WEEK) / A M 1, A N 2, B N 1/;

還可在定義集合時使用條件判斷

HEAVY_DUTY(TRUCKS) | CAPACITY(&1) #GT# 50000:;

其中&1 是集合的索引符。

使用data: …… enddata關鍵字定義資料段,資料段中向集合元素賦值

SETS:
  SET1: X, Y;
ENDSETS
DATA:
  SET1 = A B C;
  X = 1 2 3;
  Y = 4 5 6;
ENDDATA

或者

SETS:
  SET1: X, Y;
ENDSETS
DATA:
SET1 X Y = A 1 4 B 2 5 C 3 6; ENDDATA

也就是說,Lingo中按照列讀入資料。

使用@FOR @SUM @MIN @MAX @PROD批量設定約束,例如

@FOR(NUMBERS(I):
    RECIPROCAL(I) = 1 / VALUE(I)

DEMAND_L3 = @SUM(VENDORS(J) | J #LE# 3: DEMAND(J));

MIN_DEMAND = @MIN(VENDORS(J): DEMAND(J));


綜合運用

MIN = @SUM(DAYS(I): START(I));
@FOR( DAYS(J): 
  @SUM( DAYS(I) | I #LE# 5: 
     START(@WRAP(J - I + 1, 7)))>= REQUIRED(J));

上面這個約束對應“僱員排程問題”。僱員每週工作5天休息2天,商店各日需要的人數不同。故任意一天所需要的人數 REQUIRED(J) 應小於等於過去5天開始工作的僱員總人數 @SUM(DAYS(I) | I #LE# 5: START(@WRAP(J-I+1,7)))

@FOR( NUTS(I): 
@SUM( BRANDS(J): 
    OUNCES(I, J) * PRODUCE(J) / 16) <= SUPPLY(I));

上面這個約束對應生產J種商品所用的I種原料均不超過供應

PAIRS(ANALYSTS, ANALYSTS) | &2 #GT# &1:
   RATING, MATCH;
DATA:
  RATING = 
     9  3  4  2  1  5  6
        1  7  3  5  2  1
           4  4  2  9  2
              1  5  5  2
                 8  7  6
                    2  3
                       4;
ENDDATA

MIN = @SUM(PAIRS(I,J): 
RATING(I,J) * MATCH(I,J));
@FOR(ANALYSTS(I):
    @SUM(PAIRS(J,K) | J #EQ# I #OR# K #EQ# I:
    MATCH(J,K)) = 1);
@FOR(PAIRS(I,J): @BIN(MATCH(I,J)));

配對問題。在建立集合PAIRS的時候使用布林條件,只建立上三角陣。第一個FOR設定一對一配對約束;第二個FOR設定0-1整數變數。

常用條件運算子

#EQ# equal
#NE# not equal
#GE# greater-than-or-equal-to
#LE# less-than-or-equal-to
#GT# greater than
#LT# less than

約束可以命名,以在方便在結果報告和錯誤報告中指代。使用符號[] 放在約束的開頭。

[OBJECTIVE] MIN = X;
@FOR( LINKS( I, J): [DEMAND_ROW]
@SUM( SOURCES( I): SHIP( I, J)) >=
DEMAND( J));