U
    9%e"                     @   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/Darija-Ai-API/env/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  }nt
 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     qt|}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   