qpe_toolbox.circuit.mpo_circuit_transpilation ============================================= .. py:module:: qpe_toolbox.circuit.mpo_circuit_transpilation Attributes ---------- .. autoapisummary:: qpe_toolbox.circuit.mpo_circuit_transpilation.list_paulis Functions --------- .. autoapisummary:: qpe_toolbox.circuit.mpo_circuit_transpilation.exp_Pauli_string_as_MPO qpe_toolbox.circuit.mpo_circuit_transpilation.trotter1_approx_as_MPO qpe_toolbox.circuit.mpo_circuit_transpilation.trotter2_approx_as_MPO qpe_toolbox.circuit.mpo_circuit_transpilation.trotter4_approx_as_MPO qpe_toolbox.circuit.mpo_circuit_transpilation.trotter_approx_as_MPO qpe_toolbox.circuit.mpo_circuit_transpilation.state_preparation_mpo qpe_toolbox.circuit.mpo_circuit_transpilation.init_cost_tn qpe_toolbox.circuit.mpo_circuit_transpilation.get_envs_tns qpe_toolbox.circuit.mpo_circuit_transpilation.find_transfer_structure qpe_toolbox.circuit.mpo_circuit_transpilation.build_first_sweep qpe_toolbox.circuit.mpo_circuit_transpilation.build_loc_cost_tn qpe_toolbox.circuit.mpo_circuit_transpilation.PRC_loc_cost_tn qpe_toolbox.circuit.mpo_circuit_transpilation.update_cost_tn qpe_toolbox.circuit.mpo_circuit_transpilation.update_dict_contr_envs qpe_toolbox.circuit.mpo_circuit_transpilation.optimize_single_gate_update Module Contents --------------- .. py:data:: list_paulis :value: ['I', 'X', 'Y', 'Z'] .. py:function:: exp_Pauli_string_as_MPO(ham_term, n_qubits, *, theta) Construct the MPO representation of the unitary exponential of a Pauli string. Given a Hamiltonian term of the form: H = c * P where ``c`` is a scalar coefficient and ``P`` is a tensor product of Pauli operators acting on a subset of qubits, this function builds the Matrix Product Operator (MPO) corresponding to: exp(i * theta * c * P) using the identity: exp(i α P) = cos(α) I + i sin(α) P where ``P^2 = I``. The Pauli string is expanded to the full system size by inserting identity operators on inactive qubits. :param ham_term: A tuple ``(coeff, pauli_string, active_qubits)`` where: - ``coeff`` (float): Scalar coefficient multiplying the Pauli string. - ``pauli_string`` (str): String of Pauli operators (e.g. ``"ZYXXZ"``). - ``active_qubits`` (list[int]): Indices of qubits where the Pauli operators act. The length must match ``pauli_string``. :type ham_term: tuple :param n_qubits: Total number of qubits in the system. :type n_qubits: int :param theta: Evolution parameter (e.g. time or rotation angle). :type theta: float :returns: MPO representing the operator: exp(i * theta * coeff * P) where ``P`` is the full Pauli string embedded in the ``n_qubits`` system. :rtype: qtn.MatrixProductOperator :raises ValueError: If the length of ``pauli_string`` does not match the number of ``active_qubits``. .. rubric:: Notes - The MPO is constructed in left-right-up-down index ordering. - The Pauli string MPO has bond dimension 1 before summation. - After combining the identity and Pauli MPOs, the result should not exceed a maximum bond dimension of 2. .. rubric:: Examples >>> ham_term = (-0.345, "ZYXXZ", [0, 2, 3, 6, 9]) >>> mpo = exp_Pauli_string_as_MPO(ham_term, n_qubits=10, theta=0.1) >>> mpo .. py:function:: trotter1_approx_as_MPO(ham_terms, n_qubits, *, dt, cutoff, max_bond, reverse_order=False) Construct the first-order Trotter-Suzuki approximation as a Matrix Product Operator (MPO). This function builds an MPO representation of the first-order product formula for the time-evolution operator .. math:: U(dt) \approx \prod_j e^{-i dt \, H_j}, where ``ham_terms = [H_0, H_1, ..., H_{m-1}]`` is a decomposition of the Hamiltonian into terms that can each be exponentiated individually as MPOs. Each exponential factor is generated with :func:`exp_Pauli_string_as_MPO`, and factors are successively multiplied together using MPO compression. :param ham_terms: Sequence of Hamiltonian terms. Each element must be compatible with :func:`exp_Pauli_string_as_MPO`. :type ham_terms: sequence :param n_qubits: Number of qubits (sites) in the system. :type n_qubits: int :param dt: Time step used in the Trotter approximation. :type dt: float :param cutoff: Singular value truncation threshold used during MPO compression. :type cutoff: float :param max_bond: Maximum allowed bond dimension during MPO compression. :type max_bond: int :param reverse_order: If ``False`` (default), terms are applied in forward order. after the first term. If ``True``, terms are applied in reverse index order. :type reverse_order: bool, optional :returns: MPO representation of the first-order Trotter approximation. :rtype: MPO .. rubric:: Notes The resulting MPO is built iteratively using compressed MPO products via ``apply(..., compress=True)``. Truncation errors may accumulate depending on ``cutoff`` and ``max_bond``. .. py:function:: trotter2_approx_as_MPO(ham_terms, n_qubits, *, dt, cutoff, max_bond, verbosity=0) Construct the second-order symmetric Trotter-Suzuki approximation as an MPO. This function builds the second-order product formula .. math:: U(dt) \approx U_1(dt/2)\,U_1^{\mathrm{rev}}(dt/2), where :math:`U_1` is the first-order Trotter approximation and :math:`U_1^{\mathrm{rev}}` uses the reverse operator ordering. The approximation is accurate to second order in ``dt``. :param ham_terms: Sequence of Hamiltonian terms. Each term must be compatible with :func:`exp_Pauli_string_as_MPO`. :type ham_terms: sequence :param n_qubits: Number of qubits (sites) in the system. :type n_qubits: int :param dt: Time step used in the Trotter approximation. :type dt: float or complex :param cutoff: Singular value truncation threshold used during MPO compression. :type cutoff: float :param max_bond: Maximum allowed bond dimension during MPO compression. :type max_bond: int :param verbosity: If set to ``1``, prints progress information. Default is ``0``. :type verbosity: int, optional :returns: MPO representation of the second-order Trotter approximation. :rtype: MPO .. rubric:: Notes Two first-order MPO approximants with half time step are constructed and then multiplied together using compression. .. py:function:: trotter4_approx_as_MPO(ham_terms, n_qubits, *, dt, cutoff, max_bond, verbosity=0) Construct the fourth-order Trotter-Suzuki approximation as an MPO. This function implements the standard symmetric fourth-order composition .. math:: U_4(dt) = U_2(s\,dt)\, U_2((1 - 2s)\,dt)\, U_2(s\,dt), where :math:`U_2` is the second-order Trotter approximation and .. math:: s = \frac{1}{2 - 2^{1/3}} is the symmetry factor. This approximation is accurate to fourth order in ``dt``. :param ham_terms: Sequence of Hamiltonian terms. Each term must be compatible with :func:`exp_Pauli_string_as_MPO`. :type ham_terms: sequence :param n_qubits: Number of qubits (sites) in the system. :type n_qubits: int :param dt: Time step used in the Trotter approximation. :type dt: float :param cutoff: Singular value truncation threshold used during MPO compression. :type cutoff: float :param max_bond: Maximum allowed bond dimension during MPO compression. :type max_bond: int :param verbosity: If set to ``1``, prints progress information. Default is ``0``. :type verbosity: int, optional :returns: MPO representation of the fourth-order Trotter approximation. :rtype: MPO .. rubric:: Notes The method constructs three second-order MPO approximants and combines them through compressed MPO multiplication. Intermediate bond dimensions may grow significantly depending on the system and truncation parameters. .. py:function:: trotter_approx_as_MPO(hamiltonian, *, dt, order, cutoff, max_bond, verbosity=0) Construct a Trotter-Suzuki approximation of a Hamiltonian evolution operator as an MPO. This function dispatches to a specific Trotter-Suzuki decomposition according to the requested approximation order. The Hamiltonian is assumed to provide a decomposition into elementary terms through ``hamiltonian.terms``. Depending on ``order``, the approximation is built using: .. math:: U(dt) \approx \begin{cases} \text{1st-order product formula}, & \text{if } order = 1, \\ \text{2nd-order symmetric formula}, & \text{if } order = 2, \\ \text{4th-order Suzuki formula}, & \text{if } order = 4. \end{cases} The resulting operator is returned as a compressed MPO. :param hamiltonian: Includes Pauli strings, positions and couplings. :type hamiltonian: :class:`~src.hamiltonian.hamiltonian.Hamiltonian` :param dt: Time step used in the Trotter approximation. :type dt: float :param order: Order of the Trotter-Suzuki decomposition. :type order: {1, 2, 4} :param cutoff: Singular value truncation threshold used during MPO compression. :type cutoff: float :param max_bond: Maximum allowed MPO bond dimension during compression. :type max_bond: int :param verbosity: Verbosity level forwarded to higher-order routines. Default is ``0``. :type verbosity: int, optional :returns: MPO representation of the Trotterized time-evolution operator. :rtype: MPO :raises ValueError: If the requested ``order`` is not implemented. .. rubric:: Notes Compression is performed during MPO manipulations, so the final accuracy depends on the chosen ``cutoff`` and ``max_bond`` values. .. py:function:: state_preparation_mpo(state_mps) Perform outer product between an MPS and the state 0. :param state_mps: Target MPS to be reproduced by some circuit Ansatz. :type state_mps: :quimb-api:`MatrixProductState` :returns: Tensor network containing both the reference MPO for some variational procedure. :rtype: :quimb-api:`TensorNetwork` .. py:function:: init_cost_tn(ref_mpo, depth, *, param_scaling=0.1, closed=False, seed=42) Initialize the tensor network used for optimization. It represents a cost function obtained from contracting: 1. A brickwall unitary circuit ansatz, 2. A reference target unitary (or state x zero) register represented as an MPO. The ansatz is generated as a layered brickwall circuit of two-qubit ``SU4`` gates initialized close to the identity. The resulting unitary tensor network is then combined with the target MPO into a single tensor network suitable for overlap evaluation. :param ref_mpo: Target MPO to be reproduced by the Ansatz. :type ref_mpo: :quimb-api:`MatrixProductOperator` :param depth: Depth of the brickwall circuit ansatz (even and odd count as 1). :type depth: int :param param_scaling: Scale of the random initialization parameters for the gates. Smaller values initialize the circuit closer to the identity. Default is ``1e-1``. :type param_scaling: float, optional :param closed: If ``False`` (default), the bra indices of the MPO remain open. If ``True``, ket indices are contracted (trace contraction). :type closed: bool, optional :param seed: Guarantee reproducibility. :type seed: int :returns: Tensor network containing both the variational circuit ansatz and the target MPO. :rtype: :quimb-api:`TensorNetwork` .. py:function:: get_envs_tns(n_qubits, x, cost_tn) Extract the left and right environment TNs associated to a given site. This function removes the tensors tagged with ``I{x}`` from the full cost tensor network and partitions the remaining network into left and/or right environments relative to site ``x``. :param n_qubits: Number of qubits (sites) in the tensor network. :type n_qubits: int :param x: Site index for which the environments are constructed. :type x: int :param cost_tn: Full cost tensor network. :type cost_tn: :quimb-api:`TensorNetwork` :returns: List containing the environment tensor networks. - If ``x == 0``, only the right environment is returned. - If ``x == n_qubits - 1``, only the left environment is returned. - Otherwise, the list is ordered as ``[left_env, right_env]``. :rtype: list of :quimb-api:`TensorNetwork` .. rubric:: Notes The environments are obtained by selecting tensors according to their ``I{i}`` tags: - left environment: tensors tagged with ``I0`` through ``I{x-1}``, - right environment: tensors tagged with ``I{x+1}`` through ``I{n_qubits-1}``. .. py:function:: find_transfer_structure(n_qubits, cost_tn) Determine the transfer structures connecting neighboring environments in a cost TN. This function analyzes the left and right environment tensor networks associated with each site and identifies the tensor tags involved in transferring contractions between neighboring environments. The resulting transfer structure is organized into dictionaries for left-to-right and right-to-left propagation. :param n_qubits: Number of qubits (sites) in the tensor network. :type n_qubits: int :param cost_tn: Full cost tensor network. :type cost_tn: TensorNetwork :returns: Nested dictionary containing the transfer structures. The returned dictionary has the form: .. code-block:: python { "L": { "L1_to_L2": [...], ... "L{n_qubits-1}_to_L{n_qubits}": [...] }, "R": { "R{n_qubits-2}_to_R{n_qubits-1}": [...], ... "R1_to_R0": [...] } } where each value is a list of tensor tags participating in the corresponding transfer operation. :rtype: dict .. rubric:: Notes For each neighboring pair of environments, tensors are selected according to their ``I{i}`` tags, and only tags beginning with ``"G"`` or ``"U"`` are retained in the transfer description. The transfer structures can be used to optimize sequential contraction strategies or environment updates in tensor-network algorithms. .. py:function:: build_first_sweep(n_qubits, cost_tn, dict_transf, *, drop_tags=True) Construct the initial set of contracted left and right environments for a sweeping TN optimization. This function iteratively builds partially contracted environments by propagating contractions from the edges of the tensor network toward the center using the transfer structures generated by :func:`find_transfer_structure`. The resulting environments are stored as contracted tensors labeled ``L{i}`` and ``R{i}``, corresponding to left and right effective environments at each site. :param n_qubits: Number of qubits (sites) in the tensor network. :type n_qubits: int :param cost_tn: Full cost tensor network. :type cost_tn: :quimb-api:`TensorNetwork` :param dict_transf: Transfer structure dictionary generated by :func:`find_transfer_structure`. :type dict_transf: dict :param drop_tags: Whether to drop tensor tags during contractions. Passed to :func:`tensor_contract`. Default is ``True``. :type drop_tags: bool, optional :returns: Nested dictionary containing contracted environments: .. code-block:: python { "L": { "L1": Tensor, ... }, "R": { "R{n_qubits-2}": Tensor, ... } } Each entry corresponds to an effective contracted environment tensor. :rtype: dict .. rubric:: Notes The contraction procedure starts from the MPO edge tensors tagged ``"Uref0"`` and ``"Uref{n_qubits-1}"`` and recursively absorbs the transfer tensor networks specified in ``dict_transf``. These environments are typically reused during local optimization sweeps to avoid repeated large tensor contractions. .. py:function:: build_loc_cost_tn(n_qubits, x, dict_contr_envs, cost_tn) Construct the local cost tensor network associated with a given site. This function combines the local gate tensors acting on site ``x`` with the corresponding contracted left and/or right environments to form an effective local tensor network suitable for optimization. It also returns the ordered list of gate tags corresponding to the variational tensors to optimize. :param n_qubits: Number of qubits (sites) in the tensor network. :type n_qubits: int :param x: Site index for which the local cost tensor network is constructed. :type x: int :param dict_contr_envs: Dictionary of contracted environments generated by :func:`build_first_sweep`. :type dict_contr_envs: dict :param cost_tn: Full cost tensor network. :type cost_tn: :quimb-api:`TensorNetwork` :returns: * **loc_cost_tn** (:quimb-api:`TensorNetwork`) -- Local effective tensor network containing the relevant environments and gate tensors for site ``x``. * **gate_to_opt_tags** (*list of str*) -- Ordered list of gate tensor tags to optimize. .. rubric:: Notes The local tensor network has the structure .. math:: \mathcal{S}_x = L_x \; \text{- gates -} \; R_x, where: - ``L_x`` is the contracted left environment, - ``R_x`` is the contracted right environment, - ``gates`` are the tensors tagged with ``I{x}``. Only tags beginning with ``"G"`` are considered optimization gate tags. Boundary sites are treated separately: - for ``x = 0``, only the right environment is included, - for ``x = n_qubits - 1``, only the left environment is included. .. py:function:: PRC_loc_cost_tn(loc_cost_tn, tags, hyperopt) Perform a Pop-Rehearse-Contract step on a local cost tensor network. This function removes a set of tensors from a local cost tensor network and contracts the remaining network using a specified contraction strategy. The procedure is intended to support efficient repeated contractions during sweeping optimization algorithms, where contraction paths may be rehearsed and reused across iterations. :param loc_cost_tn: Local cost tensor network. :type loc_cost_tn: :quimb-api:`TensorNetwork` :param tags: Tags identifying the tensors to remove before contraction. Typically corresponds to the variational gates currently being optimized. :type tags: sequence of str :param hyperopt: Contraction optimization strategy passed to :meth:`TensorNetwork.contract`. :type hyperopt: :cotengra-api:`ReusableHyperOptimizer` :returns: Contracted tensor obtained after removing the specified tensors. :rtype: :quimb-api:`Tensor` .. py:function:: update_cost_tn(cost_tn, list_opt_gate_tens) Update a cost tensor network with newly optimized gate tensors. This function replaces existing gate tensors in the cost tensor network with updated optimized tensors having the same gate tags. :param cost_tn: Full cost tensor network. :type cost_tn: :quimb-api:`TensorNetwork` :param list_opt_gate_tens: Sequence of optimized gate tensors to insert into the network. :type list_opt_gate_tens: sequence of :quimb-api:`Tensor` :returns: Updated cost tensor network containing the optimized gate tensors. :rtype: :quimb-api:`TensorNetwork` .. py:function:: update_dict_contr_envs(mode, list_opt_gate_tens, cost_tn, dict_transf, dict_contr_envs) Update contracted environments after local gate optimization. This function updates the cached contracted left or right environments affected by newly optimized gate tensors during a sweeping optimization procedure. Depending on the sweep direction, only the environments influenced by the updated gates are recomputed. :param mode: Sweep direction. - ``"LR"`` : left-to-right sweep, - ``"RL"`` : right-to-left sweep. :type mode: {"LR", "RL"} :param list_opt_gate_tens: Sequence of optimized gate tensors. :type list_opt_gate_tens: sequence of :quimb-api:`Tensor` :param cost_tn: Full updated cost tensor network. :type cost_tn: :quimb-api:`TensorNetwork` :param dict_transf: Transfer structure dictionary generated by :func:`find_transfer_structure`. :type dict_transf: dict :param dict_contr_envs: Updated dictionary of contracted environments initialized by :func:`build_first_sweep`. :type dict_contr_envs: dict :returns: Updated dictionary of contracted environments. :rtype: dict .. rubric:: Notes Each optimized gate acts on neighboring sites ``I{n}`` and ``I{n+1}``. Consequently, only nearby environments need to be updated. For a left-to-right sweep (``"LR"``): .. math:: L_{n+2} \leftarrow L_{n+1} \cdot T_{n+1 \to n+2}, while for a right-to-left sweep (``"RL"``): .. math:: R_{n-1} \leftarrow R_n \cdot T_{n \to n-1}. This local update strategy avoids rebuilding all environments from scratch after each optimization step. .. py:function:: optimize_single_gate_update(n_qubits, cost_tn, rtol, n_sweeps_max, dict_transf, dict_contr_envs) Optimize a TN ansatz circuit using sequential single-gate updates. This function performs alternating left-to-right and right-to-left sweeps over the variational gates of the cost tensor network. Each gate is optimized individually by contracting its effective environment, performing a singular value decomposition (SVD), and projecting the result back onto the unitary manifold. The optimization iteratively updates both the tensor network and the cached contracted environments. :param n_qubits: Number of qubits (sites) in the tensor network. :type n_qubits: int :param cost_tn: Full cost tensor network containing the variational circuit and target MPO. :type cost_tn: :quimb-api:`TensorNetwork` :param rtol: Relative tolerance condition for stopping. :type rtol: float :param n_sweeps_max: Maximum number of optimization sweeps. :type n_sweeps_max: int :param dict_transf: Transfer structure dictionary generated by :func:`find_transfer_structure`. :type dict_transf: dict :param dict_contr_envs: Dictionary of contracted environments generated by :func:`build_first_sweep`. :type dict_contr_envs: dict :returns: * **cost_tn** (:quimb-api:`TensorNetwork`) -- Optimized cost tensor network. * **dict_contr_envs** (*dict*) -- Updated dictionary of contracted environments. .. rubric:: Notes The optimization proceeds as follows: 1. Construct a local effective tensor network around a gate, 2. Remove the gate tensor and contract the surrounding environment, 3. Perform an SVD of the resulting effective tensor, 4. Reconstruct the optimal unitary gate from the isometric factors, 5. Update the tensor network and cached environments. The effective local contraction is computed using :func:`PRC_loc_cost_tn`. The gate update is obtained from an SVD decomposition. The overlap displayed in the progress bar corresponds to the cost-function value and can be verified independently from the singular values of the effective environment tensor. The sweeping schedule alternates between: - left-to-right (``"LR"``), - right-to-left (``"RL"``), in order to iteratively improve all variational gates.