quimb.tensor.tn2dinf.core ========================= .. py:module:: quimb.tensor.tn2dinf.core .. autoapi-nested-parse:: Infinite, translation-invariant 2D tensor networks on a unit cell: the flat single-tensor-per-site base and the PEPS wavefunction. See the subpackage ``__init__`` for the shared vocabulary. Classes ------- .. autoapisummary:: quimb.tensor.tn2dinf.core.TensorNetworkInfinite2DFlat quimb.tensor.tn2dinf.core.PEPSInfinite2D Module Contents --------------- .. py:class:: TensorNetworkInfinite2DFlat(geometry_or_edges, site_tag_id='I{}', bond_ind_id='b{},{}', site_type_tag_id='SITE_TYPE_{}') Base class for an infinite, translation-invariant 2D tensor network with a **single tensor per site** ('flat'), defined by a unit cell (``GeometryInfinite2D``). It explicitly stores the ``[-1, 1]^2`` block of cells as a ``fragment`` tensor network and keeps two translation-invariance registers: ``shared_tensors[site_type]`` and ``shared_indices[bond_type]``. Subclasses specialize the per-site legs and the fragment type via ``get_site_inds`` (+ ``get_site_shape`` / ``get_site_duals``) and ``_new_fragment``, e.g. ``PEPSInfinite2D`` for a wavefunction (physical index per site). On its own this base is a bare virtual-bond network, e.g. a classical network. :param geometry_or_edges: The unit-cell geometry, or a sequence of edges to build one from. :type geometry_or_edges: GeometryInfinite2D or sequence of edges :param site_tag_id: Format string for a site's tensor tag, formatted with the site. :type site_tag_id: str, optional :param bond_ind_id: Format string for a bond index, formatted with its two sorted sites. :type bond_ind_id: str, optional :param site_type_tag_id: Format string for a ``site_type``'s shared tag. :type site_type_tag_id: str, optional .. py:attribute:: site_tag_id :value: 'I{}' .. py:attribute:: bond_ind_id :value: 'b{},{}' .. py:attribute:: site_type_tag_id :value: 'SITE_TYPE_{}' .. py:attribute:: shared_tensors .. py:attribute:: shared_indices .. py:attribute:: fragment .. py:attribute:: _sites .. py:method:: _new_fragment(sites) Build the empty ``fragment`` tensor network over ``sites``. The base is a bare ``TensorNetworkGen`` (virtual bonds only); subclasses choose a richer type (and any physical ids). .. py:method:: site_tag(site) The tag of the tensor at ``site`` in the fragment tensor network. .. py:method:: site_type_tag(site_type) The shared tag applied to every tensor of ``site_type`` in the fragment tensor network. .. py:method:: get_site_inds(site) Index names of ``site``'s tensor, one per bond in ``get_site_neighbors`` order. Subclasses append extra legs (e.g. a physical index) via ``super().get_site_inds(site)``. .. py:method:: get_site_shape(site, bond_dim) Leg sizes of ``site``'s tensor, in ``get_site_inds`` order: one ``bond_dim`` per bond. .. py:method:: get_site_duals(site) The symmray ``dual`` flag per leg of ``site``'s tensor, in ``get_site_inds`` order. A bond leg is ``dual=False`` when ``site`` is the first endpoint of the bond's canonical ``bond_type`` and ``True`` when it is the second, giving opposite duals on the two ends of every bond. For symmetric (symmray) builders. .. py:method:: get_site_tags(site) The tags of the tensor at ``site`` in the fragment tensor network: the site tag and the site_type tag. .. py:method:: _block_fill(fill_fn, shape_fn) Populate the whole ``[-1, 1]^2`` block: the first tensor of each site_type gets ``fill_fn(shape_fn(site))``, later translates reuse it. .. py:method:: copy(deep=False) Copy this infinite tensor network. The ``geometry`` is shared (it is static configuration), while the explicit ``fragment`` and the shared-tensor and shared-index registers are copied so the two networks can be mutated independently. :param deep: If ``False`` (the default), the underlying numeric data arrays are shared between the two networks, matching ``TensorNetwork.copy``. If ``True``, the data arrays are copied too. :type deep: bool, optional :rtype: TensorNetworkInfinite2DFlat .. py:property:: site_types .. py:property:: site_type_tags .. py:method:: has_fragment_site(site) Check if `site` is currently present in the fragment tensor network. .. py:method:: get_bond_ind(sitea, siteb) Get the name of the bond index between two sites, invariant to which order they are supplied. .. py:method:: get_bond_type(sitea, siteb) Get the bond type between two sites, invariant to which order they are supplied. .. py:method:: add_fragment_site(site, data=None) Add, if not already present, ``site`` to the explicit fragment tensor network. No-op if ``site`` is already present. The bond and physical dimensions are defined by ``data``; ``data`` is required for the first site of each site_type and reused (shared) by all its translates, so it is ignored for later sites of the same type. Sites are normally added by a constructor (``.rand`` / ``.from_fill_fn``). :param site: The site to add, as ``(cell, site_type)``. Must lie within the ``[-1, 1]^2`` neighbor region of the unit cell. :type site: tuple[tuple[int, int], hashable] :param data: The tensor data for the first site of a new site_type (its legs are the bonds in ``get_site_neighbors`` order then any extra legs, see ``get_site_shape``). Reused for later translates. :type data: array_like, optional .. py:method:: _sync_site(site, t=None) Broadcast the data from `site` to every site of that `site_type`. The tensor is retrieved from the current fragment tensor network or you can explicitly supply it if you have it. .. py:method:: _sync_bond(bond_type, bond_ind, gauges) Broadcast the gauge on ``bond_ind`` to every index of bond_type. .. py:method:: gauge_all_simple(max_iterations=5, tol=0.0, smudge=1e-12, power=1.0, gauges=None, fuse_multibonds=False, info=None, progbar=False, inplace=False) Iterative gauge all the bonds in this tensor network with a 'simple update' like strategy. If gauges are not supplied they are initialized and then reabsorbed at the end, in which case this method acts as a kind of conditioning. More usefully, if you supply `gauges` then they will be updated inplace and *not* absorbed back into the tensor network, with the assumption that you are using/tracking them externally. As the tensors and bond weights are updated, changes are propagated to all globally shared bond and site types. :param max_iterations: The maximum number of gauging sweeps over all ``bond_types``. :type max_iterations: int, optional :param tol: The convergence tolerance on the singular values. Only enables early stopping if greater than 0.0. :type tol: float, optional :param smudge: A small value to add to the singular values when gauging. :type smudge: float, optional :param power: A power to raise the singular values to when gauging. :type power: float, optional :param gauges: The store of bond gauges, keyed by bond index in the fragment. If supplied, it is updated inplace and the gauges are left on the bonds. If not, an internal store is used and reabsorbed into the tensors at the end. :type gauges: dict, optional :param fuse_multibonds: Accepted for signature compatibility, only ``False`` is supported (bonds are gauged one ``bond_type`` representative at a time, never fused). :type fuse_multibonds: bool, optional :param info: Store extra information about the gauging process in this dict. The following keys are filled: - 'iterations': the number of sweeps performed. - 'max_sdiff': the maximum singular value difference of the final sweep (``-1.0`` if no diffs were computed). :type info: dict, optional :param progbar: Whether to show a progress bar tracking the max singular value change per sweep. :type progbar: bool, optional :param inplace: Whether to gauge this network inplace or return a gauged copy. :type inplace: bool, optional :rtype: TensorNetworkInfinite2DFlat .. py:attribute:: gauge_all_simple_ .. py:method:: max_bond() The largest bond dimension in the fragment. .. py:method:: gauge_simple_insert(gauges) Absorb the bond ``gauges`` into the tensors, split half-half per ``bond_type`` representative and synced to translates. The ``gauges`` dict is read but not modified (matching ``TensorNetwork.gauge_simple_insert``). .. py:method:: normalize_simple(gauges) Normalize the state and bond ``gauges`` in place, translation invariantly: each gauge to unit 2-norm, and each ``site_type`` to unit local norm. The local norm is computed on the cell ``(0, 0)`` representative (always fully interior, so all its bonds carry gauges) and the rescaled tensor synced to all translates. .. py:method:: _region_sites(where, radius) The set of sites within ``radius`` hops of any site in ``where``. .. py:method:: build_fragment(sites) Build a standalone fragment tensor network over an arbitrary set of ``sites``, filling each with its ``site_type``'s shared data so the patch is translation-consistent with this network. Unlike the main ``fragment``, ``sites`` are not restricted to the ``[-1, 1]^2`` block; this is how the larger neighborhoods needed by ``max_distance > 0`` clusters and generalized-loop expansions are materialized without growing the main fragment. Bonds to sites outside ``sites`` are left dangling. Use ``build_fragment_with_gauges`` to also get a tiled gauge store for the environment. :param sites: The sites to include in the fragment. :type sites: iterable[site] :rtype: TensorNetworkGen .. py:method:: build_fragment_with_gauges(sites, gauges) Build a fragment over ``sites`` (see ``build_fragment``) together with a copy of ``gauges`` tiled onto every bond present, including the dangling boundary bonds, so it can serve as the environment. :param sites: The sites to include in the fragment. :type sites: iterable[site] :param gauges: A bond-gauge store keyed by the main fragment's bond indices. The tiled copy is keyed by *this* fragment's own (translated) bond indices, each taking the value of its canonical ``bond_type`` gauge (the cell (0, 0) representative, always present). :type gauges: dict :returns: * **fragment** (*TensorNetworkGen*) * **fragment_gauges** (*dict*) .. py:class:: PEPSInfinite2D(geometry_or_edges, site_tag_id='I{}', site_ind_id='k{}', bond_ind_id='b{},{}', site_type_tag_id='SITE_TYPE_{}') Bases: :py:obj:`TensorNetworkInfinite2DFlat` Infinite 2D PEPS: a translation-invariant wavefunction with one physical index per site, on a unit cell (``GeometryInfinite2D``). Adds the physical leg, gates, and cluster expectations to ``TensorNetworkInfinite2DFlat``. :param geometry_or_edges: The unit-cell geometry, or a sequence of edges to build one from. :type geometry_or_edges: GeometryInfinite2D or sequence of edges :param site_tag_id: Format string for a site's tensor tag, formatted with the site. :type site_tag_id: str, optional :param site_ind_id: Format string for a site's physical index, formatted with the site. :type site_ind_id: str, optional :param bond_ind_id: Format string for a bond index, formatted with its two sorted sites. :type bond_ind_id: str, optional :param site_type_tag_id: Format string for a ``site_type``'s shared tag. :type site_type_tag_id: str, optional .. py:attribute:: site_ind_id :value: 'k{}' .. py:method:: from_fill_fn(fill_fn, geometry_or_edges, bond_dim, phys_dim=2, site_tag_id='I{}', site_ind_id='k{}', bond_ind_id='b{},{}', site_type_tag_id='SITE_TYPE_{}') :classmethod: Build a PEPS, filling each site_type's tensor with ``fill_fn(shape) -> array`` (``fill_fn`` first, matching ``quimb.tensor.tensor_builder.TN_from_edges_and_fill_fn``). :param fill_fn: Called as ``fill_fn(shape) -> array`` once per ``site_type`` to generate its shared tensor data. :type fill_fn: callable :param geometry_or_edges: The unit-cell geometry, or a sequence of edges to build one from. :type geometry_or_edges: GeometryInfinite2D or sequence of edges :param bond_dim: The virtual bond dimension. :type bond_dim: int :param phys_dim: The physical dimension. :type phys_dim: int, optional :param site_tag_id: Format strings for tags and indices, see the class docstring. :type site_tag_id: str, optional :param site_ind_id: Format strings for tags and indices, see the class docstring. :type site_ind_id: str, optional :param bond_ind_id: Format strings for tags and indices, see the class docstring. :type bond_ind_id: str, optional :param site_type_tag_id: Format strings for tags and indices, see the class docstring. :type site_type_tag_id: str, optional :rtype: PEPSInfinite2D .. py:method:: rand(geometry_or_edges, bond_dim, phys_dim=2, *, seed=None, dtype='float64', site_tag_id='I{}', site_ind_id='k{}', bond_ind_id='b{},{}', site_type_tag_id='SITE_TYPE_{}', **randn_opts) :classmethod: Build a PEPS with random dense tensors. :param geometry_or_edges: The unit-cell geometry, or a sequence of edges to build one from. :type geometry_or_edges: GeometryInfinite2D or sequence of edges :param bond_dim: The virtual bond dimension. :type bond_dim: int :param phys_dim: The physical dimension. :type phys_dim: int, optional :param seed: Random seed for reproducibility. :type seed: int, optional :param dtype: The data type of the random entries. :type dtype: str, optional :param site_tag_id: Format strings for tags and indices, see the class docstring. :type site_tag_id: str, optional :param site_ind_id: Format strings for tags and indices, see the class docstring. :type site_ind_id: str, optional :param bond_ind_id: Format strings for tags and indices, see the class docstring. :type bond_ind_id: str, optional :param site_type_tag_id: Format strings for tags and indices, see the class docstring. :type site_type_tag_id: str, optional :param randn_opts: Supplied to the random fill function. :rtype: PEPSInfinite2D .. py:method:: _new_fragment(sites) Build the empty ``fragment`` tensor network over ``sites``. The base is a bare ``TensorNetworkGen`` (virtual bonds only); subclasses choose a richer type (and any physical ids). .. py:method:: get_site_inds(site) Index names of ``site``'s tensor, one per bond in ``get_site_neighbors`` order. Subclasses append extra legs (e.g. a physical index) via ``super().get_site_inds(site)``. .. py:method:: get_site_shape(site, bond_dim, phys_dim=2) Leg sizes of ``site``'s tensor, in ``get_site_inds`` order: one ``bond_dim`` per bond. .. py:method:: get_site_duals(site) The symmray ``dual`` flag per leg of ``site``'s tensor, in ``get_site_inds`` order. A bond leg is ``dual=False`` when ``site`` is the first endpoint of the bond's canonical ``bond_type`` and ``True`` when it is the second, giving opposite duals on the two ends of every bond. For symmetric (symmray) builders. .. py:method:: copy(deep=False) Copy this infinite tensor network. The ``geometry`` is shared (it is static configuration), while the explicit ``fragment`` and the shared-tensor and shared-index registers are copied so the two networks can be mutated independently. :param deep: If ``False`` (the default), the underlying numeric data arrays are shared between the two networks, matching ``TensorNetwork.copy``. If ``True``, the data arrays are copied too. :type deep: bool, optional :rtype: TensorNetworkInfinite2DFlat .. py:method:: gate_simple(G, where, gauges, *, max_bond=None, cutoff=1e-10, renorm=True, smudge=1e-12, power=1.0, path=None, info=None, inplace=False, **gate_opts) Apply a gate ``G`` at sites ``where`` with local truncated gauging, then propagate the updated tensors and bond gauges to all translates. Supports one-site gates (``where`` a single site), nearest-neighbor two-site gates, and long-range two-site gates. Long-range gates are applied as an MPO string along a path of sites between the two endpoints (the path must stay within the fragment), updating every tensor and bond gauge on the path. Delegates the actual gate to the fragment ``TensorNetworkGenVector``. :param G: The gate to apply (e.g. an exponentiated local Hamiltonian term). :type G: array_like :param where: The site(s) to gate, e.g. ``(site,)`` or a ``bond_type`` ``(site_a, site_b)``. :type where: site or sequence[site] :param gauges: Diagonal bond gauges (environments), keyed by bond index. Modified in place (the only way to access the updated bond gauges). :type gauges: dict :param max_bond: The maximum bond dimension to keep. :type max_bond: int, optional :param cutoff: The singular value cutoff. :type cutoff: float, optional :param renorm: Whether to renormalize the new bond gauges before storing them. :type renorm: bool, optional :param smudge: Numerical stabilization of the bond environments. :type smudge: float, optional :param power: Numerical stabilization of the bond environments. :type power: float, optional :param path: For long-range gates, the explicit path of sites to use. If None any shortest path will be used. :type path: sequence[site], optional :param inplace: Whether to gate this network inplace or a copy. :type inplace: bool, optional :rtype: PEPSInfinite2D .. py:attribute:: gate_simple_ .. py:method:: get_cluster(where, gauges=None, max_distance=0, **kwargs) Get the local wavefunction cluster around ``where``, optionally inserting the bond ``gauges`` as the environment. Delegates to a fragment ``TensorNetworkGenVector``. For ``max_distance=0`` the main ``[-1, 1]^2`` fragment is used. Larger clusters are computed on a freshly built fragment tiled out to the ``max_distance`` neighborhood of ``where`` (see ``build_fragment``). .. py:method:: partial_trace_cluster(where, gauges=None, max_distance=0, normalized=True, **kwargs) Approximate reduced density matrix at sites ``where``, formed by partial-tracing a ``max_distance``-cluster with the bond ``gauges`` as the environment. Delegates to a fragment ``TensorNetworkGenVector`` (``get_cluster`` then ``partial_trace_exact``). :param where: The sites to keep. :type where: sequence[site] :param gauges: Diagonal bond gauges (environments), keyed by bond index. :type gauges: dict, optional :param max_distance: The graph distance neighborhood to include (``0`` uses the main fragment, ``> 0`` builds a tiled fragment). :type max_distance: int, optional :param normalized: Whether to normalize the reduced density matrix. :type normalized: bool, optional :rtype: array_like .. py:method:: local_expectation_cluster(G, where, gauges=None, max_distance=0, normalized=True, **kwargs) Approximate local expectation of gate ``G`` at sites ``where``, using a ``max_distance``-cluster with the bond ``gauges`` as the environment. Delegates to a fragment ``TensorNetworkGenVector``. :param G: The gate to compute the expectation of. :type G: array_like :param where: The sites to compute the expectation at (e.g. a ``bond_type``). :type where: sequence[site] :param gauges: Diagonal bond gauges (environments), keyed by bond index. :type gauges: dict, optional :param max_distance: The graph distance neighborhood to include (``0`` uses the main fragment, ``> 0`` builds a tiled fragment). :type max_distance: int, optional :param normalized: Whether to divide by the local norm (expectation of the identity). :type normalized: bool, optional :rtype: float .. py:method:: compute_local_expectation_cluster(terms, gauges=None, max_distance=0, normalized=True, return_all=False, **kwargs) Sum the local cluster expectations of ``terms`` over the unit cell, e.g. to estimate the energy per unit cell from a ``LocalHamInfinite2D``. :param terms: Anything with an ``.items()`` yielding ``(where, gate)``, where ``where`` is a ``bond_type``. :type terms: LocalHamInfinite2D or dict[bond_type, array_like] :param gauges: Diagonal bond gauges (environments), keyed by bond index. :type gauges: dict, optional :param max_distance: The graph distance neighborhood to include (``0`` uses the main fragment, ``> 0`` builds a single tiled fragment covering all terms). :type max_distance: int, optional :param normalized: Whether to locally normalize each term. :type normalized: bool, optional :param return_all: If ``True`` return the per-``bond_type`` expectations instead of their sum. :type return_all: bool, optional :rtype: float or dict[bond_type, float] .. py:method:: _gloop_region(where, gloops) The set of sites needed to evaluate a generalized-loop expansion of size ``gloops`` around ``where``. An explicit set of loops contributes exactly its sites; an integer max-size or ``None`` (smallest loop) is turned into a conservative graph-distance radius (a loop of ``C`` sites reaches at most ``~C // 2`` hops out and back). .. py:method:: local_expectation_gloop_expand(G, where, gloops=None, gauges=None, normalized=True, **kwargs) Approximate local expectation of gate ``G`` at sites ``where`` via a generalized-loop expansion with the bond ``gauges`` as the environment. Computed on a freshly built fragment tiled out far enough to hold the loops (see ``build_fragment`` / ``_gloop_region``); delegates to the fragment ``TensorNetworkGenVector``. :param G: The gate to compute the expectation of. :type G: array_like :param where: The sites to compute the expectation at (e.g. a ``bond_type``). :type where: sequence[site] :param gloops: The generalized loops to use, or an integer max loop size, or ``None`` for the smallest non-trivial loop. :type gloops: None, int, or sequence[sequence[site]], optional :param gauges: Diagonal bond gauges (environments), keyed by bond index. :type gauges: dict, optional :param normalized: Whether and how to normalize the result. :type normalized: bool, optional :rtype: float .. py:method:: compute_local_expectation_gloop_expand(terms, gloops=None, *, gauges=None, normalized=True, return_all=False, **kwargs) Sum the generalized-loop-expansion expectations of ``terms`` over the unit cell, e.g. an energy per unit cell that is cheaper than (though less accurate than) the equivalent-size cluster estimate. Computed on a single fragment tiled out to hold the loops around every term; delegates to the fragment ``TensorNetworkGenVector``. :param terms: Anything with an ``.items()`` yielding ``(where, gate)``. :type terms: LocalHamInfinite2D or dict[bond_type, array_like] :param gloops: The generalized loops to use, or an integer max loop size, or ``None`` for the smallest non-trivial loop. :type gloops: None, int, or sequence[sequence[site]], optional :param gauges: Diagonal bond gauges (environments), keyed by bond index. :type gauges: dict, optional :param normalized: Whether and how to normalize the result. :type normalized: bool, optional :param return_all: If ``True`` return the per-``bond_type`` expectations instead of their sum. :type return_all: bool, optional :rtype: float or dict[bond_type, float]