2. Creating Decision Variables¶
You must express the problem formulation in the program code to solve a combinatorial optimization problem with Amplify SDK. This page describes the first step in the formulation: generating the decision variables.
See also
To issue decision variables, you can also use the matrix()
method, as well as the methods described on this page, scalar()
and array()
of the VariableGenerator
class.
You can use the matrix()
method to create a quadratic objective function in a coefficient matrix format. See “Objective function with a coefficient matrix” for details.
2.1. Creating a variable generator¶
To formulate a combinatorial optimization problem, it is first necessary to create an instance of the VariableGenerator
class. This class provides methods for issuing decision variables.
from amplify import VariableGenerator
gen = VariableGenerator()
2.2. Variable generation¶
You can use the scalar()
method of the VariableGenerator
class to issue a new decision variable by specifying the variable type.
Variable type |
Description |
---|---|
A variable taking the value 0 or 1 |
|
A variable taking the value -1 or 1 |
|
A variable taking an integer value |
|
A variable taking a real value |
Following is an example of issuing a new binary variable. The variable is returned as an instance of the Poly
class, which represents the polynomial of the variable.
>>> q = gen.scalar("Binary")
>>> print(q)
q_0
Issued variables are automatically named, but you can also specify a name.
>>> i = gen.scalar("Ising", name="i")
>>> print(i)
i
Integer or real variables can have a range of possible values.
>>> x = gen.scalar("Real", bounds=(2.0, 3.0))
>>> print(x)
x_0
2.3. Creating an array of variables¶
If you want to create multiple variables at once, you can use the array()
method of the VariableGenerator
class. This method returns an array of variables in a NumPy-like multidimensional array format.
You can create an array of 3 binary variables as follows. Once the new variables are created, the variable names are automatically added with a string representing the array index.
>>> gen = VariableGenerator()
>>> q = gen.array("Binary", 3)
>>> print(q)
[q_0, q_1, q_2]
You can retrieve the elements and slices like a Python list
or 1D NumPy array.
>>> print(q[0])
q_0
>>> print(q[:2])
[q_0, q_1]
The array()
method of the VariableGenerator
class can also create multidimensional arrays. The following example creates a two-dimensional \(2 \times 3\) variable array.
>>> 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}]]
You can retrieve elements and slices in the same way as for a two-dimensional numpy.ndarray
. The retrieved element or slice will be the view of the original array.
>>> 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}]
You can specify the lower and upper bounds for variables simultaneously at output time.
>>> n = gen.array("Integer", shape=(5,), bounds=(1, 3))
>>> print(n)
[n_0, n_1, n_2, n_3, n_4]
2.4. Getting variable information¶
To get variable information from a given variable, use the as_variable()
method.
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}
The Amplify SDK provides variable information as an instance of the Variable
class, which has the following attributes.
Attribute |
Data type |
Details |
---|---|---|
Variable name |
||
Variable ID number |
||
Variable type |
||
[Integer or real variable only] Variable lower bound |
||
[Integer or real variable only] Variable upper bound |
Inverse conversion from Variable
class to Poly
class is also possible.
>>> from amplify import Poly
>>> v = x.as_variable()
>>> print(Poly(v))
x_0
In addition, information about variables issued by the VariableGenerator
class can be obtained using the variables
property.
>>> 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})]
You can change the variable’s name and lower and upper bounds later.
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}
Attention
The variables returned by the methods such as the scalar()
method are instances of the Poly
class. Note that the Poly
class can represent not only single variables but also general polynomials. However, the as_variable()
method will only succeed if the Poly
class instance represents a unary variable.
Tip
For convenience, when the is_variable()
method returns True
(as_variable()
method succeeds), you can access the attributes of the Variable
class directly.
>>> q.is_variable()
True
>>> q.name
'q_0'
>>> q.id
0
>>> print(q.type)
Binary
Tip
For each instance of the Poly
class, you can retrieve information about all of the variables contained in that instance with the variables
property; see “Polynomials and Objective Functions” for details about the Poly
class.
>>> q.variables
[Variable({name: q_0, id: 0, type: Binary})]
The methods and attributes for extracting Variable
class from each class instance are as follows.