o
    jg                     @   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s| js| js| js| jr| jrdS dS )z Helper method used in TrTF)	r   
isinstancer   
is_Integeris_Floatis_Rational	is_Number	is_Symbolis_commutative)e r   S/var/www/html/zoom/venv/lib/python3.10/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)lsublistidx	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                    sb  t |dkr"t|d tttfst|d  nt|d   |d }nt |dkr0t  |d }ntdt|tr=| S t|drKt	|jrK| S t|t
r\t
 fdd|jD  S t|tr| \}}t |dkrqt| S t| t|  }t |dkrt| | S |S t|trt|jd rt|jd r|S t| | S t|r|S t| | 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>)r   r
   r!   r   tuple
ValueErrorr	   r0   hasattrcallabler   r,   r   args_cncr   __new__r   r   )clsr,   exprc_partnc_partobjr   r2   r   r8   n   s<   





z
Tr.__new__c                 C   s   | j d }|j}|jS )Nr   )r,   kindelement_kind)selfr:   	expr_kindr   r   r   r>      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   r2   )r5   r,   rB   )r@   hintsr   r   r   doit   s   zTr.doitc                 C   s   dS )NTr   )r@   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   )r@   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-   r3   )r@   r,   r   r   r   _hashable_content   s   zTr._hashable_contentN)__name__
__module____qualname____doc__r8   propertyr>   rD   rE   rH   rI   r   r   r   r   r.   O   s    5

r.   N)sympy.core.addr   sympy.core.containersr   sympy.core.exprr   sympy.core.mulr   sympy.core.powerr   sympy.core.sortingr   sympy.core.sympifyr   sympy.matricesr	   r   r*   r-   r.   r   r   r   r   <module>   s    (