Matrix product operators ======================== ------------------------------------------------------------------------------- Dense matrix product operators ------------------------------ There are 3 classes in this module: ``MPOSite``, ``DenseMPO``, ``DenseMPOList`` **DenseMPO** This is the standard textbook-like MPO that acts on specified sites (``DenseMPO.sites``). It is a list of ``MPOSite``-s :: | | | | -O-O-O-O- | | | | **MPOSite** Each tensor in the ``DenseMPO`` is stored as ``MPOSite``. For example, a 4-body ``DenseMPO`` is going to be a list of 4 ``MPOSite``-s. :: | -O- | **DenseMPOList** A list of ``DenseMPO``-s. Here, the ``DenseMPOList`` is usually used to represent Hamiltonians. Hamiltonians are special because they are normally a sum of polynomially-many tensor product operator (TPO) terms. For local hamiltonians, each TPO acts on a finite number of sites. Hence we can store a Hamiltonian as a list of TPO terms, where each TPO is represented as a ``DenseMPO``. For example, the Ising model contains nearest-neighbour :math:`\sigma_x\sigma_x` and :math:`\sigma_z` terms, and every 2-body TPO term :math:`\sigma_x\sigma_x` and local term :math:`\sigma_z` would be stored as a separate ``DenseMPO`` added to a ``DenseMPOList``. :: | | | | | -O-O- , -O-O- , -O- , ... | | | | | Therefore, the number of sites in each individual ``DenseMPO`` in a ``DenseMPOList`` does not correspond to the total number of sites - instead, it corresponds to the number of sites on which the individual Hamiltonian term is acting on. **Some useful attributes/functions** Initialize ``MPOSite`` with ``MPOSite([list of sites], tensor_str_name, pstrength=None, prefactor=1.0, operators=op_dict, params={})`` - ``MPOSite.site`` = on which site in a system does this MPO site act - ``MPOSite.operator`` = get an actual tensor - ``MPOSite.pstrength``, ``MPOSite.weight`` = prefactors that multiply the elements of an operator. The difference between ``pstrength`` and ``weight`` is that ``pstrength`` is parametrized via params dictionary and ``weight`` is a number. The default prefactor is 1, i.e. ``pstrength=None`` and ``weight=1``. Initialize ``DenseMPO`` with ``DenseMPO([list of MPOSite-s], tensor_backend)`` - ``DenseMPO.num_sites`` = on how many sites does this MPO act - ``DenseMPO.sites`` = list of sites on which MPO acts - ``DenseMPO[ind].operator`` = get tensor on site ind - ``DenseMPO.append(MPOSite)`` = add ``MPOSite`` to ``DenseMPO`` Initialize ``DenseMPOList`` with ``DenseMPOList()`` and then append ``DenseMPO``-s - ``DenseMPOList[ind]`` = get ``ind``-th ``DenseMPO`` in a list - ``DenseMPOList.from_model_prepared(\*args, \*\*kwargs)`` = create a ``DenseMPOList`` object from a given Hamiltonian model **See the more detailed documentation of individual functions below** .. autoclass:: qtealeaves.mpos.MPOSite :members: .. autoclass:: qtealeaves.mpos.DenseMPO :members: .. autoclass:: qtealeaves.mpos.DenseMPOList :members: ------------------------------------------------------------------------------- Indexed tensor product operators -------------------------------- This is the default MPO representation for the Hamiltonians and the observables which the library uses during computationally extensive operations in simulations. (The other option are sparse MPOs, but indexed tensor product operators (iTPOs) for now allow more generality.) Here is the short introduction to iTPO framework. A Hamiltonian MPO (or any MPO operator) is often a sum of tensor product terms (TPOs), where every TPO term contains *n* operators acting on *n* sites. Therefore, as it is the case with dense MPOs (see above), we can treat the Hamiltonian as a list of TPO terms. Very often, however, we have only few different operator tensors building the Hamiltonian: the Ising Hamiltonian is, for example, built only from :math:`\sigma_x` and :math:`\sigma_z` operators. Therefore, to save memory, we don't have to define our Hamiltonian MPO by saving every operator at every site (as it is done in a ``DenseMPOList``), but instead we can assign every operator tensor an index ``ii`` and store only the information of type: "operator ``ii`` acting on site ``x`` with the prefactor ``w``", where ``ii`` points to e.g. :math:`\sigma_x` tensor. Every TPO term is assigned a unique integer TPO ID going from 0 to number of TPO terms. The same TPO IDs are assigned to the corresponding operators inside TPO terms, so we can keep track which operator belongs to which TPO term. This way of representing MPOs is what we call the indexed TPO picture. Another difference between iTPOs with respect to ``DenseMPO`` / ``DenseMPOLists`` is that local terms are treated differently in the iTPO picture. All the local terms acting on the same site are contracted into a single local term of same dimensions. There are 3 classes in this module: ``ITPOTerm``, ``ITPOSites``, ``ITPO`` **ITPOTerm** ``ITPOTerm`` contains all operators acting on a single site, each coming from a different TPO term in the MPO. The "Term" in the name is a bit misleading, as ``ITPOTerm`` does not refer to the TPO term (which usually acts on more than one site), but instead refers to a collection of operators acting on a single site. ``ITPOTerm`` can contain one local term, which is treated separately and is stored under ``ITPOTerm._local``. **ITPO** The full MPO, containing all its TPO terms. In general, it has two parts: ``ITPO.site_terms`` and ``ITPO.eff_ops``. ``ITPO.site_terms`` are an instance of ``ITPOSites`` (description below) and they represent the TPO terms coming from a Hamiltonian or any operator acting on the physical sites of the tensor network. ``ITPO.eff_ops``, on the other hand, represent all the TPO terms inside the effective operators around each tensor in a tensor network. Therefore, ``ITPO.eff_ops`` depend on a TN ansatz. In a simulation, ``ITPO.site_terms`` are usually the input Hamiltonian and ``ITPO.eff_ops`` are computed by contracting this Hamiltonian with tensors in a TN. **ITPOSites** Represent the TPO terms coming from a Hamiltonian or any operator acting on physical sites of the tensor network. Stored as a list of ``ITPOTerm``-s, such that there is one ``ITPOTerm`` per system site. **Some useful attributes/functions/remarks** ITPOTerm acts on a single site, but there is no attribute inside of it which tell which site it is. This info is instead stored in ``ITPO`` and ``ITPOSites``. - ``ITPOTerm._tensors`` : following the iTPO convention, this is a dictionary with all the tensors, where the key is the operator string which defines it and the value is a corresponding tensor - ``ITPOTerm._operators`` : a dictionary, with the key being a TPO ID of the corresponding TPO term in the parent ITPO and the value is the corresponding operator string - ``ITPOTerm.weights`` : list of prefactors for every operator tensor in ``ITPOTerm``, ordered by TPO IDs - ``ITPOTerm._local`` : tensor of a local term, if any The easiest way to create an ``ITPO`` is to first create a ``DenseMPOList``, initialize the empty ITPO with ``itpo = ITPO(num_sites)``, and then convert ``DenseMPOList`` to ``ITPO`` with ``itpo.add_dense_mpo_list(DenseMPOList)`` - ``ITPO.site_terms`` : ``ITPOSites``, i.e. a list of ``ITPOTerm``-s that act on physical sites in a TN - ``ITPO.eff_ops`` : a dictionary of effective operators around every tensor in a tensor network. The keys in a dictionary specify which tensor we are looking at, with the convention differing for different TNs (e.g. for MPS, it's just the index of the tensor, for TTN it's ``(layer_idx, tensor_idx)``). The value for each iterm in ``ITPO.eff_ops`` is again a dictionary containing three ``ITPOTerm``-s, as there are three effective operators per tensor. The convention for keys of this dictionary again differs for different TNs, but (roughly speaking) it's supposed to specify whether the corresponding ``ITPOTerm`` is left, down, or right effective operator. Upon initialization, ``ITPO.eff_ops`` is an empty dictionary. The actual effective operators are computed once ``ITPO.contr_to_eff_op()`` is called. **See the more detailed documentation of individual functions below** .. autoclass:: qtealeaves.mpos.ITPOTerm :members: .. autoclass:: qtealeaves.mpos.ITPOSites :members: .. autoclass:: qtealeaves.mpos.ITPO :members: ------------------------------------------------------------------------------- Sparse matrix operators ----------------------- .. autoclass:: qtealeaves.mpos.SparseMatrixOperator :members: .. autoclass:: qtealeaves.mpos.SparseMatrixOperatorPy :members: ------------------------------------------------------------------------------- Sparse matrix product operators ------------------------------- .. autoclass:: qtealeaves.mpos.SparseMPO :members: .. autoclass:: qtealeaves.mpos.SparseMatrixProductOperator :members: ------------------------------------------------------------------------------- Abstract effective operators ---------------------------- .. autoclass:: qtealeaves.mpos._AbstractEffectiveOperators :members: ------------------------------------------------------------------------------- Disentanglers ------------- .. autoclass:: qtealeaves.mpos.DELayer :members: ------------------------------------------------------------------------------- TTN Projector -------------