U
    	-e                     @   s   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
 Zdd Zdd ZG dd deZdS )    )Add)Tuple)Expr)Mul)Pow)default_sort_key)sympify)Matrixc                 C   s>   t | } t| tr:| js6| js6| js6| js6| jr:| jr:dS dS )z Helper method used in TrTF)	r   
isinstancer   Z
is_IntegerZis_FloatZis_RationalZ	is_NumberZ	is_SymbolZis_commutative)e r   \/var/www/html/Darija-Ai-Train/env/lib/python3.8/site-packages/sympy/physics/quantum/trace.py
_is_scalar   s    
r   c                    s   t | dkr| S t| tdfddt| D  t| |   t |  d    fddtt  d D }|t|} |  | t |   }|S )a5   Cyclic permutations based on canonical ordering

    Explanation
    ===========

    This method does the sort based ascii values while
    a better approach would be to used lexicographic sort.

    TODO: Handle condition such as symbols have subscripts/superscripts
    in case of lexicographic sort

       )keyc                    s   g | ]\}}| kr|qS r   r   ).0ix)min_itemr   r   
<listcomp>,   s      z"_cycle_permute.<locals>.<listcomp>r   c                    s&   g | ]} |  |d    gqS )r   r   )r   r   )indicesler   r   r   7   s     )	lenminr   	enumeratelistextendappendrangeindex)lZsublistidxZ	ordered_lr   )r   r   r   r   _cycle_permute   s    
r"   c                 C   s<   t | dkr| S t| dd }|| dd  t| jS )zk this just moves the last arg to first position
     to enable expansion of args
     A,B,A ==> A**2,B
    r   Nr   )r   r   r   r   args)r    r   r   r   r   _rearrange_argsB   s
    r%   c                   @   sH   e Zd ZdZdd Zedd Zdd Zedd	 Zd
d Z	dd Z
dS )Tra   Generic Trace operation than can trace over:

    a) SymPy matrix
    b) operators
    c) outer products

    Parameters
    ==========
    o : operator, matrix, expr
    i : tuple/list indices (optional)

    Examples
    ========

    # TODO: Need to handle printing

    a) Trace(A+B) = Tr(A) + Tr(B)
    b) Trace(scalar*Operator) = scalar*Trace(Operator)

    >>> from sympy.physics.quantum.trace import Tr
    >>> from sympy import symbols, Matrix
    >>> a, b = symbols('a b', commutative=True)
    >>> A, B = symbols('A B', commutative=False)
    >>> Tr(a*A,[2])
    a*Tr(A)
    >>> m = Matrix([[1,2],[1,1]])
    >>> Tr(m)
    2

    c                    sv  t |dkrDt|d tttfs.t|d  nt|d   |d }n$t |dkr`t  |d }ntdt|trz| S t|drt	|jr| S t|t
rt
 fdd|jD  S t|tr| \}}t |dkrt| S t| t|  }t |dkrt| | S |S n\t|trVt|jd rFt|jd rF|S t| | S nt|rd|S t| | S dS )	z Construct a Trace object.

        Parameters
        ==========
        args = SymPy expression
        indices = tuple/list if indices, optional

           r   r   z5Arguments to Tr should be of form (expr[, [indices]])tracec                    s   g | ]}t | qS r   )r&   )r   argr   r   r   r      s     zTr.__new__.<locals>.<listcomp>N)r   r
   r   r   tuple
ValueErrorr	   r(   hasattrcallabler   r$   r   Zargs_cncr   __new__r   r   )clsr$   exprZc_partZnc_partobjr   r*   r   r/   n   s<    



 
z
Tr.__new__c                 C   s   | j d }|j}|jS )Nr   )r$   kindZelement_kind)selfr1   Z	expr_kindr   r   r   r3      s    
zTr.kindc                 K   s,   t | jd dr(| jd j| jd dS | S )a   Perform the trace operation.

        #TODO: Current version ignores the indices set for partial trace.

        >>> from sympy.physics.quantum.trace import Tr
        >>> from sympy.physics.quantum.operator import OuterProduct
        >>> from sympy.physics.quantum.spin import JzKet, JzBra
        >>> t = Tr(OuterProduct(JzKet(1,1), JzBra(1,1)))
        >>> t.doit()
        1

        r   _eval_tracer   r*   )r-   r$   r5   )r4   hintsr   r   r   doit   s    zTr.doitc                 C   s   dS )NTr   )r4   r   r   r   	is_number   s    zTr.is_numberc                 C   st   |dkr|t | jd j }nt|t | jd j  }t| jd j| d | jd jd|   }tt| S )a   Permute the arguments cyclically.

        Parameters
        ==========

        pos : integer, if positive, shift-right, else shift-left

        Examples
        ========

        >>> from sympy.physics.quantum.trace import Tr
        >>> from sympy import symbols
        >>> A, B, C, D = symbols('A B C D', commutative=False)
        >>> t = Tr(A*B*C*D)
        >>> t.permute(2)
        Tr(C*D*A*B)
        >>> t.permute(-2)
        Tr(C*D*A*B)

        r   N)r   r$   absr   r&   r   )r4   posr$   r   r   r   permute   s
    0z
Tr.permutec                 C   sF   t | jd tr&tt| jd j}n| jd g}t|| jd f S )Nr   r   )r
   r$   r   r"   r%   r+   )r4   r$   r   r   r   _hashable_content   s    zTr._hashable_contentN)__name__
__module____qualname____doc__r/   propertyr3   r7   r8   r;   r<   r   r   r   r   r&   O   s   5

r&   N)Zsympy.core.addr   Zsympy.core.containersr   Zsympy.core.exprr   Zsympy.core.mulr   Zsympy.core.powerr   Zsympy.core.sortingr   Zsympy.core.sympifyr   Zsympy.matricesr	   r   r"   r%   r&   r   r   r   r   <module>   s   (