Constraint

このセクションでは制約条件を表すクラスについて説明します。

制約条件オブジェクト

量子アニーリングマシン・イジングマシンで問題を解く際に、使用する変数の間に制約条件を課す必要が生じることがあります。

例えば、\(x_0, x_1, x_2\) を変数とする目的関数 \(f\left(x_0, x_1, x_2 \right)\) の最適解を探索する際に、変数の間に \(x_0 + x_1 + x_2 = 1\) などの等式制約や、\(x_0 + x_1 + x_2 \leq 2\) などの不等式制約が課されていると、制約条件を満たす「実行可能解」の中から最適解を見つける必要があります。

ところが、量子アニーリングマシン・イジングマシンの扱える QUBO やイジングモデルは、そのような制約条件を直接は扱うことが出来ません。そのため、基本的なアプローチとして、制約条件を満たす場合に最小値をとるようなペナルティ関数 \(g\) を重み \(\lambda\) を付けて元の目的関数 \(f\) に追加する方法が行われます。

つまり、\(f\) の代わりに、\(h = f + \lambda g \quad (\lambda > 0)\) の最適解を求めることで、ペナルティ関数 \(g\) が最小、すなわち制約条件を満たす実行可能解の取得が可能になります。実際には、マシンの出力が必ずしも最適解であるとは限らないので、\(h\) の解を \(g\) で評価したときに最小値であるかを確認することで、実行可能解かどうかを識別します。

Amplify SDK では、このようなペナルティ関数の定式化、ペナルティ関数の重み、解を評価する際の充足チェック等、構築から管理までを行う制約条件オブジェクトという形でこれを抽象化します。

制約条件クラスは、多項式クラスや行列クラスに付与される、変数間に働く制約条件を表します。

多項式クラス・行列クラスとの対応関係は次の通りです。

多項式クラス

行列クラス

制約条件クラス

BinaryPoly

BinaryMatrix

BinaryConstraint

IsingPoly

IsingMatrix

IsingConstraint

BinaryIntPoly

BinaryIntMatrix

BinaryIntConstraint

IsingIntPoly

IsingIntPoly

IsingIntConstraint

制約条件オブジェクトは、BinaryQuadraticModel 等に与えることで論理模型に変換できるほか、多項式クラスや行列クラスと組み合わせることで、与えられた多項式・行列オブジェクトに対する付加的な制約条件として扱われます。

ペナルティ関数を用いた構築

変数 \(\mathbf q\) の間の制約条件は、適切にペナルティ関数 \(g(\mathbf{q})\) を設定することで表現できます。 \(g(\mathbf{q})\) は、制約条件を満たす \(\mathbf{q}\) が入力されると最小値をとるような関数です。制約条件を満たさない \(\mathbf{q}\) が入力されると最小値より大きな値をとるような「ペナルティ」が課されるので、\(g(\mathbf{q})\) はペナルティ関数と呼ばれます。

事前にペナルティ関数がわかっている場合、次の生成関数を用いて制約条件クラスを構築することが出来ます。

制約

生成関数

使用可能条件

\(f\left( \mathbf{q} \right) = 0\)

penalty()

\(\min f\left( \mathbf{q} \right) = 0\)

penalty() はペナルティ関数を表す基本的な制約条件オブジェクトです。多項式 \(f\) の最小値が \(\min f = 0\) であり \(f = 0\) の時に制約を満たすようなペナルティ関数を与えます。

論理式による制約

次のような例を考えます。ある2変数 \(q_0, q_1\) について、両方同時に \(1\) にならないような制約を考えます。これは、両方 \(1\) のとき False その他の時 True と考えると、 NAND 演算に相当します。

この例について論理式クラスを用いて制約条件オブジェクトを生成します。論理式クラスについては Logical Expression を参照してください。

次のように NOT AND を表す論理式を構築します。

from amplify import LogicPoly

x = gen_symbols(LogicPoly, 2)
p = ~(x[0] & x[1])
>>> p
- x_0 x_1 + 1

論理式 p をバイナリ変数の多項式に変換します。最適化(最小化)問題としては True\(1\)False\(0\) の関係が逆転しているので、変換前に NOT 演算を行います。

from amplify.constraint import penalty

f = (~p).to_Poly()
g = penalty(f)
>>> g
q_0 q_1 == 0

これにより、True の場合に \(0\)False の場合に \(1\) となる最小化問題に変換できました。このように最適値かつ最小値が \(0\) になるような制約条件は penalty() 関数を用いて制約条件オブジェクトを生成できます。

from amplify import (
    BinaryQuadraticModel,
    decode_solution,
    gen_symbols,
    LogicPoly,
    Solver,
)
from amplify.client import FixstarsClient

client = FixstarsClient()
client.token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
client.parameters.timeout = 1000
client.parameters.outputs.duplicate = True
client.parameters.outputs.num_outputs = 0

model = BinaryQuadraticModel(g)
solver = Solver(client)
result = solver.solve(model)

g = penalty(f) にて制約条件オブジェクトを生成し、論理模型を構築することで実行結果を確認できます。

>>> for solution in result
>>>     values = solution.values
>>>     print(decode_solution(x, values))
[1, 0]
[0, 1]
[0, 0]

上記のように、NAND 条件を満たす解を全て得ることが出来ました。

ヘルパー関数を用いた構築

penalty() 関数を用いる場合は、制約条件を満たすペナルティ関数を手動で設計する必要があります。そこで Amplify SDK では、典型的な制約条件に関して制約条件オブジェクトの作成を行うヘルパー関数が用意されています。

  • equal_to() は与えられた多項式 \(f\) が定数値 \(c\) になるように制約します。

  • less_equal() は与えられた多項式 \(f\) が定数値 \(c\) 以下になるように制約します。ただし \(f\) は整数値のみを取る多項式であり、制約範囲と値域が重なっている必要があります。

  • greater_equal() は与えられた多項式 \(f\) が定数値 \(c\) 以上になるように制約します。ただし \(f\) は整数値のみを取る多項式であり、制約範囲と値域が重なっている必要があります。

  • clamp() は与えられた多項式 \(f\) が定数値 \(c_1\) 以上 \(c_2\) 以下になるように制約します。ただし \(f\) は整数値のみを取る多項式であり、制約範囲と値域が重なっている必要があります。

制約

生成関数

使用可能条件

\(f \left( \mathbf{q} \right) = c\)

equal_to()

\(\exists \mathbf{q}, f\left( \mathbf{q} \right) = c\)

\(f \left( \mathbf{q} \right) \le c\)

less_equal()

\(\forall \mathbf{q}, f\left( \mathbf{q} \right) \in \mathbb{Z}\) かつ \(\exists \mathbf{q}, f\left( \mathbf{q} \right) \le c\)

\(f \left( \mathbf{q} \right) \ge c\)

greater_equal()

\(\forall \mathbf{q}, f\left( \mathbf{q} \right) \in \mathbb{Z}\) かつ \(\exists \mathbf{q}, f\left( \mathbf{q} \right) \ge c\)

\(c_1 \le f \left( \mathbf{q} \right) \le c_2\)

clamp()

\(\forall \mathbf{q}, f\left( \mathbf{q} \right) \in \mathbb{Z}\) かつ \(\exists \mathbf{q}, f\left( \mathbf{q} \right) \le c_2\) かつ \(\exists \mathbf{q}, f\left( \mathbf{q} \right) \ge c_1\)

下記に具体的な制約条件を用いた例を示します。

One-hot 制約

代表的な制約条件として One-hot 制約があげられます。複数のビット変数セットに対し、一つだけ \(1\) になり他は \(0\) になる制約です。

例えば \(n\) 変数の多項式について \(\sum_{i = 0}^{n-1} q_i = 1\) の時のみ制約を満たします。

これを制約条件オブジェクトとして構築するには equal_to() を使用します。

from amplify import BinaryPoly, gen_symbols, sum_poly
from amplify.constraint import equal_to

q = gen_symbols(BinaryPoly, 4)
f = equal_to(sum_poly(q), 1)
>>> f
q_0 + q_1 + q_2 + q_3 == 1.000000

上記では equal_to(sum_poly(q), 1) にて第一引数を制約対象となる多項式オブジェクトを、第二引数に定数値を設定します。 次のようにして、クライアントを設定し制約条件オブジェクトから論理模型を構築することで、実行結果を確認できます。

from amplify import BinaryQuadraticModel, Solver, decode_solution
from amplify.client import FixstarsClient

client = FixstarsClient()
client.token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
client.parameters.timeout = 1000
client.parameters.outputs.duplicate = True  # エネルギー値が同一の解を重複して出力する
client.parameters.outputs.num_outputs = 0

model = BinaryQuadraticModel(f)
solver = Solver(client)
result = solver.solve(model)
>>> for solution in result
>>>     values = solution.values
>>>     print(decode_solution(q, values))
[1, 0, 0, 0]
[0, 1, 0, 0]
[0, 0, 1, 0]
[0, 0, 0, 1]

対象となる変数配列 q について、一つだけ \(1\) をとりその他は \(0\) となる解が四通り全て得られました。

等式制約

任意の多項式を \(f \left( \mathbf{q} \right) = c\) に制約します。

One-hot 制約と同様に equal_to() を使用します。

from amplify import BinaryPoly, gen_symbols, sum_poly
from amplify.constraint import equal_to

q = gen_symbols(BinaryPoly, 4)
f = 3 * q[0] - q[1] - 2 * q[2] + q[3]
g = equal_to(f, 2)
>>> g
3.000000 q_0 - q_1 - 2.000000 q_2 + q_3 == 2.000000

上記では equal_to(f, 2) にて第一引数を制約対象となる多項式オブジェクトを、第二引数に定数値を設定します。 次のようにして、クライアントを設定し制約条件オブジェクトから論理模型を構築することで、実行結果を確認できます。

from amplify import BinaryQuadraticModel, Solver, decode_solution
from amplify.client import FixstarsClient

client = FixstarsClient()
client.token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
client.parameters.timeout = 1000
client.parameters.outputs.duplicate = True  # エネルギー値が同一の解を重複して出力する
client.parameters.outputs.num_outputs = 0

model = BinaryQuadraticModel(g)
solver = Solver(client)
result = solver.solve(model)
>>> for solution in result
>>>     values = solution.values
>>>     print(decode_solution(q, values))
[1, 1, 0, 0]
[1, 0, 1, 1]

多項式 f について、f = 2 を満たす変数配列 q が得られました。

不等式制約

正の整数値をとる多項式を不等式(以上・以下・範囲)で制約します。

  • less_equal() は与えられた多項式 \(f\) が値 \(c\) 以下 (\(f \le c\)) になるように制約します。

  • greater_equal() は与えられた多項式 \(f\) が値 \(c\) 以上 (\(f \ge c\)) になるように制約します。

  • clamp() は与えられた多項式 \(f\) が値 \(c_1\) 以上 \(c_2\) 以下 (\(c_1 \le f \le c_2\)) になるように制約します。

from amplify import BinaryPoly, gen_symbols, sum_poly
from amplify.constraint import less_equal

q = gen_symbols(BinaryPoly, 4)
f = 4 * q[0] + 3 * q[1] + 2 * q[2] + q[3]
g = less_equal(f, 3)

上記では \(f \le 3\) で制約するために、 less_equal(f, 3) にて第一引数を制約対象となる多項式オブジェクトを渡し第二引数に定数値を設定します。 次のようにして実行結果を確認できます。

from amplify import BinaryQuadraticModel, Solver, decode_solution
from amplify.client import FixstarsClient

client = FixstarsClient()
client.token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
client.parameters.timeout = 1000
client.parameters.outputs.duplicate = True  # エネルギー値が同一の解を重複して出力する
client.parameters.outputs.num_outputs = 0

solver = Solver(client)
result = solver.solve(g)
>>> g
4.000000 q_0 + 3.000000 q_1 + 2.000000 q_2 + q_3 <= 3
>>> for solution in result
>>>     values = solution.values
>>>     print(decode_solution(q, values))
[0, 0, 0, 0]
[0, 0, 0, 1]
[0, 0, 1, 0]
[0, 0, 1, 1]
[0, 1, 0, 0]

多項式 f について、f <= 3 を満たす変数配列 q が得られました。

同様にして、\(f \ge 3\) で制約する場合は greater_equal() 関数を用います。

from amplify.constraint import greater_equal

g = greater_equal(f, 3)
result = solver.solve(g)
>>> g
4.000000 q_0 + 3.000000 q_1 + 2.000000 q_2 + q_3 >= 3
>>> for solution in result
>>>     values = solution.values
>>>     print(decode_solution(q, values))
[0, 0, 1, 1]
[0, 1, 0, 0]
[0, 1, 0, 1]
[0, 1, 1, 0]
[0, 1, 1, 1]
[1, 0, 0, 0]
[1, 0, 0, 1]
[1, 0, 1, 0]
[1, 0, 1, 1]
[1, 1, 0, 0]
[1, 1, 0, 1]
[1, 1, 1, 0]
[1, 1, 1, 1]

同様にして、値の範囲 \(2 \le f \le 3\) で制約する場合は clamp() 関数を用います。第二引数に下限値を、第三引数に上限値を指定します。

from amplify.constraint import clamp

g = clamp(f, 2, 3)
result = solver.solve(g)
>>> g
2 <= 4.000000 q_0 + 3.000000 q_1 + 2.000000 q_2 + q_3 <= 3
>>> for solution in result
>>>     values = solution.values
>>>     print(decode_solution(q, values))
[0, 0, 1, 1]
[0, 0, 1, 0]
[0, 1, 0, 0]

多項式 f について、2 <= f <= 3 を満たす変数配列 q が得られました。

注釈

less_equal() 等を用いた不等式制約の実現は、定式化が複雑になるだけでなく、多くの補助変数を消費するため求解が困難になることがあります。また、実数値による不等式制約はヘルパー関数の適用対象外である事に注意が必要です。このような場合には、高度な制約条件の構築 による不等式制約の構築が有効である可能性があります。

制約条件へのラベル付け

制約条件オブジェクトにはラベルを付けることができます。これにより、ラベルを元にした制約条件のフィルタリングを行うことができます。 具体的なフィルタリングの使用例については 制約条件のフィルタリング を参照してください。

以下のように制約条件オブジェクトにラベルを付けることができます。

from amplify.constraint import (penalty, equal_to)

g1 = penalty(f, "penalty_label")
g2 = equal_to(f, 2, "equal_to_label")
>>> g1
penalty_label: 4.000000 q_0 + 3.000000 q_1 + 2.000000 q_2 + q_3 == 0
>>> g2
equal_to_label: 4.000000 q_0 + 3.000000 q_1 + 2.000000 q_2 + q_3 == 2.000000

プリント時にラベルが制約式とともに表示される他、ラベルのみを確認することもできます。

>>> g1.label
'penalty_label'

高度な制約条件の構築

penalty() 関数を用いると、ペナルティ関数を設定し制約条件オブジェクトを構築することが出来ます。通常は、与えられたペナルティ関数 \(g\) は全ての変数の組合せに対して \(g \ge 0\) であり \(g = 0\) の場合に制約が充足していると判断されます。この充足判定式を変更し、任意の値による等式条件や不等式条件に変更することが可能です。

例えば、与えたペナルティ関数 \(g\) の最小値が \(m \ne 0\) の場合を考えます。この時、次のようにして等式の右辺を明示的に指定することが可能です。

from amplify import BinaryPoly, Solver, decode_solution, gen_symbols
from amplify.constraint import penalty

q = gen_symbols(BinaryPoly, 3)
f = -q[0] - 0.5 * q[1] - 0.5 * q[2]             # 目的関数 f
g = q[0] * q[1] + q[1] * q[2] + q[2] * q[0] + 1 # ペナルティ関数 g (最小値 1)
p = penalty(g, eq = 1, label = "g = 1")         # g = 1 で充足判定を行う
>>> p
g = 1: q_0 q_1 + q_0 q_2 + q_1 q_2 == 1.000000

penalty() 関数の第一引数にペナルティ関数を指定し、キーワード引数を用いて eq (equal to) に等式の右辺を与えます。上記の例では、ペナルティ関数 \(g\) に対して、\(g = 1\) で充足判定を行う事を意味します。制約条件へのラベル付け を行う場合にはキーワード引数 label で与える必要があることに注意してください。

from amplify.client import FixstarsClient

client = FixstarsClient()
client.token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
client.parameters.timeout = 1000
client.parameters.outputs.duplicate = True  # エネルギー値が同一の解を重複して出力する
client.parameters.outputs.num_outputs = 0   # 探索された全ての解を出力する
solver = Solver(client)
>>> result = solver.solve(f + p)
>>> for sol in result:
>>>     print(f"q = {decode_solution(q, sol.values)}, f = {sol.energy}, g = {g.replace_all(sol.values)}")
q = [1, 0, 0], f = -1.0, g = 1.0

ペナルティ関数の評価値が \(g = 1\) となる解を得ることが出来ました。

一方で、不等式による充足判定の指定は、ペナルティ関数の持つ本来の制約条件より「弱い制約条件」を実現したり、「不等式制約」を間接的に実現するために用いられます。本来、ペナルティ関数は評価値が最小値 \(m\) となるように働きかけますが、これを緩和してある範囲内の解を実行可能解と判定させることが出来ます。これにより、なるべく \(g\) は小さい方が良いが、必ずしも最小値 \(g = m\) でなくて良いという状況を作ることが可能です。

充足判定を不等式に変更した制約条件オブジェクトは次のようにして構築できます。

q = gen_symbols(BinaryPoly, 3)
f = -q[0] - 0.5 * q[1] - 0.5 * q[2]         # 目的関数 f
g = q[0] * q[1] + q[1] * q[2] + q[2] * q[0] # ペナルティ関数 g (最小値 0)
p = penalty(g, le = 1, label = "g <= 1")    # g <= 1 で充足判定を行う
>>> p
g <= 1: q_0 q_1 + q_0 q_2 + q_1 q_2 <= 1.000000

不等式を表すキーワード引数は le (less equal), ge (greater equal), lt (less than), gt (greater than) が指定できます。上記の例では、ペナルティ関数 \(g \ge 0\) に対して、(\(g = 0\) ではなく) \(g \le 1\) で充足判定を行う事を意味します。

>>> result = solver.solve(f + p)
>>> for sol in result:
>>>     print(f"q = {decode_solution(q, sol.values)}, f = {sol.energy}, g = {g.replace_all(sol.values)}")
q = [1, 1, 0], f = -1.5, g = 1.0
q = [1, 0, 1], f = -1.5, g = 1.0
q = [1, 0, 0], f = -1.0, g = 0.0

制約の充足判定を \(g \le 1\) とした解を複数得ることが出来ました。

注釈

与えたペナルティ関数の働きに注意を払って充足判定関数を設定してください。最適化におけるペナルティ関数の意味と、充足判定関数の指定が矛盾したり競合する場合、実行可能解を得ることが期待出来なくなります。

制約条件クラスの演算子とメソッド

制約条件を充たすか調べる

制約条件オブジェクトに変数値を与えることで制約条件を満たしているかを返します。変数値は、辞書・リスト・関数オブジェクトとして与えることが出来ますが、制約条件に含まれる変数のインデックス全てに対して解決可能でなければなりません。

from amplify import BinaryPoly, gen_symbols, sum_poly
from amplify.constraint import equal_to

q = gen_symbols(BinaryPoly, 4)
f = equal_to(sum_poly(q), 1)
>>> f.is_satisfied({0: 1, 1: 0, 2: 0, 3: 0})
True
>>> f.is_satisfied([0, 1, 0, 0])
True
>>> f.is_satisfied(lambda i: 1 if i == 0 else 0)
True
>>> f.is_satisfied({0: 1, 1: 0, 2: 0, 3: 1})
False
>>> f.is_satisfied([1, 1, 1, 1])
False
>>> f.is_satisfied(lambda i: 0)
False

ペナルティ関数の取得

制約条件オブジェクトの内部表現であるペナルティ関数を取得します。

from amplify import BinaryPoly, gen_symbols, sum_poly
from amplify.constraint import equal_to, less_equal

q = gen_symbols(BinaryPoly, 4)
f1 = equal_to(sum_poly(q), 1)
f2 = less_equal(sum_poly(q), 2)
>>> f1.penalty
2.000000 q_0 q_1 + 2.000000 q_0 q_2 + 2.000000 q_0 q_3 + 2.000000 q_1 q_2 + 2.000000 q_1 q_3 + 2.000000 q_2 q_3 - q_0 - q_1 - q_2 - q_3 + 1.000000

高次多項式を与えた場合や不等式制約など、ペナルティ関数の構築に補助変数が必要な場合はそのままでは取得できません。これは補助変数のインデックスが未確定なためです。

>>> f2.penalty
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: Function to publish ancillary variables is not given

この場合は BinaryQuadraticModel 等に与え論理模型に変換した後で、ペナルティ関数が確認出来ます。ただし論理模型に変換されているため、入力変数のインデックスと論理変数のインデックスの間に変数変換が行われている可能性があることに注意が必要です。

>>> m = BinaryQuadraticModel(f2)
>>> m.input_constraints
[(q_0 + q_1 + q_2 + q_3 <= 2, 1)]
>>> m.input_constraints[0][0].penalty
2.000000 q_0 q_1 + 2.000000 q_0 q_2 + 2.000000 q_0 q_3 - 2.000000 q_0 q_4 - 2.000000 q_0 q_5 + 2.000000 q_1 q_2 + 2.000000 q_1 q_3 - 2.000000 q_1 q_4 - 2.000000 q_1 q_5 + 2.000000 q_2 q_3 - 2.000000 q_2 q_4 - 2.000000 q_2 q_5 - 2.000000 q_3 q_4 - 2.000000 q_3 q_5 + 2.000000 q_4 q_5 + q_0 + q_1 + q_2 + q_3 + q_4 + q_5

制約条件の強さの設定

制約条件オブジェクトは、BinaryQuadraticModel 等の論理模型に与えることを前提としていますが、この際に「強さ」を設定することも出来ます。「強さ」は制約条件オブジェクト単体では実質意味を持ちませんが、論理模型に変換されるときに、多項式オブジェクトや行列クラス、その他の制約条件オブジェクトに対する相対的な強さとして扱われます。

from amplify import BinaryPoly, gen_symbols, sum_poly
from amplify.constraint import equal_to

q = gen_symbols(BinaryPoly, 4)
f = 1 * equal_to(sum_poly(q), 1)
>>> f
(q_0 + q_1 + q_2 + q_3 == 1.000000, 1)

強さが設定された制約条件オブジェクトは制約条件と強さのペアで表現されます。強さの係数値は後から変更することも可能ですが、制約条件自体は変更できません。

>>> f[1] = 2
>>> f
(q_0 + q_1 + q_2 + q_3 == 1.000000, 2)

制約条件のコンテナ化

BinaryQuadraticModel 等の論理模型に与える時に、複数の制約条件オブジェクトをまとめ上げることが可能です。

from amplify import BinaryPoly, gen_symbols, sum_poly
from amplify.constraint import equal_to

q = gen_symbols(BinaryPoly, 4)
f1 = equal_to(q[0] + q[1], 1)
f2 = 2 * equal_to(q[2] + q[3], 1)
g = f1 + f2
>>> g
[(q_0 + q_1 == 1.000000, 1), (q_2 + q_3 == 1.000000, 2)]

強さが設定されている場合もされていない場合も、区別無く加算してコンテナ化することが出来ます。この時、強さが設定されていない制約条件オブジェクトはデフォルト値として 1 が与えられているとします。

下記の様にして制約条件オブジェクトコンテナ全体に強さを乗算・除算することが出来ます。

>>> g *= 2
>>> g
[(q_0 + q_1 == 1.000000, 2), (q_2 + q_3 == 1.000000, 4)]

注釈

具体的な制約条件のコンテナ化や強さの設定例については EXAMPLES の 制約の強さの調整 を参照してください。

乗算・除算演算子

制約条件オブジェクトに対する乗算と除算は制約の強さの係数値を変更します。

乗算・除算対象と返却値の関係は次の通りです。

係数型

乗算・除算対象クラス

返却クラス

int

BinaryConstraint BinaryConstraintTerm

BinaryConstraintTerm

BinaryIntConstraint BinaryIntConstraintTerm

BinaryIntConstraintTerm

BinaryConstraints

BinaryConstraints

BinaryIntConstraints

BinaryIntConstraints

float

BinaryConstraint BinaryConstraintTerm

BinaryConstraintTerm

BinaryIntConstraint BinaryIntConstraintTerm

BinaryConstraints

BinaryConstraints

BinaryIntConstraints

加算演算子

制約条件オブジェクトに対する加算は、加算対象によって振る舞いを変えます。対象が多項式オブジェクトや行列オブジェクトの場合には論理模型を構築します。一方、対象が制約条件オブジェクトの場合には制約条件コンテナを構築します。

加算対象と返却値の関係は次の通りです。

制約条件クラス

加算対象クラス

返却クラス

BinaryConstraint BinaryConstraintTerm

BinaryConstraint BinaryConstraintTerm

BinaryConstraints

BinaryIntConstraint BinaryIntConstraintTerm

BinaryPoly

BinaryQuadraticModel

BinaryMatrix

BinaryIntPoly

BinaryIntMatrix

BinaryIntConstraint BinaryIntConstraintTerm

BinaryConstraint BinaryConstraintTerm

BinaryConstraints

BinaryIntConstraint BinaryIntConstraintTerm

BinaryIntConstraints

BinaryPoly

BinaryQuadraticModel

BinaryMatrix

BinaryIntPoly

BinaryIntQuadraticModel

BinaryIntMatrix