
    z	i6"                        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	 jrSSS
 jjrS rSS jrS rg)z3
Quantum information utility functions for states.
    )annotationsN)QiskitError)Statevector)DensityMatrix)SuperOp)ATOL_DEFAULTc                B   [        U SS9n U R                  R                  US9nUR                  Ul        UR
                  Ul        UR                  S:X  a  U R                  5       $ [        U [        5      (       a  [        U R                  R                  5       5      S-
  [        R                  " U5      -
  nU R                  R!                  U R                  R"                  5      n[        R$                  " XDR'                  5       X34S9n[        R                   " XRR(                  5      n[+        XRR                  S9$ U(       d  U R-                  5       $ U R/                  U5      n[1        [        R2                  " US   5      R!                  SUS   S-  5      US   /S/S	9nU R5                  XqS   /5      n[7        USS
 USS
 5       HK  u  p[1        [        R2                  " U
5      R!                  SU
S-  5      U
/S/S	9nUR5                  Xy/5      nMM     X(l        U$ )a  Return reduced density matrix by tracing out part of quantum state.

If all subsystems are traced over this returns the
:meth:`~qiskit.quantum_info.DensityMatrix.trace` of the
input state.

Args:
    state (Statevector or DensityMatrix): the input state.
    qargs (list): The subsystems to trace over.

Returns:
    DensityMatrix: The reduced density matrix.

Raises:
    QiskitError: if input state is invalid.
Fvalidate)qargsr      )axesdims   )
input_dimsoutput_dimsN)_format_state	_op_shaperemove_dims_l_dims_r_num_qargs_l_num_qargs_rsizetrace
isinstancer   lendims_lnparray_datareshapetensor_shape	tensordotconjshaper   copyr   r   eyeevolvezip)stater   traced_shapetrace_systemsarrrhor   tr_opretqargdims              Z/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/quantum_info/states/utils.pypartial_tracer6      s   " %%0E ??)))6L'//L , 9 9L A{{} %%%EOO22459BHHUOKkk!!%//">">?ll3
-1OPjj001S';';<< zz|::eDBFF47O++AtAw!|<$q'ab`cdE
,,uQxj
)CqrDH-	s++AsAv6C5WXVYZjj' . !MJ    c                   ^ US:X  a  S nO4U[         R                  :X  a  S nO[        R                  " U5      mU4S jnSnU  H   nSUs=:  a  S:  d  M  O  M  X2" U5      -  nM"     U$ )a  Compute the Shannon entropy of a probability vector.

The shannon entropy of a probability vector
:math:`\vec{p} = [p_0, ..., p_{n-1}]` is defined as

.. math::

    H(\vec{p}) = \sum_{i=0}^{n-1} p_i \log_b(p_i)

where :math:`b` is the log base and (default 2), and
:math:`0 \log_b(0) \equiv 0`.

Args:
    pvec (array_like): a probability vector.
    base (int): the base of the logarithm [Default: 2].

Returns:
    float: The Shannon entropy H(pvec).
r   c                6    U * [         R                  " U 5      -  $ N)mathlog2xs    r5   logfnshannon_entropy.<locals>.logfni   s    2		!$$r7   c                6    U * [         R                  " U 5      -  $ r:   r;   logr=   s    r5   r?   r@   n   s    2##r7   c                >   > U * [         R                  " U 5      -  T-  $ r:   rB   )r>   log_bases    r5   r?   r@   t   s    2#h..r7   g        r   r   )r    er;   rC   )pvecbaser?   h_valr>   rE   s        @r5   shannon_entropyrJ   S   sj    ( qy	% 
	$ 88D>	/ Eq9199U1XE  Lr7   c                f   [        U SS9n [        U [        5      (       a  U R                  5       n U R	                  5       nU R
                  R                  USSS2   5      nUR                  n[        [        U5      5      n[        U[        [        R                  45      (       d  [        S5      e[        U5      nU[        U5      :X  d  UR                  U5      (       d  [        S5      e[        U5      nU Vs/ s H  owU;  d  M
  UPM     nnU R	                  U5      n	U R	                  U5      n
[        R                  " U	5      n[        R                  " U
5      nXh-    Vs/ s H  ouSSS2   R!                  U5      PM     snSSS2   nUR#                  U5      nUR                  X/5      n[        R$                  R'                  USS9u  nnn[)        UUR*                  U5       VVVs/ s H(  u  nnnU[,        :  d  M  U[/        UU
S9[/        UU	S94PM*     nnnnU$ s  snf s  snf s  snnnf )	a  Return the Schmidt Decomposition of a pure quantum state.

For an arbitrary bipartite state:

.. math::
     |\psi\rangle_{AB} = \sum_{i,j} c_{ij}
                         |x_i\rangle_A \otimes |y_j\rangle_B,

its Schmidt Decomposition is given by the single-index sum over k:

.. math::
    |\psi\rangle_{AB} = \sum_{k} \lambda_{k}
                        |u_k\rangle_A \otimes |v_k\rangle_B

where :math:`|u_k\rangle_A` and :math:`|v_k\rangle_B` are an
orthonormal set of vectors in their respective spaces :math:`A` and :math:`B`,
and the Schmidt coefficients :math:`\lambda_k` are positive real values.

Args:
    state (Statevector or DensityMatrix): the input state.
    qargs (list): the list of Input state positions corresponding to subsystem :math:`B`.

Returns:
    list: list of tuples ``(s, u, v)``, where ``s`` (float) are the Schmidt coefficients
    :math:`\lambda_k`, and ``u`` (Statevector), ``v`` (Statevector) are the Schmidt vectors
    :math:`|u_k\rangle_A`, :math:`|u_k\rangle_B`, respectively.

Raises:
    QiskitError: if Input qargs is not a list of positions of the Input state.
    QiskitError: if Input qargs is not a proper subset of Input state.

.. note::
    In Qiskit, qubits are ordered using little-endian notation, with the least significant
    qubits having smaller indices. For example, a four-qubit system is represented as
    :math:`|q_3q_2q_1q_0\rangle`. Using this convention, setting ``qargs=[0]`` will partition the
    state as :math:`|q_3q_2q_1\rangle_A\otimes|q_0\rangle_B`. Furthermore, qubits will be organized
    in this notation regardless of the order they are passed. For instance, passing either
    ``qargs=[1,2]`` or ``qargs=[2,1]`` will result in partitioning the state as
    :math:`|q_3q_0\rangle_A\otimes|q_2q_1\rangle_B`.
Fr
   Nz9Input qargs is not a list of positions of the Input statez1Input qargs is not a proper subset of Input state)full_matricesr   )r   r   r   to_statevectorr   r"   r#   ndimlistranger    ndarrayr   setissubsetprodindex	transposelinalgsvdr+   Tr   r   )r,   r   r   
state_tensrO   quditsqargs_biqargs_adims_bdims_andim_bndim_a
qargs_axes	state_matu_mats_arrvh_matsuvschmidt_componentss                         r5   schmidt_decompositionrm   ~   s   R %%0E %''$$& ::<D$$T$B$Z0J??D%+F edBJJ/00UVVJEF5>>&#9#9MNN 5kG 5&QW$4q&G5ZZ FZZ FWWV_FWWV_F 291BC1BA2,$$Q'1BCDbDIJ%%j1J ""F#34I99==%=HE5& 5%''622GAq!| 	FK'QV)DE2   ) 6 Ds   ;	H"H"$ H'-H,H,c                   [        U [        5      (       a  [        R                  " U [        S9n [        U [        R
                  5      (       aT  U R                  nUS:X  a  [        U 5      n O6US:X  a0  U R                  u  p4US:X  a  [        U 5      n OX4:X  a  [        U 5      n [        U [        [        45      (       d  [        S5      eU(       a   U R                  5       (       d  [        S5      eU $ )z$Format input state into class object)dtyper   r   zInput is not a quantum statez"Input quantum state is not a valid)r   rP   r    r!   complexrR   rO   r   r'   r   r   is_valid)r,   r   rO   dim1dim2s        r5   r   r      s    %g.%$$zz19&EQYJDqy#E*%e,ek=9::899((>??Lr7   c                    SSK Jn  UR                  U 5      u  p4n[        R                  " U" U5      5      nUR                  U5      R                  U5      $ )aF  Apply real scalar function to singular values of a matrix.

Args:
    matrix (array_like): (N, N) Matrix at which to evaluate the function.
    func (callable): Callable object that evaluates a scalar function f.

Returns:
    ndarray: funm (N, N) Value of the matrix function specified by func
             evaluated at `A`.
r   N)scipy.linalgrX   rY   r    diagdot)matrixfunclaunitary1singular_valuesunitary2diag_func_singulars          r5   	_funm_svdr      sH     *,&&.'Hxo!67<<*+//99r7   )r,   zStatevector | DensityMatrixr   rP   returnr   )r   )rG   zlist | np.ndarrayrH   intr   float)T)__doc__
__future__r   r;   numpyr    qiskit.exceptionsr   &qiskit.quantum_info.states.statevectorr   (qiskit.quantum_info.states.densitymatrixr   %qiskit.quantum_info.operators.channelr   (qiskit.quantum_info.operators.predicatesr   r6   rJ   rm   r   r    r7   r5   <module>r      sA    #   ) > B 9 A3l(VRj*:r7   