o
    8Vaw'                     @   s   d 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 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] http://mathworld.wolfram.com/KroneckerDelta.html

    )AddMulSDummy)cacheit)default_sort_key)KroneckerDelta	Piecewisepiecewise_fold)Intervalc                    sx   | j s| S d}t}tjg| jD ]' |du 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   6/usr/lib/python3/dist-packages/sympy/concrete/delta.py
<listcomp>       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stdd}g }| jD ]}|du r/t||r/|}q!|	| q!|| 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   X   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      F)r   r   r%   r   Zas_polyZdegree)r   r   pr   r   r   r!   i   s
   r!   c                 C   s   ddl m} | jr| jttt| j S | js| S g }g }| jD ]}t	|t
r5||jd |jd   q || q |s?| S ||dd}t|dkrNtjS t|dkrv|d  D ]}|t
||d |  qZ| j| }| |krvt|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/   v   s.   


r/   c                 C   s   ddl m} t| tr@z*|| jd | jd  dd}|r0t|dkr3tdd |d  D  W S W | S W | S  ty?   Y | S w | S )zB
    Rewrite a KroneckerDelta's indices in its simplest form.
    r   r(   r&   Tr*   c                 S   s   g | ]
\}}t ||f qS r   )r   )r   r4   valuer   r   r   r      s    z#_simplify_delta.<locals>.<listcomp>)	r,   r)   r   r   r   r0   r   itemsNotImplementedError)r   r)   Zslnsr   r   r   _simplify_delta   s"   


r8   c           
   	      s4  ddl m} d d  dk dkrtjS | ts|| S | jrd g }t| jt	dD ]} du r=t
|d r=| q-|| q-| 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  }t|S t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}	 z|	t|W S  ty   t| Y S w || 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   )product   r&   TN)r4   Zkprime)Zintegerc              	      sT   g | ]&}t d  d |d f d  | t d  |d d f qS )r   r&   r:   )deltaproductsubs)r   Zikr   limitZnewexprr   r   r      s    z deltaproduct.<locals>.<listcomp>)no_piecewise)factor)Zsympy.concrete.productsr9   r   r   r%   r   r   sortedr   r   r   r"   r   r   r   intr;   sumrangedeltasummationr<   r/   r$   r   Zsympyr@   AssertionErrorr8   )
fr>   r9   r   r#   kresult_gr@   r   r=   r   r;      sV   





(r;   Fc                    sz  ddl m} ddlm}  d  d  dk dkrtjS | ts%||  S  d }t| |}|j	rAt
|j fdd|jD  S t||\}}|d	url|jd	url|j\}	}
 d |	 dkdkrl d |
 dkdkrld|ss||  S ||jd |jd  |}t|dkrtjS t|dkrdd
l m} ||  S |d }r|||S t|||t dd  |ftjdfS )au  
    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 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
    >>> 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   )	summationr(   r:   r&   Tc                    s   g | ]}t | qS r   )rE   )r   r   r>   r?   r   r   r   7  r   z"deltasummation.<locals>.<listcomp>N)Sum   )Zsympy.concrete.summationsrL   r,   r)   r   r1   r%   r   r   r   r
   r   r   r$   Zdelta_ranger0   rN   r<   r	   r   Zas_relational)rG   r>   r?   rL   r)   xrK   r   r   ZdinfZdsupr3   rN   r5   r   rM   r   rE      s@   D



(

 rE   N)F)__doc__Z
sympy.corer   r   r   r   Zsympy.core.cacher   Zsympy.core.compatibilityr   Zsympy.functionsr   r	   r
   Z
sympy.setsr   r   r$   r   r!   r/   r8   r;   rE   r   r   r   r   <module>   s,    	

2




>