o
    oh"                     @   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   sZ   t |tr|j| }|j}| t||\}}}}tj| g|R  }||_||_	||_
|S N)
isinstancer   	variablesexpr _contract_indices_for_derivativer   r   __new___indices_free_dum)clsr   r   argsindicesfreedumobj r   k/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/sympy/tensor/toperators.pyr   `   s   

zPartialDerivative.__new__c                 C   s   t jS r   )r   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 ]#}t |tr| }||dd |D  qt |tr'|| qtj|g| dd\}}}}	tdt	|D ]}|| }
t |
tr\||  }|| dd |D ||< q=||||	fS )Nc                 S      i | ]}|| qS r   r   .0kr   r   r   
<dictcomp>       zFPartialDerivative._contract_indices_for_derivative.<locals>.<dictcomp>T)replace_indices   c                 S   r"   r   r   r#   r   r   r   r&      r'   )
r   r   get_free_indicesappendxreplacer   r
   _tensMul_contract_indicesrangelen)r   r   r   variables_opposite_valenceii_free_indicesr   r   r   r   args_i	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s$tj	S t
 jtr< jj fdd|jjD  }|S t
 jtrt jdkrg }t jj}tt|D ]/}t
t|| tsj|| g jR   }	|t|d | |	g ||d d     qWt|}|S  j} jD ]
}
||
 }q|S )Nr   c                    s$   g | ]}j |g jR   qS r   )r5   r   _expand_partial_derivative)r$   ar   r   r   r   
<listcomp>   s    z@PartialDerivative._expand_partial_derivative.<locals>.<listcomp>r)   )r   r   r   r5   r   r   r   free_symbolsr   Zeror   r	   r   r
   r/   listr.   r   r   r8   r+   fromiter)r   r   r   r   r   resulttermsmulargsinddvr   r:   r   r8      s@   



z,PartialDerivative._expand_partial_derivativec                 C   sD   | j }| jD ]}t|tr||}q|jr||}qtj}q|S r   )	r   r   r   r   _eval_partial_derivative	_diff_wrt_eval_derivativer   r=   )r   r@   rE   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>   s    z4PartialDerivative.get_free_indices.<locals>.<lambda>)keyc                 S   s   g | ]}|d  qS )r   r   r$   r1   r   r   r   r;      r'   z6PartialDerivative.get_free_indices.<locals>.<listcomp>)sortedr   )r   r   r   r   r   r*      s   z"PartialDerivative.get_free_indicesc                    sD   | j |}dd | D   fdd| jD }| j|g|R  S )Nc                 S   s   i | ]	\}}| | qS r   r   )r$   r%   rE   r   r   r   r&      s    z6PartialDerivative._replace_indices.<locals>.<dictcomp>c                    s   g | ]}|  qS r   )r,   rO   mirroredr   r   r;      s    z6PartialDerivative._replace_indices.<locals>.<listcomp>)r   r,   itemsr   r5   )r   replr   r   r   rQ   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 rK   rV   r   r   r   r   r      s   zPartialDerivative.variablesc                    sL  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|  |  < qo| |v r|| }||d|d f}|| q|| q||fS )	Nr)   )derive_by_arraytensorcontractionc                 S   s   g | ]}| qS r   r   rO   r   r   r   r;      s    z3PartialDerivative._extract_data.<locals>.<listcomp>c                 S   s   g | ]}|  qS r   )as_coeff_MulrO   r   r   r   r;      r'   c                    s   g | ]}|  qS r   r   rO   dim_increaser   r   r;      r'   r   c                 S   s   g | ]}t d qS r   )slicerO   r   r   r   r;      r'   )arrayrW   rX   r   _extract_datar   zipr/   shaper   r.   r>   
as_mutable	enumeratetupleindexpopr+   )r   replacement_dictrW   rX   r   r]   variablevar_indices	var_arraycoeff_array
dim_before	dim_aftervarindexcoeff_indexr1   r    posr   rZ   r   r^      s.   



(
zPartialDerivative._extract_dataN)__name__
__module____qualname____doc__r   propertyr    r!   classmethodr   r7   r8   rI   rJ   r*   rU   r   r   r^   r   r   r   r   r   	   s(    V



,

r   N)sympyr   sympy.core.numbersr   sympy.core.singletonr   sympy.core.symbolr   sympy.core.sympifyr   sympy.tensor.tensorr   r   r	   r
   r   r   r   r   r   <module>   s    