Hamiltonians#

The main abstract Hamiltonian object of Qibo is:

class qibo.hamiltonians.abstract.AbstractHamiltonian[source]#

Qibo abstraction for Hamiltonian objects.

abstract property matrix#

Return the full matrix representation.

For \(n\) qubits, can be a dense \(2^{n} \times 2^{n}\) array or a sparse matrix, depending on how the Hamiltonian was created.

abstract eigenvalues(k=6)[source]#

Computes the eigenvalues for the Hamiltonian.

Parameters:

k (int) – Number of eigenvalues to calculate if the Hamiltonian was created using a sparse matrix. This argument is ignored if the Hamiltonian was created using a dense matrix. See qibo.backends.abstract.AbstractBackend.eigvalsh() for more details.

abstract eigenvectors(k=6)[source]#

Computes a tensor with the eigenvectors for the Hamiltonian.

Parameters:

k (int) – Number of eigenvalues to calculate if the Hamiltonian was created using a sparse matrix. This argument is ignored if the Hamiltonian was created using a dense matrix. See qibo.backends.abstract.AbstractBackend.eigh() for more details.

ground_state()[source]#

Computes the ground state of the Hamiltonian.

Uses qibo.hamiltonians.AbstractHamiltonian.eigenvectors() and returns eigenvector corresponding to the lowest energy.

abstract exp(a)[source]#

Computes a tensor corresponding to \(\exp(-i \, a \, H)\).

Parameters:

a (complex) – Complex number to multiply Hamiltonian before exponentiation.

abstract expectation(circuit, nshots=None)[source]#

Computes the expectation value for a given circuit.

Parameters:
  • circuit (Circuit) – circuit to calculate the expectation value from. If the circuit has already been executed, this will just make use of the cached result, otherwise it will execute the circuit.

  • nshots (int, optional) – number of shots to calculate the expectation value, if None it will try to compute the exact expectation value (if possible). Defaults to None.

Returns:

The expectation value.

Return type:

float

expectation_from_state(state, normalize=False)[source]#

Compute the expectation value starting from a quantum state.

Parameters:
  • state (ArrayLike) – the quantum state.

  • normalize (bool, optional) – whether to normalize the input state. Defaults to False.

Returns:

The expectation value.

Return type:

float

Matrix Hamiltonian#

The first implementation of Hamiltonians uses the full matrix representation of the Hamiltonian operator in the computational basis. For \(n\) qubits, this matrix has size \(2^{n} \times 2^{n}\). Therefore, its construction is feasible only when \(n\) is small.

Alternatively, the user can construct this Hamiltonian using a sparse matrices. Sparse matrices from the scipy.sparse module are supported by the numpy and qibojit backends while the tensorflow.sparse can be used for tensorflow. Scipy sparse matrices support algebraic operations (addition, subtraction, scalar multiplication), linear algebra operations (eigenvalues, eigenvectors, matrix exponentiation) and multiplication to dense or other sparse matrices. All these properties are inherited by qibo.hamiltonians.Hamiltonian objects created using sparse matrices. Tensorflow sparse matrices support only multiplication to dense matrices. Both backends support calculating Hamiltonian expectation values using a sparse Hamiltonian matrix.

class qibo.hamiltonians.Hamiltonian(nqubits, matrix, backend=None)[source]#

Hamiltonian based on a dense or sparse matrix representation.

Parameters:
  • nqubits (int) – number of quantum bits.

  • matrix (ArrayLike) – Matrix representation of the Hamiltonian in the computational basis as an array of shape \(2^{n} \times 2^{n}\). Sparse matrices based on scipy.sparse for numpy / qibojit backends (or on tf.sparse for the tensorflow backend) are also supported.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

property matrix: ArrayLike#

Returns the full matrix representation.

For \(n\) qubits, can be a dense \(2^{n} \times 2^{n}\) array or a sparse matrix, depending on how the Hamiltonian was created.

eigenvalues(k=6)[source]#

Computes the eigenvalues for the Hamiltonian.

Parameters:

k (int) – Number of eigenvalues to calculate if the Hamiltonian was created using a sparse matrix. This argument is ignored if the Hamiltonian was created using a dense matrix. See qibo.backends.abstract.AbstractBackend.eigvalsh() for more details.

Return type:

ArrayLike

eigenvectors(k=6)[source]#

Computes a tensor with the eigenvectors for the Hamiltonian.

Parameters:

k (int) – Number of eigenvalues to calculate if the Hamiltonian was created using a sparse matrix. This argument is ignored if the Hamiltonian was created using a dense matrix. See qibo.backends.abstract.AbstractBackend.eigh() for more details.

Return type:

ArrayLike

exp(a)[source]#

Computes a tensor corresponding to \(\exp(-i \, a \, H)\).

Parameters:

a (complex) – Complex number to multiply Hamiltonian before exponentiation.

Return type:

ArrayLike

expectation(circuit, nshots=None, qubit_map=None)[source]#

Computes the expectation value for a given circuit. This works only for diagonal observables if nshots != None.

Parameters:
  • circuit (qibo.models.circuit.Circuit) – circuit to calculate the expectation value from. If the circuit has already been executed, this will just make use of the cached result, otherwise it will execute the circuit.

  • nshots (int, optional) – number of shots to calculate the expectation value, if None it will try to compute the exact expectation value (if possible). Defaults to None.

  • qubit_map (dict | None) –

Returns:

The expectation value.

Return type:

float

expectation_from_samples(frequencies, qubit_map=None)[source]#

Compute the expectation value starting from some samples, works only for diagonal observables.

Parameters:
  • frequencies (Dict[str | int, int]) – the dictionary of samples.

  • qubit_map (Tuple[int, ...], optional) – optional qubit reordering.

Returns:

The expectation value.

Return type:

float

energy_fluctuation(circuit)[source]#

Evaluate energy fluctuation:

\[\Xi_{k}(\mu) = \sqrt{\bra{\mu} \, H^{2} \, \ket{\mu} - \bra{\mu} \, H \, \ket{\mu}^2} \, .\]

for a given state \(\ket{\mu}\).

Parameters:

circuit (qibo.models.circuit.Circuit) – circuit to compute the energy fluctuation from.

Returns:

Energy fluctuation value.

Return type:

float

Symbolic Hamiltonian#

Qibo allows the user to define Hamiltonians using sympy symbols. In this case the full Hamiltonian matrix is not constructed unless this is required. This makes the implementation more efficient for larger qubit numbers. For more information on constructing Hamiltonians using symbols we refer to the How to define custom Hamiltonians using symbols? example.

class qibo.hamiltonians.SymbolicHamiltonian(form, nqubits=None, backend=None)[source]#

Hamiltonian based on a symbolic representation.

Calculations using symbolic Hamiltonians are either done directly using the given sympy expression as it is (form) or by parsing the corresponding terms (which are qibo.core.terms.SymbolicTerm objects). The latter approach is more computationally costly as it uses a sympy.expand call on the given form before parsing the terms. For this reason the terms are calculated only when needed, for example during Trotterization. The dense matrix of the symbolic Hamiltonian can be calculated directly from form without requiring terms calculation (see qibo.core.hamiltonians.SymbolicHamiltonian.calculate_dense() for details).

Parameters:
property dense: Hamiltonian#

Creates the equivalent Hamiltonian matrix.

property terms: list#

List of terms of which the Hamiltonian is a sum of.

Terms will be objects of type qibo.core.terms.HamiltonianTerm.

property simple_terms: tuple[list[float], list[str], list[tuple[int, ...]]]#

A simpler (more framework agnostic) representation of the of terms composing the Hamiltonian, defined as: their scalar coefficients, the strings of the names of their observables and the qubits they act on

Returns:

(Tuple[List[float], List[str], List[Tuple[int, …]]])

property diagonal_terms: list[list[qibo.hamiltonians.terms.SymbolicTerm]]#

List of terms that can be diagonalized simultaneously, i.e. that commute with each other. In detail each element of the list is a sublist of commuting qibo.hamiltonians.terms.SymbolicTerm terms.

property diagonal_simple_terms: tuple[list[list[float]], list[list[str]], list[list[tuple[int, ...]]]]#

A simpler (more framework agnostic) representation of the simultaneously diagonalizable terms of the hamiltonian, defined as: their scalar coefficients, the strings of the names of their observables and the qubits they act on.

Returns:

Tuple[List[List[float]], List[List[str]], List[List[Tuple[int, …]]]]

property matrix: ArrayLike#

Returns the full matrix representation.

Consisting of \(2^{n} \times 2^{n}`\) elements.

eigenvalues(k=6)[source]#

Computes the eigenvalues for the Hamiltonian.

Parameters:

k (int) – Number of eigenvalues to calculate if the Hamiltonian was created using a sparse matrix. This argument is ignored if the Hamiltonian was created using a dense matrix. See qibo.backends.abstract.AbstractBackend.eigvalsh() for more details.

Return type:

ArrayLike

eigenvectors(k=6)[source]#

Computes a tensor with the eigenvectors for the Hamiltonian.

Parameters:

k (int) – Number of eigenvalues to calculate if the Hamiltonian was created using a sparse matrix. This argument is ignored if the Hamiltonian was created using a dense matrix. See qibo.backends.abstract.AbstractBackend.eigh() for more details.

Return type:

ArrayLike

ground_state()[source]#

Computes the ground state of the Hamiltonian.

Uses qibo.hamiltonians.AbstractHamiltonian.eigenvectors() and returns eigenvector corresponding to the lowest energy.

Return type:

ArrayLike

exp(a)[source]#

Computes a tensor corresponding to \(\exp(-i \, a \, H)\).

Parameters:

a (complex) – Complex number to multiply Hamiltonian before exponentiation.

Return type:

ArrayLike

expectation(circuit, nshots=None)[source]#

Computes the expectation value for a given circuit.

Parameters:
  • circuit (qibo.models.circuit.Circuit) – circuit to calculate the expectation value from. If the circuit has already been executed, this will just make use of the cached result, otherwise it will execute the circuit.

  • nshots (int, optional) – number of shots to calculate the expectation value, if None it will try to compute the exact expectation value (if possible). Defaults to None.

Returns:

The expectation value.

Return type:

float

expectation_from_samples(frequencies, qubit_map=None)[source]#

Compute the expectation value starting from some samples, works only for diagonal observables.

Parameters:
  • frequencies (Dict[str | int, int]) – the dictionary of samples.

  • qubit_map (Tuple[int, ...], optional) – optional qubit reordering.

Returns:

The expectation value.

Return type:

float

apply_gates(state, density_matrix=False)[source]#

Applies gates corresponding to the Hamiltonian terms.

Gates are applied to the given state.

Helper method for qibo.hamiltonians.SymbolicHamiltonian.__matmul__().

Parameters:
  • state (ArrayLike) –

  • density_matrix (bool) –

circuit(dt, accelerators=None)[source]#

Circuit that implements a Trotter step of this Hamiltonian.

Parameters:
  • dt (float) – Time step used for Trotterization.

  • accelerators (dict, optional) – Dictionary with accelerators for distributed circuits. Defaults to None.

When a qibo.hamiltonians.SymbolicHamiltonian is used for time evolution then Qibo will automatically perform this evolution using the Trotter of the evolution operator. This is done by automatically splitting the Hamiltonian to sums of commuting terms, following the description of Sec. 4.1 of arXiv:1901.05824. For more information on time evolution we refer to the How to simulate time evolution? example.

In addition to the abstract Hamiltonian models, Qibo provides the following pre-coded Hamiltonians:

Non-interacting Pauli-X#

class qibo.hamiltonians.X(nqubits, dense=True, backend=None)[source]#

Non-interacting Pauli-\(X\) Hamiltonian.

\[H = - \sum _{k=0}^N \, X_{k} \, .\]
Parameters:
  • nqubits (int) – number of qubits.

  • dense (bool, optional) – If True it creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Return type:

Hamiltonian | SymbolicHamiltonian

Non-interacting Pauli-Y#

class qibo.hamiltonians.Y(nqubits, dense=True, backend=None)[source]#

Non-interacting Pauli-\(Y\) Hamiltonian.

\[H = - \sum _{k=0}^{N} \, Y_{k} \, .\]
Parameters:
  • nqubits (int) – number of qubits.

  • dense (bool, optional) – If True it creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Return type:

Hamiltonian | SymbolicHamiltonian

Non-interacting Pauli-Z#

class qibo.hamiltonians.Z(nqubits, dense=True, backend=None)[source]#

Non-interacting Pauli-\(Z\) Hamiltonian.

\[H = - \sum _{k=0}^{N} \, Z_{k} \, .\]
Parameters:
  • nqubits (int) – number of qubits.

  • dense (bool, optional) – If True it creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Return type:

Hamiltonian | SymbolicHamiltonian

Ising model#

class qibo.hamiltonians.Ising(nqubits, coupling_constants, local_field_strengths, dense=True, closed_boundary=True, backend=None)[source]#

Ising model on a one-dimensional chain or on a lattice with arbitrary connectivity.

\[H = \sum_{\langle j, \, k \rangle} \, J_{jk} \, Z_{j} \, Z_{k} + \sum_{j} h_{j}^{(z)} \, Z_{j} + \sum_{j} h_{j}^{(x)} \, X_{j} \, ,\]

where \(\langle j, \, k \rangle\) runs over all pairs of coupled (i.e., connected) qubits, \(\{J_{jk}\}_{j,k}\) are called the coupling constants, \(\{h_{j}^{(z)}, h_{j}^{(x)}\}_{j}\) are called the local field strengths, and \(\{X, \, Y, \, Z\}\) are the usual Pauli operators.

If nqubits is an int, the qubits form a one-dimensional chain and \(\langle j, \, k \rangle\) runs over the nearest neighbors \((j, \, j + 1)\), with \(J_{jk} \equiv J_{j}\). The pair \((n - 1, \, 0)\) is also coupled if closed_boundary=True.

For an arbitrary connectivity, nqubits can be a networkx.Graph, in which every node is a qubit and every edge is a pair of coupled qubits. If the nodes of the graph are exactly the integers \(\{0, \, 1, \, \dots, \, n - 1\}\), every node is its own qubit label \(j\). Otherwise, qubits are labeled by the order in which the nodes are stored in the graph, i.e., the \(j\)-th node of list(nqubits.nodes) has label \(j\). The graph defines all the bonds of the model. Therefore, closed_boundary is ignored, and any periodicity must be encoded as edges of the graph. Isolated nodes are qubits with no coupling, and self-loops are not allowed.

The graph can be weighted. The coupling constant of the bond between qubits \(j\) and \(k\) is \(J_{jk} = J \, w_{j,k}\), where \(J\) is coupling_constants and \(w_{j,k}\) is the "weight" attribute of the corresponding edge. Edges without this attribute have weight \(1\), and therefore an unweighted graph has a uniform coupling constant \(J\). Edge directions are ignored. Edges between the same pair of nodes, e.g., parallel edges of a multigraph, are merged into a single bond, and they must have the same weight. The local field strengths are indexed by the qubit label.

Parameters:
  • nqubits (int or networkx.Graph) – if an int, number of qubits in a one-dimensional chain. If a networkx.Graph, connectivity graph of the qubits, with one node per qubit and, optionally, a "weight" attribute per edge that scales coupling_constants.

  • coupling_constants (float or int or ArrayLike) – list or ndarray containing all coupling constants \(\{J_{k}\}_{k}\) of the chain. If int or float, then \(J_{k}\) is equal to coupling_constants for all \(k\). If nqubits is a networkx.Graph, it must be an int or float.

  • local_field_strengths (list or tuple or float or int) – array containing all local field strengths \(\left\{\left(h_{j}^{(z)}, \, h_{j}^{(x)}\right)\right\}_{j}\), e.g., \(\left\{h_{j}^{(z)}\right\}_{j}\) in the first column and \(\left\{h_{j}^{(x)}\right\}_{j}\) in the second column. If int or float, the coefficients \(h_{j}^{(z)}\) and \(h_{j}^{(x)}\) are equal to local_field_strengths, \(\forall \, j\). If Tuple[int, int], \(h_{j}^{(z)}\) \(\left(h_{j}^{(x)}\right)\) is set to the first (second) element of the tuple, \(\forall \, j\).

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • closed_boundary (bool, optional) – If True, returns Ising Hamiltonian with periodic boundary condition. If False, returns Hamiltonian with open boundaries. Ignored if nqubits is a networkx.Graph. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Ising Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

Transverse-field Ising model#

class qibo.hamiltonians.TFIM(nqubits, h=0.0, dense=True, closed_boundary=True, backend=None)[source]#

One-dimensional, \(n\)-qubit Transverse field Ising model.

\[H = - \sum _{k=0}^{n-1} \, \left(Z_{k} \, Z_{k + 1} + h \, X_{k}\right) \, ,\]

with \(Z_{n-1} Z_{n} \equiv Z_{n-1} Z_{0}\) if closed_boundary=True.

It is the qibo.hamiltonians.Ising model with coupling constants \(-1\) and local field strengths \((0, \, -h)\).

Parameters:
  • nqubits (int) – number of qubits.

  • h (float, optional) – value of the transverse field. Defaults to \(0.0\).

  • dense (bool, optional) – If True it creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • closed_boundary (bool, optional) – If True, returns TFIM with periodic boundary condition. If False, returns Hamiltonian with open boundaries. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Return type:

Hamiltonian | SymbolicHamiltonian

Axial next-nearest-neighbor Ising model#

class qibo.hamiltonians.ANNNI(nqubits, j1=1.0, j2=0.5, h=0.0, dense=True, closed_boundary=True, backend=None)[source]#

Axial next-nearest-neighbor Ising (ANNNI) model in a transverse field.

\[H = -J_{1} \sum_{j} Z_{j} \, Z_{j+1} + J_{2} \sum_{j} Z_{j} \, Z_{j+2} - h \sum_{j} X_{j} \, ,\]

where \(J_{1}\) and \(J_{2}\) are the nearest- and next-nearest-neighbor couplings, respectively, and \(h\) is the transverse field strength. For \(J_{1}, J_{2} > 0\), the first interaction is ferromagnetic and the second one is antiferromagnetic. They compete with each other, and the frustration is controlled by \(\kappa = J_{2} / J_{1}\).

With open boundaries, the sums run over all pairs of qubits that are one and two sites apart along the chain. With periodic boundaries, i.e., closed_boundary=True, the chain is a ring, and every pair of qubits is coupled at most once. Therefore, for nqubits=3 all pairs are nearest neighbors, and \(J_{2}\) has no effect.

The ANNNI model is the qibo.hamiltonians.Ising model on a graph with edge weights \(-J_{1}\) and \(J_{2}\). For \(J_{2} = 0\) and \(J_{1} = 1\), it reduces to the transverse-field Ising model qibo.hamiltonians.TFIM().

Parameters:
  • nqubits (int) – number of qubits. Must be larger than two.

  • j1 (float, optional) – nearest-neighbor coupling \(J_{1}\). Defaults to \(1.0\).

  • j2 (float, optional) – next-nearest-neighbor coupling \(J_{2}\). Defaults to \(0.5\).

  • h (float, optional) – transverse field strength \(h\). Defaults to \(0.0\).

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • closed_boundary (bool, optional) – If True, returns the Hamiltonian with periodic boundary conditions. If False, returns the Hamiltonian with open boundaries. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

ANNNI Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. W. Selke, The ANNNI model - Theoretical analysis and experimental application, Phys. Rep. 170, 213 (1988).

Cluster-Ising model#

class qibo.hamiltonians.ClusterIsing(nqubits, cluster_strength=1.0, ising_strength=0.0, field_strength=0.0, dense=True, closed_boundary=True, backend=None)[source]#

Cluster-Ising model.

\[H = -J_{c} \sum_{j} Z_{j-1} \, X_{j} \, Z_{j+1} - J \sum_{j} Z_{j} \, Z_{j+1} - h \sum_{j} X_{j} \, ,\]

where the first term is the three-body cluster interaction, and the other two terms are the transverse-field Ising model. For \(J = h = 0\), the ground states are cluster states, which are symmetry-protected topological states. The Ising interaction breaks the symmetry, i.e., competes with the cluster interaction.

With periodic boundaries, i.e., closed_boundary=True, the sums run over all qubits. With open boundaries, the cluster interaction is centered on the qubits \(j = 1, \, \dots, \, n - 2\), and the Ising interaction couples \(j = 0, \, \dots, \, n - 2\).

The cluster-Ising model is the sum of the cluster interaction and the qibo.hamiltonians.Ising model with coupling constant \(-J\) and local field strengths \((0, \, -h)\). For \(J_{c} = 0\), it reduces to the Ising model, and to the transverse-field Ising model qibo.hamiltonians.TFIM() if, in addition, \(J = 1\).

Note

Ref. [1] introduces the cluster-Ising model with the Ising-like interaction being an antiferromagnetic coupling along the \(y\)-axis, which is orthogonal to the axes of the cluster interaction \(X_{j-1} \, Z_{j} \, X_{j+1}\). Here, the Ising interaction is along the \(Z\)-axis of the cluster interaction and the field is along the \(X\)-axis, so that the model is the sum of the cluster interaction and qibo.hamiltonians.Ising.

Parameters:
  • nqubits (int) – number of qubits. Must be larger than two.

  • cluster_strength (float, optional) – strength \(J_{c}\) of the cluster interaction. Defaults to \(1.0\).

  • ising_strength (float, optional) – strength \(J\) of the Ising interaction. Defaults to \(0.0\).

  • field_strength (float, optional) – strength \(h\) of the transverse field. Defaults to \(0.0\).

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • closed_boundary (bool, optional) – If True, returns the Hamiltonian with periodic boundary conditions. If False, returns the Hamiltonian with open boundaries. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Cluster-Ising Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. P. Smacchia, L. Amico, P. Facchi, R. Fazio, G. Florio, S. Pascazio, and V. Vedral, Statistical mechanics of the cluster-Ising model, Phys. Rev. A 84, 022304 (2011).

Spin glass#

The spin glass model covers both the Sherrington-Kirkpatrick (SK) model, with all-to-all connectivity, and the Edwards-Anderson (EA) model, with connectivity given by a graph.

class qibo.hamiltonians.SpinGlass(nqubits, coupling_constant=1.0, local_field_strengths=0.0, distribution='gaussian', seed=None, dense=True, backend=None)[source]#

Ising spin glass model, i.e., Ising model with random couplings.

\[H = \sum_{\langle j, \, k \rangle} J_{jk} \, Z_{j} \, Z_{k} + \sum_{j} h_{j}^{(z)} \, Z_{j} + \sum_{j} h_{j}^{(x)} \, X_{j} \, ,\]

where \(\langle j, \, k \rangle\) runs over all pairs of coupled qubits, \(\{J_{jk}\}_{j,k}\) are independent random variables with zero mean, and \(\{h_{j}^{(z)}, h_{j}^{(x)}\}_{j}\) are the local field strengths. Without \(X\) fields, it is a classical spin glass. Otherwise, it is a quantum spin glass.

This function covers the two canonical spin glass models, which differ in the connectivity of the qubits:

  • Sherrington-Kirkpatrick (SK) model, if nqubits is an int. Every pair of qubits is coupled (infinite-range model), and the couplings have standard deviation \(J / \sqrt{n}\), where \(J\) is coupling_constant and \(n\) is the number of qubits, so that the energy is extensive.

  • Edwards-Anderson (EA) model, if nqubits is a networkx.Graph. Only the qubits connected by an edge of the graph are coupled (short-range model, e.g., networkx.grid_2d_graph() for a two-dimensional lattice), and the couplings have standard deviation \(J\).

The graph follows the same conventions as in qibo.hamiltonians.Ising, i.e., the qubit labels, the isolated nodes and the "weight" edge attribute. The coupling of an edge with weight \(w_{jk}\) is \(J_{jk} = J \, w_{jk} \, \xi_{jk}\), where \(\xi_{jk}\) is a random variable with zero mean and unit variance. The random variables are drawn in a single call, one per bond, following the lexicographic order of the bonds \((j, \, k)\), with \(j < k\) the qubit labels.

The spin glass is the qibo.hamiltonians.Ising model on a graph with random edge weights.

Parameters:
  • nqubits (int or networkx.Graph) – if an int, number of qubits of the fully connected SK model. If a networkx.Graph, connectivity graph of the EA model, with one node per qubit and, optionally, a "weight" attribute per edge.

  • coupling_constant (float, optional) – energy scale \(J\) of the couplings. Defaults to \(1.0\).

  • local_field_strengths (list or tuple or float or int, optional) – local field strengths \(\left\{\left(h_{j}^{(z)}, \, h_{j}^{(x)}\right)\right\}_{j}\), following the same conventions as in qibo.hamiltonians.Ising. Defaults to \(0.0\).

  • distribution (str, optional) – distribution of the random variables \(\xi_{jk}\). If "gaussian", they follow a standard normal distribution. If "bimodal", they are \(\pm 1\) with equal probability (\(\pm J\) model). Defaults to "gaussian".

  • seed (int or numpy.random.Generator, optional) – Either a generator of random numbers or a fixed seed to initialize a generator. If None, initializes a generator with a random seed. Defaults to None.

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Spin glass Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. S. F. Edwards and P. W. Anderson, Theory of spin glasses, J. Phys. F: Met. Phys. 5, 965 (1975).

2. D. Sherrington and S. Kirkpatrick, Solvable model of a spin-glass, Phys. Rev. Lett. 35, 1792 (1975).

Max Cut#

class qibo.hamiltonians.MaxCut(nqubits, dense=True, adj_matrix=None, backend=None)[source]#

Max Cut Hamiltonian.

\[H = -\frac{1}{2} \, \sum_{j, k = 0}^{n - 1} \, A_{jk} \, \left(1 - Z_{j} \, Z_{k}\right) \, ,\]

where \(A\) is the adjacency matrix of the graph. Up to a constant energy shift, this is the qibo.hamiltonians.Ising Hamiltonian, without local fields, on the graph with weights \(w_{jk} = (A_{jk} + A_{kj}) / 2\) for \(j \neq k\), i.e.,

\[H = \sum_{j < k} \, w_{jk} \, Z_{j} \, Z_{k} - \sum_{j < k} \, w_{jk} \, .\]
Parameters:
  • nqubits (int) – number of qubits.

  • dense (bool) – If True it creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian.

  • adj_matrix (list[list[float]] | np.ndarray) – Adjecency matrix of the graph. Defaults to a homogeneous fully connected graph with all edges having an equal 1.0 weight.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Return type:

Hamiltonian | SymbolicHamiltonian

LABS#

class qibo.hamiltonians.LABS(nqubits, dense=True, backend=None)[source]#

Create Hamiltonian of the Low Autocorrelation Binary Sequences (LABS) problem.

Given an integer \(n > 2\), the LABS problem consists of finding a binary sequence \(b \in \{0, \, 1\}^{n}\) the minimizes the sidelobe energy \(E(b)\) defined as

\[E(b) = \sum_{j=1}^{n-1} \, C_{j}^{2}(b) \, ; \quad C_{j}(b) = \sum_{k=0}^{n-j} \, b_{k} \, b_{k + j} \, ,\]

where \(C_{j}(b)\) is the \(j\)-th autocorrelation of \(b\).

Parameters:
  • nqubits (int) – Total number of qubits.

  • dense (bool, optional) – If True it creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Return type:

Hamiltonian | SymbolicHamiltonian

References

1. T. Packebusch and S. Mertens, Low autocorrelation binary sequences, J. Phys. A: Math. Theor. 49 (2016) 165001.

Maximum independent set#

class qibo.hamiltonians.MaxIndependentSet(graph, penalty_coeff=2.0, dense=True, backend=None)[source]#

Maximum Independent Set (MIS) problem as a QUBO.

An independent set of a graph is a subset of its nodes in which no two nodes are connected by an edge. The MIS problem consists of finding the largest independent set, which can be formulated as minimizing the objective function

\[C(x) = -\sum_{j} x_{j} + \lambda \sum_{(j, \, k) \in E} x_{j} \, x_{k} \, ,\]

where \(x_{j} \in \{0, \, 1\}\) is equal to \(1\) if node \(j\) belongs to the set, \(E\) is the set of edges of the graph, and \(\lambda\) is the penalty coefficient that discourages the selection of connected nodes. For \(\lambda > 1\), every ground state is a maximum independent set, and the ground state energy is minus its size.

The Hamiltonian is built by qibo.hamiltonians.QUBO, and its eigenvalue on the computational basis state \(|x\rangle\) is \(C(x)\). The labels of the qubits follow the same convention as in qibo.hamiltonians.Ising: if the nodes of the graph are exactly the integers \(\{0, \, 1, \, \dots, \, n - 1\}\), every node is its own qubit label. Otherwise, qubits are labeled by the order in which the nodes are stored in the graph. The weights of the edges are ignored.

Parameters:
Returns:

Maximum independent set Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. A. Lucas, Ising formulations of many NP problems, Front. Phys. 2, 5 (2014).

Number partitioning#

class qibo.hamiltonians.NumberPartitioning(numbers, dense=True, backend=None)[source]#

Number partitioning problem.

Given a set of numbers \(\{a_{j}\}_{j=0}^{n-1}\), the problem consists of dividing it into two subsets such that the difference between the sums of their elements is minimal. Assigning \(s_{j} = +1\) or \(s_{j} = -1\) to every number, depending on the subset it belongs to, the problem is the minimization of

\[H = \left( \sum_{j} a_{j} \, Z_{j} \right)^{2} = \sum_{j} a_{j}^{2} + 2 \sum_{j < k} a_{j} \, a_{k} \, Z_{j} \, Z_{k} \, ,\]

which is the qibo.hamiltonians.Ising model, without local fields, on the complete graph with weights \(w_{jk} = 2 \, a_{j} \, a_{k}\), plus a constant. It is built as a qibo.hamiltonians.QUBO in the variables \(x_{j} = (1 - Z_{j}) / 2\), with matrix \(Q_{jk} = 4 \, a_{j} \, a_{k} - 4 \, \delta_{jk} \, a_{j} \sum_{l} a_{l}\) and constant \((\sum_{j} a_{j})^{2}\). The eigenvalue of \(H\) on every computational basis state is the squared difference between the sums of the two subsets. Hence, the ground state energy is \(0\) if, and only if, a perfect partition exists.

Parameters:
Returns:

Number partitioning Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. A. Lucas, Ising formulations of many NP problems, Front. Phys. 2, 5 (2014).

QUBO#

class qibo.hamiltonians.QUBO(matrix, dense=True, backend=None)[source]#

Quadratic unconstrained binary optimization (QUBO) problem.

Given a real \(n \times n\) matrix \(Q\), the QUBO problem consists of minimizing

\[C(x) = \sum_{j, k} Q_{jk} \, x_{j} \, x_{k} \, ,\]

over the binary variables \(x \in \{0, \, 1\}^{n}\). Since \(x_{j}^{2} = x_{j}\), the diagonal of \(Q\) is the linear part of the objective function. Only the symmetric part of \(Q\) is relevant for the off-diagonal terms, because \(Q_{jk}\) and \(Q_{kj}\) multiply the same product \(x_{j} \, x_{k}\).

The Hamiltonian is obtained with the substitution \(x_{j} \to (1 - Z_{j}) / 2\), which gives the qibo.hamiltonians.Ising model

\[H = \sum_{j < k} J_{jk} \, Z_{j} \, Z_{k} + \sum_{j} h_{j} \, Z_{j} + c \, ,\]

with \(J_{jk} = (Q_{jk} + Q_{kj}) / 4\), \(h_{j} = -Q_{jj} / 2 - \sum_{k \neq j} J_{jk}\), and the constant \(c = \sum_{j} Q_{jj} / 2 + \sum_{j < k} J_{jk}\). The computational basis state \(|x\rangle\), in which qubit \(j\) is in the state \(|x_{j}\rangle\), is an eigenstate of \(H\) with eigenvalue \(C(x)\). Thus, the ground states of \(H\) are the solutions of the QUBO problem.

Parameters:
Returns:

QUBO Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. A. Lucas, Ising formulations of many NP problems, Front. Phys. 2, 5 (2014).

Fermi-Hubbard model#

class qibo.hamiltonians.FermiHubbard(nsites, hopping_strength=-1.0, interaction_strength=0.5, dense=True, closed_boundary=True, labelling='snake', backend=None)[source]#

Jordan-Wigner-transformed Fermi-Hubbard model on a one-dimensional chain, on a two-dimensional rectangular lattice, or on a lattice with arbitrary connectivity.

In second quantization, the Hamiltonian is defined as

\[H_{\textrm{FH}} = t \, \sum_{\langle j, \, k \rangle, \, \sigma} \, \left( a_{j,\sigma}^{\dagger} \, a_{k,\sigma} + a_{k,\sigma}^{\dagger} \, a_{j,\sigma} \right) + U \, \sum_{j} \, n_{j,\uparrow} \, n_{j,\downarrow} \, ,\]

where \(\langle j, \, k \rangle\) runs over all pairs of nearest-neighbor (i.e., connected) lattice sites, \(a_{j,\sigma}\) (\(a_{j,\sigma}^{\dagger}\)) is the annihilation (creation) operator for spin \(\sigma \in \{\uparrow, \, \downarrow \}\) at site \(j\), \(n_{j,\sigma} = a_{j,\sigma}^{\dagger}\,a_{j,\sigma}\) is the number operator for spin \(\sigma\) at site \(j\), \(t\) is the tunneling amplitude, and \(U\) is the Coulomb potential.

For chains and rectangular lattices, sites are labeled according to labelling. For a lattice with \(n_{c}\) columns, site \((r, \, c)\) has label \(j = r \, n_{c} + c\) in the "row_major" scheme, in which every row is traversed from left to right. In the "snake" scheme, the first row is traversed from left to right, the second row from right to left, and so on. Thus, the label is the same as in the "row_major" scheme if \(r\) is even, and \(j = r \, n_{c} + n_{c} - 1 - c\) if \(r\) is odd. Qubits \(2j\) and \(2j + 1\) encode the spin-up and spin-down modes of site \(j\), respectively. Both schemes are equivalent for chains and single-row lattices.

For an arbitrary connectivity, nsites can be a networkx.Graph, in which every node is a lattice site and every edge is a pair of connected sites. If the nodes of the graph are exactly the integers \(\{0, \, 1, \, \dots, \, n - 1\}\), every node is its own site label \(j\). Otherwise, sites are labeled by the order in which the nodes are stored in the graph, i.e., the \(j\)-th node of list(nsites.nodes) has label \(j\). The graph defines all the bonds of the model. Therefore, closed_boundary and labelling are ignored, and any periodicity must be encoded as edges of the graph. Isolated nodes are lattice sites with no hopping, and self-loops are not allowed.

The graph can be weighted. The tunneling amplitude of the bond between sites \(j\) and \(k\) is \(t \, w_{j,k}\), where \(w_{j,k}\) is the "weight" attribute of the corresponding edge. Edges without this attribute have weight \(1\), and therefore an unweighted graph has a uniform tunneling amplitude \(t\). Edge directions are ignored. Edges between the same pair of nodes, e.g., parallel edges of a multigraph, are merged into a single bond, and they must have the same weight.

Every hopping term between qubits \(p < q\) is multiplied by the Jordan-Wigner string \(\prod_{p < m < q} Z_{m}\), so that fermionic anticommutation is correctly accounted for. A chain with \(n\) sites, nsites=n, is the same model as a lattice with a single row, nsites=(1, n).

Note

For periodic boundaries, bonds that wrap around a dimension are implemented as the same Jordan-Wigner-string hopping terms as the remaining bonds, without the correction that depends on the parity of the total number of particles.

Parameters:
  • nsites (int or tuple[int, int] or networkx.Graph) – if an int, total number of sites in a one-dimensional chain. If a tuple \((n_{r}, \, n_{c})\), number of rows and columns of a two-dimensional lattice. If a networkx.Graph, connectivity graph of the lattice, with one node per site and, optionally, a "weight" attribute per edge that scales hopping_strength.

  • hopping_strength (float or int, optional) – tunneling amplitude. Defaults to \(-1.0\).

  • interaction_strength (float or int, optional) – Coulomb potential. Defaults to \(0.5\).

  • dense (bool, optional) – If True it creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • closed_boundary (bool, optional) – If True, returns Fermi-Hubbard model with periodic boundary condition along every dimension with more than two sites. If False, returns Hamiltonian with open boundaries. Ignored if nsites is a networkx.Graph. Defaults to True.

  • labelling (str, optional) – scheme used to label the lattice sites, either "snake" or "row_major". Ignored if nsites is a networkx.Graph. Defaults to "snake".

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Fermi-Hubbard Hamiltonian \(H_{\textrm{FH}}\).

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

Besides chains and rectangular lattices, the Fermi-Hubbard model can be defined on a lattice with arbitrary connectivity. For that, the connectivity is passed as a networkx.Graph, in which every node is a lattice site and every edge is a pair of sites connected by hopping. For instance, the model on a star-shaped lattice with a central site and three leaves is built as

import networkx as nx

from qibo.hamiltonians import FermiHubbard

graph = nx.star_graph(3)
hamiltonian = FermiHubbard(graph, hopping_strength=-1.0, interaction_strength=0.5)

If the nodes of the graph are exactly the integers \(\{0, \, 1, \, \dots, \, n - 1\}\), every node is its own site label. Otherwise, sites are labeled by the order of the nodes in the graph. Periodic boundaries must be encoded as edges of the graph, e.g., a ring with \(n\) sites is obtained with nx.cycle_graph(n).

The graph can also be weighted. The "weight" attribute of an edge multiplies the hopping_strength of the corresponding bond, and edges without this attribute have weight \(1\). For instance, the following lattice has a stronger tunneling amplitude between the first two sites

import networkx as nx

from qibo.hamiltonians import FermiHubbard

graph = nx.Graph()
graph.add_weighted_edges_from([(0, 1, 2.0), (1, 2, 1.0), (0, 2, 0.5)])
hamiltonian = FermiHubbard(graph, hopping_strength=-1.0, interaction_strength=0.5)

Heisenberg model#

class qibo.hamiltonians.Heisenberg(nqubits, coupling_constants, external_field_strengths, dense=True, closed_boundary=True, backend=None)[source]#

Heisenberg model on a one-dimensional chain or on a lattice with arbitrary connectivity.

The general \(n\)-qubit Hamiltonian is given by

\[\begin{split}\begin{align} H &= -\sum_{\langle j, \, k \rangle} \, \left( J_{x} \, X_{j} \, X_{k} + J_{y} \, Y_{j} \, Y_{k} + J_{z} \, Z_{j} \, Z_{k} \right) \\ &\quad\,\, - \sum_{j} \left( h_{x} \, X_{j} + h_{y} \, Y_{j} + h_{z} \, Z_{j} \right) \, , \end{align}\end{split}\]

where \(\langle j, \, k \rangle\) runs over all pairs of coupled (i.e., connected) qubits, \(\{J_{x}, \, J_{y}, \, J_{z}\}\) are called the coupling constants, \(\{h_{x}, \, h_{y}, \, h_{z}\}\) are called the external field strengths, and \(\{X, \, Y, \, Z\}\) are the usual Pauli operators.

If nqubits is an int, the qubits form a one-dimensional chain and \(\langle j, \, k \rangle\) runs over the nearest neighbors \((j, \, j + 1)\). The pair \((n - 1, \, 0)\) is also coupled if closed_boundary=True, which is the default, i.e., the chain is a ring. In this case, for nqubits=2, the single pair of qubits appears twice in the sum.

For an arbitrary connectivity, nqubits can be a networkx.Graph, in which every node is a qubit and every edge is a pair of coupled qubits. If the nodes of the graph are exactly the integers \(\{0, \, 1, \, \dots, \, n - 1\}\), every node is its own qubit label \(j\). Otherwise, qubits are labeled by the order in which the nodes are stored in the graph, i.e., the \(j\)-th node of list(nqubits.nodes) has label \(j\). The graph defines all the bonds of the model. Therefore, closed_boundary is ignored, and any periodicity must be encoded as edges of the graph. Isolated nodes are qubits with no coupling, and self-loops are not allowed.

The graph can be weighted. The coupling constants of the bond between qubits \(j\) and \(k\) are \(\{J_{x} \, w_{j,k}, \, J_{y} \, w_{j,k}, \, J_{z} \, w_{j,k}\}\), where \(w_{j,k}\) is the "weight" attribute of the corresponding edge. Edges without this attribute have weight \(1\), and therefore an unweighted graph has uniform coupling constants. Edge directions are ignored. Edges between the same pair of nodes, e.g., parallel edges of a multigraph, are merged into a single bond, and they must have the same weight. The external field acts on all qubits, including the isolated ones.

Parameters:
  • nqubits (int or networkx.Graph) – if an int, number of qubits in a one-dimensional chain. If a networkx.Graph, connectivity graph of the qubits, with one node per qubit and, optionally, a "weight" attribute per edge that scales coupling_constants.

  • coupling_constants (list or tuple or float or int) – list or tuple with the three coupling constants \(\{J_{x}, \, J_{y}, \, J_{z}\}\). If int or float, then \(J_{x} = J_{y} = J_{z}\).

  • external_field_strengths (list or tuple or float or int) – list or tuple with the external magnetic field strengths \(\{h_{x}, \, h_{y}, \, h_{z}\}\). If int or float, then \(h_{x} = h_{y} = h_{z}\).

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • closed_boundary (bool, optional) – If True, returns the Hamiltonian with periodic boundary conditions. If False, returns the Hamiltonian with open boundaries. Ignored if nqubits is a networkx.Graph. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Heisenberg Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

Heisenberg XXX#

class qibo.hamiltonians.XXX(nqubits, coupling_constant=1, external_field_strengths=None, dense=True, backend=None)[source]#

Heisenberg \(\mathrm{XXX}\) model on a periodic chain or on an arbitrary lattice.

The \(n\)-qubit \(\mathrm{XXX}\) Hamiltonian is given by

\[H = -J \, \sum_{k = 1}^{n} \, \left( X_{k} \, X_{k + 1} + Y_{k} \, Y_{k + 1} + Z_{k} \, Z_{k + 1} \right) - \sum_{k = 1}^{n} \left(h_{x} \, X_{k} + h_{y} \, Y_{k} + h_{z} \, Z_{k} \right) \, ,\]

where \(J\) is the coupling_constant, \(\{h_{x}, \, h_{y}, \, h_{z}\}\) are called the external field strengths, and \(\{X, \, Y, \, Z\}\) are the usual Pauli operators.

If nqubits is an int, the qubits form a periodic chain. If nqubits is a networkx.Graph, the sum over \(k\) runs over the edges of the graph, and every edge scales the coupling constant \(J\) by its "weight" attribute, which is \(1\) by default. The qubit labels, the isolated nodes and the edge conventions are the same as in qibo.hamiltonians.Heisenberg. In particular, any periodicity must be encoded as edges of the graph, e.g., with networkx.cycle_graph() for a periodic chain and networkx.path_graph() for an open chain, and the external field acts on all qubits, including the isolated ones.

Parameters:
  • nqubits (int or networkx.Graph) – if an int, number of qubits in a periodic chain. If a networkx.Graph, connectivity graph of the qubits, with one node per qubit and, optionally, a "weight" attribute per edge that scales the coupling constant.

  • coupling_constant (float or int, optional) – coupling constant \(J\). Defaults to \(1\).

  • external_field_strengths (float or int or list or tuple, optional) – list or tuple with the external magnetic field strengths \(\{h_{x}, \, h_{y}, \, h_{z}\}\). If int or float, then \(h_{x} = h_{y} = h_{z}\). Defaults to \([1/2, \, 0, \, 0]\).

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Heisenberg \(\mathrm{XXX}\) Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

Heisenberg XXZ#

class qibo.hamiltonians.XXZ(nqubits, delta=0.5, dense=True, backend=None)[source]#

Heisenberg \(\mathrm{XXZ}\) model on a periodic chain or on an arbitrary lattice.

\[H = \sum _{k=0}^N \, \left( X_{k} \, X_{k + 1} + Y_{k} \, Y_{k + 1} + \delta Z_{k} \, Z_{k + 1} \right) \, .\]

If nqubits is an int, the qubits form a periodic chain. If nqubits is a networkx.Graph, the sum runs over the edges of the graph, and every edge scales the whole exchange interaction by its "weight" attribute, which is \(1\) by default. The qubit labels, the isolated nodes and the edge conventions are the same as in qibo.hamiltonians.Heisenberg. In particular, any periodicity must be encoded as edges of the graph, e.g., with networkx.cycle_graph() for a periodic chain and networkx.path_graph() for an open chain.

Example

from qibo.hamiltonians import XXZ
h = XXZ(3) # initialized XXZ model with 3 qubits
Parameters:
  • nqubits (int or networkx.Graph) – if an int, number of qubits in a periodic chain. Must be larger than one. If a networkx.Graph, connectivity graph of the qubits, with one node per qubit and, optionally, a "weight" attribute per edge that scales the interaction.

  • delta (float or int, optional) – coefficient for the \(Z\) component. Defaults to \(0.5\).

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Heisenberg \(\mathrm{XXZ}\) Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

Folded XXZ model#

class qibo.hamiltonians.FoldedXXZ(nqubits, dense=True, backend=None)[source]#

Folded XXZ model on an one-dimensional chain with open boundary conditions.

This model is the \(\Delta \rightarrow \infty\) limit of the XXZ model.

The model is only defined in one dimension. Therefore, unlike qibo.hamiltonians.XXZ(), nqubits cannot be a networkx.Graph.

\[H_{\Delta \rightarrow \infty} = -\frac{1}{8} \, \sum_{j=0}^{n-4} \, (1 + Z_{j} \, Z_{j+3}) \, (X_{j+1} \, X_{j+2} + Y_{j+1} \, Y_{j+2})\]
Parameters:
  • nqubits (int) – number of qubits. It is equivalent to the number of chain sites \(N\) plus \(2\) boundary qubits, i.e., \(N + 2\).

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

The folded XXZ Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. R. Ruiz, A. Sopena, B. Pozsgay, and E. López, Efficient eigenstate preparation in an integrable model with Hilbert space fragmentation, PRX Quantum 6, 030316 (2025).

Heisenberg XY model#

class qibo.hamiltonians.XY(nqubits, gamma=0.0, h=0.0, dense=True, closed_boundary=True, backend=None)[source]#

XY model in a transverse field.

\[H = -\sum_{\langle j, \, k \rangle} \left( \frac{1 + \gamma}{2} \, X_{j} \, X_{k} + \frac{1 - \gamma}{2} \, Y_{j} \, Y_{k} \right) - h \sum_{j} Z_{j} \, ,\]

where \(\gamma\) is the anisotropy of the exchange interaction in the \(XY\) plane and \(h\) is the transverse field strength. For \(\gamma = 0\), it is the isotropic \(XX\) model, which conserves the magnetization along \(Z\). For \(\gamma = 1\), it is unitarily equivalent to the transverse-field Ising model qibo.hamiltonians.TFIM(), with the same boundary conditions, by exchanging \(X\) and \(Z\) with a Hadamard gate on every qubit.

The XY model is the qibo.hamiltonians.Heisenberg() model with coupling constants \(\{(1 + \gamma) / 2, \, (1 - \gamma) / 2, \, 0\}\) and external field strengths \(\{0, \, 0, \, h\}\). Therefore, nqubits can be an int, for a one-dimensional chain, or a networkx.Graph, for a lattice with arbitrary connectivity, following the same conventions as in qibo.hamiltonians.Heisenberg().

Parameters:
  • nqubits (int or networkx.Graph) – if an int, number of qubits in a one-dimensional chain. Must be larger than one. If a networkx.Graph, connectivity graph of the qubits, with one node per qubit and, optionally, a "weight" attribute per edge that scales the exchange interaction.

  • gamma (float, optional) – anisotropy \(\gamma\). Defaults to \(0.0\).

  • h (float, optional) – transverse field strength \(h\). Defaults to \(0.0\).

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • closed_boundary (bool, optional) – If True, returns the Hamiltonian with periodic boundary conditions. If False, returns the Hamiltonian with open boundaries. Ignored if nqubits is a networkx.Graph. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

XY Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. E. Lieb, T. Schultz, and D. Mattis, Two soluble models of an antiferromagnetic chain, Ann. Phys. 16, 407 (1961).

Disordered Heisenberg model#

class qibo.hamiltonians.DisorderedHeisenberg(nqubits, coupling_constants, disorder_strength, distribution='uniform', seed=None, dense=True, closed_boundary=True, backend=None)[source]#

Heisenberg model with random on-site fields along the \(Z\)-axis.

\[H = -\sum_{\langle j, \, k \rangle} \left( J_{x} \, X_{j} \, X_{k} + J_{y} \, Y_{j} \, Y_{k} + J_{z} \, Z_{j} \, Z_{k} \right) - \sum_{j} h_{j} \, Z_{j} \, ,\]

where \(\langle j, \, k \rangle\) runs over all pairs of coupled qubits, \(\{J_{x}, \, J_{y}, \, J_{z}\}\) are the coupling constants, and \(h_{j} = W \, \xi_{j}\) are independent random fields with zero mean, with \(W\) the disorder strength. For isotropic couplings, it is the random-field Heisenberg chain, which is a paradigmatic model of many-body localization: the eigenstates are thermal for weak disorder, and localized for strong disorder.

The model is the sum of the qibo.hamiltonians.Heisenberg model without external field and the random fields. Therefore, nqubits can be an int, for a chain, or a networkx.Graph, for a lattice with arbitrary connectivity, and the couplings, the qubit labels and the closed_boundary option follow the same conventions as in qibo.hamiltonians.Heisenberg. For \(W = 0\), it reduces to that model.

The random variables \(\{\xi_{j}\}_{j}\) are drawn in a single call, one per qubit, following the order of the qubit labels \(j\). The random fields act on all qubits, including the isolated nodes of a graph.

Parameters:
  • nqubits (int or networkx.Graph) – if an int, number of qubits in a one-dimensional chain. Must be larger than one. If a networkx.Graph, connectivity graph of the qubits, with one node per qubit and, optionally, a "weight" attribute per edge that scales coupling_constants.

  • coupling_constants (list or tuple or float or int) – list or tuple with the three coupling constants \(\{J_{x}, \, J_{y}, \, J_{z}\}\). If int or float, then \(J_{x} = J_{y} = J_{z}\).

  • disorder_strength (float) – disorder strength \(W\).

  • distribution (str, optional) – distribution of the random variables \(\xi_{j}\). If "uniform", they are uniformly distributed in the interval \([-1, 1)\), so that \(h_{j} \in [-W, W)\). If "gaussian", they follow a standard normal distribution. Defaults to "uniform".

  • seed (int or numpy.random.Generator, optional) – Either a generator of random numbers or a fixed seed to initialize a generator. If None, initializes a generator with a random seed. Defaults to None.

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • closed_boundary (bool, optional) – If True, returns the Hamiltonian with periodic boundary conditions. If False, returns the Hamiltonian with open boundaries. Ignored if nqubits is a networkx.Graph. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Disordered Heisenberg Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. A. Pal and D. A. Huse, Many-body localization phase transition, Phys. Rev. B 82, 174411 (2010).

Heisenberg model with Dzyaloshinskii-Moriya interaction#

class qibo.hamiltonians.DMHeisenberg(nqubits, coupling_constants, external_field_strengths, dm_strengths, dense=True, closed_boundary=True, backend=None)[source]#

Heisenberg model with Dzyaloshinskii-Moriya (DM) interaction.

\[\begin{align} H &= H_{\textrm{Heisenberg}} + \sum_{\langle j, \, k \rangle} \, \left[ D_{x} \, \left( Y_{j} \, Z_{k} - Z_{j} \, Y_{k} \right) + D_{y} \, \left( Z_{j} \, X_{k} - X_{j} \, Z_{k} \right) + D_{z} \, \left( X_{j} \, Y_{k} - Y_{j} \, X_{k} \right) \right] \, , \end{align}\]

where \(H_{\textrm{Heisenberg}}\) is the qibo.hamiltonians.Heisenberg model, \(\langle j, \, k \rangle\) runs over all pairs of coupled qubits, and \(\{D_{x}, \, D_{y}, \, D_{z}\}\) are the components of the DM vector, i.e., the DM term of every bond is \(\vec{D} \cdot (\vec{\sigma}_{j} \times \vec{\sigma}_{k})\). This antisymmetric exchange appears in magnets without inversion symmetry between the coupled spins, and it favors canted spin configurations, e.g., chiral and skyrmionic textures.

The DM interaction changes sign if the two qubits of a bond are exchanged. Hence, every bond has an orientation. In a chain, bonds are oriented as \(j \to j + 1\), and the bond that closes the ring (if closed_boundary=True) is oriented as \(n - 1 \to 0\). Therefore, for nqubits=2, the two bonds of the ring have opposite orientations and the DM terms cancel. In a networkx.Graph, bonds are oriented from the lower to the higher qubit label.

The conventions for nqubits, for the labels of the qubits, and for closed_boundary are the same as in qibo.hamiltonians.Heisenberg. If nqubits is a weighted graph, the "weight" of every edge scales both the coupling constants and the DM vector of the corresponding bond.

Parameters:
  • nqubits (int or networkx.Graph) – if an int, number of qubits in a one-dimensional chain. If a networkx.Graph, connectivity graph of the qubits, with one node per qubit and, optionally, a "weight" attribute per edge.

  • coupling_constants (list or tuple or float or int) – list or tuple with the three coupling constants \(\{J_{x}, \, J_{y}, \, J_{z}\}\) of the qibo.hamiltonians.Heisenberg model. If int or float, then \(J_{x} = J_{y} = J_{z}\).

  • external_field_strengths (list or tuple or float or int) – list or tuple with the external magnetic field strengths \(\{h_{x}, \, h_{y}, \, h_{z}\}\). If int or float, then \(h_{x} = h_{y} = h_{z}\).

  • dm_strengths (list or tuple or float or int) – list or tuple with the three components \(\{D_{x}, \, D_{y}, \, D_{z}\}\) of the DM vector. If int or float, then \(D_{x} = D_{y} = D_{z}\).

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.hamiltonians.Hamiltonian, otherwise it creates a qibo.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • closed_boundary (bool, optional) – If True, returns the Hamiltonian with periodic boundary conditions. If False, returns the Hamiltonian with open boundaries. Ignored if nqubits is a networkx.Graph. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Heisenberg Hamiltonian with Dzyaloshinskii-Moriya interaction.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. I. Dzyaloshinsky, A thermodynamic theory of “weak” ferromagnetism of antiferromagnetics, J. Phys. Chem. Solids 4, 241 (1958) <https://doi.org/10.1016/0022-3697(58)90076-3>. 2. T. Moriya, Anisotropic superexchange interaction and weak ferromagnetism, Phys. Rev. 120, 91 (1960).

Heisenberg J1-J2 model#

class qibo.hamiltonians.J1J2(nqubits, j1=1.0, j2=0.5, dense=True, closed_boundary=True, backend=None)[source]#

Heisenberg \(J_{1}\)-\(J_{2}\) model on a chain.

\[H = \sum_{j} \, \left[ J_{1} \, \left( X_{j} \, X_{j+1} + Y_{j} \, Y_{j+1} + Z_{j} \, Z_{j+1} \right) + J_{2} \, \left( X_{j} \, X_{j+2} + Y_{j} \, Y_{j+2} + Z_{j} \, Z_{j+2} \right) \right] \, ,\]

where \(J_{1}\) couples nearest neighbors and \(J_{2}\) couples next-nearest neighbors. For \(J_{1}, \, J_{2} > 0\), the two interactions compete, i.e., the chain is frustrated. At \(J_{2} = J_{1} / 2\), which is the default, it is the Majumdar-Ghosh model, whose ground states are products of singlets on nearest-neighbor pairs. For \(J_{2} = 0\), it is the antiferromagnetic Heisenberg chain.

The model is the qibo.hamiltonians.Heisenberg model on a weighted graph, in which the bonds of nearest neighbors have weight \(J_{1}\) and the bonds of next-nearest neighbors have weight \(J_{2}\). If closed_boundary=True, the chain is a ring. If a pair of qubits is both a nearest and a next-nearest neighbor, which occurs for three qubits in a ring, the two interactions are added.

Parameters:
  • nqubits (int) – number of qubits. It must be larger than two.

  • j1 (float, optional) – nearest-neighbor coupling \(J_{1}\). Defaults to \(1.0\).

  • j2 (float, optional) – next-nearest-neighbor coupling \(J_{2}\). Defaults to \(0.5\).

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.hamiltonians.Hamiltonian, otherwise it creates a qibo.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • closed_boundary (bool, optional) – If True, returns the Hamiltonian with periodic boundary conditions. If False, returns the Hamiltonian with open boundaries. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Heisenberg \(J_{1}\)-\(J_{2}\) Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. C. K. Majumdar and D. K. Ghosh, On next-nearest-neighbor interaction in linear chain. I, ‘J. Math. Phys. 10, 1388 (1969) <https://doi.org/10.1063/1.1664978>’. 2. K. Okamoto and K. Nomura, Fluid-dimer critical point in S=1/2 antiferromagnetic Heisenberg chain with next nearest neighbor interactions, ‘Phys. Lett. A 169, 433 (1992) <https://doi.org/10.1016/0375-9601(92)90823-5>’.

Long-range Heisenberg model#

class qibo.hamiltonians.LongRangeHeisenberg(nqubits, coupling_constants, external_field_strengths, alpha, dense=True, closed_boundary=True, backend=None)[source]#

Heisenberg model with power-law decaying interactions on a chain.

\[\begin{split}\begin{align} H &= -\sum_{j < k} \, \frac{1}{d_{jk}^{\alpha}} \, \left( J_{x} \, X_{j} \, X_{k} + J_{y} \, Y_{j} \, Y_{k} + J_{z} \, Z_{j} \, Z_{k} \right) \\\\ &\quad\,\, - \sum_{j} \left( h_{x} \, X_{j} + h_{y} \, Y_{j} + h_{z} \, Z_{j} \right) \, , \end{align}\end{split}\]

where \(d_{jk} = |j - k|\) is the distance between qubits \(j\) and \(k\), and \(\alpha\) is the decay exponent of the interactions. If closed_boundary=True, the chain is a ring and \(d_{jk} = \min(|j - k|, \, n - |j - k|)\), with \(n\) the number of qubits. For \(\alpha = 0\) every pair of qubits is equally coupled, and for \(\alpha \to \infty\) only nearest neighbors are coupled. Choosing \(J_{x} = J_{y} = 0\) gives the long-range Ising model, and \(J_{z} = 0\) gives the long-range XY model, both of which are realized in trapped-ion and Rydberg-atom quantum simulators.

The model is the qibo.hamiltonians.Heisenberg model on the complete graph with edge weights \(1 / d_{jk}^{\alpha}\).

Parameters:
  • nqubits (int) – number of qubits. It must be larger than one.

  • coupling_constants (list or tuple or float or int) – list or tuple with the three coupling constants \(\{J_{x}, \, J_{y}, \, J_{z}\}\). If int or float, then \(J_{x} = J_{y} = J_{z}\).

  • external_field_strengths (list or tuple or float or int) – list or tuple with the external magnetic field strengths \(\{h_{x}, \, h_{y}, \, h_{z}\}\). If int or float, then \(h_{x} = h_{y} = h_{z}\).

  • alpha (float) – decay exponent \(\alpha\) of the interactions.

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.hamiltonians.Hamiltonian, otherwise it creates a qibo.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • closed_boundary (bool, optional) – If True, returns the Hamiltonian with periodic boundary conditions. If False, returns the Hamiltonian with open boundaries. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Long-range Heisenberg Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. N. Defenu, T. Donner, T. Macrì, G. Pagano, S. Ruffo, and A. Trombettoni, Long-range interacting quantum systems, Rev. Mod. Phys. 95, 035002 (2023).

Lipkin-Meshkov-Glick model#

class qibo.hamiltonians.LMG(nqubits, gamma=0.0, h=0.5, dense=True, backend=None)[source]#

Lipkin-Meshkov-Glick (LMG) model.

\[H = -\frac{1}{n} \, \sum_{j < k} \, \left( X_{j} \, X_{k} + \gamma \, Y_{j} \, Y_{k} \right) - h \, \sum_{j} Z_{j} \, ,\]

where \(n\) is the number of qubits. It is an XY model in a transverse field in which every pair of qubits is coupled (infinite-range interaction), and the factor \(1 / n\) keeps the energy per qubit finite as \(n\) grows. In the limit \(n \to \infty\) and for \(\gamma < 1\), the model has a mean-field quantum phase transition at \(h = 1\). For \(\gamma = 1\), the model has a conserved total spin projection along the \(Z\) axis.

The model is the qibo.hamiltonians.Heisenberg model on the complete graph with edges of weight \(1 / n\).

Parameters:
  • nqubits (int) – number of qubits. It must be larger than one.

  • gamma (float, optional) – anisotropy \(\gamma\) of the interaction in the \(XY\) plane. Defaults to \(0.0\).

  • h (float, optional) – transverse field strength \(h\). Defaults to \(0.5\).

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.hamiltonians.Hamiltonian, otherwise it creates a qibo.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Lipkin-Meshkov-Glick Hamiltonian.

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. H. J. Lipkin, N. Meshkov, and A. J. Glick, Validity of many-body approximation methods for a solvable model: (I). Exact solutions and perturbation theory, ‘Nucl. Phys. 62, 188 (1965) <https://doi.org/10.1016/0029-5582(65)90862-X>’. 2. S. Dusuel and J. Vidal, Finite-size scaling exponents of the Lipkin-Meshkov-Glick model, Phys. Rev. Lett. 93, 237204 (2004).

Graph Partitioning Problem#

class qibo.hamiltonians.GPP(adjacency_matrix, penalty_coeff=0.0, node_weights=None, dense=True, backend=None)[source]#

The Graph Partitioning Problem (GPP) as a quadratic function.

For a (possibly weighted) graph \(G = (V, E)\) defined by its set \(V\) of vertices and set \(E\) of edges, the GPP is the task of dividing a graph’s vertices into \(m\) subsets of approximately equal size, such that \(\bigcup_{k=1}^{m} \, V_{k} = V\), while minimizing the number of edges that connect vertices in different subsets.

The formulation of the GPP as a quadratic unconstrained binary optimization (QUBO) reduces to minimizing the following objective function \(C(x)\):

\[C(x) = \sum_{(j,k) \in E} \, A_{jk} \, (x_{j} + x_{k} - 2 \, x_{j} \, x_{k}) \, + \lambda \, P(x),\]

where \(x_{j} \in \{0, \, 1\}\) is a binary variable,

\[P(x) = \left(\sum_{k} \, v_{k} \, x_{k} - \sum_{k} \, \frac{v_{k}}{2}\right)^{2}\]

is a term designed to penalize deviations in the total node weight on each partition, and \(\lambda > 0\) is a hyperparameter.

Parameters:
  • adjacency_matrix (ndarray) – Square symmetric matrix with weigths \(A_{jk}\) representing the edges of the graph. For an unweighted graph, \(A_{jk} = 1, \,\, \forall \, j,k\).

  • penalty_coeff (float or int, optional) – hyperparameter \(\lambda\) defining the strength of the penalty term. Defaults to \(0.0\).

  • node_weights (ArrayLike, optional) – Weight of the nodes of the graph. Used when \(\lambda \neq 0\). If None, all node weights default to \(1\). Defaults to None.

  • dense (bool, optional) – If True, creates the Hamiltonian as a qibo.core.hamiltonians.Hamiltonian, otherwise it creates a qibo.core.hamiltonians.SymbolicHamiltonian. Defaults to True.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

GPP Hamiltonian \(H_{C}\).

Return type:

qibo.hamiltonians.Hamiltonian or qibo.hamiltonians.SymbolicHamiltonian

References

1. W. Aboumrad, D. Zhu, C. Girotto, F.-H. Rouet, J. Jojo, R. Lucas, J. Pathak, A. Kaushik, and M. Roetteler, Accelerating large-scale linear algebra using variational quantum imaginary time evolution, arXiv:2503.13128 (2025).

Note

All pre-coded Hamiltonians can be created as qibo.hamiltonians.Hamiltonian using dense=True or qibo.hamiltonians.SymbolicHamiltonian using the dense=False. In the first case the Hamiltonian is created using its full matrix representation of size (2 ** n, 2 ** n) where n is the number of qubits that the Hamiltonian acts on. This matrix is used to calculate expectation values by direct matrix multiplication to the state and for time evolution by exact exponentiation. In contrast, when dense=False the Hamiltonian contains a more compact representation as a sum of local terms. This compact representation can be used to calculate expectation values via a sum of the local term expectations and time evolution via the Trotter decomposition of the evolution operator. This is useful for systems that contain many qubits for which constructing the full matrix is intractable.