U
    ZÊ¹jˆ"  ã                   @   sh   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mZ G dd„ deƒZd	S )
é    )Úpermutedims)ÚNumber)ÚS)ÚSymbol)Úsympify)ÚTensorÚTensExprÚTensAddÚTensMulc                   @   sŒ   e Zd ZdZdd„ Zedd„ ƒZedd„ ƒZedd	„ ƒZ	d
d„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zedd„ ƒZedd„ ƒZdd„ ZdS )ÚPartialDerivativea…
  
    Partial derivative for tensor expressions.

    Examples
    ========

    >>> from sympy.tensor.tensor import TensorIndexType, TensorHead
    >>> from sympy.tensor.toperators import PartialDerivative
    >>> from sympy import symbols
    >>> L = TensorIndexType("L")
    >>> A = TensorHead("A", [L])
    >>> B = TensorHead("B", [L])
    >>> i, j, k = symbols("i j k")

    >>> expr = PartialDerivative(A(i), A(j))
    >>> expr
    PartialDerivative(A(i), A(j))

    The ``PartialDerivative`` object behaves like a tensorial expression:

    >>> expr.get_indices()
    [i, -j]

    Notice that the deriving variables have opposite valence than the
    printed one: ``A(j)`` is printed as covariant, but the index of the
    derivative is actually contravariant, i.e. ``-j``.

    Indices can be contracted:

    >>> expr = PartialDerivative(A(i), A(i))
    >>> expr
    PartialDerivative(A(L_0), A(L_0))
    >>> expr.get_indices()
    [L_0, -L_0]

    The method ``.get_indices()`` always returns all indices (even the
    contracted ones). If only uncontracted indices are needed, call
    ``.get_free_indices()``:

    >>> expr.get_free_indices()
    []

    Nested partial derivatives are flattened:

    >>> expr = PartialDerivative(PartialDerivative(A(i), A(j)), A(k))
    >>> expr
    PartialDerivative(A(i), A(j), A(k))
    >>> expr.get_indices()
    [i, -j, -k]

    Replace a derivative with array values:

    >>> from sympy.abc import x, y
    >>> from sympy import sin, log
    >>> compA = [sin(x), log(x)*y**3]
    >>> compB = [x, y]
    >>> expr = PartialDerivative(A(i), B(j))
    >>> expr.replace_with_arrays({A(i): compA, B(i): compB})
    [[cos(x), 0], [y**3/x, 3*y**2*log(x)]]

    The returned array is indexed by `(i, -j)`.

    Be careful that other SymPy modules put the indices of the deriving
    variables before the indices of the derivand in the derivative result.
    For example:

    >>> expr.get_free_indices()
    [i, -j]

    >>> from sympy import Matrix, Array
    >>> Matrix(compA).diff(Matrix(compB)).reshape(2, 2)
    [[cos(x), y**3/x], [0, 3*y**2*log(x)]]
    >>> Array(compA).diff(Array(compB))
    [[cos(x), y**3/x], [0, 3*y**2*log(x)]]

    These are the transpose of the result of ``PartialDerivative``,
    as the matrix and the array modules put the index `-j` before `i` in the
    derivative result. An array read with index order `(-j, i)` is indeed the
    transpose of the same array read with index order `(i, -j)`. By specifying
    the index order to ``.replace_with_arrays`` one can get a compatible
    expression:

    >>> expr.replace_with_arrays({A(i): compA, B(i): compB}, [-j, i])
    [[cos(x), y**3/x], [0, 3*y**2*log(x)]]
    c                 G   sX   t |tƒr|j| }|j}|  t|ƒ|¡\}}}}tj| f|žŽ }||_||_	||_
|S ©N)Ú
isinstancer   Ú	variablesÚexprÚ _contract_indices_for_derivativer   r   Ú__new__Ú_indicesÚ_freeÚ_dum)Úclsr   r   ÚargsÚindicesÚfreeÚdumÚobj© r   úV/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/tensor/toperators.pyr   `   s    

 ÿzPartialDerivative.__new__c                 C   s   t jS r   )r   ZOne©Úselfr   r   r   Úcoeffq   s    zPartialDerivative.coeffc                 C   s   | S r   r   r   r   r   r   Únocoeffu   s    zPartialDerivative.nocoeffc                 C   sÆ   g }|D ]F}t |tƒr:| ¡ }| | dd„ |D ƒ¡¡ qt |tƒr| |¡ qtj|g| dd�\}}}}	tdt	|ƒƒD ]>}|| }
t |
tƒrz||  ¡ }||  dd„ |D ƒ¡||< qz||||	fS )Nc                 S   s   i | ]}|| “qS r   r   ©Ú.0Úkr   r   r   Ú
<dictcomp>�   s      zFPartialDerivative._contract_indices_for_derivative.<locals>.<dictcomp>T)Zreplace_indicesé   c                 S   s   i | ]}|| “qS r   r   r!   r   r   r   r$   Œ   s      )
r   r   Úget_free_indicesÚappendÚxreplacer   r
   Z_tensMul_contract_indicesÚrangeÚlen)r   r   r   Zvariables_opposite_valenceÚiZi_free_indicesr   r   r   r   Zargs_iZ	i_indicesr   r   r   r   y   s&    
ÿ
 ÿ
z2PartialDerivative._contract_indices_for_derivativec                 K   s8   |   | j| j¡\}}}}| j|Ž }||_||_||_|S r   )r   r   r   Úfuncr   r   r   )r   Úhintsr   r   r   r   r   r   r   r   Údoit�   s    
zPartialDerivative.doitc                    sB  ˆ  ˆjˆj¡\}}}}ˆj|Ž ‰ |ˆ _|ˆ _|ˆ _ˆ }|d jsHtj	S t
ˆ jtƒrvˆ jj‡ ‡fdd„|jjD ƒŽ }nÈt
ˆ jtƒ�r>tˆ jƒdk�rg }tˆ jjƒ}tt|ƒƒD ]\}t
t|| ƒtƒs°ˆj|| fˆ jžŽ  ¡ }	| t|d |… |	g ||d d …  Ž ¡ q°t |¡}n$ˆ j}ˆ jD ]}
ˆ ||
¡ ¡ }�q&|S )Nr   c                    s"   g | ]}ˆj |fˆ jžŽ  ¡ ‘qS r   )r,   r   Ú_expand_partial_derivative)r"   Úa©r   r   r   r   Ú
<listcomp>¨   s   ÿz@PartialDerivative._expand_partial_derivative.<locals>.<listcomp>r%   )r   r   r   r,   r   r   r   Zfree_symbolsr   ÚZeror   r	   r   r
   r*   Úlistr)   r   r   r/   r'   Zfromiter)r   r   r   r   r   ÚresultZtermsZmulargsÚindÚdÚvr   r1   r   r/   š   s:    

þ
ÿþ

z,PartialDerivative._expand_partial_derivativec                 C   sD   | j }| jD ]2}t|tƒr&| |¡}q|jr8| |¡}qtj}q|S r   )	r   r   r   r   Z_eval_partial_derivativeZ	_diff_wrtZ_eval_derivativer   r3   )r   r5   r8   r   r   r   Ú_perform_derivativeÆ   s    

z%PartialDerivative._perform_derivativec                 C   s   | j S r   )r   r   r   r   r   Úget_indicesÒ   s    zPartialDerivative.get_indicesc                 C   s    t | jdd„ d�}dd„ |D ƒS )Nc                 S   s   | d S ©Nr%   r   )Úxr   r   r   Ú<lambda>Ö   ó    z4PartialDerivative.get_free_indices.<locals>.<lambda>)Úkeyc                 S   s   g | ]}|d  ‘qS )r   r   ©r"   r+   r   r   r   r2   ×   s     z6PartialDerivative.get_free_indices.<locals>.<listcomp>)Úsortedr   )r   r   r   r   r   r&   Õ   s    z"PartialDerivative.get_free_indicesc                    sB   | j  |¡}dd„ | ¡ D ƒ‰ ‡ fdd„| jD ƒ}| j|f|žŽ S )Nc                 S   s   i | ]\}}| | “qS r   r   )r"   r#   r8   r   r   r   r$   Û   s      z6PartialDerivative._replace_indices.<locals>.<dictcomp>c                    s   g | ]}|  ˆ ¡‘qS r   )r(   r@   ©Úmirroredr   r   r2   Ü   s     z6PartialDerivative._replace_indices.<locals>.<listcomp>)r   r(   Úitemsr   r,   )r   Úreplr   r   r   rB   r   Ú_replace_indicesÙ   s    z"PartialDerivative._replace_indicesc                 C   s
   | j d S )Nr   ©r   r   r   r   r   r   ß   s    zPartialDerivative.exprc                 C   s   | j dd … S r;   rG   r   r   r   r   r   ã   s    zPartialDerivative.variablesc                    sP  ddl m}m} | j |¡\}}| jD �]}| |¡\}}dd„ |D ƒ}tdd„ |D ƒŽ \}	}t|jƒ}
|||ƒ}t|jƒ}||
 ‰ t	|‡ fdd„t
|
ƒD ƒtt
ˆ ƒƒ ƒ}| ¡ }|d }dgdd„ t
t|ƒƒD ƒ }t|	ƒD ]$\}}||d< |t|ƒ  |  < qà| |k�r<| | ¡}||d|d fƒ}| |¡ q&| |¡ q&||fS )	Nr%   )Úderive_by_arrayÚtensorcontractionc                 S   s   g | ]
}| ‘qS r   r   r@   r   r   r   r2   ì   s     z3PartialDerivative._extract_data.<locals>.<listcomp>c                 S   s   g | ]}|  ¡ ‘qS r   )Zas_coeff_Mulr@   r   r   r   r2   í   s     c                    s   g | ]}|ˆ  ‘qS r   r   r@   ©Zdim_increaser   r   r2   ò   s     r   c                 S   s   g | ]}t d ƒ‘qS r   )Úslicer@   r   r   r   r2   ö   s     )ÚarrayrH   rI   r   Ú_extract_datar   Úzipr*   Úshaper   r)   r4   Z
as_mutableÚ	enumerateÚtupleÚindexÚpopr'   )r   Zreplacement_dictrH   rI   r   rL   ÚvariableZvar_indicesZ	var_arrayZcoeff_arrayZ
dim_beforeZ	dim_afterZvarindexZcoeff_indexr+   r   Úposr   rJ   r   rM   ç   s.    


(zPartialDerivative._extract_dataN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úpropertyr   r    Úclassmethodr   r.   r/   r9   r:   r&   rF   r   r   rM   r   r   r   r   r   	   s&   V



,

r   N)Zsympyr   Zsympy.core.numbersr   Zsympy.core.singletonr   Zsympy.core.symbolr   Zsympy.core.sympifyr   Zsympy.tensor.tensorr   r   r	   r
   r   r   r   r   r   Ú<module>   s   