LINGO是用來求解線性和非線性優化問題的簡易工具。LINGO內置了一種建立最優化模型的語言,可以簡便地表達大規模問題,利用LINGO高效的求解器可快速求解並分析結果。
1.LINGO快速入門
當你在windows下開始運行LINGO系統時,會得到類似下面的一個窗口:
外層是主框架窗口,包含了所有菜單命令和工具條,其它所有的窗口將被包含在主窗口之下。在主窗口內的標題為LINGO Model – LINGO1的窗口是LINGO的默認模型窗口,建立的模型都都要在該窗口內編碼實現。下面舉兩個例子。
例1.1 如何在LINGO中求解如下的LP問題:
在模型窗口中輸入如下代碼:
min=2*x1+3*x2;
x1+x2>=350;
x1>=100;
2*x1+x2<=600;
然后點擊工具條上的按鈕 即可。
例1.2 使用LINGO軟件計算6個發點8個收點的最小費用運輸問題。產銷單位運價如下表。
使用LINGO軟件,編制程序如下:
model:
!6發點8收點運輸問題;
sets:
warehouses/wh1..wh6/: capacity;
vendors/v1..v8/: demand;
links(warehouses,vendors): cost, volume;
endsets
!目標函數;
min=@sum(links: cost*volume);
!需求約束;
@for(vendors(J):
@sum(warehouses(I): volume(I,J))=demand(J));
!產量約束;
@for(warehouses(I):
@sum(vendors(J): volume(I,J))<=capacity(I));
!這里是數據;
data:
capacity=60 55 51 43 41 52;
demand=35 37 22 32 41 32 43 38;
cost=6 2 6 7 4 2 9 5
4 9 5 3 8 5 8 2
5 2 1 9 7 4 3 3
7 6 7 3 9 2 7 1
2 3 9 5 7 2 6 5
5 5 2 2 8 1 4 3;
enddata
end
然后點擊工具條上的按鈕即可。
2. LINGO中的集
對實際問題建模的時候,總會遇到一群或多群相聯系的對象,比如工廠、消費者群體、交通工具和雇工等等。LINGO允許把這些相聯系的對象聚合成集(sets)。一旦把對象聚合成集,就可以利用集來最大限度的發揮LINGO建模語言的優勢。
2.1為什么使用集?
集是LINGO建模語言的基礎,是程序設計最強有力的基本構件。借助於集,能夠用一個單一的、長的、簡明的復合公式表示一系列相似的約束,從而可以快速方便地表達規模較大的模型。
2.2什么是集?
集是一群相聯系的對象,這些對象也稱為集的成員。一個集可能是一系列產品、卡車或雇員。每個集成員可能有一個或多個與之有關聯的特征,我們把這些特征稱為屬性。屬性值可以預先給定,也可以是未知的,有待於LINGO求解。例如,產品集中的每個產品可以有一個價格屬性;卡車集中的每輛卡車可以有一個牽引力屬性;雇員集中的每位雇員可以有一個薪水屬性,也可以有一個生日屬性等等。
LINGO有兩種類型的集:原始集(primitive set)和派生集(derived set)。
一個原始集是由一些最基本的對象組成的。
一個派生集是用一個或多個其它集來定義的,也就是說,它的成員來自於其它已存在的集。
2.3模型的集部分
集部分是LINGO模型的一個可選部分。在LINGO模型中使用集之前,必須在集部分事先定義。集部分以關鍵字“sets:”開始,以“endsets”結束。一個模型可以沒有集部分,或有一個簡單的集部分,或有多個集部分。一個集部分可以放置於模型的任何地方,但是一個集及其屬性在模型約束中被引用之前必須定義了它們。
2.3.1 定義原始集
為了定義一個原始集,必須詳細聲明:
·集的名字
·可選,集的成員
·可選,集成員的屬性
定義一個原始集,用下面的語法:
setname[/member_list/][:attribute_list];
注意:用“[]”表示該部分內容可選。下同,不再贅述。
Setname是你選擇的來標記集的名字,最好具有較強的可讀性。集名字必須嚴格符合標准命名規則:以拉丁字母或下划線(_)為首字符,其后由拉丁字母(A—Z)、下划線、阿拉伯數字(0,1,…,9)組成的總長度不超過32個字符的字符串,且不區分大小寫。
注意:該命名規則同樣適用於集成員名和屬性名等的命名。
Member_list是集成員列表。如果集成員放在集定義中,那么對它們可采取顯式羅列和隱式羅列兩種方式。如果集成員不放在集定義中,那么可以在隨后的數據部分定義它們。
① 當顯式羅列成員時,必須為每個成員輸入一個不同的名字,中間用空格或逗號擱開,允許混合使用。
例2.1 可以定義一個名為students的原始集,它具有成員John、Jill、Rose和Mike,屬性有sex和age:
sets:
students/John Jill, Rose Mike/: sex, age;
endsets
② 當隱式羅列成員時,不必羅列出每個集成員。可采用如下語法:
setname/member1..memberN/[: attribute_list];
這里的member1是集的第一個成員名,memberN是集的最末一個成員名。LINGO將自動產生中間的所有成員名。LINGO也接受一些特定的首成員名和末成員名,用於創建一些特殊的集。列表如下:
③ 集成員不放在集定義中,而在隨后的數據部分來定義。
例2.2
!集部分;;
sets:
students:sex,age;
endsets
!數據部分;
data:
students,sex,age= John 1 16
Jill 0 14
Rose 0 17
Mike 1 13;
enddata
注意:開頭用感嘆號(!),末尾用分號(;)表示注釋,可跨多行。
在集部分只定義了一個集students,並未指定成員。在數據部分羅列了集成員John、Jill、Rose和Mike,並對屬性sex和age分別給出了值。
集成員無論用何種字符標記,它的索引都是從1開始連續計數。在attribute_ list可以指定一個或多個集成員的屬性,屬性之間必須用逗號隔開。
可以把集、集成員和集屬性同C語言中的結構體作個類比。如下圖:
集 ←→ 結構體
集成員 ←→ 結構體的域
集屬性 ←→ 結構體實例
LINGO內置的建模語言是一種描述性語言,用它可以描述現實世界中的一些問題,然后再借助於LINGO求解器求解。因此,集屬性的值一旦在模型中被確定,就不可能再更改。在LINGO中,只有在初始部分中給出的集屬性值在以后的求解中可更改。這與前面並不矛盾,初始部分是LINGO求解器的需要,並不是描述問題所必須的。
為了定義一個派生集,必須詳細聲明:
·集的名字
·父集的名字
·可選,集成員
·可選,集成員的屬性
可用下面的語法定義一個派生集:
setname(parent_set_list)[/member_list/][:attribute_list];
setname是集的名字。parent_set_list是已定義的集的列表,多個時必須用逗號隔開。如果沒有指定成員列表,那么LINGO會自動創建父集成員的所有組合作為派生集的成員。派生集的父集既可以是原始集,也可以是其它的派生集。
例2.3
sets:
product/A B/;
machine/M N/;
week/1..2/;
allowed(product,machine,week):x;
endsets
LINGO生成了三個父集的所有組合共八組作為allowed集的成員。列表如下:
編號 成員
1 (A,M,1)
2 (A,M,2)
3 (A,N,1)
4 (A,N,2)
5 (B,M,1)
6 (B,M,2)
7 (B,N,1)
8 (B,N,2)