Run on Jupyter Notebook
Sample codeIn this section, we introduce Amplify's features by programming an Ising machine using Amplify. For more information, see the official documentation.
A polynomial of $n$ number of binary variables, $f_n$, is expressed as follows:
$\displaystyle f_n(x_1, x_2, \cdots, x_n) = \sum_{\{k_1,k_2, \cdots, k_n\}}a_{k_1k_2\cdots k_n}x_1^{k_i}x_2^{k_2}\cdots x_n^{k_n}\,\quad k_i\in\{0, 1\}$
The $x_i$ is a binary variable, either a binary variable $q_i\in\{0,1\in\}$ or an Ising variable $s_i\in\{-1, +1\in\}$. Also, $a_{k_1k_2\cdots k_n}$ are the coefficients of the polynomial.
Amplify provides the following polynomial classes to represent binary multivariate polynomials.
BinaryPoly
(Polynomials with binary variables)IsingPoly
(Polynomials with Ising variables)Amplify can generate binary variables in the form of multi-dimensional arrays using
gen_symbols
. You can also generate polynomials by using operations of product
*
and sum +
on the generated binary variables.
from amplify import (
gen_symbols,
BinaryPoly,
)
# A one-dimensional array of four binary variables
q_1d = gen_symbols(BinaryPoly, 4)
# A 3x2 two-dimensional array of binary variables
q_2d = gen_symbols(BinaryPoly, 3, 2)
# A 3x2 two-dimensional array of binary variables with variable indices starting from 10
q_2d_2 = gen_symbols(BinaryPoly, 10, (3, 2))
print(f"q_1d = {q_1d}")
print(f"q_2d = {q_2d}")
print(f"q_2d_2 = {q_2d_2}")
It is also possible to generate polynomials using the variables you have defined, and to perform operations using the polynomials.
q = gen_symbols(BinaryPoly, 4)
# q_0 * q_1 + q_2
f0 = q[0] * q[1] + q[2]
# q_1 + q_3 + 1
f1 = q[1] + q[3] + 1
# (q_0 * q_1 + q_2) + (q_1 + q_3 + 1)
f2 = f0 + f1
# (q_1 + q_3 + 1) * (q_1 + q_3 + 1)
f3 = f1**2
print(f"f0 = {f0}")
print(f"f1 = {f1}")
print(f"f2 = {f2}")
print(f"f3 = {f3}")
The gen_symbols
function generates binary variables whose variable index starts at $0$ by
default. You can change the leading variable index by giving an offset as the second argument.
from amplify import (
gen_symbols,
BinaryPoly,
)
s1 = gen_symbols(BinaryPoly, 4)
s2 = gen_symbols(BinaryPoly, 4)
# If you don't shift the index, the same variables will be defined
print(s1, s2)
# Create variables by shifting the index by the length of s1
s3 = gen_symbols(BinaryPoly, len(s1), (4,))
# Different variables can be defined
print(s1, s3)
Amplify implements the following three functions as formulation aids for polynomial classes:
sum_poly()
: Equivalent to all sums $\sum_i$pair_sum()
: Equivalent to the sum of all combinations of functions $\sum_{i\neq j}$
product()
: Equivalent to all products $\prod_i$We show a few examples of how to use these formulation aids.
from amplify import sum_poly
# Generate 8 binary variables in 1D array format
q = gen_symbols(BinaryPoly, 8)
# Given a list of binary variables or polynomials, the sum of them can be calculated
f0 = sum_poly(q)
print(f"f0 = {f0}")
# Generate three binary variables
q = gen_symbols(BinaryPoly, 3)
# It is also possible to specify a function that takes an index and an upper limit for the index, and take the sum
f1 = sum_poly(3, lambda i: sum_poly(3, lambda j: q[i] * q[j]))
print(f"f1 = {f1}")
# Generate a 2x2 binary variable array
q = gen_symbols(BinaryPoly, 2, 2)
# Double sum of formulas involving squaring and quadrature
f2 = sum_poly(2, lambda i: (sum_poly(2, lambda j: q[i][j]) - 1) ** 2)
print(f"f2 = {f2}")
from amplify import pair_sum
# Generate three binary variables
q = gen_symbols(BinaryPoly, 3)
f3 = pair_sum(q)
print(f"f3 = {f3}")
from amplify import product
# Generate three binary variables
q = gen_symbols(BinaryPoly, 3)
f4 = product(q)
print(f"f4 = {f4}")
It is also possible to construct polynomials directly from the BinaryPoly
and
IsingPoly
polynomial constructors.
To create any term of a binary multivariate polynomial, a dictionary of the following form is put into the argument of the constructor of the above class.
$kx_{i}x_{j}\cdots x_{m} \rightarrow $ {(i, j, ..., m): k}
Multiple terms can also be combined into a dictionary form.
$k_2 x_ix_j + k_1 x_l + c \rightarrow $ {(i, j): k2, (l): k1, (): c)}
The following is a basic example:
from amplify import BinaryPoly
# q_0
f0 = BinaryPoly({(0): 1})
# 2 * q_0 * q_1 + 1
f1 = BinaryPoly({(0, 1): 2, (): 1})
print(f"f0 = {f0}")
print(f"f1 = {f1}")
When dealing with Ising polynomials, IsingPoly
.
from amplify import IsingPoly
# s_0
f0 = IsingPoly({(0): 1})
# 2 * s_0 * s_1 + 1
f1 = IsingPoly({(0, 1): 2, (): 1})
print(f"f0 = {f0}")
print(f"f1 = {f1}")