Adapter向けにInstanceを準備する#

前のPySCIPOpt Adapterで特殊制約をそのまま解くでは、Indicator制約とSOS1制約をSCIPへ直接渡しました。しかし、すべてのAdapterが同じ種類のInstanceを直接受け取れるわけではありません。

このチュートリアルでは、同じモデルをHiGHS Adapterで解きます。覚えておくことは、Adapterが直接扱えない表現も、OMMXが変換してから渡せるということです。この準備をInstance Preparationと呼びます。

実行環境#

Python SDKとAdapterのインストールで用意したv3の環境へ、同ページの手順でHiGHS Adapterを追加してください。このページの実行にPySCIPOpt Adapterは不要です。

同じモデルを作る#

このページだけでも実行できるように、前のチュートリアルと同じモデルを作り直します。

from ommx import Instance, Sos1Constraint

source = Instance.maximize()
enabled = source.new_binary("enabled")
option_a = source.new_binary("option_a")
option_b = source.new_binary("option_b")
option_c = source.new_binary("option_c")

source.objective = (
    10 * enabled
    + 6 * option_a
    + 5 * option_b
    + 4 * option_c
)
source.add_indicator_constraint(
    (option_a + option_b <= 1).with_indicator(enabled)
)
source.add_sos1_constraint(
    Sos1Constraint(
        variables=[option_b, option_c],
        name="exclusive_options",
    )
)

solve()にPreparationを任せる#

HiGHS Adapterは通常の線形制約を受け取れますが、Indicator制約やSOS1制約は直接受け取りません。それでも、前のページと同じようにsolve()を呼び出せます。

from ommx_highs_adapter import OMMXHighsAdapter

solution = OMMXHighsAdapter.solve(source)

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

# 呼び出し元のInstanceは変更されない
assert source.indicator_constraints
assert source.sos1_constraints

solution.decision_variables_df()

solve()は、元のInstanceを変更せず、そのcopyをHiGHS向けに準備してから解きます。このモデルではIndicator制約とSOS1制約を通常の線形制約へ変換します。特殊制約を通常制約へ書き換える操作をloweringと呼びます。

この例の変数はすべてBinaryであり、変換に必要な有限の上下限があります。任意のモデルを必ず変換できるわけではありません。個々のloweringの数式や適用条件はAPI Referenceで説明します。

直接受け取れる範囲と、変換の方針#

Adapterが直接受け取るInstanceの集合をINPUT_CLASS、その集合へ向けて選ぶ変換の方針をPreparationPolicyと呼びます。次のコードで、今回のsourceにはHiGHS向けの変換が必要だったことを確認できます。

assert not OMMXHighsAdapter.INPUT_CLASS.contains(source)

solve()はAdapterの推奨Policyを使いました。HiGHSの場合は今回のloweringを推奨しているため、利用者が変換コードを書く必要はありませんでした。一方、変換の選択や設定がアプリケーションに依存する場合は、推奨をそのまま使わず、自分でPolicyを選びます。

まとめ#

  • 特殊制約を直接扱わないAdapterでも、loweringして解ける場合があります。

  • solve()は入力のcopyに推奨Policyを適用するため、元のInstanceを変更しません。

  • INPUT_CLASSは直接受け取れる範囲、PreparationPolicyはそこへ向かう変換の選択です。

自分で変換を選ぶ必要が生じたら、操作ガイドPreparationで変換する制約族を選ぶへ進んでください。仕組みを理解するにはInstanceClassとAdapterの入力条件とInstance PreparationとPreparationPolicyを参照してください。