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
Noneit will try to compute the exact expectation value (if possible). Defaults toNone.
- Returns:
The expectation value.
- Return type:
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.sparsefornumpy/qibojitbackends (or ontf.sparsefor thetensorflowbackend) are also supported.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- 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]
- 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
Noneit will try to compute the exact expectation value (if possible). Defaults toNone.qubit_map (dict | None) –
- Returns:
The expectation value.
- Return type:
- expectation_from_samples(frequencies, qubit_map=None)[source]#
Compute the expectation value starting from some samples, works only for diagonal observables.
- 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:
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
sympyexpression as it is (form) or by parsing the correspondingterms(which areqibo.core.terms.SymbolicTermobjects). The latter approach is more computationally costly as it uses asympy.expandcall on the given form before parsing the terms. For this reason thetermsare calculated only when needed, for example during Trotterization. The dense matrix of the symbolic Hamiltonian can be calculated directly fromformwithout requiringtermscalculation (seeqibo.core.hamiltonians.SymbolicHamiltonian.calculate_dense()for details).- Parameters:
form (sympy.Expr) – Hamiltonian form as a
sympy.Expr. Ideally the Hamiltonian should be written using Qibo symbols. See How to define custom Hamiltonians using symbols? example for more details.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.nqubits (int | None) –
- 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.SymbolicTermterms.
- 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.
- 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
Noneit will try to compute the exact expectation value (if possible). Defaults toNone.
- Returns:
The expectation value.
- Return type:
- expectation_from_samples(frequencies, qubit_map=None)[source]#
Compute the expectation value starting from some samples, works only for diagonal observables.
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
Trueit creates the Hamiltonian as aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian. Defaults toTrue.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- Return type:
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
Trueit creates the Hamiltonian as aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- Return type:
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
Trueit creates the Hamiltonian as aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- Return type:
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 thelocal field strengths, and \(\{X, \, Y, \, Z\}\) are the usual Pauli operators.If
nqubitsis anint, 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 ifclosed_boundary=True.For an arbitrary connectivity,
nqubitscan be anetworkx.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 oflist(nqubits.nodes)has label \(j\). The graph defines all the bonds of the model. Therefore,closed_boundaryis 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_constantsand \(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 anint, number of qubits in a one-dimensional chain. If anetworkx.Graph, connectivity graph of the qubits, with one node per qubit and, optionally, a"weight"attribute per edge that scalescoupling_constants.coupling_constants (float or int or ArrayLike) –
listorndarraycontaining all coupling constants \(\{J_{k}\}_{k}\) of the chain. Ifintorfloat, then \(J_{k}\) is equal tocoupling_constantsfor all \(k\). Ifnqubitsis anetworkx.Graph, it must be anintorfloat.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
intorfloat, the coefficients \(h_{j}^{(z)}\) and \(h_{j}^{(x)}\) are equal tolocal_field_strengths, \(\forall \, j\). IfTuple[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 aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian. Defaults toTrue.closed_boundary (bool, optional) – If
True, returns Ising Hamiltonian with periodic boundary condition. IfFalse, returns Hamiltonian with open boundaries. Ignored ifnqubitsis anetworkx.Graph. Defaults toTrue.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- Returns:
Ising Hamiltonian.
- Return type:
qibo.hamiltonians.Hamiltonianorqibo.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.Isingmodel 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
Trueit creates the Hamiltonian as aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian. Defaults toTrue.closed_boundary (bool, optional) – If
True, returns TFIM with periodic boundary condition. IfFalse, returns Hamiltonian with open boundaries. Defaults toTrue.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- Return type:
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.IsingHamiltonian, 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
Trueit creates the Hamiltonian as aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.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. IfNone, it uses the current backend. Defaults toNone.
- Return type:
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
Trueit creates the Hamiltonian as aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- Return type:
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, 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,
nsitescan be anetworkx.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 oflist(nsites.nodes)has label \(j\). The graph defines all the bonds of the model. Therefore,closed_boundaryandlabellingare 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 anint, total number of sites in a one-dimensional chain. If atuple\((n_{r}, \, n_{c})\), number of rows and columns of a two-dimensional lattice. If anetworkx.Graph, connectivity graph of the lattice, with one node per site and, optionally, a"weight"attribute per edge that scaleshopping_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
Trueit creates the Hamiltonian as aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian. Defaults toTrue.closed_boundary (bool, optional) – If
True, returns Fermi-Hubbard model with periodic boundary condition along every dimension with more than two sites. IfFalse, returns Hamiltonian with open boundaries. Ignored ifnsitesis anetworkx.Graph. Defaults toTrue.labelling (str, optional) – scheme used to label the lattice sites, either
"snake"or"row_major". Ignored ifnsitesis anetworkx.Graph. Defaults to"snake".backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- Returns:
Fermi-Hubbard Hamiltonian \(H_{\textrm{FH}}\).
- Return type:
qibo.hamiltonians.Hamiltonianorqibo.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, 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 theexternal 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
intorfloat, 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
intorfloat, then \(h_{x} = h_{y} = h_{z}\).dense (bool, optional) – If
True, creates the Hamiltonian as aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian. Defaults toTrue.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.external_field_strengths (float) –
- Returns:
Heisenberg Hamiltonian.
- Return type:
qibo.hamiltonians.Hamiltonianorqibo.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 theexternal 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
intorfloat, then \(h_{x} = h_{y} = h_{z}\). Defaults to \([1/2, \, 0, \, 0]\).dense (bool, optional) – If
True, creates the Hamiltonian as aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian. Defaults toTrue.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- Returns:
Heisenberg \(\mathrm{XXX}\) Hamiltonian.
- Return type:
qibo.hamiltonians.Hamiltonianorqibo.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 aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian. Defaults toTrue.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- Returns:
Heisenberg \(\mathrm{XXZ}\) Hamiltonian.
- Return type:
qibo.hamiltonians.Hamiltonianorqibo.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 aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian. Defaults toTrue.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- Returns:
The folded XXZ Hamiltonian.
- Return type:
qibo.hamiltonians.Hamiltonianorqibo.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 toNone.dense (bool, optional) – If
True, creates the Hamiltonian as aqibo.core.hamiltonians.Hamiltonian, otherwise it creates aqibo.core.hamiltonians.SymbolicHamiltonian. Defaults toTrue.backend (
qibo.backends.abstract.Backend, optional) – backend to be used in the execution. IfNone, it uses the current backend. Defaults toNone.
- Returns:
GPP Hamiltonian \(H_{C}\).
- Return type:
qibo.hamiltonians.Hamiltonianorqibo.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.