quimb.tensor.circuit.mps ======================== .. py:module:: quimb.tensor.circuit.mps .. autoapi-nested-parse:: Matrix-product-state circuit simulators. Classes ------- .. autoapisummary:: quimb.tensor.circuit.mps.CircuitMPS quimb.tensor.circuit.mps.CircuitPermMPS quimb.tensor.circuit.mps.CircuitMPSLazy Module Contents --------------- .. py:class:: CircuitMPS(N=None, *, psi0=None, max_bond=None, cutoff=1e-10, gate_opts=None, gate_contract='auto-mps', dtype=None, to_backend=None, convert_eager=True, **circuit_opts) Bases: :py:obj:`quimb.tensor.circuit.exact.Circuit` Quantum circuit simulation keeping the state always in a MPS form. If you think the circuit will not build up much entanglement, or you just want to keep a rigorous handle on how much entanglement is present, this can be useful. :param N: The number of qubits in the circuit. :type N: int, optional :param psi0: The initial state, assumed to be ``|00000....0>`` if not given. The state is always copied and the tag ``PSI0`` added. :type psi0: TensorNetwork1DVector, optional :param max_bond: The maximum bond dimension to truncate to when applying gates, if any. This is simply a shortcut for setting ``gate_opts['max_bond']``. :type max_bond: int, optional :param cutoff: The singular value cutoff to use when truncating the state. This is simply a shortcut for setting ``gate_opts['cutoff']``. :type cutoff: float, optional :param gate_opts: Default options to pass to each gate, for example, "max_bond" and "cutoff" etc. :type gate_opts: dict, optional :param gate_contract: The default method for applying gates. Relevant MPS options are: - ``'auto-mps'``: automatically choose a method that maintains the MPS form (default). This uses ``'swap+split'`` for 2-qubit gates and ``'nonlocal'`` for 3+ qubit gates. - ``'swap+split'``: swap nonlocal qubits to be next to each other, before applying the gate, then swapping them back - ``'nonlocal'``: turn the gate into a potentially nonlocal (sub) MPO and apply it directly. See :func:`tensor_network_1d_compress`. :type gate_contract: str, optional :param dtype: The data type to use for the state tensor. :type dtype: str, optional :param to_backend: A function to convert tensor data to a particular backend. :type to_backend: callable, optional :param convert_eager: Whether to eagerly perform dtype casting and application of `to_backend` as gates are supplied, or wait until after the necessary TNs for a particular task such as sampling are formed and simplified. Eager conversion (`convert_eager=True`) is the default mode for MPS simulation, unlike full contraction. :type convert_eager: bool, optional :param circuit_opts: Supplied to :class:`~quimb.tensor.circuit.Circuit`. .. attribute:: psi The current state of the circuit, always in MPS form. :type: MatrixProductState .. rubric:: Examples Create a circuit object that always uses the "nonlocal" method for contracting in gates, and the "dm" compression method within that, using a large cutoff and maximum bond dimension:: circ = qtn.CircuitMPS( N=56, gate_opts=dict( contract="nonlocal", method="dm", max_bond=1024, cutoff=1e-3, ) ) .. py:method:: _init_state(N, dtype='complex128') .. 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:property:: psi Tensor network representation of the wavefunction. .. py:property:: uni .. py:method:: calc_qubit_ordering(qubits=None) MPS already has a natural ordering. .. py:method:: get_psi_reverse_lightcone(where, keep_psi0=False) Override ``get_psi_reverse_lightcone`` as for an MPS the lightcone is not meaningful. .. py:method:: sample(C, seed=None, dtype=None, *, qubits=None, order=None, group_size=None, max_marginal_storage=None, optimize=None, backend=None, simplify_sequence=None, simplify_atol=None, simplify_equalize_norms=None) Sample the MPS circuit ``C`` times. :param C: The number of samples to generate. :type C: int :param seed: A random seed or generator to use for reproducibility. :type seed: None, int, or generator, optional .. py:method:: fidelity_estimate() Estimate the fidelity of the current state based on its norm, which tracks how much the state has been truncated: .. math:: \tilde{F} = \left| \langle \psi | \psi \rangle \right|^2 \approx \left|\langle \psi_\mathrm{ideal} | \psi \rangle\right|^2 .. seealso:: :py:obj:`error_estimate` .. py:method:: error_estimate() Estimate the error in the current state based on the norm of the discarded part of the state: .. math:: \epsilon = 1 - \tilde{F} .. seealso:: :py:obj:`fidelity_estimate` .. py:method:: local_expectation(G, where, normalized=False, dtype=None, *, simplify_sequence=None, simplify_atol=None, simplify_equalize_norms=None, backend=None, rehearse=None, **contract_opts) Compute the local expectation value of a local operator at ``where`` (via forming the reduced density matrix). Note this moves the orthogonality around inplace, and records it in `info`. :param G: The local operator tensor. :type G: Tensor :param where: The qubit to compute the expectation value at. :type where: int :param normalized: Whether to normalize the expectation value by the norm of the state. :type normalized: bool, optional :param dtype: If given, ensure the TN is cast to this dtype before contracting. :type dtype: dtype, optional :rtype: float .. py:class:: CircuitPermMPS(N=None, psi0=None, gate_opts=None, gate_contract='swap+split', **circuit_opts) Bases: :py:obj:`CircuitMPS` Quantum circuit simulation keeping the state always in an MPS form, but lazily tracking the qubit ordering rather than 'swapping back' qubits after applying non-local gates. This can be useful for circuits with no expectation of locality. The qubit ordering is always tracked in the attribute ``qubits``. The ``psi`` attribute returns the TN with the sites reindexed and retagged according to the current qubit ordering, meaning it is no longer an MPS. Use `circ.get_psi_unordered()` to get the unpermuted MPS and use `circ.qubits` to get the current qubit ordering if you prefer. .. py:attribute:: qubits .. 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:: calc_qubit_ordering(qubits=None) Given by the current qubit permutation. .. py:method:: get_psi_unordered() Return the MPS representing the state but without reordering the sites. .. py:method:: sample(C, seed=None, dtype=None) Sample the PermMPS circuit ``C`` times. :param C: The number of samples to generate. :type C: int :param seed: A random seed or generator to use for reproducibility. :type seed: None, int, or generator, optional :Yields: *str* -- The next sample bitstring. .. py:property:: psi Tensor network representation of the wavefunction. .. py:method:: to_dense(reverse=False, optimize='auto-hq', backend=None, dtype=None) Generate the dense representation of the final wavefunction. :param reverse: Whether to reverse the order of the subsystems, to match the convention of qiskit for example. :type reverse: bool, optional :param optimize: Contraction path optimizer to use for the contraction, can be a non-reusable path optimizer as only called once (though path won't be cached for later use in that case). :type optimize: str, optional :param dtype: If given, convert the tensors to this dtype prior to contraction. :type dtype: dtype or str, optional :param simplify_sequence: Which local tensor network simplifications to perform and in which order, see :meth:`~quimb.tensor.tensor_core.TensorNetwork.full_simplify`. :type simplify_sequence: str, optional :param simplify_atol: The tolerance with which to compare to zero when applying :meth:`~quimb.tensor.tensor_core.TensorNetwork.full_simplify`. :type simplify_atol: float, optional :param simplify_equalize_norms: Actively renormalize tensor norms during simplification. :type simplify_equalize_norms: bool, optional :param backend: Backend to perform the contraction with, e.g. ``'numpy'``, ``'cupy'`` or ``'jax'``. Passed to ``cotengra``. :type backend: str, optional :param dtype: Data type to cast the TN to before contraction. :type dtype: str, optional :param rehearse: If ``True``, generate and cache the simplified tensor network and contraction tree but don't actually perform the contraction. Returns a dict with keys ``'tn'`` and ``'tree'`` with the tensor network that will be contracted and the corresponding contraction tree if so. :type rehearse: bool, optional :returns: **psi** -- The densely represented wavefunction with ``dtype`` data. :rtype: qarray .. py:method:: amplitude(b, optimize='auto-hq', backend=None, dtype=None) Get the amplitude coefficient of bitstring ``b``. .. math:: c_b = \langle b | \psi \rangle :param b: The bitstring to compute the transition amplitude for. :type b: str or sequence of int :param optimize: Contraction path optimizer to use for the amplitude, can be a non-reusable path optimizer as only called once (though path won't be cached for later use in that case). :type optimize: str, optional :param simplify_sequence: Which local tensor network simplifications to perform and in which order, see :meth:`~quimb.tensor.tensor_core.TensorNetwork.full_simplify`. :type simplify_sequence: str, optional :param simplify_atol: The tolerance with which to compare to zero when applying :meth:`~quimb.tensor.tensor_core.TensorNetwork.full_simplify`. :type simplify_atol: float, optional :param simplify_equalize_norms: Actively renormalize tensor norms during simplification. :type simplify_equalize_norms: bool, optional :param backend: Backend to perform the contraction with, e.g. ``'numpy'``, ``'cupy'`` or ``'jax'``. Passed to ``cotengra``. :type backend: str, optional :param dtype: Data type to cast the TN to before contraction. :type dtype: str, optional :param rehearse: If ``True``, generate and cache the simplified tensor network and contraction tree but don't actually perform the contraction. Returns a dict with keys ``"tn"`` and ``'tree'`` with the tensor network that will be contracted and the corresponding contraction tree if so. :type rehearse: bool or "tn", optional .. py:method:: local_expectation(G, where, *args, **kwargs) Compute the local expectation value of a local operator at ``where`` (via forming the reduced density matrix). Note this moves the orthogonality around inplace, and records it in `info`. :param G: The local operator tensor. :type G: Tensor :param where: The qubit to compute the expectation value at. :type where: int :param normalized: Whether to normalize the expectation value by the norm of the state. :type normalized: bool, optional :param dtype: If given, ensure the TN is cast to this dtype before contracting. :type dtype: dtype, optional :rtype: float .. py:class:: CircuitMPSLazy(N=None, *, psi0=None, max_bond=None, cutoff=1e-10, compress_opts=None, method='dm', compress_every=2, dtype=None, to_backend=None, convert_eager=True, **circuit_opts) Bases: :py:obj:`CircuitMPS` Quantum circuit simulation keeping the state always in an MPS form, but lazily applying gates (via sub-MPO representation) and regularly contracting and compressing the gates with the state using :func:`~quimb.tensor.tn1d.compress.tensor_network_1d_compress`. This is in contrast to the TEBD approach of eagerly applying gates and then compressing which is used in :class:`CircuitMPS`. The periodicity of compression is arbitrary and can be tuned with :attr:`compress_every`, and one can find a goldilocks point for fastest runtime. This circuit class is best utilized for long-range gates, and provides a speedup over :class:`CircuitMPS` when using ``"src"`` compression method. Note :attr:`gate_contract` is obsolete for this class as 2+ qubit gates are lazily applied via ``"nonlocal"`` and 1 qubit gates are eagerly applied via `True`. :param N: The number of qubits in the circuit. :type N: int, optional :param psi0: The initial state, assumed to be ``|00000....0>`` if not given. The state is always copied and the tag ``PSI0`` added. :type psi0: TensorNetwork1DVector, optional :param max_bond: The maximum bond dimension to truncate to when applying gates, if any. This is simply a shortcut for setting ``gate_opts['max_bond']``. :type max_bond: int, optional :param cutoff: The singular value cutoff to use when truncating the state. This is simply a shortcut for setting ``gate_opts['cutoff']``. :type cutoff: float, optional :param gate_opts: Default options to pass to each gate, for example, "max_bond" and "cutoff" etc. :type gate_opts: dict, optional :param compress_opts: Default options to pass to :func:`~quimb.tensor.tn1d.compress.tensor_network_1d_compress`, for example, "method", "max_bond" and "cutoff" etc. :type compress_opts: dict, optional :param method: The method to use for compressing the state with the gates, passed to :func:`~quimb.tensor.tn1d.compress.tensor_network_1d_compress`, e.g. ``"dm"`` for density matrix truncation, ``"src"`` for successive randomized compression, or ``"direct"`` for direct SVD truncation. :type method: str, optional :param compress_every: How many gates to apply to any qubit before contracting and compressing the state with the gates. :type compress_every: int, optional :param dtype: The data type to use for the state tensor. :type dtype: str, optional :param to_backend: A function to convert tensor data to a particular backend. :type to_backend: callable, optional :param convert_eager: Whether to eagerly perform dtype casting and application of `to_backend` as gates are supplied, or wait until after the necessary TNs for a particular task such as sampling are formed and simplified. Eager conversion (`convert_eager=True`) is the default mode for MPS simulation, unlike full contraction. :type convert_eager: bool, optional :param circuit_opts: Supplied to :class:`~quimb.tensor.circuit.Circuit`. .. attribute:: psi The current state of the circuit, always in MPS form. :type: MatrixProductState .. rubric:: Examples Create a circuit object that always uses the "src" compression method using maximum bond dimension and compressing when 5 gates are applied to any qubit:: circ = qtn.CircuitMPSLazy( N=56, max_bond=1024, cutoff=0.0, compress_every=5, method="src", ) .. py:attribute:: compress_opts .. py:attribute:: _uncompressed_sites .. py:attribute:: compress_every :value: 2 .. py:property:: max_bond .. py:property:: cutoff .. py:property:: method .. py:method:: _compress() Compress the current state by contracting in all gates and then applying the specified compression method via :func:`~quimb.tensor.tn1d.compress.tensor_network_1d_compress`. .. 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:property:: psi Tensor network representation of the wavefunction. .. py:method:: sample(C, *args, **kwargs) Sample the MPS circuit ``C`` times. :param C: The number of samples to generate. :type C: int :param seed: A random seed or generator to use for reproducibility. :type seed: None, int, or generator, optional .. py:method:: local_expectation(G, where, *args, **kwargs) Compute the local expectation value of a local operator at ``where`` (via forming the reduced density matrix). Note this moves the orthogonality around inplace, and records it in `info`. :param G: The local operator tensor. :type G: Tensor :param where: The qubit to compute the expectation value at. :type where: int :param normalized: Whether to normalize the expectation value by the norm of the state. :type normalized: bool, optional :param dtype: If given, ensure the TN is cast to this dtype before contracting. :type dtype: dtype, optional :rtype: float .. py:method:: fidelity_estimate() Estimate the fidelity of the current state based on its norm, which tracks how much the state has been truncated: .. math:: \tilde{F} = \left| \langle \psi | \psi \rangle \right|^2 \approx \left|\langle \psi_\mathrm{ideal} | \psi \rangle\right|^2 .. seealso:: :py:obj:`error_estimate`