
    z	iS?                        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SKJr  Sr " S S\	5      rS rS rS rg)z(
Generic isometries from m to n qubits.
    )annotationsN)CircuitError)Instruction)QuantumCircuit)QuantumRegister)QiskitError)is_isometry)isometry   )DiagonalGate)UCGate)	MCGupDiagg|=c                     ^  \ rS rSrSr\4         SU 4S jjjrS rSSU 4S jjjrS r	S r
S rS	 rS
 rS rS rS rS rSrU =r$ )Isometry)   az  Decomposition of arbitrary isometries from :math:`m` to :math:`n` qubits.

In particular, this allows to decompose unitaries (m=n) and to do state preparation (:math:`m=0`).

The decomposition is based on [1].

References:

[1] Iten et al., Quantum circuits for isometries (2016).
`Phys. Rev. A 93, 032318
<https://journals.aps.org/pra/abstract/10.1103/PhysRevA.93.032318>`__.

c                  > [         R                  " U[        S9n[        UR                  5      S:X  a  UR                  UR                  S   S5      nXl        X l        X0l        SU l	        X@l
        [        R                  " UR                  S   5      n[        R                  " UR                  S   5      nUR                  5       (       a  US:  a  [        S5      eUR                  5       (       a  US:  a  [        S5      eXe:  a  [        S5      e[        XR                  5      (       d  [        S5      e[!        U5      U-   U-   n["        TU ]I  S	USU/5        g)
a  
Args:
    isometry: An isometry from :math:`m` to :math`n` qubits, i.e., a complex
        ``np.ndarray`` of dimension :math:`2^n \times 2^m` with orthonormal columns (given
        in the computational basis specified by the order of the ancillas
        and the input qubits, where the ancillas are considered to be more
        significant than the input qubits).
    num_ancillas_zero: Number of additional ancillas that start in the state :math:`|0\rangle`
        (the :math:`n-m` ancillas required for providing the output of the isometry are
        not accounted for here).
    num_ancillas_dirty: Number of additional ancillas that start in an arbitrary state.
    epsilon: Error tolerance of calculations.
)dtyper   r   NzDThe number of rows of the isometry is not a non negative power of 2.zGThe number of columns of the isometry is not a non negative power of 2.zNThe input matrix has more columns than rows and hence it can't be an isometry.zMThe input matrix has non orthonormal columns and hence it is not an isometry.r
   )nparraycomplexlenshapereshapeiso_datanum_ancillas_zeronum_ancillas_dirty_inverse_epsilonmathlog2
is_integerr   r	   intsuper__init__)	selfr
   r   r   epsilonnm
num_qubits	__class__s	           k/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/circuit/library/generalized_gates/isometry.pyr$   Isometry.__init__?   s8   * 88HG4 x~~!#''q(91=H !2"4 IIhnnQ'(IIhnnQ'(||~~QV  ||~~QY  5`  8]]33_  V//2DD
ZXJ?    c                    U R                  5       nUR                  5       n[        U R                  S5      n[	        USS9nUR                  XS S  5        X0l        g )Nqr
   name)inv_gateinverser   r)   r   append
definition)r%   gater/   iso_circuits       r+   _defineIsometry._definey   sM     }}||~DOOS1$QZ841&%r-   c                T   > / U l         [        TU ]	  US9nU R                  /U l         U$ )N)	annotated)paramsr#   r3   r   )r%   r;   invr*   s      r+   r3   Isometry.inverse   s,    go	o2}}o
r-   c                |   [        U R                  S5      n[        USS9nU R                  U5      u  nnnnU R                  R                  [        5      n/ n[        [        R                  " U R                  R                  S   5      5      n	[        SU	-  5       H8  n
U R                  X!XU
5      u  pxUR                  XzS4   5        USS2SS24   nM:     [        U5      S:  aU  [        R                   " XR"                  5      (       d0  [%        [&        R(                  " U5      5      nUR                  X5        U$ )z
Call to create a circuit with gates that take the desired isometry to the first 2^m columns
 of the 2^n*2^n identity matrix (see https://arxiv.org/abs/1501.06911)
r/   isometry_to_uncomputer0   r      r   N)r   r)   r   _define_qubit_roler   astyper   r"   r   r    r   range_decompose_columnr4   r   isometry_rs#diag_is_identity_up_to_global_phaser   r   r   conj)r%   r/   circuitq_inputq_ancillas_for_outputq_ancillas_zeroq_ancillas_dirtyremaining_isometrydiagr(   column_indexdiagonals               r+   _gates_to_uncomputeIsometry._gates_to_uncompute   s!   
 DOOS1 )@A ##A&	
! "]]11':		$----a012
 "!Q$KL'+'='=Dl($ KK*?;<!3AqrE!: ( t9q=!P!P--"
 "
 $BGGDM2HNN8-r-   c           	         [        [        R                  " U R                  R                  S   5      5      n[        U5       H  nU R                  XX4XW5      u  pCM     XC4$ )z0
Decomposes the column with index column_index.
r   )r"   r   r    r   r   rD   _disentangle)r%   rI   r/   rO   rN   rP   r'   ss           r+   rE   Isometry._decompose_column   s\     		$----a012qA'+'8'8Dl($  "''r-   c                   UnSnUn	[        [        R                  " U R                  R                  S   5      5      n
S[
        R                  " XvS-   5      -  SU-  -  [
        R                  " XvS-   5      -   nS[
        R                  " XvS-   5      -  S-   SU-  -  [
        R                  " XvS-   5      -   nX-
  S-
  n[
        R                  " Xv5      S:X  Ga7  [
        R                  " XvS-   5      S:w  Ga  [        R                  " XU4   5      U R                  :  a  [
        R                  " XU4   XU4   /SU R                  5      n[        [        Xz5      5       VVs/ s H  u  nnUS:X  d  M  X:w  d  M  UPM     nnnU R                  XUUU5      n[
        R                   " U	UX5      n	[        R"                  " U5      R%                  [&        SS9n[
        R(                  " U	UU/-   U5      n	[
        R*                  " UUU/-   UU
5      nU R-                  XU5      n[
        R.                  " UU R                  5      (       d  [1        [3        U5      5      nU R5                  XUUU5      n[        R"                  " U5      R%                  [&        SS9n[
        R6                  " UU5      n[
        R8                  " U	[;        U5      U5      n	[
        R*                  " UUU/-   UU
5      nX4$ s  snnf )zy
Disentangle the s-th significant qubit (starting with s = 0) into the zero or the one state
(dependent on column_index)
r   rA   r   F)copy)r"   r   r    r   r   rF   abk_sr   absr   reverse_qubit_state	enumerate_get_binary_rep_as_list_append_mcg_up_to_diagonalapply_multi_controlled_gaterH   rC   r   apply_diagonal_gateapply_diagonal_gate_to_diag_find_squs_for_disentangling"ucg_is_identity_up_to_global_phaselistrD   _append_ucg_up_to_diagonalmerge_ucgate_and_diag	apply_ucgr   )r%   rI   r/   rO   rN   rP   rV   kk_primevr'   index1index2target_labelr6   ixcontrol_labelsdiagonal_mcgdiag_mcg_inversesingle_qubit_gatesdiagonal_ucgdiagonal_ucg_inverses                          r+   rU   Isometry._disentangle   s     		$----a012 []]1!e,,q!t3kmmA1u6MMkmmA1u--1QT9KMM!QRU<SSuqy OOA!Q&aQ'1,q)*T]]: 227?#Qw%78!T]]D
 &&=a&CDDDAq6 / D  
  ::D.,L 77><^A!ww|4;;G%;P//>\N24DA ::n~57GD ">>qQG==>PRVR_R_``!%"56N::.L $&77<#8#?#?e#?#T !,!B!B"$8" %%a^)<>PQA::n~57KQD wUs   #K14K1;K1c                    [         R                  " XX0R                  [        [        R
                  " U R                  R                  S   5      5      S9nU$ )Nr   )r'   )rF   find_squs_for_disentanglingr   r"   r   r    r   r   )r%   rm   rk   rV   ress        r+   re   %Isometry._find_squs_for_disentangling  sA    55!]]c$))DMM4G4G4J*K&L
 
r-   c                J   U R                  U5      u  nnnn	[        [        R                  " U R                  R
                  S   5      5      n
Xg-   n[        [        XKU
5      5      n[        U/X5      S   n[        USS9nUR                  X/U-   5        UR                  5       $ )Nr   T)up_to_diagonal)rB   r"   r   r    r   r   _reverse_qubit_oder_get_qubits_by_labelr   r4   _get_diagonal)r%   circr/   rv   rs   rp   rJ   rK   rL   rM   r'   qubitscontrol_qubitstarget_qubitucgs                  r+   rh   #Isometry._append_ucg_up_to_diagonal  s     ##A&	
!		$----a0120 --A.Z[-\]+\NFFqI'=C.89  ""r-   c                   U R                  U5      u  nnnn	[        [        R                  " U R                  R
                  S   5      5      n
Xg-   n[        [        XKU
5      5      n[        U/X5      S   n[        U
5       Vs/ s H  oXE/-   ;  d  M  UPM     nn[        [        XU
5      5      U	-   n[        U[        U5      [        U5      [        U5      5      nUR                  UU/U-   U-   U-   5        UR                  5       $ s  snf )Nr   )rB   r"   r   r    r   r   r   r   rD   r   r   r4   r   )r%   r   r/   r6   rs   rp   rJ   rK   rL   rM   r'   r   r   r   rq   ancilla_dirty_labelsancillas_dirtymcg_up_to_diags                     r+   ra   #Isometry._append_mcg_up_to_diagonal!  s    ##A&	
!		$----a0120,-A.Z[-\]+\NFFqI ,18`8aQ_@_7_8` 45IST UV 	 ##n%s?';S=P
 	\N^;oMP^^	
 ++--  as   DDc                6   [        [        R                  " U R                  R                  S   5      5      n[        [        R                  " U R                  R                  S   5      5      nUS U nXU nXX R
                  -    nXU R
                  -   S  nXEXg4$ )Nr   r   )r"   r   r    r   r   r   )r%   r/   r'   r(   rJ   rK   rL   rM   s           r+   rB   Isometry._define_qubit_role;  s    		$----a012		$----a012 BQ% !A$:$: :;!7!779:PPr-   c                    [        U[        R                  5      (       a  U$ [        U[        [        45      (       a  U$ [        S[        U5       SU R                   35      e)z(Isometry parameter has to be an ndarray.zinvalid param type z
 for gate )
isinstancer   ndarrayrg   r"   r   typer1   )r%   	parameters     r+   validate_parameterIsometry.validate_parameterG  sU    i,,i$--!4T)_4EZPTPYPY{[\\r-   c                ~    U R                   c%  U R                  5       nUR                  5       U l         U R                   $ )z"Return the adjoint of the unitary.)r   rR   to_instruction)r%   r7   s     r+   r2   Isometry.inv_gateP  s6    ==  224K'668DM}}r-   )r   r   r5   r   r   r   r<   )
r
   z
np.ndarrayr   r"   r   r"   r&   floatreturnNone)F)r;   bool)__name__
__module____qualname____firstlineno____doc___EPSr$   r8   r3   rR   rE   rU   re   rh   ra   rB   r   r2   __static_attributes____classcell__)r*   s   @r+   r   r   )   s    4 8@8@ 8@  	8@
 8@ 
8@ 8@t	& #J	(ET#,.4
Q] r-   r   c                @    U  Vs/ s H  o1X#-
  S-
     PM     sn$ s  snf )Nr    )labelsr   r)   labels       r+   r   r   b  s%    8>?u:%)*???s   c                *    [        [        U 5      5      $ N)rg   reversed)r   s    r+   r   r   f  s     !!r-   c                    [         R                  " U 5      R                  U5      n/ nU H&  nU H  nUR                  [	        U5      5        M     M(     X1* S  $ r   )r   binary_reprzfillr4   r"   )r'   
num_digitsbinary_stringbinarylinecs         r+   r`   r`   m  sS    NN1%++J7MFAMM#a&!   +,r-   ) r   
__future__r   r   numpyr   qiskit.circuit.exceptionsr   qiskit.circuit.instructionr   qiskit.circuit.quantumcircuitr   qiskit.circuitr   qiskit.exceptionsr   (qiskit.quantum_info.operators.predicatesr	   qiskit._accelerater
   rF   rQ   r   ucr   mcg_up_to_diagonalr   r   r   r   r   r`   r   r-   r+   <module>r      sW   $ #   2 2 8 * ) @ 6 "  )o{ or	@" r-   