
    z	i                        S r SSKJr  SSKJr  SSKrSSKrSSKrSSK	J
r
  SSKJr  SSKJr  SSKJrJr  SS	KJr  S
SKJr  Sr " S S\5      r " S S\
5      rS rg)zDiagonal matrix circuit.    )annotations)SequenceN)Gate)QuantumCircuit)CircuitError)AnnotatedOperationInverseModifier)deprecate_func   )UCRZGateg|=c                  F   ^  \ rS rSrSr\" SSSS9S	U 4S jj5       rSrU =r$ )
Diagonal"   z/Circuit implementing a diagonal transformation.z2.1zUse DiagonalGate instead.zin Qiskit 3.0)sinceadditional_msgremoval_timelinec                   > [         R                  U5        [        [        R                  " [        U5      5      5      n[        TU ]  USS9  U R                  [        U5      U R                  5        g)a<  
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selfdiag
num_qubits	__class__s      k/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/circuit/library/generalized_gates/diagonal.pyr   Diagonal.__init__%   sS     	!!$'3t9-.
*5L&4     r!   zSequence[complex]returnNone)	__name__
__module____qualname____firstlineno____doc__r
   r   __static_attributes____classcell__r#   s   @r$   r   r   "   s&    92(
5
5r&   r   c                  `   ^  \ rS rSrSrS	U 4S jjrS rU 4S jrS
SS jjr\	S 5       r
SrU =r$ )r   ;   a  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.

References:

[1] Shende et al., Synthesis of Quantum Logic Circuits, 2009
`arXiv:0406176 <https://arxiv.org/pdf/quant-ph/0406176.pdf>`_
c                   > U R                  U5        [        [        R                  " [	        U5      5      5      n[
        TU ]  SX!5        g)ze
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   DiagonalGate.__init___   s9    
 	$3t9-.
Z6r&   c                   U R                    Vs/ s H  n[        R                  " U5      PM     nn[        U5      n[	        U R
                  5      nUS:  a  / n[        SUS5       H/  n[        X&   X&S-      5      u  X&S-  '   nUR                  U5        M1     [        [        R                  " U5      5      n[        [        U R
                  U-
  S-   U R
                  5      5      n	U R
                  U-
  n
[        U5      nUR                  X/U	-   5        US-  nUS:  a  M  U=R                  US   -  sl        X@l        g s  snf )N   r   r   )paramscmathphaser   r   r"   range_extract_rzr   r   r   r   listr   global_phase
definition)r    zdiag_phasesncircuit	angles_rzirz_anglenum_act_qubitsctrl_qubitstarget_qubitucrzs               r$   _defineDiagonalGate._definei   s     04{{;{!u{{1~{; 11fI1a^0;KNK\]X]L^0_-F#X  * $ !1.NuT__~%E%I4??[\K??^;LI&DNN4+!=>!GA 1f 	A.!' <s    Ec                t   > [        U[        5      (       a  [        U5      $ [        [        TU ]  U5      5      $ )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$   rR   DiagonalGate.validate_parameter   s2     i))9%%575i@AAr&   c                    U(       a  [        U R                  5       [        5      $ [        U R                   Vs/ s H  n[
        R                  " U5      PM     sn5      $ s  snf )z(Return the inverse of the diagonal gate.)r   copyr	   r   r:   npconj)r    	annotatedentrys      r$   inverseDiagonalGate.inverse   sA    %diik?CCERWWU^EFFEs    A c                j   [        U [        [        R                  45      (       d  [	        S5      e[
        R                  " [        U 5      5      nUS:  d  UR                  5       (       d  [	        S5      e[        R                  " [        R                  " U 5      S[        S9(       d  [	        S5      eg)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)rP   r?   rW   ndarrayr   r   r   r   
is_integerallcloseabs_EPS)r!   r"   s     r$   r   DiagonalGate._check_input   s     $rzz 233STTYYs4y)
>!6!6!8!8]^^{{266$<6UVV 7r&   )rA   r(   )F)rY   bool)r+   r,   r-   r.   r/   r   rM   rR   r[   staticmethodr   r0   r1   r2   s   @r$   r   r   ;   s5    !F7"0BG W Wr&   r   c                    X-   S-  nX-
  nX#4$ )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       @r'   )phi1phi2r<   z_angles       r$   r>   r>      s    
 [CEkG>r&   )r/   
__future__r   collections.abcr   r;   r   numpyrW   qiskit.circuit.gater   qiskit.circuit.quantumcircuitr   qiskit.circuit.exceptionsr   "qiskit.circuit.annotated_operationr   r	   qiskit.utils.deprecationr
   rL   r   rc   r   r   r>   r'   r&   r$   <module>rs      sR     " $    $ 8 2 R 3 5~ 52^W4 ^WBr&   