3.8.11. 次元を落としたオブジェクト作成

選択関数 Selection に伴う,次元を落としたオブジェクト作成の方法について紹介します. 以下では変数 z[i,j] は Selection 制約のため,各 i について z[i,j].val=1 となる j が存在します.:

>>> i = Element(value=[1, 2, 3], name='i')
>>> j = Element(value=['X', 'Y'], name='j')
>>> z = BinaryVariable(index=(i,j), name='x')
>>> p = Problem()
>>> p += Selection(z[i,j], j)
>>> p.solve(silent=True)
<NuoptStatus.OPTIMAL: 1>
>>> ij = z[i,j].val>0
>>> z[ij].val
z[1,'X'].val=1
z[2,'Y'].val=1
z[3,'Y'].val=1

これを i をキーとしたオブジェクトとして扱いたい場合にはどうすればよいでしょうか. 以下では z[i,j].val>0 を満たす (i,j) の組合せ ij を用いることにより, i をキー,対応する j を値とするパラメーター a を作成しています.:

>>> a = Parameter(index=i, name='a')
>>> a[ij(0)] = ij(1)
>>> a
a[1]='X'
a[2]='Y'
a[3]='Y'

更に a は一度に Parameter(index=i, value=dict(ij.set)) と記述することも可能です.

Selection で和をとった後に残る添字(上記では i)が多次元の場合でも同様の方法で扱うことができます. では,和をとる添字(上記では j)が多次元だった場合はどうすればよいでしょうか. 以下では z[i,j,k](j,k) で Selection をとっているため,各 i について z[i,j,k].val=1 となる (j,k) の組が存在します.:

>>> i = Element(value=[1, 2, 3], name='i')
>>> j = Element(value=['A', 'B'], name='j')
>>> k = Element(value=['X', 'Y'], name='k')
>>> z = BinaryVariable(index=(i,j,k), name='z')
>>> p = Problem()
>>> p += Selection(z[i,j,k], (j,k))
>>> p.solve(silent=True)
<NuoptStatus.OPTIMAL: 1>
>>> ijk = z[i,j,k].val>0
>>> z[ijk].val
z[1,'A','Y'].val=1
z[2,'B','X'].val=1
z[3,'B','Y'].val=1

Parameter は一次元の値しかとることができないため,このような場合, j 部分を担当するパラメーター aj と, k 部分を担当するパラメーター ak に分割することで, i をキーとしたオブジェクトとして扱うことができるようになります. このようにすることで (j,k) の組合せが欲しい場合には aj[i]ak[i] と記述できます.:

>>> aj = Parameter(index=i, name='aj')
>>> aj[ijk(0)] = ijk(1)
>>> aj
aj[1]='A'
aj[2]='B'
aj[3]='B'
>>> ak = Parameter(index=i, name='ak')
>>> ak[ijk(0)] = ijk(2)
>>> ak
ak[1]='Y'
ak[2]='X'
ak[3]='Y'
>>> Printf('{}: {}, {}', i, aj[i], ak[i])
1: A, Y
2: B, X
3: B, Y

更に aj, ak はそれぞれ Parameter(index=i, value=dict(ijk(0,1).set))Parameter(index=i, value=dict(ijk(0,2).set)) と記述することも可能です.