§
    º³Ùg¯#  ã                  óÔ   — d Z ddlmZ ddlZddlZddlmZ ddlmZ ddl	Z
ddlmZ ddlmZ ddlmZmZ dd	lmZ d
dlmZmZ ej        rddlmZ ddlmZ  G d„ de¦  «        Zdd„ZdS )z#The Suzuki-Trotter product formula.é    )ÚannotationsN)ÚCallable)Úchain)ÚParameterExpression)ÚQuantumCircuit)ÚSparsePauliOpÚPauli)Údeprecate_argé   )ÚProductFormulaÚreorder_paulis)ÚParameterValueType)ÚPauliEvolutionGatec                  ó€   ‡ — e Zd ZdZ eddd„ dd¬¦  «        	 	 	 	 	 	 	 d d!ˆ fd„¦   «         Zd"d„Zed„ ¦   «         Zˆ xZ	S )#ÚSuzukiTrottera
  The (higher order) Suzuki-Trotter product formula.

    The Suzuki-Trotter formulas improve the error of the Lie-Trotter approximation.
    For example, the second order decomposition is

    .. math::

        e^{A + B} \approx e^{B/2} e^{A} e^{B/2}.

    Higher order decompositions are based on recursions, see Ref. [1] for more details.

    In this implementation, the operators are provided as sum terms of a Pauli operator.
    For example, in the second order Suzuki-Trotter decomposition we approximate

    .. math::

        e^{-it(XI + ZZ)} = e^{-it/2 XI}e^{-it ZZ}e^{-it/2 XI} + \mathcal{O}(t^3).

    References:
        [1]: D. Berry, G. Ahokas, R. Cleve and B. Sanders,
        "Efficient quantum algorithms for simulating sparse Hamiltonians" (2006).
        `arXiv:quant-ph/0508139 <https://arxiv.org/abs/quant-ph/0508139>`_
        [2]: N. Hatano and M. Suzuki,
        "Finding Exponential Product Formulas of Higher Orders" (2005).
        `arXiv:math-ph/0506007 <https://arxiv.org/pdf/math-ph/0506007.pdf>`_
    Úatomic_evolutionz1.4c                ó^   — | d uo)t          t          j        | ¦  «        j        ¦  «        dk    S )Né   )ÚlenÚinspectÚ	signatureÚ
parameters)Úcallables    ú_/granary/edev/quantum/lib/python3.11/site-packages/qiskit/synthesis/evolution/suzuki_trotter.pyú<lambda>zSuzukiTrotter.<lambda>B   s1   €  8°4Ð#7ð $=Ý•Ô! (Ñ+Ô+Ô6Ñ7Ô7¸1Ò<ð ó    zkThe 'Callable[[Pauli | SparsePauliOp, float], QuantumCircuit]' signature of the 'atomic_evolution' argumentz™Instead you should update your 'atomic_evolution' function to be of the following type: 'Callable[[QuantumCircuit, Pauli | SparsePauliOp, float], None]'.)ÚnameÚsinceÚ	predicateÚdeprecation_descriptionÚadditional_msgr   r   Fr   NTÚorderÚintÚrepsÚinsert_barriersÚboolÚcx_structureÚstrú€Callable[[Pauli | SparsePauliOp, float], QuantumCircuit] | Callable[[QuantumCircuit, Pauli | SparsePauliOp, float], None] | NoneÚwrapÚpreserve_orderÚreturnÚNonec           	     óœ   •— |dk    r|dz  dk    rt          d|› d�¦  «        ‚t          ¦   «                              |||||||¬¦  «         dS )aV  
        Args:
            order: The order of the product formula.
            reps: The number of time steps.
            insert_barriers: Whether to insert barriers between the atomic evolutions.
            cx_structure: How to arrange the CX gates for the Pauli evolutions, can be ``"chain"``,
                where next neighbor connections are used, or ``"fountain"``, where all qubits are
                connected to one. This only takes effect when ``atomic_evolution is None``.
            atomic_evolution: A function to apply the evolution of a single :class:`.Pauli`, or
                :class:`.SparsePauliOp` of only commuting terms, to a circuit. The function takes in
                three arguments: the circuit to append the evolution to, the Pauli operator to
                evolve, and the evolution time. By default, a single Pauli evolution is decomposed
                into a chain of ``CX`` gates and a single ``RZ`` gate.
                Alternatively, the function can also take Pauli operator and evolution time as
                inputs and returns the circuit that will be appended to the overall circuit being
                built.
            wrap: Whether to wrap the atomic evolutions into custom gate objects. This only takes
                effect when ``atomic_evolution is None``.
            preserve_order: If ``False``, allows reordering the terms of the operator to
                potentially yield a shallower evolution circuit. Not relevant
                when synthesizing operator with a single term.
        Raises:
            ValueError: If order is not even
        r   r   zfSuzuki product formulae are symmetric and therefore only defined for when the order is 1 or even, not ú.)r+   N)Ú
ValueErrorÚsuperÚ__init__)	Úselfr"   r$   r%   r'   r   r*   r+   Ú	__class__s	           €r   r2   zSuzukiTrotter.__init__?   sŠ   ø€ ðj �1Š9ˆ9˜ ™ aš˜ÝðAØ8=ðAð Að Añô ð õ 	‰Œ×ÒØØØØØØØ)ð 	ñ 	
ô 	
ð 	
ð 	
ð 	
r   Ú	evolutionr   ú/list[tuple[str, list[int], ParameterValueType]]c                ó.  ‡ ‡‡— |j         }|j        Šˆ ˆfd„Št          |t          ¦  «        rˆfd„|D ¦   «         }nd„  ‰|¦  «        D ¦   «         }‰                      ‰ j        |¦  «        }‰ j        t          t          j        |¦  «        ¦  «        z  }|S )aˆ  Expand the Hamiltonian into a Suzuki-Trotter sequence of sparse gates.

        For example, the Hamiltonian ``H = IX + ZZ`` for an evolution time ``t`` and
        1 repetition for an order 2 formula would get decomposed into a list of 3-tuples
        containing ``(pauli, indices, rz_rotation_angle)``, that is:

        .. code-block:: text

            ("X", [0], t), ("ZZ", [0, 1], 2t), ("X", [0], t)

        Note that the rotation angle contains a factor of 2, such that that evolution
        of a Pauli :math:`P` over time :math:`t`, which is :math:`e^{itP}`, is represented
        by ``(P, indices, 2 * t)``.

        For ``N`` repetitions, this sequence would be repeated ``N`` times and the coefficients
        divided by ``N``.

        Args:
            evolution: The evolution gate to expand.

        Returns:
            The Pauli network implementing the Trotter expansion.
        c                óv   •— ˆˆfd„|                       ¦   «         D ¦   «         }‰j        st          |¦  «        S |S )Nc                óX   •— g | ]&\  }}}||t          |¦  «        ‰z  d z  ‰j        z  f‘Œ'S ©r   )Úreal_or_failr$   )Ú.0ÚpauliÚindicesÚcoeffr3   Útimes       €€r   ú
<listcomp>z@SuzukiTrotter.expand.<locals>.to_sparse_list.<locals>.<listcomp>¡   sO   ø€ ð ð ð á)�E˜7 Eð ˜¥¨eÑ!4Ô!4°tÑ!;¸aÑ!?À$Ä)Ñ!KÐLðð ð r   )Úto_sparse_listr+   r   )ÚoperatorÚpaulisr3   r@   s     €€r   rB   z,SuzukiTrotter.expand.<locals>.to_sparse_list    s\   ø€ ðð ð ð ð à-5×-DÒ-DÑ-FÔ-Fðñ ô ˆFð Ô&ð .Ý% fÑ-Ô-Ð-àˆMr   c                ó&   •— g | ]} ‰|¦  «        ‘ŒS © rF   )r<   rC   rB   s     €r   rA   z(SuzukiTrotter.expand.<locals>.<listcomp>¬   s#   ø€ ÐPÐPÐP¸(˜^˜^¨HÑ5Ô5ÐPÐPÐPr   c                ó   — g | ]}|g‘ŒS rF   rF   )r<   Úops     r   rA   z(SuzukiTrotter.expand.<locals>.<listcomp>°   s   € ÐFÐFÐF b˜b˜TÐFÐFÐFr   )	rC   r@   Ú
isinstanceÚlistÚ_recurser"   r$   r   Úfrom_iterable)r3   r5   Ú	operatorsÚnon_commutingÚproduct_formulaÚ	flattenedr@   rB   s   `     @@r   ÚexpandzSuzukiTrotter.expandƒ   sÀ   øøø€ ð4 Ô&ˆ	ØŒ~ˆð	ð 	ð 	ð 	ð 	ð 	õ �i¥Ñ&Ô&ð 	GØPÐPÐPÐPÀiÐPÑPÔPˆMˆMð GÐF¨N¨N¸9Ñ,EÔ,EÐFÑFÔFˆMð Ÿ-š-¨¬
°MÑBÔBˆØ”I¥¥UÔ%8¸Ñ%IÔ%IÑ JÔ JÑJˆ	àÐr   c                ó~  ‡— | dk    r|S | dk    r?d„ |d d…         D ¦   «         }|d         g}||z   t          t          |¦  «        ¦  «        z   S dddd| dz
  z  z  z
  z  Šdt                               | dz
  ˆfd„|D ¦   «         ¦  «        z  }t                               | dz
  ˆfd„|D ¦   «         ¦  «        }||z   |z   S )Nr   r   c                ó&   — g | ]}d „ |D ¦   «         ‘ŒS )c                ó&   — g | ]\  }}}|||d z  f‘ŒS r:   rF   )r<   ÚlabelÚqubitsr?   s       r   rA   z5SuzukiTrotter._recurse.<locals>.<listcomp>.<listcomp>¿   s*   € ÐOÐOÐOÑ0D°°v¸u�%˜ ¨¡Ð+ÐOÐOÐOr   rF   )r<   rD   s     r   rA   z*SuzukiTrotter._recurse.<locals>.<listcomp>¾   s7   € ð ð ð àð PÐOÈÐOÑOÔOðð ð r   éÿÿÿÿé   c                ó,   •— g | ]}ˆfd „|D ¦   «         ‘ŒS )c                ó(   •— g | ]\  }}}|||‰z  f‘ŒS rF   rF   ©r<   rU   rV   r?   Ú	reductions       €r   rA   z5SuzukiTrotter._recurse.<locals>.<listcomp>.<listcomp>Ê   s,   ø€ Ð[Ð[Ð[Ñ<P¸EÀ6È5�e˜V U¨YÑ%6Ð7Ð[Ð[Ð[r   rF   ©r<   rD   r\   s     €r   rA   z*SuzukiTrotter._recurse.<locals>.<listcomp>É   s?   ø€ ð ð ð àð \Ð[Ð[Ð[ÐTZÐ[Ñ[Ô[ðð ð r   c                ó,   •— g | ]}ˆfd „|D ¦   «         ‘ŒS )c                ó4   •— g | ]\  }}}|||d d‰z  z
  z  f‘ŒS )r   rX   rF   r[   s       €r   rA   z5SuzukiTrotter._recurse.<locals>.<listcomp>.<listcomp>Ñ   sD   ø€ ð ð ð á0˜E 6¨5ð  ¨°°Q¸±]Ñ1BÑ(CÐDðð ð r   rF   r]   s     €r   rA   z*SuzukiTrotter._recurse.<locals>.<listcomp>Ð   sL   ø€ ð ð ð ð
 ð	ð ð ð à4:ðñ ô ðð ð r   )rJ   Úreversedr   rK   )r"   Úgrouped_paulisÚhalvesÚfullÚouterÚinnerr\   s         @r   rK   zSuzukiTrotter._recurse¸   s.  ø€ à�AŠ:ˆ:Ø!Ð!à�aŠZˆZðð à,¨S¨b¨SÔ1ðñ ô ˆFð # 2Ô&Ð'ˆDØ˜D‘=¥4­°Ñ(8Ô(8Ñ#9Ô#9Ñ9Ð9ð ˜Q  q¨E°A©I¡Ñ!7Ñ7Ñ8ˆIØ�×.Ò.Ø˜‘	ðð ð ð à"0ðñ ô ñô ñ ˆEõ "×*Ò*Ø˜‘	ðð ð ð ð
 #1ðñ ô ñ	ô 	ˆEð ˜5‘= 5Ñ(Ð(r   )r   r   Fr   NFT)r"   r#   r$   r#   r%   r&   r'   r(   r   r)   r*   r&   r+   r&   r,   r-   )r5   r   r,   r6   )
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r
   r2   rQ   ÚstaticmethodrK   Ú__classcell__)r4   s   @r   r   r   #   sÑ   ø€ € € € € ðð ð6 €]ØØð=ð =ð*ðVðñ ô ð  ØØ %Ø#ð
 ØØ#ð4
ð 4
ð 4
ð 4
ð 4
ð 4
ñô ð4
ðl3ð 3ð 3ð 3ðj ð)ð )ñ „\ð)ð )ð )ð )ð )r   r   éd   c                ó
  — t          | t          ¦  «        r| S |t          j        t          ¦  «        j        z  }t          t          j        | ¦  «        ¦  «        |k     rt          j        | ¦  «        S t          d| › d�¦  «        ‚)z³Return real if close, otherwise fail. Unbound parameters are left unchanged.

    Based on NumPy's ``real_if_close``, i.e. ``tol`` is in terms of machine precision for float.
    zEncountered complex value z, but expected real.)
rI   r   ÚnpÚfinfoÚfloatÚepsÚabsÚimagÚrealr0   )ÚvalueÚtolÚabstols      r   r;   r;   Û   st   € õ
 �%Õ,Ñ-Ô-ð Øˆà•2”8�E‘?”?Ô&Ñ&€FÝ
�2Œ7�5‰>Œ>ÑÔ˜VÒ#Ð#ÝŒw�u‰~Œ~Ðå
ÐM°%ÐMÐMÐMÑ
NÔ
NÐNr   )rl   )ri   Ú
__future__r   r   ÚtypingÚcollections.abcr   Ú	itertoolsr   Únumpyrn   Ú"qiskit.circuit.parameterexpressionr   Úqiskit.circuit.quantumcircuitr   Úqiskit.quantum_info.operatorsr   r	   Úqiskit.utils.deprecationr
   rO   r   r   ÚTYPE_CHECKINGr   Ú&qiskit.circuit.library.pauli_evolutionr   r   r;   rF   r   r   ú<module>rƒ      sN  ðð *Ð )à "Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø $Ð $Ð $Ð $Ð $Ð $Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð à BÐ BÐ BÐ BÐ BÐ BØ 8Ð 8Ð 8Ð 8Ð 8Ð 8Ø >Ð >Ð >Ð >Ð >Ð >Ð >Ð >Ø 2Ð 2Ð 2Ð 2Ð 2Ð 2à ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;à	Ôð JØ@Ð@Ð@Ð@Ð@Ð@ØIÐIÐIÐIÐIÐIðu)ð u)ð u)ð u)ð u)�Nñ u)ô u)ð u)ðpOð Oð Oð Oð Oð Or   