(一)在Lingo中使用集合


1.    在Lingo中使用集合

4.1 集合的基本用法和lingo模型的基本要素

Lingo雖然使用方便,但是如果要解決幾萬個,幾十萬個變量的優化問題時,我們總不能一個一個地列出x1,x2,…,x1000來解決,而這樣的問題在實際企業的應用中也是經常遇到的。好在Lingo中設計了集合語言來表示大規模變量的輸入,只需一行文字就可以建立起含有大規模變量的目標函數和成千上萬條約束。而Lingo的早期版本軟件Lindo卻不包含這樣的功能。

現通過下例來對Lingo的集合、屬性概念進行介紹。

例2 SAILCO公司需要決定決定下四個季度的帆船生產量。下四個季度的帆船需求量分別為40條,60條,75條,25條,這些需求必須按時滿足。每個季度正常的生產能力是40條帆船,每條帆船的生產費用為400美元。如果加班生產,每條船的生產費用為450美元。每個季度末,每條船的庫存費用為20美元。假定生產提前期為0,初始庫存為10條船。如何安排生產可使總費用最小?

分析與解:用DEM、RP、OP、INV分別表示需求量,正常生產的產量,加班生產的產量,庫存量。則DEM、RP、OP、INV對每個季度都應有一個對應的值,也就是說他們都應該是一個由4個元素組成的數組,其中DEM已知,而RP,OP,INV未知。現在我們可以寫出該問題的模型:

 

此外還有各變量非負的約束。

記4個季度組成的集合,他們就是DEM、RP、OP、INV等變量的下標集合,對於,都有值與之對應。LINGO正是充分利用這種數組及其下標的關系,引入了“集合”與“屬性”的概念。本例中我們把稱之為集合,DEM、RP、OP、INV稱為集合具有的屬性(即定義在該集合上的屬性)。下圖表示了這種集合與屬性的關系。

 
   

 

 

集合QUARTERS的元素

1

2

3

4

定義在集合QUARTERS上的屬性

DEM

DEM(1)

DEM(2)

DEM(3)

DEM(4)

RP

RP(1)

RP(2)

RP(3)

RP(4)

OP

OP(1)

OP(2)

OP(3)

OP(4)

INV

INV(1)

INV(2)

INV(3)

INV(4)

 

下面我們看看Lingo中具體如何定義集合及其屬性。下面是例2的Lingo代碼:

Model: Sets: QUARTERS/1,2,3,4/:DEM,RP,OP,INV; Endsets Min=@sum(QUARTERS:400*RP+450*OP+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

 

我們總結一下上面代碼的特點:

(1)、模型以“MODEL:”開始,以“END”結束。它們之間由語句組成,可以分成三步分。

(2)、集合定義部分以“SETS:”開始,以“ENDSETS”結束。中間定義了集合和相應屬性。語句“QUARTERS/1,2,3,4/:DEM,RP,OP,INV;”定義了集合QUARTERS,以及該集合的屬性DEM、RP、OP、INV,其結果正是上表里面的16個變量名。可以定義空集合,比如“Empty set/1,2,3,4/;”空集合的用法將在派生集中講述。

(3)、數據輸入部分以“DATA:”開始,以“ENDDATA”結束,語句“DEM=40,60,75,25;”給出了常量DEM的值,即DEM(1)=40,DEM(2)=60,DEM(3)=75,DEM(4)=25. 語句“DEM=40,60,75,25;”也可以寫成語句“DEM=40 60 75 25;”即數據之間可以用逗號或空格分開。

(4)、其他部分,給出了目標函數和約束。其中目標函數(“min=”后面所接的表達式)是用求和函數

“@sum=(集合(下標):關於集合的屬性的表達式)”

的方式定義的,這個函數的功能是對語句冒號“:”后面的表達式,按照“:”前面的集合指定的下標元素進行求和。本例中目標函數也可以寫成   

“Min=@sum(QUARTERS(i):400*RP(i)+450*OP(i)+20*INV(i))”

這里“@sum”相當於求和符號,而“QUARTERS(i)”相當於“”,而由於本例中已默認對所有的QUARTERS的元素求和,所以實例中可以將下標i省略。

約束是用循環函數“@for(集合(下標):關於集合的屬性的約束關系式)”的方式定義的,意思是對於“:”前面的集合的每個元素(下標),冒號“:”后面的約束關系式都要成立。但對於這個約束,實際上I=1時要用到變量,但我們定義屬性變量的時候是從I=1開始的,即是一個常數,為了區別I=1和I=2,3,4,我們要將I=1的約束單獨列出來,而對I=2,3,4的約束我們對集合下標做了的約束,即用了“#GT#1”(這個限制條件與集合之間有一個豎線“|”分開,稱為過濾條件),“I#GT#1”就表示,“#GT#”是lingo中的邏輯表達式。

 

小結一下lingo模型最基本的組成要素:

(1)        集合段:以“SETS:”開始,以“ENDSETS”結束。作用在於定義必要的集合和屬性。注意一個細節,我們可以定義QUARTERS/1,2,3,4/,若QUARTERS有1000個元素,我們也不必將其一一列出,而可以簡寫為QUARTERS/1..1000/.

(2)        目標和約束段:這部分不像其他部分,沒有段的開始和結束的標記。因此是除去其他段以外的所有語句。

(3)        數據段:以“DATA:”開始,以“ENDDATA”結束,作用在於對集合的屬性輸入必要的常數數據,格式為:  屬性=常數列表;常數列表中的常數或以逗號“,”分開,或以空格分開“ ”.

(4)        初始段:以“INIT:”開始,以“ENDINIT”結束。作用在於對集合的屬性定義初值。因為求解算法是迭代算法,所以一個好的初值可以讓程序更快解決。定義初值的格式為: 屬性=常數列表;

(5)        計算段:以“CALC:”開始,以“ENDCALC”結束,作用在於對一些原始數據進行計算處理,這種處理是在輸入數據后,求解模型前進行的。例如,對上面的例子,如果我們希望可以得到全年的總需求和季度平均需求,可以增加這個段:

CALC:

T_DEM=@sum(QUARTERS:DEM);!總需求;

A_DEM=T_DEM/@size(QUARTERS);!平均需求;

ENDCALC

要注意的是計算段中語句是按順序執行的,故上面的兩個語句不能調換。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM