U
    ZÊ¹jÓ&  ã                   @   sî   d Z ddlmZ ddlmZmZ ddlmZmZm	Z	m
Z
 ddlmZ ddlmZ ddlmZmZmZ dd	lmZ dd
lmZ ddlmZ edd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZeddd„ƒZ dS )z¥
This module implements sums and products containing the Kronecker Delta function.

References
==========

.. [1] https://mathworld.wolfram.com/KroneckerDelta.html

é   )Úproduct)ÚSumÚ	summationé    )ÚAddÚMulÚSÚDummy)Úcacheit)Údefault_sort_key)ÚKroneckerDeltaÚ	PiecewiseÚpiecewise_fold)Úfactor)ÚInterval)Úsolvec                    sx   | j s
| S d}t}tjg‰| jD ]N‰ |dkr\ˆ jr\tˆ |ƒr\d}ˆ j}‡fdd„ˆ jD ƒ‰q ‡ fdd„ˆD ƒ‰q |ˆŽ S )zB
    Expand the first Add containing a simple KroneckerDelta.
    NTc                    s   g | ]}ˆ d  | ‘qS )r   © ©Ú.0Út)Útermsr   úS/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/concrete/delta.pyÚ
<listcomp>#   s     z!_expand_delta.<locals>.<listcomp>c                    s   g | ]}|ˆ  ‘qS r   r   r   )Úhr   r   r   %   s     )Úis_Mulr   r   ÚOneÚargsÚis_AddÚ_has_simple_deltaÚfunc)ÚexprÚindexÚdeltar   r   )r   r   r   Ú_expand_delta   s    
r#   c                 C   sx   t | |ƒsd| fS t| tƒr&| tjfS | js4tdƒ‚d}g }| jD ]&}|dkr^t||ƒr^|}qB| 	|¡ qB|| j
|Ž fS )a”  
    Extract a simple KroneckerDelta from the expression.

    Explanation
    ===========

    Returns the tuple ``(delta, newexpr)`` where:

      - ``delta`` is a simple KroneckerDelta expression if one was found,
        or ``None`` if no simple KroneckerDelta expression was found.

      - ``newexpr`` is a Mul containing the remaining terms; ``expr`` is
        returned unchanged if no simple KroneckerDelta expression was found.

    Examples
    ========

    >>> from sympy import KroneckerDelta
    >>> from sympy.concrete.delta import _extract_delta
    >>> from sympy.abc import x, y, i, j, k
    >>> _extract_delta(4*x*y*KroneckerDelta(i, j), i)
    (KroneckerDelta(i, j), 4*x*y)
    >>> _extract_delta(4*x*y*KroneckerDelta(i, j), k)
    (None, 4*x*y*KroneckerDelta(i, j))

    See Also
    ========

    sympy.functions.special.tensor_functions.KroneckerDelta
    deltaproduct
    deltasummation
    NzIncorrect expr)r   Ú
isinstancer   r   r   r   Ú
ValueErrorr   Ú_is_simple_deltaÚappendr   )r    r!   r"   r   Úargr   r   r   Ú_extract_delta)   s    "



r)   c                 C   sD   |   t¡r@t| |ƒrdS | js$| jr@| jD ]}t||ƒr* dS q*dS )zØ
    Returns True if ``expr`` is an expression that contains a KroneckerDelta
    that is simple in the index ``index``, meaning that this KroneckerDelta
    is nonzero for a single value of the index ``index``.
    TF)Úhasr   r&   r   r   r   r   )r    r!   r(   r   r   r   r   \   s    



r   c                 C   sB   t | tƒr>|  |¡r>| jd | jd   |¡}|r>| ¡ dkS dS )zu
    Returns True if ``delta`` is a KroneckerDelta and is nonzero for a single
    value of the index ``index``.
    r   r   F)r$   r   r*   r   Zas_polyZdegree)r"   r!   Úpr   r   r   r&   m   s
    r&   c                 C   sä   | j r| jttt| jƒƒŽ S | js&| S g }g }| jD ]4}t|tƒr^| 	|jd |jd  ¡ q4| 	|¡ q4|sr| S t
|dd�}t|ƒdkr�tjS t|ƒdkrà|d  ¡ D ]}| 	t||d | ƒ¡ q¨| j|Ž }| |kràt|ƒS | S )z0
    Evaluate products of KroneckerDelta's.
    r   r   T©Údict)r   r   ÚlistÚmapÚ_remove_multiple_deltar   r   r$   r   r'   r   Úlenr   ÚZeroÚkeys)r    ZeqsZnewargsr(   ÚsolnsÚkeyZexpr2r   r   r   r0   z   s,    


r0   c                 C   sp   t | tƒrlzLt| jd | jd  dd�}|rTt|ƒdkrTtdd„ |d  ¡ D ƒŽ W S W n tk
rj   Y nX | S )zB
    Rewrite a KroneckerDelta's indices in its simplest form.
    r   r   Tr,   c                 S   s   g | ]\}}t ||fŽ ‘qS r   )r   )r   r5   Úvaluer   r   r   r   ¡   s   ÿz#_simplify_delta.<locals>.<listcomp>)r$   r   r   r   r1   r   ÚitemsÚNotImplementedError)r    Zslnsr   r   r   Ú_simplify_delta˜   s    

ÿr9   c              	      s   ˆd ˆd  dk dkrt jS |  t¡s2t| ˆƒS | j�rjd‰ g }t| jtd�D ]*}ˆ dkrpt	|ˆd ƒrp|‰ qP| 
|¡ qP| j|Ž ‰tddd�}tˆd tƒrîtˆd tƒrîtˆˆƒt‡ ‡‡fd	d
„ttˆd ƒtˆd d ƒƒD ƒƒ }nttˆˆƒttˆˆd ˆd |d fƒˆ  ˆd |¡ tˆˆd |d ˆd fƒ |ˆd ˆd ft	ˆˆd ƒd� }t|ƒS t| ˆd ƒ\‰ }ˆ �sÖt| ˆd ƒ}| |k�rÌztt|ˆƒƒW S  tk
�rÊ   t|ˆƒ Y S X t| ˆƒS t|  ˆd ˆd ¡tˆd ˆd ƒ ƒt jttˆd ˆd d ƒƒ  S )zÅ
    Handle products containing a KroneckerDelta.

    See Also
    ========

    deltasummation
    sympy.functions.special.tensor_functions.KroneckerDelta
    sympy.concrete.products.product
    é   r   r   TN)r5   Zkprime)Úintegerc                 3   sV   | ]N}t ˆˆd  ˆd |d fƒˆ  ˆd  |¡ t ˆˆd  |d ˆd fƒ V  qdS )r   r   r:   N)ÚdeltaproductÚsubs)r   Úik©r"   ÚlimitZnewexprr   r   Ú	<genexpr>Æ   s   þÿþzdeltaproduct.<locals>.<genexpr>)Úno_piecewise)r   r   r*   r   r   r   Úsortedr   r   r   r'   r   r	   r$   Úintr<   ÚsumÚrangeÚdeltasummationr=   r0   r)   r#   r   ÚAssertionErrorr9   )Úfr@   r   r(   ÚkÚresultÚ_Úgr   r?   r   r<   ¨   sN    


þ
ÿþû

(ÿr<   Fc                    sZ  ˆ d ˆ d  dk dkrt jS |  t¡s2t| ˆ ƒS ˆ d }t| |ƒ}|jrjt|j‡ ‡fdd„|j	D ƒŽ ƒS t
||ƒ\}}|dk	rÀ|jdk	rÀ|j\}}ˆ d | dkdkrÀˆ d | dkdkrÀd‰|sÎt| ˆ ƒS t|j	d |j	d  |ƒ}	t|	ƒdkrút jS t|	ƒdk�rt| ˆ ƒS |	d }
ˆ�r,| ||
¡S t| ||
¡tˆ dd… Ž  |
¡ft jdfƒS )	aw  
    Handle summations containing a KroneckerDelta.

    Explanation
    ===========

    The idea for summation is the following:

    - If we are dealing with a KroneckerDelta expression, i.e. KroneckerDelta(g(x), j),
      we try to simplify it.

      If we could simplify it, then we sum the resulting expression.
      We already know we can sum a simplified expression, because only
      simple KroneckerDelta expressions are involved.

      If we could not simplify it, there are two cases:

      1) The expression is a simple expression: we return the summation,
         taking care if we are dealing with a Derivative or with a proper
         KroneckerDelta.

      2) The expression is not simple (i.e. KroneckerDelta(cos(x))): we can do
         nothing at all.

    - If the expr is a multiplication expr having a KroneckerDelta term:

      First we expand it.

      If the expansion did work, then we try to sum the expansion.

      If not, we try to extract a simple KroneckerDelta term, then we have two
      cases:

      1) We have a simple KroneckerDelta term, so we return the summation.

      2) We did not have a simple term, but we do have an expression with
         simplified KroneckerDelta terms, so we sum this expression.

    Examples
    ========

    >>> from sympy import oo, symbols
    >>> from sympy.abc import k
    >>> i, j = symbols('i, j', integer=True, finite=True)
    >>> from sympy.concrete.delta import deltasummation
    >>> from sympy import KroneckerDelta
    >>> deltasummation(KroneckerDelta(i, k), (k, -oo, oo))
    1
    >>> deltasummation(KroneckerDelta(i, k), (k, 0, oo))
    Piecewise((1, i >= 0), (0, True))
    >>> deltasummation(KroneckerDelta(i, k), (k, 1, 3))
    Piecewise((1, (i >= 1) & (i <= 3)), (0, True))
    >>> deltasummation(k*KroneckerDelta(i, j)*KroneckerDelta(j, k), (k, -oo, oo))
    j*KroneckerDelta(i, j)
    >>> deltasummation(j*KroneckerDelta(i, j), (j, -oo, oo))
    i
    >>> deltasummation(i*KroneckerDelta(i, j), (i, -oo, oo))
    j

    See Also
    ========

    deltaproduct
    sympy.functions.special.tensor_functions.KroneckerDelta
    sympy.concrete.sums.summation
    r:   r   r   Tc                    s   g | ]}t |ˆ ˆƒ‘qS r   )rG   )r   r   ©r@   rB   r   r   r   2  s     z"deltasummation.<locals>.<listcomp>Né   )r   r2   r*   r   r   r#   r   r   r   r   r)   Zdelta_ranger   r1   r   r=   r   r   Zas_relational)rI   r@   rB   ÚxrM   r"   r    ZdinfZdsupr4   r6   r   rN   r   rG   ã   s:    D


ÿ
(

 þrG   N)F)!Ú__doc__Zproductsr   Z
summationsr   r   Z
sympy.corer   r   r   r	   Zsympy.core.cacher
   Zsympy.core.sortingr   Zsympy.functionsr   r   r   Zsympy.polys.polytoolsr   Zsympy.sets.setsr   Zsympy.solvers.solversr   r#   r)   r   r&   r0   r9   r<   rG   r   r   r   r   Ú<module>   s2   	

2




: