Source code for qiskit_nature.second_q.hamiltonians.fermi_hubbard_model

# This code is part of a Qiskit project.
#
# (C) Copyright IBM 2021, 2023.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""The Fermi-Hubbard model"""
import numpy as np

from qiskit_nature.second_q.operators import FermionicOp

from .lattice_model import LatticeModel
from .lattices import Lattice


[docs]class FermiHubbardModel(LatticeModel): r"""The Fermi-Hubbard model. This class implements the following Hamiltonian: .. math:: H = \sum_{i, j}\sum_{\sigma = \uparrow, \downarrow} t_{i, j} c_{i, \sigma}^\dagger c_{j, \sigma} + U \sum_{i} n_{i, \uparrow} n_{i, \downarrow}, where :math:`c_{i, \sigma}^\dagger` and :math:`c_{i, \sigma}` are creation and annihilation operators of a fermion at the site :math:`i` with spin :math:`\sigma`. The operator :math:`n_{i, \sigma}` is the number operator, which is defined by :math:`n_{i, \sigma} = c_{i, \sigma}^\dagger c_{i, \sigma}`. The matrix :math:`t_{i, j}` is a Hermitian matrix called the interaction matrix. The parameter :math:`U` represents the strength of the on-site interaction. This model is instantiated using a :class:`~qiskit_nature.second_q.hamiltonians.lattices.Lattice`. For example, using a :class:`~qiskit_nature.second_q.hamiltonians.lattices.LineLattice`: .. code-block:: python line_lattice = LineLattice(num_nodes=10, boundary_condition=BoundaryCondition.OPEN) fermi_hubbard_model = FermiHubbardModel( line_lattice.uniform_parameters( uniform_interaction=-1.0, uniform_onsite_potential=0.0, ), onsite_interaction=5.0, ) """ def __init__(self, lattice: Lattice, onsite_interaction: complex) -> None: """ Args: lattice: Lattice on which the model is defined. onsite_interaction: The strength of the on-site interaction. """ super().__init__(lattice) self._onsite_interaction = onsite_interaction
[docs] def hopping_matrix(self) -> np.ndarray: """Return the hopping matrix.""" return self.interaction_matrix()
@property def register_length(self) -> int: return 2 * self._lattice.num_nodes
[docs] def second_q_op(self) -> FermionicOp: """Return the Hamiltonian of the Fermi-Hubbard model in terms of ``FermionicOp``. Returns: FermionicOp: The Hamiltonian of the Fermi-Hubbard model. """ kinetic_ham = {} interaction_ham = {} weighted_edge_list = self._lattice.weighted_edge_list register_length = 2 * self._lattice.num_nodes # kinetic terms for spin in range(2): for node_a, node_b, weight in weighted_edge_list: if node_a == node_b: index = 2 * node_a + spin kinetic_ham[f"+_{index} -_{index}"] = weight else: if node_a < node_b: index_left = 2 * node_a + spin index_right = 2 * node_b + spin hopping_parameter = weight elif node_a > node_b: index_left = 2 * node_b + spin index_right = 2 * node_a + spin hopping_parameter = np.conjugate(weight) kinetic_ham[f"+_{index_left} -_{index_right}"] = hopping_parameter kinetic_ham[f"-_{index_left} +_{index_right}"] = -np.conjugate( hopping_parameter ) # on-site interaction terms for node in self._lattice.node_indexes: index_up = 2 * node index_down = 2 * node + 1 interaction_ham[ f"+_{index_up} -_{index_up} +_{index_down} -_{index_down}" ] = self._onsite_interaction ham = {**kinetic_ham, **interaction_ham} return FermionicOp(ham, num_spin_orbitals=register_length, copy=False)