quimb.tensor.circuit.pepo ========================= .. py:module:: quimb.tensor.circuit.pepo .. autoapi-nested-parse:: PEPO simple-update circuit simulator. Classes ------- .. autoapisummary:: quimb.tensor.circuit.pepo.CircuitPEPOSimpleUpdate Module Contents --------------- .. py:class:: CircuitPEPOSimpleUpdate(N=None, *, edges=None, gates=None, max_bond=None, cutoff=1e-10, gate_contract='reduce-split', gate_opts=None, dtype=None, to_backend=None, convert_eager=True, **circuit_opts) Bases: :py:obj:`quimb.tensor.circuit.simple_update.CircuitSimpleUpdate` Quantum circuit simulator that evolves an observable *backwards* in time, in the Heisenberg picture, by representing it as an arbitrary geometry PEPO and applying the gates with the simple update rule. Rather than evolving a state forwards, gates are simply recorded as they are applied; no contraction happens until an expectation value is requested. When :meth:`local_expectation` (or :meth:`get_evolved_operator`) is called, the local observable is built as a bond dimension 1 PEPO on the supplied ``edges`` and the recorded gates are applied in reverse order as :math:`O \rightarrow G^\dagger O G`, using :func:`~quimb.tensor.tnag.core.tensor_network_ag_gate_simple` (Vidal-style gauging plus compression). Gates that fall outside the reverse lightcone of the observable are skipped, since :math:`G^\dagger G = 1`. The evolved operator is finally projected onto the ``|00...0>`` initial state. This is the Heisenberg-picture companion to :class:`CircuitPEPSSimpleUpdate`, useful on lattices where evolving the full state is intractable but a single local observable can be evolved in a truncated, gauged operator network. :param N: The number of qubits. If not given it is inferred from the geometry. Supply it to pad the geometry up to ``N`` sites. :type N: int, optional :param edges: The edges defining the geometry. A bond is placed between each pair of sites, and two-qubit gates are only supported on these edges. If not given the geometry is inferred from the two-qubit ``gates``. :type edges: sequence[tuple[hashable, hashable]], optional :param gates: If ``edges`` is not given, infer the geometry from the two-qubit gates in this sequence (the gates are only inspected here, not applied). :type gates: sequence, optional :param max_bond: The maximum bond dimension to compress the operator to as gates are applied during the backwards evolution. :type max_bond: int, optional :param cutoff: The singular value cutoff to use when compressing. :type cutoff: float, optional :param gate_contract: How to split a two site gate, see :func:`~quimb.tensor.tnag.core.tensor_network_ag_gate_simple`. :type gate_contract: str, optional :param gate_opts: Default options forwarded to ``gate_simple_`` such as ``max_bond``, ``cutoff`` and ``renorm``. This is the single source of truth for the compression options; ``max_bond`` and ``cutoff`` are also exposed as properties. :type gate_opts: dict, optional :param dtype: If given, ensure the evolved operator tensors are cast to this data type. :type dtype: str, optional :param to_backend: If given, apply this function to the operator tensors and gate arrays to convert them to a particular array backend. :type to_backend: callable, optional :param convert_eager: Whether to apply the ``dtype`` and ``to_backend`` conversions to the freshly built operator, the observable, and each gate array as it is applied. The backwards evolution contracts every gate immediately, so there is no lazy stage to defer the conversion to, and ``False`` thus leaves all arrays as supplied. :type convert_eager: bool, optional .. attribute:: edges The unique edges defining the geometry. :type: tuple[tuple[hashable, hashable]] .. attribute:: sites The sites (qubit labels). :type: tuple[hashable] .. attribute:: gates The gates recorded so far. :type: tuple[Gate] .. rubric:: Examples >>> import quimb.tensor as qtn >>> edges = [(0, 1), (1, 2), (2, 3)] >>> circ = qtn.CircuitPEPOSimpleUpdate(edges=edges, max_bond=16) >>> circ.apply_gates(gates) # no computation happens here >>> circ.local_expectation(qu.pauli("Z"), 1) # evolve + contract here .. seealso:: :py:obj:`CircuitPEPSSimpleUpdate`, :py:obj:`CircuitMPS` .. py:property:: max_bond The maximum bond dimension to compress to. .. py:property:: cutoff The singular value cutoff to use when compressing. .. py:method:: _init_state(N, dtype='complex128') .. py:method:: _apply_gate(gate, tags=None, **gate_opts) Apply a ``Gate`` to this ``Circuit``. This is the main method that all calls to apply a gate should go through. :param gate: The gate to apply. :type gate: Gate :param tags: Tags to add to the gate tensor(s). :type tags: str or sequence of str, optional .. py:method:: apply_gates(gates, progbar=False, **gate_opts) Apply a sequence of gates to this tensor network quantum circuit. :param gates: The sequence of gates to apply. :type gates: Sequence[Gate] or Sequence[Tuple] :param gate_opts: Supplied to :meth:`~quimb.tensor.circuit.Circuit.apply_gate`. .. py:method:: _parse_where(where) .. py:method:: _initial_operator(G, where) Build the bond dimension 1 PEPO of ``G`` acting at ``where`` and the identity elsewhere, on the circuit geometry. .. py:method:: get_evolved_operator(G, where, *, max_bond=None, cutoff=None) Evolve the local observable ``G`` at ``where`` backwards through the recorded circuit, returning the Heisenberg-picture operator :math:`U^\dagger G U` as a gauged PEPO. Gates outside the reverse lightcone of the observable are skipped. :param G: The local operator acting on the site(s) in ``where``. :type G: array_like :param where: The site or sites the operator acts on. :type where: hashable or sequence[hashable] :param max_bond: Override the compression options for this call. :type max_bond: optional :param cutoff: Override the compression options for this call. :type cutoff: optional :rtype: TensorNetworkGenOperator .. py:method:: get_evolved_operator_with_state(G, where, *, max_bond=None, cutoff=None) Return the evolved operator :math:`U^\dagger G U` projected onto the ``|00...0>`` initial state on both sides, i.e. the tensor network whose full contraction is :math:`\langle 0 | U^\dagger G U | 0 \rangle`. The physical indices are projected with ``isel``; the caller can contract the returned network however they like. .. py:method:: local_expectation(G, where, *, max_bond=None, cutoff=None, optimize='auto-hq', **contract_opts) Compute :math:`\langle 0 | U^\dagger G U | 0 \rangle`, the expectation of the local operator ``G`` at ``where`` in the state prepared by the recorded circuit ``U`` acting on ``|00...0>``. :param G: The local operator acting on the site(s) in ``where``. :type G: array_like :param where: The site or sites the operator acts on. :type where: hashable or sequence[hashable] :param max_bond: Override the compression options for this call. :type max_bond: optional :param cutoff: Override the compression options for this call. :type cutoff: optional :param optimize: The contraction path optimizer for the final contraction. :type optimize: str, optional :param contract_opts: Supplied to the final :meth:`~quimb.tensor.tensor_core.TensorNetwork.contract`. :rtype: scalar .. py:method:: _unsupported(name) :abstractmethod: .. py:method:: get_psi() Get a copy of the current state tensor network. This is the single method each representation must implement to expose its state, and is what the ``psi`` property calls. .. py:method:: to_dense(*args, **kwargs)