Preparationで変換する制約族を選ぶ#

このページは、自動PreparationのTutorialを読んだ利用者向けです。アプリケーションで許可する変換を明示したい場合は、Policyを設定し、自分でPreparationしてから厳格なAPIへ渡します。 通常の求解だけならsolve()を使ってください。

ここでは「OneHotだけを通常制約へloweringし、SOS1は専用の制約としてソルバーへ渡す」という方針を固定します。PySCIPOpt AdapterはSOS1を直接扱えますが、OneHotは直接扱いません。現在の推奨Policyも同じ選択ですが、ここでは推奨の内容に依存せず、許可する制約族をアプリケーションで指定します。

モデルを作る#

Python SDKとAdapterのインストールで用意したv3の環境を使います。OneHotは「ちょうど1つが1」、SOS1は「高々1つが非ゼロ」という制約です。

from ommx import Instance, OneHotConstraint, Sos1Constraint

instance = Instance.maximize()
primary = [instance.new_binary("primary", subscripts=[i]) for i in range(2)]
optional = [instance.new_binary("optional", subscripts=[i]) for i in range(2)]
instance.objective = (
    10 * primary[0] + 8 * primary[1]
    + 4 * optional[0] + 3 * optional[1]
)
instance.add_one_hot_constraint(OneHotConstraint(variables=primary))
instance.add_sos1_constraint(Sos1Constraint(variables=optional))

Policyを選び、Instanceへ適用する#

この例では、ほかの変換を無効にしたPolicyを作り、special_constraintsだけを設定します。loweringを許可する制約族もOneHotに限定します。Policyを作るだけでは、Instanceは変わりません。

from ommx import PreparationPolicy, SpecialConstraintKind, SpecialConstraintPreparation
from ommx_pyscipopt_adapter import OMMXPySCIPOptAdapter

policy = PreparationPolicy(
    special_constraints=SpecialConstraintPreparation.lower_special_constraints(
        kinds={SpecialConstraintKind.OneHot}
    )
)

instance.prepare(OMMXPySCIPOptAdapter.INPUT_CLASS, policy)

assert OMMXPySCIPOptAdapter.INPUT_CLASS.contains(instance)
assert not instance.one_hot_constraints
assert instance.sos1_constraints

prepare()はこのInstanceを直接変更します。OneHotは通常の線形等式に変わり、SOS1はそのまま残っています。変換元のOneHotはremoved constraintとして保持されます。

Policyは「必ず実行する操作の一覧」ではありません。targetのINPUT_CLASSへ入るとPreparationは停止します。このモデルにはOneHotがあるためloweringが必要ですが、最初からtargetに入るモデルでは、設定した変換も実行されません。

自分で準備したInstanceを解く#

solve_without_preparation()は追加のPreparationを行いません。先ほど設定したPolicyの結果を、そのままソルバーへ渡せます。

solution = OMMXPySCIPOptAdapter.solve_without_preparation(instance)

assert solution.feasible
assert abs(solution.objective - 14.0) < 1e-8
solution.decision_variables_df()

通常のsolve()は、ここで指定したpolicyではなくAdapterから新たに取得した推奨Policyを使います。独自のPolicyを使う経路では、prepare()とsolve_without_preparation()を組にしてください。

Policyの各phaseや到達できない場合の扱いはInstance PreparationとPreparationPolicy、各loweringの適用条件や数式はlower_special_constraints()からAPI Referenceを参照してください。