【工程】Pulp-Amply(三)

weixin_33782386發表於2018-04-07

一、Amply

Amply允許您以Python資料結構載入和操作AMPL資料。
Amply只支援AMPL語法的特定子集:
1、設定宣告
2、設定資料語句
3、引數宣告
4、引數資料語句

二、宣告和資料語句

通常,在AMPL中表達的問題包括兩個部分,一個模型部分和一個資料部分。Amply只設計用於解析AMPL資料段中包含的引數和設定語句。然而,為了正確地解析這些語句,可能需要在模型部分中包含的資訊。例如,它不可能從它的資料語句中推斷出一個集合的維數。因此,Amply也支援設定和引數宣告。這些不必放在單獨的部分中,它們只需要在相應的資料語句之前發生。
支援的宣告語法非常有限,並且不包含AMPL程式語言的大多數元素。其目的是將該庫用作載入類似於amplam語法的資料的一種方式。
此外,Amply不對資料語句執行任何驗證。
該文件的目的是指導Amply所支援的語法,而不是一般的AMPL參考手冊。

三、快速入門指南

匯入的類:

from pulp import Amply

一個簡單的集合。

>>> data = Amply("set CITIES := Auckland Wellington Christchurch;")
>>> print data['CITIES']
<SetObject: ['Auckland', 'Wellington', 'Christchurch']>
>>> for c in data['CITIES']: print c
Auckland
Wellington
Christchurch
>>> print data['CITIES'][0]
Auckland
>>> print len(data['CITIES'])
3

資料可以是整數、實數、符號或引用字串:

>>> data = Amply("""
...   set BitsNPieces := 0 3.2 -6e4 Hello "Hello, World!";
... """)
>>> print data.BitsNPieces
<SetObject: [0.0, 3.2000000000000002, -60000.0, 'Hello', 'Hello, World!']>

集合可以包含多維資料,但是我們必須先宣告它們。

>>> data = Amply("""
... set pairs dimen 2;
... set pairs := (1, 2) (2, 3) (3, 4);
... """)
>>> print data.pairs
<SetObject: [(1, 2), (2, 3), (3, 4)]>

集合他們自己可以是多維的:

>>> data = Amply("""
... set CITIES{COUNTRIES};
... set CITIES[Australia] := Adelaide Melbourne Sydney;
... set CITIES[Italy] := Florence Milan Rome;
... """)
>>> print data.CITIES['Australia']
['Adelaide', 'Melbourne', 'Sydney']
>>> print data.CITIES['Italy']
['Florence', 'Milan', 'Rome']

注意,在上面的例子中,集合COUNTRIES實際上並不需要存在。

>>> data = Amply("""
... set SUBURBS{COUNTRIES, CITIES};
... set SUBURBS[Australia, Melbourne] := Docklands 'South Wharf' Kensington;
... """)
>>> print data.SUBURBS['Australia', 'Melbourne']
['Docklands', 'South Wharf', 'Kensington']

可以使用切片指定多維資料

>>> data=Amply("""
... set TRIPLES dimen 3;
... set TRIPLES := (1, 1, *) 2 3 4 (*, 2, *) 6 7 8 9 (*, *, *) (1, 1, 1);
... """)
>>> print data.TRIPLES
<SetObject: [(1, 1, 2), (1, 1, 3), (1, 1, 4), (6, 2, 7), (8, 2, 9), (1, 1, 1)]>

集合資料也可以使用矩陣符號來指定。“+”表示這一對被包含在集合中,而“-”表示一對不在集合中。

>>> data=Amply("""
... set ROUTES dimen 2;
... set ROUTES : A B C D :=
...            E + - - +
...            F + + - -
... ;
... """)
>>> print data.ROUTES
<SetObject: [('E', 'A'), ('E', 'D'), ('F', 'A'), ('F', 'B')]>

矩陣也可以被調換:

>>> data=Amply("""
... set ROUTES dimen 2;
... set ROUTES (tr) : E F :=
...                 A + +
...                 B - +
...                 C - -
...                 D + -
... ;
... """)
>>> print data.ROUTES
<SetObject: [('E', 'A'), ('F', 'A'), ('F', 'B'), ('E', 'D')]>

矩陣只指定2d資料,但是它們可以與切片結合來定義更高維度的資料:

>>> data = Amply("""
... set QUADS dimen 2;
... set QUADS :=
... (1, 1, *, *) : 2 3 4 :=
...              2 + - +
...              3 - + +
... (1, 2, *, *) : 2 3 4 :=
...              2 - + -
...              3 + - -
... ;
... """)
>>> print data.QUADS
<SetObject: [(1, 1, 2, 2), (1, 1, 2, 4), (1, 1, 3, 3), (1, 1, 3, 4), (1, 2, 2, 3), (1, 2, 3, 2)]>

引數也支援:

>>> data = Amply("""
... param T := 30;
... param n := 5;
... """)
>>> print data.T
30
>>> print data.n
5

引數通常在集合上被索引。

>>> data = Amply("""
... param COSTS{PRODUCTS};
... param COSTS :=
...   FISH 8.5
...   CARROTS 2.4
...   POTATOES 1.6
... ;
... """)
>>> print data.COSTS
<ParamObject: {'POTATOES': 1.6000000000000001, 'FISH': 8.5, 'CARROTS': 2.3999999999999999}>
>>> print data.COSTS['FISH']
8.5

引數可以包含預設值

>>> data = Amply("""
... param COSTS{P};
... param COSTS default 2 :=
... F 2
... E 1
... D .
... ;
... """)
>>> print data.COSTS['D']
2.0
>>> data = Amply("""
... param COSTS{P} default 42;
... param COSTS :=
... F 2
... E 1
... ;
... """)
>>> print data.COSTS['DOES NOT EXIST']
42.0

集合的複合索引:

>>> data = Amply("""
... param COSTS{CITIES, PRODUCTS};
... param COSTS :=
...  Auckland FISH 5
...  Auckland CHIPS 3
...  Wellington FISH 4
...  Wellington CHIPS 1
... ;
... """)
>>> print data.COSTS
<ParamObject: {'Wellington': {'FISH': 4.0, 'CHIPS': 1.0}, 'Auckland': {'FISH': 5.0, 'CHIPS': 3.0}}>
>>> print data.COSTS['Wellington']['CHIPS'] # nested dict
1.0
>>> print data.COSTS['Wellington', 'CHIPS'] # tuple as key
1.0
>>> data = Amply("""
... param COSTS{CITIES, PRODUCTS};
... param COSTS :=
...  [Auckland, * ]
...   FISH 5
...   CHIPS 3
...  [Wellington, * ]
...   FISH 4
...   CHIPS 1
... ;
... """)
>>> print data.COSTS
<ParamObject: {'Wellington': {'FISH': 4.0, 'CHIPS': 1.0}, 'Auckland': {'FISH': 5.0, 'CHIPS': 3.0}}>
>>> data = Amply("""
... param COSTS{CITIES, PRODUCTS};
... param COSTS: FISH CHIPS :=
...  Auckland    5    3
...  Wellington  4    1
... ;
... """)
>>> print data.COSTS
<ParamObject: {'Wellington': {'FISH': 4.0, 'CHIPS': 1.0}, 'Auckland': {'FISH': 5.0, 'CHIPS': 3.0}}>
>>> data = Amply("""
... param COSTS{CITIES, PRODUCTS};
... param COSTS (tr): Auckland Wellington :=
...            FISH   5        4
...            CHIPS  3        1
... ;
... """)
>>> print data.COSTS
<ParamObject: {'Wellington': {'FISH': 4.0, 'CHIPS': 1.0}, 'Auckland': {'FISH': 5.0, 'CHIPS': 3.0}}>

高維:

>>> data = Amply("""
... param COSTS{CITIES, PRODUCTS, SIZE};
... param COSTS :=
...  [Auckland, *, *] :   SMALL LARGE :=
...                 FISH  5     9
...                 CHIPS 3     5
...  [Wellington, *, *] : SMALL LARGE :=
...                 FISH  4     7
...                 CHIPS 1     2
... ;
... """)
>>> print data.COSTS
<ParamObject: {'Wellington': {'FISH': {'SMALL': 4.0, 'LARGE': 7.0}, 'CHIPS': {'SMALL': 1.0, 'LARGE': 2.0}}, 'Auckland': {'FISH': {'SMALL': 5.0, 'LARGE': 9.0}, '

三、API

class Amply(string=""):
    load_string(string): Parse string data.
    load_file(file): Parse contents of file or file-like object (has a read() method).
    static from_file(file): Alternate constructor. Create Amply object from contents of file or file-like object.

相關文章