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;

下一篇寫一個數獨的小例子~

推薦閱讀:

TAG:CPLEX | 數學規劃 | 數學建模 |