U
    L?h/                     @   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   X/var/www/html/venv/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 )zThe 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rt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