Ising Hamiltonians
Given \(n\) qubits, a 2-local Ising Hamiltonian is an operator of the form:
where \(\sigma_{z}^{i} = \begin{pmatrix}1 & 0 \\ 0 & -1 \end{pmatrix}\), \(h\) is a vector of real coefficients usually referred to as the local magnetic field, and \(J\) is a real symmetric matrix with a zero diagonal, usually referred to as the coupling matrix.
This Hamiltonian is the direct quantization of the following classical Ising cost function:
where \(s_{i}\in \{-1,1\}\).
Note
In the interaction term, we do not restrict the sum to, e.g., \(i < j\). This is to make the computation of the Ising cost function more straightforward to write using, for instance, standard numpy functions.
For clarity and readability, we do not include any offset constant term in the definitions above. A definition including this term would be: \(- \sum_{i=1}^{n} h_{i}s_{i} - \sum_{i,j=1}^{n} J_{ij}s_{i}s_{j} + o\), with \(o\) the offset. Such a term does not change the optimization landscape, but might be needed if one wants to match values when converting Ising cost functions into QUBO instances and vice versa.
In the context of Ising Hamiltonians, qubits are also called spins.
Quantum annealing machines are typically designed to try and reach the minimum energy state of Ising Hamiltonians, also called ground state, relying on the Adiabatic Theorem. See for instance [AL18] for a general reference on adiabatic quantum computation.
Classical annealing codes like Simulated Quantum Annealing (SA) try and do the same thing: Given \(h\) and \(J\) as input, they will, starting from a random configuration, try to apply updates, as part of Markov chain over the configuration space, in order to look for low energy states, where “energy” is defined by the formulas above.
Note
A coupling value \(J > 0\) between two spins \(\sigma_{i}\) and \(\sigma_{j}\) can sometimes be called, in our convention, a ferromagnetic coupling, as the alignment of the two spins onto a same value will tend to lower the energy of the system making it closer to its ground state.
In other words, quantum annealing machines and, consequently, classical annealing codes, SA, aim at tackling the following optimization problem:
given \(h\) and \(J\) as input.
To produce such Ising-formulated problems, one can use the qat.opt.Ising
class:
import numpy as np
from qat.opt import Ising
problem_size = 6 # number of qubits for annealing, can reach to 100s even 1000s
# Problem-specific parameters for Ising
# Magnetic field h
np.random.seed(248)
h_field = np.random.rand(problem_size)
# J-coupling matrix
any_mat = np.random.rand(problem_size, problem_size)
j_mat = ((any_mat + np.transpose(any_mat)) / 2 # make it symmetric
- np.diag(np.diag(any_mat))) # make it with 0s as the diagonal elements
# Offset - can be 0
offset = 2.18
# Create an Ising problem
problem_Ising = Ising(J=j_mat,
h=h_field,
offset_i=offset)
print("Magnetic field h:")
print(problem_Ising.magnetic_field_h, "\n")
print("J-coupling matrix:")
print(problem_Ising.j_coupling_matrix)
# Create a job
problem_Ising_job = problem_Ising.to_job(job_type="sqa", tmax=tmax)
print("\nAn Ising Job has been created - ready to run on an annealing QPU.")
# Create an Ising Observable
problem_Ising_obs = problem_Ising.get_observable("ising")
print("An Ising Observable has also been created - to be fed in a Schedule from which a Job can also be produced.")
Magnetic field h:
[0.69198662 0.48503501 0.02913885 0.56996588 0.84630373 0.99216786]
J-coupling matrix:
[[0. 0.72490608 0.36270136 0.21518767 0.43237698 0.53659164]
[0.72490608 0. 0.43329047 0.63995666 0.75877295 0.67301865]
[0.36270136 0.43329047 0. 0.74051823 0.84432295 0.68663996]
[0.21518767 0.63995666 0.74051823 0. 0.76994591 0.78961076]
[0.43237698 0.75877295 0.84432295 0.76994591 0. 0.38143552]
[0.53659164 0.67301865 0.68663996 0.78961076 0.38143552 0. ]]
Traceback (most recent call last):
File "<stdin>", line 30, in <module>
NameError: name 'tmax' is not defined
It is also possible to translate the Ising problem to qat.opt.QUBO
via to_qubo()
or to CombinatorialProblem
via to_combinatorial_problem()
.
Ising problems can be further converted to both ising Observables and terms Observables, the second being used for gate-based or analog quantum computations.
Ising Observables
Ising problems come with a special ising-type of Observable
(not to be confused with
terms-type of Observables). Such an Observable can be created using the get_observable()
method of Ising (or the respective ones of QUBO
and CombinatorialProblem
). It can then enter
a Schedule
to be converted to a Job
for Simulated Annealing.
As long as two Ising Observables act on the same number of qubits, one can apply any of the basic arithmetic operations between them (just like for terms Observables) like addition, subtraction or multiplication and division by a factor. In each case the magnetic field, the J-coupling and the energy offset are treated separately. This further allows the aforementioned to be directly given to an Ising Observable.
Bibliography
- AL18
Tameem Albash and Daniel A Lidar. Adiabatic quantum computation. Reviews of Modern Physics, 90(1):015002, 2018. URL: https://journals.aps.org/rmp/abstract/10.1103/RevModPhys.90.015002.