CPLEX學習筆記二 – OPL的數據類型
一. 基本數據類型
OPL中的基本數據類型有:
l 整數 integers
l 浮點數 floats
l 字元串 Strings
(1) 整數
OPL中整數的範圍為,通過int表示定義一個整數。如:
int i = 25;
定義了一個整數i,其值25。
(2) 浮點數
OPL中浮點數的範圍為負無窮大到正無窮大,通過float表示定義一個浮點數,如:
float f = 3.2;
定義了一個浮點數f,其值為3.2。
(3) 字元串
OPL支持字元串的定義。通過string來定義字元串,如:
{string} Tasks = {"masonry","carpentry","plumbing","ceiling","roofing","painting","windows","facade","garden","moving"};
定義了一個字元串的集合Tasks,其中{}用於表示集合(set),後面會介紹。
附:字元串中的轉義字元串:
backspace
tab
newline
f form feed
carriage return
" double quote
\ backslash
ooo octal character ooo
xXX hexadecimal character XX
二. 四種數據結構
在OPL中提供了四種基本的數據結構,可以通過靈活組合這些數據結構,使得寫入數學模型更加便捷。四種數據結構分別為:(翻譯成中文感覺怪怪的就用英文表示啦)
l Range
l Array
l Set
l Tuple
(1) Range
Range表示範圍,OPL中range數據有兩種類型,整數range和浮點數range。例:
整數range :
range Rows = 1..3;
浮點數range:
range float x = 1.0..3.0;
Range一般用兩個點表示,左右數字分別為其上下限,注意range是左右包含的,如1..3表示{1,2,3}三種取值,1.0..3.0表示1.0 ≤ x ≤ 3.0的所有浮點數的取值。至於整數range和浮點數range的區別通過這個例子也很顯而易見,當上下限有一個為浮點數類型時,則表示浮點數range;當上下限均為整數時,則表示整數range。
Range的用法:
整數range有三種用法:
a. 作為一個array的索引
range R = 1...100;int A[R]; // 定義一個有100個整數的數組A,R為A的索引
b. 用作迭代
range R = 1..100;forall (i in R) { //寫一個循環}
c. 用作一個整數變數的取值範圍。
range R = 1..100;dvar int i in R; // 整數變數i的取值為R範圍中的整數
浮點數range的用法則一般是用於定義一個浮點數變數的取值範圍,如:
range float X = 1.0..100.0;dvar float x in X;
(2) Array
Array為數組,可以是一維的也可以是多維的,個人理解是帶索引的一組數,數組中每個索引或每組索引對應一個值。在建模中常用於定義多變數或多維變數。Array用中括弧表示其索引。例:
一維array:
int a[1..4] = [10, 20, 30, 40];
這個語句定義了一個一維數組 a[1..4],它包含了四個整數a[1],...,a[4],值分別為10,20,30,40。也可以這樣寫:
range R = 1..4;int a[R] = [10, 20, 30, 40];
除了可以用range做array的索引外,還可以用set等做array的索引,多種數據結構組合可以玩出不同的花樣~
多維array則有多維索引,例如我們要解一個數獨問題,可將數獨格中所有數字視為一個9*9的array:
int input [1..9][1..9] = …;// 將input設為數獨初始輸入數據,其中空格用0表示
這裡』…』為初始化數據時不定義數據,通過data文件中的數據調用。
(3) Tuple
Tuple是將關係緊密的數據聚合起來的一種表示。定義tuple時用tuple xxx{},在{}中表明要聚合的數據。如:
tuple Point { int x; int y;};Point point[i in 1..3] = <i, i+1>;
先定義了一個tuple名為Point,Point是將x和y兩種數據聚合起來的一個tuple;再定義了一個array名為point,point中的元素為Point類型,即point中元素均為x和y成對的tuple數據;point中有三個元素point[1],point[2],point[3],取值分別為<1,2>,<2,3>,<3,4>。注意tuple的表示和書寫是用尖括弧表示的~
Tuple也支持keys,即在這種聚合的數據類型中可以有一個或多個關鍵詞,進一步通過關鍵詞就可以表示對應的tuple數據。如:
tuple nurse { key string name; int seniority; int qualification; int payRate;}NurseWorkTime[<"Isabelle">]<=20;
用name作為tuple nurse的key,通過這個key就可對應到相應的tuple,來實現對相應元素數值的調用。最後這行即等價於:
NurseWorkTime[<"Isabelle",3,1,16>]<=20;
(4) Set
Set就是集合的意思~ 一般用大括弧{}來表示,大括弧內為該集合中元素的類型/範圍,如:
{int} a = {10, 20, 30};
表示定義一個整數集合a,其元素為:10,20,30。
set中的元素也可以是tuple類型,set可作為array的索引,來看下下面這個例子:
tuple Edge { int orig; int dest;}{Edge} Edges = {<1,2>, <1,4>, <1,5>};int a[Edges] = [10,20,30];
這段代碼同時用了array,set和tuple三種數據類型,set中元素為tuple結構,array的索引為set中的元素。可對應為交通運輸中的問題,有一系列的Origin和Destination,將它們之間的OD關係聚合為Edge(邊);Edges是Edge類型數據的集合,這裡可能表示有通路的OD點對,這裡Edges的元素為<1,2>,<1,4>, <1,5>;對應每一個有通路的OD點對,定義了一個a值,其索引為Edges中的元素,值分別為10,20,30。
以上就是OPL語言中常用的四種數據類型,理解了這四種數據類型,在OPL中就可玩出很多花樣~四種數據類型的組合使用也使得OPL建模變得十分方便,但當然是要建立在很熟悉和活用的基礎上~目前我菜魚的水平還是先多參照示例中的內容,多多理解、學習和練習才好!
三. 決策變數的寫法
決策變數在一個數學模型中是未知的,OPL中用dvar來標識決策變數。如:
dvar int transp[Orig][Dest] in 0..100;
表示定義一組(二維數組)變數transp[Orig][Dest],每個變數的取值範圍均為0-100的整數。
變數的索引也可以是tuple結構的集合,如:
tuple Route { City orig; City dest}{Route} routes = ...:dvar int transp[routes] in 0..100;
通過外部數據給出routes集合的元素,將其作為變數的索引,變數的取值仍為0-100的整數。
也可對不同的變數設置不同的取值範圍,如:
tuple Route { City orig; City dest;}{Route} routes = ...;int capacity[routes] = ...;dvar int transp[r in routes] in0..capacity[r];
通過外部數據capacity給出routes集合中每個元素的容量值,在定義變數時對不同routes中的元素給出對應變數的取值範圍。(用中文表達我自己都快繞暈了)
還可以這樣寫:
float cap[o][d] = ...;dvar float transp[o in Orig][d in Dest] in 0..cap[o][d];
先給出二維數組cap用於表示各OD對之間的capcity,再定義二維變數transp,其取值應滿足不超過對應的capcity。
為了書寫方便,OPL還提供了float+,int+和boolean來分別定義非負變數、非負整數變數和0,1變數。如:
dvar int+ x; // non negative integer decision variabledvar float+ y; // non-negative decision variabledvar boolean z; // boolean decision variable
等同於:
dvar int x in 0..maxint;dvar float y in 0..infinity;dvar int z in 0..1;
下一篇寫一個數獨的小例子~
推薦閱讀: