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: _Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]#

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:

_Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]

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:

_Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]

exp(a)[source]#

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

Parameters:

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

Return type:

_Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]

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: _Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]#

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:

_Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]

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:

_Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]

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:

_Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]

exp(a)[source]#

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

Parameters:

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

Return type:

_Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]

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:
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]#

One-dimensional \(n\)-qubit Ising model.

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

where \(\{J_{k}\}_{k}\) are called the coupling constants, \(\{h_{k}^{(z)}, h_{k}^{(x)}\}_{k}\) are called the local field strengths, and \(\{X, \, Y, \, Z\}\) are the usual Pauli operators.

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

  • coupling_constants (float or int or ArrayLike) – list or ndarray containing all coupling constants \(\{J_{k}\}_{k}\). If int or float, then \(J_{k}\) is equal to coupling_constants for all $k$.

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

  • 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. 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.

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

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} \, \left(1 - Z_{j} \, Z_{k}\right) \, .\]
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.

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 or on a two-dimensional rectangular lattice.

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 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.

Lattice 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.

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]) – 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.

  • 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. Defaults to True.

  • labelling (str, optional) – scheme used to label the lattice sites, either "snake" or "row_major". 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

Heisenberg model#

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

Heisenberg model on a \(1\)-dimensional periodic lattice.

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

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

where \(\{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.

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

  • 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_strength (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.

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

  • external_field_strengths (float) –

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 with periodic boundary conditions.

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.

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

  • 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 with periodic boundary conditions.

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

Example

from qibo.hamiltonians import XXZ
h = XXZ(3) # initialized XXZ model with 3 qubits
Parameters:
  • nqubits (int) – number of qubits.

  • 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.

\[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).

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.