B
    [&                 @   s   d 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mZ ddlmZmZ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
==========

- http://mathworld.wolfram.com/KroneckerDelta.html

    )print_functiondivision)AddMulSDummy)cacheit)default_sort_keyrange)KroneckerDelta	Piecewisepiecewise_fold)Intervalc                s~   | j s
| S d}t}tdgxX| jD ]N |dkr` jr`t |r`d} j}fdd jD q$ fddD q$W | S )zB
    Expand the first Add containing a simple KroneckerDelta.
    N   Tc                s   g | ]} d  | qS )r    ).0t)termsr   3lib/python3.7/site-packages/sympy/concrete/delta.py
<listcomp>    s    z!_expand_delta.<locals>.<listcomp>c                s   g | ]}|  qS r   r   )r   r   )hr   r   r   "   s    )is_Mulr   r   argsis_Add_has_simple_deltafunc)exprindexdeltar   r   )r   r   r   _expand_delta   s    
r   c             C   s~   t | |sd| fS t| tr(| tdfS | js6tdd}g }x0| jD ]&}|dkrbt||rb|}qF|| qFW || j	| fS )as  
    Extract a simple KroneckerDelta from the expression.

    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
    Nr   zIncorrect expr)
r   
isinstancer   r   r   
ValueErrorr   _is_simple_deltaappendr   )r   r   r   r   argr   r   r   _extract_delta&   s    

r%   c             C   sF   |  trBt| |rdS | js$| jrBx| jD ]}t||r,dS q,W 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   V   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"   g   s
    r"   c             C   s   ddl m} | jr(| jttt| j S | js2| S g }g }x>| jD ]4}t	|t
rl||jd |jd   qB|| qBW |s| S ||dd}t|dkrtjS t|dkrx,|d  D ]}|t
||d |  qW | j| }| |krt|S | S )z0
    Evaluate products of KroneckerDelta's.
    r   )solver   T)dict)sympy.solversr(   r   r   listmap_remove_multiple_deltar   r   r    r   r#   lenr   Zerokeys)r   r(   ZeqsZnewargsr$   solnskeyZexpr2r   r   r   r-   t   s.    

r-   c             C   sz   ddl m} t| trvyJ|| jd | jd  dd}|r^t|dkr^tdd |d  D  S W n tk
rt   Y nX | S )zB
    Rewrite a KroneckerDelta's indices in its simplest form.
    r   )r(   r   T)r)   c             S   s   g | ]\}}t ||f qS r   )r   )r   r2   valuer   r   r   r      s   z#_simplify_delta.<locals>.<listcomp>)	r*   r(   r    r   r   r.   r   itemsNotImplementedError)r   r(   Zslnsr   r   r   _simplify_delta   s    
r6   c          	      sX  ddl m} d d  dk dkr*tjS | ts>|| S | jrzd g }x<t| jt	dD ]*} dkr~t
|d r~| q^|| q^W | j| tddd	}td trtd trt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 \ } st| d }| |krddlm}	 y|	t|S  tk
r   t|S X || S ddlm}
 |
d d d }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   )product   r   TN)r2   Zkprime)Zintegerc          	      sT   g | ]L}t d  d |d f d  | t d  |d d f qS )r   r   r8   )deltaproductsubs)r   Zik)r   limitnewexprr   r   r      s   z deltaproduct.<locals>.<listcomp>)no_piecewise)factor)Eq)Zsympy.concrete.productsr7   r   ZOner&   r   r   sortedr   r	   r   r#   r   r   r    intr9   sumr
   deltasummationr:   r-   r%   r   Zsympyr>   AssertionErrorr?   r6   )fr;   r7   r   r$   kresult_gr>   r?   cr   )r   r;   r<   r   r9      sL    



(
*

(r9   Fc                s&  ddl m} ddlm}  d  d  dk dkr6tjS | tsJ||  S  d }t| |}|j	rt
|j fdd|jD  S t||\}}|s||  S ||jd |jd  |}	t|	dkrtjS t|	dkrt|  S |	d }
r|||
S t|||
t dd	  |
ftjdfS )
a_  
    Handle summations containing a KroneckerDelta.

    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 couldn't 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 didn't 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, Piecewise
    >>> 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   )	summation)r(   r8   r   Tc                s   g | ]}t | qS r   )rC   )r   r   )r;   r=   r   r   r   4  s    z"deltasummation.<locals>.<listcomp>   )Zsympy.concrete.summationsrK   r*   r(   r   r/   r&   r   r   r   r   r   r   r%   r.   ZSumr:   r   r   Zas_relational)rE   r;   r=   rK   r(   xrI   r   r   r1   r3   r   )r;   r=   r   rC      s2    A




 rC   N)F)__doc__Z
__future__r   r   Z
sympy.corer   r   r   r   Zsympy.core.cacher   Zsympy.core.compatibilityr	   r
   Zsympy.functionsr   r   r   Z
sympy.setsr   r   r%   r   r"   r-   r6   r9   rC   r   r   r   r   <module>	   s   0A