a
    <b&                     @   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] http://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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   d/Users/vegardjervell/Documents/master/model/venv/lib/python3.9/site-packages/sympy/concrete/delta.py
<listcomp>#       z!_expand_delta.<locals>.<listcomp>c                    s   g | ]}|  qS r   r   r   )hr   r   r   %   r   )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u 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rtjS t|dkr|d  D ]}|	t||d |  q| j| }| |krt|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   r1   z   s,    


r1   c                 C   sn   t | trjzLt| jd | jd  dd}|rTt|dkrTtdd |d  D  W S W n tyh   Y n0 | 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   r6   valuer   r   r   r      s   z#_simplify_delta.<locals>.<listcomp>)r%   r   r   r   r2   r   itemsNotImplementedError)r!   Zslnsr   r   r   _simplify_delta   s    

r:   c              	      s  d d  dk dkrt jS | ts2t| S | jrjd g }t| jtdD ]*} du rpt	|d rp| qP|
| qP| 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rztt|W S  ty   t| Y S 0 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)r6   Zkprime)integerc              	      sT   g | ]L}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)r   r   r+   r   r   r   sortedr   r   r   r(   r    r	   r%   intr=   sumrangedeltasummationr>   r1   r*   r$   r   AssertionErrorr:   )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ur|jdur|j\}} d | dkdkr d | dkdkrd|st|  S t|j	d |j	d  |}	t|	dkrt jS t|	dkrt|  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;   r   r   Tc                    s   g | ]}t | qS r   )rF   )r   r   r@   rA   r   r   r   3  r   z"deltasummation.<locals>.<listcomp>N   )r   r3   r+   r   r   r$   r   r   r    r   r*   Zdelta_ranger   r2   r   r>   r   r   Zas_relational)rH   r@   rA   xrL   r#   r!   ZdinfZdsupr5   r7   r   rM   r   rF      s:    D



(

 rF   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'   r1   r:   r=   rF   r   r   r   r   <module>   s2   	

2




;