
    z	i/                        S r SSKJ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  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  Sr " S S\5      rg)z;Uniformly controlled gates (also called multiplexed gates).    )annotationsN)Gate)HGate)is_unitary_matrix)QuantumRegister)QuantumCircuit)CircuitError)QiskitError)uc_gate   )DiagonalGateg|=c                     ^  \ rS rSrSr S     SU 4S jjjrS rS rS rSSU 4S jjjr	S r
S	 rS
 rS r\S 5       rS rSrU =r$ )UCGate*   a+  Uniformly controlled gate (also called multiplexed gate).

These gates can have several control qubits and a single target qubit.
If the k control qubits are in the state :math:`|i\rangle` (in the computational basis),
a single-qubit unitary :math:`U_i` is applied to the target qubit.

This gate is represented by a block-diagonal matrix, where each block is a
:math:`2\times 2` unitary, that is

.. math::

    \begin{pmatrix}
        U_0 & 0 & \cdots & 0 \\
        0 & U_1 & \cdots & 0 \\
        \vdots  &     & \ddots & \vdots \\
        0 & 0   &  \cdots & U_{2^{k-1}}
    \end{pmatrix}.

The decomposition is based on Ref. [1].

Unnecessary controls and repeated operators can be removed as described in Ref [2].

References:

[1] Bergholm et al., Quantum circuits with uniformly controlled one-qubit gates (2005).
`Phys. Rev. A 71, 052330 <https://journals.aps.org/pra/abstract/10.1103/PhysRevA.71.052330>`__.

[2] de Carvalho et al., Quantum multiplexer simplification for state preparation (2024).
`arXiv:2409.05618 <https://arxiv.org/abs/2409.05618>`__.

c                ,  > [        U[        5      (       d  [        S5      eU H  nUR                  S:X  a  M  [        S5      e   U(       d  [        S5      e[        R
                  " [        U5      5      nUS:  d  UR                  5       (       d  [        S5      eU H#  n[        U[        5      (       a  M  [        S5      e   [        5       nU(       a  U R                  X5      u  paX64U l        [        TU ]9  S[        U5      S	-   U5        X l        g
)a  
Args:
    gate_list: List of two qubit unitaries :math:`[U_0, ..., U_{2^{k-1}}]`, where each
        single-qubit unitary :math:`U_i` is given as a :math:`2 \times 2` numpy array.
    up_to_diagonal: Determines if the gate is implemented up to a diagonal.
        or if it is decomposed completely (default: False).
        If the ``UCGate`` :math:`U` is decomposed up to a diagonal :math:`D`, this means
        that the circuit implements a unitary :math:`U'` such that :math:`D U' = U`.
    mux_simp: Determines whether the search for repetitions is conducted (default: True).
        The intention is to perform a possible simplification in the number of controls
        and operators.

Raises:
    QiskitError: in case of bad input to the constructor
z6The single-qubit unitaries are not provided in a list.)   r   z9The dimension of a controlled gate is not equal to (2,2).zThe gate list cannot be empty.r   zMThe number of controlled single-qubit gates is not a non-negative power of 2.z!A controlled gate is not unitary.multiplexerr   N)
isinstancelistr
   shapemathlog2len
is_integerr   _EPSset	_simplify
simp_contrsuper__init__intup_to_diagonal)self	gate_listr"   mux_simpgate	num_contrnew_controls	__class__s          e/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/circuit/library/generalized_gates/uc.pyr    UCGate.__init__K   s    & )T**VWWD::'!"]^^  >?? IIc)n-	q=	 4 4 6 6_ 
 D$T400!"EFF  u&*nnY&J#L#2 	I(:IF,    c                f   [        5       n[        5       nUR                  5       n[        [        U5      5       H  nUR	                  US-   5        M     [        U5      S:  a  U R                  XU5      u  pEU Vs1 s H  owU;  d  M
  UiM     nnU V	s/ s H	  oc  M  U	PM     n
n	X4$ s  snf s  sn	f )z https://arxiv.org/abs/2409.05618r   )r   copyranger!   addr   _repetition_search)r#   r$   r'   cncmux_copyixr(   r&   new_muxs              r*   r   UCGate._simplify{   s     EU>>#s9~&AEE!a%L ' y>A229RLB#$41a14$,AHD4HA$$ 5As   ;	B)B)B.B.c                   [        5       nSnU[        U5      S-  ::  a  Sn[        R                  " X   US   5      (       ad  UR	                  5       n[        U5      SU-  -  nSn	US:  a;  US-  nU R                  XX5      u  pU	SU-  -   n	U
(       d  UnOUS:X  a  SnUS:  a  M;  U(       a*  U[        R                  " U5      -
  nUR                  U5        SU-  nU[        U5      S-  ::  a  M  XC4$ )Nr   r   Fr   T)	r   r   npallcloser.   _repetition_verifyr   r   r0   )r#   muxlevelr4   r3   ddisentanglementmux_orgrepetitionspvalidremoved_contrs               r*   r1   UCGate._repetition_search   s    U3s8a<#O{{363q6**"--/!#h!a%0!Ao1$K&*&=&=aC&ROEAE	A #*"a'*. "Ao  %		! 4}%AA' 3s8a<( |r,   c                    SnX-   nXR:  a=  [         R                  " X1   X6   5      (       d  SU4$ S XF'   US-   US-   US-   pVnXR:  a  M=  SU4$ )Nr   Fr   T)r:   r;   )r#   baser?   r=   r4   r5   	next_bases          r*   r<   UCGate._repetition_verify   sd    H	e;;sy#.99h&"&H!%9q=!a%QD	 e
 X~r,   c           	       > U(       d  [        U R                  S-   U R                  / S9n[        U R                  R
                  6 n[        U R                  5       H8  nUR                  UR                  UR                  R                  US9S95        M:     U R                  R                  * Ul        X2l        U$ [        TU ]-  US9nU$ )zReturn the inverse.

This does not re-compute the decomposition for the multiplexer with the inverse of the
gates but simply inverts the existing decomposition.
_dg)name
num_qubitsparams)	annotated)	operation)r   rM   rN   r   
definitionqregsreversed_definition_appendreplacerQ   inverseglobal_phaser   )r#   rP   inverse_gaterR   instr)   s        r*   rX   UCGate.inverse   s     YY&4??2L ()>)>?J !1!12""LL4>>+A+AI+A+VLW 3
 (,'C'C&CJ#&0#  !7?Y??Lr,   c                   U R                  5       u  pU R                  S   (       a  U R                  S    Vs/ s H  o0R                  U-
  PM     nnUR                  5         [	        U R                  5       H  nUS/U-   ;  d  M  SU-  n/ n[        U5      n[	        U5       H@  nUR                  X(   5        US-   U-  S:X  d  M$  UR                  X(S-   U-
  US-    5        MB     [        R                  " U5      nM     U$ s  snf )Nr   r   r   )
_dec_ucgr   rN   reverser/   r   appendextendr:   array)	r#   _diagr5   
q_controlsr?   new_diagnjs	            r*   _get_diagonalUCGate._get_diagonal   s    
 --/??17;q7IJ7I!//A-7IJJ 4??+QC*,,1A!HD	A"1X 0EQ;!+$OODQQU,CD & 88H-D ,  Ks   Dc                4    U R                  5       u  pXl        g )N)r^   rR   )r#   ucg_circuitrc   s      r*   _defineUCGate._define   s    %r,   c           	        [         R                  " SU R                  -  5      R                  5       n[	        U R                  S5      nUS   nU R
                  S   nU(       a?  U R
                  S    Vs/ s H  oRU R                  U-
     PM     nnUR                  5         OUSS n[        USS9nU(       d%  UR                  U R                  S   US   5        Xq4$ U R                  5       u  p[        U5       GH  u  pYUS:X  a(  [        5       R                  5       R                  U	5      n
OU[        U5      S-
  :X  a[  U	R                  [         R#                  [         R$                  S-  5      5      R                  [        5       R                  5       5      n
O[        5       R                  5       R                  U	R                  [         R#                  [         R$                  S-  5      5      5      R                  [        5       R                  5       5      n
UR                  X/5        [         R&                  " US-   5      n[        U5      [        UR)                  S5      5      -
  nUnU[        U5      S-
  :X  a  GM  UR+                  Xm   U5        U=R,                  S	[         R$                  -  -  sl        GM     U R.                  (       d   [1        U5      nUR3                  X/U-   5        Xq4$ s  snf )
z
Call to create a circuit that implements the uniformly controlled gate. If
up_to_diagonal=True, the circuit implements the gate up to a diagonal gate and
the diagonal gate is also returned.
r   qr   r   Nuc)rM   0g      ?)r:   onesrN   tolistr   r   r_   r   unitaryrO   _dec_ucg_help	enumerater   	to_matrixdotr   r   _rzpibinary_reprrstripcxrY   r"   r   r`   )r#   rd   rp   q_targetmux_simplifyr5   re   circuitsingle_qubit_gatesr&   squ
binary_repnum_trailing_zerosq_contr_indexdiagonals                  r*   r^   UCGate._dec_ucg   s`    wwq$//)*113DOOS1Q4q):>//!:LM:LQDOOa/0:LJM 12J .OODKKNAaD1=  &*%7%7%9"	 !!34GAAvg'')--d3c,-11hhvzz"%%!)4599%':K:K:MN GY[S&**RUUQY"789S**,-	  OOC, A.J!$Z3z7H7H7M3N!N.M./!33

:4h?$$ruu4$$/ 50 "" $D)HNN8Z*%<=}] Ns   4K5c           	     <   U R                    Vs/ s H  n[        R                  " U[        SS9PM     nnU R                  S   (       a0  [
        R                  " U[        U R                  S   5      S-   5      $ [
        R                  " X R                  5      $ s  snf )z
This method finds the single qubit gate arising in the decomposition of UCGates given in
https://arxiv.org/pdf/quant-ph/0410066.pdf.
f)dtypeorderr   r   )	rO   r:   asarraycomplexr   r   dec_ucg_helpr   rN   )r#   r&   r   s      r*   rv   UCGate._dec_ucg_help  s    
 VZU`U`aU`TbjjWCHU`a??1''(:CPQ@R<SVW<WXX##$6HH bs   $Bc                    [         R                  " [         R                  " SU -  S-  5      S/S[         R                  " SU -  S-  5      //5      $ )Ny              ?r   r   y             )r:   rb   exp)alphas    r*   rz   
UCGate._rz&  sB    xx"&&ea0!4q"&&uq:Q6RSTTr,   c                    [        U[        R                  5      (       a  U$ [        S[	        U5       SU R
                   35      e)z9Uniformly controlled gate parameter has to be an ndarray.zinvalid param type z	 in gate )r   r:   ndarrayr	   typerM   )r#   	parameters     r*   validate_parameterUCGate.validate_parameter*  s;    i,,!4T)_4EYtyykZ[[r,   )rR   r   r"   )FT)r$   zlist[np.ndarray]r"   boolr%   r   )F)rP   r   returnr   )__name__
__module____qualname____firstlineno____doc__r    r   r1   r<   rX   ri   rm   r^   rv   staticmethodrz   r   __static_attributes____classcell__)r)   s   @r*   r   r   *   s    B [_.-).-;?.-SW.- .-`%"2 0*&:xI U U\ \r,   r   )r   
__future__r   r   numpyr:   qiskit.circuit.gater   'qiskit.circuit.library.standard_gates.hr   (qiskit.quantum_info.operators.predicatesr   qiskit.circuitr   qiskit.circuit.quantumcircuitr   qiskit.circuit.exceptionsr	   qiskit.exceptionsr
   qiskit._accelerater   r   r   r   r    r,   r*   <module>r      sD   ( B "   $ 9 F * 8 2 ) & "E\T E\r,   