U
    ;qLeæ/  ã                   @   sŒ   d dl Z d dlZd dlmZmZ d dlmZ d dlmZm	Z	 d dl
mZ d dlmZ d dlmZ G dd	„ d	eƒZd
d„ ZG dd„ deƒZdS )é    N)Ú_sympifyÚsympify)ÚExpr)ÚBasicÚTuple)ÚImmutableDenseNDimArray)ÚSymbol)ÚIntegerc                   @   sÈ   e Zd ZdZ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„ ƒZd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&S )'ÚArrayComprehensiona  
    Generate a list comprehension.

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

    If there is a symbolic dimension, for example, say [i for i in range(1, N)] where
    N is a Symbol, then the expression will not be expanded to an array. Otherwise,
    calling the doit() function will launch the expansion.

    Examples
    ========

    >>> from sympy.tensor.array import ArrayComprehension
    >>> from sympy import symbols
    >>> i, j, k = symbols('i j k')
    >>> a = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
    >>> a
    ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
    >>> a.doit()
    [[11, 12, 13], [21, 22, 23], [31, 32, 33], [41, 42, 43]]
    >>> b = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, k))
    >>> b.doit()
    ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, k))
    c                 O   s„   t dd„ |D ƒƒrtdƒ‚t|ƒg}| |  ||¡¡ tj| f|ž|Ž}|jdd … |_|  	|j¡|_
t|j
ƒ|_|  |j
¡|_|S )Nc                 s   s   | ]}t |ƒd kpdV  qdS ©é   N©Úlen©Ú.0Úl© r   ú}/home/p21-0144/sympy/latex2sympy2solve-back-end/sympyEq/lib/python3.8/site-packages/sympy/tensor/array/array_comprehension.pyÚ	<genexpr>%   s     z-ArrayComprehension.__new__.<locals>.<genexpr>úKArrayComprehension requires values lower and upper bound for the expressioné   )ÚanyÚ
ValueErrorr   ÚextendÚ_check_limits_validityr   Ú__new__Ú_argsÚ_limitsÚ_calculate_shape_from_limitsÚ_shaper   Ú_rankÚ_calculate_loop_sizeÚ
_loop_size©ÚclsÚfunctionÚsymbolsÚassumptionsZarglistÚobjr   r   r   r   $   s    
zArrayComprehension.__new__c                 C   s
   | j d S )aA  The function applied across limits.

        Examples
        ========

        >>> from sympy.tensor.array import ArrayComprehension
        >>> from sympy import symbols
        >>> i, j = symbols('i j')
        >>> a = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
        >>> a.function
        10*i + j
        r   )r   ©Úselfr   r   r   r%   1   s    zArrayComprehension.functionc                 C   s   | j S )au  
        The list of limits that will be applied while expanding the array.

        Examples
        ========

        >>> from sympy.tensor.array import ArrayComprehension
        >>> from sympy import symbols
        >>> i, j = symbols('i j')
        >>> a = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
        >>> a.limits
        ((i, 1, 4), (j, 1, 3))
        ©r   r)   r   r   r   ÚlimitsA   s    zArrayComprehension.limitsc                 C   s@   | j j}| jD ],\}}}| |¡ |j |j¡}| |¡}q|S )a)  
        The set of the free_symbols in the array.
        Variables appeared in the bounds are supposed to be excluded
        from the free symbol set.

        Examples
        ========

        >>> from sympy.tensor.array import ArrayComprehension
        >>> from sympy import symbols
        >>> i, j, k = symbols('i j k')
        >>> a = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
        >>> a.free_symbols
        set()
        >>> b = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, k+3))
        >>> b.free_symbols
        {k}
        )r%   Úfree_symbolsr   ÚdiscardÚunion)r*   Zexpr_free_symÚvarÚinfÚsupZcurr_free_symsr   r   r   r-   R   s    
zArrayComprehension.free_symbolsc                 C   s   dd„ | j D ƒS )aL  The tuples of the variables in the limits.

        Examples
        ========

        >>> from sympy.tensor.array import ArrayComprehension
        >>> from sympy import symbols
        >>> i, j, k = symbols('i j k')
        >>> a = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
        >>> a.variables
        [i, j]
        c                 S   s   g | ]}|d  ‘qS )r   r   r   r   r   r   Ú
<listcomp>{   s     z0ArrayComprehension.variables.<locals>.<listcomp>r+   r)   r   r   r   Ú	variablesm   s    zArrayComprehension.variablesc                 C   s   dd„ | j D ƒS )z¿The list of dummy variables.

        Note
        ====

        Note that all variables are dummy variables since a limit without
        lower bound or upper bound is not accepted.
        c                 S   s    g | ]}t |ƒd kr|d ‘qS )r   r   r   r   r   r   r   r3   ‡   s      z4ArrayComprehension.bound_symbols.<locals>.<listcomp>r+   r)   r   r   r   Úbound_symbols}   s    
z ArrayComprehension.bound_symbolsc                 C   s   | j S )aE  
        The shape of the expanded array, which may have symbols.

        Note
        ====

        Both the lower and the upper bounds are included while
        calculating the shape.

        Examples
        ========

        >>> from sympy.tensor.array import ArrayComprehension
        >>> from sympy import symbols
        >>> i, j, k = symbols('i j k')
        >>> a = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
        >>> a.shape
        (4, 3)
        >>> b = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, k+3))
        >>> b.shape
        (4, k + 3)
        )r   r)   r   r   r   Úshape‰   s    zArrayComprehension.shapec                 C   s,   | j D ] \}}}t||ƒ t¡r dS qdS )aø  
        Test if the array is shape-numeric which means there is no symbolic
        dimension.

        Examples
        ========

        >>> from sympy.tensor.array import ArrayComprehension
        >>> from sympy import symbols
        >>> i, j, k = symbols('i j k')
        >>> a = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
        >>> a.is_shape_numeric
        True
        >>> b = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, k+3))
        >>> b.is_shape_numeric
        False
        FT)r   r   Úatomsr   )r*   Ú_r1   r2   r   r   r   Úis_shape_numeric£   s    z#ArrayComprehension.is_shape_numericc                 C   s   | j S )a9  The rank of the expanded array.

        Examples
        ========

        >>> from sympy.tensor.array import ArrayComprehension
        >>> from sympy import symbols
        >>> i, j, k = symbols('i j k')
        >>> a = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
        >>> a.rank()
        2
        )r    r)   r   r   r   Úrank»   s    zArrayComprehension.rankc                 C   s   | j jrtdƒ‚| j S )aÔ  
        The length of the expanded array which means the number
        of elements in the array.

        Raises
        ======

        ValueError : When the length of the array is symbolic

        Examples
        ========

        >>> from sympy.tensor.array import ArrayComprehension
        >>> from sympy import symbols
        >>> i, j = symbols('i j')
        >>> a = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
        >>> len(a)
        12
        z Symbolic length is not supported)r"   r-   r   r)   r   r   r   Ú__len__Ê   s    zArrayComprehension.__len__c                 C   s¤   g }|D ]–\}}}t |ƒ}t |ƒ}t|tƒr6t|Ž }nt |ƒ}| t|||ƒ¡ tdd„ ||fD ƒƒrntdƒ‚||kdkr‚tdƒ‚||jks–||jkrtdƒ‚q|S )Nc                 s   s.   | ]&}t |tƒ p$| tt¡| ¡ kV  qd S ©N)Ú
isinstancer   r7   r   r	   )r   Úir   r   r   r   ð   s   ÿz<ArrayComprehension._check_limits_validity.<locals>.<genexpr>zABounds should be an Expression(combination of Integer and Symbol)Tz-Lower bound should be inferior to upper boundz)Variable should not be part of its bounds)	r   r=   Úlistr   Úappendr   Ú	TypeErrorr   r-   )r$   r%   r,   Z
new_limitsr0   r1   r2   r   r   r   r   â   s"    

ÿ
z)ArrayComprehension._check_limits_validityc                 C   s   t dd„ |D ƒƒS )Nc                 S   s   g | ]\}}}|| d  ‘qS ©r   r   )r   r8   r1   r2   r   r   r   r3   û   s     zCArrayComprehension._calculate_shape_from_limits.<locals>.<listcomp>)Útuple)r$   r,   r   r   r   r   ù   s    z/ArrayComprehension._calculate_shape_from_limitsc                 C   s"   |sdS d}|D ]}|| }q|S )Nr   r   r   )r$   r6   Ú	loop_sizer   r   r   r   r!   ý   s    
z'ArrayComprehension._calculate_loop_sizec                 K   s   | j s
| S |  ¡ S r<   )r9   Ú_expand_array)r*   Úhintsr   r   r   Údoit  s    zArrayComprehension.doitc                 C   s<   g }t jdd„ | jD ƒŽ D ]}| |  |¡¡ qt|| jƒS )Nc                 S   s    g | ]\}}}t ||d  ƒ‘qS rB   )Úrange)r   r0   r1   r2   r   r   r   r3     s   ÿz4ArrayComprehension._expand_array.<locals>.<listcomp>)Ú	itertoolsÚproductr   r@   Ú_get_elementr   r6   )r*   ÚresÚvaluesr   r   r   rE     s    
þz ArrayComprehension._expand_arrayc                 C   s,   | j }t| j|ƒD ]\}}| ||¡}q|S r<   )r%   Úzipr4   Úsubs)r*   rM   Útempr0   Úvalr   r   r   rK     s    zArrayComprehension._get_elementc                 C   s   | j r|  ¡  ¡ S tdƒ‚dS )aÍ  Transform the expanded array to a list.

        Raises
        ======

        ValueError : When there is a symbolic dimension

        Examples
        ========

        >>> from sympy.tensor.array import ArrayComprehension
        >>> from sympy import symbols
        >>> i, j = symbols('i j')
        >>> a = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
        >>> a.tolist()
        [[11, 12, 13], [21, 22, 23], [31, 32, 33], [41, 42, 43]]
        z-A symbolic array cannot be expanded to a listN)r9   rE   Útolistr   r)   r   r   r   rR     s    zArrayComprehension.tolistc                 C   s<   ddl m} | jstdƒ‚| jdkr,tdƒ‚||  ¡  ¡ ƒS )aE  Transform the expanded array to a matrix.

        Raises
        ======

        ValueError : When there is a symbolic dimension
        ValueError : When the rank of the expanded array is not equal to 2

        Examples
        ========

        >>> from sympy.tensor.array import ArrayComprehension
        >>> from sympy import symbols
        >>> i, j = symbols('i j')
        >>> a = ArrayComprehension(10*i + j, (i, 1, 4), (j, 1, 3))
        >>> a.tomatrix()
        Matrix([
        [11, 12, 13],
        [21, 22, 23],
        [31, 32, 33],
        [41, 42, 43]])
        r   )ÚMatrixz/A symbolic array cannot be expanded to a matrixé   zDimensions must be of size of 2)Úsympy.matricesrS   r9   r   r    rE   Útomatrix)r*   rS   r   r   r   rV   3  s    
zArrayComprehension.tomatrixN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úpropertyr%   r,   r-   r4   r5   r6   r9   r:   r;   Úclassmethodr   r   r!   rG   rE   rK   rR   rV   r   r   r   r   r
   
   s:   









		r
   c                 C   s"   dd„ }t | t|ƒƒo | j|jkS )Nc                   S   s   dS )Nr   r   r   r   r   r   Ú<lambda>U  ó    zisLambda.<locals>.<lambda>)r=   ÚtyperW   )ÚvZLAMBDAr   r   r   ÚisLambdaT  s    ra   c                   @   s,   e Zd ZdZdd„ Zedd„ ƒZdd„ ZdS )	ÚArrayComprehensionMapa[  
    A subclass of ArrayComprehension dedicated to map external function lambda.

    Notes
    =====

    Only the lambda function is considered.
    At most one argument in lambda function is accepted in order to avoid ambiguity
    in value assignment.

    Examples
    ========

    >>> from sympy.tensor.array import ArrayComprehensionMap
    >>> from sympy import symbols
    >>> i, j, k = symbols('i j k')
    >>> a = ArrayComprehensionMap(lambda: 1, (i, 1, 4))
    >>> a.doit()
    [1, 1, 1, 1]
    >>> b = ArrayComprehensionMap(lambda a: a+1, (j, 1, 4))
    >>> b.doit()
    [2, 3, 4, 5]

    c                 O   s‚   t dd„ |D ƒƒrtdƒ‚t|ƒs*tdƒ‚|  ||¡}tj| f|ž|Ž}|j|_|  |j¡|_	t
|j	ƒ|_|  |j	¡|_||_|S )Nc                 s   s   | ]}t |ƒd kpdV  qdS r   r   r   r   r   r   r   r  s     z0ArrayComprehensionMap.__new__.<locals>.<genexpr>r   zData type not supported)r   r   ra   r   r   r   r   r   r   r   r   r    r!   r"   Ú_lambdar#   r   r   r   r   q  s    zArrayComprehensionMap.__new__c                    s   G ‡ fdd„dt ƒ}|S )Nc                       s   e Zd Z‡ fdd„ZdS )z%ArrayComprehensionMap.func.<locals>._c                    s   t ˆ jf|ž|ŽS r<   )rb   rc   )r$   ÚargsÚkwargsr)   r   r   r   …  s    z-ArrayComprehensionMap.func.<locals>._.__new__N)rW   rX   rY   r   r   r)   r   r   r8   „  s   r8   )rb   )r*   r8   r   r)   r   Úfunc‚  s    zArrayComprehensionMap.funcc                 C   sB   | j }| j jjdkr|ƒ }n"| j jjdkr>|t dd„ |¡ƒ}|S )Nr   r   c                 S   s   | | S r<   r   )ÚaÚbr   r   r   r]   Ž  r^   z4ArrayComprehensionMap._get_element.<locals>.<lambda>)rc   Ú__code__Úco_argcountÚ	functoolsÚreduce)r*   rM   rP   r   r   r   rK   ‰  s    z"ArrayComprehensionMap._get_elementN)rW   rX   rY   rZ   r   r[   rf   rK   r   r   r   r   rb   X  s
   
rb   )rk   rI   Úsympy.core.sympifyr   r   Úsympy.core.exprr   Ú
sympy.corer   r   Úsympy.tensor.arrayr   Úsympy.core.symbolr   Úsympy.core.numbersr	   r
   ra   rb   r   r   r   r   Ú<module>   s     L