2.2.4. 集約・複数の添字¶
コスト定義式:
# 運転コスト/週(目的関数)
problem += costX[0]*x[0] + costX[1]*x[1], '全運転コスト'
は,すべての油田について運転コストの和をとるという意味なので, これを一般的に記述すると,以下のようになります.
\[\sum_i{costX_i \cdot x_i}\]
対応する PySIMPLE の記述は,以下のようになります.:
Sum(costX[i]*x[i], i)
Sum()
は \(\displaystyle \sum\) に対応する関数で,:
Sum(和をとる式, 添字)
の書式を持ちます.
次にノルマ制約についても,Sum() を適用したいと考えますが,旧記述では,:
# 製品ノルマ
problem += 6*x[0] + x[1] >= norma['重油'], '重油ノルマ/週'
problem += 4*x[0] + 6*x[1] >= norma['ガス'], 'ガスノルマ/週'
と各油田の生産量が直接数値で記述されているので,一般化できません. そこで,定式化において定数 \(prodX_{i,j}\) を導入し,制約式を次のように記述します.
\[\begin{split}\begin{array}{ll}
\bf{制約条件} \\ \hline
\sum_{i \in OilField}{prodX_{i,j} \cdot x_i} \ge norma_j, \quad \forall j \in Product
& 製品jのノルマ/週の制約式 \\ \hline
\\
\bf{定数} \\ \hline
prodX_{i,j}, \quad i \in OilField, j \in Product & 油田iの製品j生産量/日 \\ \hline
norma_j, \quad j \in Product & 製品jのノルマ/週 \\ \hline
\end{array}\end{split}\]
対応する PySIMPLE の記述は,以下のようになります.:
# 油田 i の製品 j 生産量/日
prodXvalue = {(0,'重油'): 6, (0,'ガス'): 4,
(1,'重油'): 1, (1,'ガス'): 6}
prodX = Parameter(index=(i,j), value=prodXvalue, name='油田の生産量')
# 製品ノルマ
problem += Sum(prodX[i,j]*x[i], i) >= norma[j], '製品ノルマ'
複数の添字に依存する定数を宣言する際には,index=(i,j,..)
と指定します.
複数の添字に対する値は辞書のキーをタプルにします.
Sum()
は指定した添字 i のみの和をとります.
i, j について和をとる場合は,Sum(任意の式, (i,j))
と記述します.
実行結果は以前と同様になります.
ここまでの変更をまとめて,添字,変数,定数,制約条件,目的関数を分類し整理すると, 定式化と PySIMPLE の記述は次のようになります.
\[\begin{split}\begin{array}{ll}
\bf{添字} \\ \hline
i \in OilField = \{ 0, 1 \} & 油田を表す添字 \\ \hline
j \in Product = \{ 重油, ガス \} & 製品を表す添字 \\ \hline
\\
\bf{定数} \\ \hline
costX_i, \quad i \in OilField & 油田iの運転コスト/日 \\ \hline
norma_j, \quad j \in Product & 製品jのノルマ/週 \\ \hline
prodX_{i,j}, \quad i \in OilField, j \in Product & 油田iの製品j生産量/日 \\ \hline
\\
\bf{変数} \\ \hline
x_i, \quad i \in OilField & 油田iの運転日数/週 \\ \hline
\\
\bf{目的関数(最小化)} \\ \hline
\sum_{i \in OilField}{costX_i \cdot x_i} & 運転コスト/週 \\ \hline
\\
\bf{制約条件} \\ \hline
\sum_{i \in OilField}{prodX_{i,j} \cdot x_i} \ge norma_j & 製品jのノルマ/週の制約式 \\ \hline
0 \le x_i \le 5, \forall i \in OilField & 油田iの週あたりの運転日数制約 \\ \hline
\end{array}\end{split}\]
from pysimple import Problem, Element, Parameter, Variable, Sum
problem = Problem(name='油田問題4')
# 油田を表す添字
i = Element(value=[0, 1], name='油田')
# 製品を表す添字
j = Element(value=['重油', 'ガス'], name='製品')
# 油田 i の運転コスト/日
costX = Parameter(index=i, value={0: 180, 1: 160}, name='油田運転コスト')
# 製品 j のノルマ/週
norma = Parameter(index=j, value={'重油': 12, 'ガス': 24}, name='製品ノルマ')
# 油田 i の製品 j 生産量/日
prodXvalue = {(0,'重油'): 6, (0,'ガス'): 4,
(1,'重油'): 1, (1,'ガス'): 6}
prodX = Parameter(index=(i,j), value=prodXvalue, name='油田の生産量')
# 油田 i の運転日数(変数)
x = Variable(lb=0, ub=5, index=i, name='油田の運転日数')
print(costX)
print(norma)
print(prodX)
# 運転コスト/週(目的関数)
problem += Sum(costX[i]*x[i], i), '全運転コスト'
# 製品ノルマ
problem += Sum(prodX[i,j]*x[i], i) >= norma[j], '製品ノルマ'
# 求解
print(problem)
problem.solve()
# 結果出力
print(x.val)
print(problem.objective.val)
このモデルは PySIMPLE のサンプルとして同梱されています. このサンプルを実行するには次のようにします.:
$ python -m pysimple.sample.tutorial oil4