
    Ed&                         d dl mZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZmZmZ d dlmZmZ d dl m!Z!  G d de          Z"d Z#d Z$dS )    )product)Add)Tuple)expand)Mul)Slog)MutableDenseMatrix
prettyForm)Dagger)HermitianOperator)	represent)numpy_ndarrayscipy_sparse_matrixto_numpy)TensorProducttensor_product_simp)Trc                   z     e Zd ZdZe fd            Zd Zd Zd Zd Z	d Z
d Zd	 Zd
 Zd Zd Zd Zd Z xZS )Densitya  Density operator for representing mixed states.

    TODO: Density operator support for Qubits

    Parameters
    ==========

    values : tuples/lists
    Each tuple/list should be of form (state, prob) or [state,prob]

    Examples
    ========

    Create a density operator with 2 states represented by Kets.

    >>> from sympy.physics.quantum.state import Ket
    >>> from sympy.physics.quantum.density import Density
    >>> d = Density([Ket(0), 0.5], [Ket(1),0.5])
    >>> d
    Density((|0>, 0.5),(|1>, 0.5))

    c                     t                                          |          }|D ]9}t          |t                    rt	          |          dk    st          d          :|S )N   z?Each argument should be of form [state,prob] or ( state, prob ))super
_eval_args
isinstancer   len
ValueError)clsargsarg	__class__s      =lib/python3.11/site-packages/sympy/physics/quantum/density.pyr   zDensity._eval_args*   sq     ww!!$'' 	8 	8CsE** 8s3xx1} 8  "7 8 8 88     c                 2    t          d | j        D              S )a  Return list of all states.

        Examples
        ========

        >>> from sympy.physics.quantum.state import Ket
        >>> from sympy.physics.quantum.density import Density
        >>> d = Density([Ket(0), 0.5], [Ket(1),0.5])
        >>> d.states()
        (|0>, |1>)

        c                     g | ]
}|d          S )r    .0r"   s     r$   
<listcomp>z"Density.states.<locals>.<listcomp>D       333#s1v333r%   r   r!   selfs    r$   stateszDensity.states7         3333344r%   c                 2    t          d | j        D              S )a#  Return list of all probabilities.

        Examples
        ========

        >>> from sympy.physics.quantum.state import Ket
        >>> from sympy.physics.quantum.density import Density
        >>> d = Density([Ket(0), 0.5], [Ket(1),0.5])
        >>> d.probs()
        (0.5, 0.5)

        c                     g | ]
}|d          S )   r(   r)   s     r$   r+   z!Density.probs.<locals>.<listcomp>S   r,   r%   r-   r.   s    r$   probszDensity.probsF   r1   r%   c                 ,    | j         |         d         }|S )at  Return specific state by index.

        Parameters
        ==========

        index : index of state to be returned

        Examples
        ========

        >>> from sympy.physics.quantum.state import Ket
        >>> from sympy.physics.quantum.density import Density
        >>> d = Density([Ket(0), 0.5], [Ket(1),0.5])
        >>> d.states()[1]
        |1>

        r   r!   )r/   indexstates      r$   	get_statezDensity.get_stateU   s    $ 	% #r%   c                 ,    | j         |         d         }|S )a  Return probability of specific state by index.

        Parameters
        ===========

        index : index of states whose probability is returned.

        Examples
        ========

        >>> from sympy.physics.quantum.state import Ket
        >>> from sympy.physics.quantum.density import Density
        >>> d = Density([Ket(0), 0.5], [Ket(1),0.5])
        >>> d.probs()[1]
        0.500000000000000

        r4   r7   )r/   r8   probs      r$   get_probzDensity.get_probj   s    $ y"r%   c                 <    fd| j         D             }t          | S )a  op will operate on each individual state.

        Parameters
        ==========

        op : Operator

        Examples
        ========

        >>> from sympy.physics.quantum.state import Ket
        >>> from sympy.physics.quantum.density import Density
        >>> from sympy.physics.quantum.operator import Operator
        >>> A = Operator('A')
        >>> d = Density([Ket(0), 0.5], [Ket(1),0.5])
        >>> d.apply_op(A)
        Density((A*|0>, 0.5),(A*|1>, 0.5))

        c                 $    g | ]\  }}|z  |fS r(   r(   )r*   r9   r<   ops      r$   r+   z$Density.apply_op.<locals>.<listcomp>   s&    DDD%RXt$DDDr%   )r!   r   )r/   r@   new_argss    ` r$   apply_opzDensity.apply_op   s,    ( EDDD$)DDD!!r%   c           
         g }| j         D ]\  }}|                                }t          |t                    rRt	          |j         d          D ]:}|                    ||                     |d         |d                   z             ;|                    ||                     ||          z             t          | S )a  Expand the density operator into an outer product format.

        Examples
        ========

        >>> from sympy.physics.quantum.state import Ket
        >>> from sympy.physics.quantum.density import Density
        >>> from sympy.physics.quantum.operator import Operator
        >>> A = Operator('A')
        >>> d = Density([Ket(0), 0.5], [Ket(1),0.5])
        >>> d.doit()
        0.5*|0><0| + 0.5*|1><1|

        r   )repeatr   r4   )r!   r   r   r   r   append_generate_outer_prod)r/   hintstermsr9   r<   r"   s         r$   doitzDensity.doit   s      !Y 	K 	KMUDLLNNE5#&& K"5:a888 I ICLLd&?&?A@CA'H 'H "H I I I II T$";";E5"I"IIJJJJE{r%   c                    |                                 \  }}|                                 \  }}t          |          dk    st          |          dk    rt          d          t          |d         t                    rRt          |          dk    r?t          |          dk    r,t          |d         t          |d                   z            }n t          | t          t          |           z  }t          | t          | z  |z  S )Nr   zHAtleast one-pair of Non-commutative instance required for outer product.r4   )args_cncr   r   r   r   r   r   r   )r/   arg1arg2c_part1nc_part1c_part2nc_part2r@   s           r$   rF   zDensity._generate_outer_prod   s     MMOO MMOOMMQ 	4#h--1"4 	4 3 4 4 4 x{M22 	7s8}}7I 	7MMQ&	7$Xa[1D1D%DEEBBhsH~ 6 66BG}S']*R//r%   c                 @    t          |                                 fi |S N)r   rI   )r/   optionss     r$   
_representzDensity._represent   s     00000r%   c                     dS )Nz\rhor(   r/   printerr!   s      r$   _print_operator_name_latexz"Density._print_operator_name_latex   s    wr%   c                      t          d          S )Nu   ρr   rW   s      r$   _print_operator_name_prettyz#Density._print_operator_name_pretty   s    6777r%   c                     |                     dg           }t          |                                 |                                          S )Nindices)getr   rI   )r/   kwargsr]   s      r$   _eval_tracezDensity._eval_trace   s9    **Y++$))++w'',,...r%   c                      t          |           S )zl Compute the entropy of a density matrix.

        Refer to density.entropy() method  for examples.
        )entropyr.   s    r$   rb   zDensity.entropy   s    
 t}}r%   )__name__
__module____qualname____doc__classmethodr   r0   r5   r:   r=   rB   rI   rF   rU   rY   r[   r`   rb   __classcell__)r#   s   @r$   r   r      s        , 
 
 
 
 [
5 5 55 5 5  *  *" " ".  80 0 0&1 1 1  8 8 8/ / /      r%   r   c                 2   t          | t                    rt          |           } t          | t                    rt	          |           } t          | t
                    rM|                                                                 }t          t          d |D                                  S t          | t                    rJddl}|j                            |           }|	                    ||                    |          z             S t          d          )a  Compute the entropy of a matrix/density object.

    This computes -Tr(density*ln(density)) using the eigenvalue decomposition
    of density, which is given as either a Density instance or a matrix
    (numpy.ndarray, sympy.Matrix or scipy.sparse).

    Parameters
    ==========

    density : density matrix of type Density, SymPy matrix,
    scipy.sparse or numpy.ndarray

    Examples
    ========

    >>> from sympy.physics.quantum.density import Density, entropy
    >>> from sympy.physics.quantum.spin import JzKet
    >>> from sympy import S
    >>> up = JzKet(S(1)/2,S(1)/2)
    >>> down = JzKet(S(1)/2,-S(1)/2)
    >>> d = Density((up,S(1)/2),(down,S(1)/2))
    >>> entropy(d)
    log(2)/2

    c              3   :   K   | ]}|t          |          z  V  d S rS   r	   )r*   es     r$   	<genexpr>zentropy.<locals>.<genexpr>   s,      551SVV8555555r%   r   Nz4numpy.ndarray, scipy.sparse or SymPy matrix expected)r   r   r   r   r   Matrix	eigenvalskeysr   sumr   numpylinalgeigvalsr
   r   )densityrs   nps      r$   rb   rb      s   4 '7## %G$$'.// $7##'6"" 	D##%%**,,s55W555555666	G]	+	+ D)##G,,wrvvg.////BD D 	Dr%   c                     t          | t                    rt          |           n| } t          |t                    rt          |          n|}t          | t                    rt          |t                    s0t	          dt          |           dt          |          d          | j        |j        k    r| j        rt	          d          | t          j	        z  }t          ||z  |z  t          j	        z                                            S )a   Computes the fidelity [1]_ between two quantum states

    The arguments provided to this function should be a square matrix or a
    Density object. If it is a square matrix, it is assumed to be diagonalizable.

    Parameters
    ==========

    state1, state2 : a density matrix or Matrix


    Examples
    ========

    >>> from sympy import S, sqrt
    >>> from sympy.physics.quantum.dagger import Dagger
    >>> from sympy.physics.quantum.spin import JzKet
    >>> from sympy.physics.quantum.density import fidelity
    >>> from sympy.physics.quantum.represent import represent
    >>>
    >>> up = JzKet(S(1)/2,S(1)/2)
    >>> down = JzKet(S(1)/2,-S(1)/2)
    >>> amp = 1/sqrt(2)
    >>> updown = (amp*up) + (amp*down)
    >>>
    >>> # represent turns Kets into matrices
    >>> up_dm = represent(up*Dagger(up))
    >>> down_dm = represent(down*Dagger(down))
    >>> updown_dm = represent(updown*Dagger(updown))
    >>>
    >>> fidelity(up_dm, up_dm)
    1
    >>> fidelity(up_dm, down_dm) #orthogonal states
    0
    >>> fidelity(up_dm, updown_dm).evalf().round(3)
    0.707

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Fidelity_of_quantum_states

    zBstate1 and state2 must be of type Density or Matrix received type=z for state1 and type=z for state2z]The dimensions of both args should be equal and the matrix obtained should be a square matrix)r   r   r   rm   r   typeshape	is_squarer   Halfr   rI   )state1state2sqrt_state1s      r$   fidelityr~     s   X #-VW"="=IYv6F",VW"="=IYv6Fff%% 7Z-G-G 7jv,,,,V6 7 7 	7 |v|# F(8 F E F F 	F !&.K{6!+-677<<>>>r%   N)%	itertoolsr   sympy.core.addr   sympy.core.containersr   sympy.core.functionr   sympy.core.mulr   sympy.core.singletonr   &sympy.functions.elementary.exponentialr
   sympy.matrices.denser   rm    sympy.printing.pretty.stringpictr   sympy.physics.quantum.daggerr   sympy.physics.quantum.operatorr   sympy.physics.quantum.representr   !sympy.physics.quantum.matrixutilsr   r   r   #sympy.physics.quantum.tensorproductr   r   sympy.physics.quantum.tracer   r   rb   r~   r(   r%   r$   <module>r      s               ' ' ' ' ' ' & & & & & &       " " " " " " 6 6 6 6 6 6 = = = = = = 7 7 7 7 7 7 / / / / / / < < < < < < 5 5 5 5 5 5 Z Z Z Z Z Z Z Z Z Z R R R R R R R R * * * * * *D D D D D D D DN)D )D )DX9? 9? 9? 9? 9?r%   