Ising Hamiltonians

Given \(n\) qubits, a 2-local Ising Hamiltonian is an operator of the form:

\[H = - \sum_{i=1}^{n} h_{i}\sigma_{z}^{i} - \sum_{i,j=1}^{n} J_{ij}\sigma_{z}^{i}\sigma_{z}^{j}\]

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:

\[H(s_{1},...,s_{n}) = - \sum_{i=1}^{n} h_{i}s_{i} - \sum_{i,j=1}^{n} J_{ij}s_{i}s_{j}\]

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.

Our classical annealing codes (see Simulated Quantum Annealing (SQA)) 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, SQA, aim at tackling the following optimization problem:

\[\min_{s_{1}...s_{n}\in \{-1,1\}} \left(- \sum_{i=1}^{n} h_{i}s_{i} - \sum_{i,j=1}^{n} J_{ij}s_{i}s_{j}\right)\]

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
from qat.core.variables import Variable

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 by specifying the gamma function (needed for SQA)
t_var = Variable("t")
tmax = 1.23
gamma_max = 170.89 # it is usually problem-specific
gamma_t_fun = gamma_max * (1 - t_var / tmax)  # linear decrease to 0 at t=tmax
problem_Ising_job = problem_Ising.to_job(job_type="sqa", gamma_t=gamma_t_fun, 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 (together with gamma_t) 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.        ]]

An Ising Job has been created - ready to run on an annealing QPU.
An Ising Observable has also been created - to be fed in a Schedule (together with gamma_t) from which a Job can also be produced.

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 (together with a gamma_t for SQAQPU) to be converted to a Job for Simulated Quantum 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.