
    z	i.                    r    S r SSKJr  SSKrSSKJrJr  SSKJ	r	  SSK
Jr  SSKJr  SSKJr   " S	 S
\5      rg)zLinear Function.    )annotationsN)QuantumCircuitGate)CircuitError)PermutationGate)deprecate_func)Cliffordc                     ^  \ rS rSrSr S     SU 4S jjjr\SS j5       r\S 5       r\S 5       r	S r
S rS	 r\" S
SSS9S 5       r\S 5       r\S 5       rSS jrS rSS jrS rS rSrU =r$ )LinearFunction   uN  A linear reversible circuit on n qubits.

Internally, a linear function acting on n qubits is represented
as a n x n matrix of 0s and 1s in numpy array format.

A linear function can be synthesized into CX and SWAP gates using the Patel–Markov–Hayes
algorithm, as implemented in :func:`~qiskit.synthesis.synth_cnot_count_full_pmh`
based on reference [1].

For efficiency, the internal n x n matrix is stored in the format expected
by cnot_synth, which is the big-endian (and not the little-endian) bit-ordering convention.

Example:
 
The circuit

.. code-block:: text

    q_0: ──■──
         ┌─┴─┐
    q_1: ┤ X ├
         └───┘
    q_2: ─────

is represented by a 3x3 linear matrix

.. math::

        \begin{pmatrix}
            1 & 0 & 0 \\
            1 & 1 & 0 \\
            0 & 0 & 1
        \end{pmatrix}


References:

[1] Ketan N. Patel, Igor L. Markov, and John P. Hayes,
Optimal synthesis of linear reversible circuits,
Quantum Inf. Comput. 8(3) (2008).
`Online at umich.edu. <https://web.eecs.umich.edu/~imarkov/pubs/jour/qic08-cnot.pdf>`_
c                @  > Sn[        U[        [        R                  45      (       a   [        R                  " U[
        SS9n[        UR                  5      S:w  d   UR                  S   UR                  S   :w  a  [        S5      eU(       a  SSK
Jn  U" U5      (       d  [        S	5      eO[        U[        5      (       a  Un[        R                  U5      nO[        U[        5      (       a  UR                  R!                  5       nOa[        U["        5      (       a  [        R%                  U5      nO6[        U[&        5      (       a  [        R)                  U5      nO[        S
5      e[*        TU ]Y  S[        U5      X/S9  g! [         a    [        S5      Sef = f)av  
Args:
    linear: data from which a linear function can be constructed. It can be either a
        nxn matrix (describing the linear transformation), a permutation (which is a
        special case of a linear function), another linear function, a clifford (when
        it corresponds to a linear function), or a quantum circuit composed of
        linear gates (CX and SWAP) and other objects described above, including
        nested subcircuits.

    validate_input: if True, performs more expensive input validation checks,
        such as checking that a given n x n matrix is invertible.

Raises:
    CircuitError: if the input is invalid:
        either the input matrix is not square or not invertible,
        or the input quantum circuit contains non-linear objects
        (for example, a Hadamard gate, or a Clifford that does
        not correspond to a linear function).
NT)dtypecopyz9A linear function must be represented by a square matrix.   r      )check_invertible_binary_matrixz>A linear function must be represented by an invertible matrix.z5A linear function cannot be successfully constructed.linear_function)name
num_qubitsparams)
isinstancelistnpndarrayarraybool
ValueErrorr   lenshapeqiskit.synthesis.linearr   r   r   _circuit_to_matlinearr   r   _permutation_to_matr	   _clifford_to_matsuper__init__)selfr"   validate_inputoriginal_circuitr   	__class__s        r/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/circuit/library/generalized_gates/linear_function.pyr&   LinearFunction.__init__F   sf   @  ftRZZ011&4@ 6<< A%aFLLO)K"#^__ R5f==&X  //%#33F;F//]]'')F00#77?F)) $44V<F VWW"s6{FC] 	 	
S  "Os   F Fc                   U R                   n[        R                  " X[        S9nU R                   GH  nUR
                  R                  S;   a  M   UR
                  R                  S:X  ai  U R                  UR                  S   5      R                  nU R                  UR                  S   5      R                  nX%SS24   X$SS24   -  X%SS24'   M  UR
                  R                  S:X  a]  U R                  UR                  S   5      R                  nU R                  UR                  S   5      R                  nX%U/   X$U/'   GM  [        UR
                  SS5      b   [        UR
                  R                  5      nO[        UR
                  5      nUR                   Vs/ s H  opR                  U5      R                  PM     nnUR                  [        U5      U5      n[        R                  " UR                   R#                  [$        5      UR#                  [$        5      5      S	-  nUR#                  [        5      nGM     U$ s  snf )
zEThis creates a nxn matrix corresponding to the given quantum circuit.r   )barrierdelaycxr   r   Nswap
definitionr   )r   r   eyer   data	operationr   find_bitqubitsindexgetattrr   r3   extend_with_identityr   dotr"   astypeint)	qcnqmatinstructioncbtbotherq	positionss	            r+   r!   LinearFunction._circuit_to_mat   s    ]]ffR4(77K$$))-AA$$))T1[[!3!3A!67==[[!3!3A!67==!a%jSQZ8E
$$))V3[[!3!3A!67==[[!3!3A!67== #HH
 {,,lDAM&{'<'<'G'GH&{'<'<=7B7I7IJ7I!Q--7IIJ..s3xCE&&,,S13::c?CaGC**T"C9 #< 
 Ks   '$Ic                   U R                   R                  5       (       d>  U R                  R                  5       (       d  U R                  R                  5       (       a  [	        S5      e[
        R                  " U R                  5      $ )a>  This creates a nxn matrix corresponding to the given Clifford, when Clifford
can be converted to a linear function. This is possible when the clifford has
tableau of the form [[A, B], [C, D]], with B = C = 0 and D = A^{-1}^t, and zero
phase vector. In this case, the required matrix is A^t.
Raises an error otherwise.
z<The given clifford does not correspond to a linear function.)phaseanydestab_zstab_xr   r   	transposedestab_x)cliffs    r+   r$   LinearFunction._clifford_to_mat   sX     ;;?? 2 2 4 48H8H8J8J]^^||ENN++    c                    [        U R                  5      n[        R                  " X4[        S9n[        U R                  5       H  u  p4SX#U4'   M     U$ )z8This creates a nxn matrix from a given permutation gate.r.   T)r   patternr   zerosr   	enumerate)permr@   rA   ijs        r+   r#   "LinearFunction._permutation_to_mat   sI     hhxt,dll+DAC1I ,
rR   c                |    [        U[        5      (       d  gU R                  UR                  :H  R                  5       $ )z8Check if two linear functions represent the same matrix.F)r   r   r"   all)r'   rE   s     r+   __eq__LinearFunction.__eq__   s.    %00u||+0022rR   c                    U$ )zParameter validation )r'   	parameters     r+   validate_parameter!LinearFunction.validate_parameter   s    rR   c                >    SSK Jn  U" U R                  5      U l        g)z<Populates self.definition with a decomposition of this gate.r   )synth_cnot_count_full_pmhN)r    re   r"   r3   )r'   re   s     r+   _defineLinearFunction._define   s    E3DKK@rR   z2.1z?Call LinearFunction.definition instead, or compile the circuit.zin Qiskit 3.0)sinceadditional_msgremoval_timelinec                    U R                   $ )z|Synthesizes the linear function into a quantum circuit.

Returns:
    QuantumCircuit: A circuit implementing the evolution.
r3   r'   s    r+   
synthesizeLinearFunction.synthesize   s     rR   c                     U R                   S   $ )z;Returns the n x n matrix representing this linear function.r   r   rm   s    r+   r"   LinearFunction.linear   s     {{1~rR   c                     U R                   S   $ )zReturns the original circuit used to construct this linear function
(including None, when the linear function is not constructed from a circuit).
r   rq   rm   s    r+   r)   LinearFunction.original_circuit   s    
 {{1~rR   c                    U R                   n[        R                  " [        R                  " USS9S:H  5      =(       a,    [        R                  " [        R                  " USS9S:H  5      nU$ )zReturns whether this linear function is a permutation,
that is whether every row and every column of the n x n matrix
has exactly one 1.
r   )axisr   )r"   r   r\   sum)r'   r"   rW   s      r+   is_permutationLinearFunction.is_permutation   sP    
 vvbffV!,12ZrvvbffVRS>TXY>Y7ZrR   c                    U R                  5       (       d  [        S5      eU R                  n[        R                  " US:H  5      nUS   $ )zThis method first checks if a linear function is a permutation and raises a
`qiskit.circuit.exceptions.CircuitError` if not. In the case that this linear function
is a permutation, returns the permutation pattern.
z(The linear function is not a permutationr   )rx   r   r"   r   where)r'   r"   locss      r+   permutation_pattern"LinearFunction.permutation_pattern  sC    
 ""$$IJJxx!$AwrR   c                    [         R                  " U[        S9n[        U5       H  u  pEU R                  SS2U4   X2U4'   M     [        U5      $ )aA  Extend linear function to a linear function over nq qubits,
with identities on other subsystems.

Args:
    num_qubits: number of qubits of the extended function.

    positions: describes the positions of original qubits in the extended
        function's qubits.

Returns:
    LinearFunction: extended linear function.
r.   N)r   r4   r   rV   r"   r   )r'   r   rG   extended_matrX   poss         r+   r;   #LinearFunction.extend_with_identity  sK     vvj5	*FA+/;;q!t+<LC( + l++rR   c                R    [        U R                  R                  [        5      5      $ )zYReturn string representation of the linear function
viewed as a matrix with 0/1 entries.
)strr"   r=   r>   rm   s    r+   mat_strLinearFunction.mat_str(  s     4;;%%c*++rR   c                *   SnU R                   n[        U R                  5       Hf  nSn[        U R                  5       H/  nX#U4   (       d  M  U(       d  US-  nUS[        U5      -   -  nSnM1     X0R                  S-
  :w  d  Ma  US-  nMh     US-  nU$ )	zWReturn string representation of the linear function
viewed as a linear transformation.
(Tz + x_Fr   z, z)
)r"   ranger   r   )r'   outrA   rowfirst_entrycols         r+   function_strLinearFunction.function_str.  s     kk)CKT__-Cx==&u4#c(?*C"'K . oo))t * 	u
rR   rl   )F)r"   zblist[list[bool]] | np.ndarray[bool] | QuantumCircuit | LinearFunction | PermutationGate | Cliffordr(   r   returnNone)r?   r   )r   r   )r   r>   rG   z	list[int]r   r   )__name__
__module____qualname____firstlineno____doc__r&   staticmethodr!   r$   r#   r]   rb   rf   r   rn   propertyr"   r)   rx   r}   r;   r   r   __static_attributes____classcell__)r*   s   @r+   r   r      s    )j  %Q
Q
 Q
 
Q
 Q
f # #J , ,  3A X(

    
,(, rR   r   )r   
__future__r   numpyr   qiskit.circuit.quantumcircuitr   r   qiskit.circuit.exceptionsr   4qiskit.circuit.library.generalized_gates.permutationr   qiskit.utils.deprecationr   qiskit.quantum_infor	   r   r`   rR   r+   <module>r      s/     "  > 2 P 3 )eT erR   