quimb.experimental.merabuilder ============================== .. py:module:: quimb.experimental.merabuilder .. autoapi-nested-parse:: Tools for constructing MERA for arbitrary geometry. TODO:: - [ ] 2D, 3D MERA classes - [ ] general strategies for arbitrary geometries - [ ] layer_tag? and hanling of other attributes - [ ] handle dangling case - [ ] invariant generators? DONE:: - [x] layer_gate methods for arbitrary geometry - [x] 1D: generic way to handle finite and open boundary conditions - [x] hook into other arbgeom infrastructure for computing rdms etc Classes ------- .. autoapisummary:: quimb.experimental.merabuilder.TensorNetworkGenIso quimb.experimental.merabuilder.MERA Functions --------- .. autoapisummary:: quimb.experimental.merabuilder.calc_1d_unis_isos quimb.experimental.merabuilder.TTN_randtree_rand Module Contents --------------- .. py:class:: TensorNetworkGenIso(ts=(), *, virtual=False, check_collisions=True) Bases: :py:obj:`quimb.tensor.tensor_arbgeom.TensorNetworkGenVector` A class for building generic 'isometric' or MERA like tensor network states with arbitrary geometry. After supplying the underyling `sites` of the problem - which can be an arbitrary sequence of hashable objects - one places either unitaries, isometries or tree tensors layered above groups of sites. The isometric and tree tensors effectively coarse grain blocks into a single new site, and the unitaries generally 'disentangle' between blocks. .. py:attribute:: _EXTRA_PROPS :value: ('_site_tag_id', '_sites', '_site_ind_id', '_layer_ind_id') .. py:method:: empty(sites, phys_dim=2, site_tag_id='I{}', site_ind_id='k{}', layer_ind_id='l{}') :classmethod: .. py:property:: layer_ind_id .. py:method:: layer_ind(site) .. py:method:: layer_gate_raw(G, where, iso=True, new_sites=None, tags=None, all_site_tags=None) Build out this MERA by placing either a new unitary, isometry or tree tensor, given by ``G``, at the sites given by ``where``. This handles propagating the lightcone of tags and marking the correct indices of the ``IsoTensor`` as ``left_inds``. :param G: The raw array to place at the sites. Its shape determines whether it is a unitary or isometry/tree. It should have ``k + len(where)`` dimensions. For a unitary ``k == len(where)``. If it is an isometry/tree, ``k`` will generally be ``1``, or ``0`` to 'cap' the MERA. The rightmost indices are those attached to the current open layer indices. :type G: array_like :param where: The sites to layer the tensor above. :type where: sequence of hashable :param iso: Whether to declare the tensor as an unitary/isometry by marking the left indices. If ``iso = False`` (a 'tree' tensor) then one should have ``k <= 1``. Once you have such a 'tree' tensor you cannot place isometries or unitaries above it. It will also have the lightcone tags of every site. Technically one could place 'PEPS' style tensor with ``iso = False`` and ``k > 1`` but some methods might break. :type iso: bool, optional :param new_sites: Which sites to make new open sites. If not given, defaults to the first ``k`` sites in ``where``. :type new_sites: sequence of hashable, optional :param tags: Custom tags to add to the new tensor, in addition to the automatically generated site tags. :type tags: sequence of str, optional :param all_site_tags: For performance, supply all site tags to avoid recomputing them. :type all_site_tags: sequence of str, optional .. py:method:: layer_gate_fill_fn(fill_fn, operation, where, max_bond, new_sites=None, tags=None, all_site_tags=None) Build out this MERA by placing either a new unitary, isometry or tree tensor at sites ``where``, generating the data array using ``fill_fn`` and maximum bond dimension ``max_bond``. :param fill_fn: A function with signature ``fill_fn(shape) -> array_like``. :type fill_fn: callable :param operation: The type of tensor to place. :type operation: {"iso", "uni", "cap", "tree", "treecap"} :param where: The sites to layer the tensor above. :type where: sequence of hashable :param max_bond: The maximum bond dimension of the tensor. This only applies for isometries and trees and when the product of the lower dimensions is greater than ``max_bond``. :type max_bond: int :param new_sites: Which sites to make new open sites. If not given, defaults to the first ``k`` sites in ``where``. :type new_sites: sequence of hashable, optional :param tags: Custom tags to add to the new tensor, in addition to the automatically generated site tags. :type tags: sequence of str, optional :param all_site_tags: For performance, supply all site tags to avoid recomputing them. :type all_site_tags: sequence of str, optional .. seealso:: :obj:`layer_gate_raw` .. py:method:: partial_trace(keep, optimize='auto-hq', rehearse=False, preserve_tensor=False, **contract_opts) Partial trace out all sites except those in ``keep``, making use of the lightcone structure of the MERA. :param keep: The sites to keep. :type keep: sequence of hashable :param optimize: The contraction ordering strategy to use. :type optimize: str or PathOptimzer, optional :param rehearse: Whether to rehearse the contraction rather than actually performing it. If: - ``False``: perform the contraction and return the reduced density matrix, - "tn": just the lightcone tensor network is returned, - "tree": just the contraction tree that will be used is returned. :type rehearse: {False, "tn", "tree"}, optional :param contract_opts: Additional options to pass to :func:`~quimb.tensor.tensor_core.tensor_contract`. :returns: The reduced density matrix on sites ``keep``. :rtype: array_like .. py:method:: local_expectation(G, where, optimize='auto-hq', rehearse=False, **contract_opts) Compute the expectation value of a local operator ``G`` at sites ``where``. This is done by contracting the lightcone tensor network to form the reduced density matrix, before taking the trace with ``G``. :param G: The local operator to compute the expectation value of. :type G: array_like :param where: The sites to compute the expectation value at. :type where: sequence of hashable :param optimize: The contraction ordering strategy to use. :type optimize: str or PathOptimzer, optional :param rehearse: Whether to rehearse the contraction rather than actually performing it. See :meth:`~quimb.tensor.mera.MERA.partial_trace` for details. :type rehearse: {False, "tn", "tree"}, optional :param contract_opts: Additional options to pass to :func:`~quimb.tensor.tensor_core.tensor_contract`. :returns: The expectation value of ``G`` at sites ``where``. :rtype: float .. seealso:: :obj:`partial_trace` .. py:method:: compute_local_expectation(terms, optimize='auto-hq', return_all=False, rehearse=False, executor=None, progbar=False, **contract_opts) Compute the expectation value of a collection of local operators ``terms`` at sites ``where``. This is done by contracting the lightcone tensor network to form the reduced density matrices, before taking the trace with each ``G`` in ``terms``. :param terms: The local operators to compute the expectation value of, keyed by the sites they act on. :type terms: dict[tuple[hashable], array_like] :param optimize: The contraction ordering strategy to use. :type optimize: str or PathOptimzer, optional :param return_all: Whether to return all the expectation values, or just the sum. :type return_all: bool, optional :param rehearse: Whether to rehearse the contraction rather than actually performing it. See :meth:`~quimb.tensor.mera.MERA.partial_trace` for details. :type rehearse: {False, "tn", "tree"}, optional :param executor: The executor to use for parallelism. :type executor: Executor, optional :param progbar: Whether to show a progress bar. :type progbar: bool, optional :param contract_opts: Additional options to pass to :func:`~quimb.tensor.tensor_core.tensor_contract`. .. py:method:: expand_bond_dimension(new_bond_dim, rand_strength=0.0, inds_to_expand=None, inplace=False) Expand the maxmimum bond dimension of this isometric tensor network to ``new_bond_dim``. Unlike :meth:`~quimb.tensor.tensor_core.TensorNetwork.expand_bond_dimension` this proceeds from the physical indices upwards, and only increases a bonds size if ``new_bond_dim`` is larger than product of the lower indices dimensions. :param new_bond_dim: The new maximum bond dimension to expand to. :type new_bond_dim: int :param rand_strength: The strength of random noise to add to the new array entries, if any. :type rand_strength: float, optional :param inds_to_expand: The indices to expand, if not all. :type inds_to_expand: sequence of str, optional :param inplace: Whether to expand this tensor network in place, or return a new one. :type inplace: bool, optional :rtype: TensorNetworkGenIso .. py:attribute:: expand_bond_dimension_ .. py:function:: calc_1d_unis_isos(sites, block_size, cyclic, group_from_right) Given ``sites``, assumed to be in a 1D order, though not neccessarily contiguous, calculate unitary and isometry groupings:: │ │ <- new grouped site ┐ ┌─────┐ ┌─────┐ ┌ │ │ ISO │ │ ISO │ │ ┘ └─────┘ └─────┘ └ │ │..│..│ │..│..│ │ ┌───┐ │ ┌───┐ │ ┌───┐ │UNI│ │ │UNI│ │ │UNI│ └───┘ │ └───┘ │ └───┘ │ │ ... │ │ ... │ │ ^^^^^^^ <- isometry groupings of size, block_size ^^^^^ ^^^^^ <- unitary groupings of size 2 :param sites: The sites to apply a layer to. :type sites: sequence of hashable :param block_size: How many sites to group together per isometry block. Note that currently the unitaries will only ever act on blocks of size 2 across isometry block boundaries. :type block_size: int :param cyclic: Whether to apply disentangler / unitaries across the boundary. The isometries will never be applied across the boundary, but since they always form a tree such a bipartition is natural. :type cyclic: bool :param group_from_right: Wether to group the sites starting from the left or right. This only matters if ``block_size`` does not divide the number of sites. Alternating between left and right more evenly tiles the unitaries and isometries, especially at lower layers. :type group_from_right: bool :returns: * **unis** (*list[tuple]*) -- The unitary groupings. * **isos** (*list[tuple]*) -- The isometry groupings. .. py:class:: MERA(*args, **kwargs) Bases: :py:obj:`quimb.tensor.tensor_1d.TensorNetwork1DVector`, :py:obj:`TensorNetworkGenIso` Replacement class for ``MERA`` which uses the new infrastructure and thus has methods like ``compute_local_expectation``. .. py:attribute:: _EXTRA_PROPS .. py:attribute:: _CONTRACT_STRUCTURED :value: False .. py:attribute:: _num_layers :value: None .. py:method:: from_fill_fn(fill_fn, L, D, phys_dim=2, block_size=2, cyclic=True, uni_fill_fn=None, iso_fill_fn=None, cap_fill_fn=None, **kwargs) :classmethod: Create a 1D MERA using ``fill_fn(shape) -> array_like`` to fill the tensors. :param fill_fn: A function which takes a shape and returns an array_like of that shape. You can override this specfically for the unitaries, isometries and cap tensors using the kwargs ``uni_fill_fn``, ``iso_fill_fn`` and ``cap_fill_fn``. :type fill_fn: callable :param L: The number of sites. :type L: int :param D: The maximum bond dimension. :type D: int :param phys_dim: The dimension of the physical indices. :type phys_dim: int, optional :param block_size: The size of the isometry blocks. Binary MERA is the default, ternary MERA is ``block_size=3``. :type block_size: int, optional :param cyclic: Whether to apply disentangler / unitaries across the boundary. The isometries will never be applied across the boundary, but since they always form a tree such a bipartition is natural. :type cyclic: bool, optional :param uni_fill_fn: A function which takes a shape and returns an array_like of that shape. This is used to fill the unitary tensors. If ``None`` then ``fill_fn`` is used. :type uni_fill_fn: callable, optional :param iso_fill_fn: A function which takes a shape and returns an array_like of that shape. This is used to fill the isometry tensors. If ``None`` then ``fill_fn`` is used. :type iso_fill_fn: callable, optional :param cap_fill_fn: A function which takes a shape and returns an array_like of that shape. This is used to fill the cap tensors. If ``None`` then ``fill_fn`` is used. :type cap_fill_fn: callable, optional :param kwargs: Supplied to ``TensorNetworkGenIso.__init__``. .. py:method:: rand(L, D, seed=None, block_size=2, phys_dim=2, cyclic=True, isometrize_method='svd', **kwargs) :classmethod: Return a random (optionally isometrized) MERA. :param L: The number of sites. :type L: int :param D: The maximum bond dimension. :type D: int :param seed: A random seed. :type seed: int, optional :param block_size: The size of the isometry blocks. Binary MERA is the default, ternary MERA is ``block_size=3``. :type block_size: int, optional :param phys_dim: The dimension of the physical indices. :type phys_dim: int, optional :param cyclic: Whether to apply disentangler / unitaries across the boundary. The isometries will never be applied across the boundary, but since they always form a tree such a bipartition is natural. :type cyclic: bool, optional :param isometrize_method: If given, the method to use to isometrize the MERA. If ``None`` then the MERA is not isometrized. :type isometrize_method: str or None, optional .. py:property:: num_layers .. py:function:: TTN_randtree_rand(sites, D, phys_dim=2, group_size=2, iso=False, seed=None, **kwargs) Return a randomly constructed tree tensor network. :param sites: The sites of the tensor network. :type sites: list of hashable :param D: The maximum bond dimension. :type D: int :param phys_dim: The dimension of the physical indices. :type phys_dim: int, optional :param group_size: How many sites to group together in each tensor. :type group_size: int, optional :param iso: Whether to build the tree with an isometric flow towards the top. :type iso: bool, optional :param seed: A random seed. :type seed: int, optional :param kwargs: Supplied to ``TensorNetworkGenIso.empty``. :returns: **ttn** -- The tree tensor network. :rtype: TensorNetworkGenIso