3.3.11. 範囲演算関数 Sum, Prod

数式における \(\sum\)\(\prod\) に類する機能として,PySIMPLE では範囲演算関数として, Sum 関数と Prod 関数が提供されています. 次の例では,制約式 \(\sum_{i=1}^3 x_i = 10\) を記述しています.:

i = Element(value=[1, 2, 3])
x = Variable(index=i)
Sum(x[i], i) == 10

上の記述を Sum 関数を使わずに書くと次のようになります.:

i = Element(value=[1, 2, 3])
x = Variable(index=i)
x[1] + x[2] + x[3] == 10

次の例では,制約式 \((\prod_{i=1}^3 a_i)x = 20\) を記述しています.:

i = Element(value=[1, 2, 3])
a = Parameter(index=i)
x = Variable()
Prod(a[i], i)*x == 20

上の記述を Prod 関数を使わずに書くと次のようになります.:

i = Element(value=[1, 2, 3])
a = Parameter(index=i)
x = Variable()
a[1]*a[2]*a[3]*x == 20

複数の添字に対して適用する事もできます. 次の例では,制約式 \(\sum_{i=1}^3 \sum_{j=1}^2 a_i b_j y_{ij} = 10\) を記述しています.:

i = Element(value=[1, 2, 3])
j = Element(value=[1, 2])
y = Variable(index=(i,j))
a = Parameter(index=i)
b = Parameter(index=j)
Sum(a[i]*b[j]*y[i,j], (i,j)) == 10

次のように記述することも可能です.:

Sum(Sum(a[i]*b[j]*y[i,j], j), i) == 10

すべての添字について演算を行う場合は第二引数を省略することもできます.:

Sum(a[i]*b[j]*y[i,j]) == 10

次の \(\sum_{i=1}^3 a_i b_j y_{ij} = 10\) のように一部の添字について演算を行う場合は 第二引数を省略することはできません.:

Sum(a[i]*b[j]*y[i,j], i) == 10

条件式を用いて,和や積を取る範囲を制限する事もできます. 次の例では,制約式 \(\sum_{i=3}^5 x_i = 10\) を記述しています.:

i = Element(value=range(1, 6))
x = Variable(index=i)
i3 = i>=3
Sum(x[i3], i3) == 10

条件付けられた添字と条件付けられていない添字を混在することはできません. 次の例はいずれも誤りです.:

Sum(x[i], i>=3) == 10
Sum(x[i>=3], i) == 10

条件式が複数箇所に登場する場合,条件式は一度保存したものを使用する必要があります. 次の例は誤りです.:

Sum(x[i>=3], i>=3) == 10

条件付けられた添字が一度しか登場しない場合は直接記述することができます.:

Sum(x[i>=3]) == 10

次の例では,制約式 \(\sum_{i\in T} x_{i} =10\)\(\sum_{i\notin T} x_{i} = 20\) を記述しています.:

i = Element(value=['p', 'q', 'r', 's'])
T = Set(value=['p', 'r'])
x = Variable(index=i)
iinT = i<T
Sum(x[iinT], iinT) == 10
inotinT = i>T
Sum(x[inotinT], inotinT) == 20

次のように記述することもできます.:

i = Element(value=['p', 'q', 'r', 's'])
T = Set(value=['p', 'r'])
x = Variable(index=i)
Sum(x[i<T]) == 10
Sum(x[i>T]) == 20

集合を用意しなくても記述することができます. 次の例はいずれも正しい書き方です.:

i = Element(value=['p', 'q', 'r', 's'])
x = Variable(index=i)
iinT = i<['p', 'r']
Sum(x[iinT], iinT) == 10
inotinT = i>['p', 'r']
Sum(x[inotinT], inotinT) == 20
i = Element(value=['p', 'q', 'r', 's'])
x = Variable(index=i)
Sum(x[i<['p', 'r']]) == 10
Sum(x[i>['p', 'r']]) == 20