U
    ˜9%eæ/  ã                   @   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   úe/var/www/html/Darija-Ai-API/env/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ÚsymbolsZ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   r2   ‡   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)   Ú_r0   r1   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   r6   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_limitsr/   r0   r1   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   r7   r0   r1   r   r   r   r2   û   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$   r5   Z	loop_sizer   r   r   r   r!   ý   s    
z'ArrayComprehension._calculate_loop_sizec                 K   s   | j s
| S |  ¡ S r;   )r8   Ú_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 rA   )Úrange)r   r/   r0   r1   r   r   r   r2     s   ÿz4ArrayComprehension._expand_array.<locals>.<listcomp>)Ú	itertoolsÚproductr   r?   Ú_get_elementr   r5   )r)   ÚresÚvaluesr   r   r   rC     s    
þz ArrayComprehension._expand_arrayc                 C   s,   | j }t| j|ƒD ]\}}| ||¡}q|S r;   )r%   Úzipr3   Úsubs)r)   rK   Útempr/   Úvalr   r   r   rI     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)r8   rC   Útolistr   r(   r   r   r   rP     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)Zsympy.matricesrQ   r8   r   r    rC   Útomatrix)r)   rQ   r   r   r   rS   3  s    
zArrayComprehension.tomatrixN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úpropertyr%   r+   r,   r3   r4   r5   r8   r9   r:   Úclassmethodr   r   r!   rE   rC   rI   rP   rS   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<   ÚtyperT   )ÚvZLAMBDAr   r   r   ÚisLambdaT  s    r^   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   r^   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;   )r_   r`   )r$   ÚargsÚkwargsr(   r   r   r   …  s    z-ArrayComprehensionMap.func.<locals>._.__new__N)rT   rU   rV   r   r   r(   r   r   r7   „  s   r7   )r_   )r)   r7   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   rZ   Ž  r[   z4ArrayComprehensionMap._get_element.<locals>.<lambda>)r`   Ú__code__Úco_argcountÚ	functoolsÚreduce)r)   rK   rN   r   r   r   rI   ‰  s    z"ArrayComprehensionMap._get_elementN)rT   rU   rV   rW   r   rX   rc   rI   r   r   r   r   r_   X  s
   
r_   )rh   rG   Zsympy.core.sympifyr   r   Zsympy.core.exprr   Z
sympy.corer   r   Zsympy.tensor.arrayr   Zsympy.core.symbolr   Zsympy.core.numbersr	   r
   r^   r_   r   r   r   r   Ú<module>   s     L