ó
¡¼™\c           @  s  d  d l  m Z m Z d  d l m Z d  d l m Z m Z m Z m	 Z	 m
 Z
 m Z 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 e f d „  ƒ  YZ d „  Z d „  Z  d S(   iÿÿÿÿ(   t   print_functiont   division(   t   product(   t   Tuplet   Addt   Mult   Matrixt   logt   expandt   Rational(   t   Tr(   t
   prettyForm(   t   Dagger(   t   HermitianOperator(   t	   represent(   t   numpy_ndarrayt   scipy_sparse_matrixt   to_numpy(   t   TensorProductt   tensor_product_simpt   Densityc           B  s‰   e  Z d  Z e 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 RS(   s  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         C  s]   t  t |  ƒ j | ƒ } x> | D]6 } t | t ƒ oC t | ƒ d k s t d ƒ ‚ q q W| S(   Ni   s?   Each argument should be of form [state,prob] or ( state, prob )(   t   superR   t
   _eval_argst
   isinstanceR   t   lent
   ValueError(   t   clst   argst   arg(    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyR   '   s    c         C  s$   t  g  |  j D] } | d ^ q Œ  S(   s  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>)

        i    (   R   R   (   t   selfR   (    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt   states5   s    c         C  s$   t  g  |  j D] } | d ^ q Œ  S(   s#  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)

        i   (   R   R   (   R   R   (    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt   probsD   s    c         C  s   |  j  | d } | S(   st  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>

        i    (   R   (   R   t   indext   state(    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt	   get_stateS   s    c         C  s   |  j  | d } | S(   s¢  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

        i   (   R   (   R   R    t   prob(    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt   get_probh   s    c         C  s6   g  |  j  D] \ } } | | | f ^ q
 } t | Œ  S(   så  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))

        (   R   R   (   R   t   opR!   R#   t   new_args(    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt   apply_op}   s    ,c         K  sª   g  } x— |  j  D]Œ \ } } | j ƒ  } t | t ƒ r xb t | j  d d ƒD]+ } | j | |  j | d | d ƒ ƒ qM Wq | j | |  j | | ƒ ƒ q Wt | Œ  S(   s¥  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|

        t   repeati   i    i   (   R   R   R   R   R   t   appendt   _generate_outer_prod(   R   t   hintst   termsR!   R#   R   (    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt   doit”   s    	#	c         C  sã   | j  ƒ  \ } } | j  ƒ  \ } } t | ƒ d k sH t | ƒ d k rW t d ƒ ‚ n  t | d t ƒ r¯ t | ƒ d k r¯ t | ƒ d k r¯ t | d t | d ƒ ƒ } n t | Œ  t t | Œ  ƒ } t | Œ  t | Œ  | S(   Ni    sH   Atleast one-pair of Non-commutative instance required for outer product.i   (   t   args_cncR   R   R   R   R   R   R   (   R   t   arg1t   arg2t   c_part1t   nc_part1t   c_part2t   nc_part2R%   (    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyR*   ±   s    $!c         K  s   t  |  j ƒ  |  S(   N(   R   R-   (   R   t   options(    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt
   _representÅ   s    c         G  s   | j  d | Œ S(   Ns   \rho(   t   _print(   R   t   printerR   (    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt   _print_operator_name_latexÈ   s    c         G  s   t  t d ƒ ƒ S(   Ns   \N{GREEK SMALL LETTER RHO}(   R   t   unichr(   R   R8   R   (    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt   _print_operator_name_prettyË   s    c         K  s+   | j  d g  ƒ } t |  j ƒ  | ƒ j ƒ  S(   Nt   indices(   t   getR
   R-   (   R   t   kwargsR<   (    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt   _eval_traceÎ   s    c         C  s
   t  |  ƒ S(   sl    Compute the entropy of a density matrix.

        Refer to density.entropy() method  for examples.
        (   t   entropy(   R   (    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyR@   Ò   s    (   t   __name__t
   __module__t   __doc__t   classmethodR   R   R   R"   R$   R'   R-   R*   R6   R9   R;   R?   R@   (    (    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyR      s   											c         C  sÐ   t  |  t ƒ r t |  ƒ }  n  t  |  t ƒ r< t |  ƒ }  n  t  |  t ƒ rx |  j ƒ  j ƒ  } t t	 d „  | Dƒ ƒ ƒ St  |  t
 ƒ rÀ d d l } | j j |  ƒ } | j	 | | j | ƒ ƒ St d ƒ ‚ d S(   sT  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.represent import represent
    >>> from sympy.physics.quantum.matrixutils import scipy_sparse_matrix
    >>> from sympy.physics.quantum.spin import JzKet, Jz
    >>> from sympy import S, log
    >>> 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         s  s   |  ] } | t  | ƒ Vq d  S(   N(   R   (   t   .0t   e(    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pys	   <genexpr>þ   s    iÿÿÿÿNs4   numpy.ndarray, scipy.sparse or sympy matrix expected(   R   R   R   R   R   R   t	   eigenvalst   keysR   t   sumR   t   numpyt   linalgt   eigvalsR   R   (   t   densityRL   t   np(    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyR@   Ú   s    c         C  sé   t  |  t ƒ r t |  ƒ n |  }  t  | t ƒ r< t | ƒ n | } t  |  t ƒ sb t  | t ƒ r‡ t d t |  ƒ t | ƒ f ƒ ‚ n  |  j | j k r± |  j r± t d ƒ ‚ n  |  t d d ƒ } t	 | | | t d d ƒ ƒ j
 ƒ  S(   s»   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 Density, 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

    sf   state1 and state2 must be of type Density or Matrix received type=%s for state1 and type=%s for state2s]   The dimensions of both args should be equal and the matrix obtained should be a square matrixi   i   (   R   R   R   R   R   t   typet   shapet	   is_squareR	   R
   R-   (   t   state1t   state2t   sqrt_state1(    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt   fidelity  s    ,!!N(!   t
   __future__R    R   t	   itertoolsR   t   sympyR   R   R   R   R   R   R	   t   sympy.core.traceR
   t    sympy.printing.pretty.stringpictR   t   sympy.physics.quantum.daggerR   t   sympy.physics.quantum.operatorR   t   sympy.physics.quantum.representR   t!   sympy.physics.quantum.matrixutilsR   R   R   t#   sympy.physics.quantum.tensorproductR   R   R   R@   RU   (    (    (    s<   lib/python2.7/site-packages/sympy/physics/quantum/density.pyt   <module>   s   4Ë	.