§
    ¹³Ùg^  ã                  óÈ   — d Z ddlmZ ddlmZ ddlZddlZddlZddl	m
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 dZ G d„ de¦  «        Z G d„ de
¦  «        Zd„ ZdS )zDiagonal matrix circuit.é    )Úannotations)ÚSequenceN)ÚGate)ÚQuantumCircuit)ÚCircuitError)ÚAnnotatedOperationÚInverseModifier)Údeprecate_funcé   )ÚUCRZGateg»½×Ùß|Û=c                  óL   ‡ — e Zd ZdZ eddd¬¦  «        dˆ fd
„¦   «         Zˆ xZS )ÚDiagonalz/Circuit implementing a diagonal transformation.z1.3zUse DiagonalGate instead.T)ÚsinceÚadditional_msgÚpendingÚdiagúSequence[complex]ÚreturnÚNonec                ó.  •— t                                |¦  «         t          t          j        t          |¦  «        ¦  «        ¦  «        }t          ¦   «                              |d¬¦  «         |                      t          |¦  «        | j	        ¦  «         dS )at  
        Args:
            diag: List of the :math:`2^k` diagonal entries (for a diagonal gate on :math:`k` qubits).

        Raises:
            CircuitError: if the list of the diagonal entries or the qubit list is in bad format;
                if the number of diagonal entries is not :math:`2^k`, where :math:`k` denotes the
                number of qubits.
        r   )ÚnameN)
ÚDiagonalGateÚ_check_inputÚintÚmathÚlog2ÚlenÚsuperÚ__init__ÚappendÚqubits©Úselfr   Ú
num_qubitsÚ	__class__s      €úg/granary/edev/quantum/lib/python3.11/site-packages/qiskit/circuit/library/generalized_gates/diagonal.pyr   zDiagonal.__init__%   sw   ø€ õ 	×!Ò! $Ñ'Ô'Ð'Ý�œ¥3 t¡9¤9Ñ-Ô-Ñ.Ô.ˆ
å‰Œ×Ò˜¨*ÐÑ5Ô5Ð5Ø�Š•L Ñ&Ô&¨¬Ñ4Ô4Ð4Ð4Ð4ó    ©r   r   r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r
   r   Ú__classcell__©r%   s   @r&   r   r   "   sb   ø€ € € € € Ø9Ð9à€^˜%Ð0KÐUYÐZÑZÔZð5ð 5ð 5ð 5ð 5ñ [ÔZð5ð 5ð 5ð 5ð 5r'   r   c                  óT   ‡ — e Zd ZdZdˆ fd„Zd„ Zˆ fd„Zddd„Zed„ ¦   «         Z	ˆ xZ
S )r   ac  A generic diagonal quantum gate.

    Matrix form:

    .. math::
        \text{DiagonalGate}\ q_0, q_1, .., q_{n-1} =
            \begin{pmatrix}
                D[0]    & 0         & \dots     & 0 \\
                0       & D[1]      & \dots     & 0 \\
                \vdots  & \vdots    & \ddots    & 0 \\
                0       & 0         & \dots     & D[n-1]
            \end{pmatrix}

    Diagonal gates are useful as representations of Boolean functions,
    as they can map from :math:`\{0,1\}^{2^n}` to :math:`\{0,1\}^{2^n}` space. For example a phase
    oracle can be seen as a diagonal gate with :math:`\{1, -1\}` on the diagonals. Such
    an oracle will induce a :math:`+1` or :math`-1` phase on the amplitude of any corresponding
    basis state.

    Diagonal gates appear in many classically hard oracular problems such as
    Forrelation or Hidden Shift circuits.

    Diagonal gates are represented and simulated more efficiently than a dense
    :math:`2^n \times 2^n` unitary matrix.

    The reference implementation is via the method described in
    Theorem 7 of [1]. The code is based on Emanuel Malvetti's semester thesis
    at ETH in 2018, supervised by Raban Iten and Prof. Renato Renner.

    **Reference:**

    [1] Shende et al., Synthesis of Quantum Logic Circuits, 2009
    `arXiv:0406176 <https://arxiv.org/pdf/quant-ph/0406176.pdf>`_
    r   r   r   r   c                óÔ   •— |                       |¦  «         t          t          j        t	          |¦  «        ¦  «        ¦  «        }t          ¦   «                              d||¦  «         dS )z}
        Args:
            diag: list of the :math:`2^k` diagonal entries (for a diagonal gate on :math:`k` qubits).
        ÚdiagonalN)r   r   r   r   r   r   r   r"   s      €r&   r   zDiagonalGate.__init__[   sX   ø€ ð
 	×Ò˜$ÑÔÐÝ�œ¥3 t¡9¤9Ñ-Ô-Ñ.Ô.ˆ
å‰Œ×Ò˜ Z°Ñ6Ô6Ð6Ð6Ð6r'   c                ór  — d„ | j         D ¦   «         }t          |¦  «        }t          | j        ¦  «        }|dk    rßg }t	          d|d¦  «        D ]?}t          ||         ||dz            ¦  «        \  ||dz  <   }|                     |¦  «         Œ@t          t          j	        |¦  «        ¦  «        }t          t	          | j        |z
  dz   | j        ¦  «        ¦  «        }| j        |z
  }	t          |¦  «        }
|                     |
|	g|z   ¦  «         |dz  }|dk    °ß|xj        |d         z  c_        || _        d S )Nc                ó6   — g | ]}t          j        |¦  «        ‘ŒS © )ÚcmathÚphase)Ú.0Úzs     r&   ú
<listcomp>z(DiagonalGate._define.<locals>.<listcomp>h   s    € Ð;Ð;Ð;¨!•u”{ 1‘~”~Ð;Ð;Ð;r'   é   r   r   )Úparamsr   r   r$   ÚrangeÚ_extract_rzr    r   r   r   Úlistr   Úglobal_phaseÚ
definition)r#   Údiag_phasesÚnÚcircuitÚ	angles_rzÚiÚrz_angleÚnum_act_qubitsÚctrl_qubitsÚtarget_qubitÚucrzs              r&   Ú_definezDiagonalGate._definee   sG  € ð <Ð;¨t¬{Ð;Ñ;Ô;ˆÝ�ÑÔˆÝ  ¤Ñ1Ô1ˆà�1ŠfˆfØˆIÝ˜1˜a ‘^”^ð +ð +�Ý0;¸KÈ¼NÈKÐXYÐ\]ÑX]ÔL^Ñ0_Ô0_Ñ-�˜A ™FÑ# XØ× Ò  Ñ*Ô*Ð*Ð*Ý ¥¤¨1¡¤Ñ.Ô.ˆNÝ�u T¤_°~Ñ%EÈÑ%IÈ4Ì?Ñ[Ô[Ñ\Ô\ˆKØœ?¨^Ñ;ˆLå˜IÑ&Ô&ˆDØ�NŠN˜4 , °+Ñ!=Ñ>Ô>Ð>à�!‰GˆAð �1Šfˆfð 	ÐÔ ¨A¤Ñ.ÐÔà!ˆŒˆˆr'   c                ó¨   •— t          |t          ¦  «        rt          |¦  «        S t          t          ¦   «                              |¦  «        ¦  «        S )zƒDiagonal Gate parameter should accept complex
        (in addition to the Gate parameter types) and always return build-in complex.)Ú
isinstanceÚcomplexr   Úvalidate_parameter)r#   Ú	parameterr%   s     €r&   rO   zDiagonalGate.validate_parameter}   sF   ø€ õ �i¥Ñ)Ô)ð 	BÝ˜9Ñ%Ô%Ð%å�5™7œ7×5Ò5°iÑ@Ô@ÑAÔAÐAr'   FÚ	annotatedÚboolc                ó�   — |r't          |                      ¦   «         t          ¦  «        S t          d„ | j        D ¦   «         ¦  «        S )z(Return the inverse of the diagonal gate.c                ó6   — g | ]}t          j        |¦  «        ‘ŒS r4   )ÚnpÚconj)r7   Úentrys     r&   r9   z(DiagonalGate.inverse.<locals>.<listcomp>Š   s    € ÐEÐEÐE°�RœW U™^œ^ÐEÐEÐEr'   )r   Úcopyr	   r   r;   )r#   rQ   s     r&   ÚinversezDiagonalGate.inverse…   sB   € àð 	DÝ% d§i¢i¡k¤kµ?ÑCÔCÐCåÐEÐE¸¼ÐEÑEÔEÑFÔFÐFr'   c                ót  — t          | t          t          j        f¦  «        st	          d¦  «        ‚t          j        t          | ¦  «        ¦  «        }|dk     s|                     ¦   «         st	          d¦  «        ‚t          j	        t          j
        | ¦  «        dt          ¬¦  «        st	          d¦  «        ‚dS )z%Check if ``diag`` is in valid format.z2Diagonal entries must be in a list or numpy array.r   z<The number of diagonal entries is not a positive power of 2.)Úatolz4A diagonal element does not have absolute value one.N)rM   r>   rU   Úndarrayr   r   r   r   Ú
is_integerÚallcloseÚabsÚ_EPS)r   r$   s     r&   r   zDiagonalGate._check_inputŒ   s§   € õ ˜$¥¥r¤zÐ 2Ñ3Ô3ð 	UÝÐSÑTÔTÐTÝ”Y�s 4™yœyÑ)Ô)ˆ
Ø˜Š>ˆ> ×!6Ò!6Ñ!8Ô!8ˆ>ÝÐ]Ñ^Ô^Ð^ÝŒ{�2œ6 $™<œ<¨µÐ6Ñ6Ô6ð 	WÝÐUÑVÔVÐVð	Wð 	Wr'   r(   )F)rQ   rR   )r)   r*   r+   r,   r   rK   rO   rY   Ústaticmethodr   r-   r.   s   @r&   r   r   7   sµ   ø€ € € € € ð!ð !ðF7ð 7ð 7ð 7ð 7ð 7ð"ð "ð "ð0Bð Bð Bð Bð BðGð Gð Gð Gð Gð ðWð Wñ „\ðWð Wð Wð Wð Wr'   r   c                ó$   — | |z   dz  }|| z
  }||fS )z®
    Extract a Rz rotation (angle given by first output) such that exp(j*phase)*Rz(z_angle)
    is equal to the diagonal matrix with entires exp(1j*ph1) and exp(1j*ph2).
    g       @r4   )Úphi1Úphi2r6   Úz_angles       r&   r=   r=   ˜   s%   € ð
 �D‰[˜CÑ€EØ�T‰k€GØ�'ˆ>Ðr'   )r,   Ú
__future__r   Úcollections.abcr   r5   r   ÚnumpyrU   Úqiskit.circuit.gater   Úqiskit.circuit.quantumcircuitr   Úqiskit.circuit.exceptionsr   Ú"qiskit.circuit.annotated_operationr   r	   Úqiskit.utils.deprecationr
   rJ   r   r`   r   r   r=   r4   r'   r&   ú<module>rn      sD  ðð Ð à "Ð "Ð "Ð "Ð "Ð "Ø $Ð $Ð $Ð $Ð $Ð $à €€€Ø €€€Ø Ð Ð Ð à $Ð $Ð $Ð $Ð $Ð $Ø 8Ð 8Ð 8Ð 8Ð 8Ð 8Ø 2Ð 2Ð 2Ð 2Ð 2Ð 2Ø RÐ RÐ RÐ RÐ RÐ RÐ RÐ RØ 3Ð 3Ð 3Ð 3Ð 3Ð 3à Ð Ð Ð Ð Ð à€ð5ð 5ð 5ð 5ð 5ˆ~ñ 5ô 5ð 5ð*^Wð ^Wð ^Wð ^Wð ^W�4ñ ^Wô ^Wð ^WðBð ð ð ð r'   