# モデルの定式化 組合せ最適化問題は、決定変数と目的関数、制約条件からなります。 「[2. 決定変数の作り方](variables.md)」、「[3. 多項式と目的関数](objective.md)」、「[4. 制約条件](constraint.md)」では、 決定変数は {py:class}`~amplify.VariableGenerator` を用いて作成することができ、 目的関数と制約条件は {py:class}`~amplify.Poly` と {py:class}`~amplify.Constraint` によって表現することができることを解説しました。 このページでは、これらを組み合わせて、組合せ最適化問題をプログラムコード上で表現する方法について解説します。 ```{seealso} {py:class}`~amplify.Poly` クラスのほかに係数行列形式 {py:class}`~amplify.Matrix` クラスのインスタンスも目的関数として使用することができます。 目的関数が {py:class}`~amplify.Matrix` として表現されている場合も、このページで解説する内容と全く同様に使用することができます。 係数行列形式についての詳細は「[係数行列による目的関数の作成](matrix.md)」を参照してください。 ``` ## モデルの構築 Amplify SDK において、組合せ最適化問題は {py:class}`~amplify.Model` クラスのインスタンスとして表現されます。 目的関数と制約条件が両方ある組合せ最適化問題を表現するには、目的関数を表す {py:class}`~amplify.Poly` と制約条件を表す {py:class}`~amplify.Constraint` または {py:class}`~amplify.ConstraintList` を加算するのが簡単な方法です。 ```{testcode} from amplify import VariableGenerator, Model, equal_to, one_hot gen = VariableGenerator() q = gen.array("Binary", shape=(2, 3)) objective = q[0, 0] * q[0, 1] - q[0, 2] constraint1 = equal_to(q[0, 0] + q[0, 1] - q[0, 2], 0) constraint2 = one_hot(q[1, :]) constraint_list = constraint1 + constraint2 ``` * 目的関数と制約条件を足してモデルを構築する: ```{doctest} >>> model = objective + constraint1 >>> print(model) minimize: q_{0,0} q_{0,1} - q_{0,2} subject to: q_{0,0} + q_{0,1} - q_{0,2} == 0 (weight: 1) ``` * 目的関数と制約条件リストを足してモデルを構築する: ```{doctest} >>> model = objective + constraint_list >>> print(model) minimize: q_{0,0} q_{0,1} - q_{0,2} subject to: q_{0,0} + q_{0,1} - q_{0,2} == 0 (weight: 1), q_{1,0} + q_{1,1} + q_{1,2} == 1 (weight: 1) ``` 目的関数のみまたは制約条件のみからなる組合せ最適化問題を表現するには、 {py:class}`~amplify.Model` クラスのコンストラクタに、目的関数を表す {py:class}`~amplify.Poly` (または {py:class}`~amplify.Matrix`) のインスタンス、あるいは制約条件を表す {py:class}`~amplify.Constraint` または {py:class}`~amplify.ConstraintList` のインスタンスを渡します。 * 目的関数 ({py:class}`~amplify.Poly`) からモデルを構築する: ```{doctest} >>> model = Model(objective) >>> print(model) minimize: q_{0,0} q_{0,1} - q_{0,2} ``` * 単一の制約条件オブジェクト ({py:class}`~amplify.Constraint`) からモデルを構築する: ```{doctest} >>> model = Model(constraint1) >>> print(model) minimize: 0 subject to: q_{0,0} + q_{0,1} - q_{0,2} == 0 (weight: 1) ``` * 複数の制約条件オブジェクト ({py:class}`~amplify.ConstraintList`) からモデルを構築する: ```{doctest} >>> model = Model(constraint_list) >>> print(model) minimize: 0 subject to: q_{0,0} + q_{0,1} - q_{0,2} == 0 (weight: 1), q_{1,0} + q_{1,1} + q_{1,2} == 1 (weight: 1) ``` モデルを構築したあとで、制約条件 ({py:class}`~amplify.Constraint` または {py:class}`~amplify.ConstraintList`) を追加することもできます。 ```{doctest} >>> model = Model(objective) >>> print(model) minimize: q_{0,0} q_{0,1} - q_{0,2} >>> model += constraint1 >>> print(model) minimize: q_{0,0} q_{0,1} - q_{0,2} subject to: q_{0,0} + q_{0,1} - q_{0,2} == 0 (weight: 1) ``` モデルが目的関数を多項式 {py:class}`~amplify.Poly` クラスのインスタンスで持つ場合には、目的関数の加算と減算も可能です。 ```{doctest} >>> model += q[0, 0] * q[0, 1] >>> print(model) minimize: 2 q_{0,0} q_{0,1} - q_{0,2} subject to: q_{0,0} + q_{0,1} - q_{0,2} == 0 (weight: 1) ``` ```{doctest} >>> model -= q[0, 0] >>> print(model) minimize: 2 q_{0,0} q_{0,1} - q_{0,0} - q_{0,2} subject to: q_{0,0} + q_{0,1} - q_{0,2} == 0 (weight: 1) ``` ## モデルのアトリビュート {py:attr}`~amplify.Model.objective` プロパティにより、{py:class}`~amplify.Model` クラスが持っている目的関数を取得することができます。 ```{testcode} from amplify import VariableGenerator, equal_to gen = VariableGenerator() q = gen.array("Binary", 2, 3) objective = q[0,0] * q[0,1] - q[0,2] constraint = equal_to(q[0,0] + q[0,1] - q[0,2], 0) model = objective + constraint ``` ```{doctest} >>> print(model.objective) q_{0,0} q_{0,1} - q_{0,2} ``` {py:attr}`~amplify.Model.constraints` プロパティにより、{py:class}`~amplify.Model` クラスが保持している制約条件を取得することができます。このプロパティは {py:class}`~amplify.ConstraintList` クラスのインスタンスを返します。 ```{doctest} >>> print(model.constraints) [q_{0,0} + q_{0,1} - q_{0,2} == 0 (weight: 1)] ``` ````{note} モデルは目的関数と制約条件をコピーせずに格納します。そのため、モデルに含まれる目的関数や制約条件を変更すると、構築前の変数も変更されることに注意してください。 ```{doctest} model = Model(objective) model += q[0, 0] assert model.objective == objective ``` ```` ## モデルに含まれる制約条件の重みを変更する モデルの構築後に、モデルが含んでいる制約条件の重みを変更したい場合があります。 ```{note} 制約条件の重みの調整に関しては「[](#penalty-weight)」を参照してください。 ``` 以下の例では、特定の制約条件の重みを 2 倍にします。 ```{doctest} >>> print(model) minimize: q_{0,0} q_{0,1} - q_{0,2} subject to: q_{0,0} + q_{0,1} - q_{0,2} == 0 (weight: 1) >>> model.constraints[0] *= 2 >>> print(model) minimize: q_{0,0} q_{0,1} - q_{0,2} subject to: q_{0,0} + q_{0,1} - q_{0,2} == 0 (weight: 2) ```