2. 決定変数の作り方¶
Amplify SDK を使用して組合せ最適化問題を解くためには、問題の定式化をプログラムコード上で表現することが必要です。 このページでは、定式化の最初のステップとして、決定変数の生成について解説します。
参考
変数を発行する方法としては、このページで解説する VariableGenerator
クラスの scalar()
および array()
メソッドのほかに matrix()
メソッドが提供されています。
二次の目的関数を係数行列形式で作成したい場合はこのメソッドを用いることができます。詳細は「係数行列による目的関数の作成」を参照してください。
2.1. 変数ジェネレータの作成¶
組合せ最適化問題の定式化を行うには、最初に VariableGenerator
クラスのインスタンスを作成することが必要です。このクラスは決定変数を発行するためのメソッドを提供します。
from amplify import VariableGenerator
gen = VariableGenerator()
2.2. 変数の生成¶
VariableGenerator
クラスの scalar()
メソッドを使うと、変数の種類を指定して新しい変数が発行できます。Amplify SDK で指定できる変数の種類は以下の表の通りです。
次のようにして新しくバイナリ変数を発行します。
変数は変数の多項式を表す Poly
クラスのインスタンスとして返されます。
>>> q = gen.scalar("Binary")
>>> print(q)
q_0
発行される変数には自動で名前がつきますが、名前を指定することもできます。
>>> i = gen.scalar("Ising", name="i")
>>> print(i)
i
整数変数または実数変数には取り得る値の範囲を指定できます。
>>> x = gen.scalar("Real", bounds=(2.0, 3.0))
>>> print(x)
x_0
2.3. 変数配列の作成¶
複数個の変数を一括で生成したい場合、VariableGenerator
の array()
メソッドを使うことができます。
このメソッドは、NumPy-like な多次元配列形式で変数の配列を返します。
次のようにして 3 個のバイナリ変数からなる配列を作成します。新たに 3 個の変数が発行され、変数名には自動で配列のインデックスを表す文字列が付きます。
>>> gen = VariableGenerator()
>>> q = gen.array("Binary", 3)
>>> print(q)
[q_0, q_1, q_2]
Python の list
や 1 次元 NumPy 配列と同様にして要素やスライスを取得することができます。
>>> print(q[0])
q_0
>>> print(q[:2])
[q_0, q_1]
VariableGenerator
の array()
メソッドは多次元の配列も作成することができます。以下の例では、 \(2 \times 3\) の 2 次元変数配列を作成します。
>>> gen = VariableGenerator()
>>> q = gen.array("Binary", shape=(2, 3))
>>> print(q)
[[q_{0,0}, q_{0,1}, q_{0,2}],
[q_{1,0}, q_{1,1}, q_{1,2}]]
2 次元の numpy.ndarray
と同様にして要素やスライスを取得することができます。取得される要素やスライスは、もとの配列のビューとなります。
>>> print(q[0, 0])
q_{0,0}
>>> print(q[0, :])
[q_{0,0}, q_{0,1}, q_{0,2}]
>>> print(q[:, 0])
[q_{0,0}, q_{1,0}]
変数の下限値と上限値は発行時に一括で指定することができます。
>>> n = gen.array("Integer", shape=(5,), bounds=(1, 3))
>>> print(n)
[n_0, n_1, n_2, n_3, n_4]
2.4. 変数情報の取得¶
発行した変数から変数の情報を取得するには、as_variable()
メソッドを使います。
gen = VariableGenerator()
q = gen.scalar("Binary")
i = gen.scalar("Ising", name="i")
x = gen.scalar("Real", bounds=(2.0, 3.0))
>>> print(q.as_variable())
{name: q_0, id: 0, type: Binary}
変数の情報は Variable
クラスのインスタンスとして提供されます。Variable
クラスの持つアトリビュートは以下の通りです。
アトリビュート |
データ型 |
詳細 |
---|---|---|
変数名 |
||
変数の識別番号 |
||
変数の種類 |
||
[整数変数または実数変数のみ] 変数の下限値 |
||
[整数変数または実数変数のみ] 変数の上限値 |
また、VariableGenerator
クラスが発行した変数の情報は variables
プロパティで取得できます。
>>> vars = gen.variables
>>> vars
[Variable({name: q_0, id: 0, type: Binary}),
Variable({name: i, id: 1, type: Ising}),
Variable({name: x_0, id: 2, type: Real, lower_bound: 2, upper_bound: 3})]
変数の名前、下限値、上限値については後から変更することも可能です。
vars[2].name = "r"
vars[2].lower_bound = 0.0
vars[2].upper_bound = 1.0
>>> print(vars[2])
{name: r, id: 2, type: Real, lower_bound: 0, upper_bound: 1}
注意
scalar()
メソッドなどにより発行される変数は Poly
クラスのインスタンスです。 Poly
クラスは単一の変数だけでなく一般の多項式も表現できますが、as_variable()
メソッドは Poly
クラスのインスタンスが単項の変数を表すときのみ成功することに注意してください。
Tip
簡便のために、is_variable()
メソッドが True
を返す場合 (as_variable()
メソッドが成功する場合) は、Variable
クラスのアトリビュートに直接アクセスできます。
>>> q.is_variable()
True
>>> q.name
'q_0'
>>> q.id
0
>>> print(q.type)
Binary