U
    ZÊ¹jý  ã                   @   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   úZ/var/www/html/bwave/python/venv/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ƒr–t	|jƒr–| ¡ S t|t
ƒr¸t
‡ fdd„|jD ƒŽ S t|tƒ�r| ¡ \}}t |ƒdkrät|Ž 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   (