2. 決定変数の作り方

Amplify SDK を使用して組合せ最適化問題を解くためには、問題の定式化をプログラムコード上で表現することが必要です。 このページでは、定式化の最初のステップとして、決定変数の生成について解説します。

参考

変数を発行する方法としては、このページで解説する VariableGenerator クラスの scalar() および array() メソッドのほかに matrix() メソッドが提供されています。 二次の目的関数を係数行列形式で作成したい場合はこのメソッドを用いることができます。詳細は「係数行列による目的関数の作成」を参照してください。

2.1. 変数ジェネレータの作成

組合せ最適化問題の定式化を行うには、最初に VariableGenerator クラスのインスタンスを作成することが必要です。このクラスは決定変数を発行するためのメソッドを提供します。

from amplify import VariableGenerator

gen = VariableGenerator()

2.2. 変数の生成

VariableGenerator クラスの scalar() メソッドを使うと、変数の種類を指定して新しい変数が発行できます。Amplify SDK で指定できる変数の種類は以下の表の通りです。

変数種別

詳細

Binary

0 または 1 の値をとる変数

Ising

-1 または 1 の値をとる変数

Integer

整数値をとる変数

Real

実数値をとる変数

次のようにして新しくバイナリ変数を発行します。
変数は変数の多項式を表す 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. 変数配列の作成

複数個の変数を一括で生成したい場合、VariableGeneratorarray() メソッドを使うことができます。 このメソッドは、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]

VariableGeneratorarray() メソッドは多次元の配列も作成することができます。以下の例では、 \(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]

参考

array() メソッドは多項式配列を表す PolyArray クラスのインスタンスを返します。 PolyArray クラスには要素の取得やスライス以外にも ndarray と互換性のあるさまざまなメソッドが提供されています。 詳細はPolyArray クラスのリファレンスを参照してください。

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 クラスの持つアトリビュートは以下の通りです。

アトリビュート

データ型

詳細

name

str

変数名

id

int

変数の識別番号
発行された順に0 から始まる整数値が割り当てられます

type

VariableType

変数の種類

lower_bound

float

[整数変数または実数変数のみ] 変数の下限値
None\(- \inf\) を意味する

upper_bound

float

[整数変数または実数変数のみ] 変数の上限値
None\(+ \inf\) を意味する

Variable クラスから Poly クラスに逆変換することも可能です。

>>> from amplify import Poly
>>> v = x.as_variable()
>>> print(Poly(v))
x_0

また、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

Tip

任意の Poly クラスのインスタンスに対して、そのインスタンスに含まれるすべての変数の情報を variables プロパティにより取得することができます。Poly クラスの詳細は「多項式と目的関数」を参照してください。

>>> q.variables
[Variable({name: q_0, id: 0, type: Binary})]

なお、各クラスのインスタンスから Variable クラスを取得するメソッドまたはアトリビュートは以下のようなものがあります。