ommx.v1.ParametricInstance

ommx.v1.ParametricInstance#

ommx.v1.ParametricInstanceommx.v1.Instance と同じように数理モデルを表現するクラスですが、決定変数に加えてパラメータ(ommx.v1.Parameter)を持つことができます。パラメータの値を決めるたびに ommx.v1.Instance を生成することができるため、例えば目的関数や制約条件の一部の係数が異なる一連の数理モデル群を扱いたい場合などに便利です。同じommx.v1.ParametricInstanceから生成された ommx.v1.Instance は決定変数や制約条件のIDを共有しているため、解の比較などが行いやすくなっています。

次のナップザック問題を考えましょう。

\[\begin{split} \begin{align*} \text{maximize} \quad & \sum_{i=1}^{N} p_i x_i \\ \text{subject to} \quad & \sum_{i=1}^{N} w_i x_i \leq W \\ & x_i \in \{0, 1\} \quad (i=1, 2, \ldots, N) \end{align*} \end{split}\]

ここで、\(N\)はアイテムの数、\(p_i\)はアイテム\(i\)の価値、\(w_i\)はアイテム\(i\)の重さ、\(W\)はナップザックの容量です。\(x_i\)はアイテム\(i\)をナップザックに入れるかどうかを表すバイナリ変数です。ommx.v1.Instance では \(p_i\)\(w_i\) は固定値を使いましたが、ここではこれらをパラメータとして扱います。

from ommx.v1 import ParametricInstance, DecisionVariable, Parameter, Instance

N = 6
x = [DecisionVariable.binary(id=i, name="x", subscripts=[i]) for i in range(N)]

p = [Parameter.new(id=i+  N, name="Profit", subscripts=[i]) for i in range(N)]
w = [Parameter.new(id=i+2*N, name="Weight", subscripts=[i]) for i in range(N)]
W =  Parameter.new(id=  3*N, name="Capacity")

ommx.v1.Parameter もIDを持ちますが、これは ommx.v1.DecisionVariable のIDと共通なので、重複しないようにする必要があります。決定変数と同じようにパラメータにも名前や添え字を付与できます。これらは決定変数と同じように +<= で演算して ommx.v1.Functionommx.v1.Constraint を作成することができます。

objective = sum(p[i] * x[i] for i in range(N))
constraint = sum(w[i] * x[i] for i in range(N)) <= W

これらを組み合わせてナップザック問題を表現する ommx.v1.ParametricInstance を作りましょう。

parametric_instance = ParametricInstance.from_components(
    decision_variables=x,
    parameters=p + w + [W],
    objective=objective,
    constraints=[constraint],
    sense=Instance.MAXIMIZE,
)

ommx.v1.Instanceと同様に decision_variables 及び constraints プロパティで決定変数と制約条件をDataFrameとして取得できますが、加えて ommx.v1.ParametricInstance には parameters プロパティがあります。これはパラメータの情報をDataFrameとして取得できます。

parametric_instance.parameters
[Parameter(raw=id: 6
 name: "Profit"
 subscripts: 0
 ),
 Parameter(raw=id: 7
 name: "Profit"
 subscripts: 1
 ),
 Parameter(raw=id: 8
 name: "Profit"
 subscripts: 2
 ),
 Parameter(raw=id: 9
 name: "Profit"
 subscripts: 3
 ),
 Parameter(raw=id: 10
 name: "Profit"
 subscripts: 4
 ),
 Parameter(raw=id: 11
 name: "Profit"
 subscripts: 5
 ),
 Parameter(raw=id: 12
 name: "Weight"
 subscripts: 0
 ),
 Parameter(raw=id: 13
 name: "Weight"
 subscripts: 1
 ),
 Parameter(raw=id: 14
 name: "Weight"
 subscripts: 2
 ),
 Parameter(raw=id: 15
 name: "Weight"
 subscripts: 3
 ),
 Parameter(raw=id: 16
 name: "Weight"
 subscripts: 4
 ),
 Parameter(raw=id: 17
 name: "Weight"
 subscripts: 5
 ),
 Parameter(raw=id: 18
 name: "Capacity"
 )]

さて具体的なパラメータを指定してみましょう。それには ParametricInstance.with_parameters を使います。これは ommx.v1.Parameter のIDをキー、値を値とする辞書を引数に取ります。

p_values = { x.id: value for x, value in zip(p, [10, 13, 18, 31, 7, 15]) }
w_values = { x.id: value for x, value in zip(w, [11, 15, 20, 35, 10, 33]) }
W_value = { W.id: 47 }

instance = parametric_instance.with_parameters({**p_values, **w_values, **W_value})

Note

ommx.v1.ParametricInstance では \(N\) のように決定変数やパラメータの数が変化するようなパラメータは扱えません。JijModelingなどのより高度なモデラーを使ってください。